Revision: 20757
          http://sourceforge.net/p/jmol/code/20757
Author:   hansonr
Date:     2015-09-06 04:09:52 +0000 (Sun, 06 Sep 2015)
Log Message:
-----------
Jmol.___JmolVersion="14.3.16_2015.09.05"

new feature: POLYHEDRA
  -- same as POLYHEDRA BONDS {selected}
new feature: POLYHEDRA 4
  -- same as POLYHEDRA 4 BONDS {selected}  
new feature: POLYHEDRA OFFSET 1.4
  -- same as POLYHEDRA COLLAPSED faceCenterOffset 1.4
new feature: POLYHEDRA COLLAPSED 1.4
  -- same as POLYHEDRA COLLAPSED faceCenterOffset 1.4

code: Polyhedra work, including more efficient algorithms for completing set of 
faces

bug fix: tracking down thread-safe issue in application console
bug fix: in Java, mouse should not lose control if moved out of application

undocumented POLYHEDRA FLAT removed

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/awt/Mouse.java
    trunk/Jmol/src/org/jmol/script/ScriptExpr.java
    trunk/Jmol/src/org/jmol/script/T.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/viewer/Jmol.properties
    trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/AppConsole.java
    
trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/ConsoleTextArea.java

Modified: trunk/Jmol/src/org/jmol/awt/Mouse.java
===================================================================
--- trunk/Jmol/src/org/jmol/awt/Mouse.java      2015-09-05 04:19:46 UTC (rev 
20756)
+++ trunk/Jmol/src/org/jmol/awt/Mouse.java      2015-09-06 04:09:52 UTC (rev 
20757)
@@ -102,7 +102,7 @@
       mousePressed(time, x, y, modifiers, false);
       break;
     case Event.MOUSE_DRAG:
-      mouseDragged(time, x, y, modifiers);
+      mouseDragged(time, x, y);
       break;
     case Event.MOUSE_ENTER:
       mouseEntered(time, x, y);
@@ -157,16 +157,7 @@
 
   @Override
   public void mouseDragged(MouseEvent e) {
-    int modifiers = e.getModifiers();
-    /****************************************************************
-     * Netscape 4.* Win32 has a problem with mouseDragged if you left-drag then
-     * none of the modifiers are selected we will try to fix that here
-     ****************************************************************/
-    if ((modifiers & Event.BUTTON_MASK) == 0)
-      modifiers |= Event.MOUSE_LEFT;
-    
-    /****************************************************************/
-    mouseDragged(e.getWhen(), e.getX(), e.getY(), modifiers);
+    mouseDragged(e.getWhen(), e.getX(), e.getY());
   }
 
   @Override
@@ -308,15 +299,11 @@
 
   private void mouseEntered(long time, int x, int y) {
     wheeling = false;
-    isMouseDown = false;
-    modifiersDown = 0;
     manager.mouseEnterExit(time, x, y, false);
   }
 
   private void mouseExited(long time, int x, int y) {
     wheeling = false;
-    isMouseDown = false;
-    modifiersDown = 0;
     manager.mouseEnterExit(time, x, y, true);
   }
 
@@ -378,7 +365,7 @@
     manager.mouseAction(Event.RELEASED, time, x, y, 0, modifiers);
   }
 
