/** * Input W must be initialized to a nonzero vector, output is {U,V,W}, an orthonormal basis. A * hint is provided about whether or not W is already unit length. * * @param kU DOCUMENT ME! * @param kV DOCUMENT ME! * @param kW DOCUMENT ME! * @param bUnitLengthW DOCUMENT ME! */ static void generateOrthonormalBasis( MjVector3f kU, MjVector3f kV, MjVector3f kW, boolean bUnitLengthW) { if (!bUnitLengthW) { kW.normalizeSafe(); } float fInvLength; if (Math.abs(kW.x) >= Math.abs(kW.y)) { // W.x or W.z is the largest magnitude component, swap them fInvLength = 1.0f / (float) Math.sqrt((kW.x * kW.x) + (kW.z * kW.z)); kU.x = -kW.z * fInvLength; kU.y = 0.0f; kU.z = +kW.x * fInvLength; } else { // W.y or W.z is the largest magnitude component, swap them fInvLength = 1.0f / (float) Math.sqrt((kW.y * kW.y) + (kW.z * kW.z)); kU.x = 0.0f; kU.y = +kW.z * fInvLength; kU.z = -kW.y * fInvLength; } kV.cross(kW, kU); }
public class Tetrahedron extends Shape3D { private static final float sqrt3 = (float) Math.sqrt(3.0); private static final float sqrt3_3 = sqrt3 / 3.0f; private static final float sqrt24_3 = (float) Math.sqrt(24.0) / 3.0f; private static final float ycenter = 0.5f * sqrt24_3; private static final float zcenter = -sqrt3_3; private static final Point3f p1 = new Point3f(-1.0f, -ycenter, -zcenter); private static final Point3f p2 = new Point3f(1.0f, -ycenter, -zcenter); private static final Point3f p3 = new Point3f(0.0f, -ycenter, -sqrt3 - zcenter); private static final Point3f p4 = new Point3f(0.0f, sqrt24_3 - ycenter, 0.0f); private static final Point3f[] verts = { p1, p2, p4, // front face p1, p4, p3, // left, back face p2, p3, p4, // right, back face p1, p3, p2, // bottom face }; private Point2f texCoord[] = { new Point2f(0.0f, 0.0f), new Point2f(1.0f, 0.0f), new Point2f(0.5f, sqrt3 / 2.0f), }; public Tetrahedron() { int i; TriangleArray tetra = new TriangleArray( 12, TriangleArray.COORDINATES | TriangleArray.NORMALS | TriangleArray.TEXTURE_COORDINATE_2); tetra.setCoordinates(0, verts); for (i = 0; i < 12; i++) { tetra.setTextureCoordinate(i, texCoord[i % 3]); } int face; Vector3f normal = new Vector3f(); Vector3f v1 = new Vector3f(); Vector3f v2 = new Vector3f(); Point3f[] pts = new Point3f[3]; for (i = 0; i < 3; i++) pts[i] = new Point3f(); for (face = 0; face < 4; face++) { tetra.getCoordinates(face * 3, pts); v1.sub(pts[1], pts[0]); v2.sub(pts[2], pts[0]); normal.cross(v1, v2); normal.normalize(); for (i = 0; i < 3; i++) { tetra.setNormal((face * 3 + i), normal); } } this.setGeometry(tetra); this.setAppearance(new Appearance()); } }
/** * Calculates the min and max boundaries of the structure after it has been transformed into its * canonical orientation. */ private void calcBoundaries() { minBoundary.x = Double.MAX_VALUE; maxBoundary.x = Double.MIN_VALUE; minBoundary.y = Double.MAX_VALUE; maxBoundary.x = Double.MIN_VALUE; minBoundary.z = Double.MAX_VALUE; maxBoundary.z = Double.MIN_VALUE; xzRadiusMax = Double.MIN_VALUE; Point3d probe = new Point3d(); for (Point3d[] list : subunits.getTraces()) { for (Point3d p : list) { probe.set(p); transformationMatrix.transform(probe); minBoundary.x = Math.min(minBoundary.x, probe.x); maxBoundary.x = Math.max(maxBoundary.x, probe.x); minBoundary.y = Math.min(minBoundary.y, probe.y); maxBoundary.y = Math.max(maxBoundary.y, probe.y); minBoundary.z = Math.min(minBoundary.z, probe.z); maxBoundary.z = Math.max(maxBoundary.z, probe.z); xzRadiusMax = Math.max(xzRadiusMax, Math.sqrt(probe.x * probe.x + probe.z * probe.z)); } } // System.out.println("MinBoundary: " + minBoundary); // System.out.println("MaxBoundary: " + maxBoundary); // System.out.println("zxRadius: " + xzRadiusMax); }
/** * Return a midpoint of a helix, calculated from three positions of three adjacent subunit * centers. * * @param p1 center of first subunit * @param p2 center of second subunit * @param p3 center of third subunit * @return midpoint of helix */ private Point3d getMidPoint(Point3d p1, Point3d p2, Point3d p3) { Vector3d v1 = new Vector3d(); v1.sub(p1, p2); Vector3d v2 = new Vector3d(); v2.sub(p3, p2); Vector3d v3 = new Vector3d(); v3.add(v1); v3.add(v2); v3.normalize(); // calculat the total distance between to subunits double dTotal = v1.length(); // calculate the rise along the y-axis. The helix axis is aligned with y-axis, // therfore, the rise between subunits is the y-distance double rise = p2.y - p1.y; // use phythagorean theoremm to calculate chord length between two subunit centers double chord = Math.sqrt(dTotal * dTotal - rise * rise); // System.out.println("Chord d: " + dTotal + " rise: " + rise + "chord: " + chord); double angle = helixLayers.getByLargestContacts().getAxisAngle().angle; // using the axis angle and the chord length, we can calculate the radius of the helix // http://en.wikipedia.org/wiki/Chord_%28geometry%29 double radius = chord / Math.sin(angle / 2) / 2; // can this go to zero? // System.out.println("Radius: " + radius); // project the radius onto the vector that points toward the helix axis v3.scale(radius); v3.add(p2); // System.out.println("Angle: " + // Math.toDegrees(helixLayers.getByLowestAngle().getAxisAngle().angle)); Point3d cor = new Point3d(v3); return cor; }
/** * Normalize this vector in place. If the vector is very close to zero length, then this vector is * stored as the zero vector. */ void normalizeSafe() { float fLengthSquared = lengthSquared(); if (0.0f == fLengthSquared) { set(ZERO); } else { scale(1.0f / (float) Math.sqrt(fLengthSquared)); } }
/** * calculates z and adjusts for border conditions * * @param x * @param y * @return */ private float calculateZ(float x, float y) { float z = 0; z = 1 - x * x - y * y; if (z > 0) { z = (float) Math.sqrt(z); } else { z = 0; } return z; }
public void vec2FieldMagnitude(Field field, AffineTransform ftoi) { AffineTransform itof = null; try { itof = ftoi.createInverse(); } catch (NoninvertibleTransformException niv) { TDebug.println(0, "NoninvertibleTransformException: " + niv); } Vector3d v = new Vector3d(); Point2D.Double p = new Point2D.Double(); for (int j = 0, k = 0; j < height; ++j) for (int i = 0; i < width; ++i, ++k) { p.x = i; p.y = j; itof.transform(p, p); v = field.get(p.x, p.y, 0.0); f[k] = (float) Math.sqrt(v.x * v.x + v.y * v.y); } }
boolean intersect(Ray r, Hit h, Range range) { // ToDo: boolean retVal = false; double Aq = r.getDirection().dot(r.getDirection()); double Bq = 2 * r.getDirection() .dot( new Vector3d( r.getOrigin().x - center.x, r.getOrigin().y - center.y, r.getOrigin().z - center.z)); double Cq = (Math.pow(r.getOrigin().x - center.x, 2) + Math.pow(r.getOrigin().y - center.y, 2) + Math.pow(r.getOrigin().z - center.z, 2)) - Math.pow(radius, 2); double discriminant = Math.pow(Bq, 2) - (4 * Aq * Cq); // Hay intersección, si se cumple esta condición... solo se ne // necesita el primer valor que es el de la primera intersección if (discriminant >= 0) { discriminant = Math.sqrt(discriminant); double firstT = (-Bq - discriminant) / (2 * Aq); if (firstT > range.minT && firstT < range.maxT) { h.setColor(this.color); range.maxT = firstT; h.setT(firstT); // se debe retornar T } retVal = true; } return retVal; // Compute the intersection of the ray with the // Sphere and update what needs to be updated // Valid values for t must be within the "range" // ... }