Revision: 20771
          http://sourceforge.net/p/jmol/code/20771
Author:   hansonr
Date:     2015-09-14 04:27:09 +0000 (Mon, 14 Sep 2015)
Log Message:
-----------
polyhedra update

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/renderspecial/PolyhedraRenderer.java
    trunk/Jmol/src/org/jmol/script/ScriptTokenParser.java
    trunk/Jmol/src/org/jmol/scriptext/CmdExt.java
    trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java
    trunk/Jmol/src/org/jmol/shapespecial/Polyhedron.java
    trunk/Jmol/src/org/jmol/smiles/SmilesGenerator.java
    trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java
    trunk/Jmol/src/org/jmol/smiles/SmilesParser.java
    trunk/Jmol/src/org/jmol/symmetry/UnitCellIterator.java
    trunk/Jmol/src/org/jmol/viewer/GlobalSettings.java
    trunk/Jmol/src/org/jmol/viewer/JC.java

Modified: trunk/Jmol/src/org/jmol/renderspecial/PolyhedraRenderer.java
===================================================================
--- trunk/Jmol/src/org/jmol/renderspecial/PolyhedraRenderer.java        
2015-09-10 12:34:16 UTC (rev 20770)
+++ trunk/Jmol/src/org/jmol/renderspecial/PolyhedraRenderer.java        
2015-09-14 04:27:09 UTC (rev 20771)
@@ -84,7 +84,7 @@
         screens3f[i] = new P3();
     }
     P3[] sc = this.screens3f;
