Revision: 18330
          http://sourceforge.net/p/jmol/code/18330
Author:   hansonr
Date:     2013-06-14 12:44:40 +0000 (Fri, 14 Jun 2013)
Log Message:
-----------
___JmolVersion="13.1.17_dev_2013.06.14"

bug fix: COMPARE could rotate to less-good fit with SMARTS search
bug fix: draw ARROW ATOM/BOND broken

new feature: compare({atomset1} {atomset2} "ccCCN" "bonds")
new feature: {1.1}.find("ccCCN", "BONDS")

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/modelset/AtomCollection.java
    trunk/Jmol/src/org/jmol/modelset/ModelCollection.java
    trunk/Jmol/src/org/jmol/modelset/ModelSet.java
    trunk/Jmol/src/org/jmol/script/SV.java
    trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java
    trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java
    trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java
    trunk/Jmol/src/org/jmol/thread/SpinThread.java
    trunk/Jmol/src/org/jmol/util/Measure.java
    trunk/Jmol/src/org/jmol/viewer/ActionManager.java
    trunk/Jmol/src/org/jmol/viewer/Jmol.properties
    trunk/Jmol/src/org/jmol/viewer/TransformManager.java
    trunk/Jmol/src/org/jmol/viewer/Viewer.java

Modified: trunk/Jmol/src/org/jmol/modelset/AtomCollection.java
===================================================================
--- trunk/Jmol/src/org/jmol/modelset/AtomCollection.java        2013-06-14 
12:43:25 UTC (rev 18329)
+++ trunk/Jmol/src/org/jmol/modelset/AtomCollection.java        2013-06-14 
12:44:40 UTC (rev 18330)
@@ -2537,6 +2537,7 @@
     info.put("info", getAtomInfo(i, null));
     info.put("sym", getElementSymbol(i));
   }
-  
+
+
 }
 

Modified: trunk/Jmol/src/org/jmol/modelset/ModelCollection.java
===================================================================
--- trunk/Jmol/src/org/jmol/modelset/ModelCollection.java       2013-06-14 
12:43:25 UTC (rev 18329)
+++ trunk/Jmol/src/org/jmol/modelset/ModelCollection.java       2013-06-14 
12:44:40 UTC (rev 18330)
@@ -3381,4 +3381,30 @@
     return info;
   }
 
+  public int[][] getDihedralMap(int[] alist) {
+    JmolList<int[]> list = new JmolList<int[]>();
+    int n = alist.length;
+    Atom ai = null, aj = null, ak = null, al = null;
+    for (int i = n - 1; --i >= 0;)
+      for (int j = n; --j > i;) {
+        ai = atoms[alist[i]];
+        aj = atoms[alist[j]];
+        if (ai.isBonded(aj)) {
+          for (int k = n; --k >= 0;)
+            if (k != i && k != j && (ak = atoms[alist[k]]).isBonded(ai))
+              for (int l = n; --l >= 0;)
+                if (l != i && l != j && l != k
+                    && (al = atoms[alist[l]]).isBonded(aj))
+                  list.addLast(new int[] { ak.index, ai.index, aj.index,
+                      al.index });
+        }
+      }
+    n = list.size();
+    int[][] ilist = new int[n][];
+    for (int i = n; --i >= 0;)
+      ilist[n - i - 1] = list.get(i);
+    return ilist;
+  }
+
+
 }

Modified: trunk/Jmol/src/org/jmol/modelset/ModelSet.java
===================================================================
--- trunk/Jmol/src/org/jmol/modelset/ModelSet.java      2013-06-14 12:43:25 UTC 
(rev 18329)
+++ trunk/Jmol/src/org/jmol/modelset/ModelSet.java      2013-06-14 12:44:40 UTC 
(rev 18330)
@@ -25,6 +25,7 @@
 
 package org.jmol.modelset;
 
+import org.jmol.util.AxisAngle4f;
 import org.jmol.util.BS;
 import org.jmol.util.BSUtil;
 import org.jmol.util.JmolEdge;
@@ -40,6 +41,7 @@
 import org.jmol.util.V3;
 
 import org.jmol.viewer.JC;
+import org.jmol.viewer.TransformManager;
 import org.jmol.viewer.Viewer;
 import org.jmol.script.T;
 import org.jmol.api.Interface;
@@ -50,6 +52,7 @@
 import org.jmol.util.JmolList;
 
 
+import java.util.Hashtable;
 import java.util.Map;
 
 
@@ -831,6 +834,29 @@
   private final Matrix4f mat4t = new Matrix4f();
   private final V3 vTemp = new V3();
 
+  public void setDihedrals(float[] dihedralList, BS[] bsBranches, float f) {
+    int n = dihedralList.length / 6;
+    for (int j = 0, pt = 0; j < n; j++, pt += 6) {
+      BS bs = bsBranches[j];
+      if (bs == null || bs.isEmpty())
+        continue;
+      Atom a1 = atoms[(int) dihedralList[pt + 1]];
+      Atom a2 = atoms[(int) dihedralList[pt + 2]];
+      V3 v = V3.newV(a2);
+      v.sub(a1);
+      float angle = (dihedralList[pt + 5] - dihedralList[pt + 4]) * f;
+      AxisAngle4f aa = AxisAngle4f.newVA(v, (float)(-angle / 
TransformManager.degreesPerRadian));
+      matTemp.setAA(aa);
+      ptTemp.setT(a1);
+      for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
+        atoms[i].sub(ptTemp);
+        matTemp.transform(atoms[i]);
+        atoms[i].add(ptTemp);
+        taintAtom(i, TAINT_COORD);
+      }
+    }    
+  }
+
   public void moveAtoms(Matrix3f mNew, Matrix3f matrixRotate,
                         V3 translation, BS bs, P3 center,
                         boolean isInternal) {
@@ -882,7 +908,6 @@
     recalculatePositionDependentQuantities(bs, mat4);
   }
 
-  
   public void recalculatePositionDependentQuantities(BS bs, Matrix4f mat) {
     if (getHaveStraightness())
       calculateStraightness();
@@ -901,5 +926,38 @@
             */
   }
 
