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 @@ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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]];
+
+ }
+}