/** * 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; }
/* (non-Javadoc) * @see org.biojava.nbio.structure.quaternary.core.AxisAligner#getDimension() */ @Override public Vector3d getDimension() { run(); Vector3d dimension = new Vector3d(); dimension.sub(maxBoundary, minBoundary); dimension.scale(0.5); return dimension; }
protected void computeCircle() { Vector3d center = new Vector3d((Vector3d) get(0)); Vector3d p2 = new Vector3d((Vector3d) get(1)); p2.sub(center); double radius = p2.length(); removeAllElements(); double angle = 0; double incAngle = 2 * Math.PI / sides; for (int i = 0; i < sides; i++) { super.add( new Vector3d( center.x + radius * Math.cos(angle), center.y + radius * Math.sin(angle), 0)); angle += incAngle; } super.add(new Vector3d(center.x + radius, center.y, 0)); }
/** * Returns the default reference vector for the alignment of Cn structures * * @return */ private Vector3d getReferenceAxisCylic() { // get principal axis vector that is perpendicular to the principal // rotation vector Vector3d vmin = null; double dotMin = 1.0; for (Vector3d v : principalAxesOfInertia) { if (Math.abs(principalRotationVector.dot(v)) < dotMin) { dotMin = Math.abs(principalRotationVector.dot(v)); vmin = new Vector3d(v); } } if (principalRotationVector.dot(vmin) < 0) { vmin.negate(); } return vmin; }
private void calcTransformationBySymmetryAxes() { Vector3d[] axisVectors = new Vector3d[2]; axisVectors[0] = new Vector3d(principalRotationVector); axisVectors[1] = new Vector3d(referenceVector); // y,z axis centered at the centroid of the subunits Vector3d[] referenceVectors = new Vector3d[2]; referenceVectors[0] = new Vector3d(Z_AXIS); referenceVectors[1] = new Vector3d(Y_AXIS); transformationMatrix = alignAxes(axisVectors, referenceVectors); // combine with translation Matrix4d combined = new Matrix4d(); combined.setIdentity(); Vector3d trans = new Vector3d(subunits.getCentroid()); trans.negate(); combined.setTranslation(trans); transformationMatrix.mul(combined); // for helical geometry, set a canonical view for the Z direction calcZDirection(); }
private double[] springPenalty(Vector3d xi, Vector3d xj, double dist) { double[] F = new double[6]; // collision normal Vector3d n = xi.minus(xj); n = n.dot(1 / n.norm()); F[0] = -(k * (n.x()) * (-2 * proximity + dist)); F[1] = -(k * (n.y()) * (-2 * proximity + dist)); F[2] = -(k * (n.z()) * (-2 * proximity + dist)); F[3] = -F[0]; F[4] = -F[1]; F[5] = -F[2]; return F; }
private Vector3d orthogonalize(Vector3d vector1, Vector3d vector2) { double dot = vector1.dot(vector2); Vector3d ref = new Vector3d(vector2); // System.out.println("p.r: " + dot); // System.out.println("Orig refVector: " + referenceVector); if (dot < 0) { vector2.negate(); } if (Math.abs(dot) < 0.00001) { System.out.println("HelixAxisAligner: Warning: reference axis parallel"); } vector2.cross(vector1, vector2); // System.out.println("Intermed. refVector: " + vector2); vector2.normalize(); // referenceVector.cross(referenceVector, principalRotationVector); vector2.cross(vector1, vector2); vector2.normalize(); if (ref.dot(vector2) < 0) { vector2.negate(); } // System.out.println("Mod. refVector: " + vector2); return vector2; }
private double[] calculatePenaltyForces(double[] X, double[] V, HashSet<Collision> cSet) { double[] penalty = new double[X.length]; // for each collision, apply the penalties for (Collision col : cSet) { // Collision col = col_rec[i]; // vertex-face collision if (col.getType() == Collision.VERTEX_FACE) { // System.out.println("VERTEX-FACE"); // get indicies int[] parts = col.getParticles(); int p = parts[0]; int a = parts[1]; int b = parts[2]; int c = parts[3]; // get barycentric coords double[] bc = col.getBaryCoords(); double u = bc[0]; double v = bc[1]; double w = bc[2]; // get collision point and collision velocities Vector3d xa = new Vector3d(); // was Vector3d xa, xb, va, vb; Vector3d xb = new Vector3d(); Vector3d va = new Vector3d(); Vector3d vb = new Vector3d(); xa.set(X[3 * p], X[3 * p + 1], X[3 * p + 2]); xb.set( u * X[3 * a] + v * X[3 * b] + w * X[3 * c], u * X[3 * a + 1] + v * X[3 * b + 1] + w * X[3 * c + 1], u * X[3 * a + 2] + v * X[3 * b + 2] + w * X[3 * c + 2]); va.set(V[3 * p], V[3 * p + 1], V[3 * p + 2]); vb.set( u * V[3 * a] + v * V[3 * b] + w * V[3 * c], u * V[3 * a + 1] + v * V[3 * b + 1] + w * V[3 * c + 1], u * V[3 * a + 2] + v * V[3 * b + 2] + w * V[3 * c + 2]); // System.out.println("REL VEL "+xa.minus(xb).dot(va.minus(vb))+" "+va+" "+vb+" "+xa+" // "+xb); // System.out.println("REL VEL2 "+xb.minus(xa).dot(vb.minus(va))); /*if the objects have do not have a seperating velocity, apply the local spring penalty */ if (xa.minus(xb).dot(va.minus(vb)) < 0) { double[] local_penalty = springPenalty(xa, xb, col.getDistance()); // apply to vertex penalty[3 * p] += local_penalty[0]; penalty[3 * p + 1] += local_penalty[1]; penalty[3 * p + 2] += local_penalty[2]; // apply to triangle coordinates penalty[3 * a] += bc[0] * local_penalty[3]; penalty[3 * a + 1] += bc[0] * local_penalty[4]; penalty[3 * a + 2] += bc[0] * local_penalty[5]; penalty[3 * b] += bc[1] * local_penalty[3]; penalty[3 * b + 1] += bc[1] * local_penalty[4]; penalty[3 * b + 2] += bc[1] * local_penalty[5]; penalty[3 * c] += bc[2] * local_penalty[3]; penalty[3 * c + 1] += bc[2] * local_penalty[4]; penalty[3 * c + 2] += bc[2] * local_penalty[5]; } } // edge-edge collision if (col.getType() == Collision.EDGE_EDGE) { // get indicies int[] parts = col.getParticles(); int p1 = parts[0]; int q1 = parts[1]; int p2 = parts[2]; int q2 = parts[3]; // get barycentric coords double[] coords = col.getBaryCoords(); double s = coords[0]; double t = coords[1]; Vector3d xa = new Vector3d(); // was Vector3d xa, xb, va, vb; Vector3d xb = new Vector3d(); Vector3d va = new Vector3d(); Vector3d vb = new Vector3d(); // edge points xa.set( s * X[3 * p1] + (1 - s) * X[3 * q1], s * X[3 * p1 + 1] + (1 - s) * X[3 * q1 + 1], s * X[3 * p1 + 2] + (1 - s) * X[3 * q1 + 2]); xb.set( t * X[3 * p2] + (1 - t) * X[3 * q2], t * X[3 * p2 + 1] + (1 - t) * X[3 * q2 + 1], t * X[3 * p2 + 2] + (1 - t) * X[3 * q2 + 2]); // velocities va.set( s * V[3 * p1] + (1 - s) * V[3 * q1], s * V[3 * p1 + 1] + (1 - s) * V[3 * q1 + 1], s * V[3 * p1 + 2] + (1 - s) * V[3 * q1 + 2]); vb.set( t * V[3 * p2] + (1 - t) * V[3 * q2], t * V[3 * p2 + 1] + (1 - t) * V[3 * q2 + 1], t * V[3 * p2 + 2] + (1 - t) * V[3 * q2 + 2]); /*if the objects have do not have a seperating velocity, apply the local spring penalty */ if (xa.minus(xb).dot(va.minus(vb)) < 0) { double[] local_penalty = springPenalty(xa, xb, col.getDistance()); // apply penalty to first edge penalty[3 * p1] += s * local_penalty[0]; penalty[3 * p1 + 1] += s * local_penalty[1]; penalty[3 * p1 + 2] += s * local_penalty[2]; penalty[3 * q1] += (1 - s) * local_penalty[0]; penalty[3 * q1 + 1] += (1 - s) * local_penalty[1]; penalty[3 * q1 + 2] += (1 - s) * local_penalty[2]; // apply penalty to second edge penalty[3 * p2] += t * local_penalty[3]; penalty[3 * p2 + 1] += t * local_penalty[4]; penalty[3 * p2 + 2] += t * local_penalty[5]; penalty[3 * q2] += (1 - t) * local_penalty[3]; penalty[3 * q2 + 1] += (1 - t) * local_penalty[4]; penalty[3 * q2 + 2] += (1 - t) * local_penalty[5]; } } } return penalty; }
/** * 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); }
/** * Returns a transformation matrix that rotates refPoints to match coordPoints * * @param refPoints the points to be aligned * @param referenceVectors * @return */ private Matrix4d alignAxes(Vector3d[] axisVectors, Vector3d[] referenceVectors) { Matrix4d m1 = new Matrix4d(); AxisAngle4d a = new AxisAngle4d(); Vector3d axis = new Vector3d(); // calculate rotation matrix to rotate refPoints[0] into coordPoints[0] Vector3d v1 = new Vector3d(axisVectors[0]); Vector3d v2 = new Vector3d(referenceVectors[0]); double dot = v1.dot(v2); if (Math.abs(dot) < 0.999) { axis.cross(v1, v2); axis.normalize(); a.set(axis, v1.angle(v2)); m1.set(a); // make sure matrix element m33 is 1.0. It's 0 on Linux. m1.setElement(3, 3, 1.0); } else if (dot > 0) { // parallel axis, nothing to do -> identity matrix m1.setIdentity(); } else if (dot < 0) { // anti-parallel axis, flip around x-axis m1.set(flipX()); } // apply transformation matrix to all refPoints m1.transform(axisVectors[0]); m1.transform(axisVectors[1]); // calculate rotation matrix to rotate refPoints[1] into coordPoints[1] v1 = new Vector3d(axisVectors[1]); v2 = new Vector3d(referenceVectors[1]); Matrix4d m2 = new Matrix4d(); dot = v1.dot(v2); if (Math.abs(dot) < 0.999) { axis.cross(v1, v2); axis.normalize(); a.set(axis, v1.angle(v2)); m2.set(a); // make sure matrix element m33 is 1.0. It's 0 on Linux. m2.setElement(3, 3, 1.0); } else if (dot > 0) { // parallel axis, nothing to do -> identity matrix m2.setIdentity(); } else if (dot < 0) { // anti-parallel axis, flip around z-axis m2.set(flipZ()); } // apply transformation matrix to all refPoints m2.transform(axisVectors[0]); m2.transform(axisVectors[1]); // combine the two rotation matrices m2.mul(m1); // the RMSD should be close to zero Point3d[] axes = new Point3d[2]; axes[0] = new Point3d(axisVectors[0]); axes[1] = new Point3d(axisVectors[1]); Point3d[] ref = new Point3d[2]; ref[0] = new Point3d(referenceVectors[0]); ref[1] = new Point3d(referenceVectors[1]); if (SuperPosition.rmsd(axes, ref) > 0.1) { System.out.println( "Warning: AxisTransformation: axes alignment is off. RMSD: " + SuperPosition.rmsd(axes, ref)); } return m2; }