1 /* $RCSfile$
2  * $Author: hansonr $
3  * $Date: 2006-03-05 12:22:08 -0600 (Sun, 05 Mar 2006) $
4  * $Revision: 4545 $
5  *
6  * Copyright (C) 2002-2005  The Jmol Development Team
7  *
8  * Contact: jmol-developers@lists.sf.net
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 2.1 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 package org.jmol.scriptext;
26 
27 import java.util.Map;
28 
29 import javajs.util.AU;
30 import javajs.util.Lst;
31 import javajs.util.M4;
32 import javajs.util.P3;
33 import javajs.util.P4;
34 import javajs.util.PT;
35 import javajs.util.Quat;
36 import javajs.util.SB;
37 import javajs.util.T3;
38 import javajs.util.V3;
39 
40 import org.jmol.adapter.readers.quantum.GenNBOReader;
41 import org.jmol.api.Interface;
42 import org.jmol.api.JmolDataManager;
43 import org.jmol.api.SymmetryInterface;
44 import org.jmol.atomdata.RadiusData;
45 import org.jmol.atomdata.RadiusData.EnumType;
46 import org.jmol.c.VDW;
47 import javajs.util.BS;
48 import org.jmol.modelset.Atom;
49 import org.jmol.quantum.MepCalculation;
50 import org.jmol.script.SV;
51 import org.jmol.script.ScriptError;
52 import org.jmol.script.ScriptEval;
53 import org.jmol.script.ScriptException;
54 import org.jmol.script.ScriptInterruption;
55 import org.jmol.script.T;
56 import org.jmol.shape.MeshCollection;
57 import org.jmol.util.BSUtil;
58 import org.jmol.util.BoxInfo;
59 import org.jmol.util.C;
60 import org.jmol.util.ColorEncoder;
61 import org.jmol.util.Escape;
62 import org.jmol.util.Logger;
63 import org.jmol.util.MeshCapper;
64 import org.jmol.util.Parser;
65 import org.jmol.util.SimpleUnitCell;
66 import org.jmol.util.TempArray;
67 import org.jmol.util.Triangulator;
68 import org.jmol.viewer.JC;
69 import org.jmol.viewer.JmolAsyncException;
70 
71 public class IsoExt extends ScriptExt {
72 
IsoExt()73   public IsoExt() {
74     // used by Reflection
75   }
76 
77   @Override
dispatch(int iTok, boolean b, T[] st)78   public String dispatch(int iTok, boolean b, T[] st) throws ScriptException {
79     chk = e.chk;
80     slen = e.slen;
81     this.st = st;
82 
83     switch (iTok) {
84     case JC.SHAPE_CGO:
85       cgo();
86       break;
87     case JC.SHAPE_CONTACT:
88       contact();
89       break;
90     case JC.SHAPE_DIPOLES:
91       dipole();
92       break;
93     case JC.SHAPE_DRAW:
94       draw();
95       break;
96     case JC.SHAPE_ISOSURFACE:
97     case JC.SHAPE_PLOT3D:
98     case JC.SHAPE_PMESH:
99       isosurface(iTok);
100       break;
101     case JC.SHAPE_LCAOCARTOON:
102       lcaoCartoon();
103       break;
104     case JC.SHAPE_MO:
105     case JC.SHAPE_NBO:
106       mo(b, iTok);
107       break;
108     }
109     return null;
110   }
111 
dipole()112   private void dipole() throws ScriptException {
113     ScriptEval eval = e;
114     // dipole intWidth floatMagnitude OFFSET floatOffset {atom1} {atom2}
115     String propertyName = null;
116     Object propertyValue = null;
117     boolean iHaveAtoms = false;
118     boolean iHaveCoord = false;
119     boolean idSeen = false;
120     boolean getCharges = false;
121     BS bsSelected = null;
122 
123     eval.sm.loadShape(JC.SHAPE_DIPOLES);
124     if (tokAt(1) == T.list && listIsosurface(JC.SHAPE_DIPOLES))
125       return;
126     setShapeProperty(JC.SHAPE_DIPOLES, "init", null);
127     if (slen == 1) {
128       setShapeProperty(JC.SHAPE_DIPOLES, "thisID", null);
129       return;
130     }
131     for (int i = 1; i < slen; ++i) {
132       propertyName = null;
133       propertyValue = null;
134       switch (getToken(i).tok) {
135       case T.all:
136         propertyName = "all";
137         getCharges = true;
138         break;
139       case T.on:
140         propertyName = "on";
141         break;
142       case T.off:
143         propertyName = "off";
144         break;
145       case T.delete:
146         propertyName = "delete";
147         break;
148       case T.integer:
149       case T.decimal:
150         propertyName = "value";
151         propertyValue = Float.valueOf(floatParameter(i));
152         break;
153       case T.bitset:
154         if (tokAt(i + 1) == T.bitset) {
155           // fix for atomno2 < atomno1
156           setShapeProperty(JC.SHAPE_DIPOLES, "startSet", atomExpressionAt(i++));
157         } else {
158           // early Jmol
159           propertyName = "atomBitset";
160         }
161         //$FALL-THROUGH$
162       case T.expressionBegin:
163         if (propertyName == null)
164           propertyName = (iHaveAtoms || iHaveCoord ? "endSet" : "startSet");
165         propertyValue = bsSelected = atomExpressionAt(i);
166         i = eval.iToken;
167         if (tokAt(i + 1) == T.nada && propertyName == "startSet")
168           propertyName = "atomBitset";
169         iHaveAtoms = true;
170         getCharges = true;
171         break;
172       case T.leftbrace:
173       case T.point3f:
174         // {X, Y, Z}
175         P3 pt = getPoint3f(i, true);
176         i = eval.iToken;
177         propertyName = (iHaveAtoms || iHaveCoord ? "endCoord" : "startCoord");
178         propertyValue = pt;
179         iHaveCoord = true;
180         break;
181       case T.bonds:
182         propertyName = "bonds";
183         getCharges = true;
184         break;
185       case T.calculate:
186         getCharges = true;
187         propertyName = "calculate";
188         if (eval.isAtomExpression(i + 1)) {
189           propertyValue = bsSelected = atomExpressionAt(++i);
190           i = eval.iToken;
191         }
192         break;
193       case T.id:
194         setShapeId(JC.SHAPE_DIPOLES, ++i, idSeen);
195         i = eval.iToken;
196         break;
197       case T.cross:
198         propertyName = "cross";
199         propertyValue = Boolean.TRUE;
200         break;
201       case T.nocross:
202         propertyName = "cross";
203         propertyValue = Boolean.FALSE;
204         break;
205       case T.offset:
206         if (isFloatParameter(i + 1)) {
207           float v = floatParameter(++i);
208           if (eval.theTok == T.integer) {
209             propertyName = "offsetPercent";
210             propertyValue = Integer.valueOf((int) v);
211           } else {
212             propertyName = "offset";
213             propertyValue = Float.valueOf(v);
214           }
215         } else {
216           propertyName = "offsetPt";
217           propertyValue = centerParameter(++i);
218           i = eval.iToken;
219         }
220         break;
221       case T.offsetside:
222         propertyName = "offsetSide";
223         propertyValue = Float.valueOf(floatParameter(++i));
224         break;
225       case T.val:
226         propertyName = "value";
227         propertyValue = Float.valueOf(floatParameter(++i));
228         break;
229       case T.width:
230         propertyName = "width";
231         propertyValue = Float.valueOf(floatParameter(++i));
232         break;
233       default:
234         if (eval.theTok == T.times || T.tokAttr(eval.theTok, T.identifier)) {
235           setShapeId(JC.SHAPE_DIPOLES, i, idSeen);
236           i = eval.iToken;
237           break;
238         }
239         invArg();
240       }
241       idSeen = (eval.theTok != T.delete && eval.theTok != T.calculate);
242       if (getCharges) {
243         // ensures that we do have charges and catch the Script interruption if asynchronous
244         if (!chk)
245           eval.getPartialCharges(bsSelected);
246         getCharges = false;
247       }
248       if (propertyName != null)
249         setShapeProperty(JC.SHAPE_DIPOLES, propertyName, propertyValue);
250     }
251     if (iHaveCoord || iHaveAtoms)
252       setShapeProperty(JC.SHAPE_DIPOLES, "set", null);
253   }
254 
draw()255   private void draw() throws ScriptException {
256     ScriptEval eval = e;
257     eval.sm.loadShape(JC.SHAPE_DRAW);
258     switch (tokAt(1)) {
259     case T.list:
260       if (listIsosurface(JC.SHAPE_DRAW))
261         return;
262       break;
263     case T.helix:
264     case T.quaternion:
265     case T.ramachandran:
266       e.getCmdExt().dispatch(T.plot, false, st);
267       return;
268     }
269     boolean havePoints = false;
270     boolean isInitialized = false;
271     boolean isSavedState = false;
272     boolean isIntersect = false;
273     boolean isFrame = false;
274     P4 plane;
275     int tokIntersect = 0;
276     float translucentLevel = Float.MAX_VALUE;
277     int[] colorArgb = new int[] { Integer.MIN_VALUE };
278     int intScale = 0;
279     String swidth = "";
280     int iptDisplayProperty = 0;
281     P3 center = null;
282     String thisId = initIsosurface(JC.SHAPE_DRAW);
283     boolean idSeen = (thisId != null);
284     boolean isWild = (idSeen && getShapeProperty(JC.SHAPE_DRAW, "ID") == null);
285     int[] connections = null;
286     int iConnect = 0;
287     int iArray = -1;
288     SymmetryInterface uc = null;
289     for (int i = eval.iToken; i < slen; ++i) {
290       String propertyName = null;
291       Object propertyValue = null;
292       int tok = getToken(i).tok;
293       switch (tok) {
294       case T.pointgroup:
295         // draw pointgroup [array  of points] CENTER xx
296         // draw pointgroup SPACEGROUP
297         // draw pointgroup [C2|C3|Cs|Ci|etc.] [n] [scale x]
298         P3[] pts = (eval.isArrayParameter(++i)
299             ? eval.getPointArray(i, -1, false)
300             : null);
301         if (pts != null) {
302           i = eval.iToken + 1;
303           if (tokAt(i) == T.center) {
304             center = eval.centerParameter(++i, null);
305             i = eval.iToken + 1;
306           }
307         }
308         String type;
309         switch (tokAt(i)) {
310         case T.scale:
311           type = "";
312           break;
313         case T.chemicalshift:
314           type = "Cs";
315           break;
316         case T.dollarsign:
317           Object[] data = new Object[] { eval.objectNameParameter(++i), null };
318           if (chk)
319             return;
320           vwr.shm.getShapePropertyData(JC.SHAPE_POLYHEDRA, "points", data);
321           pts = (P3[]) data[1];
322           if (pts == null)
323             invArg();
324           type = "";
325           break;
326         case T.polyhedra:
327           type = ":poly";
328           break;
329         case T.spacegroup:
330           if (center == null)
331             center = new P3();
332           Lst<P3> crpts = vwr.ms.generateCrystalClass(vwr.bsA().nextSetBit(0),
333               P3.new3(Float.NaN, Float.NaN, Float.NaN));
334           if (pts != null)
335             invArg();
336           pts = new P3[crpts.size()];
337           for (int j = crpts.size(); --j >= 0;)
338             pts[j] = crpts.get(j);
339           i++;
340           type = "";
341           break;
342         default:
343           type = eval.optParameterAsString(i);
344           break;
345         }
346         float scale = (intScale == 0 ? 1 : intScale/100f);
347         int index = 0;
348         if (type.length() > 0) {
349           if (isFloatParameter(++i))
350             index = intParameter(i++);
351         }
352         if (tokAt(i) == T.scale)
353           scale = floatParameter(++i);
354         if (!chk)
355           eval.runScript(vwr.ms.getPointGroupAsString(vwr.bsA(), type, index,
356               scale, pts, center, thisId == null ? "" : thisId));
357         return;
358       case T.unitcell:
359       case T.boundbox:
360         if (chk)
361           break;
362         if (tok == T.boundbox && tokAt(i + 1) == T.best) {
363           tok = T.unitcell;
364         }
365         if (tok == T.unitcell) {
366           if (eval.isArrayParameter(i + 1)) {
367             P3[] oabc = eval.getPointArray(i + 1, -1, false);
368             uc = vwr.getSymTemp().getUnitCell(oabc, false, null);
369             i = eval.iToken;
370           } else if (tokAt(i + 1) == T.best) {
371             i++;
372             uc = vwr.getSymTemp().getUnitCell(
373                 (P3[]) vwr.getOrientationText(T.unitcell, "array", null), false,
374                 null);
375           } else {
376             uc = vwr.getCurrentUnitCell();
377           }
378           if (uc == null)
379             invArg();
380         }
381         Lst<Object> vp = getPlaneIntersection(tok, null, uc, intScale / 100f,
382             0);
383         intScale = 0;
384         propertyName = "polygon";
385         propertyValue = vp;
386         havePoints = true;
387         break;
388       case T.connect:
389         connections = new int[4];
390         iConnect = 4;
391         float[] farray = eval.floatParameterSet(++i, 4, 4);
392         i = eval.iToken;
393         for (int j = 0; j < 4; j++)
394           connections[j] = (int) farray[j];
395         havePoints = true;
396         break;
397       case T.bonds:
398       case T.atoms:
399         if (connections == null
400             || iConnect > (eval.theTok == T.bondcount ? 2 : 3)) {
401           iConnect = 0;
402           connections = new int[] { -1, -1, -1, -1 };
403         }
404         connections[iConnect++] = atomExpressionAt(++i).nextSetBit(0);
405         i = eval.iToken;
406         connections[iConnect++] = (eval.theTok == T.bonds
407             ? atomExpressionAt(++i).nextSetBit(0)
408             : -1);
409         i = eval.iToken;
410         havePoints = true;
411         break;
412       case T.slab:
413         switch (getToken(++i).tok) {
414         case T.dollarsign:
415           propertyName = "slab";
416           propertyValue = eval.objectNameParameter(++i);
417           i = eval.iToken;
418           havePoints = true;
419           break;
420         default:
421           invArg();
422         }
423         break;
424       case T.intersection:
425         switch (getToken(i + 1).tok) {
426         case T.unitcell:
427         case T.boundbox:
428           tokIntersect = eval.theTok;
429           isIntersect = true;
430           continue;
431         case T.dollarsign:
432           propertyName = "intersect";
433           propertyValue = eval.objectNameParameter(++i);
434           i = eval.iToken;
435           isIntersect = true;
436           havePoints = true;
437           break;
438         default:
439           invArg();
440         }
441         break;
442       case T.polyhedra:
443       case T.point:
444       case T.polygon:
445         tok = eval.theTok;
446         boolean isPoints = (tok == T.point);
447         propertyName = "polygon";
448         havePoints = true;
449         Lst<Object> v = new Lst<Object>();
450         int nVertices = 0;
451         int nTriangles = 0;
452         P3[] points = null;
453         Lst<SV> vpolygons = null;
454         int[][] polygons = null;
455         if (eval.isArrayParameter(++i)) {
456           // draw POLYGON [points]
457           points = eval.getPointArray(i, -1, true);
458           if (points.length > 0 && points[0] == null) {
459             int[][] faces;
460             if (tok == T.polyhedra) {
461               faces = getIntArray2(i);
462             } else {
463               faces = AU.newInt2(1);
464               faces[0] = (int[]) eval.expandFloatArray(
465                   eval.floatParameterSet(i, -1, Integer.MAX_VALUE), -1, false);
466             }
467             points = getAllPoints(e.iToken + 1, 3);
468             try {
469               polygons = ((MeshCapper) Interface
470                   .getInterface("org.jmol.util.MeshCapper", vwr, "script"))
471                       .set(null).triangulateFaces(faces, points, null);
472             } catch (Throwable e) {
473               invArg();
474             }
475           }
476           nVertices = points.length;
477         }
478 
479         if (tok == T.polyhedra) {
480           // draw POLYHEDRA @x @y
481           //  where x is [[0,3,4][4,5,6] ...] where numbers are atom indices
482           //  and optional y is an atom bitset or a list of points
483           nVertices = points.length;
484         }
485 
486         if (points == null) {
487           // draw POLYGON nPoints pt1 pt2 pt3...
488           nVertices = Math.max(0, intParameter(i));
489           points = new P3[nVertices];
490           for (int j = 0; j < nVertices; j++)
491             points[j] = centerParameter(++eval.iToken);
492         }
493         i = eval.iToken;
494         switch (tokAt(i + 1)) {
495         case T.matrix3f:
496         case T.matrix4f:
497           // draw POLYGON <points> [[0,1,2],[1,2,3]...]
498           vpolygons = SV.newT(getToken(++i)).toArray().getList();
499           nTriangles = vpolygons.size();
500           break;
501         case T.varray:
502           // draw POLYGON <points> [[0,1,2],[1,2,3]...]
503           vpolygons = ((SV) getToken(++i)).getList();
504           nTriangles = vpolygons.size();
505           break;
506         case T.integer:
507           // draw POLYGON <points> nTriangles
508           nTriangles = intParameter(++i);
509           if (nTriangles < 0)
510             isPoints = true;
511           break;
512         default:
513           // get triangles from a list of points
514           if (polygons == null && !isPoints && !chk)
515             polygons = ((MeshCapper) Interface
516                 .getInterface("org.jmol.util.MeshCapper", vwr, "script"))
517                     .set(null).triangulatePolygon(points, -1);
518         }
519         if (polygons == null && !isPoints) {
520           // read array of arrays of triangle vertex pointers
521           polygons = AU.newInt2(nTriangles);
522           for (int j = 0; j < nTriangles; j++) {
523             float[] f = (vpolygons == null
524                 ? eval.floatParameterSet(++eval.iToken, 3, 4)
525                 : SV.flistValue(vpolygons.get(j), 0));
526             if (f.length < 3 || f.length > 4)
527               invArg();
528             polygons[j] = new int[] { (int) f[0], (int) f[1], (int) f[2],
529                 (f.length == 3 ? 7 : (int) f[3]) };
530           }
531         }
532         if (nVertices > 0) {
533           v.addLast(points);
534           v.addLast(polygons);
535         } else {
536           v = null;
537         }
538         propertyValue = v;
539         i = eval.iToken;
540         break;
541       case T.spacegroup:
542       case T.symop:
543         String xyz = null;
544         int iSym = Integer.MAX_VALUE;
545         plane = null;
546         P3 target = null;
547         BS bsAtoms = null;
548         int options = 0;
549         P3 trans = null;
550         if (tok == T.symop) {
551           iSym = 0;
552           switch (tokAt(++i)) {
553           case T.string:
554             xyz = stringParameter(i);
555             break;
556           case T.matrix4f:
557             xyz = SV.sValue(getToken(i));
558             break;
559           case T.integer:
560           default:
561             if (!eval.isCenterParameter(i)) {
562               iSym = intParameter(i++);
563               if (eval.isArrayParameter(i)) {
564                 trans = P3.newA(eval.floatParameterSet(i, 3, 3));
565                 i = ++eval.iToken;
566               }
567             }
568             Object[] ret = new Object[] { null, vwr.getFrameAtoms() };
569             if (eval.isCenterParameter(i))
570               center = eval.centerParameter(i, ret);
571             if (eval.isCenterParameter(eval.iToken + 1))
572               target = eval.centerParameter(++eval.iToken, ret);
573             if (chk)
574               return;
575             i = eval.iToken;
576           }
577         }
578         if (center == null && i + 1 < slen) {
579           center = centerParameter(++i);
580           // draw ID xxx symop [n or "x,-y,-z"] [optional {center}]
581           // so we also check here for the atom set to get the right model
582           bsAtoms = (eval.isAtomExpression(i) ? atomExpressionAt(i) : null);
583           i = eval.iToken;
584         }
585         int nth = (target != null && tokAt(i + 1) == T.integer
586             ? eval.getToken(++i).intValue
587             : -1);
588         if (tokAt(i + 1) == T.unitcell) {
589           target = new P3();
590           options = T.offset;
591           i++;
592           eval.iToken = i;
593         } else if (tokAt(i + 1) == T.offset) {
594           i++;
595           target = getPoint3f(i + 1, false);
596           options = T.offset;
597           i = eval.iToken;
598         }
599 
600         eval.checkLast(eval.iToken);
601         if (!chk) {
602           String s = "";
603           if (bsAtoms == null && vwr.am.cmi >= 0)
604             bsAtoms = vwr.getModelUndeletedAtomsBitSet(vwr.am.cmi);
605           if (bsAtoms != null) {
606             s = null;
607             int iatom = bsAtoms.nextSetBit(0);
608             if (options != 0) {
609               // options is T.offset, and target is an {i j k} offset from cell 555
610               Object o = vwr.getSymmetryInfo(iatom, xyz, iSym, trans, center,
611                   target, T.point, null, intScale / 100f, nth, options);
612               if (o instanceof P3)
613                 target = (P3) o;
614               else
615                 s = "";
616             }
617             if (thisId == null)
618               thisId = "sym";
619             if (s == null)
620               s = (String) vwr.getSymmetryInfo(iatom, xyz, iSym, trans, center,
621                   target, T.draw, thisId, intScale / 100f, nth, options);
622           }
623           eval.runBufferedSafely(
624               s.length() > 0 ? s : "draw ID \"" + thisId + "_*\" delete",
625               eval.outputBuffer);
626         }
627         return;
628       case T.frame:
629         isFrame = true;
630         // draw ID xxx frame {center} {q1 q2 q3 q4}
631         continue;
632       case T.leftbrace:
633       case T.point4f:
634       case T.point3f:
635         // {X, Y, Z}
636         if (eval.theTok == T.point4f || !eval.isPoint3f(i)) {
637           propertyValue = eval.getPoint4f(i);
638           if (isFrame) {
639             eval.checkLast(eval.iToken);
640             if (!chk)
641               eval.runScript(Escape.drawQuat(Quat.newP4((P4) propertyValue),
642                   (thisId == null ? "frame" : thisId), " " + swidth,
643                   (center == null ? new P3() : center), intScale / 100f));
644             return;
645           }
646           propertyName = "planedef";
647         } else {
648           propertyValue = center = getPoint3f(i, true);
649           propertyName = "coord";
650         }
651         i = eval.iToken;
652         havePoints = true;
653         break;
654       case T.hkl:
655       case T.plane:
656         if (!havePoints && !isIntersect && tokIntersect == 0) {
657           if (eval.theTok == T.hkl) {
658             havePoints = true;
659             setShapeProperty(JC.SHAPE_DRAW, "plane", null);
660             plane = eval.hklParameter(++i, true);
661             i = eval.iToken;
662             propertyName = "coords";
663             Lst<P3> list = new Lst<P3>();
664             list.addLast(P3.newP(eval.pt1));
665             list.addLast(P3.newP(eval.pt2));
666             list.addLast(P3.newP(eval.pt3));
667             propertyValue = list;
668           } else {
669             propertyName = "plane";
670             iArray = i + 1;
671           }
672           break;
673         }
674         if (eval.theTok == T.plane) {
675           plane = eval.planeParameter(i);
676         } else {
677           plane = eval.hklParameter(++i, false);
678         }
679         i = eval.iToken;
680         if (tokIntersect != 0) {
681           if (chk)
682             break;
683           Lst<Object> vpc = getPlaneIntersection(tokIntersect, plane, uc,
684               intScale / 100f, 0);
685           intScale = 0;
686           propertyName = "polygon";
687           propertyValue = vpc;
688         } else {
689           propertyValue = plane;
690           propertyName = "planedef";
691         }
692         havePoints = true;
693         break;
694       case T.linedata:
695         propertyName = "lineData";
696         propertyValue = eval.floatParameterSet(++i, 0, Integer.MAX_VALUE);
697         i = eval.iToken;
698         havePoints = true;
699         break;
700       case T.define:
701       case T.bitset:
702       case T.expressionBegin:
703         propertyName = "atomSet";
704         propertyValue = atomExpressionAt(i);
705         if (isFrame)
706           center = centerParameter(i);
707         i = eval.iToken;
708         havePoints = true;
709         break;
710       case T.varray:
711         havePoints = true;
712         propertyName = (iArray == i ? "coords" : "modelBasedPoints");
713         propertyValue = eval.theToken.value;
714         break;
715       case T.spacebeforesquare:
716       case T.comma:
717         break;
718       case T.leftsquare:
719         // [x y] or [x y %]
720         propertyValue = eval.xypParameter(i);
721         if (propertyValue != null) {
722           i = eval.iToken;
723           propertyName = "coord";
724           havePoints = true;
725           break;
726         }
727         if (isSavedState)
728           invArg();
729         isSavedState = true;
730         break;
731       case T.rightsquare:
732         if (!isSavedState)
733           invArg();
734         isSavedState = false;
735         break;
736       case T.reverse:
737         propertyName = "reverse";
738         break;
739       case T.string:
740         propertyValue = stringParameter(i);
741         propertyName = "title";
742         break;
743       case T.vector:
744         propertyName = "vector";
745         break;
746       case T.length:
747         propertyValue = Float.valueOf(floatParameter(++i));
748         propertyName = "length";
749         break;
750       case T.decimal:
751         // $drawObject
752         propertyValue = Float.valueOf(floatParameter(i));
753         propertyName = "length";
754         break;
755       case T.modelindex:
756         propertyName = "modelIndex";
757         propertyValue = Integer.valueOf(intParameter(++i));
758         break;
759       case T.integer:
760         if (isSavedState) {
761           propertyName = "modelIndex";
762           propertyValue = Integer.valueOf(intParameter(i));
763         } else {
764           intScale = intParameter(i);
765         }
766         break;
767       case T.scale:
768         intScale = Math.round(
769             floatParameter(++i) * (getToken(i).tok == T.integer ? 1 : 100));
770         continue;
771       case T.id:
772         thisId = setShapeId(JC.SHAPE_DRAW, ++i, idSeen);
773         isWild = (getShapeProperty(JC.SHAPE_DRAW, "ID") == null);
774         i = eval.iToken;
775         break;
776       case T.modelbased:
777         propertyName = "fixed";
778         propertyValue = Boolean.FALSE;
779         break;
780       case T.fixed:
781         propertyName = "fixed";
782         propertyValue = Boolean.TRUE;
783         break;
784       case T.offset:
785         P3 pt = getPoint3f(++i, true);
786         i = eval.iToken;
787         propertyName = "offset";
788         propertyValue = pt;
789         break;
790       case T.crossed:
791         propertyName = "crossed";
792         break;
793       case T.width:
794         propertyValue = Float.valueOf(floatParameter(++i));
795         propertyName = "width";
796         swidth = propertyName + " " + propertyValue;
797         break;
798       case T.line:
799         propertyName = "line";
800         propertyValue = Boolean.TRUE;
801         iArray = i + 1;
802         break;
803       case T.curve:
804         propertyName = "curve";
805         iArray = i + 1;
806         break;
807       case T.arc:
808         propertyName = "arc";
809         iArray = i + 1;
810         break;
811       case T.arrow:
812         propertyName = "arrow";
813         iArray = i + 1;
814         break;
815       case T.vertices:
816         propertyName = "vertices";
817         iArray = i + 1;
818         break;
819       case T.circle:
820         propertyName = "circle";
821         break;
822       case T.cylinder:
823         propertyName = "cylinder";
824         break;
825       case T.nohead:
826         propertyName = "nohead";
827         break;
828       case T.barb:
829         propertyName = "isbarb";
830         break;
831       case T.rotate45:
832         propertyName = "rotate45";
833         break;
834       case T.perpendicular:
835         propertyName = "perp";
836         break;
837       case T.radius:
838       case T.diameter:
839         boolean isRadius = (eval.theTok == T.radius);
840         float f = floatParameter(++i);
841         if (isRadius)
842           f *= 2;
843         propertyValue = Float.valueOf(f);
844         propertyName = (isRadius || tokAt(i) == T.decimal ? "width"
845             : "diameter");
846         swidth = propertyName
847             + (tokAt(i) == T.decimal ? " " + f : " " + ((int) f));
848         break;
849       case T.dollarsign:
850         // $drawObject[m]
851         if ((tokAt(i + 2) == T.leftsquare || isFrame)) {
852           P3 pto = center = centerParameter(i);
853           i = eval.iToken;
854           propertyName = "coord";
855           propertyValue = pto;
856           havePoints = true;
857           break;
858         }
859         // $drawObject
860         propertyValue = eval.objectNameParameter(++i);
861         propertyName = "identifier";
862         havePoints = true;
863         break;
864       case T.color:
865       case T.translucent:
866       case T.opaque:
867         idSeen = true;
868         translucentLevel = getColorTrans(eval, i, false, colorArgb);
869         i = eval.iToken;
870         continue;
871       default:
872         if (!eval.setMeshDisplayProperty(JC.SHAPE_DRAW, 0, eval.theTok)) {
873           if (eval.theTok == T.times || T.tokAttr(eval.theTok, T.identifier)) {
874             thisId = setShapeId(JC.SHAPE_DRAW, i, idSeen);
875             i = eval.iToken;
876             break;
877           }
878           invArg();
879         }
880         if (iptDisplayProperty == 0)
881           iptDisplayProperty = i;
882         i = eval.iToken;
883         continue;
884       }
885       idSeen = (eval.theTok != T.delete);
886       if (havePoints && !isInitialized && !isFrame) {
887         setShapeProperty(JC.SHAPE_DRAW, "points", Integer.valueOf(intScale));
888         isInitialized = true;
889         intScale = 0;
890       }
891       if (havePoints && isWild)
892         invArg();
893       if (propertyName != null)
894         setShapeProperty(JC.SHAPE_DRAW, propertyName, propertyValue);
895     }
896     finalizeObject(JC.SHAPE_DRAW, colorArgb[0], translucentLevel, intScale,
897         havePoints, connections, iptDisplayProperty, null);
898   }
899 
mo(boolean isInitOnly, int iShape)900   private void mo(boolean isInitOnly, int iShape) throws ScriptException {
901     ScriptEval eval = e;
902     int offset = Integer.MAX_VALUE;
903     boolean isNegOffset = false;
904     String nboType = null;
905     BS bsModels = vwr.getVisibleFramesBitSet();
906     Lst<Object[]> propertyList = new Lst<Object[]>();
907     boolean isBeta = false;
908     boolean isNBO = (tokAt(0) == T.nbo);
909     int i0 = 1;
910     if (isNBO) {
911       // NBO command by itself starts the NBO Server Interface panel
912       // NBO OPTIONS include "NOZAP;VIEW"
913       boolean isViewOnly = e.optParameterAsString(1).equals("view");
914       if (e.slen == 1 || isViewOnly
915           || e.optParameterAsString(1).equals("options")) {
916         if (!chk) {
917           String options = (isViewOnly ? "VIEW" : e.optParameterAsString(2));
918           vwr.startNBO(options);
919         }
920         return;
921       }
922     }
923     if (tokAt(1) == T.model || tokAt(1) == T.frame) {
924       i0 = eval.modelNumberParameter(2);
925       if (i0 < 0)
926         invArg();
927       bsModels.clearAll();
928       bsModels.set(i0);
929       i0 = 3;
930     }
931     eval.sm.loadShape(iShape);
932     for (int iModel = bsModels.nextSetBit(0); iModel >= 0; iModel = bsModels
933         .nextSetBit(iModel + 1)) {
934       int i = i0;
935       if (tokAt(i) == T.list && listIsosurface(iShape))
936         return;
937       setShapeProperty(iShape, "init", Integer.valueOf(iModel));
938       if (isInitOnly)
939         return;// (moNumber != 0);
940       String title = null;
941       int moNumber = ((Integer) getShapeProperty(iShape, "moNumber"))
942           .intValue();
943       float[] linearCombination = (float[]) getShapeProperty(iShape,
944           "moLinearCombination");
945       Boolean squared = (Boolean) getShapeProperty(iShape, "moSquareData");
946       Boolean linearSquared = (linearCombination == null ? null
947           : (Boolean) getShapeProperty(iShape, "moSquareLinear"));
948       if (moNumber == 0)
949         moNumber = Integer.MAX_VALUE;
950       String propertyName = null;
951       Object propertyValue = null;
952       boolean ignoreSquared = false;
953       String nboName = null;
954       switch (getToken(i).tok) {
955       case T.type:
956         if (iShape == T.mo) {
957           mo(isInitOnly, JC.SHAPE_NBO);
958           return;
959         }
960         nboType = paramAsStr(++i).toUpperCase();
961         if (eval.tokAt(i + 1) == T.string) {
962           nboName = paramAsStr(++eval.iToken);
963           // NBO "C1-C2"
964         }
965         break;
966       case T.cap:
967       case T.slab:
968         propertyName = (String) eval.theToken.value;
969         propertyValue = getCapSlabObject(i, false);
970         i = eval.iToken;
971         break;
972       case T.density:
973         linearSquared = Boolean.TRUE;
974         linearCombination = new float[] { 1 };
975         offset = moNumber = 0;
976         break;
977       case T.integer:
978         moNumber = intParameter(i);
979         if (tokAt(i + 1) == T.beta) {
980           isBeta = true;
981           i++;
982         }
983         linearCombination = moCombo(propertyList);
984         if (linearCombination == null && moNumber < 0)
985           linearCombination = new float[] { -100, -moNumber };
986         ignoreSquared = true;
987         break;
988       case T.minus:
989         switch (tokAt(++i)) {
990         case T.homo:
991         case T.lumo:
992           break;
993         default:
994           invArg();
995         }
996         isNegOffset = true;
997         //$FALL-THROUGH$
998       case T.homo:
999       case T.lumo:
1000         if ((offset = moOffset(i)) == Integer.MAX_VALUE)
1001           invArg();
1002         moNumber = 0;
1003         linearCombination = moCombo(propertyList);
1004         ignoreSquared = true;
1005         break;
1006       case T.next:
1007         moNumber = T.next;
1008         isBeta = false;
1009         linearCombination = moCombo(propertyList);
1010         ignoreSquared = true;
1011         break;
1012       case T.prev:
1013         moNumber = T.prev;
1014         isBeta = false;
1015         linearCombination = moCombo(propertyList);
1016         ignoreSquared = true;
1017         break;
1018       case T.color:
1019         setColorOptions(null, i + 1, iShape, 2);
1020         break;
1021       case T.plane:
1022         propertyName = "plane";
1023         propertyValue = (tokAt(e.iToken = ++i) == T.none ? null
1024             : eval.planeParameter(i));
1025         break;
1026       case T.point:
1027         addShapeProperty(propertyList, "randomSeed",
1028             tokAt(i + 2) == T.integer ? Integer.valueOf(intParameter(i + 2))
1029                 : null);
1030         propertyName = "monteCarloCount";
1031         propertyValue = Integer.valueOf(intParameter(i + 1));
1032         break;
1033       case T.scale:
1034         propertyName = "scale";
1035         propertyValue = Float.valueOf(floatParameter(i + 1));
1036         break;
1037       case T.cutoff:
1038         if (tokAt(i + 1) == T.plus) {
1039           propertyName = "cutoffPositive";
1040           propertyValue = Float.valueOf(floatParameter(i + 2));
1041         } else {
1042           propertyName = "cutoff";
1043           propertyValue = Float.valueOf(floatParameter(i + 1));
1044         }
1045         break;
1046       case T.debug:
1047         propertyName = "debug";
1048         break;
1049       case T.noplane:
1050         propertyName = "plane";
1051         break;
1052       case T.pointsperangstrom:
1053       case T.resolution:
1054         propertyName = "resolution";
1055         propertyValue = Float.valueOf(floatParameter(i + 1));
1056         break;
1057       case T.squared:
1058         if (linearCombination == null)
1059           squared = Boolean.TRUE;
1060         else
1061           linearSquared = Boolean.TRUE;
1062         ignoreSquared = false;
1063         break;
1064       case T.titleformat:
1065         if (i + 1 < slen && tokAt(i + 1) == T.string) {
1066           propertyName = "titleFormat";
1067           propertyValue = paramAsStr(i + 1);
1068         }
1069         break;
1070       case T.identifier:
1071         invArg();
1072         break;
1073       case T.string:
1074         if (isNBO && i == 1) {
1075           nboName = eval.stringParameter(i);
1076           // NBO "C1-C2"
1077           break;
1078         }
1079         //$FALL-THROUGH$
1080       default:
1081         if (isNBO && eval.tokAt(i) == T.string) {
1082           nboName = paramAsStr(i++);
1083           // NBO "C1-C2"
1084         }
1085         if (eval.isArrayParameter(i)) {
1086           linearCombination = eval.floatParameterSet(i, 1, Integer.MAX_VALUE);
1087           if (tokAt(eval.iToken + 1) == T.squared) {
1088             ignoreSquared = false;
1089             linearSquared = Boolean.TRUE;
1090             eval.iToken++;
1091           }
1092           break;
1093         }
1094         int ipt = eval.iToken;
1095         if (!eval.setMeshDisplayProperty(iShape, 0, eval.theTok))
1096           invArg();
1097         setShapeProperty(iShape, "setProperties", propertyList);
1098         eval.setMeshDisplayProperty(iShape, ipt, tokAt(ipt));
1099         return;
1100       }
1101       if (propertyName != null)
1102         addShapeProperty(propertyList, propertyName, propertyValue);
1103       boolean haveMO = (moNumber != Integer.MAX_VALUE
1104           || linearCombination != null);
1105       if (chk)
1106         return;
1107       if (nboType != null || nboName != null || haveMO) {
1108         if (haveMO && tokAt(eval.iToken + 1) == T.string) {
1109           title = paramAsStr(++eval.iToken);
1110         }
1111         eval.setCursorWait(true);
1112         if (nboType != null || nboName != null)
1113           nboType = nboType + ":" + nboName;
1114         setMoData(propertyList, moNumber, linearCombination, offset,
1115             isNegOffset, iModel, title, nboType, isBeta);
1116         if (haveMO) {
1117           addShapeProperty(propertyList, "finalize", null);
1118         }
1119       }
1120       if (!ignoreSquared) {
1121         setShapeProperty(iShape, "squareLinear", linearSquared);
1122         setShapeProperty(iShape, "squareData", squared);
1123       }
1124       if (propertyList.size() > 0)
1125         setShapeProperty(iShape, "setProperties", propertyList);
1126       if (haveMO && !eval.tQuiet) {
1127         String moLabel = "";
1128         if (isNBO) {
1129           moLabel = (String) getShapeProperty(iShape, "moLabel");
1130         } else {
1131           moNumber = ((Integer) getShapeProperty(iShape, "moNumber"))
1132               .intValue();
1133           moLabel = "" + moNumber;
1134         }
1135         showString(T.nameOf(tokAt(0)) + " " + moLabel + " "
1136             + (isBeta ? "beta " : "") + getShapeProperty(iShape, "message"));
1137       }
1138 
1139       propertyList.clear();
1140     }
1141   }
1142 
1143   @SuppressWarnings({ "static-access", "unchecked" })
setNBOType(Map<String, Object> moData, String type)1144   private int setNBOType(Map<String, Object> moData, String type)
1145       throws ScriptException {
1146 
1147     int nboNumber = -1;
1148     String name = null;
1149     int pt = type.indexOf(":");
1150     if (pt > 0) {
1151       name = type.substring(pt + 1);
1152       type = type.substring(0, pt);
1153       if (type.equals("null"))
1154         type = null;
1155       if (name.equals("null"))
1156         name = null;
1157     }
1158     if ((type == null ? 0 : JC.getNBOTypeFromName(type)) < 0)
1159       invArg();
1160     if (!moData.containsKey("nboLabels"))
1161       error(ScriptError.ERROR_moModelError);
1162     if (chk)
1163       return -1;
1164     if (type != null && !((GenNBOReader) Interface.getInterface(
1165         "org.jmol.adapter.readers.quantum.GenNBOReader", vwr, "script"))
1166             .readNBOCoefficients(moData, type, vwr))
1167       error(ScriptError.ERROR_moModelError);
1168 
1169     Lst<String> auxFiles = (Lst<String>) moData.get("auxFiles");
1170     Lst<String> auxFiles0 = (Lst<String>) vwr.getCurrentModelAuxInfo()
1171         .get("auxFiles");
1172     if (auxFiles0 == null) {
1173       vwr.getCurrentModelAuxInfo().put("auxFiles", auxFiles);
1174     } else {
1175       auxFiles0.addAll(auxFiles);
1176     }
1177     if (name != null) {
1178       pt = name.indexOf(".");
1179       if (pt > 0) {
1180         int ipt = PT.parseInt(name.substring(pt + 1));
1181         name = name.substring(0, pt);
1182         pt = ipt;
1183       }
1184       String[] labels = (String[]) moData.get("nboLabels");
1185       for (int i = 0, n = labels.length; i < n; i++) {
1186         if (name.equals(labels[i])) {
1187           if (pt < 0 || --pt == 0) {
1188             nboNumber = i + 1;
1189             break;
1190           }
1191         }
1192       }
1193       if (nboNumber < 0)
1194         error(ScriptError.ERROR_moModelError);
1195     }
1196     return nboNumber;
1197   }
1198 
moCombo(Lst<Object[]> propertyList)1199   private float[] moCombo(Lst<Object[]> propertyList) {
1200     if (tokAt(e.iToken + 1) != T.squared)
1201       return null;
1202     addShapeProperty(propertyList, "squareLinear", Boolean.TRUE);
1203     e.iToken++;
1204     return new float[0];
1205   }
1206 
moOffset(int index)1207   private int moOffset(int index) throws ScriptException {
1208     boolean isHomo = (getToken(index).tok == T.homo);
1209     int offset = (isHomo ? 0 : 1);
1210     int tok = tokAt(++index);
1211     if (tok == T.integer && ((String) e.st[index].value).charAt(0) == '-') // could be '-0'
1212       offset += intParameter(index);
1213     else if (tok == T.plus)
1214       offset += intParameter(++index);
1215     else if (tok == T.minus) // - <space> n
1216       offset -= intParameter(++index);
1217     return offset;
1218   }
1219 
1220   @SuppressWarnings("unchecked")
setMoData(Lst<Object[]> propertyList, int moNumber, float[] lc, int offset, boolean isNegOffset, int modelIndex, String title, String nboType, boolean isBeta)1221   private void setMoData(Lst<Object[]> propertyList, int moNumber, float[] lc,
1222                          int offset, boolean isNegOffset, int modelIndex,
1223                          String title, String nboType, boolean isBeta)
1224       throws ScriptException {
1225     ScriptEval eval = e;
1226     if (modelIndex < 0) {
1227       modelIndex = vwr.am.cmi;
1228       if (modelIndex < 0)
1229         eval.errorStr(ScriptError.ERROR_multipleModelsDisplayedNotOK,
1230             "MO isosurfaces");
1231     }
1232     Map<String, Object> moData = (Map<String, Object>) vwr.ms
1233         .getInfo(modelIndex, "moData");
1234     if (moData == null)
1235       error(ScriptError.ERROR_moModelError);
1236     vwr.checkMenuUpdate();
1237     if (nboType != null) {
1238       int nboNumber = setNBOType(moData, nboType);
1239       int nOrbitals = ((String[]) moData.get("nboLabels")).length;
1240       eval.showString(nOrbitals + " orbitals of type " + nboType.substring(0, nboType.indexOf(":") + 1) + " modelIndex=" + vwr.getModelNumberDotted(modelIndex));
1241       if (nboNumber > 0)
1242         moNumber = nboNumber;
1243       if (lc == null && moNumber == Integer.MAX_VALUE)
1244         return;
1245     }
1246     Lst<Map<String, Object>> mos = null;
1247     Map<String, Object> mo;
1248     int nOrb = 0;
1249     Float f = null;
1250     if (lc == null || lc.length < 2) {
1251       if (lc != null && lc.length == 1)
1252         offset = 0;
1253       else if (isBeta && moData.containsKey("firstBeta"))
1254         offset = ((Integer) moData.get("firstBeta")).intValue();
1255       int lastMoNumber = (moData.containsKey("lastMoNumber")
1256           ? ((Integer) moData.get("lastMoNumber")).intValue()
1257           : 0);
1258       int lastMoCount = (moData.containsKey("lastMoCount")
1259           ? ((Integer) moData.get("lastMoCount")).intValue()
1260           : 1);
1261       if (moNumber == T.prev)
1262         moNumber = lastMoNumber - 1;
1263       else if (moNumber == T.next)
1264         moNumber = lastMoNumber + lastMoCount;
1265       mos = (Lst<Map<String, Object>>) (moData.get("mos"));
1266       nOrb = (mos == null ? 0 : mos.size());
1267       if (nOrb == 0)
1268         error(ScriptError.ERROR_moCoefficients);
1269       if (nOrb == 1 && moNumber > 1)
1270         error(ScriptError.ERROR_moOnlyOne);
1271       if (offset != Integer.MAX_VALUE) {
1272         // 0: HOMO;
1273         if (isBeta) {
1274         } else if (moData.containsKey("HOMO")) {
1275           moNumber = ((Integer) moData.get("HOMO")).intValue() + offset;
1276           offset = 0;
1277         } else {
1278           moNumber = nOrb;
1279           for (int i = 0; i < nOrb; i++) {
1280             mo = mos.get(i);
1281             if ((f = (Float) mo.get("occupancy")) != null) {
1282               if (f.floatValue() < 0.5f) {
1283                 // go for LUMO = first unoccupied
1284                 moNumber = i;
1285                 break;
1286               }
1287               continue;
1288             } else if ((f = (Float) mo.get("energy")) != null) {
1289               if (f.floatValue() > 0) {
1290                 // go for LUMO = first positive
1291                 moNumber = i;
1292                 break;
1293               }
1294               continue;
1295             }
1296             break;
1297           }
1298           if (f == null)
1299             error(ScriptError.ERROR_moOccupancy);
1300         }
1301         moNumber += offset;
1302         if (!chk)
1303           Logger.info("MO " + moNumber);
1304       }
1305       if (moNumber < 1 || moNumber > nOrb)
1306         eval.errorStr(ScriptError.ERROR_moIndex, "" + nOrb);
1307     }
1308     moNumber = Math.abs(moNumber);
1309     moData.put("lastMoNumber", Integer.valueOf(moNumber));
1310     moData.put("lastMoCount", Integer.valueOf(1));
1311     if (isNegOffset && lc == null)
1312       lc = new float[] { -100, moNumber };
1313     if (lc != null && lc.length < 2) {
1314       mo = mos.get(moNumber - 1);
1315       if ((f = (Float) mo.get("energy")) == null) {
1316         lc = new float[] { 100, moNumber };
1317       } else {
1318 
1319         // constuct set of equivalent energies and square this
1320 
1321         float energy = f.floatValue();
1322         BS bs = BS.newN(nOrb);
1323         int n = 0;
1324         boolean isAllElectrons = (lc.length == 1 && lc[0] == 1);
1325         for (int i = 0; i < nOrb; i++) {
1326           if ((f = (Float) mos.get(i).get("energy")) == null)
1327             continue;
1328           float e = f.floatValue();
1329           if (isAllElectrons ? e <= energy : e == energy) {
1330             bs.set(i + 1);
1331             n += 2;
1332           }
1333         }
1334         lc = new float[n];
1335         for (int i = 0, pt = 0; i < n; i += 2) {
1336           lc[i] = 1;
1337           lc[i + 1] = (pt = bs.nextSetBit(pt + 1));
1338         }
1339         moData.put("lastMoNumber", Integer.valueOf(bs.nextSetBit(0)));
1340         moData.put("lastMoCount", Integer.valueOf(n / 2));
1341       }
1342       addShapeProperty(propertyList, "squareLinear", Boolean.TRUE);
1343     }
1344     addShapeProperty(propertyList, "moData", moData);
1345     if (title != null)
1346       addShapeProperty(propertyList, "title", title);
1347     addShapeProperty(propertyList, "molecularOrbital",
1348         lc != null ? lc : Integer.valueOf(Math.abs(moNumber)));
1349     addShapeProperty(propertyList, "clear", null);
1350   }
1351 
isosurface(int iShape)1352   private void isosurface(int iShape) throws ScriptException {
1353     // also called by lcaoCartoon
1354     ScriptEval eval = e;
1355     eval.sm.loadShape(iShape);
1356     if (tokAt(1) == T.list && listIsosurface(iShape))
1357       return;
1358     int iptDisplayProperty = 0;
1359     boolean isDisplay = false;
1360     boolean isIsosurface = (iShape == JC.SHAPE_ISOSURFACE);
1361     boolean isPmesh = (iShape == JC.SHAPE_PMESH);
1362     boolean isPlot3d = (iShape == JC.SHAPE_PLOT3D);
1363     boolean isLcaoCartoon = (iShape == JC.SHAPE_LCAOCARTOON);
1364     boolean isSilent = (isLcaoCartoon || tokAt(1) == T.delete
1365         || eval.isStateScript);
1366     boolean surfaceObjectSeen = false;
1367     boolean planeSeen = false;
1368     boolean isMapped = false;
1369     boolean isBicolor = false;
1370     boolean isPhased = false;
1371     boolean doCalcArea = false;
1372     boolean doCalcVolume = false;
1373     boolean isBeta = false;
1374     boolean isCavity = false;
1375     boolean haveRadius = false;
1376     boolean toCache = false;
1377     boolean isFxy = false;
1378     boolean haveSlab = false;
1379     boolean haveIntersection = false;
1380     boolean isFrontOnly = false;
1381     String nbotype = null;
1382     float[] data = null;
1383     String cmd = null;
1384     BS thisSet = null;
1385     int nFiles = 0;
1386     int nX, nY, nZ, ptX, ptY;
1387     float sigma = Float.NaN;
1388     float cutoff = Float.NaN;
1389     int ptWithin = 0;
1390     Boolean smoothing = null;
1391     int smoothingPower = Integer.MAX_VALUE;
1392     BS bs = null;
1393     BS bsSelect = null;
1394     BS bsIgnore = null;
1395     SB sbCommand = new SB();
1396     P3 pt;
1397     P4 plane = null;
1398     P3 lattice = null;
1399     boolean fixLattice = false;
1400     P3[] pts = null;
1401     int color = 0;
1402     String str = null;
1403     int modelIndex = (chk ? 0 : Integer.MIN_VALUE);
1404     eval.setCursorWait(true);
1405     boolean idSeen = (initIsosurface(iShape) != null);
1406     boolean isWild = (idSeen && getShapeProperty(iShape, "ID") == null);
1407     boolean isColorSchemeTranslucent = false;
1408     boolean isInline = false;
1409     boolean isSign = false;
1410     Object onlyOneModel = null;
1411     Object[] filesData = null;
1412     String translucency = null;
1413     String colorScheme = null;
1414     String mepOrMlp = null;
1415     M4[] symops = null;
1416     short[] discreteColixes = null;
1417     Lst<Object[]> propertyList = new Lst<Object[]>();
1418     boolean defaultMesh = false;
1419     if (isPmesh || isPlot3d)
1420       addShapeProperty(propertyList, "fileType", "Pmesh");
1421 
1422     for (int i = eval.iToken; i < slen; ++i) {
1423       String propertyName = null;
1424       Object propertyValue = null;
1425       int tok = getToken(i).tok;
1426       if (tok == T.identifier) {
1427         str = paramAsStr(i);
1428         if (str.equalsIgnoreCase("map"))
1429           tok = T.mapproperty;
1430       }
1431       switch (tok) {
1432       // settings only
1433       case T.silent:
1434         isSilent = true;
1435         sbCommand.append(" silent");
1436         propertyName = "silent";
1437         break;
1438       case T.isosurfacepropertysmoothing:
1439         smoothing = (getToken(++i).tok == T.on ? Boolean.TRUE
1440             : eval.theTok == T.off ? Boolean.FALSE : null);
1441         if (smoothing == null)
1442           invArg();
1443         continue;
1444       case T.isosurfacepropertysmoothingpower:
1445         smoothingPower = intParameter(++i);
1446         continue;
1447       // offset, rotate, and scale3d don't need to be saved in sbCommand
1448       // because they are display properties
1449       case T.move: // Jmol 13.0.RC2 -- required for state saving after coordinate-based translate/rotate
1450         // but this will not work for MO calculations, which have to be
1451         // generated in their original atom-based frame
1452         propertyName = "moveIsosurface";
1453         if (tokAt(++i) != T.matrix4f)
1454           invArg();
1455         propertyValue = getToken(i++).value;
1456         break;
1457       case T.symop:
1458         float[][] ff = floatArraySet(i + 2, intParameter(i + 1), 16);
1459         symops = new M4[ff.length];
1460         for (int j = symops.length; --j >= 0;)
1461           symops[j] = M4.newA16(ff[j]);
1462         i = eval.iToken;
1463         break;
1464       case T.symmetry:
1465         if (modelIndex < 0)
1466           modelIndex = Math.min(vwr.am.cmi, 0);
1467         boolean needIgnore = (bsIgnore == null);
1468         if (bsSelect == null)
1469           bsSelect = BSUtil.copy(vwr.bsA());
1470         // and in symop=1
1471         bsSelect.and(vwr.ms.getAtoms(T.symop, Integer.valueOf(1)));
1472         if (!needIgnore)
1473           bsSelect.andNot(bsIgnore);
1474         addShapeProperty(propertyList, "select", bsSelect);
1475         if (needIgnore) {
1476           bsIgnore = BSUtil.copy(bsSelect);
1477           BSUtil.invertInPlace(bsIgnore, vwr.ms.ac);
1478           isFrontOnly = true;
1479           addShapeProperty(propertyList, "ignore", bsIgnore);
1480           sbCommand.append(" ignore ").append(Escape.eBS(bsIgnore));
1481         }
1482         sbCommand.append(" symmetry");
1483         if (color == 0)
1484           addShapeProperty(propertyList, "colorRGB", Integer.valueOf(T.symop));
1485         symops = vwr.ms.getSymMatrices(modelIndex);
1486         break;
1487       case T.offset:
1488         propertyName = "offset";
1489         propertyValue = centerParameter(++i);
1490         i = eval.iToken;
1491         break;
1492       case T.rotate:
1493         propertyName = "rotate";
1494         propertyValue = (tokAt(eval.iToken = ++i) == T.none ? null
1495             : eval.getPoint4f(i));
1496         i = eval.iToken;
1497         break;
1498       case T.scale3d:
1499         propertyName = "scale3d";
1500         propertyValue = Float.valueOf(floatParameter(++i));
1501         break;
1502       case T.period:
1503         sbCommand.append(" periodic");
1504         propertyName = "periodic";
1505         break;
1506       case T.origin:
1507       case T.step:
1508       case T.point:
1509         propertyName = eval.theToken.value.toString();
1510         sbCommand.append(" ").appendO(eval.theToken.value);
1511         propertyValue = centerParameter(++i);
1512         sbCommand.append(" ").append(Escape.eP((P3) propertyValue));
1513         i = eval.iToken;
1514         break;
1515       case T.boundbox:
1516         if (eval.fullCommand.indexOf("# BBOX=") >= 0) {
1517           String[] bbox = PT
1518               .split(PT.getQuotedAttribute(eval.fullCommand, "# BBOX"), ",");
1519           pts = new P3[] { (P3) Escape.uP(bbox[0]), (P3) Escape.uP(bbox[1]) };
1520         } else if (eval.isCenterParameter(i + 1)) {
1521           pts = new P3[] { getPoint3f(i + 1, true),
1522               getPoint3f(eval.iToken + 1, true) };
1523           i = eval.iToken;
1524         } else {
1525           pts = vwr.ms.getBBoxVertices();
1526         }
1527         sbCommand.append(" boundBox " + Escape.eP(pts[0]) + " "
1528             + Escape.eP(pts[pts.length - 1]));
1529         propertyName = "boundingBox";
1530         propertyValue = pts;
1531         break;
1532       case T.pmesh:
1533         isPmesh = true;
1534         sbCommand.append(" pmesh");
1535         propertyName = "fileType";
1536         propertyValue = "Pmesh";
1537         break;
1538       case T.intersection:
1539         // isosurface intersection {A} {B} VDW....
1540         // isosurface intersection {A} {B} function "a-b" VDW....
1541         bsSelect = atomExpressionAt(++i);
1542         if (chk) {
1543           bs = new BS();
1544         } else if (tokAt(eval.iToken + 1) == T.expressionBegin
1545             || tokAt(eval.iToken + 1) == T.bitset) {
1546           bs = atomExpressionAt(++eval.iToken);
1547           bs.and(vwr.ms.getAtomsWithinRadius(5.0f, bsSelect, false, null));
1548         } else {
1549           // default is "within(5.0, selected) and not within(molecule,selected)"
1550           bs = vwr.ms.getAtomsWithinRadius(5.0f, bsSelect, true, null);
1551           bs.andNot(vwr.ms.getAtoms(T.molecule, bsSelect));
1552         }
1553         bs.andNot(bsSelect);
1554         sbCommand.append(" intersection ").append(Escape.eBS(bsSelect))
1555             .append(" ").append(Escape.eBS(bs));
1556         i = eval.iToken;
1557         if (tokAt(i + 1) == T.function) {
1558           i++;
1559           String f = (String) getToken(++i).value;
1560           sbCommand.append(" function ").append(PT.esc(f));
1561           if (!chk)
1562             addShapeProperty(propertyList, "func",
1563                 (f.equals("a+b") || f.equals("a-b") ? f
1564                     : createFunction("__iso__", "a,b", f)));
1565         } else {
1566           haveIntersection = true;
1567         }
1568         propertyName = "intersection";
1569         propertyValue = new BS[] { bsSelect, bs };
1570         break;
1571       case T.display:
1572       case T.within:
1573         isDisplay = (tok == T.display);
1574         if (isDisplay) {
1575           sbCommand.append(" display");
1576           iptDisplayProperty = i;
1577           tok = tokAt(i + 1);
1578           if (tok == T.nada)
1579             continue;
1580           i++;
1581           addShapeProperty(propertyList, "token", Integer.valueOf(T.on));
1582           if (tok == T.bitset || tok == T.all) {
1583             propertyName = "bsDisplay";
1584             if (tok == T.all) {
1585               sbCommand.append(" all");
1586             } else {
1587               propertyValue = st[i].value;
1588               sbCommand.append(" ").append(Escape.eBS((BS) propertyValue));
1589             }
1590             eval.checkLast(i);
1591             break;
1592           } else if (tok != T.within) {
1593             eval.iToken = i;
1594             invArg();
1595           }
1596         } else {
1597           ptWithin = i;
1598         }
1599         float distance;
1600         P3 ptc = null;
1601         bs = null;
1602         Object[] ret = new Object[1];
1603         if (tokAt(i + 1) == T.expressionBegin) {
1604           // within ( x.x , .... )
1605           distance = floatParameter(i + 3);
1606           if (eval.isPoint3f(i + 4)) {
1607             ptc = eval.centerParameter(i + 4, null);
1608             eval.iToken += 2;
1609           } else if (eval.isPoint3f(i + 5)) {
1610             ptc = eval.centerParameter(i + 5, null);
1611             eval.iToken += 2;
1612           } else {
1613             bs = eval.atomExpression(st, i + 5, slen, true, false, ret, true);
1614             if (bs == null)
1615               invArg();
1616           }
1617         } else {
1618           distance = floatParameter(++i);
1619           ptc = eval.centerParameter(++i, ret);
1620           bs = (ret[0] instanceof BS ? (BS) ret[0] : null);
1621         }
1622         if (isDisplay)
1623           eval.checkLast(eval.iToken);
1624         i = eval.iToken;
1625         if (eval.fullCommand.indexOf("# WITHIN=") >= 0)
1626           bs = BS.unescape(PT.getQuotedAttribute(eval.fullCommand, "# WITHIN"));
1627         if (!chk) {
1628           if (bs != null && modelIndex >= 0) {
1629             bs.and(vwr.getModelUndeletedAtomsBitSet(modelIndex));
1630           }
1631           if (ptc == null)
1632             ptc = (bs == null ? new P3() : vwr.ms.getAtomSetCenter(bs));
1633           pts = getWithinDistanceVector(propertyList, distance, ptc, bs,
1634               isDisplay);
1635           sbCommand.append(" within ").appendF(distance).append(" ")
1636               .append(bs == null ? Escape.eP(ptc) : Escape.eBS(bs));
1637         }
1638         continue;
1639       case T.parameters:
1640         propertyName = "parameters";
1641         // if > 1 parameter, then first is assumed to be the cutoff.
1642         float[] fparams = eval.floatParameterSet(++i, 1, 10);
1643         i = eval.iToken;
1644         propertyValue = fparams;
1645         sbCommand.append(" parameters ").append(Escape.eAF(fparams));
1646         break;
1647       case T.property:
1648       case T.variable:
1649         onlyOneModel = eval.theToken.value;
1650         boolean isVariable = (tok == T.variable);
1651         int tokProperty = tokAt(i + 1);
1652         if (mepOrMlp == null) { // not mlp or mep
1653           if (!surfaceObjectSeen && !isMapped && !planeSeen) {
1654             addShapeProperty(propertyList, "sasurface", Float.valueOf(0));
1655             //if (surfaceObjectSeen)
1656             sbCommand.append(" vdw");
1657             surfaceObjectSeen = true;
1658           }
1659           propertyName = "property";
1660           if (smoothing == null) {
1661             boolean allowSmoothing = T.tokAttr(tokProperty, T.floatproperty);
1662             smoothing = (allowSmoothing
1663                 && vwr.getIsosurfacePropertySmoothing(false) == 1 ? Boolean.TRUE
1664                     : Boolean.FALSE);
1665           }
1666           addShapeProperty(propertyList, "propertySmoothing", smoothing);
1667           sbCommand.append(" isosurfacePropertySmoothing " + smoothing);
1668           if (smoothing == Boolean.TRUE) {
1669             if (smoothingPower == Integer.MAX_VALUE)
1670               smoothingPower = vwr.getIsosurfacePropertySmoothing(true);
1671             addShapeProperty(propertyList, "propertySmoothingPower",
1672                 Integer.valueOf(smoothingPower));
1673             sbCommand
1674                 .append(" isosurfacePropertySmoothingPower " + smoothingPower);
1675           }
1676           if (vwr.g.rangeSelected)
1677             addShapeProperty(propertyList, "rangeSelected", Boolean.TRUE);
1678         } else {
1679           propertyName = mepOrMlp;
1680         }
1681         str = paramAsStr(i);
1682         //        if (surfaceObjectSeen)
1683         sbCommand.append(" ").append(str);
1684 
1685         if (str.toLowerCase().indexOf("property_") == 0) {
1686           data = new float[vwr.ms.ac];
1687           if (chk)
1688             continue;
1689           data = (float[]) vwr.getDataObj(str, null,
1690               JmolDataManager.DATA_TYPE_AF);
1691           if (data == null)
1692             invArg();
1693           addShapeProperty(propertyList, propertyName, data);
1694           continue;
1695         }
1696 
1697         int ac = vwr.ms.ac;
1698         data = new float[ac];
1699 
1700         if (isVariable) {
1701           String vname = paramAsStr(++i);
1702           if (vname.length() == 0) {
1703             data = eval.floatParameterSet(i, ac, ac);
1704           } else {
1705             data = new float[ac];
1706             if (!chk)
1707               Parser.parseStringInfestedFloatArray(
1708                   "" + eval.getParameter(vname, T.string, true), null, data);
1709           }
1710           if (!chk/* && (surfaceObjectSeen)*/)
1711             sbCommand.append(" \"\" ").append(Escape.eAF(data));
1712         } else {
1713           getToken(++i);
1714           if (!chk) {
1715             sbCommand.append(" " + eval.theToken.value);
1716             Atom[] atoms = vwr.ms.at;
1717             vwr.autoCalculate(tokProperty, null);
1718             if (tokProperty != T.color) {
1719               pt = new P3();
1720               for (int iAtom = ac; --iAtom >= 0;)
1721                 data[iAtom] = atoms[iAtom].atomPropertyFloat(vwr, tokProperty,
1722                     pt);
1723             }
1724           }
1725           if (tokProperty == T.color)
1726             colorScheme = "inherit";
1727           if (tokAt(i + 1) == T.within) {
1728             float d = floatParameter(i = i + 2);
1729             sbCommand.append(" within " + d);
1730             addShapeProperty(propertyList, "propertyDistanceMax",
1731                 Float.valueOf(d));
1732           }
1733         }
1734         propertyValue = data;
1735         break;
1736       case T.modelindex:
1737       case T.model:
1738         if (surfaceObjectSeen)
1739           invArg();
1740         modelIndex = (tok == T.modelindex ? intParameter(++i)
1741             : eval.modelNumberParameter(++i));
1742         sbCommand.append(" modelIndex " + modelIndex);
1743         if (modelIndex < 0) {
1744           propertyName = "fixed";
1745           propertyValue = Boolean.TRUE;
1746           break;
1747         }
1748         propertyName = "modelIndex";
1749         propertyValue = Integer.valueOf(modelIndex);
1750         break;
1751       case T.select:
1752         // in general, vwr.getCurrentSelection() is used, but we may
1753         // override that here. But we have to be careful that
1754         // we PREPEND the selection to the command if no surface object
1755         // has been seen yet, and APPEND it if it has.
1756         propertyName = "select";
1757         BS bs1 = atomExpressionAt(++i);
1758         propertyValue = bs1;
1759         i = eval.iToken;
1760         boolean isOnly = (tokAt(i + 1) == T.only);
1761         if (isOnly) {
1762           i++;
1763           bsIgnore = BSUtil.copy(bs1);
1764           BSUtil.invertInPlace(bsIgnore, vwr.ms.ac);
1765           addShapeProperty(propertyList, "ignore", bsIgnore);
1766           sbCommand.append(" ignore ").append(Escape.eBS(bsIgnore));
1767           isFrontOnly = true;
1768         }
1769         if (surfaceObjectSeen || isMapped) {
1770           sbCommand.append(" select " + Escape.eBS(bs1));
1771         } else {
1772           bsSelect = (BS) propertyValue;
1773           if (modelIndex < 0 && bsSelect.nextSetBit(0) >= 0)
1774             modelIndex = vwr.ms.at[bsSelect.nextSetBit(0)].mi;
1775         }
1776         break;
1777       case T.subset:
1778         if (eval.getToken(++i).tok == T.bitset) {
1779           thisSet = (BS) eval.theToken.value;
1780         } else {
1781           thisSet = (BS) eval.expandFloatArray(
1782               eval.floatParameterSet(i, 1, Integer.MAX_VALUE), 1, true);
1783         }
1784         i = eval.iToken;
1785         break;
1786       case T.set:
1787         int ns = intParameter(++i);
1788         if (ns > 0)
1789           thisSet = BSUtil.newAndSetBit(ns - 1);
1790         else
1791           thisSet = new BS();
1792         break;
1793       case T.center:
1794         propertyName = "center";
1795         propertyValue = centerParameter(++i);
1796         sbCommand.append(" center " + Escape.eP((P3) propertyValue));
1797         i = eval.iToken;
1798         break;
1799       case T.sign:
1800       case T.color:
1801         idSeen = true;
1802         if (tok == T.sign) {
1803           isSign = true;
1804           sbCommand.append(" sign");
1805           addShapeProperty(propertyList, "sign", Boolean.TRUE);
1806         } else {
1807           if (tokAt(i + 1) == T.density) {
1808             i++;
1809             propertyName = "colorDensity";
1810             sbCommand.append(" color density");
1811             if (isFloatParameter(i + 1)) {
1812               float ptSize = floatParameter(++i);
1813               sbCommand.append(" " + ptSize);
1814               propertyValue = Float.valueOf(ptSize);
1815             }
1816             break;
1817           }
1818           /*
1819            * "color" now is just used as an equivalent to "sign" and as an
1820            * introduction to "absolute" any other use is superfluous; it has
1821            * been replaced with MAP for indicating "use the current surface"
1822            * because the term COLOR is too general.
1823            */
1824 
1825           if (getToken(i + 1).tok == T.string) {
1826             colorScheme = paramAsStr(++i);
1827             if (colorScheme.indexOf(" ") > 0) {
1828               discreteColixes = C.getColixArray(colorScheme);
1829               if (discreteColixes == null)
1830                 error(ScriptError.ERROR_badRGBColor);
1831             }
1832           } else if (eval.theTok == T.mesh) {
1833             i++;
1834             sbCommand.append(" color mesh");
1835             color = eval.getArgbParam(++i);
1836             addShapeProperty(propertyList, "meshcolor", Integer.valueOf(color));
1837             sbCommand.append(" ").append(Escape.escapeColor(color));
1838             i = eval.iToken;
1839             continue;
1840           }
1841           if ((eval.theTok = tokAt(i + 1)) == T.translucent
1842               || eval.theTok == T.opaque) {
1843             sbCommand.append(" color");
1844             translucency = setColorOptions(sbCommand, i + 1,
1845                 JC.SHAPE_ISOSURFACE, -2);
1846             i = eval.iToken;
1847             continue;
1848           }
1849           switch (tokAt(i + 1)) {
1850           case T.absolute:
1851           case T.range:
1852             getToken(++i);
1853             sbCommand.append(" color range");
1854             addShapeProperty(propertyList, "rangeAll", null);
1855             if (tokAt(i + 1) == T.all) {
1856               i++;
1857               sbCommand.append(" all");
1858               continue;
1859             }
1860             float min = floatParameter(++i);
1861             float max = floatParameter(++i);
1862             addShapeProperty(propertyList, "red", Float.valueOf(min));
1863             addShapeProperty(propertyList, "blue", Float.valueOf(max));
1864             sbCommand.append(" ").appendF(min).append(" ").appendF(max);
1865             continue;
1866           }
1867           if (eval.isColorParam(i + 1)) {
1868             color = eval.getArgbParam(i + 1);
1869             if (tokAt(i + 2) == T.to) {
1870               colorScheme = eval.getColorRange(i + 1);
1871               i = eval.iToken;
1872               break;
1873             }
1874           }
1875           sbCommand.append(" color");
1876         }
1877         if (eval.isColorParam(i + 1)) {
1878           color = eval.getArgbParam(++i);
1879           sbCommand.append(" ").append(Escape.escapeColor(color));
1880           i = eval.iToken;
1881           addShapeProperty(propertyList, "colorRGB", Integer.valueOf(color));
1882           idSeen = true;
1883           if (eval.isColorParam(i + 1)) {
1884             color = eval.getArgbParam(++i);
1885             i = eval.iToken;
1886             addShapeProperty(propertyList, "colorRGB", Integer.valueOf(color));
1887             sbCommand.append(" ").append(Escape.escapeColor(color));
1888             isBicolor = true;
1889           } else if (isSign) {
1890             invPO();
1891           }
1892         } else if (!isSign && discreteColixes == null && colorScheme == null) {
1893           invPO();
1894         }
1895         continue;
1896       case T.cache:
1897         if (!isIsosurface)
1898           invArg();
1899         toCache = !chk;
1900         continue;
1901       case T.file:
1902         if (tokAt(i + 1) != T.string)
1903           invPO();
1904         continue;
1905       case T.bondingradius:
1906       case T.vanderwaals:
1907         //if (surfaceObjectSeen)
1908         sbCommand.append(" ").appendO(eval.theToken.value);
1909         RadiusData rd = eval.encodeRadiusParameter(i, false, true);
1910         if (rd == null)
1911           return;
1912         //if (surfaceObjectSeen)
1913         sbCommand.append(" ").appendO(rd);
1914         if (Float.isNaN(rd.value))
1915           rd.value = 100;
1916         propertyValue = rd;
1917         propertyName = "radius";
1918         haveRadius = true;
1919         if (isMapped)
1920           surfaceObjectSeen = false;
1921         i = eval.iToken;
1922         break;
1923       case T.plane:
1924         // plane {X, Y, Z, W}
1925         planeSeen = true;
1926         propertyName = "plane";
1927         propertyValue = eval.planeParameter(i);
1928         i = eval.iToken;
1929         //if (surfaceObjectSeen)
1930         sbCommand.append(" plane ").append(Escape.eP4((P4) propertyValue));
1931         break;
1932       case T.scale:
1933         propertyName = "scale";
1934         propertyValue = Float.valueOf(floatParameter(++i));
1935         sbCommand.append(" scale ").appendO(propertyValue);
1936         break;
1937       case T.all:
1938         if (idSeen)
1939           invArg();
1940         propertyName = "thisID";
1941         break;
1942       case T.ellipsoid:
1943         // ellipsoid {xc yc zc f} where a = b and f = a/c
1944         // NOT OR ellipsoid {u11 u22 u33 u12 u13 u23}
1945         surfaceObjectSeen = true;
1946         ++i;
1947         //        ignoreError = true;
1948         //      try {
1949         propertyValue = eval.getPoint4f(i);
1950         propertyName = "ellipsoid";
1951         i = eval.iToken;
1952         sbCommand.append(" ellipsoid ").append(Escape.eP4((P4) propertyValue));
1953         break;
1954       //        } catch (Exception e) {
1955       //        }
1956       //        try {
1957       //          propertyName = "ellipsoid";
1958       //          propertyValue = eval.floatParameterSet(i, 6, 6);
1959       //          i = eval.iToken;
1960       //          sbCommand.append(" ellipsoid ").append(
1961       //              Escape.eAF((float[]) propertyValue));
1962       //          break;
1963       //        } catch (Exception e) {
1964       //        }
1965       //        ignoreError = false;
1966       //        bs = atomExpressionAt(i);
1967       //        sbCommand.append(" ellipsoid ").append(Escape.eBS(bs));
1968       //        int iAtom = bs.nextSetBit(0);
1969       //        if (iAtom < 0)
1970       //          return;
1971       //        Atom[] atoms = vwr.modelSet.atoms;
1972       //        Tensor[] tensors = atoms[iAtom].getTensors();
1973       //        if (tensors == null || tensors.length < 1 || tensors[0] == null
1974       //            || (propertyValue = vwr.getQuadricForTensor(tensors[0], null)) == null)
1975       //          return;
1976       //        i = eval.iToken;
1977       //        propertyName = "ellipsoid";
1978       //        if (!chk)
1979       //          addShapeProperty(propertyList, "center", vwr.getAtomPoint3f(iAtom));
1980       //        break;
1981       case T.hkl:
1982         // miller indices hkl
1983         planeSeen = true;
1984         propertyName = "plane";
1985         propertyValue = eval.hklParameter(++i, false);
1986         i = eval.iToken;
1987         sbCommand.append(" plane ").append(Escape.eP4((P4) propertyValue));
1988         break;
1989       case T.lcaocartoon:
1990         surfaceObjectSeen = true;
1991         String lcaoType = paramAsStr(++i);
1992         addShapeProperty(propertyList, "lcaoType", lcaoType);
1993         sbCommand.append(" lcaocartoon ").append(PT.esc(lcaoType));
1994         switch (getToken(++i).tok) {
1995         case T.define:
1996         case T.bitset:
1997         case T.expressionBegin:
1998           // automatically selects just the model of the first atom in the set.
1999           propertyName = "lcaoCartoon";
2000           bs = atomExpressionAt(i);
2001           i = eval.iToken;
2002           if (chk)
2003             continue;
2004           int atomIndex = bs.nextSetBit(0);
2005           if (atomIndex < 0)
2006             error(ScriptError.ERROR_expressionExpected);
2007           sbCommand.append(" ({").appendI(atomIndex).append("})");
2008           modelIndex = vwr.ms.at[atomIndex].mi;
2009           addShapeProperty(propertyList, "modelIndex",
2010               Integer.valueOf(modelIndex));
2011           V3[] axes = { new V3(), new V3(), V3.newV(vwr.ms.at[atomIndex]),
2012               new V3() };
2013           if (!lcaoType.equalsIgnoreCase("s")
2014               && vwr.getHybridizationAndAxes(atomIndex, axes[0], axes[1],
2015                   lcaoType) == null)
2016             return;
2017           propertyValue = axes;
2018           break;
2019         default:
2020           error(ScriptError.ERROR_expressionExpected);
2021         }
2022         break;
2023       case T.nbo:
2024         nbotype = paramAsStr(++i).toUpperCase();
2025         sbCommand.append(" nbo ").append(nbotype).append(" ");
2026         //$FALL-THROUGH$
2027       case T.mo:
2028         if (nbotype == null)
2029           sbCommand.append(" mo ");
2030         // mo 1-based-index
2031         int moNumber = Integer.MAX_VALUE;
2032         int offset = Integer.MAX_VALUE;
2033         boolean isNegOffset = (tokAt(i + 1) == T.minus);
2034         if (isNegOffset)
2035           i++;
2036         float[] linearCombination = null;
2037         switch (tokAt(++i)) {
2038         case T.nada:
2039           eval.bad();
2040           break;
2041         case T.density:
2042           sbCommand.append("[1] squared ");
2043           addShapeProperty(propertyList, "squareLinear", Boolean.TRUE);
2044           linearCombination = new float[] { 1 };
2045           offset = moNumber = 0;
2046           i++;
2047           break;
2048         case T.homo:
2049         case T.lumo:
2050           offset = moOffset(i);
2051           moNumber = 0;
2052           i = eval.iToken;
2053           //if (surfaceObjectSeen) {
2054           sbCommand.append((isNegOffset ? "-" : "") + "HOMO ");
2055           if (offset > 0)
2056             sbCommand.append("+");
2057           if (offset != 0)
2058             sbCommand.appendI(offset);
2059           //}
2060           break;
2061         case T.integer:
2062           moNumber = intParameter(i);
2063           //if (surfaceObjectSeen)
2064           sbCommand.appendI(moNumber);
2065           if (tokAt(i + 1) == T.beta) {
2066             isBeta = true;
2067             i++;
2068           }
2069           break;
2070         default:
2071           if (eval.isArrayParameter(i)) {
2072             linearCombination = eval.floatParameterSet(i, 1, Integer.MAX_VALUE);
2073             i = eval.iToken;
2074           }
2075         }
2076         boolean squared = (tokAt(i + 1) == T.squared);
2077         if (squared) {
2078           addShapeProperty(propertyList, "squareLinear", Boolean.TRUE);
2079           sbCommand.append(" squared");
2080           if (linearCombination == null)
2081             linearCombination = new float[0];
2082         } else if (tokAt(i + 1) == T.point) {
2083           ++i;
2084           int monteCarloCount = intParameter(++i);
2085           int seed = (tokAt(i + 1) == T.integer ? intParameter(++i)
2086               : ((int) -System.currentTimeMillis()) % 10000);
2087           addShapeProperty(propertyList, "monteCarloCount",
2088               Integer.valueOf(monteCarloCount));
2089           addShapeProperty(propertyList, "randomSeed", Integer.valueOf(seed));
2090           sbCommand.append(" points ").appendI(monteCarloCount).appendC(' ')
2091               .appendI(seed);
2092         }
2093         setMoData(propertyList, moNumber, linearCombination, offset,
2094             isNegOffset, modelIndex, null, nbotype, isBeta);
2095         surfaceObjectSeen = true;
2096         continue;
2097       case T.nci:
2098         propertyName = "nci";
2099         //if (surfaceObjectSeen)
2100         sbCommand.append(" " + propertyName);
2101         tok = tokAt(i + 1);
2102         boolean isPromolecular = (tok != T.file && tok != T.string
2103             && tok != T.mrc);
2104         propertyValue = Boolean.valueOf(isPromolecular);
2105         if (isPromolecular)
2106           surfaceObjectSeen = true;
2107         break;
2108       case T.mep:
2109       case T.mlp:
2110         boolean isMep = (tok == T.mep);
2111         propertyName = (isMep ? "mep" : "mlp");
2112         //if (surfaceObjectSeen)
2113         sbCommand.append(" " + propertyName);
2114         String fname = null;
2115         int calcType = -1;
2116         surfaceObjectSeen = true;
2117         if (tokAt(i + 1) == T.integer) {
2118           calcType = intParameter(++i);
2119           sbCommand.append(" " + calcType);
2120           addShapeProperty(propertyList, "mepCalcType",
2121               Integer.valueOf(calcType));
2122         }
2123         if (tokAt(i + 1) == T.string) {
2124           fname = stringParameter(++i);
2125           //if (surfaceObjectSeen)
2126           sbCommand.append(" /*file*/" + PT.esc(fname));
2127         } else if (tokAt(i + 1) == T.property) {
2128           mepOrMlp = propertyName;
2129           continue;
2130         }
2131         if (!chk)
2132           try {
2133             data = (fname == null && isMep
2134                 ? vwr.getOrCalcPartialCharges(bsSelect, bsIgnore)
2135                 : getAtomicPotentials(bsSelect, bsIgnore, fname));
2136           } catch (JmolAsyncException e1) {
2137             throw new ScriptInterruption(e, "partialcharge", 1);
2138           }
2139         if (!chk && data == null)
2140           error(ScriptError.ERROR_noPartialCharges);
2141         propertyValue = data;
2142         break;
2143       case T.volume:
2144         doCalcVolume = !chk;
2145         sbCommand.append(" volume");
2146         break;
2147       case T.id:
2148         setShapeId(iShape, ++i, idSeen);
2149         isWild = (getShapeProperty(iShape, "ID") == null);
2150         i = eval.iToken;
2151         break;
2152       case T.colorscheme:
2153         // either order NOT OK -- documented for TRANSLUCENT "rwb"
2154         if (tokAt(i + 1) == T.translucent) {
2155           isColorSchemeTranslucent = true;
2156           i++;
2157         }
2158         colorScheme = paramAsStr(++i).toLowerCase();
2159         if (colorScheme.equals("sets")) {
2160           sbCommand.append(" colorScheme \"sets\"");
2161         } else if (eval.isColorParam(i)) {
2162           colorScheme = eval.getColorRange(i);
2163           i = eval.iToken;
2164         }
2165         break;
2166       case T.addhydrogens:
2167         propertyName = "addHydrogens";
2168         propertyValue = Boolean.TRUE;
2169         sbCommand.append(" addHydrogens");
2170         break;
2171       case T.angstroms:
2172         propertyName = "angstroms";
2173         sbCommand.append(" angstroms");
2174         break;
2175       case T.anisotropy:
2176         propertyName = "anisotropy";
2177         propertyValue = getPoint3f(++i, false);
2178         sbCommand.append(" anisotropy").append(Escape.eP((P3) propertyValue));
2179         i = eval.iToken;
2180         break;
2181       case T.area:
2182         doCalcArea = !chk;
2183         sbCommand.append(" area");
2184         break;
2185       case T.atomicorbital:
2186       case T.orbital:
2187         surfaceObjectSeen = true;
2188         if (isBicolor && !isPhased) {
2189           sbCommand.append(" phase \"_orb\"");
2190           addShapeProperty(propertyList, "phase", "_orb");
2191         }
2192         float[] nlmZprs = new float[7];
2193         nlmZprs[0] = intParameter(++i);
2194         nlmZprs[1] = intParameter(++i);
2195         nlmZprs[2] = intParameter(++i);
2196         nlmZprs[3] = (isFloatParameter(i + 1) ? floatParameter(++i) : 6f);
2197         //if (surfaceObjectSeen)
2198         sbCommand.append(" atomicOrbital ").appendI((int) nlmZprs[0])
2199             .append(" ").appendI((int) nlmZprs[1]).append(" ")
2200             .appendI((int) nlmZprs[2]).append(" ").appendF(nlmZprs[3]);
2201         if (tokAt(i + 1) == T.point) {
2202           i += 2;
2203           nlmZprs[4] = intParameter(i);
2204           nlmZprs[5] = (tokAt(i + 1) == T.decimal ? floatParameter(++i) : 0);
2205           nlmZprs[6] = (tokAt(i + 1) == T.integer ? intParameter(++i)
2206               : ((int) -System.currentTimeMillis()) % 10000);
2207           //if (surfaceObjectSeen)
2208           sbCommand.append(" points ").appendI((int) nlmZprs[4]).appendC(' ')
2209               .appendF(nlmZprs[5]).appendC(' ').appendI((int) nlmZprs[6]);
2210         }
2211         propertyName = "hydrogenOrbital";
2212         propertyValue = nlmZprs;
2213         break;
2214       case T.binary:
2215         sbCommand.append(" binary");
2216         // for PMESH, specifically
2217         // ignore for now
2218         continue;
2219       case T.blockdata:
2220         sbCommand.append(" blockData");
2221         propertyName = "blockData";
2222         propertyValue = Boolean.TRUE;
2223         break;
2224       case T.cap:
2225       case T.slab:
2226         haveSlab = true;
2227         propertyName = (String) eval.theToken.value;
2228         propertyValue = getCapSlabObject(i, false);
2229         i = eval.iToken;
2230         break;
2231       case T.cavity:
2232         if (!isIsosurface)
2233           invArg();
2234         isCavity = true;
2235         float cavityRadius = (isFloatParameter(i + 1) ? floatParameter(++i)
2236             : 1.2f);
2237         float envelopeRadius = (isFloatParameter(i + 1) ? floatParameter(++i)
2238             : 10f);
2239         if (chk)
2240           continue;
2241         if (envelopeRadius > 50f) {
2242           eval.integerOutOfRange(0, 50);
2243           return;
2244         }
2245         sbCommand.append(" cavity ").appendF(cavityRadius).append(" ")
2246             .appendF(envelopeRadius);
2247         addShapeProperty(propertyList, "envelopeRadius",
2248             Float.valueOf(envelopeRadius));
2249         addShapeProperty(propertyList, "cavityRadius",
2250             Float.valueOf(cavityRadius));
2251         propertyName = "cavity";
2252         break;
2253       case T.contour:
2254       case T.contours:
2255         propertyName = "contour";
2256         sbCommand.append(" contour");
2257         switch (tokAt(i + 1)) {
2258         case T.discrete:
2259           propertyValue = eval.floatParameterSet(i + 2, 1, Integer.MAX_VALUE);
2260           sbCommand.append(" discrete ")
2261               .append(Escape.eAF((float[]) propertyValue));
2262           i = eval.iToken;
2263           break;
2264         case T.increment:
2265           pt = getPoint3f(i + 2, false);
2266           if (pt.z <= 0 || pt.y < pt.x)
2267             invArg(); // from to step
2268           if (pt.z == (int) pt.z && pt.z > (pt.y - pt.x))
2269             pt.z = (pt.y - pt.x) / pt.z;
2270           propertyValue = pt;
2271           i = eval.iToken;
2272           sbCommand.append(" increment ").append(Escape.eP(pt));
2273           break;
2274         default:
2275           propertyValue = Integer
2276               .valueOf(tokAt(i + 1) == T.integer ? intParameter(++i) : 0);
2277           sbCommand.append(" ").appendO(propertyValue);
2278           if (tokAt(i + 1) == T.integer) {
2279             addShapeProperty(propertyList, propertyName, propertyValue);
2280             propertyValue = Integer.valueOf(-Math.abs(intParameter(++i)));
2281             sbCommand.append(" ").appendO(propertyValue);
2282           }
2283         }
2284         break;
2285       case T.cutoff:
2286         sbCommand.append(" cutoff ");
2287         if (tokAt(++i) == T.plus) {
2288           propertyName = "cutoffPositive";
2289           propertyValue = Float.valueOf(cutoff = floatParameter(++i));
2290           sbCommand.append("+").appendO(propertyValue);
2291         } else if (isFloatParameter(i)) {
2292           propertyName = "cutoff";
2293           propertyValue = Float.valueOf(cutoff = floatParameter(i));
2294           sbCommand.appendO(propertyValue);
2295         } else {
2296           propertyName = "cutoffRange";
2297           propertyValue = eval.floatParameterSet(i, 2, 2);
2298           addShapeProperty(propertyList, "cutoff", Float.valueOf(0));
2299           sbCommand.append(Escape.eAF((float[]) propertyValue));
2300           i = eval.iToken;
2301         }
2302         break;
2303       case T.downsample:
2304         propertyName = "downsample";
2305         propertyValue = Integer.valueOf(intParameter(++i));
2306         //if (surfaceObjectSeen)
2307         sbCommand.append(" downsample ").appendO(propertyValue);
2308         break;
2309       case T.eccentricity:
2310         propertyName = "eccentricity";
2311         propertyValue = eval.getPoint4f(++i);
2312         //if (surfaceObjectSeen)
2313         sbCommand.append(" eccentricity ")
2314             .append(Escape.eP4((P4) propertyValue));
2315         i = eval.iToken;
2316         break;
2317       case T.ed:
2318         sbCommand.append(" ed");
2319         // electron density - never documented
2320         setMoData(propertyList, -1, null, 0, false, modelIndex, null, null,
2321             false);
2322         surfaceObjectSeen = true;
2323         continue;
2324       case T.debug:
2325       case T.nodebug:
2326         sbCommand.append(" ").appendO(eval.theToken.value);
2327         propertyName = "debug";
2328         propertyValue = (tok == T.debug ? Boolean.TRUE : Boolean.FALSE);
2329         break;
2330       case T.fixed:
2331         sbCommand.append(" fixed");
2332         propertyName = "fixed";
2333         propertyValue = Boolean.TRUE;
2334         break;
2335       case T.fullplane:
2336         sbCommand.append(" fullPlane");
2337         propertyName = "fullPlane";
2338         propertyValue = Boolean.TRUE;
2339         break;
2340       case T.functionxy:
2341       case T.functionxyz:
2342         // isosurface functionXY "functionName"|"data2d_xxxxx"
2343         // isosurface functionXYZ "functionName"|"data3d_xxxxx"
2344         // {origin} {ni ix iy iz} {nj jx jy jz} {nk kx ky kz}
2345         // or
2346         // isosurface origin.. step... count... functionXY[Z] = "x + y + z"
2347         boolean isFxyz = (tok == T.functionxyz);
2348         propertyName = "" + eval.theToken.value;
2349         Lst<Object> vxy = new Lst<Object>();
2350         propertyValue = vxy;
2351         isFxy = surfaceObjectSeen = true;
2352         //if (surfaceObjectSeen)
2353         sbCommand.append(" ").append(propertyName);
2354         String name = paramAsStr(++i);
2355         if (name.equals("=")) {
2356           //if (surfaceObjectSeen)
2357           sbCommand.append(" =");
2358           name = paramAsStr(++i);
2359           //if (surfaceObjectSeen)
2360           sbCommand.append(" ").append(PT.esc(name));
2361           vxy.addLast(name);
2362           if (!chk)
2363             addShapeProperty(propertyList, "func",
2364                 createFunction("__iso__", "x,y,z", name));
2365           //surfaceObjectSeen = true;
2366           break;
2367         }
2368         // override of function or data name when saved as a state
2369         String dName = PT.getQuotedAttribute(eval.fullCommand,
2370             "# DATA" + (isFxy ? "2" : ""));
2371         if (dName == null)
2372           dName = "inline";
2373         else
2374           name = dName;
2375         boolean isXYZ = (name.indexOf("data2d_") == 0);
2376         boolean isXYZV = (name.indexOf("data3d_") == 0);
2377         isInline = name.equals("inline");
2378         //if (!surfaceObjectSeen)
2379         sbCommand.append(" inline");
2380         vxy.addLast(name); // (0) = name
2381         P3 pt3 = getPoint3f(++i, false);
2382         //if (!surfaceObjectSeen)
2383         sbCommand.append(" ").append(Escape.eP(pt3));
2384         vxy.addLast(pt3); // (1) = {origin}
2385         P4 pt4;
2386         ptX = ++eval.iToken;
2387         vxy.addLast(pt4 = eval.getPoint4f(ptX)); // (2) = {ni ix iy iz}
2388         //if (!surfaceObjectSeen)
2389         sbCommand.append(" ").append(Escape.eP4(pt4));
2390         nX = (int) pt4.x;
2391         ptY = ++eval.iToken;
2392         vxy.addLast(pt4 = eval.getPoint4f(ptY)); // (3) = {nj jx jy jz}
2393         //if (!surfaceObjectSeen)
2394         sbCommand.append(" ").append(Escape.eP4(pt4));
2395         nY = (int) pt4.x;
2396         vxy.addLast(pt4 = eval.getPoint4f(++eval.iToken)); // (4) = {nk kx ky kz}
2397         //if (!surfaceObjectSeen)
2398         sbCommand.append(" ").append(Escape.eP4(pt4));
2399         nZ = (int) pt4.x;
2400 
2401         if (nX == 0 || nY == 0 || nZ == 0)
2402           invArg();
2403         if (!chk) {
2404           float[][] fdata = null;
2405           float[][][] xyzdata = null;
2406           if (isFxyz) {
2407             if (isInline) {
2408               nX = Math.abs(nX);
2409               nY = Math.abs(nY);
2410               nZ = Math.abs(nZ);
2411               xyzdata = floatArraySetXYZ(++eval.iToken, nX, nY, nZ);
2412             } else if (isXYZV) {
2413               xyzdata = (float[][][]) vwr.getDataObj(name, null,
2414                   JmolDataManager.DATA_TYPE_AFFF);
2415             } else {
2416               xyzdata = vwr.functionXYZ(name, nX, nY, nZ);
2417             }
2418             nX = Math.abs(nX);
2419             nY = Math.abs(nY);
2420             nZ = Math.abs(nZ);
2421             if (xyzdata == null) {
2422               eval.iToken = ptX;
2423               eval.errorStr(ScriptError.ERROR_what, "xyzdata is null.");
2424             }
2425             if (xyzdata.length != nX || xyzdata[0].length != nY
2426                 || xyzdata[0][0].length != nZ) {
2427               eval.iToken = ptX;
2428               eval.errorStr(ScriptError.ERROR_what,
2429                   "xyzdata[" + xyzdata.length + "][" + xyzdata[0].length + "]["
2430                       + xyzdata[0][0].length + "] is not of size [" + nX + "]["
2431                       + nY + "][" + nZ + "]");
2432             }
2433             vxy.addLast(xyzdata); // (5) = float[][][] data
2434             //if (!surfaceObjectSeen)
2435             sbCommand.append(" ").append(Escape.e(xyzdata));
2436           } else {
2437             if (isInline) {
2438               nX = Math.abs(nX);
2439               nY = Math.abs(nY);
2440               fdata = floatArraySet(++eval.iToken, nX, nY);
2441             } else if (isXYZ) {
2442               fdata = (float[][]) vwr.getDataObj(name, null,
2443                   JmolDataManager.DATA_TYPE_AFF);
2444               nX = (fdata == null ? 0 : fdata.length);
2445               nY = 3;
2446             } else {
2447               fdata = vwr.functionXY(name, nX, nY);
2448               nX = Math.abs(nX);
2449               nY = Math.abs(nY);
2450             }
2451             if (fdata == null) {
2452               eval.iToken = ptX;
2453               eval.errorStr(ScriptError.ERROR_what, "fdata is null.");
2454             }
2455             if (fdata.length != nX && !isXYZ) {
2456               eval.iToken = ptX;
2457               eval.errorStr(ScriptError.ERROR_what,
2458                   "fdata length is not correct: " + fdata.length + " " + nX
2459                       + ".");
2460             }
2461             for (int j = 0; j < nX; j++) {
2462               if (fdata[j] == null) {
2463                 eval.iToken = ptY;
2464                 eval.errorStr(ScriptError.ERROR_what,
2465                     "fdata[" + j + "] is null.");
2466               }
2467               if (fdata[j].length != nY) {
2468                 eval.iToken = ptY;
2469                 eval.errorStr(ScriptError.ERROR_what,
2470                     "fdata[" + j + "] is not the right length: "
2471                         + fdata[j].length + " " + nY + ".");
2472               }
2473             }
2474             vxy.addLast(fdata); // (5) = float[][] data
2475             //if (!surfaceObjectSeen)
2476             sbCommand.append(" ").append(Escape.e(fdata));
2477           }
2478         }
2479         i = eval.iToken;
2480         break;
2481       case T.val:
2482         boolean isBS = e.isAtomExpression(++i);
2483         P3[] probes = getAllPoints(i, 1);
2484         sbCommand.append(" value "
2485             + (isBS ? e.atomExpressionAt(i).toString() : Escape.eAP(probes)));
2486         propertyName = "probes";
2487         propertyValue = probes;
2488         i = e.iToken;
2489         break;
2490       case T.gridpoints:
2491         propertyName = "gridPoints";
2492         sbCommand.append(" gridPoints");
2493         break;
2494       case T.ignore:
2495         propertyName = "ignore";
2496         propertyValue = bsIgnore = atomExpressionAt(++i);
2497         sbCommand.append(" ignore ").append(Escape.eBS(bsIgnore));
2498         i = eval.iToken;
2499         break;
2500       case T.insideout:
2501         propertyName = "insideOut";
2502         sbCommand.append(" insideout");
2503         break;
2504       case T.internal:
2505       case T.interior:
2506       case T.pocket:
2507         //if (!surfaceObjectSeen)
2508         sbCommand.append(" ").appendO(eval.theToken.value);
2509         propertyName = "pocket";
2510         propertyValue = (tok == T.pocket ? Boolean.TRUE : Boolean.FALSE);
2511         break;
2512       case T.lobe:
2513         // lobe {eccentricity}
2514         propertyName = "lobe";
2515         propertyValue = eval.getPoint4f(++i);
2516         i = eval.iToken;
2517         //if (!surfaceObjectSeen)
2518         sbCommand.append(" lobe ").append(Escape.eP4((P4) propertyValue));
2519         surfaceObjectSeen = true;
2520         break;
2521       case T.lonepair:
2522       case T.lp:
2523         // lp {eccentricity}
2524         propertyName = "lp";
2525         propertyValue = eval.getPoint4f(++i);
2526         i = eval.iToken;
2527         //if (!surfaceObjectSeen)
2528         sbCommand.append(" lp ").append(Escape.eP4((P4) propertyValue));
2529         surfaceObjectSeen = true;
2530         break;
2531       case T.mapproperty:
2532         if (isMapped || slen == i + 1)
2533           invArg();
2534         isMapped = true;
2535         if ((isCavity || haveRadius || haveIntersection)
2536             && !surfaceObjectSeen) {
2537           surfaceObjectSeen = true;
2538           addShapeProperty(propertyList, "bsSolvent",
2539               (haveRadius || haveIntersection ? new BS()
2540                   : eval.lookupIdentifierValue("solvent")));
2541           addShapeProperty(propertyList, "sasurface", Float.valueOf(0));
2542         }
2543         if (sbCommand.length() == 0) {
2544           plane = (P4) getShapeProperty(JC.SHAPE_ISOSURFACE, "plane");
2545           if (plane == null) {
2546             if (getShapeProperty(JC.SHAPE_ISOSURFACE, "contours") != null) {
2547               addShapeProperty(propertyList, "nocontour", null);
2548             }
2549           } else {
2550             addShapeProperty(propertyList, "plane", plane);
2551             sbCommand.append("plane ").append(Escape.eP4(plane));
2552             planeSeen = true;
2553             plane = null;
2554           }
2555         } else if (!surfaceObjectSeen && !planeSeen) {
2556           invArg();
2557         }
2558         sbCommand.append("; isosurface map");
2559         addShapeProperty(propertyList, "map",
2560             (surfaceObjectSeen ? Boolean.TRUE : Boolean.FALSE));
2561         break;
2562       case T.maxset:
2563         propertyName = "maxset";
2564         propertyValue = Integer.valueOf(intParameter(++i));
2565         sbCommand.append(" maxSet ").appendO(propertyValue);
2566         break;
2567       case T.minset:
2568         propertyName = "minset";
2569         propertyValue = Integer.valueOf(intParameter(++i));
2570         sbCommand.append(" minSet ").appendO(propertyValue);
2571         break;
2572       case T.radical:
2573         // rad {eccentricity}
2574         surfaceObjectSeen = true;
2575         propertyName = "rad";
2576         propertyValue = eval.getPoint4f(++i);
2577         i = eval.iToken;
2578         //if (!surfaceObjectSeen)
2579         sbCommand.append(" radical ").append(Escape.eP4((P4) propertyValue));
2580         break;
2581       case T.modelbased:
2582         propertyName = "fixed";
2583         propertyValue = Boolean.FALSE;
2584         sbCommand.append(" modelBased");
2585         break;
2586       case T.molecular:
2587       case T.sasurface:
2588       case T.solvent:
2589         onlyOneModel = eval.theToken.value;
2590         float radius;
2591         if (tok == T.molecular) {
2592           propertyName = "molecular";
2593           sbCommand.append(" molecular");
2594           radius = (isFloatParameter(i + 1) ? floatParameter(++i) : 1.4f);
2595         } else {
2596           addShapeProperty(propertyList, "bsSolvent",
2597               eval.lookupIdentifierValue("solvent"));
2598           propertyName = (tok == T.sasurface ? "sasurface" : "solvent");
2599           sbCommand.append(" ").appendO(eval.theToken.value);
2600           radius = (isFloatParameter(i + 1) ? floatParameter(++i)
2601               : vwr.getFloat(T.solventproberadius));
2602         }
2603         sbCommand.append(" ").appendF(radius);
2604         propertyValue = Float.valueOf(radius);
2605         if (tokAt(i + 1) == T.full) {
2606           addShapeProperty(propertyList, "doFullMolecular", null);
2607           //if (!surfaceObjectSeen)
2608           sbCommand.append(" full");
2609           i++;
2610         }
2611         surfaceObjectSeen = true;
2612         break;
2613       case T.mrc:
2614         addShapeProperty(propertyList, "fileType", "Mrc");
2615         sbCommand.append(" mrc");
2616         continue;
2617       case T.type:
2618         String s = eval.stringParameter(++i);
2619         addShapeProperty(propertyList, "fileType", s);
2620         sbCommand.append(" type \"" + s + "\"");
2621         continue;
2622       case T.object:
2623       case T.obj:
2624         addShapeProperty(propertyList, "fileType", "Obj");
2625         sbCommand.append(" obj");
2626         continue;
2627       case T.msms:
2628         addShapeProperty(propertyList, "fileType", "Msms");
2629         sbCommand.append(" msms");
2630         continue;
2631       case T.phase:
2632         if (surfaceObjectSeen)
2633           invArg();
2634         propertyName = "phase";
2635         isPhased = true;
2636         propertyValue = (tokAt(i + 1) == T.string ? stringParameter(++i)
2637             : "_orb");
2638         sbCommand.append(" phase ").append(PT.esc((String) propertyValue));
2639         break;
2640       case T.pointsperangstrom:
2641       case T.resolution:
2642         propertyName = "resolution";
2643         propertyValue = Float.valueOf(floatParameter(++i));
2644         sbCommand.append(" resolution ").appendO(propertyValue);
2645         break;
2646       case T.reversecolor:
2647         propertyName = "reverseColor";
2648         propertyValue = Boolean.TRUE;
2649         sbCommand.append(" reversecolor");
2650         break;
2651       case T.rmsd:
2652       case T.sigma:
2653         propertyName = "sigma";
2654         propertyValue = Float.valueOf(sigma = floatParameter(++i));
2655         sbCommand.append(" sigma ").appendO(propertyValue);
2656         break;
2657       case T.geosurface:
2658         // geosurface [radius]
2659         propertyName = "geodesic";
2660         propertyValue = Float.valueOf(floatParameter(++i));
2661         //if (!surfaceObjectSeen)
2662         sbCommand.append(" geosurface ").appendO(propertyValue);
2663         surfaceObjectSeen = true;
2664         break;
2665       case T.sphere:
2666         // sphere [radius]
2667         propertyName = "sphere";
2668         propertyValue = Float.valueOf(floatParameter(++i));
2669         //if (!surfaceObjectSeen)
2670         sbCommand.append(" sphere ").appendO(propertyValue);
2671         surfaceObjectSeen = true;
2672         break;
2673       case T.squared:
2674         propertyName = "squareData";
2675         propertyValue = Boolean.TRUE;
2676         sbCommand.append(" squared");
2677         break;
2678       case T.inline:
2679         propertyName = (!surfaceObjectSeen && !planeSeen && !isMapped
2680             ? "readFile"
2681             : "mapColor");
2682         str = stringParameter(++i);
2683         if (str == null)
2684           invArg();
2685         // inline PMESH data
2686         if (isPmesh)
2687           str = PT.replaceWithCharacter(str, "{,}|", ' ');
2688         if (eval.debugHigh)
2689           Logger.debug("pmesh inline data:\n" + str);
2690         propertyValue = (chk ? null : str);
2691         addShapeProperty(propertyList, "fileName", "");
2692         sbCommand.append(" INLINE ").append(PT.esc(str));
2693         surfaceObjectSeen = true;
2694         break;
2695       case T.leftsquare:
2696       case T.spacebeforesquare:
2697       case T.varray:
2698         // [ float, filename, float, filename, ...]
2699         if (filesData != null || isWild)
2700           invArg();
2701         Lst<Object> list = eval.listParameter4(i, 2, Integer.MAX_VALUE, true);
2702         i = eval.iToken;
2703         int n = list.size() / 2;
2704         if (n == 0 || n * 2 != list.size())
2705           invArg();
2706         String[] files = new String[n];
2707         float[] factors = new float[n];
2708         sbCommand.append("[");
2709         try {
2710           for (int j = 0, ptf = 0; j < n; j++) {
2711             factors[j] = ((Float) list.get(ptf++)).floatValue();
2712             files[j] = e.checkFileExists("ISOSURFACE_" + j + "_", false,
2713                 (String) list.get(ptf++), i, false);
2714             sbCommand.appendF(factors[j]);
2715             sbCommand.append(" /*file*/").append(PT.esc(files[j]));
2716           }
2717           sbCommand.append("]");
2718         } catch (Exception e) {
2719           invArg();
2720         }
2721         filesData = new Object[] { files, factors };
2722         propertyName = (!surfaceObjectSeen && !planeSeen && !isMapped
2723             ? "readFile"
2724             : "mapColor");
2725         surfaceObjectSeen = true;
2726         if (chk)
2727           break;
2728         addShapeProperty(propertyList, "filesData", filesData);
2729         break;
2730       case T.eds:
2731       case T.edsdiff:
2732       case T.density:
2733       case T.string:
2734         boolean firstPass = (!surfaceObjectSeen && !planeSeen);
2735         String filename = null;
2736         propertyName = (firstPass && !isMapped ? "readFile" : "mapColor");
2737         if (tok == T.string) {
2738           filename = paramAsStr(i);
2739         } else if (tok == T.density) {
2740           filename = "=density/";
2741         }
2742         if (filename == null || filename.length() == 0 || filename.equals("*") || filename.equals("=")) {
2743           String pdbID = vwr.getPdbID();
2744           if (pdbID == null)
2745             eval.errorStr(ScriptError.ERROR_invalidArgument,
2746                 "no PDBID available");
2747           filename = "*" + (tok == T.edsdiff ? "*" : "") + pdbID;
2748         }
2749 
2750         /*
2751          * A file name, optionally followed by a calculation type and/or an integer file index.
2752          * Or =xxxx, an EDM from Uppsala Electron Density Server
2753          * If the model auxiliary info has "jmolSufaceInfo", we use that.
2754          */
2755         boolean checkWithin = false;
2756         if (filename.startsWith("http://eds.bmc.uu.se/eds/dfs/cb/")
2757             && filename.endsWith(".omap")) {
2758           // decommissoning Uppsala
2759           filename = (filename.indexOf("_diff") >= 0 ? "*" : "") + "*"
2760               + filename.substring(32, 36);
2761           //"http://eds.bmc.uu.se/eds/dfs/cb/1cbs/1cbs_diff.omap"
2762           // 0         1         2         3 xxxx
2763           // 0123456789012345678901234567890123456789
2764         }
2765 
2766         if (filename.startsWith("*") || filename.startsWith("=")) {
2767           boolean haveCutoff = (!Float.isNaN(cutoff) || !Float.isNaN(sigma));
2768           boolean isFull = (filename.indexOf("/full") >= 0);
2769           if (isFull)
2770             filename = PT.rep(filename, "/full", "");
2771           if (filename.indexOf("/diff") >= 0)
2772             filename = "*" + filename.substring(0, filename.indexOf("/diff"));
2773           if (filename.startsWith("**")) {
2774             if (!haveCutoff)
2775               addShapeProperty(propertyList, "sigma", Float.valueOf(sigma = 3));
2776             if (!isSign) {
2777               isSign = true;
2778               sbCommand.append(" sign");
2779               addShapeProperty(propertyList, "sign", Boolean.TRUE);
2780             }
2781           }
2782           String fn = filename;
2783           filename = (String) vwr.setLoadFormat(filename,
2784               (chk? '?' : isFull ? '_' : '-'), false);
2785           if (filename == null)
2786             eval.errorStr(ScriptError.ERROR_invalidArgument,
2787                 "error parsing filename: " + fn);
2788           // the initial dummy call just asertains that
2789           checkWithin = !isFull;
2790         }
2791         if (checkWithin) {
2792           if (pts == null && ptWithin == 0) {
2793             onlyOneModel = filename;
2794             if (modelIndex < 0)
2795               modelIndex = vwr.am.cmi;
2796             bs = vwr.getModelUndeletedAtomsBitSet(modelIndex);
2797             if (bs.nextSetBit(0) >= 0) {
2798               pts = getWithinDistanceVector(propertyList, 2.0f, null, bs,
2799                   false);
2800               sbCommand.append(" within 2.0 ").append(Escape.eBS(bs));
2801             }
2802           }
2803           if (pts != null && filename.indexOf("/0,0,0/0,0,0?") >= 0) {
2804             filename = filename.replace("0,0,0/0,0,0",
2805                 pts[0].x + "," + pts[0].y + "," + pts[0].z + "/"
2806                     + pts[pts.length - 1].x + "," + pts[pts.length - 1].y + ","
2807                     + pts[pts.length - 1].z);
2808           }
2809           if (firstPass)
2810             defaultMesh = true;
2811         }
2812         int p = (filename == null ? -1 : filename.indexOf("#-"));
2813         if (Float.isNaN(sigma) && Float.isNaN(cutoff)) {
2814           if ((p = filename.indexOf("#-cutoff=")) >= 0) {
2815             addShapeProperty(propertyList, "cutoff", Float.valueOf(cutoff = Float.parseFloat(filename.substring(p + 9))));
2816             sbCommand.append(" cutoff " + cutoff);
2817           } else if ((p = filename.indexOf("#-sigma=")) >= 0) {
2818             addShapeProperty(propertyList, "sigma", Float.valueOf(sigma = Float.parseFloat(filename.substring(p + 8))));
2819             sbCommand.append(" sigma " + sigma);
2820           }
2821         }
2822         if (!Float.isNaN(sigma))
2823           showString("using sigma = " + sigma);
2824         else if (!Float.isNaN(cutoff))
2825           showString("using cutoff = " + cutoff);
2826         if (firstPass && vwr.getP("_fileType").equals("Pdb")
2827             && Float.isNaN(sigma) && Float.isNaN(cutoff)) {
2828           // negative sigma just indicates that
2829           addShapeProperty(propertyList, "sigma", Float.valueOf(-1));
2830           sbCommand.append(" sigma -1.0");
2831         }
2832         if (filename.length() == 0) {
2833           if (modelIndex < 0)
2834             modelIndex = vwr.am.cmi;
2835           filename = eval.getFullPathName();
2836           propertyValue = vwr.ms.getInfo(modelIndex, "jmolSurfaceInfo"); // not implemented?
2837         }
2838         int fileIndex = -1;
2839         if (propertyValue == null && tokAt(i + 1) == T.integer)
2840           addShapeProperty(propertyList, "fileIndex",
2841               Integer.valueOf(fileIndex = intParameter(++i)));
2842         String stype = (tokAt(i + 1) == T.string ? stringParameter(++i) : null);
2843         // done reading parameters
2844         surfaceObjectSeen = true;
2845         if (chk) {
2846           break;
2847         }
2848         String[] fullPathNameOrError;
2849         String localName = null;
2850         if (propertyValue == null) {
2851           if (eval.fullCommand.indexOf("# FILE" + nFiles + "=") >= 0) {
2852             // old way, abandoned
2853             filename = PT.getQuotedAttribute(eval.fullCommand,
2854                 "# FILE" + nFiles);
2855             if (tokAt(i + 1) == T.as)
2856               i += 2; // skip that
2857           } else if (tokAt(i + 1) == T.as) {
2858             localName = vwr.fm.getFilePath(
2859                 stringParameter(eval.iToken = (i = i + 2)), false, false);
2860             fullPathNameOrError = vwr.getFullPathNameOrError(localName);
2861             localName = fullPathNameOrError[0];
2862             if (vwr.fm.getPathForAllFiles() != "") {
2863               // we use the LOCAL name when reading from a local path only (in the case of JMOL files)
2864               filename = localName;
2865               localName = null;
2866             } else {
2867               addShapeProperty(propertyList, "localName", localName);
2868             }
2869           }
2870         }
2871         // just checking here, and getting the full path name
2872         if (stype == null) {
2873           filename = e.checkFileExists("ISOSURFACE_" + (isMapped ? "MAP_" : ""),
2874               false, filename, i, false);
2875         }
2876         showString("reading isosurface data from " + filename);
2877 
2878         if (stype != null) {
2879           propertyValue = vwr.fm.cacheGet(filename, false);
2880           addShapeProperty(propertyList, "calculationType", stype);
2881         }
2882         if (propertyValue == null) {
2883           addShapeProperty(propertyList, "fileName", filename);
2884           if (localName != null)
2885             filename = localName;
2886           if (fileIndex >= 0)
2887             sbCommand.append(" ").appendI(fileIndex);
2888         }
2889         sbCommand.append(" /*file*/").append(PT.esc(filename));
2890         if (stype != null)
2891           sbCommand.append(" ").append(PT.esc(stype));
2892         break;
2893       case T.connect:
2894         propertyName = "connections";
2895         switch (tokAt(++i)) {
2896         case T.define:
2897         case T.bitset:
2898         case T.expressionBegin:
2899           propertyValue = new int[] { atomExpressionAt(i).nextSetBit(0) };
2900           break;
2901         default:
2902           propertyValue = new int[] {
2903               (int) eval.floatParameterSet(i, 1, 1)[0] };
2904           break;
2905         }
2906         i = eval.iToken;
2907         break;
2908       case T.atomindex:
2909         propertyName = "atomIndex";
2910         propertyValue = Integer.valueOf(intParameter(++i));
2911         break;
2912       case T.link:
2913         propertyName = "link";
2914         sbCommand.append(" link");
2915         break;
2916       case T.unitcell:
2917         if (iShape != JC.SHAPE_ISOSURFACE)
2918           invArg();
2919         if (tokAt(i + 1) == T.plus)
2920           i++;
2921         propertyName = "extendGrid";
2922         propertyValue = Float.valueOf(floatParameter(++i));
2923         sbCommand.append(" unitcell " + propertyValue);
2924         break;
2925       case T.lattice:
2926         if (iShape != JC.SHAPE_ISOSURFACE)
2927           invArg();
2928         pt = getPoint3f(++i, false);
2929         i = eval.iToken;
2930         if (pt.x <= 0 || pt.y <= 0 || pt.z <= 0)
2931           break;
2932         pt.x = (int) pt.x;
2933         pt.y = (int) pt.y;
2934         pt.z = (int) pt.z;
2935         sbCommand.append(" lattice ").append(Escape.eP(pt));
2936         if (isMapped) {
2937           propertyName = "mapLattice";
2938           propertyValue = pt;
2939         } else {
2940           lattice = pt;
2941           if (tokAt(i + 1) == T.fixed) {
2942             sbCommand.append(" fixed");
2943             fixLattice = true;
2944             i++;
2945           }
2946         }
2947         break;
2948       default:
2949         if (tok == T.identifier) {
2950           propertyName = "thisID";
2951           propertyValue = str;
2952         }
2953         /* I have no idea why this is here....
2954         if (planeSeen && !surfaceObjectSeen) {
2955           addShapeProperty(propertyList, "nomap", Float.valueOf(0));
2956           surfaceObjectSeen = true;
2957         }
2958         */
2959         if (!eval.setMeshDisplayProperty(iShape, 0, tok)) {
2960           if (T.tokAttr(tok, T.identifier) && !idSeen) {
2961             setShapeId(iShape, i, idSeen);
2962             i = eval.iToken;
2963             break;
2964           }
2965           invArg();
2966         }
2967         if (iptDisplayProperty == 0)
2968           iptDisplayProperty = i;
2969         i = slen - 1;
2970         break;
2971       }
2972       idSeen = (tok != T.delete);
2973       if (isWild && surfaceObjectSeen)
2974         invArg();
2975       if (propertyName != null)
2976         addShapeProperty(propertyList, propertyName, propertyValue);
2977     }
2978 
2979     // OK, now send them all
2980 
2981     if (!chk) {
2982       if ((isCavity || haveRadius) && !surfaceObjectSeen) {
2983         surfaceObjectSeen = true;
2984         addShapeProperty(propertyList, "bsSolvent",
2985             (haveRadius ? new BS() : eval.lookupIdentifierValue("solvent")));
2986         addShapeProperty(propertyList, "sasurface", Float.valueOf(0));
2987       }
2988       if (planeSeen && !surfaceObjectSeen && !isMapped) {
2989         // !isMapped mp.added 6/14/2012 12.3.30
2990         // because it was preventing planes from being mapped properly
2991         addShapeProperty(propertyList, "nomap", Float.valueOf(0));
2992         surfaceObjectSeen = true;
2993       }
2994       if (thisSet != null)
2995         addShapeProperty(propertyList, "getSurfaceSets", thisSet);
2996       if (discreteColixes != null) {
2997         addShapeProperty(propertyList, "colorDiscrete", discreteColixes);
2998       } else if ("sets".equals(colorScheme)) {
2999         addShapeProperty(propertyList, "setColorScheme", null);
3000       } else if (colorScheme != null) {
3001         ColorEncoder ce = vwr.cm.getColorEncoder(colorScheme);
3002         if (ce != null) {
3003           ce.isTranslucent = isColorSchemeTranslucent;
3004           ce.hi = Float.MAX_VALUE;
3005           addShapeProperty(propertyList, "remapColor", ce);
3006         }
3007       }
3008       if (surfaceObjectSeen && !isLcaoCartoon && sbCommand.indexOf(";") != 0) {
3009         propertyList.add(0, new Object[] { "newObject", null });
3010         boolean needSelect = (bsSelect == null);
3011         if (needSelect)
3012           bsSelect = BSUtil.copy(vwr.bsA());
3013         if (modelIndex < 0)
3014           modelIndex = vwr.am.cmi;
3015         bsSelect.and(vwr.getModelUndeletedAtomsBitSet(modelIndex));
3016         if (onlyOneModel != null) {
3017           BS bsModels = vwr.ms.getModelBS(bsSelect, false);
3018           if (bsModels.cardinality() > 1)
3019             eval.errorStr(ScriptError.ERROR_multipleModelsDisplayedNotOK,
3020                 "ISOSURFACE " + onlyOneModel);
3021           if (needSelect) {
3022             propertyList.add(0, new Object[] { "select", bsSelect });
3023             if (sbCommand.indexOf("; isosurface map") == 0) {
3024               sbCommand = new SB().append("; isosurface map select ")
3025                   .append(Escape.eBS(bsSelect)).append(sbCommand.substring(16));
3026             }
3027           }
3028         }
3029       }
3030       if (haveIntersection && !haveSlab) {
3031         if (!surfaceObjectSeen)
3032           addShapeProperty(propertyList, "sasurface", Float.valueOf(0));
3033         if (!isMapped) {
3034           addShapeProperty(propertyList, "map", Boolean.TRUE);
3035           addShapeProperty(propertyList, "select", bs);
3036           addShapeProperty(propertyList, "sasurface", Float.valueOf(0));
3037         }
3038         addShapeProperty(propertyList, "slab", getCapSlabObject(-100, false));
3039       }
3040 
3041       boolean timeMsg = (surfaceObjectSeen && vwr.getBoolean(T.showtiming));
3042       if (timeMsg)
3043         Logger.startTimer("isosurface");
3044       setShapeProperty(iShape, "setProperties", propertyList);
3045       if (timeMsg)
3046         showString(Logger.getTimerMsg("isosurface", 0));
3047       if (defaultMesh) {
3048         setShapeProperty(iShape, "token", Integer.valueOf(T.mesh));
3049         setShapeProperty(iShape, "token", Integer.valueOf(T.nofill));
3050         isFrontOnly = true;
3051         sbCommand.append(" mesh nofill frontOnly");
3052       }
3053     }
3054     if (lattice != null) { // before MAP, this is a display option
3055       setShapeProperty(iShape, "lattice", lattice);
3056       if (fixLattice)
3057         setShapeProperty(iShape, "fixLattice", Boolean.TRUE);
3058     }
3059     if (symops != null) // before MAP, this is a display option
3060       setShapeProperty(iShape, "symops", symops);
3061     if (isFrontOnly)
3062       setShapeProperty(iShape, "token", Integer.valueOf(T.frontonly));
3063     if (iptDisplayProperty > 0) {
3064       if (!eval.setMeshDisplayProperty(iShape, iptDisplayProperty, 0))
3065         invArg();
3066     }
3067     if (chk)
3068       return;
3069     Object area = null;
3070     Object volume = null;
3071     if (doCalcArea) {
3072       area = getShapeProperty(iShape, "area");
3073       if (area instanceof Float)
3074         vwr.setFloatProperty("isosurfaceArea", ((Float) area).floatValue());
3075       else
3076         vwr.g.setUserVariable("isosurfaceArea",
3077             SV.getVariableAD((double[]) area));
3078     }
3079     if (doCalcVolume) {
3080       volume = (doCalcVolume ? getShapeProperty(iShape, "volume") : null);
3081       if (volume instanceof Float)
3082         vwr.setFloatProperty("isosurfaceVolume", ((Float) volume).floatValue());
3083       else
3084         vwr.g.setUserVariable("isosurfaceVolume",
3085             SV.getVariableAD((double[]) volume));
3086     }
3087     if (!isLcaoCartoon) {
3088       String s = null;
3089       if (isMapped && !surfaceObjectSeen) {
3090         setShapeProperty(iShape, "finalize", sbCommand.toString());
3091       } else if (surfaceObjectSeen) {
3092         cmd = sbCommand.toString();
3093         setShapeProperty(iShape, "finalize",
3094             (cmd.indexOf("; isosurface map") == 0 ? ""
3095                 : " select " + Escape.eBS(bsSelect) + " ") + cmd);
3096         s = (String) getShapeProperty(iShape, "ID");
3097         if (s != null && !eval.tQuiet && !isSilent) {
3098           cutoff = ((Float) getShapeProperty(iShape, "cutoff")).floatValue();
3099           if (Float.isNaN(cutoff) && !Float.isNaN(sigma))
3100             Logger.error("sigma not supported");
3101           s += " created " + getShapeProperty(iShape, "message");
3102         }
3103       }
3104       String sarea, svol;
3105       if (doCalcArea || doCalcVolume) {
3106         sarea = (doCalcArea ? "isosurfaceArea = "
3107             + (area instanceof Float ? "" + area : Escape.eAD((double[]) area))
3108             : null);
3109         svol = (doCalcVolume
3110             ? "isosurfaceVolume = " + (volume instanceof Float ? "" + volume
3111                 : Escape.eAD((double[]) volume))
3112             : null);
3113         if (s == null) {
3114           if (doCalcArea)
3115             showString(sarea);
3116           if (doCalcVolume)
3117             showString(svol);
3118         } else {
3119           if (doCalcArea)
3120             s += "\n" + sarea;
3121           if (doCalcVolume)
3122             s += "\n" + svol;
3123         }
3124       }
3125       if (s != null && !isSilent)
3126         showString(s);
3127       if (surfaceObjectSeen) {
3128         s = (String) getShapeProperty(iShape, "output");
3129         if (s != null && !isSilent)
3130           showString(s);
3131       }
3132     }
3133 
3134     if (translucency != null)
3135       setShapeProperty(iShape, "translucency", translucency);
3136     setShapeProperty(iShape, "clear", null);
3137     if (toCache)
3138       setShapeProperty(iShape, "cache", null);
3139     if (!isSilent && !isDisplay && !haveSlab && eval.theTok != T.delete)
3140       listIsosurface(iShape);
3141   }
3142 
lcaoCartoon()3143   private void lcaoCartoon() throws ScriptException {
3144     ScriptEval eval = e;
3145     eval.sm.loadShape(JC.SHAPE_LCAOCARTOON);
3146     if (eval.tokAt(1) == T.list && listIsosurface(JC.SHAPE_LCAOCARTOON))
3147       return;
3148     setShapeProperty(JC.SHAPE_LCAOCARTOON, "init", eval.fullCommand);
3149     if (slen == 1) {
3150       setShapeProperty(JC.SHAPE_LCAOCARTOON, "lcaoID", null);
3151       return;
3152     }
3153     boolean idSeen = false;
3154     String translucency = null;
3155     for (int i = 1; i < slen; i++) {
3156       String propertyName = null;
3157       Object propertyValue = null;
3158       switch (getToken(i).tok) {
3159       case T.cap:
3160       case T.slab:
3161         propertyName = (String) eval.theToken.value;
3162         if (tokAt(i + 1) == T.off)
3163           eval.iToken = i + 1;
3164         propertyValue = getCapSlabObject(i, true);
3165         i = eval.iToken;
3166         break;
3167       case T.center:
3168         // serialized lcaoCartoon in isosurface format
3169         isosurface(JC.SHAPE_LCAOCARTOON);
3170         return;
3171       case T.rotate:
3172         float degx = 0;
3173         float degy = 0;
3174         float degz = 0;
3175         switch (getToken(++i).tok) {
3176         case T.x:
3177           degx = floatParameter(++i) * JC.radiansPerDegree;
3178           break;
3179         case T.y:
3180           degy = floatParameter(++i) * JC.radiansPerDegree;
3181           break;
3182         case T.z:
3183           degz = floatParameter(++i) * JC.radiansPerDegree;
3184           break;
3185         default:
3186           invArg();
3187         }
3188         propertyName = "rotationAxis";
3189         propertyValue = V3.new3(degx, degy, degz);
3190         break;
3191       case T.on:
3192       case T.display:
3193       case T.displayed:
3194         propertyName = "on";
3195         break;
3196       case T.off:
3197       case T.hide:
3198       case T.hidden:
3199         propertyName = "off";
3200         break;
3201       case T.delete:
3202         propertyName = "delete";
3203         break;
3204       case T.define:
3205       case T.bitset:
3206       case T.expressionBegin:
3207         propertyName = "select";
3208         propertyValue = atomExpressionAt(i);
3209         i = eval.iToken;
3210         break;
3211       case T.color:
3212         translucency = setColorOptions(null, i + 1, JC.SHAPE_LCAOCARTOON, -2);
3213         if (translucency != null)
3214           setShapeProperty(JC.SHAPE_LCAOCARTOON, "settranslucency",
3215               translucency);
3216         i = eval.iToken;
3217         idSeen = true;
3218         continue;
3219       case T.translucent:
3220       case T.opaque:
3221         eval.setMeshDisplayProperty(JC.SHAPE_LCAOCARTOON, i, eval.theTok);
3222         i = eval.iToken;
3223         idSeen = true;
3224         continue;
3225       case T.spacefill:
3226       case T.string:
3227         propertyValue = paramAsStr(i).toLowerCase();
3228         if (propertyValue.equals("spacefill"))
3229           propertyValue = "cpk";
3230         propertyName = "create";
3231         if (eval.optParameterAsString(i + 1).equalsIgnoreCase("molecular")) {
3232           i++;
3233           propertyName = "molecular";
3234         }
3235         break;
3236       case T.select:
3237         if (eval.isAtomExpression(i + 1)) {
3238           propertyName = "select";
3239           propertyValue = atomExpressionAt(i + 1);
3240           i = eval.iToken;
3241         } else {
3242           propertyName = "selectType";
3243           propertyValue = paramAsStr(++i);
3244           if (propertyValue.equals("spacefill"))
3245             propertyValue = "cpk";
3246         }
3247         break;
3248       case T.scale:
3249         propertyName = "scale";
3250         propertyValue = Float.valueOf(floatParameter(++i));
3251         break;
3252       case T.lonepair:
3253       case T.lp:
3254         propertyName = "lonePair";
3255         break;
3256       case T.radical:
3257       case T.rad:
3258         propertyName = "radical";
3259         break;
3260       case T.molecular:
3261         propertyName = "molecular";
3262         break;
3263       case T.create:
3264         propertyValue = paramAsStr(++i);
3265         propertyName = "create";
3266         if (eval.optParameterAsString(i + 1).equalsIgnoreCase("molecular")) {
3267           i++;
3268           propertyName = "molecular";
3269         }
3270         break;
3271       case T.id:
3272         propertyValue = eval.setShapeNameParameter(++i);
3273         i = eval.iToken;
3274         if (idSeen)
3275           invArg();
3276         propertyName = "lcaoID";
3277         break;
3278       default:
3279         if (eval.theTok == T.times || T.tokAttr(eval.theTok, T.identifier)) {
3280           if (eval.theTok != T.times)
3281             propertyValue = paramAsStr(i);
3282           if (idSeen)
3283             invArg();
3284           propertyName = "lcaoID";
3285           break;
3286         }
3287         break;
3288       }
3289       if (eval.theTok != T.delete)
3290         idSeen = true;
3291       if (propertyName == null)
3292         invArg();
3293       setShapeProperty(JC.SHAPE_LCAOCARTOON, propertyName, propertyValue);
3294     }
3295     setShapeProperty(JC.SHAPE_LCAOCARTOON, "clear", null);
3296   }
3297 
contact()3298   private boolean contact() throws ScriptException {
3299     ScriptEval eval = e;
3300     eval.sm.loadShape(JC.SHAPE_CONTACT);
3301     if (tokAt(1) == T.list && listIsosurface(JC.SHAPE_CONTACT))
3302       return false;
3303     int iptDisplayProperty = 0;
3304     eval.iToken = 1;
3305     String thisId = initIsosurface(JC.SHAPE_CONTACT);
3306     boolean idSeen = (thisId != null);
3307     boolean isWild = (idSeen
3308         && getShapeProperty(JC.SHAPE_CONTACT, "ID") == null);
3309     BS bsA = null;
3310     BS bsB = null;
3311     BS bs = null;
3312     RadiusData rd = null;
3313     float[] params = null;
3314     boolean colorDensity = false;
3315     SB sbCommand = new SB();
3316     int minSet = Integer.MAX_VALUE;
3317     int displayType = T.plane;
3318     int contactType = T.nada;
3319     float distance = Float.NaN;
3320     float saProbeRadius = Float.NaN;
3321     boolean localOnly = true;
3322     Boolean intramolecular = null;
3323     Object userSlabObject = null;
3324     int colorpt = 0;
3325     boolean colorByType = false;
3326     int tok;
3327     int modelIndex = Integer.MIN_VALUE;
3328     boolean okNoAtoms = (eval.iToken > 1);
3329     for (int i = eval.iToken; i < slen; ++i) {
3330       switch (tok = getToken(i).tok) {
3331       // these first do not need atoms defined
3332       default:
3333         okNoAtoms = true;
3334         if (!eval.setMeshDisplayProperty(JC.SHAPE_CONTACT, 0, eval.theTok)) {
3335           if (eval.theTok != T.times && !T.tokAttr(eval.theTok, T.identifier))
3336             invArg();
3337           thisId = setShapeId(JC.SHAPE_CONTACT, i, idSeen);
3338           i = eval.iToken;
3339           break;
3340         }
3341         if (iptDisplayProperty == 0)
3342           iptDisplayProperty = i;
3343         i = eval.iToken;
3344         continue;
3345       case T.id:
3346         okNoAtoms = true;
3347         setShapeId(JC.SHAPE_CONTACT, ++i, idSeen);
3348         isWild = (getShapeProperty(JC.SHAPE_CONTACT, "ID") == null);
3349         i = eval.iToken;
3350         break;
3351       case T.color:
3352         switch (tokAt(i + 1)) {
3353         case T.density:
3354           tok = T.nada;
3355           colorDensity = true;
3356           sbCommand.append(" color density");
3357           i++;
3358           break;
3359         case T.type:
3360           tok = T.nada;
3361           colorByType = true;
3362           sbCommand.append(" color type");
3363           i++;
3364           break;
3365         }
3366         if (tok == T.nada)
3367           break;
3368         //$FALL-THROUGH$ to translucent
3369       case T.translucent:
3370       case T.opaque:
3371         okNoAtoms = true;
3372         if (colorpt == 0)
3373           colorpt = i;
3374         eval.setMeshDisplayProperty(JC.SHAPE_CONTACT, i, eval.theTok);
3375         i = eval.iToken;
3376         break;
3377       case T.slab:
3378         okNoAtoms = true;
3379         userSlabObject = getCapSlabObject(i, false);
3380         setShapeProperty(JC.SHAPE_CONTACT, "slab", userSlabObject);
3381         i = eval.iToken;
3382         break;
3383 
3384       // now after this you need atoms
3385 
3386       case T.density:
3387         colorDensity = true;
3388         sbCommand.append(" density");
3389         if (isFloatParameter(i + 1)) {
3390           if (params == null)
3391             params = new float[1];
3392           params[0] = -Math.abs(floatParameter(++i));
3393           sbCommand.append(" " + -params[0]);
3394         }
3395         break;
3396       case T.resolution:
3397         float resolution = floatParameter(++i);
3398         if (resolution > 0) {
3399           sbCommand.append(" resolution ").appendF(resolution);
3400           setShapeProperty(JC.SHAPE_CONTACT, "resolution",
3401               Float.valueOf(resolution));
3402         }
3403         break;
3404       case T.model:
3405       case T.modelindex:
3406         modelIndex = (eval.theTok == T.modelindex ? intParameter(++i)
3407             : eval.modelNumberParameter(++i));
3408         sbCommand.append(" modelIndex " + modelIndex);
3409         break;
3410       case T.within:
3411       case T.distance:
3412         distance = floatParameter(++i);
3413         sbCommand.append(" within ").appendF(distance);
3414         break;
3415       case T.plus:
3416       case T.integer:
3417       case T.decimal:
3418         rd = eval.encodeRadiusParameter(i, false, false);
3419         if (rd == null)
3420           return false;
3421         sbCommand.append(" ").appendO(rd);
3422         i = eval.iToken;
3423         break;
3424       case T.intermolecular:
3425       case T.intramolecular:
3426         intramolecular = (tok == T.intramolecular ? Boolean.TRUE
3427             : Boolean.FALSE);
3428         sbCommand.append(" ").appendO(eval.theToken.value);
3429         break;
3430       case T.minset:
3431         minSet = intParameter(++i);
3432         break;
3433       case T.hbond:
3434       case T.clash:
3435       case T.vanderwaals:
3436         contactType = tok;
3437         sbCommand.append(" ").appendO(eval.theToken.value);
3438         break;
3439       case T.sasurface:
3440         if (isFloatParameter(i + 1))
3441           saProbeRadius = floatParameter(++i);
3442         //$FALL-THROUGH$
3443       case T.cap:
3444       case T.nci:
3445       case T.surface:
3446         localOnly = false;
3447         //$FALL-THROUGH$
3448       case T.trim:
3449       case T.full:
3450       case T.plane:
3451       case T.connect:
3452         displayType = tok;
3453         sbCommand.append(" ").appendO(eval.theToken.value);
3454         if (tok == T.sasurface)
3455           sbCommand.append(" ").appendF(saProbeRadius);
3456         break;
3457       case T.parameters:
3458         params = eval.floatParameterSet(++i, 1, 10);
3459         i = eval.iToken;
3460         break;
3461       case T.define:
3462       case T.bitset:
3463       case T.expressionBegin:
3464         if (isWild || bsB != null)
3465           invArg();
3466         bs = BSUtil.copy(atomExpressionAt(i));
3467         i = eval.iToken;
3468         if (bsA == null)
3469           bsA = bs;
3470         else
3471           bsB = bs;
3472         sbCommand.append(" ").append(Escape.eBS(bs));
3473         break;
3474       }
3475       idSeen = (eval.theTok != T.delete);
3476     }
3477     if (!okNoAtoms && bsA == null)
3478       error(ScriptError.ERROR_endOfStatementUnexpected);
3479     if (chk)
3480       return false;
3481 
3482     if (bsA != null) {
3483       // bond mode, intramolec set here
3484       if (contactType == T.vanderwaals && rd == null)
3485         rd = new RadiusData(null, 0, EnumType.OFFSET, VDW.AUTO);
3486       RadiusData rd1 = (rd == null
3487           ? new RadiusData(null, 0.26f, EnumType.OFFSET, VDW.AUTO)
3488           : rd);
3489       if (displayType == T.nci && bsB == null && intramolecular != null
3490           && intramolecular.booleanValue())
3491         bsB = bsA;
3492       else
3493         bsB = eval.getMathExt().setContactBitSets(bsA, bsB, localOnly, distance,
3494             rd1, true);
3495       switch (displayType) {
3496       case T.cap:
3497       case T.sasurface:
3498         BS bsSolvent = eval.lookupIdentifierValue("solvent");
3499         bsA.andNot(bsSolvent);
3500         bsB.andNot(bsSolvent);
3501         bsB.andNot(bsA);
3502         break;
3503       case T.surface:
3504         bsB.andNot(bsA);
3505         break;
3506       case T.nci:
3507         if (minSet == Integer.MAX_VALUE)
3508           minSet = 100;
3509         setShapeProperty(JC.SHAPE_CONTACT, "minset", Integer.valueOf(minSet));
3510         sbCommand.append(" minSet ").appendI(minSet);
3511         if (params == null)
3512           params = new float[] { 0.5f, 2 };
3513       }
3514 
3515       if (intramolecular != null) {
3516         params = (params == null ? new float[2] : AU.ensureLengthA(params, 2));
3517         params[1] = (intramolecular.booleanValue() ? 1 : 2);
3518       }
3519 
3520       if (params != null)
3521         sbCommand.append(" parameters ").append(Escape.eAF(params));
3522 
3523       // now adjust for type -- HBOND or HYDROPHOBIC or MISC
3524       // these are just "standard shortcuts" they are not necessary at all
3525       setShapeProperty(JC.SHAPE_CONTACT, "set",
3526           new Object[] { Integer.valueOf(contactType),
3527               Integer.valueOf(displayType), Boolean.valueOf(colorDensity),
3528               Boolean.valueOf(colorByType), bsA, bsB, rd,
3529               Float.valueOf(saProbeRadius), params, Integer.valueOf(modelIndex),
3530               sbCommand.toString() });
3531       if (colorpt > 0)
3532         eval.setMeshDisplayProperty(JC.SHAPE_CONTACT, colorpt, 0);
3533     }
3534     if (iptDisplayProperty > 0) {
3535       if (!eval.setMeshDisplayProperty(JC.SHAPE_CONTACT, iptDisplayProperty, 0))
3536         invArg();
3537     }
3538     if (userSlabObject != null && bsA != null)
3539       setShapeProperty(JC.SHAPE_CONTACT, "slab", userSlabObject);
3540     if (bsA != null && (displayType == T.nci || localOnly)) {
3541       Object volume = getShapeProperty(JC.SHAPE_CONTACT, "volume");
3542       double v;
3543       boolean isFull = (displayType == T.full);
3544       if (AU.isAD(volume)) {
3545         double[] vs = (double[]) volume;
3546         v = 0;
3547         for (int i = 0; i < vs.length; i++)
3548           v += (isFull ? vs[i] : Math.abs(vs[i])); // no abs value for full -- some are negative
3549       } else {
3550         v = ((Float) volume).floatValue();
3551       }
3552       v = (Math.round(v * 1000) / 1000.);
3553       if (colorDensity || displayType != T.trim) {
3554         int nsets = ((Integer) getShapeProperty(JC.SHAPE_CONTACT, "nSets"))
3555             .intValue(); // will be < 0 if FULL option
3556         String s = "Contacts: " + (nsets < 0 ? -nsets / 2 : nsets);
3557         if (v != 0)
3558           s += ", with " + (isFull ? "approx " : "net ") + "volume " + v
3559               + " A^3";
3560         showString(s);
3561       }
3562     }
3563     return true;
3564   }
3565 
cgo()3566   private boolean cgo() throws ScriptException {
3567     ScriptEval eval = e;
3568     eval.sm.loadShape(JC.SHAPE_CGO);
3569     if (tokAt(1) == T.list && listIsosurface(JC.SHAPE_CGO))
3570       return false;
3571     int iptDisplayProperty = 0;
3572     String thisId = initIsosurface(JC.SHAPE_CGO);
3573     boolean idSeen = (thisId != null);
3574     boolean isWild = (idSeen && getShapeProperty(JC.SHAPE_CGO, "ID") == null);
3575     boolean isInitialized = false;
3576     int modelIndex = -1;
3577     Lst<Object> data = null;
3578     float translucentLevel = Float.MAX_VALUE;
3579     int[] colorArgb = new int[] { Integer.MIN_VALUE };
3580     int intScale = 0;
3581     for (int i = eval.iToken; i < slen; ++i) {
3582       String propertyName = null;
3583       Object propertyValue = null;
3584       int tok = getToken(i).tok;
3585       switch (tok) {
3586       case T.leftsquare:
3587       case T.spacebeforesquare:
3588       case T.varray:
3589         if (data != null || isWild)
3590           invArg();
3591         data = new Lst<Object>();
3592         int[] ai = new int[] { i, slen };
3593         if (!eval.getShapePropertyData(JC.SHAPE_CGO, "data",
3594             new Object[] { st, ai, data, vwr }))
3595           invArg();
3596         i = ai[0];
3597         continue;
3598       case T.scale:
3599         if (++i >= slen)
3600           error(ScriptError.ERROR_numberExpected);
3601         switch (getToken(i).tok) {
3602         case T.integer:
3603           intScale = intParameter(i);
3604           continue;
3605         case T.decimal:
3606           intScale = Math.round(floatParameter(i) * 100);
3607           continue;
3608         }
3609         error(ScriptError.ERROR_numberExpected);
3610         break;
3611       case T.fixed:
3612         propertyName = "modelIndex";
3613         propertyValue = Integer.valueOf(-1);
3614         break;
3615       case T.modelindex:
3616       case T.model:
3617         modelIndex = (eval.theTok == T.modelindex ? intParameter(++i)
3618             : eval.modelNumberParameter(++i));
3619         propertyName = "modelIndex";
3620         propertyValue = Integer.valueOf(modelIndex);
3621         break;
3622       case T.color:
3623       case T.translucent:
3624       case T.opaque:
3625         translucentLevel = getColorTrans(eval, i, false, colorArgb);
3626         i = eval.iToken;
3627         idSeen = true;
3628         continue;
3629       case T.id:
3630         thisId = setShapeId(JC.SHAPE_CGO, ++i, idSeen);
3631         isWild = (getShapeProperty(JC.SHAPE_CGO, "ID") == null);
3632         i = eval.iToken;
3633         break;
3634       default:
3635         if (!eval.setMeshDisplayProperty(JC.SHAPE_CGO, 0, eval.theTok)) {
3636           if (eval.theTok == T.times || T.tokAttr(eval.theTok, T.identifier)) {
3637             thisId = setShapeId(JC.SHAPE_CGO, i, idSeen);
3638             i = eval.iToken;
3639             break;
3640           }
3641           invArg();
3642         }
3643         if (iptDisplayProperty == 0)
3644           iptDisplayProperty = i;
3645         i = eval.iToken;
3646         continue;
3647       }
3648       idSeen = (eval.theTok != T.delete);
3649       if (data != null && !isInitialized) {
3650         propertyName = "points";
3651         propertyValue = Integer.valueOf(intScale);
3652         isInitialized = true;
3653         intScale = 0;
3654       }
3655       if (propertyName != null)
3656         setShapeProperty(JC.SHAPE_CGO, propertyName, propertyValue);
3657     }
3658     finalizeObject(JC.SHAPE_CGO, colorArgb[0], translucentLevel, intScale,
3659         data != null, data, iptDisplayProperty, null);
3660     return true;
3661   }
3662 
3663   /**
3664    *
3665    * @param bsSelected
3666    * @param bsIgnore
3667    * @param fileName
3668    * @return calculated atom potentials
3669    */
getAtomicPotentials(BS bsSelected, BS bsIgnore, String fileName)3670   private float[] getAtomicPotentials(BS bsSelected, BS bsIgnore,
3671                                       String fileName) {
3672     float[] potentials = new float[vwr.ms.ac];
3673     MepCalculation m = (MepCalculation) Interface
3674         .getOption("quantum.MlpCalculation", vwr, "script");
3675     m.set(vwr);
3676     String data = (fileName == null ? null
3677         : vwr.getFileAsString3(fileName, false, null));
3678     try {
3679       m.assignPotentials(vwr.ms.at, potentials,
3680           vwr.getSmartsMatch("a", bsSelected),
3681           vwr.getSmartsMatch("/noAromatic/[$(C=O),$(O=C),$(NC=O)]", bsSelected),
3682           bsIgnore, data);
3683     } catch (Exception e) {
3684     }
3685     return potentials;
3686   }
3687 
getCapSlabObject(int i, boolean isLcaoCartoon)3688   private Object getCapSlabObject(int i, boolean isLcaoCartoon)
3689       throws ScriptException {
3690     if (i < 0) {
3691       // standard range -100 to 0
3692       return TempArray.getSlabWithinRange(i, 0);
3693     }
3694     ScriptEval eval = e;
3695     Object data = null;
3696     int tok0 = tokAt(i);
3697     boolean isSlab = (tok0 == T.slab);
3698     int tok = tokAt(i + 1);
3699     P4 plane = null;
3700     P3[] pts = null;
3701     float d, d2;
3702     BS bs = null;
3703     Short slabColix = null;
3704     Integer slabMeshType = null;
3705     if (tok == T.translucent) {
3706       float slabTranslucency = (isFloatParameter(++i + 1) ? floatParameter(++i)
3707           : 0.5f);
3708       if (eval.isColorParam(i + 1)) {
3709         slabColix = Short.valueOf(
3710             C.getColixTranslucent3(C.getColix(eval.getArgbParam(i + 1)),
3711                 slabTranslucency != 0, slabTranslucency));
3712         i = eval.iToken;
3713       } else {
3714         slabColix = Short.valueOf(C.getColixTranslucent3(C.INHERIT_COLOR,
3715             slabTranslucency != 0, slabTranslucency));
3716       }
3717       switch (tok = tokAt(i + 1)) {
3718       case T.mesh:
3719       case T.fill:
3720         slabMeshType = Integer.valueOf(tok);
3721         tok = tokAt(++i + 1);
3722         break;
3723       default:
3724         slabMeshType = Integer.valueOf(T.fill);
3725         break;
3726       }
3727     }
3728     //TODO: check for compatibility with LCAOCARTOONS
3729     switch (tok) {
3730     case T.off:
3731       eval.iToken = i + 1;
3732       return Integer.valueOf(Integer.MIN_VALUE);
3733     case T.none:
3734       eval.iToken = i + 1;
3735       break;
3736     case T.dollarsign:
3737       // do we need distance here? "-" here?
3738       i++;
3739       data = new Object[] { Float.valueOf(1), paramAsStr(++i) };
3740       tok = T.mesh;
3741       break;
3742     case T.within:
3743       // isosurface SLAB WITHIN RANGE f1 f2
3744       i++;
3745       if (tokAt(++i) == T.range) {
3746         d = floatParameter(++i);
3747         d2 = floatParameter(++i);
3748         data = new Object[] { Float.valueOf(d), Float.valueOf(d2) };
3749         tok = T.range;
3750       } else if (isFloatParameter(i)) {
3751         // isosurface SLAB WITHIN distance {atomExpression}|[point array]
3752         d = floatParameter(i);
3753         if (eval.isCenterParameter(++i)) {
3754           Object[] ret = new Object[1];
3755           P3 pt = eval.centerParameter(i, ret);
3756           if (chk || !(ret[0] instanceof BS)) {
3757             pts = new P3[] { pt };
3758           } else {
3759             Atom[] atoms = vwr.ms.at;
3760             bs = (BS) ret[0];
3761             pts = new P3[bs.cardinality()];
3762             for (int k = 0, j = bs.nextSetBit(0); j >= 0; j = bs
3763                 .nextSetBit(j + 1), k++)
3764               pts[k] = atoms[j];
3765           }
3766         } else {
3767           pts = eval.getPointArray(i, -1, false);
3768         }
3769         if (pts.length == 0) {
3770           eval.iToken = i;
3771           invArg();
3772         }
3773         data = new Object[] { Float.valueOf(d), pts, bs };
3774       } else {
3775         data = eval.getPointArray(i, 4, false);
3776         tok = T.boundbox;
3777       }
3778       break;
3779     case T.boundbox:
3780       eval.iToken = i + 1;
3781       data = BoxInfo.toOABC(vwr.ms.getBBoxVertices(), null);
3782       break;
3783     //case Token.slicebox:
3784     // data = BoxInfo.getCriticalPoints(((JmolViewer)(vwr)).slicer.getSliceVert(), null);
3785     //eval.iToken = i + 1;
3786     //break;
3787     case T.brillouin:
3788     case T.unitcell:
3789       eval.iToken = i + 1;
3790       SymmetryInterface unitCell = vwr.getCurrentUnitCell();
3791       if (unitCell == null) {
3792         if (tok == T.unitcell)
3793           invArg();
3794       } else {
3795         pts = BoxInfo.toOABC(unitCell.getUnitCellVerticesNoOffset(),
3796             unitCell.getCartesianOffset());
3797         int iType = (int) unitCell
3798             .getUnitCellInfoType(SimpleUnitCell.INFO_DIMENSIONS);
3799         V3 v1 = null;
3800         V3 v2 = null;
3801         switch (iType) {
3802         case 3:
3803           break;
3804         case 1: // polymer
3805           v2 = V3.newVsub(pts[2], pts[0]);
3806           v2.scale(1000f);
3807           //$FALL-THROUGH$
3808         case 2: // slab
3809           // "a b c" is really "z y x"
3810           v1 = V3.newVsub(pts[1], pts[0]);
3811           v1.scale(1000f);
3812           pts[0].sub(v1);
3813           pts[1].scale(2000f);
3814           if (iType == 1) {
3815             pts[0].sub(v2);
3816             pts[2].scale(2000f);
3817           }
3818           break;
3819         }
3820         data = pts;
3821       }
3822       break;
3823     case T.define:
3824     case T.bitset:
3825     case T.expressionBegin:
3826       data = atomExpressionAt(i + 1);
3827       tok = T.decimal;
3828       if (!eval.isCenterParameter(++eval.iToken)) {
3829         isSlab = true;
3830         break;
3831       }
3832       data = null;
3833       //$FALL-THROUGH$
3834     default:
3835       // isosurface SLAB n
3836       // isosurface SLAB -100. 0.  as "within range"
3837       if (!isLcaoCartoon && isSlab && isFloatParameter(i + 1)) {
3838         d = floatParameter(++i);
3839         if (!isFloatParameter(i + 1))
3840           return Integer.valueOf((int) d);
3841         d2 = floatParameter(++i);
3842         data = new Object[] { Float.valueOf(d), Float.valueOf(d2) };
3843         tok = T.range;
3844         break;
3845       }
3846       // isosurface SLAB [plane]
3847       plane = eval.planeParameter(++i);
3848       float off = (isFloatParameter(eval.iToken + 1)
3849           ? floatParameter(++eval.iToken)
3850           : Float.NaN);
3851       if (!Float.isNaN(off))
3852         plane.w -= off;
3853       data = plane;
3854       tok = T.plane;
3855     }
3856     Object colorData = (slabMeshType == null ? null
3857         : new Object[] { slabMeshType, slabColix });
3858     return TempArray.getSlabObjectType(tok, data, !isSlab, colorData);
3859   }
3860 
setColorOptions(SB sb, int index, int iShape, int nAllowed)3861   private String setColorOptions(SB sb, int index, int iShape, int nAllowed)
3862       throws ScriptException {
3863     ScriptEval eval = e;
3864     getToken(index);
3865     String translucency = "opaque";
3866     if (eval.theTok == T.translucent) {
3867       translucency = "translucent";
3868       if (nAllowed < 0) {
3869         float value = (isFloatParameter(index + 1) ? floatParameter(++index)
3870             : Float.MAX_VALUE);
3871         eval.setShapeTranslucency(iShape, null, "translucent", value, null);
3872         if (sb != null) {
3873           sb.append(" translucent");
3874           if (value != Float.MAX_VALUE)
3875             sb.append(" ").appendF(value);
3876         }
3877       } else {
3878         eval.setMeshDisplayProperty(iShape, index, eval.theTok);
3879       }
3880     } else if (eval.theTok == T.opaque) {
3881       if (nAllowed >= 0)
3882         eval.setMeshDisplayProperty(iShape, index, eval.theTok);
3883     } else {
3884       eval.iToken--;
3885     }
3886     nAllowed = Math.abs(nAllowed);
3887     for (int i = 0; i < nAllowed; i++) {
3888       if (eval.isColorParam(eval.iToken + 1)) {
3889         int color = eval.getArgbParam(++eval.iToken);
3890         setShapeProperty(iShape, "colorRGB", Integer.valueOf(color));
3891         if (sb != null)
3892           sb.append(" ").append(Escape.escapeColor(color));
3893       } else if (eval.iToken < index) {
3894         invArg();
3895       } else {
3896         break;
3897       }
3898     }
3899     return translucency;
3900   }
3901 
3902   /**
3903    * for the ISOSURFACE command
3904    *
3905    * @param fname
3906    * @param xyz
3907    * @param ret
3908    * @return [ ScriptFunction, Params ]
3909    */
createFunction(String fname, String xyz, String ret)3910   private Object[] createFunction(String fname, String xyz, String ret) {
3911     ScriptEval e = (new ScriptEval()).setViewer(vwr);
3912     try {
3913       e.compileScript(null,
3914           "function " + fname + "(" + xyz + ") { return " + ret + "}", false);
3915       Lst<SV> params = new Lst<SV>();
3916       for (int i = 0; i < xyz.length(); i += 2)
3917         params.addLast(SV.newF(0).setName(xyz.substring(i, i + 1)));
3918       return new Object[] { e.aatoken[0][1].value, params };
3919     } catch (Exception ex) {
3920       return null;
3921     }
3922   }
3923 
getWithinDistanceVector(Lst<Object[]> propertyList, float distance, P3 ptc, BS bs, boolean isShow)3924   private P3[] getWithinDistanceVector(Lst<Object[]> propertyList,
3925                                        float distance, P3 ptc, BS bs,
3926                                        boolean isShow) {
3927     Lst<P3> v = new Lst<P3>();
3928     P3[] pts = new P3[2];
3929     if (bs == null) {
3930       P3 pt1 = P3.new3(distance, distance, distance);
3931       P3 pt0 = P3.newP(ptc);
3932       pt0.sub(pt1);
3933       pt1.add(ptc);
3934       pts[0] = pt0;
3935       pts[1] = pt1;
3936       v.addLast(ptc);
3937     } else {
3938       BoxInfo bbox = vwr.ms.getBoxInfo(bs, -Math.abs(distance * 2));
3939       pts[0] = bbox.getBoundBoxVertices()[0];
3940       pts[1] = bbox.getBoundBoxVertices()[BoxInfo.XYZ];
3941       if (bs.cardinality() == 1)
3942         v.addLast(vwr.ms.at[bs.nextSetBit(0)]);
3943     }
3944     if (v.size() == 1 && !isShow) {
3945       addShapeProperty(propertyList, "withinDistance", Float.valueOf(distance));
3946       addShapeProperty(propertyList, "withinPoint", v.get(0));
3947     }
3948     addShapeProperty(propertyList, (isShow ? "displayWithin" : "withinPoints"),
3949         new Object[] { Float.valueOf(distance), pts, bs, v });
3950     return pts;
3951   }
3952 
addShapeProperty(Lst<Object[]> propertyList, String key, Object value)3953   private void addShapeProperty(Lst<Object[]> propertyList, String key,
3954                                 Object value) {
3955     if (chk)
3956       return;
3957     propertyList.addLast(new Object[] { key, value });
3958   }
3959 
floatArraySetXYZ(int i, int nX, int nY, int nZ)3960   private float[][][] floatArraySetXYZ(int i, int nX, int nY, int nZ)
3961       throws ScriptException {
3962     ScriptEval eval = e;
3963     int tok = tokAt(i++);
3964     if (tok == T.spacebeforesquare)
3965       tok = tokAt(i++);
3966     if (tok != T.leftsquare || nX <= 0)
3967       invArg();
3968     float[][][] fparams = AU.newFloat3(nX, -1);
3969     int n = 0;
3970     while (tok != T.rightsquare) {
3971       tok = getToken(i).tok;
3972       switch (tok) {
3973       case T.spacebeforesquare:
3974       case T.rightsquare:
3975         continue;
3976       case T.comma:
3977         i++;
3978         break;
3979       case T.leftsquare:
3980         fparams[n++] = floatArraySet(i, nY, nZ);
3981         i = ++eval.iToken;
3982         tok = T.nada;
3983         if (n == nX && tokAt(i) != T.rightsquare)
3984           invArg();
3985         break;
3986       default:
3987         invArg();
3988       }
3989     }
3990     return fparams;
3991   }
3992 
floatArraySet(int i, int nX, int nY)3993   private float[][] floatArraySet(int i, int nX, int nY)
3994       throws ScriptException {
3995     int tok = tokAt(i++);
3996     if (tok == T.spacebeforesquare)
3997       tok = tokAt(i++);
3998     if (tok != T.leftsquare)
3999       invArg();
4000     float[][] fparams = AU.newFloat2(nX);
4001     int n = 0;
4002     while (tok != T.rightsquare) {
4003       tok = getToken(i).tok;
4004       switch (tok) {
4005       case T.spacebeforesquare:
4006       case T.rightsquare:
4007         continue;
4008       case T.comma:
4009         i++;
4010         break;
4011       case T.leftsquare:
4012         i++;
4013         float[] f = new float[nY];
4014         fparams[n++] = f;
4015         for (int j = 0; j < nY; j++) {
4016           f[j] = floatParameter(i++);
4017           if (tokAt(i) == T.comma)
4018             i++;
4019         }
4020         if (tokAt(i++) != T.rightsquare)
4021           invArg();
4022         tok = T.nada;
4023         if (n == nX && tokAt(i) != T.rightsquare)
4024           invArg();
4025         break;
4026       default:
4027         invArg();
4028       }
4029     }
4030     return fparams;
4031   }
4032 
initIsosurface(int iShape)4033   private String initIsosurface(int iShape) throws ScriptException {
4034 
4035     // handle isosurface/mo/pmesh delete and id delete here
4036 
4037     ScriptEval eval = e;
4038     setShapeProperty(iShape, "init", eval.fullCommand);
4039     eval.iToken = 0;
4040     int tok1 = tokAt(1);
4041     int tok2 = tokAt(2);
4042     if (tok1 == T.delete || tok2 == T.delete && tokAt(++eval.iToken) == T.all) {
4043       setShapeProperty(iShape, "delete", null);
4044       eval.iToken += 2;
4045       if (slen > eval.iToken) {
4046         setShapeProperty(iShape, "init", eval.fullCommand);
4047         setShapeProperty(iShape, "thisID", MeshCollection.PREVIOUS_MESH_ID);
4048       }
4049       return null;
4050     }
4051     eval.iToken = 1;
4052     if (!eval.setMeshDisplayProperty(iShape, 0, tok1)) {
4053       setShapeProperty(iShape, "thisID", MeshCollection.PREVIOUS_MESH_ID);
4054       if (iShape != JC.SHAPE_DRAW)
4055         setShapeProperty(iShape, "title", new String[] { eval.thisCommand });
4056       if (tok1 != T.id && (tok2 == T.times
4057           || tok1 == T.times && eval.setMeshDisplayProperty(iShape, 0, tok2))) {
4058         String id = setShapeId(iShape, 1, false);
4059         eval.iToken++;
4060         return id;
4061       }
4062     }
4063     return null;
4064   }
4065 
listIsosurface(int iShape)4066   private boolean listIsosurface(int iShape) throws ScriptException {
4067     String s = (slen > 3 ? "0"
4068         : tokAt(2) == T.nada ? "" : " " + getToken(2).value);
4069     if (!chk)
4070       showString((String) getShapeProperty(iShape, "list" + s));
4071     return true;
4072   }
4073 
4074   /**
4075    *
4076    * @param type
4077    *        unitcell or boundbox
4078    * @param plane
4079    *        plane to intersect, or null for just the full box
4080    * @param scale
4081    * @param uc
4082    * @param flags
4083    *        1 -- edges only 2 -- triangles only 3 -- both
4084    * @return Vector
4085    */
getPlaneIntersection(int type, P4 plane, SymmetryInterface uc, float scale, int flags)4086   private Lst<Object> getPlaneIntersection(int type, P4 plane,
4087                                            SymmetryInterface uc, float scale,
4088                                            int flags) {
4089     T3[] pts = null;
4090     switch (type) {
4091     case T.unitcell:
4092       if (uc == null)
4093         return null;
4094       pts = uc.getCanonicalCopy(scale, true);
4095       break;
4096     case T.boundbox:
4097       pts = BoxInfo.getCanonicalCopy(vwr.ms.getBoxInfo().getBoundBoxVertices(),
4098           scale);
4099       break;
4100     }
4101     Triangulator t = vwr.getTriangulator(); // this instantiation forces reflection to get Triangulator class
4102     if (plane != null)
4103       return t.intersectPlane(plane, pts, flags);
4104     Lst<Object> v = new Lst<Object>();
4105     v.addLast(pts);
4106     v.addLast(Triangulator.fullCubePolygon);
4107     return v;
4108   }
4109 
4110 }
4111