package ProGAL.geom3d.kineticDelaunay; //import java.awt.Color; //import java.util.Arrays; //import static java.lang.Math.sin; //import static java.lang.Math.cos; //import static java.lang.Math.tan; //import static java.lang.Math.atan; // //import ProGAL.geom3d.Line; //import ProGAL.geom3d.Point; //import ProGAL.geom3d.Triangle; //import ProGAL.geom3d.Vector; //import ProGAL.geom3d.viewer.J3DScene; //import ProGAL.geom3d.volumes.Sphere; //import ProGAL.geom3d.volumes.Tetrahedron; //import ProGAL.math.Constants; //import ProGAL.math.Matrix; public class KineticToolbox { // // /** // * Given a configuration of 5 vertices spanning two neighboring tetrahedra and an indication // * of which vertices are moving (moving specifies indices in vertices), // * find the smallest rotation angle that causes the five vertices to be cospherical. The rotation // * is assumed to be a right-hand-rotation around the z-axis. // * @param vertices An array of 5 vertices spanning two neighboring tetrahedra // * @param moving An array indicating the indices of the points that are rotating. // * @return // */ // static double nextEvent(Vertex[] vertices, int[] moving){ // return 0; // } // // // /** // * Given a configuration of 5 vertices and the index of one rotating vertex this method returns the // * smallest absolute rotation angle that causes the five vertices to be cospherical. The rotation // * is assumed to be a right-hand-rotation around the z-axis and the rotating point has already // * rotated an angle of curAlpha even though this is not reflected in its coordinates. // * // * @param vertices An array of 5 vertices // * @param moving The index of the point that is rotating. // * @param curAlpha Rotating points will not have their coordinates changed between events, so // * curAlpha indicates how far they have rotated. // * @return The absolute angle rotation angle of vertices[moving] around the z-axis // * where the five vertices will be co-spherical. // */ // static double nextEvent(Vertex[] vertices, int moving, double curAlpha){ // //Create the inSphere matrix (except the last row) // Matrix m = new Matrix(5,5); // for(int r=0;r<4;r++){ // int vIdx = r+(rt2){ double tmp = t1; t1 = t2; t2=tmp; } // // double alpha1 = 2*Math.atan( t1 ); // double alpha2 = 2*Math.atan( t2 ); // // //Find the current position of the rotating point and determine the correct earliest absolute rotation angle // double vAlpha = Math.atan2(v.y(),v.x())+curAlpha;//TODO: Should be atan // if(vAlpha>alpha2) return alpha1+2*Math.PI; // if(vAlpha>alpha1) return alpha2; // return alpha1; // } // // // static void testEvent1(){ // Vertex[] vs = { // new Vertex(new Point(0,1,0)), // new Vertex(new Point(1,1,0)), // new Vertex(new Point(0,2,0)), // new Vertex(new Point(0,1,1)), // new Vertex(new Point(Math.sqrt(2),0,0)) // }; // double a = nextEvent(vs, 4, 0*Math.PI/180); // System.out.printf("Vertex 4 will intersect circumsphere of 0-3 at the angle %.2f___. Expects 45___\n", a*180/Math.PI); // } // // /** // * Given a configuration of 5 vertices and the index of two rotating vertices this method returns the // * smallest absolute rotation angle that causes the five vertices to be cospherical. The rotation // * is assumed to be a right-hand-rotation around the z-axis and the rotating points have already // * rotated an angle of curAlpha even though this is not reflected in its coordinates. // * // * @param vertices An array of 5 vertices // * @param moving The index of the point that is rotating. // * @param curAlpha Rotating points will not have their coordinates changed between events, so // * curAlpha indicates how far they have rotated. // * @return The absolute angle rotation angle of vertices[moving] around the z-axis // * where the five vertices will be co-spherical. // */ // static double nextEvent(Vertex[] vertices, int moving1, int moving2, double curAlpha){ // //Create the inSphere matrix (except the last two rows) // Matrix m = new Matrix(5,5); // for(int r=0;r<3;r++){ // int vIdx = r+(ralpha) return alpha+2*Math.PI; // return alpha; // } // // double t1 = (-C2+Math.sqrt(D))/(C3-C1); // double t2 = (-C2-Math.sqrt(D))/(C3-C1); // if(t1>t2){ double tmp = t1; t1 = t2; t2=tmp; } // // double alpha1 = 2*atan( t1 ); // double alpha2 = 2*atan( t2 ); // System.out.println(alpha1*180/Math.PI); // System.out.println(alpha2*180/Math.PI); // // //Find the current position of the rotating point and determine the correct earliest absolute rotation angle // if(curAlpha>alpha2) return alpha1+2*Math.PI; // if(curAlpha>alpha1) return alpha2; // return alpha1; // } // // // static void testEvent2(){ // Vertex[] vs = { // new Vertex(new Point( 0,-0.9, 0)), // new Vertex(new Point( 0, 0.1, 1)), // new Vertex(new Point( 0, 1.1, 0)), // new Vertex(new Point( 1, 0, 0)), // new Vertex(new Point(-1, 0, 0)), // }; // Line l = new Line(new Triangle(vs[0],vs[1],vs[2]).circumcenter(), new Vector(1,0,1).normalizeThis()); // vs[4] = new Vertex(new Sphere(new Triangle(vs[0],vs[1],vs[2]).circumcenter(), new Triangle(vs[0],vs[1],vs[2]).circumradius()).getIntersection(l).getA()); // l = new Line(new Triangle(vs[0],vs[1],vs[2]).circumcenter(), new Vector(1,0,0).normalizeThis()); // vs[3] = new Vertex(new Sphere(new Triangle(vs[0],vs[1],vs[2]).circumcenter(), new Triangle(vs[0],vs[1],vs[2]).circumradius()).getIntersection(l).getB()); // l = new Line(new Point(0,0,0), new Vector(0,0,1)); // double angle = 10*Math.PI/180; // l.rotateIn(vs[3], -angle); // l.rotateIn(vs[4], -angle); // System.out.println(Arrays.toString(vs[3].getCoords())); // System.out.println(Arrays.toString(vs[4].getCoords())); // double a = nextEvent(vs, 3,4, 0*Math.PI/180); // System.out.printf("Common sphere at angle %.10f___\n", a*180/Math.PI); //// Line l = new Line(new Point(0,0,0), new Vector(0,0,1)); //// l.rotateIn(vs[3], a); //// l.rotateIn(vs[4], a); // // Sphere s0 = Sphere.getMinSphere(vs[0],vs[1],vs[2],vs[3]); // Sphere s1 = Sphere.getMinSphere(vs[1],vs[2],vs[3],vs[4]); // s0.toConsole(); // s1.toConsole(); // } // // // static double nextEvent(Vertex[] vertices, int moving1, int moving2, int moving3, double curAlpha){ // int[] staticIds = new int[2]; // int c=0; // for(int i=0;i<5;i++){ // if(i!=moving1&&i!=moving2&&i!=moving3) staticIds[c++]=i; // } // // double twoAngle = nextEvent(vertices, staticIds[0], staticIds[1], -curAlpha); // return 2*Math.PI-twoAngle; // } // // static void testEvent3(){ // J3DScene scene = J3DScene.createJ3DSceneInFrame(); // scene.setAxisEnabled(false); // Vertex[] vs = { // new Vertex(new Point( 1, 1, 0)), // new Vertex(new Point( 0, 2, 0)), // new Vertex(new Point( 0, 1, 1)), // new Vertex(new Point( 0, 1, 0)), // null // }; // Line l; // l = new Line(new Triangle(vs[0],vs[1],vs[2]).circumcenter(), new Vector(1,0,0).normalizeThis()); // Tetrahedron tetra = new Tetrahedron(vs[0],vs[1],vs[2],vs[3]); // tetra.toScene(scene); // Sphere circumTetra = tetra.circumSphere(); // circumTetra.toScene(scene, new Color(0, 0, 0, 75)); // vs[4] = new Vertex(circumTetra.getIntersection(l).getB()); // vs[0].toScene(scene, 0.03, Color.red); // vs[1].toScene(scene, 0.03, Color.red); // vs[2].toScene(scene, 0.03, Color.red); // vs[3].toScene(scene, 0.03, Color.red); // vs[4].toScene(scene, 0.03, Color.pink); // // for(Vertex v: vs) System.out.println(Arrays.toString(v.getCoords())); // // // Matrix m = new Matrix(5,5); // for(int r=0;r<5;r++){ // int vIdx = r; // for(int c=0;c<3;c++){ // m.set(r, c, vs[vIdx].get(c)); // } // m.set(r, 3, vs[vIdx].dot(vs[vIdx])); // m.set(r, 4, 1); // } // // Vertex v1 = vs[3]; // double r1 = Math.sqrt(v1.x()*v1.x()+v1.y()*v1.y()); // Vertex v2 = vs[4]; // double r2 = Math.sqrt(v2.x()*v2.x()+v2.y()*v2.y()); // // double a; // l = new Line(new Point(0,0,0), new Vector(0,0,1)); // // a = nextEvent(vs, 3,4, 0*Math.PI/180); // System.out.printf("Common sphere at angle %.2f___\n", a*180/Math.PI); // // double a1 = Math.atan2(v1.y(),v1.x()); // double a2 = Math.atan2(v2.y(),v2.x()); // System.out.println(a1*180/Math.PI+" "+a2*180/Math.PI); // scene.addShape(new Sphere(new Point(vs[3]),0.03), new Color(200,50,50,100)); // scene.addShape(new Sphere(new Point(vs[4]),0.03), new Color(200,50,50,100)); //// l.rotateIn(vs[3], a); //// l.rotateIn(vs[4], a); // // scene.addShape(new Sphere(new Tetrahedron(vs[0],vs[1],vs[2],vs[3]).circumCenter(), new Tetrahedron(vs[0],vs[1],vs[2],vs[3]).circumRadius()), new Color(0,200,0,100)); // for(Vertex v: vs){ // scene.addShape(new Sphere(new Point(v),0.05)); // System.out.println(Arrays.toString(v.getCoords())); // } // // // double angle = 10*Math.PI/180; //// l.rotateIn(vs[0], angle); //// l.rotateIn(vs[1], angle); //// l.rotateIn(vs[2], angle); //// System.out.println(Arrays.toString(vs[4].getCoords())); //// scene.addShape(new Sphere(new Point(vs[0]),0.05),Color.RED); //// scene.addShape(new Sphere(new Point(vs[1]),0.05),Color.RED); //// scene.addShape(new Sphere(new Point(vs[2]),0.05),Color.RED); //// a = nextEvent(vs, 0,1,2, 0*Math.PI/180); //// System.out.printf("Common sphere at angle %.2f___ (expects %.2f___)\n", a*180/Math.PI, angle*180/Math.PI); // // // // } // // static Tet getThirdTet(Tet t1, Tet t2) { for (int i = 0; i < 4; i++) { if (t1.neighbors[i] == t2) continue; for (int j = 0; j < 4; j++) if(t2.neighbors[j] == t1.neighbors[i]) return t1.neighbors[i]; } return null; } // // static void flip(Tet t, int face){ // Tet n = t.neighbors[face]; // for(int i=0;i<4;i++){ // if(i==face) continue; // for(int j=0;j<4;j++) // if(n.neighbors[j]==t.neighbors[i]){ // flip32(t, n, t.neighbors[i]); // return; // } // } // flip23(t,n); // } // // /** // * Performs a 3-2-flip of the three specified tetrahedra. Two of these tetrahedra are preserved // * and the third (deleted) is returned. // * @requires Arrays.equals(t0.corners, Arrays.sort(t0.corners) ) && // * Arrays.equals(t1.corners, Arrays.sort(t1.corners) ) && // * Arrays.equals(t1.corners, Arrays.sort(t1.corners) ) && // * _two vertices shared by all three tetrahedra_ // * @return The deleted tetrahedron. // */ // static Tet flip32(Tet t0, Tet t1, Tet t2){ // // //Locate three non-shared vertices // Vertex[] vs = new Vertex[3]; // vs[0] = t0.getCorners()[t0.apex(t1)]; // vs[1] = t1.getCorners()[t1.apex(t2)]; // vs[2] = t2.getCorners()[t2.apex(t0)]; // // //Locate two shared vertices // Vertex v0 = t0.getCorners()[0]; // for(int i=0;i<4&&(vs[0]==v0 || vs[1]==v0);i++) // v0 = t0.getCorners()[i]; // Vertex v1 = t0.getCorners()[0]; // for(int i=0;i<4&&(vs[0]==v1 || vs[1]==v1 || v0==v1);i++) // v1 = t0.getCorners()[i]; // // int a0 = t0.indexOf(v0); // int b0 = t0.indexOf(v1); // int a1 = t1.indexOf(v1); // int b1 = t1.indexOf(v0); // // //Name neighbors // Tet[][] ns = { // {t0.neighbors[ a0 ], t0.neighbors[ b0 ]}, // {t1.neighbors[ b1 ], t1.neighbors[ a1 ]}, // {t2.neighbors[t2.indexOf(v0)], t2.neighbors[t2.indexOf(v1)]} // }; // // //Change corners of t0 and t1 // t0.getCorners()[b0] = vs[2]; // t1.getCorners()[b1] = vs[0]; // // //Change neighbors // t0.neighbors[a0] = t1; // t1.neighbors[a1] = t0; // // t0.neighbors[t0.indexOf_slow(vs[0])] = ns[1][1]; // if(ns[1][1]!=null) { // ns[1][1].neighbors[ns[1][1].apex(t1)] = t0; // Vertex oppV = ns[1][1].getCorners()[ns[1][1].apex(t0)]; // int count = t0.getCount(); // if (oppV.getType() == Vertex.VertexType.R) count = count + 16; // angles = getRoot(t0, oppV, count); // if (angles != null) addToHeap(angles, t0, ns[1][1], heapItem); // // } // t0.neighbors[t0.indexOf_slow(vs[1])] = ns[2][1]; // if(ns[2][1]!=null) ns[2][1].neighbors[ns[2][1].apex(t2)] = t0; // ///t0.neighbors[t0.indexOf(vs[2])] = ns[0][1]; if(ns[0][1]!=null) ns[0][1].neighbors[ns[0][1].apex(t0)] = t0;//Already there // // //t1.neighbors[t1.indexOf(vs[0])] = ns[1][0]; if(ns[1][0]!=null) ns[1][0].neighbors[ns[1][0].apex(t1)] = t1;//Already there // t1.neighbors[t1.indexOf_slow(vs[1])] = ns[2][0]; // if(ns[2][0]!=null) ns[2][0].neighbors[ns[2][0].apex(t2)] = t1; // t1.neighbors[t1.indexOf_slow(vs[2])] = ns[0][0]; // if(ns[0][0]!=null) ns[0][0].neighbors[ns[0][0].apex(t0)] = t1; // // //Resort // t0.sortCorners(); // t1.sortCorners(); // // t2.setAlive(false); // return t2; // } // // /** // * Performs a 2-3-flip of the two specified tetrahedra. The two existing tetrahedra are preserved and // * a new is created and returned. // * @requires Arrays.equals(t0.corners, Arrays.sort(t0.corners) ) && // * Arrays.equals(t1.corners, Arrays.sort(t1.corners) ) && // * convex(t0,t1) // * @return The newly created tetrahedron. // */ // static Tet flip23(Tet t0, Tet t1){ // int a0 = t0.apex(t1); // int a1 = t1.apex(t0); // // //Make a local copy of the entire configuration // Vertex[] vs = new Vertex[3]; // Tet[][] ns = new Tet[2][3]; // int[][] faceIds = new int[2][3];//Corner-indices of shared triangle // for(int i=0;i<3;i++){ // faceIds[0][i] = i+(i