package ProGAL.geom3d.volumes; import java.awt.Color; import java.text.DecimalFormat; import java.util.List; import ProGAL.geom3d.Circle; import ProGAL.geom3d.Line; import ProGAL.geom3d.LineSegment; import ProGAL.geom3d.Plane; import ProGAL.geom3d.Point; import ProGAL.geom3d.Vector; import ProGAL.geom3d.kineticDelaunay.Tri; import ProGAL.geom3d.kineticDelaunay.Vertex; import ProGAL.geom3d.viewer.J3DScene; import ProGAL.math.Constants; import ProGAL.math.Matrix; import ProGAL.math.Polynomial; /** * Let the radius from the center of the hole to the center of the torus tube be R, and the radius of * the tube be r. Then the equation in Cartesian coordinates for a torus azimuthally symmetric about * the z-axis is * (R - sqrt(x^2+y^2))^2 + z^2 = r^2 * and the parametric equations are * x = (R + rcos(v)) cos(u) * y = (R + rsin(v)) sin(u) * z = rsin(v) * for u, v in [0, 2PI[ * * The three different classes of standard tori correspond to the three possible relative sizes of r * and R. When R > r, the surface will be the familiar ring torus. The case R = r corresponds to the * horn torus, which in effect is a torus with no "hole". The case R < r describes the self-intersecting * spindle torus. When R = 0, the torus degenerates to the sphere. */ public class Torus { protected Point center; protected Vector normal; protected double R; protected double r; public Torus(Point center, Vector normal, double majorRadius, double minorRadius) { this.center = center; this.normal = normal; this.R = majorRadius; this.r = minorRadius; } /** Returns TRUE if point q is in the interior of the torus */ public boolean contains(Point q) { double RR = R*R; Vector vp = new Vector(center, q); return Math.pow(q.distanceSquared(center) + RR - r*r,2) - 4*RR*(vp.cross(normal).getLengthSquared()) < 0.0; } public Circle getMainCircle() { return new Circle(center, R, normal); } public Plane getMainPlane() { return new Plane(center, normal); } public Circle getPoloidalCircle() { return null; } public Circle getSweepingCircle() { Vector v = normal.getOrthonormal(); return new Circle(center.add(v.scaleToLength(R)), r, normal.cross(v)); } public Sphere getSweepingSphere() { Vector v = normal.getOrthonormal(); return new Sphere(center.add(v.scaleToLength(R)), r); } public double getSurfaceArea() { return 4*Math.PI*Math.PI*R*r; } public Circle getToroidalCircle() { return new Circle(center, R, normal); } public double getVolume() { return 2*Math.PI*Math.PI*R*r*r; } /** Two circles of major radius R, tilted to the center plane by slopes of r/R and -r/R and offset from the center by minor radius distance r */ public Circle[] getVillarceauCircles () { return null; } public double getMajorRadius(){ return R; } public double getMinorRadius(){ return r; } public Vector getNormal(){ return normal; } public Point getCenter() { return center; } // Daisy /** Find up to four intersection points with circle C(p,n). See http://ubm.opus.hbz-nrw.de/volltexte/2009/2037/pdf/diss.pdf **/ public Point[] getIntersectionCircle(Circle C) { // DecimalFormat newFormat = new DecimalFormat("#.#########"); /*Vector newCircleNormal = C.getNormal(); Point newCircleCenter = C.getCenter();*/ Vector e3 = new Vector(0,0,1); Vector rotAxis = normal.cross(e3); if (!(rotAxis.equals(new Vector(0,0,0)))) { rotAxis.normalizeThis(); } double angle = normal.angle(e3); Matrix rotMatrix = Matrix.createRotationMatrix(angle, rotAxis); Vector translate = new Vector(-center.x(),-center.y(),-center.z()); // Vector newTorusNormal = rotMatrix.multiply(normal).normalize(); Vector newCircleNormal = rotMatrix.multiply(C.getNormal()).normalizeThis(); Point CC0 = C.getCenter().add(translate); Point newCircleCenter = (Point)rotMatrix.multiplyIn(CC0); Point[] intersections = new Point[4]; double ax, ay, az, bx, by, bz, nz; Vector a_, b_; double nx = newCircleNormal.get(0); double ny = newCircleNormal.get(1); if (nx*nx+ny*ny == 0) { ax = 1; ay = 0; az = 0; a_ = new Vector(ax, ay, az); bx = 0; by = 1; bz = 0; b_ = new Vector(bx, by, bz); nx = 0; ny = 0; nz = 1; } else { nz = newCircleNormal.get(2); a_ = newCircleNormal.getOrthogonal().normalizeThis(); b_ = a_.cross(newCircleNormal).normalizeThis(); } double[] m1 = {a_.get(0), b_.get(0), nx}; double[] m2 = {a_.get(1), b_.get(1), ny}; double[] m3 = {a_.get(2), b_.get(2), nz}; double[][] mlist = {m1, m2, m3}; // Matrix M = new Matrix(mlist); //Point p = M.invert().multiply(center.subtract(pPoint)); // Point p = new Point(0,0,0); double alph = newCircleCenter.dot(newCircleCenter); double gam = newCircleCenter.dot(a_); double del = newCircleCenter.dot(b_); double eps = alph + C.getRadius()*C.getRadius()+R*R-r*r; double a = 4*gam*gam - 4*R*R*(a_.get(0)*a_.get(0)+a_.get(1)*a_.get(1)); double b = 4*del*del - 4*R*R*(b_.get(0)*b_.get(0)+b_.get(1)*b_.get(1)); double f = 4*gam*del - 4*R*R*(a_.get(0)*b_.get(0)+a_.get(1)*b_.get(1)); double l = 2*gam*eps - 4*R*R*(newCircleCenter.x()*a_.get(0) + newCircleCenter.y()*a_.get(1)); double m = 2*del*eps - 4*R*R*(newCircleCenter.x()*b_.get(0) + newCircleCenter.y()*b_.get(1)); double d = eps*eps - 4*R*R*(newCircleCenter.x()*newCircleCenter.x() + newCircleCenter.y()*newCircleCenter.y()); double[] er0 = {a, f, l}; double[] er1 = {f, b, m}; double[] er2 = {l, m, d}; double[][] emat = {er0, er1, er2}; Matrix E = new Matrix(emat); /* Vector a1 = M.multiply(new Vector(1,0,0)); double cPHI = a1.dot(M.multiply(new Vector(1,0,0))); double sPHI = -a1.dot(M.multiply(new Vector(0,1,0))); double[] ar0 = {cPHI, -sPHI, p.x()}; double[] ar1 = {sPHI, cPHI, p.y()}; double[] ar2 = {0, 0, 1}; double[][] amat = {ar0, ar1, ar2}; Matrix A = new Matrix(amat); System.out.println("A = "+A.toString()); Matrix ENew = ((A.invert().transpose()).multiply(E)).multiply(A.invert()); System.out.println("E' = "+ENew.toString());*/ Matrix ENew = E; double[] pars = new double[5]; pars[4] = ENew.get(0,0)*C.getRadius()*C.getRadius() - 2*ENew.get(2,0)*C.getRadius() + ENew.get(2,2); //pars[4] = Double.valueOf(newFormat.format(pars[4])); pars[3] = -4*ENew.get(1,0)*C.getRadius()*C.getRadius() + 4*ENew.get(1,2)*C.getRadius(); //pars[3] = Double.valueOf(newFormat.format(pars[3])); pars[2] = -2*ENew.get(0,0)*C.getRadius()*C.getRadius() + 4*ENew.get(1,1)*C.getRadius()*C.getRadius() + 2*ENew.get(2,2); //pars[2] = Double.valueOf(newFormat.format(pars[2])); pars[1] = 4*ENew.get(0,1)*C.getRadius()*C.getRadius() + 4*ENew.get(1,2)*C.getRadius(); //pars[1] = Double.valueOf(newFormat.format(pars[1])); pars[0] = ENew.get(0,0)*C.getRadius()*C.getRadius() + 2*ENew.get(0,2)*C.getRadius() + ENew.get(2,2); //pars[0] = Double.valueOf(newFormat.format(pars[0])); for (int z = 0 ; z < 5 ; z++) { if (Math.abs(pars[z]) <= Constants.EPSILON) pars[z] = 0.0; } Polynomial func; int tmpDeg = 4; while ((tmpDeg != 0) && (pars[tmpDeg] == 0.0)) { tmpDeg--; } if (tmpDeg != 4) { double[] coeffs = new double[tmpDeg+1]; for (int i = 0; i <= tmpDeg ; i++) { coeffs[i] = pars[i]; } func = new Polynomial(coeffs); } else { func = new Polynomial(pars); } // System.out.println("func = "+func.toString()); // System.out.println("func = "+pars[4]+"x^4 + "+pars[3]+"x^3 + "+pars[2]+"x^2 + "+pars[1]+"x + "+pars[0]); Double[] roots = Polynomial.solveQuartic(func.coeff); if (roots==null) return null; /* for (Double r : roots) { if (r==null) break; System.out.println("root = "+r); }*/ // Point[] ps = new Point[4]; if (roots.length == 0) return null; for (int k = 0 ; k