+  public BS[] getBsBranches(float[] dihedralList) {
+    int n = dihedralList.length / 6;
+    BS[] bsBranches = new BS[n];
+    Map<String, Boolean> map = new Hashtable<String, Boolean>();
+    for (int i = 0, pt = 0; i < n; i++, pt += 6) {
+      float dv = dihedralList[pt + 5] - dihedralList[pt + 4];
+      if (Math.abs(dv) < 1f)
+        continue;
+      int i0 = (int) dihedralList[pt + 1];
+      int i1 = (int) dihedralList[pt + 2];
+      String s = "" + i0 + "_" + i1;
+      if (map.containsKey(s))
+        continue;
+      map.put(s, Boolean.TRUE);
+      BS bs = viewer.getBranchBitSet(i1, i0, true);
+      Bond[] bonds = atoms[i0].bonds;
+      Atom a0 = atoms[i0];
+      for (int j = 0; j < bonds.length; j++) {
+        Bond b = bonds[j];
+        if (!b.isCovalent())
+          continue;
+        int i2 = b.getOtherAtom(a0).index;
+        if (i2 == i1)
+          continue;
+        if (bs.get(i2)) {
+          bs = null;
+          break;
+        }
+      }
+      bsBranches[i] = bs;
+    }
+    return bsBranches;
+  }
 }
 

Modified: trunk/Jmol/src/org/jmol/script/SV.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/SV.java      2013-06-14 12:43:25 UTC (rev 
18329)
+++ trunk/Jmol/src/org/jmol/script/SV.java      2013-06-14 12:44:40 UTC (rev 
18330)
@@ -329,7 +329,7 @@
   static SV getVariableAI(int[] ix) {
     JmolList<SV> objects = new  JmolList<SV>();
     for (int i = 0; i < ix.length; i++)
-      objects.addLast(newVariable(integer, Integer.valueOf(ix[i])));
+      objects.addLast(newScriptVariableInt(ix[i]));
     return newVariable(varray, objects);
   }
 
@@ -1254,6 +1254,28 @@
     return list;
   }
 
+  static JmolList<Object> listAny(SV x) {
+    JmolList<Object> list = new JmolList<Object>();
+    JmolList<SV> l = x.getList();
+    for (int i = 0; i < l.size(); i++) {
+      SV v = l.get(i);
+      JmolList<SV> l2 = v.getList();
+      if (l2 == null) {
+        list.addLast(v.value);        
+      } else {
+        JmolList<Object> o = new JmolList<Object>();
+        for (int j = 0; j < l2.size(); j++) {
+          v = l2.get(j);
+          System.out.println(v);
+          
+        }
+        list.addLast(o);
+      }
+      System.out.println(v);
+    }
+    return list;
+    
+  }
   static float[] flistValue(T x, int nMin) {
     if (x.tok != varray)
       return new float[] { fValue(x) };

Modified: trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2013-06-14 12:43:25 UTC 
(rev 18329)
+++ trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2013-06-14 12:44:40 UTC 
(rev 18330)
@@ -4591,6 +4591,7 @@
     float[] fparams = null;
     int n = 0;
     String s = null;
+    iToken = i;
     switch (tokAt(i)) {
     case T.string:
       s = SV.sValue(st[i]);
@@ -7358,7 +7359,7 @@
 
         Matrix4f m4 = new Matrix4f();
         float stddev = getSmilesCorrelation(bsFrom, bsTo, strSmiles, null,
-            null, m4, null, !isSmiles, false);
+            null, m4, null, !isSmiles, false, null);
         if (Float.isNaN(stddev))
           error(ERROR_invalidArgument);
         V3 translation = new V3();
@@ -7396,7 +7397,7 @@
       if (!useThreads())
         doAnimate = false;
       viewer.rotateAboutPointsInternal(this, centerAndPoints[0][0], pt1, 
endDegrees
-          / nSeconds, endDegrees, doAnimate, bsFrom, translation, ptsB);
+          / nSeconds, endDegrees, doAnimate, bsFrom, translation, ptsB, null);
       if (doAnimate && isJS)
         throw new ScriptInterruption(this, "compare", 1);
     }
@@ -7404,17 +7405,16 @@
 
   float getSmilesCorrelation(BS bsA, BS bsB, String smiles,
                              JmolList<P3> ptsA, JmolList<P3> ptsB,
-                             Matrix4f m, JmolList<BS> vReturn, 
-                             boolean isSmarts, boolean asMap)
+                             Matrix4f m4, JmolList<BS> vReturn, 
+                             boolean isSmarts, boolean asMap, int[][] mapSet)
       throws ScriptException {
-    float tolerance = 0.1f; // TODO
+    float tolerance = (mapSet == null ? 0.1f : Float.MAX_VALUE);
     try {
       if (ptsA == null) {
         ptsA = new  JmolList<P3>();
         ptsB = new  JmolList<P3>();
       }
-      if (m == null)
-        m = new Matrix4f();
+      Matrix4f m = new Matrix4f();
 
       Atom[] atoms = viewer.modelSet.atoms;
       int atomCount = viewer.getAtomCount();
@@ -7424,8 +7424,9 @@
         evalError(viewer.getSmilesMatcher().getLastException(), null);
       if (maps.length == 0)
         return Float.NaN;
-      for (int i = 0; i < maps[0].length; i++)
-        ptsA.addLast(atoms[maps[0][i]]);
+      int[] mapA = maps[0];
+      for (int i = 0; i < mapA.length; i++)
+        ptsA.addLast(atoms[mapA[i]]);
       maps = viewer.getSmilesMatcher().getCorrelationMaps(smiles, atoms,
           atomCount, bsB, isSmarts, false);
       if (maps == null)
@@ -7456,9 +7457,16 @@
         }
         if (stddev < lowestStdDev) {
           mapB = maps[i];
+          if (m4 != null)
+            m4.setM(m);
           lowestStdDev = stddev;
         }
       }
+      if (mapSet != null) {
+        mapSet[0] = mapA;
+        mapSet[1] = mapB;
+      }
+      ptsB.clear();
       for (int i = 0; i < mapB.length; i++)
         ptsB.addLast(atoms[mapB[i]]);
       return lowestStdDev;