-    int[][] planes = p.faces;
+    int[][] planes = p.triangles;
     for (int i = vertices.length; --i >= 0;) {
       Atom atom = (vertices[i] instanceof Atom ? (Atom) vertices[i] : null);
       if (atom == null) {

Modified: trunk/Jmol/src/org/jmol/script/ScriptTokenParser.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/ScriptTokenParser.java       2015-09-10 
12:34:16 UTC (rev 20770)
+++ trunk/Jmol/src/org/jmol/script/ScriptTokenParser.java       2015-09-14 
04:27:09 UTC (rev 20771)
@@ -628,8 +628,9 @@
     } else if (isImplicitExpression) {
       addTokenToPostfixToken(T.tokenExpressionEnd);
       tokenNext();
-    } else if (isEmbeddedExpression && !isHash) {
-      tokenNext();
+    } else if (isEmbeddedExpression) {
+      if (!isHash)
+        tokenNext();
     } else {
       addNextToken();
     }

Modified: trunk/Jmol/src/org/jmol/scriptext/CmdExt.java
===================================================================
--- trunk/Jmol/src/org/jmol/scriptext/CmdExt.java       2015-09-10 12:34:16 UTC 
(rev 20770)
+++ trunk/Jmol/src/org/jmol/scriptext/CmdExt.java       2015-09-14 04:27:09 UTC 
(rev 20771)
@@ -4079,6 +4079,13 @@
       if (!chk)
         msg = vwr.fm.getPathForAllFiles();
       break;
+    case T.polyhedra:
+      if (!chk) {
+        Object[] info = new Object[2];
+        vwr.shm.getShapePropertyData(JC.SHAPE_POLYHEDRA, "allInfo", info);
+        msg = SV.getVariable(info[1]).asString();
+      }
+      break;
     case T.nmr:
       if (eval.optParameterAsString(2).equalsIgnoreCase("1H")) {
         len = 3;

Modified: trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java
===================================================================
--- trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java 2015-09-10 12:34:16 UTC 
(rev 20770)
+++ trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java 2015-09-14 04:27:09 UTC 
(rev 20771)
@@ -55,7 +55,7 @@
 
 public class Polyhedra extends AtomShape {
 
-  private final static float DEFAULT_DISTANCE_FACTOR = 1.85f;
+//  private final static float DEFAULT_DISTANCE_FACTOR = 1.85f;
   private final static float DEFAULT_FACECENTEROFFSET = 0.25f;
   private final static int EDGES_NONE = 0;
   public final static int EDGES_ALL = 1;
@@ -69,7 +69,7 @@
 
   private static final int MODE_BONDING = 1;
   private static final int MODE_POINTS = 2;
-  private static final int MODE_ITERATE = 3;
+  private static final int MODE_RADIUS = 3;
   private static final int MODE_BITSET = 4;
   private static final int MODE_UNITCELL = 5;
   private static final int MODE_INFO = 6;
@@ -77,6 +77,7 @@
    * a dot product comparison term
    */
   private static final float DEFAULT_PLANAR_PARAM = 0.98f;
+  private static final float CONVEX_HULL_MAX = 0.02f;
 
   public int polyhedronCount;
   public Polyhedron[] polyhedrons = new Polyhedron[32];
@@ -354,7 +355,7 @@
         nv = Integer.MIN_VALUE;
       for (int i = polyhedronCount; --i >= 0;) {
         if (nv > 0 && polyhedrons[i].nVertices != nv || nv > Integer.MIN_VALUE
-            && nv < 0 && polyhedrons[i].faces.length != -nv)
+            && nv < 0 && polyhedrons[i].triangles.length != -nv)
           continue;
         if (smiles == null) {
           bs.set(polyhedrons[i].centralAtom.i);
@@ -372,6 +373,13 @@
       data[2] = bs;
       return true;
     }
+    if (property == "allInfo") {
+      Lst<Map<String, Object>> info = new Lst<Map<String, Object>>();
+      for (int i = polyhedronCount; --i >= 0;)
+          info.addLast(polyhedrons[i].getInfo(vwr, true));
+      data[1] = info;
+      return false;
+    }
     if (property == "info") {
       iatom = ((Integer) data[0]).intValue();
       for (int i = polyhedronCount; --i >= 0;) {
@@ -443,15 +451,14 @@
     boolean useBondAlgorithm = radius == 0 || bondedOnly;
     buildMode = (info != null ? MODE_INFO : nPoints > 0 ? MODE_POINTS
         : haveBitSetVertices ? MODE_BITSET : useUnitCell ? MODE_UNITCELL
-            : useBondAlgorithm ? MODE_BONDING : MODE_ITERATE);
-    AtomIndexIterator iter = (buildMode == MODE_ITERATE ? ms
+            : useBondAlgorithm ? MODE_BONDING : MODE_RADIUS);
+    AtomIndexIterator iter = (buildMode == MODE_RADIUS ? ms
         .getSelectedAtomIterator(null, false, false, false, false) : null);
     for (int i = centers.nextSetBit(0); i >= 0; i = centers.nextSetBit(i + 1)) 
{
       Atom atom = atoms[i];
       Polyhedron p = null;
       switch (buildMode) {
       case MODE_BITSET:
-        bsVertices.clear(i);
         p = constructBitSetPolyhedron(atom);
         break;
       case MODE_UNITCELL:
@@ -460,16 +467,16 @@
       case MODE_BONDING:
         p = constructBondsPolyhedron(atom, 0);
         break;
-      case MODE_POINTS:
-        p = constructPointPolyhedron(atom);
-        break;
-      case MODE_ITERATE:
+      case MODE_RADIUS:
         vwr.setIteratorForAtom(iter, i, radius);
         p = constructRadiusPolyhedron(atom, iter);
         break;
       case MODE_INFO:
         p = new Polyhedron().setInfo(info, vwr.ms.at);
         break;
+      case MODE_POINTS:
+        p = validatePolyhedron(atom, nPoints);
+        break;
       }
       if (p != null) {
         if (polyhedronCount == polyhedrons.length)
@@ -483,8 +490,29 @@
       iter.release();
   }
 
-  private Polyhedron constructPointPolyhedron(Atom atom) {
-    return validatePolyhedron(atom, nPoints, otherAtoms);
+  private Polyhedron constructBondsPolyhedron(Atom atom, int otherAtomCount) {
+    if (otherAtomCount == 0) {
+      Bond[] bonds = atom.bonds;
+      if (bonds == null)
+        return null;
+      float r2 = radius * radius;
+      for (int i = bonds.length; --i >= 0;) {
+        Bond bond = bonds[i];
+        if (!bond.isCovalent())
+          continue;
+        Atom other = bond.getOtherAtom(atom);
+        if (bsVertices != null && !bsVertices.get(other.i) || radius > 0
+            && other.distanceSquared(atom) > r2)
+          continue;
+        otherAtoms[otherAtomCount++] = other;
+        if (otherAtomCount >= MAX_VERTICES)
+          break;
+      }
+    }
+    distanceRef = 0;
+    return (otherAtomCount < 3 || otherAtomCount >= MAX_VERTICES || nVertices 
> 0
+        && !bsVertexCount.get(otherAtomCount) ? null : validatePolyhedron(atom,
+        otherAtomCount));
   }
 
   private Polyhedron constructUnitCellPolygon(Atom atom,
@@ -507,8 +535,8 @@
     float bondTolerance = vwr.getFloat(T.bondtolerance);
     float minBondDistance = vwr.getFloat(T.minbonddistance);
     float minBondDistance2 = minBondDistance * minBondDistance;
-    int bondCount = 0;
-    while (iter.hasNext()) {
+    int otherAtomCount = 0;
+    outer: while (iter.hasNext()) {
       Atom other = atoms[iter.next()];
       float otherRadius = other.getBondingRadius();
       P3 pt = iter.getPosition();
@@ -516,129 +544,70 @@
       if (!vwr.ms.isBondable(myBondingRadius, otherRadius, distance2,
           minBondDistance2, bondTolerance))
         continue;
-      otherAtoms[bondCount++] = pt;
-      if (bondCount >= MAX_VERTICES)
+      for (int i = 0; i < otherAtomCount; i++)
+        if (otherAtoms[i].distanceSquared(pt) < 0.01f)
+          continue outer;
+      otherAtoms[otherAtomCount++] = pt;
+      if (otherAtomCount >= MAX_VERTICES)
         break;
     }
-    return constructBondsPolyhedron(atom, bondCount);
+    return constructBondsPolyhedron(atom, otherAtomCount);
   }
 
-  private Polyhedron constructBondsPolyhedron(Atom atom, int bondCount) {
-    if (bondCount == 0) {
-      Bond[] bonds = atom.bonds;
-      if (bonds == null)
-        return null;
-      for (int i = bonds.length; --i >= 0;) {
-        Bond bond = bonds[i];
-        if (!bond.isCovalent())
-          continue;
-        Atom other = bond.getOtherAtom(atom);
-        if (bsVertices != null && !bsVertices.get(other.i) || radius > 0
-            && other.distance(atom) > radius)
-          continue;
-        otherAtoms[bondCount++] = other;
-        if (bondCount >= MAX_VERTICES)
-          break;
-      }
-    }
-    distanceRef = 0;
-    return (bondCount < 3 || bondCount >= MAX_VERTICES || nVertices > 0
-        && !bsVertexCount.get(bondCount) ? null : validatePolyhedron(atom,
-        bondCount, otherAtoms));
-  }
-
   private Polyhedron constructBitSetPolyhedron(Atom atom) {
+    bsVertices.clear(atom.i);
     int otherAtomCount = 0;
     distanceRef = 0;
     for (int i = bsVertices.nextSetBit(0); i >= 0; i = bsVertices
         .nextSetBit(i + 1))
       otherAtoms[otherAtomCount++] = atoms[i];
-    return validatePolyhedron(atom, otherAtomCount, otherAtoms);
+    return validatePolyhedron(atom, otherAtomCount);
   }
 
   private Polyhedron constructRadiusPolyhedron(Atom atom, AtomIndexIterator 
iter) {
     int otherAtomCount = 0;
     distanceRef = radius;
-    while (iter.hasNext()) {
+    float r2 = radius * radius;
+    outer: while (iter.hasNext()) {
       Atom other = atoms[iter.next()];
       P3 pt = iter.getPosition();
       if (pt == null) {
         // this will happen with standard radius atom iterator
         pt = other;
         if (bsVertices != null && !bsVertices.get(other.i)
-            || atom.distance(pt) > radius)
+            || atom.distanceSquared(pt) > r2)
           continue;
       }
       if (other.altloc != atom.altloc && other.altloc != 0 && atom.altloc != 0)
         continue;
       if (otherAtomCount == MAX_VERTICES)
         break;
+      for (int i = 0; i < otherAtomCount; i++)
+        if (otherAtoms[i].distanceSquared(pt) < 0.01f)
+          continue outer;
+
       otherAtoms[otherAtomCount++] = pt;
     }
     return (otherAtomCount < 3 || nVertices > 0
         && !bsVertexCount.get(otherAtomCount) ? null : validatePolyhedron(atom,
-        otherAtomCount, otherAtoms));
+        otherAtomCount));
   }
 
-  private Polyhedron validatePolyhedron(Atom centralAtom, int vertexCount,
-                                        P3[] points) {
+  private Polyhedron validatePolyhedron(Atom centralAtom, int vertexCount) {
+    P3[] points = otherAtoms;
     boolean collapsed = isCollapsed;
-    boolean checkDist = (distanceRef != 0);
-    int planeCount = 0;
+    int triangleCount = 0;
     int nPoints = vertexCount + 1;
     int ni = vertexCount - 2;
     int nj = vertexCount - 1;
     float planarParam = (Float.isNaN(this.planarParam) ? DEFAULT_PLANAR_PARAM
         : this.planarParam);
-//    float factor = (!Float.isNaN(distanceFactor) ? distanceFactor
-//        : DEFAULT_DISTANCE_FACTOR);
-//    BS bs = BS.newN(vertexCount);
 
-    // here we are assuring that at least ONE face is drawn to 
-    // all matching vertices -- skip this for BOND polyhedra
-
     points[vertexCount] = centralAtom;
-    P3 ptAve = new P3();
+    P3 ptAve = P3.newP(centralAtom);
     for (int i = 0; i < vertexCount; i++)
       ptAve.add(points[i]);
-    ptAve.scale(1f / vertexCount);
-//    float distMax = 0;
-//    if (checkDist) {
-//      float dAverage = 0;
-//      for (int i = 0; i < vertexCount; i++)
-//        dAverage += points[vertexCount].distance(points[i]);
-//      dAverage /= vertexCount;
-//      boolean isOK = (dAverage == 0);
-//      while (!isOK && factor < 10.0f) {
-//        distMax = dAverage * factor;
-//        bs.setBits(0, vertexCount);
-//        for (int i = 0; i < ni; i++)
-//          for (int j = i + 1; j < nj; j++) {
-//            if (points[i].distance(points[j]) > distMax)
-//              continue;
-//            for (int k = j + 1; k < vertexCount; k++) {
-//              if (points[i].distance(points[k]) > distMax
-//                  || points[j].distance(points[k]) > distMax)
-//                continue;
-//              bs.clear(i);
-//              bs.clear(j);
-//              bs.clear(k);
-//            }
-//          }
-//        isOK = true;
-//        for (int i = 0; i < vertexCount; i++)
-//          if (bs.get(i)) {
-//            isOK = false;
-//            factor *= 1.05f;
-//            if (Logger.debugging) {
-//              Logger.debug("Polyhedra distanceFactor for " + vertexCount
-//                  + " atoms increased to " + factor + " in order to include "
-//                  + points[i]);
-//            }
-//            break;
-//          }
-//      }
-//    }
+    ptAve.scale(1f / (vertexCount + 1));
     /*  Start by defining a face to be when all three distances
      *  are < distanceFactor * (longest central) but if a vertex is missed, 
      *  then expand the range. The collapsed trick is to introduce 
@@ -664,30 +633,22 @@
           if (isPlanar(points[i], points[j], points[k], ptRef))
             bsThroughCenter.set(pt);
     // this next check for distance allows for bond AND distance constraints
-    int[][] faces = planesT;
+    int[][] triangles = planesT;
     P4 pTemp = new P4();
     V3 nTemp = new V3();
     float offset = faceCenterOffset;
     int fmax = FACE_COUNT_MAX;
     int vmax = MAX_VERTICES;
     BS bsTemp = Normix.newVertexBitSet();
-    BS bsTemp1 = new BS();
     V3[] normals = normalsT;
-    Map<Object, Object> htNormMap = new Hashtable<Object, Object>();
+    Map<Integer, Object[]> htNormMap = new Hashtable<Integer, Object[]>();
+    Map<String, Object> htEdgeMap = new Hashtable<String, Object>();
     BS bsCenterPlanes = new BS();
-    V3 vTemp = vAC;
+    V3 vAC = this.vAC;
     for (int i = 0, pt = 0; i < ni; i++)
       for (int j = i + 1; j < nj; j++) {
-//        if (checkDist && points[i].distance(points[j]) > distMax) {
-//          pt += vertexCount - j - 1;
-//          continue;
-//        }
         for (int k = j + 1; k < vertexCount; k++, pt++) {
-//          if (checkDist
-//              && (points[i].distance(points[k]) > distMax || points[j]
-//                  .distance(points[k]) > distMax))
-//            continue;
-          if (planeCount >= fmax) {
+          if (triangleCount >= fmax) {
             Logger.error("Polyhedron error: maximum face(" + fmax
                 + ") -- reduce RADIUS");
             return null;
@@ -701,42 +662,43 @@
           P3 rpt = (isThroughCenter ? randomPoint : ptAve);
           V3 normal = new V3();
           boolean isWindingOK = Measure.getNormalFromCenter(rpt, points[i], 
points[j],
-              points[k], !isThroughCenter, normal, vTemp);
+              points[k], !isThroughCenter, normal, vAC);
           // the standard face:
-          normals[planeCount] = normal;
-          faces[planeCount] = new int[] { isWindingOK ? i : j, isWindingOK ? j 
: i,
+          normals[triangleCount] = normal;
+          triangles[triangleCount] = new int[] { isWindingOK ? i : j, 
isWindingOK ? j : i,
               k, -7 };
-          if (!checkFace(points, vertexCount, faces, normals, planeCount, 
pTemp, nTemp,
-              vTemp, htNormMap, planarParam, bsTemp, bsTemp1))
+          if (!checkFace(points, vertexCount, triangles, normals, 
triangleCount, pTemp, nTemp,
+              vAC, htNormMap, htEdgeMap, planarParam, bsTemp))
             continue;
           if (isThroughCenter) {
-            bsCenterPlanes.set(planeCount++);
+            bsCenterPlanes.set(triangleCount++);
           } else if (collapsed) {
             ptRef.setT(points[nPoints] = new P3());
             points[nPoints].scaleAdd2(offset, normal, centralAtom);
-            addFacet(i, j, k, ptRef, points, normals, faces, planeCount++, 
nPoints,
-                isWindingOK, vTemp);
-            addFacet(k, i, j, ptRef, points, normals, faces, planeCount++, 
nPoints,
-                isWindingOK, vTemp);
-            addFacet(j, k, i, ptRef, points, normals, faces, planeCount++, 
nPoints,
-                isWindingOK, vTemp);
+            addFacet(i, j, k, ptRef, points, normals, triangles, 
triangleCount++, nPoints,
+                isWindingOK, vAC);
+            addFacet(k, i, j, ptRef, points, normals, triangles, 
triangleCount++, nPoints,
+                isWindingOK, vAC);
+            addFacet(j, k, i, ptRef, points, normals, triangles, 
triangleCount++, nPoints,
+                isWindingOK, vAC);
             nPoints++;
           } else {
-            planeCount++;
+            triangleCount++;
           }
         }
       }
     nPoints--;
     if (Logger.debugging) {
       Logger
-          .info("Polyhedron planeCount=" + planeCount + " nPoints=" + nPoints);
-      for (int i = 0; i < planeCount; i++)
-        Logger.info("Polyhedron " + PT.toJSON("face[" +i + "]", faces[i]));
+          .info("Polyhedron planeCount=" + triangleCount + " nPoints=" + 
nPoints);
+      for (int i = 0; i < triangleCount; i++)
+        Logger.info("Polyhedron " + PT.toJSON("face[" +i + "]", triangles[i]));
     }
+    //System.out.println(PT.toJSON(null, htEdgeMap));
     return new Polyhedron().set(centralAtom, points, nPoints, vertexCount,
-        faces, planeCount, normals, bsCenterPlanes, collapsed, distanceRef);
+        triangles, triangleCount, getFaces(triangles, triangleCount, 
htNormMap), normals, bsCenterPlanes, collapsed, distanceRef);
   }
-
+  
   /**
    * Add one of the three "facets" that compose the planes of a "collapsed" 
polyhedron.
    * A mask of -2 ensures that only the [1-2] edge is marked as an outer edge.
@@ -778,51 +740,71 @@
    * @param index
    * @param pTemp
    * @param vNorm
-   * @param vTemp
+   * @param vAC
    * @param htNormMap
+   * @param htEdgeMap 
    * @param planarParam
    * @param bsTemp
-   * @param bsPts
    * @return true if valid
    */
   private boolean checkFace(P3[] points, int nPoints, int[][] planes,
                             V3[] normals, int index, P4 pTemp, V3 vNorm,
-                            V3 vTemp, Map<Object, Object> htNormMap,
-                            float planarParam, BS bsTemp, BS bsPts) {
+                            V3 vAC, Map<Integer, Object[]> htNormMap,
+                            Map<String, Object> htEdgeMap, float planarParam,
+                            BS bsTemp) {
     int[] p1 = planes[index];
 
-    // Check here for a 3D convex hull: 
-    pTemp = Measure.getPlaneThroughPoints(points[p1[0]], points[p1[1]],
-        points[p1[2]], vNorm, vTemp, pTemp);
-    // See if all vertices are OUTSIDE the the plane we are considering.      
+    // Check here for a 3D convex hull:
+    int i0 = p1[0];
+    pTemp = Measure.getPlaneThroughPoints(points[i0], points[p1[1]],
+        points[p1[2]], vNorm, vAC, pTemp);
+    // See if all vertices are OUTSIDE the the plane we are considering.
+    //System.out.println(PT.toJSON(null, p1));
+    P3 pt = points[i0];
     for (int j = 0; j < nPoints; j++) {
-      vTemp.sub2(points[p1[0]], points[j]);
-      float v = vTemp.dot(vNorm);
-      if (v < -0.15) {
+      if (j == i0)
+        continue;
+      vAC.sub2(points[j], pt);
+      vAC.normalize();
+      float v = vAC.dot(vNorm);
+      // we cannot just take a negative dot product as indication of being
+      // inside the convex hull. That would be fine if this were about regular
+      // polyhedra. But we can have imperfect quadrilateral faces that are 
slightly
+      // bowed inward. 
+      if (v > CONVEX_HULL_MAX) {
         return false;
       }
     }
     V3 norm = normals[index];
     Integer normix = Integer.valueOf(Normix.getNormixV(norm, bsTemp));
-    Object o = htNormMap.get(normix);
+    Object[] o = htNormMap.get(normix);
+    //System.out.println(PT.toJSON(null, p1) + " " + normix);
     if (o == null) {
-      // we must see if there is a close normix to this
+      // We must see if there is a close normix to this.
+      // The Jmol lighting model uses 642 normals,
+      // which have a neighboring vertex dot product of 0.990439.
+      // This is too tight for polyhedron planarity. We relax this
+      // requirement to 0.98 by default, but this can be relaxed even
+      // more if desired.
+
       V3[] norms = Normix.getVertexVectors();
-      for (Entry<Object, Object> e : htNormMap.entrySet()) {
-        Object ikey = e.getKey();
-        if (ikey instanceof Integer) {
-          Integer n = (Integer) ikey;
-          if (norms[n.intValue()].dot(norm) > planarParam) {
-            normix = n;
-            break;
-          }
+      for (Entry<Integer, Object[]> e : htNormMap.entrySet()) {
+        Integer n = e.getKey();
+        if (norms[n.intValue()].dot(norm) > planarParam) {
+          normix = n;
+          o = e.getValue();
+          break;
         }
       }
-      htNormMap.put(normix, Boolean.TRUE);
+      if (o == null)
+        htNormMap.put(normix, o = new Object[] {new BS(), new Lst<int[]>()});
     }
-    bsPts.clearAll();
+    //System.out.println(PT.toJSON(null, p1) + " " + normix);
+    BS bsPts = (BS) o[0];
+    @SuppressWarnings("unchecked")
+    Lst<int[]> lst = (Lst<int[]>) o[1];
     for (int i = 0; i < 3; i++)
-      if (!addEdge(htNormMap, normix, p1, i, points, bsPts))
+      if (!addEdge(lst, htEdgeMap, normix, p1, i, points, bsPts))
         return false;
     return true;
   }
@@ -835,8 +817,8 @@
    * (b) it does not have vertex points on both sides of it
    * 
    * (c) if it runs opposite another edge, then both edge masks are set 
properly
-   * 
-   * @param htNormMap
+   * @param faceList 
+   * @param htEdgeMap
    * @param normix
    * @param p1
    * @param i
@@ -845,7 +827,7 @@
    * @return true if this triangle is OK
    * 
    */
-  private boolean addEdge(Map<Object, Object> htNormMap, Integer normix,
+  private boolean addEdge(Lst<int[]>faceList, Map<String, Object> htEdgeMap, 
Integer normix,
                           int[] p1, int i, P3[] points, BS bsPts) {
     // forward maps are out
     int pt1 = p1[(i + 1) % 3];
@@ -853,11 +835,12 @@
     int pt = p1[i];
     String s = "_" + pt;
     String edge = normix + s + s1;
-    if (htNormMap.containsKey(edge))
+    if (htEdgeMap.containsKey(edge))
       return false;
     //reverse maps are in
     String edge0 = normix + s1 + s;
-    Object o = htNormMap.get(edge0);
+    Object o = htEdgeMap.get(edge0);
+    int[] b;
     if (o == null) {
       // first check that we have all points on the same side of this line. 
       P3 coord2 = points[pt1];
@@ -878,14 +861,18 @@
       }
       bsPts.set(pt);
       bsPts.set(pt1);
+      b = new int[] {pt, pt1};
+      faceList.addLast(b);
+      htEdgeMap.put(edge, new Object[] { p1, Integer.valueOf(i), b });
     } else {
       // set mask to exclude both of these.
       int[] p10 = (int[]) ((Object[]) o)[0];
       int i0 = ((Integer) ((Object[]) o)[1]).intValue();
       p10[3] = -((-p10[3]) ^ (1 << i0));
       p1[3] = -((-p1[3]) ^ (1 << i));
+      b = (int[])((Object[]) o)[2];
+      faceList.removeObj(b);
     }
-    htNormMap.put(edge, new Object[] { p1, Integer.valueOf(i) });
     return true;
   }
 
@@ -908,6 +895,47 @@
     return (Math.abs(d) < MAX_DISTANCE_TO_PLANE);
   }
 
+
+  private int[][] getFaces(int[][] triangles, int triangleCount,
+                           Map<Integer, Object[]> htNormMap) {
+    int n = htNormMap.size();
+    int[][] faces = AU.newInt2(n);
+    if (triangleCount == n) {
+      for (int i = triangleCount; --i >= 0;)
+        faces[i] = AU.arrayCopyI(triangles[i], 3);
+      return faces;
+    }
+    int fpt = 0;
+    for (Entry<Integer, Object[]> e : htNormMap.entrySet()) {
+      @SuppressWarnings("unchecked")
+      Lst<int[]> faceList = (Lst<int[]>)e.getValue()[1];
+      n = faceList.size();
+      int[] face = faces[fpt++] = new int[n];
+      if (n < 2)
+        continue;
+      int[] edge = faceList.get(0);
+      //System.out.println("poly edge=" + PT.toJSON(null, edge));
+      face[0] = edge[0];
+      face[1] = edge[1];
+      int pt = 2;
+      int i0 = 1;
+      int  pt0 =  -1;
+      while (pt < n && pt0 != pt) {
+        pt0 = pt;
+        for (int i = i0; i < n; i++) {
+          edge = faceList.get(i);
+          if (edge[0] == face[pt - 1]) {
+            face[pt++] = edge[1];
+            if (i == i0)
+              i0++;
+            break;
+          }
+        }
+      }
+    }
+    return faces;
+  }
+
   @Override
   public void setModelVisibilityFlags(BS bsModels) {
     /*

Modified: trunk/Jmol/src/org/jmol/shapespecial/Polyhedron.java
===================================================================
--- trunk/Jmol/src/org/jmol/shapespecial/Polyhedron.java        2015-09-10 
12:34:16 UTC (rev 20770)
+++ trunk/Jmol/src/org/jmol/shapespecial/Polyhedron.java        2015-09-14 
04:27:09 UTC (rev 20771)
@@ -17,7 +17,9 @@
 import org.jmol.script.SV;
 import org.jmol.script.T;
 import org.jmol.util.C;
+import org.jmol.util.Elements;
 import org.jmol.util.Escape;
+import org.jmol.util.Logger;
 import org.jmol.util.Node;
 import org.jmol.util.Normix;
 import org.jmol.util.Point3fi;
@@ -28,6 +30,7 @@
 
   public Atom centralAtom;
   public P3[] vertices;
+  public int[][] triangles;
   public int[][] faces;
   int nVertices;
   boolean collapsed;
@@ -50,76 +53,26 @@
   }
   
   Polyhedron set(Atom centralAtom, P3[] points, int nPoints, int vertexCount,
-      int[][] planes, int planeCount, V3[] normals, BS bsFlat, boolean 
collapsed, float distanceRef) {
+      int[][] triangles, int triangleCount, int[][] faces, V3[] normals, BS 
bsFlat, boolean collapsed, float distanceRef) {
     this.distanceRef = distanceRef;
     this.centralAtom = centralAtom;
     this.nVertices = vertexCount;
     this.vertices = new P3[nPoints + 1];
-    this.normals = new V3[planeCount];
+    this.normals = new V3[triangleCount];
+    this.faces = faces;
     this.bsFlat = bsFlat;
-    this.faces = AU.newInt2(planeCount);
+    this.triangles = AU.newInt2(triangleCount);
     for (int i = nPoints + 1; --i >= 0;)
       // includes central atom as last atom or possibly reference point
       vertices[i] = points[i];
-    for (int i = planeCount; --i >= 0;)
+    for (int i = triangleCount; --i >= 0;)
       this.normals[i] = V3.newV(normals[i]);
-    for (int i = planeCount; --i >= 0;)
-      this.faces[i] = planes[i];
+    for (int i = triangleCount; --i >= 0;)
+      this.triangles[i] = triangles[i];
     this.collapsed = collapsed;
     return this;
   }
 
-  Map<String, Object> info;
-  
-  Map<String, Object> getInfo(Viewer vwr, boolean isAll) {
-    if (isAll && this.info != null)
-      return this.info;
-    Map<String, Object> info = new Hashtable<String, Object>();
-    if (isAll) {
-      this.info = info;
-      info.put("modelIndex", Integer.valueOf(centralAtom.mi));
-      info.put("modelNumber", Integer.valueOf(centralAtom.getModelNumber()));
-      info.put("center", P3.newP(centralAtom));
-      info.put("atomNumber", Integer.valueOf(centralAtom.getAtomNumber()));
-      info.put("atomName", centralAtom.getInfo());
-      info.put("element", centralAtom.getElementSymbol());
-      info.put("faceCount", Integer.valueOf(faces.length));
-      info.put("volume", getVolume());
-      if (smarts != null)
-        info.put("smarts", smarts);
-      if (smiles != null)
-        info.put("smiles", smiles);
-      if (polySmiles != null)
-        info.put("polySmiles", polySmiles);
-      if (pointGroup != null)
-        info.put("pointGroup", pointGroup.getPointGroupName());
-      Object energy = vwr.ms.getInfo(centralAtom.mi, "Energy");
-      if (energy != null)
-        info.put("energy", energy);
-    } else {
-      info.put("bsFlat", bsFlat);
-      if (collapsed)
-        info.put("collapsed", Boolean.valueOf(collapsed));
-      info.put("distanceRef", Float.valueOf(distanceRef));
-    }
-    info.put("vertexCount", Integer.valueOf(nVertices));
-    info.put("atomIndex", Integer.valueOf(centralAtom.i));
-    info.put("vertices", AU.arrayCopyPt(vertices, (isAll ? nVertices : 
vertices.length)));
-    P3[] n = new P3[normals.length];
-    for (int i = n.length; --i >= 0;)
-      n[i] = P3.newP(normals[i]);
-    info.put("normals", n);
-    info.put("faces", AU.arrayCopyII(faces, faces.length));
-    int[] elemNos = new int[nVertices];
-    for (int i = 0; i < nVertices; i++) {
-      P3 pt = vertices[i];
-      elemNos[i] = (pt instanceof Node ? ((Node) pt).getElementNumber()
-          : pt instanceof Point3fi ? ((Point3fi) pt).sD : -2);
-    }
-    info.put("elemNos", elemNos);
-    return info;
-  }
-
   Polyhedron setInfo(Map<String, SV> info, Atom[] at) {
     try {
       collapsed = info.containsKey("collapsed");
@@ -134,7 +87,7 @@
       } else {
         nVertices = vc.intValue;
         vertices = new P3[lst.size()];
-        vc = info.get("distanceRef");
+        vc = info.get("r");
         if (vc != null)
           distanceRef = vc.asFloat();
       }
@@ -152,17 +105,19 @@
           vertices[i] = p;
         }
       }
-      lst = info.get("faces").getList();
-      faces = AU.newInt2(lst.size());
-      normals = new V3[faces.length];
+      SV faces = info.get("faces");
+      SV o = info.get("triangles");
+      if (o == null) { // formerly
+        o = faces;
+      } else {
+        this.faces = toInt2(faces);
+      }
+      triangles = toInt2(o);
+      normals = new V3[triangles.length];
       V3 vAB = new V3();
-      for (int i = faces.length; --i >= 0;) {
-        Lst<SV> lst2 = lst.get(i).getList();
-        int[] a = new int[lst2.size()];
-        for (int j = a.length; --j >= 0;)
-          a[j] = lst2.get(j).intValue;
-        faces[i] = a;
+      for (int i = triangles.length; --i >= 0;) {
         normals[i] = new V3();
+        int[] a = triangles[i];
         Measure.getNormalThroughPoints(vertices[a[0]], vertices[a[1]],
             vertices[a[2]], normals[i], vAB);
       }
@@ -173,15 +128,93 @@
     return this;
   }
 
+  private int[][] toInt2(SV o) {
+    Lst<SV> lst = o.getList();
+    int[][] ai = AU.newInt2(lst.size());
+    for (int i = ai.length; --i >= 0;) {
+      Lst<SV> lst2 = lst.get(i).getList();
+      int[] a = ai[i] = new int[lst2.size()];
+      for (int j = a.length; --j >= 0;)
+        a[j] = lst2.get(j).intValue;
+    }
+    return ai;
+  }
+
+  Map<String, Object> info;
+  
+  Map<String, Object> getInfo(Viewer vwr, boolean isAll) {
+    if (isAll && this.info != null && !Logger.debugging)
+      return this.info;
+    Map<String, Object> info = new Hashtable<String, Object>();
+    if (isAll) {
+      this.info = info;
+      info.put("modelIndex", Integer.valueOf(centralAtom.mi));
+      info.put("modelNumber", Integer.valueOf(centralAtom.getModelNumber()));
+      info.put("center", P3.newP(centralAtom));
+      info.put("atomNumber", Integer.valueOf(centralAtom.getAtomNumber()));
+      info.put("atomName", centralAtom.getInfo());
+      info.put("element", centralAtom.getElementSymbol());
+      info.put("triangleCount", Integer.valueOf(triangles.length));
+      info.put("volume", getVolume());
+      String[] names = new String[nVertices];
+      for (int i = nVertices; --i >= 0;) {
+        P3 pt = vertices[i];
+        names[i] = (pt instanceof Node ? ((Node) pt).getAtomName()
+            : pt instanceof Point3fi ? Elements
+                .elementSymbolFromNumber(((Point3fi) pt).sD) : "");
+      }
+      if (faces != null)
+        info.put("faceCount", Integer.valueOf(faces.length));
+      info.put("atomNames", names);
+      if (smarts != null)
+        info.put("smarts", smarts);
+      if (smiles != null)
+        info.put("smiles", smiles);
+      if (polySmiles != null)
+        info.put("polySmiles", polySmiles);
+      if (pointGroup != null)
+        info.put("pointGroup", pointGroup.getPointGroupName());
+      Object energy = vwr.ms.getInfo(centralAtom.mi, "Energy");
+      if (energy != null)
+        info.put("energy", energy);
+    }
+    if (faces != null)
+      info.put("faces", faces);
+    if (!isAll || Logger.debugging) {
+      info.put("bsFlat", bsFlat);
+      if (collapsed)
+        info.put("collapsed", Boolean.valueOf(collapsed));
+      if (distanceRef != 0)
+        info.put("r", Float.valueOf(distanceRef));
+      P3[] n = new P3[normals.length];
+      for (int i = n.length; --i >= 0;)
+        n[i] = P3.newP(normals[i]);
+      info.put("normals", n);
+      info.put("triangles", AU.arrayCopyII(triangles, triangles.length));
+    }
+    info.put("vertexCount", Integer.valueOf(nVertices));
+    info.put("atomIndex", Integer.valueOf(centralAtom.i));
+    info.put("vertices",
+        AU.arrayCopyPt(vertices, (isAll ? nVertices : vertices.length)));
+    int[] elemNos = new int[nVertices];
+    for (int i = 0; i < nVertices; i++) {
+      P3 pt = vertices[i];
+      elemNos[i] = (pt instanceof Node ? ((Node) pt).getElementNumber()
+          : pt instanceof Point3fi ? ((Point3fi) pt).sD : -2);
+    }
+    info.put("elemNos", elemNos);
+    return info;
+  }
+
   String getSymmetry(Viewer vwr, boolean withPointGroup) {
     info = null;
     SmilesMatcherInterface sm = vwr.getSmilesMatcher();
     try {
-      String details = (distanceRef <= 0 ? null : "" + distanceRef);
+      String details = (distanceRef <= 0 ? null : "r=" + distanceRef);
       if (smarts == null) {
-        smarts = sm.polyhedronToSmiles(centralAtom, faces, nVertices, null, 
JC.SMILES_TOPOLOGY | JC.SMILES_NOSTEREO, null);
-        smiles = sm.polyhedronToSmiles(centralAtom, faces, nVertices, 
vertices, JC.SMILES_TYPE_SMILES | JC.SMILES_NOSTEREO, null);
-        polySmiles = sm.polyhedronToSmiles(centralAtom, faces, nVertices, 
vertices,  JC.SMILES_TYPE_SMILES | JC.SMILES_ATOM_COMMENT, details);
+        smarts = sm.polyhedronToSmiles(centralAtom, faces, nVertices, null, 
JC.SMILES_TOPOLOGY, null);
+        smiles = sm.polyhedronToSmiles(centralAtom, faces, nVertices, 
vertices, JC.SMILES_TYPE_SMILES, null);
+        polySmiles = sm.polyhedronToSmiles(centralAtom, faces, nVertices, 
vertices,  JC.SMILES_TYPE_SMILES | JC.SMILES_POLYHEDRAL | 
JC.SMILES_ATOM_COMMENT, details);
       }
     } catch (Exception e) {
     }
@@ -207,9 +240,9 @@
     V3 vAC = new V3();
     V3 vTemp = new V3();
     float v = 0;
-    if (bsFlat.cardinality() < faces.length)
-      for (int i = faces.length; --i >= 0;) {
-        int[] face = faces[i];
+    if (bsFlat.cardinality() < triangles.length)
+      for (int i = triangles.length; --i >= 0;) {
+        int[] face = triangles[i];
         for (int j = face.length - 2; --j >= 0;)
           if (face[j + 2] >= 0)
             v += triangleVolume(face[j], face[j + 1], face[j + 2], vAB, vAC,
@@ -228,7 +261,7 @@
   }
 
   String getState(Viewer vwr) {
-    return "polyhedron @" + Escape.e(getInfo(vwr, false)) 
+    return "  polyhedron @{" + Escape.e(getInfo(vwr, false)) + "} " 
         + (isFullyLit ? " fullyLit" : "") + ";"
         + (visible ? "" : "polyhedra ({"+centralAtom.i+"}) off;") + "\n";
   }

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesGenerator.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesGenerator.java 2015-09-10 12:34:16 UTC 
(rev 20770)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesGenerator.java 2015-09-14 04:27:09 UTC 
(rev 20771)
@@ -88,6 +88,7 @@
   private boolean noStereo;
   public P3 stereoReference;
   private SmilesStereo smilesStereo;
+  private boolean isPolyhedral;
 
   // generation of SMILES strings
 
@@ -109,6 +110,7 @@
     topologyOnly = JC.checkFlag(flags, JC.SMILES_TOPOLOGY);
     getAromatic = !JC.checkFlag(flags, JC.SMILES_NOAROMATIC);
     noStereo = JC.checkFlag(flags, JC.SMILES_NOSTEREO);
+    isPolyhedral = JC.checkFlag(flags, JC.SMILES_POLYHEDRAL);
     return getSmilesComponent(atoms[ipt], bsSelected, true, false, false);
   }
 
@@ -265,17 +267,19 @@
    * 
    * @param atom
    * @param bs
-   * @param allowBioResidues 
+   * @param allowBioResidues
    * @param allowConnectionsToOutsideWorld
-   * @param forceBrackets 
+   * @param forceBrackets
    * @return SMILES
    * @throws InvalidSmilesException
    */
   private String getSmilesComponent(Node atom, BS bs, boolean allowBioResidues,
-                                    boolean allowConnectionsToOutsideWorld, 
boolean forceBrackets)
+                                    boolean allowConnectionsToOutsideWorld,
+                                    boolean forceBrackets)
       throws InvalidSmilesException {
 
-    if (!explicitH && atom.getElementNumber() == 1 && atom.getEdges().length > 
0)
+    if (!explicitH && atom.getElementNumber() == 1
+        && atom.getEdges().length > 0)
       atom = atoms[atom.getBondedAtomIndex(0)]; // don't start with H
     bsSelected = JmolMolecule.getBranchBitSet(atoms, atom.getIndex(),
         BSUtil.copy(bs), null, -1, true, allowBioResidues);
@@ -307,19 +311,18 @@
     bsToDo = BSUtil.copy(bsSelected);
     SB sb = new SB();
 
-    
     // The idea hear is to allow a hypervalent atom to be listed first
-    for (int i = bsToDo.nextSetBit(0); i >= 0; i = bsToDo.nextSetBit(i + 1))
-      if (atoms[i].getCovalentBondCount() > 4) {
-        if (atom == null)
-          sb.append(".");
-        getSmilesAt(sb, atoms[i], allowConnectionsToOutsideWorld, false,
-            explicitH, forceBrackets);
-        atom = null;
-      }
+      for (int i = bsToDo.nextSetBit(0); i >= 0; i = bsToDo.nextSetBit(i + 1))
+        if (atoms[i].getCovalentBondCount() > 4 || isPolyhedral) {
+          if (atom == null)
+            sb.append(".");
+          getSmilesAt(sb, atoms[i], allowConnectionsToOutsideWorld, false,
+              explicitH, forceBrackets);
+          atom = null;
+        }
     if (atom != null)
-      while ((atom = getSmilesAt(sb, atom, allowConnectionsToOutsideWorld, 
true,
-          explicitH, forceBrackets)) != null) {
+      while ((atom = getSmilesAt(sb, atom, allowConnectionsToOutsideWorld,
+          true, explicitH, forceBrackets)) != null) {
       }
     while (bsToDo.cardinality() > 0 || !htRings.isEmpty()) {
       Iterator<Object[]> e = htRings.values().iterator();
@@ -333,8 +336,8 @@
       sb.append(".");
       prevSp2Atoms = null;
       prevAtom = null;
-      while ((atom = getSmilesAt(sb, atom, allowConnectionsToOutsideWorld, 
true,
-          explicitH, forceBrackets)) != null) {
+      while ((atom = getSmilesAt(sb, atom, allowConnectionsToOutsideWorld,
+          true, explicitH, forceBrackets)) != null) {
       }
     }
     if (!htRings.isEmpty()) {
@@ -508,13 +511,7 @@
     Edge[] bonds = atom.getEdges();
     if (stereoReference != null) {
       allowBranches = false;
-      if (smilesStereo == null)
-        try {
-          smilesStereo = SmilesStereo.newStereo(null);
-        } catch (InvalidSmilesException e) {
-          // not possible
-        }
-      smilesStereo.sortBondsByStereo(atom, prevAtom, stereoReference, bonds, 
vTemp.vA);
+      sortBonds(atom, prevAtom, stereoReference);
     }
     Node aH = null;
     int stereoFlag = (isAromatic ? 10 : 0);
@@ -748,6 +745,16 @@
     return atomNext;
   }
 
+  void sortBonds(Node atom, Node refAtom, P3 center) {
+    if (smilesStereo == null)
+      try {
+        smilesStereo = SmilesStereo.newStereo(null);
+      } catch (InvalidSmilesException e) {
+        // not possible
+      }
+    smilesStereo.sortBondsByStereo(atom, refAtom, center, atom.getEdges(), 
vTemp.vA);
+  }
+
   /**
    * We must sort the bond vector such that a diaxial pair is
    * first and last. Then we assign stereochemistry based on what

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java   2015-09-10 12:34:16 UTC 
(rev 20770)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java   2015-09-14 04:27:09 UTC 
(rev 20771)
@@ -379,20 +379,12 @@
     for (int i = faces.length; --i >= 0;) {
       int[] face = faces[i];
       int n = face.length;
-      int mask = face[n - 1];
-      if (mask < 0) {
-        mask = -mask;
-        n--;
-      } else {
-        mask = -1;
-      }
       int iatom, iatom2;
       for (int j = n; --j >= 0;) {
         if ((iatom = face[j]) >= atomCount
             || (iatom2 = face[(j + 1) % n]) >= atomCount)
           continue;
-        if ((mask & (1 << j)) != 0
-            && atoms[iatom].getBondTo(atoms[iatom2]) == null) {
+        if (atoms[iatom].getBondTo(atoms[iatom2]) == null) {
           SmilesBond b = new SmilesBond(atoms[iatom], atoms[iatom2],
               SmilesBond.TYPE_SINGLE, false);
           b.index = nBonds++;
@@ -404,18 +396,20 @@
       if (n == 0 || n != atoms[i].bonds.length)
         atoms[i].bonds = (SmilesBond[]) AU.arrayCopyObject(atoms[i].bonds, n);
     }
+    String s = null;
     SmilesGenerator g = new SmilesGenerator();
     if (points != null)
       g.stereoReference = (P3) center;
     InvalidSmilesException.clear();
-    String s = g.getSmiles(atoms, atomCount, BSUtil.newBitSet2(0, atomCount),
+    s = g.getSmiles(atoms, atomCount, BSUtil.newBitSet2(0, atomCount),
         null, flags | JC.SMILES_EXPLICIT_H | JC.SMILES_NOAROMATIC
             | JC.SMILES_NOSTEREO);
-    if (!JC.checkFlag(flags, JC.SMILES_NOSTEREO)) {
+    if (JC.checkFlag(flags, JC.SMILES_POLYHEDRAL)) {
       s = "//* " + center + " *//\t["
           + Elements.elementSymbolFromNumber(center.getElementNumber()) + "@PH"
           + atomCount + (details == null ? "" : "/" + details + "/") + "]." + 
s;
     }
+
     return s;
   }
 

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesParser.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesParser.java    2015-09-10 12:34:16 UTC 
(rev 20770)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesParser.java    2015-09-14 04:27:09 UTC 
(rev 20771)
@@ -1096,7 +1096,8 @@
    * 
    * @param newAtom
    * @param name
-   * @param ret set [0] to 1 for new atom; 0 otherwise
+   * @param ret
+   *        set [0] to 1 for new atom; 0 otherwise
    * @return new or old atom
    */
   private SmilesAtom checkReference(SmilesAtom newAtom, String name, int[] 
ret) {
@@ -1106,9 +1107,20 @@
     if (ref == null) {
       // this is a new atom
       atomRefs.put(newAtom.referance = name, ref = newAtom);
+      if (!newAtom.hasSymbol) {
+        if (name.length() > 0) {
+          String s = null;
+          if (name.length() >= 2
+              && (Elements.elementNumberFromSymbol(s = name.substring(0, 2),
+                  true) > 0 || Elements.elementNumberFromSymbol(
+                  s = name.substring(0, 1), true) > 0)) {
+            newAtom.setSymbol(s);
+          }
+        }
+      }
       ret[0] = 1;
     } else {
-      ret[0] = 0;      
+      ret[0] = 0;
     }
     return ref;
   }

Modified: trunk/Jmol/src/org/jmol/symmetry/UnitCellIterator.java
===================================================================
--- trunk/Jmol/src/org/jmol/symmetry/UnitCellIterator.java      2015-09-10 
12:34:16 UTC (rev 20770)
+++ trunk/Jmol/src/org/jmol/symmetry/UnitCellIterator.java      2015-09-14 
04:27:09 UTC (rev 20771)
@@ -191,6 +191,8 @@
     Atom a = getAtom();
     if (Logger.debugging)
       Logger.info("draw ID p_" + nFound  + " " + p + " //" + a + " " + t);
+    if (this.p.distanceSquared(a) < 0.0001f)
+      return a;
     Point3fi p = new Point3fi();
     p.setT(this.p);
     p.i = a.i;

Modified: trunk/Jmol/src/org/jmol/viewer/GlobalSettings.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/GlobalSettings.java  2015-09-10 12:34:16 UTC 
(rev 20770)
+++ trunk/Jmol/src/org/jmol/viewer/GlobalSettings.java  2015-09-14 04:27:09 UTC 
(rev 20771)
@@ -898,14 +898,13 @@
       else if (database.equals("nci"))
         id += "/file?format=sdf&get3d=True";
     }
-    while (format.indexOf("%c") >= 0) {
-      try {
+    try {
+      while (format.indexOf("%c") >= 0)
         for (int i = 1; i < 10; i++) {
           format = PT.rep(format, "%c" + i, id.substring(i - 1, i));
         }
-      } catch (Exception e) {
-        // too bad.
-      }
+    } catch (Exception e) {
+      // too bad.
     }
     return (format.indexOf("%FILE") < 0 ? format + id : PT.formatStringS(
         format, "FILE", id));

Modified: trunk/Jmol/src/org/jmol/viewer/JC.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/JC.java      2015-09-10 12:34:16 UTC (rev 
20770)
+++ trunk/Jmol/src/org/jmol/viewer/JC.java      2015-09-14 04:27:09 UTC (rev 
20771)
@@ -1044,6 +1044,7 @@
   public static final int SMILES_TOPOLOGY                  = 0x00200;
   public static final int SMILES_NOAROMATIC                = 0x00400;
   public static final int SMILES_NOSTEREO                  = 0x00800;
+  public static final int SMILES_POLYHEDRAL                = 0x01000;
   public static final int SMILES_BIO                       = 0x10000;
   public static final int SMILES_BIO_ALLOW_UNMATCHED_RINGS = 0x11000;
   public static final int SMILES_BIO_COV_CROSSLINK         = 0x12000;

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


------------------------------------------------------------------------------
_______________________________________________
Jmol-commits mailing list
Jmol-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jmol-commits

Reply via email to