/**
   * 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;
 }
Example #3
0
 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;
  }