Revision: 21451 http://sourceforge.net/p/jmol/code/21451 Author: hansonr Date: 2017-03-25 19:37:24 +0000 (Sat, 25 Mar 2017) Log Message: ----------- Jmol.___JmolVersion="14.10.0" // released 3/25/2017
new feature: x = {*}.find(smartsString,"map") -- returns an array of arrays of atom indices (0-based) -- indicates exact correlation between atoms in {*} and atoms of smartsString -- only unique sets of atoms are found, not every possibility -- for example: load $caffeine print {*}.find("*1*****1", "map").format("JSON") [ [ 0,2,4,6,11,12 ] ] new feature: SELECT @x where x is an array of integers or array of array of integers -- selects atoms from array rather than from a bitset -- note that variable must be used, as SELECT [1,2,3] would look for PDB group "1,2,3" -- for example: load $caffeine x = {*}.find("*1*****1", "map")[0] select @x 6 atoms selected new feature: DRAW polyhedron @faces @points -- draws sets of polygons based on arrays of atom indices -- @faces is an array of array of integers, not necessarily wound correctly -- @points is an atom bitset or an array of points (optional, defaults to {*} -- for example: load $caffeine draw polyhedra @{{*}.find("*1****1||*1*****1","map")} new feature: POLYHEDRON ID xxx @faces @points -- @faces is an array of array of integers, not necessarily wound correctly -- @points is an atom bitset or an array of points (optional, defaults to {*} new feature: 4-order bond in MOL file using 14 for bond order -- Jmol extension for MOL file format to allow 4-bond -- example: [Re2Cl8](2-) -- see https://en.wikipedia.org/wiki/Quadruple_bond new feature: 5-order bond in MOL file using 15 for bond order -- Jmol extension for MOL file format to allow 5-bond -- example: [Mo2Cl8](4-) -- see https://en.wikipedia.org/wiki/Quintuple_bond new feature: 6-order bond in MOL file using 16 for bond order -- Jmol extension for MOL file format to allow 6-bond -- example: Mo2 -- see https://en.wikipedia.org/wiki/Sextuple_bond bug fix: DSSR fix for multi-model PDB file bug fix: EXIT command with -n command line flag does not exit Jmol bug fix: echo renderer may not show correct font size bug fix: POLYHEDRA ID id OFFSET {x y z} broken bug fix: ScriptManager debug output being sent even if -i (silent) command line option set. Modified Paths: -------------- trunk/Jmol/src/org/jmol/scriptext/CmdExt.java trunk/Jmol/src/org/jmol/scriptext/IsoExt.java trunk/Jmol/src/org/jmol/scriptext/ScriptExt.java trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties Modified: trunk/Jmol/src/org/jmol/scriptext/CmdExt.java =================================================================== --- trunk/Jmol/src/org/jmol/scriptext/CmdExt.java 2017-03-25 16:29:28 UTC (rev 21450) +++ trunk/Jmol/src/org/jmol/scriptext/CmdExt.java 2017-03-25 19:37:24 UTC (rev 21451) @@ -3238,6 +3238,8 @@ P3 offset = null; String id = null; boolean ok = false; + int[][] faces = null; + P3[] points = null; for (int i = 1; i < slen; ++i) { String propertyName = null; Object propertyValue = null; @@ -3249,7 +3251,8 @@ break; case T.point: propertyName = "points"; - propertyValue = Float.valueOf(tokAt(++i) == T.off ? 0 : e.floatParameter(i)); + propertyValue = Float.valueOf(tokAt(++i) == T.off ? 0 : e + .floatParameter(i)); ok = true; break; case T.scale: @@ -3276,6 +3279,18 @@ : eval.theTok == T.on ? "on" : "delete"); onOffDelete = true; break; + case T.varray: + if (id == null || needsGenerating) + invArg(); + needsGenerating = true; + faces = getIntArray2(i); + points = getAllPoints(eval.iToken + 1); + i = eval.iToken; + if (points[0] instanceof Atom) + setShapeProperty(JC.SHAPE_POLYHEDRA, "model", Integer.valueOf(((Atom) points[0]).getModelIndex())); + propertyName = "definedFaces"; + propertyValue = new Object[] { faces, points }; + break; case T.full: propertyName = "full"; break; @@ -3312,7 +3327,8 @@ if (nAtomSets > 0) invPO(); propertyName = (radius <= 0 ? "radius" : "radius1"); - propertyValue = Float.valueOf(radius = (radius == 0 ? 0 : floatParameter(i))); + propertyValue = Float.valueOf(radius = (radius == 0 ? 0 + : floatParameter(i))); needsGenerating = true; break; case T.offset: @@ -5304,5 +5320,4 @@ return data; } - } Modified: trunk/Jmol/src/org/jmol/scriptext/IsoExt.java =================================================================== --- trunk/Jmol/src/org/jmol/scriptext/IsoExt.java 2017-03-25 16:29:28 UTC (rev 21450) +++ trunk/Jmol/src/org/jmol/scriptext/IsoExt.java 2017-03-25 19:37:24 UTC (rev 21451) @@ -438,7 +438,8 @@ case T.polyhedra: case T.point: case T.polygon: - boolean isPoints = (eval.theTok == T.point); + tok = eval.theTok; + boolean isPoints = (tok == T.point); propertyName = "polygon"; havePoints = true; Lst<Object> v = new Lst<Object>(); @@ -447,29 +448,22 @@ P3[] points = null; Lst<SV> vpolygons = null; int[][] polygons = null; - if (eval.isArrayParameter(++i)) { + if (tok == T.polyhedra) { + // draw POLYHEDRA @x @y + // where x is [[0,3,4][4,5,6] ...] where numbers are atom indices + // and optional y is an atom bitset or a list of points + int[][] faces = getIntArray2(++i); + points = getAllPoints(e.iToken + 1); + polygons = ((MeshCapper) Interface.getInterface( + "org.jmol.util.MeshCapper", vwr, "script")).set(null) + .triangulateFaces(faces, points, null); + nVertices = points.length; + } else if (eval.isArrayParameter(++i)) { // draw POLYGON [points] - // draw POLYGON @x where x is [[0,3,4][4,5,6] ...] where numbers are atom indices points = eval.getPointArray(i, -1, true); - if (points.length > 0 && points[0] == null && eval.tokAt(i) == T.varray) { - Lst<SV> list = vwr.evaluateExpressionAsVariable("{*}.xyz.all") - .getList(); - points = new P3[list.size()]; - for (int vi = points.length; --vi >= 0;) - points[vi] = SV.ptValue(list.get(vi)); - list = ((SV) eval.getToken(i)).getList(); - int[][] faces = AU.newInt2(list.size()); - for (int vi = faces.length; --vi >= 0;) { - Lst<SV> face = list.get(vi).getList(); - if (face != null) { - faces[vi] = new int[face.size()]; - for (int vii = faces[vi].length; --vii >= 0;) - faces[vi][vii] = face.get(vii).intValue; - } - } - polygons = ((MeshCapper) Interface.getInterface( - "org.jmol.util.MeshCapper", vwr, "script")).set(null) - .triangulateFaces(faces, points, null); + if (tok == T.polyhedra && points.length > 0 && points[0] == null + && eval.tokAt(i) == T.varray) { + } nVertices = points.length; } else { Modified: trunk/Jmol/src/org/jmol/scriptext/ScriptExt.java =================================================================== --- trunk/Jmol/src/org/jmol/scriptext/ScriptExt.java 2017-03-25 16:29:28 UTC (rev 21450) +++ trunk/Jmol/src/org/jmol/scriptext/ScriptExt.java 2017-03-25 19:37:24 UTC (rev 21451) @@ -1,8 +1,11 @@ package org.jmol.scriptext; +import javajs.util.AU; +import javajs.util.Lst; import javajs.util.P3; import org.jmol.java.BS; +import org.jmol.script.SV; import org.jmol.script.ScriptError; import org.jmol.script.ScriptEval; import org.jmol.script.ScriptException; @@ -168,5 +171,48 @@ } } + protected int[][] getIntArray2(int i) throws ScriptException { + Lst<SV> list = ((SV) e.getToken(i)).getList(); + int[][] faces = AU.newInt2(list.size()); + for (int vi = faces.length; --vi >= 0;) { + Lst<SV> face = list.get(vi).getList(); + if (face != null) { + faces[vi] = new int[face.size()]; + for (int vii = faces[vi].length; --vii >= 0;) + faces[vi][vii] = face.get(vii).intValue; + } + } + return faces; + } + protected P3[] getAllPoints(int index) throws ScriptException { + P3[] points = null; + BS bs = null; + try { + switch (e.tokAt(index)) { + case T.varray: + points = e.getPointArray(index, -1, false); + break; + case T.bitset: + case T.expressionBegin: + bs = atomExpressionAt(index); + break; + } + if (points == null) { + if (bs == null) + bs = vwr.getAllAtoms(); + points = new P3[bs.cardinality()]; + for (int i = bs.nextSetBit(0), pt = 0; i >= 0; i = bs.nextSetBit(i + 1)) + points[pt++] = vwr.ms.at[i]; + } + } catch (Exception e) { + } + if (points.length < 3) + invArg(); + return points; + + } + + + } Modified: trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java =================================================================== --- trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java 2017-03-25 16:29:28 UTC (rev 21450) +++ trunk/Jmol/src/org/jmol/shapespecial/Polyhedra.java 2017-03-25 19:37:24 UTC (rev 21451) @@ -41,6 +41,7 @@ import javajs.util.V3; import org.jmol.api.AtomIndexIterator; +import org.jmol.api.Interface; import org.jmol.api.SmilesMatcherInterface; import org.jmol.api.SymmetryInterface; import org.jmol.c.PAL; @@ -47,6 +48,7 @@ import org.jmol.java.BS; import org.jmol.modelset.Atom; import org.jmol.modelset.Bond; +import org.jmol.modelset.Model; import org.jmol.script.SV; import org.jmol.script.T; import org.jmol.shape.AtomShape; @@ -53,6 +55,7 @@ import org.jmol.util.BSUtil; import org.jmol.util.C; import org.jmol.util.Logger; +import org.jmol.util.MeshCapper; import org.jmol.util.Normix; public class Polyhedra extends AtomShape implements Comparator<Object[]>{ @@ -119,6 +122,7 @@ private float distanceRef; private int modelIndex; private boolean isAuto; + private int[][] explicitFaces; @SuppressWarnings("unchecked") @Override @@ -144,6 +148,10 @@ return; } + if ("definedFaces" == propertyName) { + setDefinedFaces((P3[]) ((Object[]) value)[1], (int[][]) ((Object[]) value)[0]); + return; + } if ("generate" == propertyName) { if (!iHaveCenterBitSet) { centers = bs; @@ -401,6 +409,48 @@ setPropAS(propertyName, value, bs); } + private void setDefinedFaces(P3[] points, int[][] faces) { + BS bsUsed = new BS(); + for (int i = faces.length; --i >= 0;) { + int[] face = faces[i]; + for (int j = face.length; --j >= 0;) + bsUsed.set(face[j]); + } + BS bsNot = BSUtil.newBitSet2(0, bsUsed.length()); + bsNot.andNot(bsUsed); + int nNot = bsNot.cardinality(); + if (nNot > 0) { + int np = points.length; + int[] mapOldToNew = new int[np]; + int[] mapNewToOld = new int[np]; + int n = 0; + for (int i = 0; i < np; i++) + if (!bsNot.get(i)) { + mapNewToOld[n] = i; + mapOldToNew[i] = n++; + } + P3[] pnew = new P3[n]; + for (int i = 0; i < n; i++) + pnew[i] = points[mapNewToOld[i]]; + points = pnew; + for (int i = faces.length; --i >= 0;) { + int[] face = faces[i]; + for (int j = face.length; --j >= 0;) + face[j] = mapOldToNew[face[j]]; + } + } + int n = nPoints = points.length; + center = new P3(); + otherAtoms = new P3[n + 1]; + if (n > 0) { + otherAtoms[n] = center; + for (int i = 0; i < n; i++) + center.add(otherAtoms[i] = points[i]); + center.scale(1f / n); + } + explicitFaces = faces; + } + private void pointsPolyhedra(BS bs, float pointScale) { bs = findPolyBS(thisID == null ? bs : null); for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) @@ -831,126 +881,171 @@ private Polyhedron validatePolyhedron(P3 atomOrPt, int vertexCount) { P3[] points = otherAtoms; + int[][] faces = explicitFaces; + int[][] faceTriangles; + V3[] normals; boolean collapsed = isCollapsed; 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); - points[vertexCount] = atomOrPt; - P3 ptAve = P3.newP(atomOrPt); - for (int i = 0; i < vertexCount; i++) - ptAve.add(points[i]); - 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 - * a "simple" atom near the center but not quite the center, - * so that our planes on either side of the facet don't overlap. - * We step out faceCenterOffset * normal from the center. - * - * Alan Hewat pointed out the issue of faces that CONTAIN the center -- - * square planar, trigonal and square pyramids, see-saw. In these cases with no - * additional work, you get a brilliance effect when two faces are drawn over - * each other. The solution is to identify this sort of face and, if not collapsed, - * to cut them into smaller pieces and only draw them ONCE by producing a little - * catalog. This uses the Point3i().toString() method. - * - * For these special cases, then, we define a reference point just behind the plane - * - * Note that this is NOT AN OPTION for ID-named polyhedra (Jmol 14.5.0 10/31/2015) - */ + BS bsCenterPlanes = new BS(); + int[][] triangles; + if (faces != null) { + collapsed = false; + faceTriangles = AU.newInt2(faces.length); + normals = new V3[faces.length]; + for (int i = faces.length; --i >= 0;) + faces[i] = fixExplicitFaceWinding(faces[i], i, points, normals); + triangles = ((MeshCapper) Interface.getInterface( + "org.jmol.util.MeshCapper", vwr, "script")).set(null) + .triangulateFaces(faces, points, faceTriangles); + triangleCount = triangles.length; + } else { - P3 ptRef = P3.newP(ptAve); - BS bsThroughCenter = new BS(); - if (thisID == null) - 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[][] 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(); - V3[] normals = normalsT; - Map<Integer, Object[]> htNormMap = new Hashtable<Integer, Object[]>(); - Map<String, Object> htEdgeMap = new Hashtable<String, Object>(); - BS bsCenterPlanes = new BS(); - Lst<int[]> lstRejected = (isFull ? new Lst<int[]>() : null); - Object[] edgeTest = new Object[3]; - V3 vAC = this.vAC; - for (int i = 0, pt = 0; i < ni; i++) - for (int j = i + 1; j < nj; j++) { - for (int k = j + 1; k < vertexCount; k++, pt++) { - if (triangleCount >= fmax) { - Logger.error("Polyhedron error: maximum face(" + fmax - + ") -- reduce RADIUS"); - return null; - } - if (nPoints >= vmax) { - Logger.error("Polyhedron error: maximum vertex count(" + vmax - + ") -- reduce RADIUS"); - return null; - } - boolean isThroughCenter = bsThroughCenter.get(pt); - P3 rpt = (isThroughCenter ? randomPoint : ptAve); - V3 normal = new V3(); - boolean isWindingOK = Measure.getNormalFromCenter(rpt, points[i], - points[j], points[k], !isThroughCenter, normal, vAC); - // the standard face: - int[] t = new int[] { isWindingOK ? i : j, isWindingOK ? j : i, k, -7 }; - float err = checkFacet(points, vertexCount, t, triangleCount, normal, pTemp, nTemp, - vAC, htNormMap, htEdgeMap, planarParam, bsTemp, edgeTest); - if (err != 0) { - if (isFull && err != Float.MAX_VALUE && err < 0.5f) { - t[3] = (int) (err * 100); - lstRejected.addLast(t); + int nPoints = vertexCount + 1; + int ni = vertexCount - 2; + int nj = vertexCount - 1; + float planarParam = (Float.isNaN(this.planarParam) ? DEFAULT_PLANAR_PARAM + : this.planarParam); + + points[vertexCount] = atomOrPt; + P3 ptAve = P3.newP(atomOrPt); + for (int i = 0; i < vertexCount; i++) + ptAve.add(points[i]); + 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 + * a "simple" atom near the center but not quite the center, + * so that our planes on either side of the facet don't overlap. + * We step out faceCenterOffset * normal from the center. + * + * Alan Hewat pointed out the issue of faces that CONTAIN the center -- + * square planar, trigonal and square pyramids, see-saw. In these cases with no + * additional work, you get a brilliance effect when two faces are drawn over + * each other. The solution is to identify this sort of face and, if not collapsed, + * to cut them into smaller pieces and only draw them ONCE by producing a little + * catalog. This uses the Point3i().toString() method. + * + * For these special cases, then, we define a reference point just behind the plane + * + * Note that this is NOT AN OPTION for ID-named polyhedra (Jmol 14.5.0 10/31/2015) + */ + + P3 ptRef = P3.newP(ptAve); + BS bsThroughCenter = new BS(); + if (thisID == null) + 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 + 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(); + normals = normalsT; + Map<Integer, Object[]> htNormMap = new Hashtable<Integer, Object[]>(); + Map<String, Object> htEdgeMap = new Hashtable<String, Object>(); + Lst<int[]> lstRejected = (isFull ? new Lst<int[]>() : null); + Object[] edgeTest = new Object[3]; + V3 vAC = this.vAC; + for (int i = 0, pt = 0; i < ni; i++) + for (int j = i + 1; j < nj; j++) { + for (int k = j + 1; k < vertexCount; k++, pt++) { + if (triangleCount >= fmax) { + Logger.error("Polyhedron error: maximum face(" + fmax + + ") -- reduce RADIUS"); + return null; } - continue; + if (nPoints >= vmax) { + Logger.error("Polyhedron error: maximum vertex count(" + vmax + + ") -- reduce RADIUS"); + return null; + } + boolean isThroughCenter = bsThroughCenter.get(pt); + P3 rpt = (isThroughCenter ? randomPoint : ptAve); + V3 normal = new V3(); + boolean isWindingOK = Measure.getNormalFromCenter(rpt, points[i], + points[j], points[k], !isThroughCenter, normal, vAC); + // the standard face: + int[] t = new int[] { isWindingOK ? i : j, isWindingOK ? j : i, k, + -7 }; + float err = checkFacet(points, vertexCount, t, triangleCount, + normal, pTemp, nTemp, vAC, htNormMap, htEdgeMap, planarParam, + bsTemp, edgeTest); + if (err != 0) { + if (isFull && err != Float.MAX_VALUE && err < 0.5f) { + t[3] = (int) (err * 100); + lstRejected.addLast(t); + } + continue; + } + normals[triangleCount] = normal; + triangles[triangleCount] = t; + if (isThroughCenter) { + bsCenterPlanes.set(triangleCount++); + } else if (collapsed) { + points[nPoints] = new P3(); + points[nPoints].scaleAdd2(offset, normal, atomOrPt); + ptRef.setT(points[nPoints]); + 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 { + triangleCount++; + } } - normals[triangleCount] = normal; - triangles[triangleCount] = t; - if (isThroughCenter) { - bsCenterPlanes.set(triangleCount++); - } else if (collapsed) { - points[nPoints] = new P3(); - points[nPoints].scaleAdd2(offset, normal, atomOrPt); - ptRef.setT(points[nPoints]); - 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 { - triangleCount++; - } } + nPoints--; + if (Logger.debugging) { + Logger.info("Polyhedron planeCount=" + triangleCount + " nPoints=" + + nPoints); + for (int i = 0; i < triangleCount; i++) + Logger.info("Polyhedron " + + PT.toJSON("face[" + i + "]", triangles[i])); } - nPoints--; - if (Logger.debugging) { - Logger.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, lstRejected)); + faces = getFaces(triangles, triangleCount, htNormMap); + faceTriangles = getFaceTriangles(faces.length, htNormMap, triangleCount); } - //System.out.println(PT.toJSON(null, lstRejected)); - int[][] faces = getFaces(triangles, triangleCount, htNormMap); - int[][] faceTriangles = getFaceTriangles(faces.length, htNormMap, triangleCount); return new Polyhedron().set(thisID, modelIndex, atomOrPt, points, nPoints, - vertexCount, triangles, triangleCount, - faces, faceTriangles, normals, bsCenterPlanes, - collapsed, distanceRef, pointScale); + vertexCount, triangles, triangleCount, faces, faceTriangles, normals, + bsCenterPlanes, collapsed, distanceRef, pointScale); } - + + /** + * Check to see that the winding of the explicit face is correct. If not, + * correct it. Also set the normals. + * @param face + * @param ipt + * @param points + * @param normals + * @return correctly wound face + */ + private int[] fixExplicitFaceWinding(int[] face, int ipt, P3[] points, V3[] normals) { + int n = face.length; + for (int i = 0, nlast = n - 2; i < nlast; i++) { + P3 a = points[face[i]]; + P3 b = points[face[(i + 1) % n]]; + P3 c = points[face[(i + 2) % n]]; + if (Measure.computeAngleABC(a, b, c, true) < 178) { + // ignore nearly linear angles -- we only need one + if (!Measure.getNormalFromCenter(center, a, b, c, true, normals[ipt] = new V3(), vAC)) + face = AU.arrayCopyRangeRevI(face, 0, -1); + break; + } + } + return face; + } + private int[][] getFaceTriangles(int n, Map<Integer, Object[]> htNormMap, int triangleCount) { int[][] faceTriangles = AU.newInt2(n); if (triangleCount == n) { Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2017-03-25 16:29:28 UTC (rev 21450) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2017-03-25 19:37:24 UTC (rev 21451) @@ -49,7 +49,7 @@ # 10. Run jmol/tools build-release.xml # -Jmol.___JmolVersion="14.10.0-beta-2017-3-25" +Jmol.___JmolVersion="14.10.0" // released 3/25/2017 new feature: x = {*}.find(smartsString,"map") -- returns an array of arrays of atom indices (0-based) @@ -73,12 +73,19 @@ 6 atoms selected -new feature: DRAW polyhedron @x where x is an array of array of integers +new feature: DRAW polyhedron @faces @points -- draws sets of polygons based on arrays of atom indices + -- @faces is an array of array of integers, not necessarily wound correctly + -- @points is an atom bitset or an array of points (optional, defaults to {*} -- for example: load $caffeine draw polyhedra @{{*}.find("*1****1||*1*****1","map")} + +new feature: POLYHEDRON ID xxx @faces @points + -- @faces is an array of array of integers, not necessarily wound correctly + -- @points is an atom bitset or an array of points (optional, defaults to {*} + new feature: 4-order bond in MOL file using 14 for bond order -- Jmol extension for MOL file format to allow 4-bond This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits