protected void readVoxelVector(int voxelVectorIndex) throws Exception {
   readLine();
   V3 voxelVector = volumetricVectors[voxelVectorIndex];
   if ((voxelCounts[voxelVectorIndex] = parseIntStr(line)) == Integer.MIN_VALUE) // unreadable
   next[0] = line.indexOf(" ");
   voxelVector.set(parseFloat(), parseFloat(), parseFloat());
   if (isAnisotropic) setVectorAnisotropy(voxelVector);
 }
 /**
  * Matches normals for adjacent mesh sections to create a seamless overall mesh. We use temporary
  * normals here. We will convert normals to normixes later.
  *
  * @param i
  * @param nPer
  */
 void adjustCartoonSeamNormals(int i, int nPer) {
   if (bsTemp == null) bsTemp = Normix.newVertexBitSet();
   if (i == iNext - 1
       && iNext < monomerCount
       && monomers[i].getStrucNo() == monomers[iNext].getStrucNo()
       && meshReady[i]
       && meshReady[iNext]) {
     try {
       V3[] normals2 = meshes[iNext].getNormalsTemp();
       V3[] normals = meshes[i].getNormalsTemp();
       int normixCount = normals.length;
       if (doCap0) normixCount -= nPer;
       for (int j = 1; j <= nPer; ++j) {
         norml.add2(normals[normixCount - j], normals2[nPer - j]);
         norml.normalize();
         meshes[i].normalsTemp[normixCount - j].setT(norml);
         meshes[iNext].normalsTemp[nPer - j].setT(norml);
       }
     } catch (Exception e) {
     }
   }
 }
Exemple #3
0
 private void getStateID(SB sb) {
   V3 v1 = new V3();
   for (Ellipsoid ellipsoid : simpleEllipsoids.values()) {
     Tensor t = ellipsoid.tensor;
     if (!ellipsoid.isValid || t == null) continue;
     sb.append("  Ellipsoid ID ")
         .append(ellipsoid.id)
         .append(" modelIndex ")
         .appendI(t.modelIndex)
         .append(" center ")
         .append(Escape.eP(ellipsoid.center))
         .append(" axes");
     for (int i = 0; i < 3; i++) {
       v1.setT(t.eigenVectors[i]);
       v1.scale(ellipsoid.lengths[i]);
       sb.append(" ").append(Escape.eP(v1));
     }
     sb.append(" " + getColorCommandUnk("", ellipsoid.colix, translucentAllowed));
     if (ellipsoid.options != null) sb.append(" options ").append(PT.esc(ellipsoid.options));
     if (!ellipsoid.isOn) sb.append(" off");
     sb.append(";\n");
   }
 }
Exemple #4
0
  private void setSymmetry(boolean setOperators) {
    double[][] a;

    // Part 1: Get sigma_nu
    // van Smaalen, p. 92.

    Logger.info("[subsystem " + code + "]");

    Matrix winv = w.inverse();
    Logger.info("w=" + w);
    Logger.info("w_inv=" + winv);

    //      w33  w3d      van Smaalen, p. 94, Eqn. 4.15
    // w =
    //      wd3  wdd

    Matrix w33 = w.getSubmatrix(0, 0, 3, 3);
    Matrix wd3 = w.getSubmatrix(3, 0, d, 3);
    Matrix w3d = w.getSubmatrix(0, 3, 3, d);
    Matrix wdd = w.getSubmatrix(3, 3, d, d);
    Matrix sigma = msRdr.getSigma();
    // Eqn. 4.16
    Matrix sigma_nu = wdd.mul(sigma).add(wd3).mul(w3d.mul(sigma).add(w33).inverse());
    Matrix tFactor = wdd.sub(sigma_nu.mul(w3d));

    Logger.info("sigma_nu = " + sigma_nu);

    // Part 2: Get the new unit cell and symmetry operators

    SymmetryInterface s0 = msRdr.cr.asc.getSymmetry();
    V3[] vu43 = s0.getUnitCellVectors();
    V3[] vr43 = reciprocalsOf(vu43);

    // using full matrix math here:
    //
    // mar3  = just 3x3 matrix of ai* (a*, b*, c*)
    // mard3 = full (3+d)x3 matrix of ai* (a*, b*, c*, x4*, x5*,....)
    //       = [ mard3 | sigma * mard3 ]
    //
    Matrix mard3 = new Matrix(null, 3 + d, 3);
    Matrix mar3 = new Matrix(null, 3, 3);
    double[][] mard3a = mard3.getArray();
    double[][] mar3a = mar3.getArray();
    for (int i = 0; i < 3; i++)
      mard3a[i] = mar3a[i] = new double[] {vr43[i + 1].x, vr43[i + 1].y, vr43[i + 1].z};

    Matrix sx = sigma.mul(mar3);
    a = sx.getArray();
    for (int i = 0; i < d; i++) mard3a[i + 3] = a[i];
    a = w.mul(mard3).getArray();

    // back to vector notation and direct lattice

    V3[] uc_nu = new V3[4];
    uc_nu[0] = vu43[0]; // origin
    for (int i = 0; i < 3; i++)
      uc_nu[i + 1] = V3.new3((float) a[i][0], (float) a[i][1], (float) a[i][2]);
    uc_nu = reciprocalsOf(uc_nu);
    symmetry =
        ((Symmetry) msRdr.cr.getInterface("org.jmol.symmetry.Symmetry"))
            .getUnitCell(uc_nu, false, null);
    modMatrices = new Matrix[] {sigma_nu, tFactor};
    if (!setOperators) return;
    isFinalized = true;

    // Part 3: Transform the operators
    //

    Logger.info("unit cell parameters: " + symmetry.getUnitCellInfo());
    symmetry.createSpaceGroup(-1, "[subsystem " + code + "]", new Lst<M4>());
    int nOps = s0.getSpaceGroupOperationCount();
    for (int iop = 0; iop < nOps; iop++) {
      Matrix rv = s0.getOperationRsVs(iop);
      Matrix r0 = rv.getRotation();
      Matrix v0 = rv.getTranslation();
      Matrix r = w.mul(r0).mul(winv);
      Matrix v = w.mul(v0);
      String code = this.code;
      if (isMixed(r)) {
        // This operator mixes x4,x5... into x1,x2,x3.
        // It is not a pure operation. Instead, it correlates one
        // subsystem with another. Our job is to find the other
        // subsystem "j" that will satisfy the following condition:
        //
        // (Wj R Wi_inv).submatrix(0,3,3,d) == all_zeros
        //
        for (Entry<String, Subsystem> e : msRdr.htSubsystems.entrySet()) {
          Subsystem ss = e.getValue();
          if (ss == this) continue;
          Matrix rj = ss.w.mul(r0).mul(winv);
          if (!isMixed(rj)) {
            // We have found the corresponding subsystem.
            // The result of this operation will be in other system,
            // and the operation itself will be used to rotate the modulation.
            // ss.code will be used to mark any atom created by this operation as
            // part of the other system.
            r = rj;
            v = ss.w.mul(v0);
            code = ss.code;
            break;
          }
        }
      }
      String jf = symmetry.addOp(code, r, v, sigma_nu);
      Logger.info(
          this.code + "." + (iop + 1) + (this.code.equals(code) ? "   " : ">" + code + " ") + jf);
    }
  }
  /**
   * Cartoon meshes are triangulated objects.
   *
   * @param i
   * @param madBeg
   * @param madMid
   * @param madEnd
   * @param aspectRatio
   * @param tension
   * @return true if deferred rendering is required due to normals averaging
   */
  private boolean createMesh(
      int i, int madBeg, int madMid, int madEnd, float aspectRatio, int tension) {
    setNeighbors(i);
    if (controlPoints[i].distanceSquared(controlPoints[iNext]) == 0) return false;

    // options:

    // isEccentric == not just a tube
    boolean isEccentric = (aspectRatio != 1 && wingVectors != null);
    // isFlatMesh == using mesh even for hermiteLevel = 0 (for exporters)
    boolean isFlatMesh = (aspectRatio == 0);
    // isElliptical == newer cartoonFancy business
    boolean isElliptical = (cartoonsFancy || hermiteLevel >= 6);

    // parameters:

    int nHermites = (hermiteLevel + 1) * 2 + 1; // 5 for hermiteLevel = 1; 13 for hermitelevel 5
    int nPer =
        (isFlatMesh
            ? 4
            : (hermiteLevel + 1) * 4 - 2); // 6 for hermiteLevel 1; 22 for hermiteLevel 5
    float angle = (float) ((isFlatMesh ? Math.PI / (nPer - 1) : 2 * Math.PI / nPer));
    Mesh mesh = meshes[i] = new Mesh().mesh1("mesh_" + shapeID + "_" + i, (short) 0, i);
    boolean variableRadius = (madBeg != madMid || madMid != madEnd);

    // control points and vectors:

    if (controlHermites == null || controlHermites.length < nHermites + 1) {
      controlHermites = new P3[nHermites + 1];
    }
    GData.getHermiteList(
        tension,
        controlPoints[iPrev],
        controlPoints[i],
        controlPoints[iNext],
        controlPoints[iNext2],
        controlPoints[iNext3],
        controlHermites,
        0,
        nHermites,
        true);
    // wing hermites determine the orientation of the cartoon
    if (wingHermites == null || wingHermites.length < nHermites + 1) {
      wingHermites = new V3[nHermites + 1];
    }

    wing.setT(wingVectors[iPrev]);
    if (madEnd == 0) wing.scale(2.0f); // adds a flair to an arrow
    GData.getHermiteList(
        tension,
        wing,
        wingVectors[i],
        wingVectors[iNext],
        wingVectors[iNext2],
        wingVectors[iNext3],
        wingHermites,
        0,
        nHermites,
        false);
    //    }
    // radius hermites determine the thickness of the cartoon
    float radius1 = madBeg / 2000f;
    float radius2 = madMid / 2000f;
    float radius3 = madEnd / 2000f;
    if (variableRadius) {
      if (radiusHermites == null || radiusHermites.length < ((nHermites + 1) >> 1) + 1) {
        radiusHermites = new P3[((nHermites + 1) >> 1) + 1];
      }
      ptPrev.set(radius1, radius1, 0);
      pt.set(radius1, radius2, 0);
      pt1.set(radius2, radius3, 0);
      ptNext.set(radius3, radius3, 0);
      // two for the price of one!
      GData.getHermiteList(
          4, ptPrev, pt, pt1, ptNext, ptNext, radiusHermites, 0, (nHermites + 1) >> 1, true);
    }

    // now create the cartoon polygon

    int nPoints = 0;
    int iMid = nHermites >> 1;
    int kpt1 = (nPer + 2) / 4;
    int kpt2 = (3 * nPer + 2) / 4;
    int mode =
        (!isEccentric
            ? MODE_TUBE
            : isFlatMesh ? MODE_FLAT : isElliptical ? MODE_ELLIPTICAL : MODE_NONELLIPTICAL);
    boolean useMat = (mode == MODE_TUBE || mode == MODE_NONELLIPTICAL);
    for (int p = 0; p < nHermites; p++) {
      norm.sub2(controlHermites[p + 1], controlHermites[p]);
      float scale =
          (!variableRadius ? radius1 : p < iMid ? radiusHermites[p].x : radiusHermites[p - iMid].y);
      wing.setT(wingHermites[p]);
      wing1.setT(wing);
      switch (mode) {
        case MODE_FLAT:
          // hermiteLevel = 0 and not exporting
          break;
        case MODE_ELLIPTICAL:
          // cartoonFancy
          wing1.cross(norm, wing);
          wing1.normalize();
          wing1.scale(wing.length() / aspectRatio);
          break;
        case MODE_NONELLIPTICAL:
          // older nonelliptical hermiteLevel > 0
          wing.scale(2 / aspectRatio);
          wing1.sub(wing);
          break;
        case MODE_TUBE:
          // not helix or sheet
          wing.cross(wing, norm);
          wing.normalize();
          break;
      }
      wing.scale(scale);
      wing1.scale(scale);
      if (useMat) {
        aa.setVA(norm, angle);
        mat.setAA(aa);
      }
      pt1.setT(controlHermites[p]);
      float theta = (isFlatMesh ? 0 : angle);
      for (int k = 0; k < nPer; k++, theta += angle) {
        if (useMat && k > 0) mat.rotate(wing);
        switch (mode) {
          case MODE_FLAT:
            wingT.setT(wing1);
            wingT.scale((float) Math.cos(theta));
            break;
          case MODE_ELLIPTICAL:
            wingT.setT(wing1);
            wingT.scale((float) Math.sin(theta));
            wingT.scaleAdd2((float) Math.cos(theta), wing, wingT);
            break;
          case MODE_NONELLIPTICAL:
            wingT.setT(wing);
            if (k == kpt1 || k == kpt2) wing1.scale(-1);
            wingT.add(wing1);
            break;
          case MODE_TUBE:
            wingT.setT(wing);
            break;
        }
        pt.add2(pt1, wingT);
        mesh.addV(pt, true);
      }
      if (p > 0) {
        int nLast = (isFlatMesh ? nPer - 1 : nPer);
        for (int k = 0; k < nLast; k++) {
          // draw the triangles of opposing quads congruent, so they won't clip
          // esp. for high ribbonAspectRatio values
          int a = nPoints - nPer + k;
          int b = nPoints - nPer + ((k + 1) % nPer);
          int c = nPoints + ((k + 1) % nPer);
          int d = nPoints + k;
          if (k < nLast / 2) mesh.addQuad(a, b, c, d);
          else mesh.addQuad(b, c, d, a);
        }
      }
      nPoints += nPer;
    }
    if (!isFlatMesh) {
      int nPointsPreCap = nPoints;
      // copying vertices here so that the caps are not connected to the rest of
      // the mesh preventing light leaking around the sharp edges
      if (doCap0) {
        for (int l = 0; l < nPer; l++) mesh.addV(mesh.vs[l], true);
        nPoints += nPer;
        for (int k = hermiteLevel * 2; --k >= 0; )
          mesh.addQuad(
              nPoints - nPer + k + 2,
              nPoints - nPer + k + 1,
              nPoints - nPer + (nPer - k) % nPer,
              nPoints - k - 1);
      }
      if (doCap1) {
        for (int l = 0; l < nPer; l++) mesh.addV(mesh.vs[nPointsPreCap - nPer + l], true);
        nPoints += nPer;
        for (int k = hermiteLevel * 2; --k >= 0; )
          mesh.addQuad(
              nPoints - k - 1,
              nPoints - nPer + (nPer - k) % nPer,
              nPoints - nPer + k + 1,
              nPoints - nPer + k + 2);
      }
    }
    meshReady[i] = true;
    adjustCartoonSeamNormals(i, nPer);
    mesh.setVisibilityFlags(1);
    return true;
  }