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