1// Example of a generalized kaleidoscope. The idea is similar to a traditional
2// kaleidoscope, which consists of 3 flat mirrors with dihedral angles of 60
3// degrees. One can place an arbitrary object inside such a kaleidoscope and
4// reflections in the mirrors create an infinite repeating pattern. Here we use
5// both flat and spherical mirrors. "Reflection" in a spherical mirror is
6// inversion in the sphere. If the dihedral angles between the spheres and
7// planes are integer submultiples of the half turn (tau/2 or 180 degrees) the
8// reflections in such mirrors form a regular pattern. The type of pattern
9// created by such a kaleidoscope can be wildly complex. In this case we have 4
10// mirrors: 2 flat mirrors and 2 spherical mirrors. The mirrors are placed such
11// that the pattern scales down near the boundary of a disk. It resembles a
12// tiling of the 2D hyperbolic plane in the Poincare disk model, with the
13// important difference that our pattern is three dimensional.
14//
15// Credit: the ShapeJS project
16
17
18var voxelSize = 0.2*MM;
19
20function getQuad_1( r, r1, alpha){
21  var r2 = r*r/(r1*Math.cos(alpha));
22  var x1 = Math.sqrt(r1*r1 + r*r);
23  var y2 = Math.sqrt(r2*r2 + r*r);
24
25  var splanes = new Array();
26  var count = 0;
27  splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(0,-1,0), 0.0);
28  splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(-1,0,0), 0.0);
29  splanes[count++] = new ReflectionSymmetry.getSphere(new Vector3d(x1,0,0), -r1);
30  splanes[count++] = new ReflectionSymmetry.getSphere(new Vector3d(0,y2,0), -r2);
31
32  return splanes;
33}
34
35function makePart_g(size, thickness){
36  var t = (thickness/2) * 1.5;
37  var s = size/2;
38  //var g = createGrid(-t, t, -t, t, -s, s,voxelSize);
39  var b = 20*MM;
40  var g = createGrid(-b,b,-b,b,-b,b,0.5*MM);
41
42  var boxZ = new Box(0,0,0,thickness, thickness, size);
43
44  var mm = new GridMaker();
45  mm.setSource(boxZ);
46  mm.setMaxAttributeValue(255);
47  mm.makeGrid(g);
48
49  var gmm = new GridMipMap(g);
50
51  gmm.setScalingType(GridMipMap.SCALING_AVERAGE);
52  //gmm.setScalingType(GridMipMap.SCALING_MAX);
53
54  return gmm;
55}
56
57function makePart(size, thickeness){
58  var union = new Union();
59  var boxX = new Box(0,0,0,thickeness, thickeness, size);
60  union.add(boxX);
61  return union;
62}
63
64function main(){
65  var a = 25*MM;
66  var voxelSize = 0.1*MM;
67  var cz = 20.0*MM;
68  var cx = 5.0*MM;
69  var cy = 5.0*MM;
70
71  var part = makePart_g(30*MM, 5*MM);
72  part.setTransform(new Rotation(new Vector3d(-1,1,0), 3*Math.PI/8));
73
74  var dt = new DataTransformer();
75  dt.setSource(part);
76
77  var sym = new ReflectionSymmetry(getQuad_1(25*MM, 30*MM, Math.PI/3));
78  sym.setMaxCount(50);
79
80  dt.setTransform(sym);
81
82  var maker = new GridMaker();
83  maker.setSource(dt);
84  var dest = createGrid(-a,a,-a,a,-a,a,voxelSize);
85  maker.makeGrid(dest);
86
87  return dest;
88}
89
90