diff --git a/truchet/truchet.html b/truchet/truchet.html new file mode 100644 index 0000000..b5de97b --- /dev/null +++ b/truchet/truchet.html @@ -0,0 +1,75 @@ + +JavaScript <=> PaperScript example + + + + + + + + + + + + + + + + diff --git a/truchet/truchet.js b/truchet/truchet.js new file mode 100644 index 0000000..0cb6e43 --- /dev/null +++ b/truchet/truchet.js @@ -0,0 +1,154 @@ + +const tile_shapes = ['x.', '/']; +//const tile_shapes = ['/']; + +const HLEN = 4/3 * Math.tan(Math.PI/8); +function add_qcarc(path, center, steps=1) { + var lastseg = path.segments[path.segments.length - 1]; + var v_last = lastseg.point.subtract(center); + var p_new = center.add(v_last.rotate((steps>0) ? 90 : -90)); + var v_new = p_new.subtract(center); + var hlen = HLEN * v_new.length; + lastseg.handleOut = v_new.normalize(hlen); + path.add(new Segment(p_new, v_last.normalize(hlen), null)); + if(Math.abs(steps) > 1) { + add_qcarc(path, center, steps - Math.sign(steps)); + } +} + +function gen_tiles(depth, min_depth, max_depth) { + if(((depth >= min_depth) && (Math.random() < 0.5)) || (depth >= max_depth)) { + return tile_shapes[Math.floor(Math.random() * tile_shapes.length)]; + } else { + return [ + gen_tiles(depth + 1, min_depth, max_depth), + gen_tiles(depth + 1, min_depth, max_depth), + gen_tiles(depth + 1, min_depth, max_depth), + gen_tiles(depth + 1, min_depth, max_depth), + ]; + } +} + +function draw_tile(tile, pos, size, inverted) { + console.log(pos, size); + var bounds = [ + new Path.Rectangle({ + point: pos, + size: new Size(size, size), + strokeWidth: 1, + strokeColor: 'black', + //fillColor: inverted ? '#cccccc' : 'white', + }), + new Path.Line({ + from: pos.add(new Point(size * 2/3, 0)), + to: pos.add(new Point(size, size / 3)), + strokeWidth: 1, + strokeColor: 'black' + }), + ]; + + var bg = new Path.Rectangle({ + point: pos, + size: new Size(size, size), + strokeWidth: 1, + strokeColor: 'red', + }); + for(var x=0; x<2; x++) { + for(var y=0; y<2; y++) { + bg = bg.unite(new Path.Circle({ + center: pos.add(new Point(x*size, y*size)), + radius: size / 3, + strokeWidth: 1, + strokeColor: 'red', + })); + } + } + + var shape = new CompoundPath({strokeWidth: 1, strokeColor: 'green'}); + if(tile == 'x.') { + var shape1 = new Path(); + shape1.add(pos.add(new Point(size/3, 0))); + add_qcarc(shape1, pos, 1); + add_qcarc(shape1, pos.add(new Point(0, size/2)), -2); + add_qcarc(shape1, pos.add(new Point(0, size)), 1); + add_qcarc(shape1, pos.add(new Point(size/2, size)), -2); + add_qcarc(shape1, pos.add(new Point(size, size)), 1); + add_qcarc(shape1, pos.add(new Point(size, size/2)), -2); + add_qcarc(shape1, pos.add(new Point(size, 0)), 1); + add_qcarc(shape1, pos.add(new Point(size/2, 0)), -2); + shape1.closed = true; + shape.addChild(shape1); + } else if(tile == '/') { + var shape1 = new Path(); + shape1.add(pos.add(new Point(size/3, 0))); + add_qcarc(shape1, pos.add(new Point(size/2, 0)), 2); + add_qcarc(shape1, pos.add(new Point(size, 0)), -1); + add_qcarc(shape1, pos.add(new Point(size, size/2)), 2); + add_qcarc(shape1, pos.add(new Point(size, 0)), 1); + shape1.closed = true; + shape.addChild(shape1); + var shape2 = new Path(); + shape2.add(pos.add(new Point(size/3, size))); + add_qcarc(shape2, pos.add(new Point(size/2, size)), -2); + add_qcarc(shape2, pos.add(new Point(0, size)), -1); + add_qcarc(shape2, pos.add(new Point(0, size/2)), -2); + add_qcarc(shape2, pos.add(new Point(0, size)), 1); + shape2.closed = true; + shape.addChild(shape2); + } + + + bg = bg.subtract(shape); + + + /* + if(!inverted) { + return [[ shape ], [ bg ]]; + } else { + return [[ bg ], [ shape ]]; + } + */ + //return ret; + if(!inverted) { + return [shape, bg, bounds]; + } else { + return [bg, shape, bounds]; + } + +} + + +function draw_tiles(tiles, pos, depth=1, inverted=true) { + if(typeof tiles === 'string') { + return draw_tile(tiles, pos, 1/Math.pow(2, depth-1), inverted); + } else { + var ret = null; + var newsize = 1 / Math.pow(2, depth); + for(var i=0; i<4; i++) { + var fgbg = draw_tiles( + tiles[i], + pos.add(new Point(newsize * (i%2), newsize * Math.floor(i/2))), + depth+1, + !inverted + ); + if(i==0) { + ret = fgbg; + } else { + ret[0] = ret[0].unite(fgbg[0]); + ret[1] = ret[1].unite(fgbg[1]); + ret[2].push.apply(ret[2], fgbg[2]); + } + /* + if(i==0) { + ret = fgbg; + } else { + ret[0].push.apply(ret[0], fgbg[0]); + ret[1].push.apply(ret[1], fgbg[1]); + } + */ + } + var bg = ret[1].subtract(ret[0]); + return [ret[0], bg, ret[2]]; + + } +}