@@ -7515,7 +7523,7 @@
 
       JmolList<BS> vReturn = new  JmolList<BS>();
       float stddev = getSmilesCorrelation(bsMatch3D, bsSelected, pattern, null,
-          null, null, vReturn, isSmarts, false);
+          null, null, vReturn, isSmarts, false, null);
       if (Float.isNaN(stddev)) {
         if (asOneBitset)
           return new BS();
@@ -10357,6 +10365,7 @@
     float endDegrees = Float.MAX_VALUE;
     boolean isMolecular = false;
     boolean haveRotation = false;
+    float[] dihedralList = null;
     JmolList<P3> ptsA = null;
     P3[] points = new P3[2];
     V3 rotAxis = V3.new3(0, 1, 0);
@@ -10393,8 +10402,7 @@
         // {X, Y, Z}
         // $drawObject[n]
         P3 pt1 = centerParameterForModel(i, viewer.getCurrentModelIndex());
-        if (!chk && tok == T.dollarsign
-            && tokAt(i + 2) != T.leftsquare) {
+        if (!chk && tok == T.dollarsign && tokAt(i + 2) != T.leftsquare) {
           // rotation about an axis such as $line1
           isMolecular = true;
           rotAxis = getDrawObjectAxis(objectNameParameter(++i), viewer
@@ -10419,6 +10427,7 @@
         if (isSpin) {
           // rotate spin ... [degreesPerSecond]
           // rotate spin ... [endDegrees] [degreesPerSecond]
+          // rotate spin BRANCH <DihedralList> [seconds]
           if (degreesPerSecond == Float.MIN_VALUE) {
             degreesPerSecond = floatParameter(i);
             continue;
@@ -10481,17 +10490,23 @@
         q = Quaternion.newVA(rotAxis, endDegrees);
         break;
       case T.branch:
-        haveRotation = true;
-        int iAtom1 = atomExpressionAt(++i).nextSetBit(0);
-        int iAtom2 = atomExpressionAt(++iToken).nextSetBit(0);
-        if (iAtom1 < 0 || iAtom2 < 0)
-          return;
-        bsAtoms = viewer.getBranchBitSet(iAtom2, iAtom1);
         isSelected = true;
         isMolecular = true;
-        points[0] = viewer.getAtomPoint3f(iAtom1);
-        points[1] = viewer.getAtomPoint3f(iAtom2);
-        nPoints = 2;
+        haveRotation = true;
+        if (isArrayParameter(++i)) {
+          dihedralList = floatParameterSet(i, 6, Integer.MAX_VALUE);
+          i = iToken;
+          isSpin = true;
+        } else {
+          int iAtom1 = atomExpressionAt(i).nextSetBit(0);
+          int iAtom2 = atomExpressionAt(++iToken).nextSetBit(0);
+          if (iAtom1 < 0 || iAtom2 < 0)
+            return;
+          bsAtoms = viewer.getBranchBitSet(iAtom2, iAtom1, true);
+          points[0] = viewer.getAtomPoint3f(iAtom1);
+          points[1] = viewer.getAtomPoint3f(iAtom2);
+          nPoints = 2;
+        }
         break;
 
       // 12.0 options
@@ -10527,8 +10542,7 @@
         if (endDegrees == 0 && points[0] != null) {
           // glide plane
           rotAxis.normalize();
-          Measure.getPlaneThroughPoint(points[0], rotAxis,
-              invPlane = new P4());
+          Measure.getPlaneThroughPoint(points[0], rotAxis, invPlane = new 
P4());
         }
         q = Quaternion.newVA(rotAxis, endDegrees);
         nPoints = (points[0] == null ? 0 : 1);
@@ -10552,8 +10566,8 @@
           m4 = new Matrix4f();
           points[0] = new P3();
           nPoints = 1;
-          float stddev = (chk ? 0 : Measure.getTransformMatrix4(ptsA,
-              ptsB, m4, points[0]));
+          float stddev = (chk ? 0 : Measure.getTransformMatrix4(ptsA, ptsB, m4,
+              points[0]));
           // if the standard deviation is very small, we leave ptsB
           // because it will be used to set the absolute final positions
           if (stddev > 0.001)
@@ -10589,11 +10603,11 @@
         bsAtoms = bsCompare;
     }
     float rate = (degreesPerSecond == Float.MIN_VALUE ? 10
-        : endDegrees == Float.MAX_VALUE ? degreesPerSecond 
-        : (degreesPerSecond < 0) == (endDegrees > 0) ?
-        // -n means number of seconds, not degreesPerSecond
-        -endDegrees / degreesPerSecond
-            : degreesPerSecond);
+        : endDegrees == Float.MAX_VALUE ? degreesPerSecond
+            : (degreesPerSecond < 0) == (endDegrees > 0) ?
+            // -n means number of seconds, not degreesPerSecond
+            -endDegrees / degreesPerSecond
+                : degreesPerSecond);
     if (q != null) {
       // only when there is a translation (4x4 matrix or TRANSLATE)
       // do we set the rotation to be the center of the selected atoms or model
@@ -10631,7 +10645,7 @@
       if (rotAxis == null)
         return;
     }
-    if (nPoints < 2) {
+    if (nPoints < 2 && dihedralList == null) {
       if (!isMolecular) {
         // fixed-frame rotation
         // rotate x 10 # Chime-like
@@ -10640,8 +10654,9 @@
         // rotate x 10 $object # point-centered
         if (isSpin && bsAtoms == null && !useThreads())
           return;
-        if (viewer.rotateAxisAngleAtCenter(this, points[0], rotAxis, rate, 
endDegrees,
-            isSpin, bsAtoms) && isJS && isSpin && bsAtoms == null)
+        if (viewer.rotateAxisAngleAtCenter(this, points[0], rotAxis, rate,
+            endDegrees, isSpin, bsAtoms)
+            && isJS && isSpin && bsAtoms == null)
           throw new ScriptInterruption(this, "rotate", 1);
         return;
       }
@@ -10685,8 +10700,9 @@
     } else {
       if (!useThreads())
         return;
-      if (viewer.rotateAboutPointsInternal(this, points[0], points[1], rate, 
endDegrees,
-          isSpin, bsAtoms, translation, ptsB) && isJS && isSpin)
+      if (viewer.rotateAboutPointsInternal(this, points[0], points[1], rate,
+          endDegrees, isSpin, bsAtoms, translation, ptsB, dihedralList)
+          && isJS && isSpin)
         throw new ScriptInterruption(this, "rotate", 1);
     }
   }

Modified: trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java     2013-06-14 
12:43:25 UTC (rev 18329)
+++ trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java     2013-06-14 
12:44:40 UTC (rev 18330)
@@ -77,7 +77,7 @@
    * 
    */
 
-  private boolean isSyntaxCheck;
+  private boolean chk;
   private boolean wasSyntaxCheck;
   private boolean logMessages;
   private ScriptEvaluator eval;
@@ -105,7 +105,7 @@
     this.eval = eval;
     this.viewer = eval.viewer;
     this.logMessages = eval.logMessages;
-    this.isSyntaxCheck = wasSyntaxCheck = eval.chk;
+    this.chk = wasSyntaxCheck = eval.chk;
     this.isArrayItem = isArrayItem;
     this.asVector = asVector || isArrayItem;
     this.asBitSet = asBitSet;
@@ -453,7 +453,7 @@
     case T.plusPlus:
       incrementX = (op.tok == T.plusPlus ? 1 : -1);
       if (ptid == ptx) {
-        if (isSyntaxCheck)
+        if (chk)
           return true;
         SV x = xStack[xPt];
         xStack[xPt] = SV.newVariable(T.string, "").setv(x, false);
@@ -625,7 +625,7 @@
         boolean tf = getX().asBoolean();
         addXVar(SV.getBoolean(tf));
         if (tf == (op.tok == T.opOr)) { // TRUE or.. FALSE and...
-          isSyntaxCheck = true;
+          chk = true;
           op = (op.tok == T.opOr ? T.tokenOrTRUE : T.tokenAndFALSE);
         }
       }
@@ -730,7 +730,7 @@
     // we cannot know what variables are real
     // if this is a property selector, as in x.func(), then we
     // just exit; otherwise we add a new TRUE to xStack
-    if (isSyntaxCheck)
+    if (chk)
       return (op.tok == T.propselector ? true : addXBool(true));
     switch (tok) {
     case T.abs:
@@ -842,6 +842,7 @@
     // compare({bitset},{bitset}[,"SMARTS"|"SMILES"],smilesString [,"stddev"])
     // returns matrix4f for rotation/translation or stddev
     // compare({bitset},{bitset},"ISOMER")  12.1.5
+    // compare({bitset},{bitset},"BONDS",smilesString) 13.1.17
 
     if (args.length < 2 || args.length > 5)
       return false;
@@ -849,7 +850,9 @@
     String sOpt = SV.sValue(args[args.length - 1]);
     boolean isStdDev = sOpt.equalsIgnoreCase("stddev");
     boolean isIsomer = sOpt.equalsIgnoreCase("ISOMER");
-    boolean isSmiles = (!isIsomer && args.length > (isStdDev ? 3 : 2));
+    boolean isBonds = sOpt.equalsIgnoreCase("BONDS");
+    boolean isSmiles = (isBonds || !isIsomer
+        && args.length > (isStdDev ? 3 : 2));
     BS bs1 = (args[0].tok == T.bitset ? (BS) args[0].value : null);
     BS bs2 = (args[1].tok == T.bitset ? (BS) args[1].value : null);
     String smiles1 = (bs1 == null ? SV.sValue(args[0]) : "");
@@ -861,51 +864,82 @@
       if (bs1 == null || bs2 == null)
         return false;
     }
+    if (isBonds) {
+      if (args.length != 4)
+        return false;
+      smiles1 = SV.sValue(args[2]);
+      int[][] mapSet = ArrayUtil.newInt2(2);
+      eval.getSmilesCorrelation(bs1, bs2, smiles1, null, null,
+          null, null, true, false, mapSet);
+      int[][] bondMap1 = viewer.getDihedralMap(mapSet[0]);
+      int[][] bondMap2 = (bondMap1 == null ? null : 
viewer.getDihedralMap(mapSet[1]));
+      if (bondMap2 == null || bondMap2.length != bondMap1.length)
+        return addXStr("");
+      float[][] angles = new float[bondMap1.length][3];
+      Atom[] atoms = viewer.modelSet.atoms;
+      getTorsions(atoms, bondMap2, angles, 0);
+      getTorsions(atoms, bondMap1, angles, 1);
+      float[] data = new float[bondMap1.length * 6];
+      for (int i = 0, pt = 0; i < bondMap1.length; i++) {
+        int[] map = bondMap1[i];
+        data[pt++] = map[0];
+        data[pt++] = map[1];
+        data[pt++] = map[2];
+        data[pt++] = map[3];
+        data[pt++] = angles[i][0];
+        data[pt++] = angles[i][1];
+      }
+      return addXAF(data);
+    }
     if (isIsomer) {
       if (args.length != 3)
         return false;
-      if (bs1 == null && bs2 == null) 
-        return addXStr(viewer.getSmilesMatcher().getRelationship(smiles1, 
smiles2).toUpperCase());
+      if (bs1 == null && bs2 == null)
+        return addXStr(viewer.getSmilesMatcher().getRelationship(smiles1,
+            smiles2).toUpperCase());
       String mf1 = (bs1 == null ? viewer.getSmilesMatcher()
-          .getMolecularFormula(smiles1, false) : 
JmolMolecule.getMolecularFormula(
-          viewer.getModelSet().atoms, bs1, false));
+          .getMolecularFormula(smiles1, false) : JmolMolecule
+          .getMolecularFormula(viewer.getModelSet().atoms, bs1, false));
       String mf2 = (bs2 == null ? viewer.getSmilesMatcher()
-          .getMolecularFormula(smiles2, false) : 
JmolMolecule.getMolecularFormula(
-          viewer.getModelSet().atoms, bs2, false));
+          .getMolecularFormula(smiles2, false) : JmolMolecule
+          .getMolecularFormula(viewer.getModelSet().atoms, bs2, false));
       if (!mf1.equals(mf2))
         return addXStr("NONE");
       if (bs1 != null)
-        smiles1 = (String) eval.getSmilesMatches("", null, bs1, null, false, 
true);
+        smiles1 = (String) eval.getSmilesMatches("", null, bs1, null, false,
+            true);
       boolean check;
       if (bs2 == null) {
         // note: find smiles1 IN smiles2 here
         check = (viewer.getSmilesMatcher().areEqual(smiles2, smiles1) > 0);
       } else {
-        check = (((BS) eval.getSmilesMatches(smiles1, null, bs2, null,
-            false, true)).nextSetBit(0) >= 0);
+        check = (((BS) eval.getSmilesMatches(smiles1, null, bs2, null, false,
+            true)).nextSetBit(0) >= 0);
       }
       if (!check) {
         // MF matched, but didn't match SMILES
         String s = smiles1 + smiles2;
         if (s.indexOf("/") >= 0 || s.indexOf("\\") >= 0 || s.indexOf("@") >= 
0) {
-          if (smiles1.indexOf("@") >= 0 && (bs2 != null || 
smiles2.indexOf("@") >= 0)) {
+          if (smiles1.indexOf("@") >= 0
+              && (bs2 != null || smiles2.indexOf("@") >= 0)) {
             // reverse chirality centers
             smiles1 = viewer.getSmilesMatcher().reverseChirality(smiles1);
             if (bs2 == null) {
               check = (viewer.getSmilesMatcher().areEqual(smiles1, smiles2) > 
0);
             } else {
-              check = (((BS) eval.getSmilesMatches(smiles1, null, bs2,
-                  null, false, true)).nextSetBit(0) >= 0);
+              check = (((BS) eval.getSmilesMatches(smiles1, null, bs2, null,
+                  false, true)).nextSetBit(0) >= 0);
             }
             if (check)
               return addXStr("ENANTIOMERS");
           }
           // remove all stereochemistry from SMILES string
           if (bs2 == null) {
-            check = (viewer.getSmilesMatcher().areEqual("/nostereo/" + 
smiles2, smiles1) > 0);
+            check = (viewer.getSmilesMatcher().areEqual("/nostereo/" + smiles2,
+                smiles1) > 0);
           } else {
-            Object ret = eval.getSmilesMatches("/nostereo/" + smiles1, null, 
bs2, null,
-                false, true);
+            Object ret = eval.getSmilesMatches("/nostereo/" + smiles1, null,
+                bs2, null, false, true);
             check = (((BS) ret).nextSetBit(0) >= 0);
           }
           if (check)
@@ -918,12 +952,12 @@
       if (bs1 == null || bs2 == null)
         return addXStr("IDENTICAL");
       stddev = eval.getSmilesCorrelation(bs1, bs2, smiles1, null, null, null,
-          null, false, false);
+          null, false, false, null);
       return addXStr(stddev < 0.2f ? "IDENTICAL"
           : "IDENTICAL or CONFORMATIONAL ISOMERS (RMSD=" + stddev + ")");
     } else if (isSmiles) {
-      ptsA = new  JmolList<P3>();
-      ptsB = new  JmolList<P3>();
+      ptsA = new JmolList<P3>();
+      ptsB = new JmolList<P3>();
       sOpt = SV.sValue(args[2]);
       boolean isMap = sOpt.equalsIgnoreCase("MAP");
       isSmiles = (sOpt.equalsIgnoreCase("SMILES"));
@@ -933,18 +967,19 @@
       if (sOpt == null)
         return false;
       stddev = eval.getSmilesCorrelation(bs1, bs2, sOpt, ptsA, ptsB, m, null,
-          !isSmiles, isMap);
+          !isSmiles, isMap, null);
       if (isMap) {
         int nAtoms = ptsA.size();
         if (nAtoms == 0)
           return addXStr("");
         int nMatch = ptsB.size() / nAtoms;
-        JmolList<int[][]> ret = new  JmolList<int[][]>();
+        JmolList<int[][]> ret = new JmolList<int[][]>();
         for (int i = 0, pt = 0; i < nMatch; i++) {
           int[][] a = ArrayUtil.newInt2(nAtoms);
           ret.addLast(a);
           for (int j = 0; j < nAtoms; j++, pt++)
-            a[j] = new int[] { ((Atom)ptsA.get(j)).index, 
((Atom)ptsB.get(pt)).index};
+            a[j] = new int[] { ((Atom) ptsA.get(j)).index,
+                ((Atom) ptsB.get(pt)).index };
         }
         return addXList(ret);
       }
@@ -957,6 +992,22 @@
     return (isStdDev || Float.isNaN(stddev) ? addXFloat(stddev) : addXM4(m));
   }
 
+  private static void getTorsions(Atom[] atoms, int[][] bondMap,
+                                  float[][] diff, int pt) {
+    for (int i = bondMap.length; --i >= 0;) {
+      int[] map = bondMap[i];
+      float v = Measure.computeTorsion(atoms[map[0]], atoms[map[1]],
+          atoms[map[2]], atoms[map[3]], true);
+      if (pt == 1) {
+        if (v - diff[i][0] > 180)
+          v -= 360;
+        else if (v - diff[i][0] <= -180)
+          v += 360;
+      }
+      diff[i][pt] = v;
+    }
+  }
+
 //  private boolean evaluateVolume(ScriptVariable[] args) throws 
ScriptException {
 //    ScriptVariable x1 = getX();
 //    if (x1.tok != Token.bitset)
@@ -1209,7 +1260,7 @@
   public P3 ptValue(SV x, boolean allowFloat)
       throws ScriptException {
     Object pt;
-    if (isSyntaxCheck)
+    if (chk)
       return new P3();
     switch (x.tok) {
     case T.point3f:
@@ -1236,7 +1287,7 @@
   }
 
   private P4 planeValue(T x) {
-    if (isSyntaxCheck)
+    if (chk)
       return new P4();
     switch (x.tok) {
     case T.point4f:
@@ -1386,6 +1437,7 @@
     // "CCCC".find("SMARTS", "CC")
     // "CCCC".find("SMILES", "MF")
     // {2.1}.find("CCCC",{1.1}) // find pattern "CCCC" in {2.1} with 
conformation given by {1.1}
+    // {*}.find("ccCCN","BONDS")
 
     SV x1 = getX();
     String sFind = SV.sValue(args[0]);
@@ -1399,7 +1451,9 @@
       int iPt = (isSmiles || isSearch ? 2 : 1);
       BS bs2 = (iPt < args.length && args[iPt].tok == T.bitset ? (BS) 
args[iPt++].value
           : null);
-      boolean isAll = (args[args.length - 1].tok == T.on);
+      boolean asBonds = ("bonds".equalsIgnoreCase(SV
+          .sValue(args[args.length - 1])));
+      boolean isAll = (asBonds || args[args.length - 1].tok == T.on);
       Object ret = null;
       switch (x1.tok) {
       case T.string:
@@ -1407,12 +1461,12 @@
         if (bs2 != null)
           return false;
         if (flags.equalsIgnoreCase("mf")) {
-          ret = viewer.getSmilesMatcher()
-              .getMolecularFormula(smiles, isSearch);
+          ret = viewer.getSmilesMatcher().getMolecularFormula(smiles, 
isSearch);
           if (ret == null)
             eval.evalError(viewer.getSmilesMatcher().getLastException(), null);
         } else {
-          ret = eval.getSmilesMatches(flags, smiles, null, null, isSearch, 
!isAll);
+          ret = eval.getSmilesMatches(flags, smiles, null, null, isSearch,
+              !isAll);
         }
         break;
       case T.bitset:
@@ -1420,16 +1474,24 @@
           return addXStr(JmolMolecule.getMolecularFormula(
               viewer.getModelSet().atoms, (BS) x1.value, false));
         if (isSequence)
-          return addXStr(viewer.getSmiles(-1, -1, (BS) x1.value, true, isAll, 
isAll, false));
+          return addXStr(viewer.getSmiles(-1, -1, (BS) x1.value, true, isAll,
+              isAll, false));
         if (isSmiles || isSearch)
           sFind = flags;
         BS bsMatch3D = bs2;
-        ret = eval.getSmilesMatches(sFind, null, (BS) x1.value, bsMatch3D, 
!isSmiles,
-            !isAll);
+        if (asBonds) {
+          int[][] map = viewer.getSmilesMatcher().getCorrelationMaps(sFind,
+              viewer.modelSet.atoms, viewer.getAtomCount(), (BS) x1.value,
+              !isSmiles, true);
+          ret = (map.length > 0 ? viewer.getDihedralMap(map[0]) : new int[0]);
+        } else {
+          ret = eval.getSmilesMatches(sFind, null, (BS) x1.value, bsMatch3D,
+              !isSmiles, !isAll);
+        }
         break;
       }
       if (ret == null)
-        eval.error(ScriptEvaluator.ERROR_invalidArgument); 
+        eval.error(ScriptEvaluator.ERROR_invalidArgument);
       return addXObj(ret);
     }
     boolean isReverse = (flags.indexOf("v") >= 0);
@@ -1452,7 +1514,7 @@
       int ipt = 0;
       int n = 0;
       Matcher matcher = null;
-      JmolList<String> v = (asMatch ? new  JmolList<String>() : null);
+      JmolList<String> v = (asMatch ? new JmolList<String>() : null);
       for (int i = 0; i < list.length; i++) {
         String what = list[i];
         matcher = pattern.matcher(what);
@@ -1468,8 +1530,8 @@
       }
       if (!isList) {
         return (asMatch ? addXStr(v.size() == 1 ? (String) v.get(0) : "")
-            : isReverse ? addXBool(n == 1) : asMatch ? addXStr(n == 0 ? "" : 
matcher
-                .group()) : addXInt(n == 0 ? 0 : matcher.start() + 1));
+            : isReverse ? addXBool(n == 1) : asMatch ? addXStr(n == 0 ? ""
+                : matcher.group()) : addXInt(n == 0 ? 0 : matcher.start() + 
1));
       }
       if (n == 1)
         return addXStr(asMatch ? (String) v.get(0) : list[ipt]);
@@ -2341,7 +2403,7 @@
         return false;
       return addXBs(viewer.getBranchBitSet(
           ((BS) args[2].value).nextSetBit(0), ((BS) args[1].value)
-              .nextSetBit(0)));
+              .nextSetBit(0), true));
     case T.smiles:
     case T.substructure:  // same as "SMILES"
     case T.search:
@@ -2506,7 +2568,7 @@
     if (i == args.length || !(args[i].value instanceof BS))
       return false;
     BS bsA = BSUtil.copy(SV.bsSelectVar(args[i++]));
-    if (isSyntaxCheck)
+    if (chk)
       return addXBs(new BS());
     BS bsB = (i < args.length ? BSUtil.copy(SV
         .bsSelectVar(args[i])) : null);
@@ -2719,14 +2781,14 @@
       x2 = SV.selectItemVar(x2);
 
     if (op.tok == T.minusMinus || op.tok == T.plusPlus) {
-      if (!isSyntaxCheck && !x2.increment(incrementX))
+      if (!chk && !x2.increment(incrementX))
         return false;
       wasX = true;
       putX(x2); // reverse getX()
       return true;
     }
     if (op.tok == T.opNot) {
-      if (isSyntaxCheck)
+      if (chk)
         return addXBool(true);
       switch (x2.tok) {
       case T.point4f: // quaternion
@@ -2802,9 +2864,9 @@
         }
         break;
       case T.boundbox:
-        return (isSyntaxCheck ? addXStr("x") : getBoundBox(x2));
+        return (chk ? addXStr("x") : getBoundBox(x2));
       }
-      if (isSyntaxCheck)
+      if (chk)
         return addXStr(SV.sValue(x2));
       if (x2.tok == T.string) {
         Object v = SV
@@ -2820,9 +2882,9 @@
 
     // binary:
     SV x1 = getX();
-    if (isSyntaxCheck) {
+    if (chk) {
       if (op == T.tokenAndFALSE || op == T.tokenOrTRUE)
-        isSyntaxCheck = false;
+        chk = false;
       return addXVar(SV.newScriptVariableToken(x1));
     }
     switch (op.tok) {
@@ -3362,7 +3424,7 @@
       throws ScriptException {
     if (x2.tok != T.bitset)
       return false;
-    if (isSyntaxCheck)
+    if (chk)
       return addXStr("");
     BS bs = SV.bsSelectVar(x2);
     JmolList<T> tokens;
@@ -3397,7 +3459,7 @@
   private boolean getBoundBox(SV x2) {
     if (x2.tok != T.bitset)
       return false;
-    if (isSyntaxCheck)
+    if (chk)
       return addXStr("");
     BoxInfo b = viewer.getBoxInfo(SV.bsSelectVar(x2), 1);
     P3[] pts = b.getBoundBoxPoints(true);

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java   2013-06-14 12:43:25 UTC 
(rev 18329)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java   2013-06-14 12:44:40 UTC 
(rev 18330)
@@ -365,8 +365,7 @@
   @SuppressWarnings({ "unchecked" })
   private Object match(String pattern, JmolNode[] atoms, int atomCount,
                        BS bsSelected, BS bsAromatic, boolean isSmarts,
-                       boolean matchAllAtoms, boolean firstMatchOnly,
-                       int mode) {
+                       boolean matchAllAtoms, boolean firstMatchOnly, int 
mode) {
     InvalidSmilesException.setLastError(null);
     try {
       SmilesSearch search = SmilesParser.getMolecule(pattern, isSmarts);

Modified: trunk/Jmol/src/org/jmol/thread/SpinThread.java
===================================================================
--- trunk/Jmol/src/org/jmol/thread/SpinThread.java      2013-06-14 12:43:25 UTC 
(rev 18329)
+++ trunk/Jmol/src/org/jmol/thread/SpinThread.java      2013-06-14 12:44:40 UTC 
(rev 18330)
@@ -42,6 +42,7 @@
   private final TransformManager transformManager;
   private float endDegrees;
   private JmolList<P3> endPositions;
+  private float[] dihedralList;
   private float nDegrees;
   private BS bsAtoms;
   private boolean isNav;
@@ -51,16 +52,24 @@
   private boolean haveNotified;
   private int index;
   //private boolean navigatingSurface;
+  private BS[] bsBranches;
   
+  private int nmove = 0;
+  
   public boolean isGesture() {
     return isGesture;
   }
   
-  public SpinThread(TransformManager transformManager, Viewer viewer, float 
endDegrees, JmolList<P3> endPositions, BS bsAtoms, boolean isNav, boolean 
isGesture) {
+  public SpinThread(TransformManager transformManager, Viewer viewer,
+      float endDegrees, JmolList<P3> endPositions, float[] dihedralList, BS 
bsAtoms, boolean isNav,
+      boolean isGesture) {
     super();
     setViewer(viewer, "SpinThread");
     this.transformManager = transformManager;
-    this.endDegrees = Math.abs(endDegrees);
+    this.endDegrees = endDegrees;
+    this.dihedralList = dihedralList;
+    if (dihedralList != null) 
+      bsBranches = viewer.getBsBranches(dihedralList);
     this.endPositions = endPositions;
     this.bsAtoms = bsAtoms;
     this.isNav = isNav;
@@ -163,7 +172,9 @@
         mode = MAIN;
         break;
       case FINISH:
-        if (bsAtoms != null && endPositions != null) {
+        if (dihedralList != null) {
+          viewer.setDihedrals(dihedralList, bsBranches, 0F);
+        } else if (bsAtoms != null && endPositions != null) {
           // when the standard deviations of the end points was
           // exact, we know that we want EXACTLY those final positions
           viewer.setAtomCoords(bsAtoms, T.xyz, endPositions);
@@ -180,7 +191,11 @@
   }
 
   private void doTransform() {
-    if (isNav) {
+    if (dihedralList != null) {
+      float f = 1f / myFps / endDegrees;
+      viewer.setDihedrals(dihedralList, bsBranches, f);
+      nDegrees += 1f / myFps;
+    } else if (isNav) {
       transformManager.setNavigationOffsetRelative();//navigatingSurface);
     } else if (transformManager.isSpinInternal
         || transformManager.isSpinFixed) {

Modified: trunk/Jmol/src/org/jmol/util/Measure.java
===================================================================
--- trunk/Jmol/src/org/jmol/util/Measure.java   2013-06-14 12:43:25 UTC (rev 
18329)
+++ trunk/Jmol/src/org/jmol/util/Measure.java   2013-06-14 12:44:40 UTC (rev 
18330)
@@ -458,7 +458,7 @@
     P3[] cptsB = getCenterAndPoints(ptsB);
     float[] retStddev = new float[2];
     Quaternion q = calculateQuaternionRotation(new P3[][] { cptsA,
-        cptsB }, retStddev, false);
+        cptsB }, retStddev, true); // was false
     V3 v = V3.newV(cptsB[0]);
     v.sub(cptsA[0]);
     m.setMV(q.getMatrix(), v);

Modified: trunk/Jmol/src/org/jmol/viewer/ActionManager.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/ActionManager.java   2013-06-14 12:43:25 UTC 
(rev 18329)
+++ trunk/Jmol/src/org/jmol/viewer/ActionManager.java   2013-06-14 12:44:40 UTC 
(rev 18330)
@@ -1870,7 +1870,7 @@
           int[] points = new int[nb];
           int ni = 0;
           for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1), 
ni++) {
-            lengths[ni] = viewer.getBranchBitSet(i, atomIndex).cardinality();
+            lengths[ni] = viewer.getBranchBitSet(i, atomIndex, 
true).cardinality();
             points[ni] = i;
           }
           for (int j = 0; j < nb - 2; j++) {

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2013-06-14 12:43:25 UTC 
(rev 18329)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2013-06-14 12:44:40 UTC 
(rev 18330)
@@ -9,8 +9,14 @@
 #  The quotes above look odd for a parameter file, but they are 
 #  important for the JavaScript version of Jmol.
 
-___JmolVersion="13.1.17_dev_2013.06.13"
+___JmolVersion="13.1.17_dev_2013.06.14"
 
+bug fix: COMPARE could rotate to less-good fit with SMARTS search
+bug fix: draw ARROW ATOM/BOND broken
+
+new feature: compare({atomset1} {atomset2} "ccCCN" "bonds")
+new feature: {1.1}.find("ccCCN", "BONDS")
+
 bug fix: animation MORPH broken for non-PyMOL files
  -- load trajectory ({0 6}) 1cdr.pdb
  -- animation MORPH 10

Modified: trunk/Jmol/src/org/jmol/viewer/TransformManager.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/TransformManager.java        2013-06-14 
12:43:25 UTC (rev 18329)
+++ trunk/Jmol/src/org/jmol/viewer/TransformManager.java        2013-06-14 
12:44:40 UTC (rev 18330)
@@ -223,7 +223,7 @@
     unTransformPoint(pt2, pt2);
     viewer.setInMotion(false);
     rotateAboutPointsInternal(null, pt2, pt1, 10 * speed, Float.NaN, false,
-        true, null, true, null, null);
+        true, null, true, null, null, null);
   }
 
   final V3 arcBall0 = new V3();
@@ -361,7 +361,7 @@
       isSpinInternal = false;
       isSpinFixed = true;
       isSpinSelected = (bsAtoms != null);
-      setSpin(eval, true, endDegrees, null, bsAtoms, false);
+      setSpin(eval, true, endDegrees, null, null, bsAtoms, false);
       return false;
     }
     float radians = endDegrees * JC.radiansPerDegree;
@@ -388,7 +388,7 @@
                                     float endDegrees, boolean isClockwise,
                                     boolean isSpin, BS bsAtoms,
                                     boolean isGesture, V3 translation,
-                                    JmolList<P3> finalPoints) {
+                                    JmolList<P3> finalPoints, float[] 
dihedralList) {
 
     // *THE* Viewer INTERNAL frame rotation entry point
 
@@ -401,7 +401,7 @@
       isSpin = false;
     }
 
-    if ((translation == null || translation.length() < 0.001)
+    if (dihedralList == null && (translation == null || translation.length() < 
0.001)
         && (!isSpin || endDegrees == 0 || Float.isNaN(degreesPerSecond) || 
degreesPerSecond == 0)
         && (isSpin || endDegrees == 0))
       return false;
@@ -420,6 +420,7 @@
     boolean isSelected = (bsAtoms != null);
     if (isSpin) {
       // we need to adjust the degreesPerSecond to match a multiple of the 
frame rate
+      if (dihedralList == null) {
       int nFrames = (int) (Math.abs(endDegrees) / Math.abs(degreesPerSecond)
           * spinFps + 0.5);
       if (Float.isNaN(endDegrees)) {
@@ -433,7 +434,10 @@
       isSpinInternal = true;
       isSpinFixed = false;
       isSpinSelected = isSelected;
-      setSpin(eval, true, endDegrees, finalPoints, bsAtoms, isGesture);
+      } else {
+        endDegrees = degreesPerSecond;
+      }
+      setSpin(eval, true, endDegrees, finalPoints, dihedralList, bsAtoms, 
isGesture);
       return false;
     }
     float radians = endDegrees * JC.radiansPerDegree;
@@ -1964,15 +1968,16 @@
   private SpinThread spinThread;
 
   public void setSpinOn() {
-    setSpin(null, true, Float.MAX_VALUE, null, null, false);
+    setSpin(null, true, Float.MAX_VALUE, null, null, null, false);
   }
 
   public void setSpinOff() {
-    setSpin(null, false, Float.MAX_VALUE, null, null, false);
+    setSpin(null, false, Float.MAX_VALUE, null, null, null, false);
   }
 
   private void setSpin(JmolScriptEvaluator eval, boolean spinOn,
-                       float endDegrees, JmolList<P3> endPositions, BS bsAtoms,
+                       float endDegrees, JmolList<P3> endPositions, float[] 
dihedralList, 
+                       BS bsAtoms,
                        boolean isGesture) {
     if (navOn && spinOn)
       setNavOn(false);
@@ -1980,7 +1985,7 @@
     viewer.getGlobalSettings().setB("_spinning", spinOn);
     if (spinOn) {
       if (spinThread == null) {
-        spinThread = new SpinThread(this, viewer, endDegrees, endPositions,
+        spinThread = new SpinThread(this, viewer, endDegrees, endPositions, 
dihedralList,
             bsAtoms, false, isGesture);
         spinThread.setEval(eval);
         if (bsAtoms == null) {
@@ -2000,7 +2005,7 @@
       return;
     boolean wasOn = this.navOn;
     if (navOn && spinOn)
-      setSpin(null, false, 0, null, null, false);
+      setSpin(null, false, 0, null, null, null, false);
     this.navOn = navOn;
     viewer.getGlobalSettings().setB("_navigating", navOn);
     if (!navOn)
@@ -2011,7 +2016,7 @@
       if (navFps == 0)
         navFps = 10;
       if (spinThread == null) {
-        spinThread = new SpinThread(this, viewer, 0, null, null, true, false);
+        spinThread = new SpinThread(this, viewer, 0, null, null, null, true, 
false);
         spinThread.start();
       }
     } else if (wasOn) {

Modified: trunk/Jmol/src/org/jmol/viewer/Viewer.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Viewer.java  2013-06-14 12:43:25 UTC (rev 
18329)
+++ trunk/Jmol/src/org/jmol/viewer/Viewer.java  2013-06-14 12:44:40 UTC (rev 
18330)
@@ -3343,12 +3343,12 @@
     return modelSet.getAtomsConnected(min, max, intType, bs);
   }
 
-  public BS getBranchBitSet(int atomIndex, int atomIndexNot) {
+  public BS getBranchBitSet(int atomIndex, int atomIndexNot, boolean 
allowCyclic) {
     if (atomIndex < 0 || atomIndex >= getAtomCount())
       return new BS();
     return JmolMolecule.getBranchBitSet(modelSet.atoms, atomIndex,
         getModelUndeletedAtomsBitSet(modelSet.atoms[atomIndex].modelIndex),
-        null, atomIndexNot, true, true);
+        null, atomIndexNot, allowCyclic, true);
   }
 
   public int getAtomIndexFromAtomNumber(int atomNumber) {
@@ -7938,11 +7938,11 @@
                                            P3 point2, float degreesPerSecond,
                                            float endDegrees, boolean isSpin,
                                            BS bsSelected, V3 translation,
-                                           JmolList<P3> finalPoints) {
+                                           JmolList<P3> finalPoints, float[] 
dihedralList) {
     // Eval: rotate INTERNAL
     boolean isOK = transformManager.rotateAboutPointsInternal(eval, point1,
         point2, degreesPerSecond, endDegrees, false, isSpin, bsSelected, false,
-        translation, finalPoints);
+        translation, finalPoints, dihedralList);
     if (isOK)
       refresh(-1, "rotateAxisAboutPointsInternal");
     return isOK;
@@ -7958,7 +7958,7 @@
     }
     transformManager.rotateAboutPointsInternal(null, pt1, pt2,
         global.pickingSpinRate, Float.MAX_VALUE, isClockwise, true, null,
-        false, null, null);
+        false, null, null, null);
   }
 
   public V3 getModelDipole() {
@@ -8154,7 +8154,7 @@
     statusManager.setStatusAtomMoved(bs);
   }
 
-  void moveAtoms(Matrix3f mNew, Matrix3f matrixRotate, V3 translation,
+  public void moveAtoms(Matrix3f mNew, Matrix3f matrixRotate, V3 translation,
                  P3 center, boolean isInternal, BS bsAtoms) {
     // from TransformManager exclusively
     if (bsAtoms.cardinality() == 0)
@@ -8294,7 +8294,7 @@
       }
       if (Measure.computeAngleABC(pt, atom1, atom2, true) > 90
           || Measure.computeAngleABC(pt, atom2, atom1, true) > 90) {
-        bsBranch = getBranchBitSet(atom2.index, atom1.index);
+        bsBranch = getBranchBitSet(atom2.index, atom1.index, true);
       }
       if (bsBranch != null)
         for (int n = 0, i = atom1.getBonds().length; --i >= 0;) {
@@ -8323,7 +8323,7 @@
     bs.andNot(selectionManager.getMotionFixedAtoms());
 
     rotateAboutPointsInternal(eval, atom1, atom2, 0, degrees, false, bs, null,
-        null);
+        null, null);
   }
 
   public void refreshMeasures(boolean andStopMinimization) {
@@ -10036,4 +10036,16 @@
     modelSet.setBondParametersBS(modelIndex, i, bsBonds, rad, pymolValence, 
argb, trans);
   }
 
+  public int[][] getDihedralMap(int[] atoms) {
+    return modelSet.getDihedralMap(atoms);
+  }
+
+  public void setDihedrals(float[] dihedralList, BS[] bsBranches, float rate) {
+    modelSet.setDihedrals(dihedralList, bsBranches, rate);
+  }
+
+  public BS[] getBsBranches(float[] dihedralList) {
+    return modelSet.getBsBranches(dihedralList);
+  }
+
 }

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
Jmol-commits mailing list
Jmol-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jmol-commits

Reply via email to