-  private void mouseDragged(long time, int x, int y, int modifiers) {
+  private void mouseDragged(long time, int x, int y) {
     if (wheeling)
       return;
     if ((modifiersDown & Event.MAC_COMMAND) == Event.MAC_COMMAND)

Modified: trunk/Jmol/src/org/jmol/script/ScriptExpr.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/ScriptExpr.java      2015-09-05 04:19:46 UTC 
(rev 20756)
+++ trunk/Jmol/src/org/jmol/script/ScriptExpr.java      2015-09-06 04:09:52 UTC 
(rev 20757)
@@ -2342,6 +2342,7 @@
    * these, because they must be integrated with the statement dynamically.
    * 
    * @param st0  aaToken[i]
+   * @param pt0 
    * @return a fixed token set -- with possible overrun of unused null tokens
    * 
    * @throws ScriptException

Modified: trunk/Jmol/src/org/jmol/script/T.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/T.java       2015-09-05 04:19:46 UTC (rev 
20756)
+++ trunk/Jmol/src/org/jmol/script/T.java       2015-09-06 04:09:52 UTC (rev 
20757)
@@ -1200,7 +1200,7 @@
   public final static int filter         = misc  | 116;
   public final static int first   = misc  | 118;
   public final static int fixedtemp      = misc  | 122;
-  public final static int flat           = misc  | 124;
+//  public final static int flat           = misc  | 124; was only in 
Polyhedra; never documented
   public final static int fps            = misc  | 126 | expression;
   public final static int from           = misc  | 128;
   public final static int front   = misc  | 130;
@@ -1209,7 +1209,7 @@
   public final static int frontonly = misc  | 136;
   public final static int full            = misc  | 137;
   public final static int fullplane       = misc  | 138;
-  public final static int fullylit = misc  | 140;
+  public final static int fullylit        = misc  | 140;
   public final static int functionxy     = misc  | 142;
   public final static int functionxyz    = misc  | 144;
   public final static int gridpoints     = misc  | 146;
@@ -2226,7 +2226,7 @@
        "first",
        "fixed",
        "fix",
-       "flat",
+//       "flat",
        "fps",
        "from",
        "frontEdges",
@@ -3259,7 +3259,7 @@
         first,                              //        "first"
         fixed,                              //        "fixed"
         -1,                                 //        "fix"
-        flat,                               //        "flat"
+//        flat,                               //        "flat"
         fps,                                //        "fps"
         from,                               //        "from"
         frontedges,                         //        "frontEdges"

Modified: trunk/Jmol/src/org/jmol/scriptext/CmdExt.java
===================================================================
--- trunk/Jmol/src/org/jmol/scriptext/CmdExt.java       2015-09-05 04:19:46 UTC 
(rev 20756)
+++ trunk/Jmol/src/org/jmol/scriptext/CmdExt.java       2015-09-06 04:09:52 UTC 
(rev 20757)
@@ -3156,6 +3156,15 @@
 
   private boolean polyhedra() throws ScriptException {
     ScriptEval eval = e;
+    // polyhedra
+    // polyhedra on/off/delete
+    // polyhedra [type]
+    // where [type] is one of
+    //   n [opt. BONDS]
+    //   n-m [opt. BONDS]
+    //   [opt. RADIUS] x.y 
+    // polyhedra [type] [
+
     /*
      * needsGenerating:
      * 
@@ -3166,17 +3175,15 @@
      * 
      * polyhedra [at most one selection set] [type-and/or-edge or 
on/off/delete]
      */
-    boolean needsGenerating = false;
+    boolean haveBonds = (slen == 1);
+    boolean needsGenerating = haveBonds;
     boolean onOffDelete = false;
     boolean typeSeen = false;
     boolean edgeParameterSeen = false;
-    boolean isDesignParameter = false;
-    int lighting = 0;
+    //    int lighting = T.nada; // never implemented; fullyLit does nothing
     int nAtomSets = 0;
     e.sm.loadShape(JC.SHAPE_POLYHEDRA);
     setShapeProperty(JC.SHAPE_POLYHEDRA, "init", Boolean.TRUE);
-    String setPropertyName = "centers";
-    String decimalPropertyName = "radius_";
     float translucentLevel = Float.MAX_VALUE;
     int[] colorArgb = new int[] { Integer.MIN_VALUE };
     for (int i = 1; i < slen; ++i) {
@@ -3191,6 +3198,7 @@
       case T.unitcell:
         propertyName = "unitCell";
         propertyValue = Boolean.TRUE;
+        needsGenerating = true;
         break;
       case T.only:
         e.restrictSelected(false, false);
@@ -3199,116 +3207,132 @@
       case T.on:
       case T.delete:
       case T.off:
-        if (i + 1 != slen || needsGenerating || nAtomSets > 1 || nAtomSets == 0
-            && "to".equals(setPropertyName))
+        if (i + 1 != slen || needsGenerating || nAtomSets > 1)
           error(ScriptError.ERROR_incompatibleArguments);
         propertyName = (eval.theTok == T.off ? "off"
             : eval.theTok == T.on ? "on" : "delete");
         onOffDelete = true;
         break;
-      case T.opEQ:
-      case T.comma:
-        continue;
+      case T.integer:
+        propertyName = "nVertices";
+        propertyValue = Integer.valueOf(intParameter(i));
+        needsGenerating = true;
+        switch (tokAt(i + 1)) {
+        // wish I had not done this. Inconsistent with general syntax; only 
used here
+        case T.opEQ:
+        case T.comma:
+          i++;
+          break;
+        }
+        break;
       case T.bonds:
         if (nAtomSets > 0)
           invPO();
         needsGenerating = true;
         propertyName = "bonds";
+        haveBonds = true;
         break;
       case T.radius:
-        decimalPropertyName = "radius";
-        continue;
-      case T.integer:
+        i++;
+        //$FALL-THROUGH$
       case T.decimal:
-        if (nAtomSets > 0 && !isDesignParameter)
+        if (nAtomSets > 0)
           invPO();
-        if (eval.theTok == T.integer) {
-          if (decimalPropertyName == "radius_") {
-            propertyName = "nVertices";
-            propertyValue = Integer.valueOf(intParameter(i));
-            needsGenerating = true;
-            break;
-          }
-        }
-        propertyName = (decimalPropertyName == "radius_" ? "radius"
-            : decimalPropertyName);
+        propertyName = "radius";
         propertyValue = Float.valueOf(floatParameter(i));
-        decimalPropertyName = "radius_";
-        isDesignParameter = false;
         needsGenerating = true;
         break;
-      case T.bitset:
-      case T.expressionBegin:
-        if (typeSeen)
-          invPO();
-        if (++nAtomSets > 2)
-          eval.bad();
-        if ("to".equals(setPropertyName))
-          needsGenerating = true;
-        propertyName = setPropertyName;
-        setPropertyName = "to";
-        propertyValue = atomExpressionAt(i);
-        i = eval.iToken;
+      case T.offset:
+        eval.theTok = T.facecenteroffset;
+        //$FALL-THROUGH$
+      case T.facecenteroffset:
+        setShapeProperty(JC.SHAPE_POLYHEDRA, "collapsed", Boolean.TRUE);
+        //$FALL-THROUGH$
+      case T.planarparam:
+      case T.distancefactor:
+        propertyName = T.nameOf(eval.theTok);
+        switch (tokAt(i + 1)) {
+        // wish I had not done this. Inconsistent with general syntax; only 
used here
+        case T.opEQ:
+        case T.comma:
+          i++;
+          break;
+        }
+        propertyValue = Float.valueOf(floatParameter(++i));
         break;
       case T.to:
         if (nAtomSets > 1)
           invPO();
-        if (tokAt(i + 1) == T.bitset || tokAt(i + 1) == T.expressionBegin
+        if ((tokAt(++i) == T.bitset || tokAt(i) == T.expressionBegin)
             && !needsGenerating) {
+          // select... polyhedron .... to ....
           propertyName = "toBitSet";
-          propertyValue = atomExpressionAt(++i);
-          i = eval.iToken;
-          needsGenerating = true;
+          propertyValue = atomExpressionAt(i);
+        } else if (eval.isArrayParameter(i)) {
+          // select... polyhedron .... to [...]
+          // polyhedron {...} to [...]
+          propertyName = "toVertices";
+          propertyValue = eval.getPointArray(i, -1, false);
+        } else {
+          error(ScriptError.ERROR_insufficientArguments);
+        }
+        i = eval.iToken;
+        needsGenerating = true;
+        break;
+      case T.bitset:
+      case T.expressionBegin:
+        if (typeSeen)
+          invPO();
+        switch (++nAtomSets) {
+        case 1:
+          propertyName = "centers";
           break;
-        } else if (eval.isArrayParameter(i + 1)) {
-          propertyName = "toVertices";
-          propertyValue = eval.getPointArray(i + 1, -1, false);
-          i = eval.iToken;
+        case 2:
+          propertyName = "to";
           needsGenerating = true;
           break;
-        } else if (!needsGenerating) {
-          error(ScriptError.ERROR_insufficientArguments);
+        default:
+          eval.bad();
         }
-        setPropertyName = "to";
-        continue;
-      case T.facecenteroffset:
-      case T.planarparam:
-      case T.distancefactor:
-//        if (nAtomSets == 0)
-//          error(ScriptError.ERROR_insufficientArguments);
-        decimalPropertyName = T.nameOf(eval.theTok);
-        isDesignParameter = true;
-        continue;
+        propertyValue = atomExpressionAt(i);
+        i = eval.iToken;
+        if (i + 1 == slen)
+          needsGenerating = true;
+        break;
       case T.color:
       case T.translucent:
       case T.opaque:
         translucentLevel = getColorTrans(eval, i, true, colorArgb);
         i = eval.iToken;
         continue;
+        //      case T.flat: // removed in Jmol 14.4 -- never documented
       case T.collapsed:
-      case T.flat:
-        propertyName = "collapsed";
-        propertyValue = (eval.theTok == T.collapsed ? Boolean.TRUE
-            : Boolean.FALSE);
+        // COLLAPSED
+        // COLLAPSED [faceCenterOffset]
         if (typeSeen)
           error(ScriptError.ERROR_incompatibleArguments);
         typeSeen = true;
+        if (isFloatParameter(i + 1))
+          setShapeProperty(JC.SHAPE_POLYHEDRA, "faceCenterOffset",
+              Float.valueOf(floatParameter(++i)));
+        propertyName = "collapsed";
+        propertyValue = Boolean.TRUE;
         break;
-      case T.triangles:
-      case T.notriangles:
-        propertyName = "token";
-        propertyValue = Integer.valueOf(e.theTok);
-        break;
       case T.noedges:
       case T.edges:
       case T.frontedges:
         if (edgeParameterSeen)
           error(ScriptError.ERROR_incompatibleArguments);
-        propertyName = paramAsStr(i);
         edgeParameterSeen = true;
+        propertyName = T.nameOf(eval.iToken);
         break;
+      case T.triangles:
+      case T.notriangles:
+      case T.backlit:
+      case T.frontlit:
       case T.fullylit:
-        lighting = eval.theTok;
+        // never implemented or 
+        //        lighting = eval.theTok;
         continue;
       default:
         if (eval.isColorParam(i)) {
@@ -3322,18 +3346,21 @@
       if (onOffDelete)
         return false;
     }
-    if (!needsGenerating && !typeSeen && !edgeParameterSeen && lighting == 0)
+    if (needsGenerating) {
+      if (!typeSeen && haveBonds)
+        setShapeProperty(JC.SHAPE_POLYHEDRA, "bonds", null);
+      setShapeProperty(JC.SHAPE_POLYHEDRA, "generate", null);
+    } else if (!edgeParameterSeen) {// && lighting == T.nada)
       error(ScriptError.ERROR_insufficientArguments);
-    if (needsGenerating)
-      setShapeProperty(JC.SHAPE_POLYHEDRA, "generate", null);
+    }
     if (colorArgb[0] != Integer.MIN_VALUE)
       setShapeProperty(JC.SHAPE_POLYHEDRA, "colorThis",
           Integer.valueOf(colorArgb[0]));
     if (translucentLevel != Float.MAX_VALUE)
       eval.setShapeTranslucency(JC.SHAPE_POLYHEDRA, "", "translucentThis",
           translucentLevel, null);
-    if (lighting != 0)
-      setShapeProperty(JC.SHAPE_POLYHEDRA, "token", Integer.valueOf(lighting));
+    //    if (lighting != T.nada)
+    //      setShapeProperty(JC.SHAPE_POLYHEDRA, "token", 
Integer.valueOf(lighting));
     setShapeProperty(JC.SHAPE_POLYHEDRA, "init", Boolean.FALSE);
     return true;
   }

Modified: trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java
===================================================================
--- trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java 2015-09-05 04:19:46 UTC 
(rev 20756)
+++ trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java 2015-09-06 04:09:52 UTC 
(rev 20757)
@@ -56,16 +56,15 @@
 public class Polyhedra extends AtomShape {
 
   private final static float DEFAULT_DISTANCE_FACTOR = 1.85f;
-  //  private final static float DEFAULT_MANY_VERTEX_DISTANCE_FACTOR = 1.5f;
   private final static float DEFAULT_FACECENTEROFFSET = 0.25f;
   private final static int EDGES_NONE = 0;
   public final static int EDGES_ALL = 1;
   public final static int EDGES_FRONT = 2;
   private final static int MAX_VERTICES = 250;
   private final static int FACE_COUNT_MAX = MAX_VERTICES - 3;
-  private P3[] otherAtoms = new P3[MAX_VERTICES + 1];
+  private P3[] otherAtoms = new P3[MAX_VERTICES + FACE_COUNT_MAX + 1];
   private V3[] normalsT = new V3[MAX_VERTICES + 1];
-  private int[][] planesT = new int[MAX_VERTICES][3];
+  private int[][] planesT = AU.newInt2(MAX_VERTICES);
   private final static P3 randomPoint = P3.new3(3141f, 2718f, 1414f);
 
   private static final int MODE_BONDING = 1;
@@ -103,7 +102,6 @@
   private float planarParam;
   private Map<String, SV> info;
   private float distanceRef;
-  private int nBondsRef;
 
   @SuppressWarnings("unchecked")
   @Override
@@ -179,7 +177,7 @@
 
     if ("toVertices" == propertyName) {
       P3[] points = (P3[]) value;
-      nPoints = points.length;
+      nPoints = Math.min(points.length, MAX_VERTICES);
       for (int i = nPoints; --i >= 0;)
         otherAtoms[i] = points[i];
       return;
@@ -271,14 +269,15 @@
       //allow super
     }
 
-    if ("token" == propertyName) {
-      int tok = ((Integer) value).intValue();
-      if (tok == T.triangles && tok == T.notriangles) {
-      } else {
-        setLighting(tok == T.fullylit, bs);
-      }
-      return;
-    }
+//    if ("token" == propertyName) {
+//      int tok = ((Integer) value).intValue();
+//      Swit
+//      if (tok == T.triangles && tok == T.notriangles) {
+//      } else {
+//        setLighting(tok == T.fullylit, bs);
+//      }
+//      return;
+//    }
 
     if ("radius" == propertyName) {
       radius = ((Float) value).floatValue();
@@ -289,11 +288,10 @@
       int modelIndex = ((int[]) ((Object[]) value)[2])[0];
       for (int i = polyhedronCount; --i >= 0;) {
         polyhedrons[i].info = null;
-        if (polyhedrons[i].modelIndex == modelIndex) {
+        int mi = polyhedrons[i].centralAtom.mi;
+        if (mi == modelIndex) {
           polyhedronCount--;
           polyhedrons = (Polyhedron[]) AU.deleteElements(polyhedrons, i, 1);
-        } else if (polyhedrons[i].modelIndex > modelIndex) {
-          polyhedrons[i].modelIndex--;
         }
       }
       //pass on to AtomShape
@@ -310,9 +308,9 @@
         s += polyhedrons[i].getSymmetry(vwr, true) + "\n";
       return s;
     }
-    return null;  
+    return null;
   }
-  
+
   @Override
   public boolean getPropertyData(String property, Object[] data) {
     int iatom;
@@ -329,8 +327,10 @@
       return false;
     }
     if (property == "move") {
+      M4 mat = (M4) data[1];
+      if (mat == null)
+        return false;
       BS bs = (BS) data[0];
-      M4 mat = (M4) data[1];
       for (int i = polyhedronCount; --i >= 0;) {
         Polyhedron p = polyhedrons[i];
         if (bs.get(p.centralAtom.i))
@@ -391,17 +391,17 @@
     return lst;
   }
 
-  private void setLighting(boolean isFullyLit, BS bs) {
-    for (int i = polyhedronCount; --i >= 0;)
-      if (bs.get(polyhedrons[i].centralAtom.i)) {
-        short[] normixes = polyhedrons[i].getNormixes();
-        polyhedrons[i].isFullyLit = isFullyLit;
-        for (int j = normixes.length; --j >= 0;) {
-          if (normixes[j] < 0 != isFullyLit)
-            normixes[j] = (short) ~normixes[j];
-        }
-      }
-  }
+//  private void setLighting(boolean isFullyLit, BS bs) {
+//    for (int i = polyhedronCount; --i >= 0;)
+//      if (bs.get(polyhedrons[i].centralAtom.i)) {
+//        short[] normixes = polyhedrons[i].getNormixes();
+//        polyhedrons[i].isFullyLit = isFullyLit;
+//        for (int j = normixes.length; --j >= 0;) {
+//          if (normixes[j] < 0 != isFullyLit)
+//            normixes[j] = (short) ~normixes[j];
+//        }
+//      }
+//  }
 
   private BS andBitSet(BS bs) {
     BS bsCenters = new BS();
@@ -435,17 +435,19 @@
     }
   }
 
+  private int buildMode;
+
   private void buildPolyhedra() {
     boolean useBondAlgorithm = radius == 0 || bondedOnly;
-    int mode = (info != null ? MODE_INFO : nPoints > 0 ? MODE_POINTS
+    buildMode = (info != null ? MODE_INFO : nPoints > 0 ? MODE_POINTS
         : haveBitSetVertices ? MODE_BITSET : useUnitCell ? MODE_UNITCELL
             : useBondAlgorithm ? MODE_BONDING : MODE_ITERATE);
-    AtomIndexIterator iter = (mode == MODE_ITERATE ? ms
+    AtomIndexIterator iter = (buildMode == MODE_ITERATE ? 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 (mode) {
+      switch (buildMode) {
       case MODE_BITSET:
         bsVertices.clear(i);
         p = constructBitSetPolyhedron(atom);
@@ -529,7 +531,7 @@
         if (!bond.isCovalent())
           continue;
         Atom other = bond.getOtherAtom(atom);
-        if (bsVertices != null && !bsVertices.get(i) || radius > 0
+        if (bsVertices != null && !bsVertices.get(other.i) || radius > 0
             && other.distance(atom) > radius)
           continue;
         otherAtoms[bondCount++] = other;
@@ -537,7 +539,6 @@
           break;
       }
     }
-    nBondsRef = bondCount;
     distanceRef = 0;
     return (bondCount < 3 || bondCount >= MAX_VERTICES || nVertices > 0
         && !bsVertexCount.get(bondCount) ? null : validatePolyhedron(atom,
@@ -546,7 +547,6 @@
 
   private Polyhedron constructBitSetPolyhedron(Atom atom) {
     int otherAtomCount = 0;
-    nBondsRef = bsVertices.cardinality();
     distanceRef = 0;
     for (int i = bsVertices.nextSetBit(0); i >= 0; i = bsVertices
         .nextSetBit(i + 1))
@@ -556,12 +556,12 @@
 
   private Polyhedron constructRadiusPolyhedron(Atom atom, AtomIndexIterator 
iter) {
     int otherAtomCount = 0;
-    nBondsRef = 0;
     distanceRef = radius;
     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)
@@ -579,62 +579,64 @@
   }
 
   private Polyhedron validatePolyhedron(Atom centralAtom, int vertexCount,
-                                        P3[] otherAtoms) {
+                                        P3[] points) {
+    boolean collapsed = isCollapsed;
+    boolean checkDist = (distanceRef != 0);
     int planeCount = 0;
-    int iCenter = vertexCount;
-    int nPoints = iCenter + 1;
-    float distMax = 0;
-    float dAverage = 0;
+    int nPoints = vertexCount + 1;
+    int ni = vertexCount - 2;
+    int nj = vertexCount - 1;
     float planarParam = (Float.isNaN(this.planarParam) ? DEFAULT_PLANAR_PARAM
         : this.planarParam);
-    P3[] points = new P3[MAX_VERTICES * 3];
-    points[iCenter] = otherAtoms[iCenter] = centralAtom;
-    for (int i = 0; i < iCenter; i++) {
-      points[i] = otherAtoms[i];
-      dAverage += points[iCenter].distance(points[i]);
-    }
-    dAverage = dAverage / iCenter;
-    boolean isOK = (dAverage == 0);
-    int nRef = iCenter;
-    int nother1 = iCenter - 1;
-    int nother2 = iCenter - 2;
     float factor = (!Float.isNaN(distanceFactor) ? distanceFactor
         : DEFAULT_DISTANCE_FACTOR);
-    BS bs = BS.newN(iCenter);
+    BS bs = BS.newN(vertexCount);
 
     // here we are assuring that at least ONE face is drawn to 
-    // all matching vertices
+    // all matching vertices -- skip this for BOND polyhedra
 
-    while (!isOK && factor < 10.0f) {
-      distMax = dAverage * factor;
-      bs.setBits(0, iCenter);
-      for (int i = 0; i < nother2; i++)
-        for (int j = i + 1; j < nother1; j++) {
-          if (points[i].distance(points[j]) > distMax)
-            continue;
-          for (int k = j + 1; k < iCenter; k++) {
-            if (points[i].distance(points[k]) > distMax
-                || points[j].distance(points[k]) > distMax)
+    points[vertexCount] = centralAtom;
+    P3 ptAve = new P3();
+    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;
-            bs.clear(i);
-            bs.clear(j);
-            bs.clear(k);
+            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 < iCenter; i++)
-        if (bs.get(i)) {
-          isOK = false;
-          factor *= 1.05f;
-          if (Logger.debugging) {
-            Logger.debug("Polyhedra distanceFactor for " + iCenter
-                + " atoms increased to " + factor + " in order to include "
-                + otherAtoms[i]);
+        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;
           }
-          break;
-        }
+      }
     }
-
     /*  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 
@@ -652,53 +654,40 @@
      *  For these special cases, then, we define a reference point just behind 
the plane
      */
 
-    // produce face-centered catalog and facet-aligned catalog
-    String facesThroughCenter = "";
-    String ignoreFlat = "";
-    P3 ptRef = P3.newP(points[iCenter]);
-    for (int i = 0; i < nother2; i++)
-      for (int j = i + 1; j < nother1; j++)
-        for (int k = j + 1; k < iCenter; k++) {
-          if (isPlanar(points[i], points[j], points[k], ptRef)) {
-            facesThroughCenter += faceId(i, j, k);
-            if (isAligned(points[i], points[j], ptRef))
-              ignoreFlat += faceId(i, j, -1);
-            if (isAligned(points[j], points[k], ptRef))
-              ignoreFlat += faceId(j, k, -1);
-            if (isAligned(points[i], points[k], ptRef))
-              ignoreFlat += faceId(i, k, -1);
-          }
-        }
-    ptRef = new P3();
+    P3 ptRef = P3.newP(ptAve);
+    BS bsThroughCenter = new BS();
+    for (int pt = 0, i = 0; i < ni; i++)
+      for (int j = i + 1; j < nj; j++)
+        for (int k = j + 1; k < vertexCount; k++, pt++)
+          if (isPlanar(points[i], points[j], points[k], ptRef))
+            bsThroughCenter.set(pt);
     // this next check for distance allows for bond AND distance constraints
-    int[][] p = planesT;
+    int[][] faces = planesT;
     P4 pTemp = new P4();
     V3 nTemp = new V3();
     float offset = faceCenterOffset;
     int fmax = FACE_COUNT_MAX;
     int vmax = MAX_VERTICES;
-    P3 rpt = randomPoint;
     BS bsTemp = Normix.newVertexBitSet();
     BS bsTemp1 = new BS();
     V3[] normals = normalsT;
     Map<Object, Object> htNormMap = new Hashtable<Object, Object>();
-    BS bsFlat = new BS();
-    String facet;
+    BS bsCenterPlanes = new BS();
     V3 vTemp = vAC;
-    boolean isComplex = (iCenter >= 5);
-    boolean doAllowFlat = !isComplex && !useUnitCell;
-    boolean collapsed = isCollapsed;
-    for (int i = 0; i < nother2; i++)
-      for (int j = i + 1; j < nother1; j++) {
-        if (points[i].distance(points[j]) > distMax)
+    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 < iCenter; k++) {
-          if (points[i].distance(points[k]) > distMax
-              || points[j].distance(points[k]) > distMax)
+        }
+        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) {
             Logger.error("Polyhedron error: maximum face(" + fmax
-                + ") -- reduce RADIUS or DISTANCEFACTOR");
+                + ") -- reduce RADIUS");
             return null;
           }
           if (nPoints >= vmax) {
@@ -706,108 +695,76 @@
                 + ") -- reduce RADIUS");
             return null;
           }
-          boolean isFlat = (facesThroughCenter.indexOf(faceId(i, j, k)) >= 0);
-          if (isFlat && !doAllowFlat)
+          boolean isThroughCenter = bsThroughCenter.get(pt);
+          P3 rpt = (isThroughCenter ? randomPoint : ptAve);
+          V3 normal = new V3();
+          boolean isWindingOK = getNormalFromCenter(rpt, points[i], points[j],
+              points[k], !isThroughCenter, normal);
+          // the standard face:
+          normals[planeCount] = normal;
+          faces[planeCount] = new int[] { isWindingOK ? i : j, isWindingOK ? j 
: i,
+              k, -7 };
+          if (!checkFace(points, vertexCount, faces, normals, planeCount, 
pTemp, nTemp,
+              vTemp, htNormMap, planarParam, bsTemp, bsTemp1))
             continue;
-          // if center is on the face, then we need an arbitrary reference 
point to 
-          // define the normal
-          boolean isSpecial = collapsed;
-          V3 normal = new V3();
-          boolean isWindingOK;
-          if (isFlat) {
-            isWindingOK = getNormalFromCenter(rpt, points[i], points[j],
-                points[k], false, normal);
+          if (isThroughCenter) {
+            bsCenterPlanes.set(planeCount++);
+          } 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);
+            addFacet(k, i, j, ptRef, points, normals, faces, planeCount++, 
nPoints,
+                isWindingOK);
+            addFacet(j, k, i, ptRef, points, normals, faces, planeCount++, 
nPoints,
+                isWindingOK);
+            nPoints++;
           } else {
-            isWindingOK = getNormalFromCenter(points[iCenter], points[i],
-                points[j], points[k], true, normal);
-            // the standard face:
-            p[planeCount] = new int[] { isWindingOK ? i : j,
-                isWindingOK ? j : i, k, -7 };
-            normals[planeCount] = normal;
-            if (isComplex
-                && !checkFace(points, iCenter, p, normals, planeCount, pTemp,
-                    nTemp, vTemp, htNormMap, planarParam, bsTemp, bsTemp1))
-              continue;
-//            System.out.println("draw ID \"d" + faceId(i, j, k) + "\" VECTOR "
-//                + ptRef + " " + normal + "\">" + faceId(i, j, k) + 
isWindingOK
-//                + "\"");
-          }
-          if (!isFlat && !isSpecial) {
             planeCount++;
-            continue;
           }
-          if (isFlat) {
-            ptRef.sub2(points[iCenter], normal);
-            nRef = iCenter;
-          } else {
-            nRef = nPoints;
-            otherAtoms[nPoints] = points[nPoints] = new P3();
-            points[nPoints++].scaleAdd2(offset, normal, points[iCenter]);
-          }
-          // facet i j k
-          if (!collapsed) {
-            facet = faceId(i, j, -1);
-            isSpecial = (ignoreFlat.indexOf(facet) < 0);
-            if (isSpecial) {
-              ignoreFlat += facet;
-              bsFlat.set(planeCount);
-            }
-          }
-          if (isSpecial) {
-            p[planeCount] = new int[] { isWindingOK ? i : j,
-                isWindingOK ? j : i, nRef, isFlat ? -15 : -6 };
-            getNormalFromCenter(points[k], points[i], points[j], ptRef, false,
-                normal);
-            normals[planeCount++] = normal;
-          }
-          // facet i k j
-          if (!collapsed) {
-            facet = faceId(i, k, -1);
-            isSpecial = (ignoreFlat.indexOf(facet) < 0);
-            if (isSpecial) {
-              ignoreFlat += facet;
-              bsFlat.set(planeCount);
-            }
-          }
-          if (isSpecial) {
-            p[planeCount] = new int[] { isWindingOK ? i : k, nRef,
-                isWindingOK ? k : i, isFlat ? -15 : -5 };
-            getNormalFromCenter(points[j], points[i], ptRef, points[k], false,
-                normal);
-            normals[planeCount++] = normal;
-          }
-          // face j k i
-          if (!collapsed) {
-            facet = faceId(j, k, -1);
-            isSpecial = (ignoreFlat.indexOf(facet) < 0);
-            if (isSpecial) {
-              ignoreFlat += facet;
-              bsFlat.set(planeCount);
-            }
-          }
-          if (isSpecial) {
-            p[planeCount] = new int[] { nRef, isWindingOK ? j : k,
-                isWindingOK ? k : j, isFlat ? -15 : -4 };
-            getNormalFromCenter(points[i], ptRef, points[j], points[k], false,
-                normal);
-            normals[planeCount++] = normal;
-          }
         }
       }
     nPoints--;
-
     if (Logger.debugging) {
       Logger
           .info("Polyhedron planeCount=" + planeCount + " nPoints=" + nPoints);
       for (int i = 0; i < planeCount; i++)
-        Logger.info("Polyhedron " + getKey(p[i], i));
+        Logger.info("Polyhedron " + PT.toJSON("face[" +i + "]", faces[i]));
     }
-    return new Polyhedron().set(centralAtom, iCenter, nPoints, planeCount,
-        otherAtoms, normals, bsFlat, p, collapsed, distanceRef);
+    return new Polyhedron().set(centralAtom, points, nPoints, vertexCount,
+        faces, planeCount, 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.
    * 
+   * @param i
+   * @param j
+   * @param k
+   * @param ptRef slightly out from the center; based on centerOffset parameter
+   * @param points
+   * @param normals
+   * @param faces
+   * @param planeCount
+   * @param nRef
+   * @param isWindingOK
+   */
+  private void addFacet(int i, int j, int k, P3 ptRef, P3[] points,
+                        V3[] normals, int[][] faces, int planeCount, int nRef,
+                        boolean isWindingOK) {
+    V3 normal = new V3();
+    getNormalFromCenter(points[k], ptRef, points[i], points[j], false, normal);
+    normals[planeCount] = normal;
+    faces[planeCount] = new int[] { nRef, isWindingOK ? i : j, isWindingOK ? j 
: i,
+        -2 };
+    //            System.out.println("draw ID \"d" + faceId(i, j, k) + "\" 
VECTOR "
+    //              + ptRef + " " + normal + " color blue \">" + faceId(i, j, 
k) + isWindingOK
+    //            + "\"");
+  }
+
+  /**
+   * 
    * @param ptCenter
    * @param ptA
    * @param ptB
@@ -828,43 +785,38 @@
   }
 
   /**
-   * Clean out oeverlapping triangles based on normals and cross products. 
-   * For now, we use normixes, which are approximations of normals. 
-   * It is not 100% guaranteed that this will work.
+   * Clean out overlapping triangles based on normals and cross products. For
+   * now, we use normixes, which are approximations of normals. It is not 100%
+   * guaranteed that this will work.
    * 
    * @param points
-   * @param ptCenter
+   * @param nPoints
    * @param planes
    * @param normals
    * @param index
    * @param pTemp
    * @param vNorm
+   * @param vTemp
    * @param htNormMap
    * @param planarParam
    * @param bsTemp
+   * @param bsPts
    * @return true if valid
    */
-  private boolean checkFace(P3[] points, int ptCenter, int[][] planes,
-                             V3[] normals, int index, P4 pTemp, V3 vNorm, V3 
vTemp,
-                             Map<Object, Object> htNormMap, float planarParam,
-                             BS bsTemp, BS bsPts) {
+  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) {
     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);
-    //    P3 ptest = P3.newP(points[p1[0]]);
-    //    ptest.add(points[p1[1]]);
-    //    ptest.add(points[p1[2]]);
-    //    ptest.scale(1/3f);
-    //    System.out.println("$draw ID p" + index +" vector " + ptest  + 
vNorm);
-
     // See if all vertices are OUTSIDE the the plane we are considering.      
-    for (int j = 0; j < ptCenter; j++) {
+    for (int j = 0; j < nPoints; j++) {
       vTemp.sub2(points[p1[0]], points[j]);
       float v = vTemp.dot(vNorm);
-      if (v < -0.1) {
-        //System.out.println("$draw ID p" + index + "_" + j + points[j]); 
+      if (v < -0.15) {
         return false;
       }
     }
@@ -877,14 +829,14 @@
       for (Entry<Object, Object> e : htNormMap.entrySet()) {
         Object ikey = e.getKey();
         if (ikey instanceof Integer) {
-          Integer n = (Integer)ikey;
+          Integer n = (Integer) ikey;
           if (norms[n.intValue()].dot(norm) > planarParam) {
             normix = n;
             break;
           }
         }
       }
-      htNormMap.put(normix,  Boolean.TRUE);    
+      htNormMap.put(normix, Boolean.TRUE);
     }
     bsPts.clearAll();
     for (int i = 0; i < 3; i++)
@@ -894,13 +846,13 @@
   }
 
   /**
-   * Check each edge to see that 
+   * Check each edge to see that
    * 
    * (a) it has not been used before
    * 
    * (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 
+   * (c) if it runs opposite another edge, then both edge masks are set 
properly
    * 
    * @param htNormMap
    * @param normix
@@ -921,7 +873,6 @@
     String edge = normix + s + s1;
     if (htNormMap.containsKey(edge))
       return false;
-//    System.out.println(edge);
     //reverse maps are in
     String edge0 = normix + s1 + s;
     Object o = htNormMap.get(edge0);
@@ -956,36 +907,11 @@
     return true;
   }
 
-  private String getKey(int[] p1, int index) {
-    SB sb = new SB();
-    for (int i = 0, n = p1.length; i < n; i++)
-      if (p1[i] >= 0)
-        sb.append("_").appendI(p1[i]);
-    sb.append("_").appendI(p1[0]);
-    sb.append("_,").appendI(index).append(";");
-    return sb.toString();
-  }
-
-  private String faceId(int i, int j, int k) {
-    return "[" + i + "," + j + "," + k + "]";
-  }
-
-  private V3 align1 = new V3();
-  private V3 align2 = new V3();
-
-  private boolean isAligned(P3 pt1, P3 pt2, P3 pt3) {
-    align1.sub2(pt1, pt3);
-    align2.sub2(pt2, pt3);
-    float angle = align1.angle(align2);
-    return (angle < 0.01f || angle > 3.13f);
-  }
-
   private final V3 vAB = new V3();
   private final V3 vAC = new V3();
   private final V3 vBC = new V3();
-  
 
-  private static float minDistanceForPlanarity = 0.1f;
+  private static float MAX_DISTANCE_TO_PLANE = 0.1f;
 
   private boolean isPlanar(P3 pt1, P3 pt2, P3 pt3, P3 ptX) {
     /*
@@ -997,7 +923,7 @@
     V3 norm = new V3();
     float w = Measure.getNormalThroughPoints(pt1, pt2, pt3, norm, vAB);
     float d = Measure.distanceToPlaneV(norm, w, ptX);
-    return (Math.abs(d) < minDistanceForPlanarity);
+    return (Math.abs(d) < MAX_DISTANCE_TO_PLANE);
   }
 
   @Override
@@ -1011,7 +937,7 @@
       Polyhedron p = polyhedrons[i];
       if (ms.at[p.centralAtom.i].isDeleted())
         p.isValid = false;
-      p.visibilityFlags = (p.visible && bsModels.get(p.modelIndex)
+      p.visibilityFlags = (p.visible && bsModels.get(p.centralAtom.mi)
           && !ms.isAtomHidden(p.centralAtom.i)
           && !ms.at[p.centralAtom.i].isDeleted() ? vf : 0);
       if (p.visibilityFlags != 0)

Modified: trunk/Jmol/src/org/jmol/shapespecial/Polyhedron.java
===================================================================
--- trunk/Jmol/src/org/jmol/shapespecial/Polyhedron.java        2015-09-05 
04:19:46 UTC (rev 20756)
+++ trunk/Jmol/src/org/jmol/shapespecial/Polyhedron.java        2015-09-06 
04:09:52 UTC (rev 20757)
@@ -26,16 +26,16 @@
 
 public class Polyhedron {
 
-  int modelIndex;
   public Atom centralAtom;
   public P3[] vertices;
   public int[][] faces;
   int nVertices;
-  boolean collapsed = false;
+  boolean collapsed;
   private BS bsFlat;
-  
+  private float distanceRef;  
   private V3[] normals;
   private short[] normixes;
+
   public String smiles, smarts, stereoSmiles;
   private SymmetryInterface pointGroup;
   private Float volume;
@@ -45,24 +45,22 @@
   public boolean isValid = true;
   public short colixEdge = C.INHERIT_ALL;
   public int visibilityFlags = 0;
-  private float distanceRef;
 
   Polyhedron() {  
   }
   
-  Polyhedron set(Atom centralAtom, int nVertices, int nPoints, int planeCount,
-      P3[] otherAtoms, V3[] normals, BS bsFlat, int[][] planes, boolean 
collapsed, float distanceRef) {
+  Polyhedron set(Atom centralAtom, P3[] points, int nPoints, int vertexCount,
+      int[][] planes, int planeCount, V3[] normals, BS bsFlat, boolean 
collapsed, float distanceRef) {
     this.distanceRef = distanceRef;
     this.centralAtom = centralAtom;
-    modelIndex = centralAtom.mi;
-    this.nVertices = nVertices;
+    this.nVertices = vertexCount;
     this.vertices = new P3[nPoints + 1];
     this.normals = new V3[planeCount];
     this.bsFlat = bsFlat;
     this.faces = AU.newInt2(planeCount);
     for (int i = nPoints + 1; --i >= 0;)
       // includes central atom as last atom or possibly reference point
-      vertices[i] = otherAtoms[i];
+      vertices[i] = points[i];
     for (int i = planeCount; --i >= 0;)
       this.normals[i] = V3.newV(normals[i]);
     for (int i = planeCount; --i >= 0;)
@@ -85,7 +83,6 @@
       info.put("atomNumber", Integer.valueOf(centralAtom.getAtomNumber()));
       info.put("atomName", centralAtom.getInfo());
       info.put("element", centralAtom.getElementSymbol());
-      info.put("vertexCount", Integer.valueOf(nVertices));
       info.put("faceCount", Integer.valueOf(faces.length));
       info.put("volume", getVolume());
       if (smarts != null)
@@ -103,10 +100,15 @@
       info.put("bsFlat", bsFlat);
       if (collapsed)
         info.put("collapsed", Boolean.valueOf(collapsed));
-      info.put("ptRef", vertices[nVertices]);
+      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, nVertices));
+    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++) {
@@ -120,12 +122,25 @@
 
   Polyhedron setInfo(Map<String, SV> info, Atom[] at) {
     try {
+      collapsed = info.containsKey("collapsed");
       centralAtom = at[info.get("atomIndex").intValue];
-      modelIndex = centralAtom.mi;
       Lst<SV> lst = info.get("vertices").getList();
-      vertices = new P3[lst.size() + 1];
-      nVertices = vertices.length - 1;
-      for (int i = nVertices; --i >= 0;)
+      SV vc = info.get("vertexCount");
+      if (vc == null) {
+        // old style
+        nVertices = lst.size();
+        vertices = new P3[nVertices + 1];
+        vertices[nVertices] = SV.ptValue(info.get("ptRef"));
+      } else {
+        nVertices = vc.intValue;
+        vertices = new P3[lst.size()];
+        vc = info.get("distanceRef");
+        if (vc != null)
+          distanceRef = vc.asFloat();
+      }
+      // note that nVertices will be smaller than lst.size()
+      // because lst will contain the central atom and any collapsed points
+      for (int i = lst.size(); --i >= 0;)
         vertices[i] = SV.ptValue(lst.get(i));
       lst = info.get("elemNos").getList();
       for (int i = nVertices; --i >= 0;) {
@@ -137,7 +152,6 @@
           vertices[i] = p;
         }
       }
-      vertices[nVertices] = SV.ptValue(info.get("ptRef"));
       lst = info.get("faces").getList();
       faces = AU.newInt2(lst.size());
       normals = new V3[faces.length];
@@ -153,7 +167,6 @@
             vertices[a[2]], normals[i], vAB);
       }
       bsFlat = SV.getBitSet(info.get("bsFlat"), false);
-      collapsed = info.containsKey("collapsed");
     } catch (Exception e) {
       return null;
     }
@@ -194,13 +207,14 @@
     V3 vAC = new V3();
     V3 vTemp = new V3();
     float v = 0;
-    for (int i = faces.length; --i >= 0;) {
-      int[] face = faces[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,
-              vTemp);
-    }
+    if (bsFlat.cardinality() < faces.length)
+      for (int i = faces.length; --i >= 0;) {
+        int[] face = faces[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,
+                vTemp);
+      }
     return Float.valueOf(v / 6);
   }
 
@@ -214,7 +228,7 @@
   }
 
   String getState(Viewer vwr) {
-    return "  var p = " + Escape.e(getInfo(vwr, false)) + ";polyhedron @p" 
+    return "polyhedron @" + Escape.e(getInfo(vwr, false)) 
         + (isFullyLit ? " fullyLit" : "") + ";"
         + (visible ? "" : "polyhedra ({"+centralAtom.i+"}) off;") + "\n";
   }

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2015-09-05 04:19:46 UTC 
(rev 20756)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2015-09-06 04:09:52 UTC 
(rev 20757)
@@ -59,8 +59,24 @@
 TODO: image off  stops JSmol
 TODO: Rolf's errors in Safari due to move + zoomto
 
-Jmol.___JmolVersion="14.3.16_2015.09.04"
+Jmol.___JmolVersion="14.3.16_2015.09.05"
 
+new feature: POLYHEDRA
+  -- same as POLYHEDRA BONDS {selected}
+new feature: POLYHEDRA 4
+  -- same as POLYHEDRA 4 BONDS {selected}  
+new feature: POLYHEDRA OFFSET 1.4
+  -- same as POLYHEDRA COLLAPSED faceCenterOffset 1.4
+new feature: POLYHEDRA COLLAPSED 1.4
+  -- same as POLYHEDRA COLLAPSED faceCenterOffset 1.4
+
+code: Polyhedra work, including more efficient algorithms for completing set 
of faces
+
+bug fix: tracking down thread-safe issue in application console
+bug fix: in Java, mouse should not lose control if moved out of application
+
+JmolVersion="14.3.16_2015.09.04"
+
 bug fix: Mac OS does not add modifiers (left, right, ctrl, etc.) to drag 
operations
 
 

Modified: 
trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/AppConsole.java
===================================================================
--- trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/AppConsole.java   
2015-09-05 04:19:46 UTC (rev 20756)
+++ trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/AppConsole.java   
2015-09-06 04:09:52 UTC (rev 20757)
@@ -28,6 +28,7 @@
 import java.awt.Component;
 import java.awt.Container;
 import java.awt.Dimension;
+import java.awt.EventQueue;
 import java.awt.Font;
 import java.awt.Rectangle;
 import java.awt.Window;
@@ -777,7 +778,16 @@
                   : 1) : vwr.getSetHistory(up ? -1
           : 1));
       if (cmd == null) {
-        hBar.setValue(0);
+        EventQueue.invokeLater(new Runnable() {
+          @Override
+          public void run() {
+            try {
+              hBar.setValue(0);
+            } catch (Throwable e) {
+              //
+            }
+          }
+        });
         return;
       }
       boolean isError = false;
@@ -914,16 +924,20 @@
 
         pt = caretPosition.getOffset();
         consoleTextPane.setCaretPosition(pt);
-        try {
-          vBar.setValue(vBar.getMaximum());
-        } catch (Throwable e) {
-          //
-        }
-        
       } catch (Exception e) {
         e.printStackTrace();
         consoleTextPane.setCaretPosition(getLength());
       }
+      EventQueue.invokeLater(new Runnable() {
+        @Override
+        public void run() {
+          try {
+            vBar.setValue(vBar.getMaximum());
+          } catch (Throwable e) {
+            //
+          }
+        }
+      });
     }
 
     void outputError(String strError) {

Modified: 
trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/ConsoleTextArea.java
===================================================================
--- 
trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/ConsoleTextArea.java  
    2015-09-05 04:19:46 UTC (rev 20756)
+++ 
trunk/Jmol/src/org/openscience/jmol/app/jmolpanel/console/ConsoleTextArea.java  
    2015-09-06 04:09:52 UTC (rev 20757)
@@ -29,10 +29,8 @@
 import java.io.InputStreamReader;
 import java.io.PrintStream;
 
-import javax.swing.JOptionPane;
 import javax.swing.JTextArea;
 
-import org.jmol.i18n.GT;
 import org.openscience.jmol.app.jmolpanel.LoopedStreams;
 
 public class ConsoleTextArea extends JTextArea {
@@ -50,46 +48,35 @@
 
     String redirect = (doRedirect ? System.getProperty("JmolConsole") : 
"false");
     if (redirect == null || redirect.equals("true")) {
-        // Redirect System.out & System.err.
-        
+        // Redirect System.out & System.err.        
         PrintStream ps = new PrintStream(ls.getOutputStream());
         System.setOut(ps);
         System.setErr(ps);
     }
-
     startConsoleReaderThread(ls.getInputStream());
   }    // ConsoleTextArea()
 
 
   private void startConsoleReaderThread(InputStream inStream) {
 
-    final BufferedReader br =
-      new BufferedReader(new InputStreamReader(inStream));
+    final BufferedReader br = new BufferedReader(new 
InputStreamReader(inStream));
     new Thread(new Runnable() {
-
-      
       @Override
       public void run() {
         Thread.currentThread().setName("ConsoleReaderThread");
-        StringBuilder sb = new StringBuilder();
         try {
           String s;
           //Document doc = getDocument();
-          s = br.readLine();
-          while (s != null) {
+          while ((s = br.readLine()) != null) {
             //boolean caretAtEnd = false;
             //caretAtEnd = (getCaretPosition() == doc.getLength());
-            sb.setLength(0);
-            append(sb.append(s).append('\n').toString());
+            append(s + "\n");
             //if (caretAtEnd) {
               //setCaretPosition(doc.getLength());
            //}
-            s = br.readLine();
           }
-        } catch (IOException e) {
-          JOptionPane.showMessageDialog(null, GT.o(GT._(
-              "Error reading from BufferedReader: {0}"), e.getMessage()));
-          System.exit(1);
+        } catch (Exception e) {
+          //
         }
       }
     }).start();

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