1 /* $RCSfile$
2  * $Author: hansonr $
3  * $Date: 2006-03-12 21:37:51 -0600 (Sun, 12 Mar 2006) $
4  * $Revision: 4586 $
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.shapespecial;
26 
27 import java.util.Hashtable;
28 import java.util.Map;
29 
30 import javajs.util.AU;
31 import javajs.util.Lst;
32 import javajs.util.P3;
33 import javajs.util.PT;
34 import javajs.util.SB;
35 import javajs.util.V3;
36 
37 import javajs.util.BS;
38 import org.jmol.modelset.Atom;
39 import org.jmol.modelset.Bond;
40 import org.jmol.modelset.BondIterator;
41 import org.jmol.script.T;
42 import org.jmol.shape.Shape;
43 import org.jmol.util.C;
44 import org.jmol.util.Edge;
45 import org.jmol.util.JmolMolecule;
46 import org.jmol.util.Logger;
47 
48 
49 
50 public class Dipoles extends Shape {
51 
52   final static short DEFAULT_MAD = 10;
53   final static float DEFAULT_OFFSETSIDE = 0.40f;
54 
55   public int dipoleCount = 0;
56   public Dipole[] dipoles = new Dipole[4];
57 
58   private Dipole currentDipole;
59   private Dipole tempDipole;
60   private P3 startCoord = new P3();
61   private P3 endCoord = new P3();
62   private float dipoleValue;
63   private boolean isUserValue;
64   private boolean isBond;
65   private boolean iHaveTwoEnds;
66   private int atomIndex1;
67   private int atomIndex2;
68   private short colix;
69   private V3 calculatedDipole;
70   private String wildID;
71   private short mad;
72 
73   @Override
initShape()74   public void initShape() {
75     // nothing to do
76   }
77 
78   @Override
setProperty(String propertyName, Object value, BS bs)79   public void setProperty(String propertyName, Object value, BS bs) {
80 
81     if ("init" == propertyName) {
82       tempDipole = new Dipole();
83       tempDipole.dipoleValue = 1;
84       tempDipole.mad = DEFAULT_MAD;
85       atomIndex1 = -1;
86       tempDipole.modelIndex = -1;
87       dipoleValue = 0;
88       calculatedDipole = null;
89       mad = -1;
90       isUserValue = isBond = iHaveTwoEnds = false;
91       return;
92     }
93 
94     if ("calculate" == propertyName) {
95       try {
96         calculatedDipole = vwr.calculateMolecularDipole((BS) value);
97       } catch (Exception e) {
98       }
99       Logger.info("calculated molecular dipole = " + calculatedDipole + " "
100           + (calculatedDipole == null ? "" : "" + calculatedDipole.length()));
101       return;
102     }
103 
104     if ("thisID" == propertyName) {
105       wildID = null;
106       String thisID = (String) value;
107       if (thisID == null || PT.isWild(thisID)) {
108         currentDipole = null;
109         if (thisID != null)
110           wildID = thisID.toUpperCase();
111         return;
112       }
113       currentDipole = findDipole(thisID);
114       if (currentDipole == null)
115         currentDipole = allocDipole(thisID, "");
116       tempDipole = currentDipole;
117       if (thisID.equals("molecular"))
118         getMolecular(null);
119       return;
120     }
121 
122     if ("bonds" == propertyName) {
123       isBond = true;
124       currentDipole = null;
125       for (int i = dipoleCount; --i >= 0;)
126         if (isBondDipole(i))
127           return;
128       getBondDipoles(); // only once if any bond dipoles are defined
129       return;
130     }
131 
132     if ("all" == propertyName) {
133       tempDipole.lstDipoles = new Lst<Object>();
134       return;
135     }
136 
137     if ("on" == propertyName) {
138       setPropertyTok(T.on, isBond, 0, 0);
139       return;
140     }
141 
142     if ("off" == propertyName) {
143       setPropertyTok(T.off, isBond, 0, 0);
144       return;
145     }
146 
147     if ("delete" == propertyName) {
148       if (wildID == null && currentDipole == null) {
149         clear(false);
150         return;
151       }
152       setPropertyTok(T.delete, isBond, 0, 0);
153       return;
154     }
155 
156     if ("width" == propertyName) {
157       mad = tempDipole.mad = (short) (((Float) value).floatValue() * 1000);
158       if (currentDipole == null)
159         setPropertyTok(T.wireframe, isBond, mad, 0); //
160       return;
161     }
162 
163     if ("offset" == propertyName) {
164       float offset = tempDipole.offsetAngstroms = ((Float) value).floatValue();
165       if (currentDipole == null)
166         setPropertyTok(T.axes, isBond, 0, offset);
167       return;
168     }
169 
170     if ("offsetPt" == propertyName) {
171       tempDipole.offsetPt = (P3) value;
172       if (currentDipole != null) {
173         currentDipole.setOffsetPt(tempDipole.offsetPt);
174       }
175       return;
176     }
177 
178     if ("offsetPercent" == propertyName) {
179       int offsetPercent = tempDipole.offsetPercent = ((Integer) value)
180           .intValue();
181       if (tempDipole.dipoleValue != 0)
182         tempDipole.offsetAngstroms = offsetPercent / 100f
183             * tempDipole.dipoleValue;
184       if (currentDipole == null)
185         setPropertyTok(T.percent, isBond, 0, offsetPercent / 100f);
186       return;
187     }
188 
189     if ("offsetSide" == propertyName) {
190       float offsetSide = ((Float) value).floatValue();
191       setPropertyTok(T.sidechain, isBond, 0, offsetSide);
192       return;
193     }
194 
195     if ("cross" == propertyName) {
196       setPropertyTok(T.cross, isBond, (((Boolean) value).booleanValue() ? 1 : 0),
197           0);
198       return;
199     }
200 
201     if ("color" == propertyName) {
202       colix = C.getColixO(value);
203       if (isBond) {
204         setColixDipole(colix, Edge.BOND_COVALENT_MASK, bs);
205       } else if (value != null) {
206         setPropertyTok(T.color, false, 0, 0);
207       }
208       return;
209     }
210 
211     if ("translucency" == propertyName) {
212       setPropertyTok(T.translucent, isBond, (value.equals("translucent") ? 1 : 0),
213           0);
214       return;
215     }
216 
217     if ("clear" == propertyName) {
218       currentDipole = null;
219       clear(false);
220     }
221 
222     if ("clearBonds" == propertyName) {
223       clear(true);
224     }
225 
226     if ("startSet" == propertyName) {
227       BS bsAtoms = (BS) value;
228       endCoord = null;
229       startCoord = ms.getAtomSetCenter(bsAtoms);
230       tempDipole.set2Value(startCoord, P3.new3(0, 0, 0), dipoleValue);
231       if (bsAtoms.cardinality() == 1)
232         atomIndex1 = bsAtoms.nextSetBit(0);
233       return;
234     }
235 
236     if ("atomBitset" == propertyName) {
237       BS atomset = (BS) value;
238       switch (atomset.cardinality()) {
239       case 0:
240         return;
241       case 1:
242         break;
243       case 2:
244         atomIndex1 = atomset.nextSetBit(0);
245         startCoord = ms.at[atomIndex1];
246         atomset.clear(atomIndex1);
247         break;
248       default:
249         getMolecular(atomset);
250         return;
251       }
252       propertyName = "endSet";
253       //passes to endSet
254     }
255 
256     if ("endSet" == propertyName) {
257       iHaveTwoEnds = true;
258       BS atomset = (BS) value;
259       if (atomIndex1 >= 0 && atomset.cardinality() == 1) {
260         atomIndex2 = atomset.nextSetBit(0);
261         tempDipole.set2AtomValue(ms.at[atomIndex1], ms.at[atomIndex2], 1);
262         currentDipole = findDipoleFor(tempDipole.thisID, tempDipole.dipoleInfo);
263         tempDipole.thisID = currentDipole.thisID;
264         if (isSameAtoms(currentDipole, tempDipole.dipoleInfo)) {
265           tempDipole = currentDipole;
266           if (dipoleValue > 0)
267             tempDipole.dipoleValue = dipoleValue;
268           if (mad > 0)
269             tempDipole.mad = mad;
270         }
271       } else {
272         tempDipole.set2Value(startCoord, ms.getAtomSetCenter(atomset),
273             dipoleValue);
274       }
275       //NOTTTTTT!!!! currentDipole = tempDipole;
276       return;
277     }
278 
279     if ("startCoord" == propertyName) {
280       startCoord.setT((P3) value);
281       tempDipole.set2Value(startCoord, P3.new3(0, 0, 0), dipoleValue);
282       return;
283     }
284 
285     if ("endCoord" == propertyName) {
286       iHaveTwoEnds = true;
287       endCoord.setT((P3) value);
288       tempDipole.set2Value(startCoord, endCoord, dipoleValue);
289       dumpDipoles("endCoord");
290       return;
291     }
292 
293     if ("value" == propertyName) {
294       dipoleValue = ((Float) value).floatValue();
295       isUserValue = true;
296       tempDipole.setValue(dipoleValue);
297       if (tempDipole.offsetPercent != 0)
298         tempDipole.offsetAngstroms = tempDipole.offsetPercent / 100f
299             * tempDipole.dipoleValue;
300       return;
301     }
302 
303     if ("set" == propertyName) {
304       if (isBond || !iHaveTwoEnds && tempDipole.bsMolecule == null)
305         return;
306       setDipole();
307       setModelIndex();
308       return;
309     }
310 
311     if (propertyName == "deleteModelAtoms") {
312       int modelIndex = ((int[]) ((Object[]) value)[2])[0];
313       for (int i = dipoleCount; --i >= 0;)
314         if (dipoles[i].modelIndex > modelIndex) {
315           dipoles[i].modelIndex--;
316         } else if (dipoles[i].modelIndex == modelIndex) {
317           if (dipoles[i] == currentDipole)
318             currentDipole = null;
319           dipoles = (Dipole[]) AU.deleteElements(dipoles, i, 1);
320           dipoleCount--;
321         }
322       currentDipole = null;
323       return;
324     }
325 
326   }
327 
getMolecular(BS bsMolecule)328   private void getMolecular(BS bsMolecule) {
329     V3 v = (bsMolecule == null ? calculatedDipole : null);
330     if (v == null && bsMolecule == null) {
331       v = vwr.getModelDipole();
332       Logger.info("file molecular dipole = " + v + " "
333           + (v != null ? "" + v.length() : ""));
334     }
335     if (v == null)
336       try {
337         calculatedDipole = v = vwr.calculateMolecularDipole(bsMolecule);
338       } catch (Exception e) {
339       }
340     if (v == null) {
341       Logger
342           .warn("No molecular dipole found for this model; setting to {0 0 0}");
343       v = new V3();
344     }
345     tempDipole.bsMolecule = bsMolecule;
346     tempDipole.setPtVector(P3.new3(0, 0, 0), V3.new3(-v.x, -v.y, -v.z));
347     if (tempDipole.lstDipoles != null) {
348       getAllMolecularDipoles(bsMolecule);
349     }
350     tempDipole.type = Dipole.DIPOLE_TYPE_MOLECULAR;
351     if (currentDipole == null || currentDipole.thisID == null || bsMolecule == null)
352       tempDipole.thisID = "molecular";
353     setDipole();
354   }
355 
getAllMolecularDipoles(BS bsAtoms)356   private void getAllMolecularDipoles(BS bsAtoms) {
357     JmolMolecule[] mols = ms.getMolecules();
358     for (int i = mols.length; --i >= 0;) {
359       JmolMolecule m = mols[i];
360       if (m.atomList.intersects(bsAtoms)) {
361         V3 v = null;
362         try {
363           v = vwr.calculateMolecularDipole(m.atomList);
364         } catch (Exception e) {
365         }
366         if (v == null)
367           continue;
368         P3 center = ms.getAtomSetCenter(m.atomList);
369         tempDipole.lstDipoles.addLast(new Object[] {v, center, m.atomList});
370       }
371     }
372   }
373 
setPropertyTok(int tok, boolean bondOnly, int iValue, float fValue)374   private void setPropertyTok(int tok, boolean bondOnly, int iValue, float fValue) {
375     if (currentDipole != null)
376       setPropertyFor(tok, currentDipole, iValue, fValue);
377     else {
378       for (int i = dipoleCount; --i >= 0;)
379         if (!bondOnly || isBondDipole(i))
380           if (wildID == null
381               || PT.isMatch(dipoles[i].thisID.toUpperCase(), wildID,
382                   true, true))
383             setPropertyFor(tok, dipoles[i], iValue, fValue);
384     }
385   }
386 
setPropertyFor(int tok, Dipole dipole, int iValue, float fValue)387   private void setPropertyFor(int tok, Dipole dipole, int iValue, float fValue) {
388     switch (tok) {
389     case T.on:
390       dipole.visible = true;
391       return;
392     case T.off:
393       dipole.visible = false;
394       return;
395     case T.delete:
396       deleteDipole(dipole);
397       return;
398     case T.wireframe:
399       dipole.mad = tempDipole.mad = (short) iValue;
400       return;
401     case T.axes:
402       dipole.offsetAngstroms = fValue;
403       return;
404     case T.percent:
405       dipole.offsetAngstroms = fValue * dipole.dipoleValue;
406       return;
407     case T.sidechain:
408       dipole.offsetSide = fValue;
409       return;
410     case T.cross:
411       dipole.noCross = (iValue == 0);
412       return;
413     case T.color:
414       dipole.colix = colix;
415       return;
416     case T.translucent:
417       dipole.setTranslucent(iValue == 1, translucentLevel);
418       return;
419     }
420     Logger.error("Unkown dipole property! " + T.nameOf(tok));
421   }
422 
423 //  @SuppressWarnings("unchecked")
424   @Override
getPropertyData(String property, Object[] data)425   public boolean getPropertyData(String property, Object[] data) {
426     if (property == "getNames") {
427       /* just implemented for MeshCollection
428       Map<String, Token> map = (Map<String, Token>) data[0];
429       boolean withDollar = ((Boolean) data[1]).booleanValue();
430       for (int i = dipoleCount; --i >= 0;)
431         map.put((withDollar ? "$" : "") + dipoles[i].thisID, Token.tokenAnd); // just a placeholder
432       return true;
433       */
434     }
435     if (property == "checkID") {
436       String key = ((String) data[0]).toUpperCase();
437       boolean isWild = PT.isWild(key);
438       for (int i = dipoleCount; --i >= 0;) {
439         String id = dipoles[i].thisID;
440         if (id.equalsIgnoreCase(key) || isWild
441             && PT.isMatch(id.toUpperCase(), key, true, true)) {
442           data[1] = id;
443           return true;
444         }
445       }
446       return false;
447     }
448     return getPropShape(property, data);
449   }
450 
451   @Override
getProperty(String property, int index)452   public Object getProperty(String property, int index) {
453     if (property.equals("list")) {
454       return getShapeState();
455     }
456     return null;
457   }
458 
getBondDipoles()459   private void getBondDipoles() {
460     float[] partialCharges = ms.getPartialCharges();
461     if (partialCharges == null)
462       return;
463     clear(true);
464     Bond[] bonds = ms.bo;
465     for (int i = ms.bondCount; --i >= 0;) {
466       Bond bond = bonds[i];
467       if (!bond.isCovalent())
468         continue;
469       float c1 = partialCharges[bond.atom1.i];
470       float c2 = partialCharges[bond.atom2.i];
471       if (c1 != c2)
472         setDipoleAtoms(bond.atom1, bond.atom2, c1, c2);
473     }
474   }
475 
isBondDipole(int i)476   private boolean isBondDipole(int i) {
477     if (i >= dipoles.length || dipoles[i] == null)
478       return false;
479     return (dipoles[i].isBondType());
480   }
481 
setColixDipole(short colix, int bondTypeMask, BS bs)482   private void setColixDipole(short colix, int bondTypeMask, BS bs) {
483     if (colix == C.USE_PALETTE)
484       return; // not implemented
485     BondIterator iter = ms.getBondIteratorForType(bondTypeMask, bs);
486     while (iter.hasNext()) {
487       Dipole d = findBondDipole(iter.next());
488       if (d != null)
489         d.colix = colix;
490     }
491   }
492 
setDipole()493   private void setDipole() {
494     if (currentDipole == null)
495       currentDipole = allocDipole("", "");
496     currentDipole.set(tempDipole);
497     currentDipole.isUserValue = isUserValue;
498     currentDipole.modelIndex = vwr.am.cmi;
499   }
500 
501   final private static float E_ANG_PER_DEBYE = 0.208194f;
502 
setDipoleAtoms(Atom atom1, Atom atom2, float c1, float c2)503   private void setDipoleAtoms(Atom atom1, Atom atom2, float c1, float c2) {
504     Dipole dipole = findAtomDipole(atom1, atom2, true);
505     float value = (c1 - c2) / 2f * atom1.distance(atom2) / E_ANG_PER_DEBYE;
506     if (value < 0) {
507       dipole.set2AtomValue(atom2, atom1, -value);
508     } else {
509       dipole.set2AtomValue(atom1, atom2, value);
510     }
511     dipole.type = Dipole.DIPOLE_TYPE_BOND;
512     dipole.modelIndex = atom1.mi;
513   }
514 
getDipoleIndexFor(String dipoleInfo, String thisID)515   private int getDipoleIndexFor(String dipoleInfo, String thisID) {
516     if (dipoleInfo != null && dipoleInfo.length() > 0)
517       for (int i = dipoleCount; --i >= 0;)
518         if (isSameAtoms(dipoles[i], dipoleInfo))
519           return i;
520     return getIndexFromName(thisID);
521   }
522 
isSameAtoms(Dipole dipole, String dipoleInfo)523   private boolean isSameAtoms(Dipole dipole, String dipoleInfo) {
524     // order-independent search for two atoms:
525     // looking for (xyz)(x'y'z') in (xyz)(x'y'z')(xyz)(x'y'z')
526     return (dipole != null && dipole.isBondType() && (dipole.dipoleInfo + dipole.dipoleInfo)
527         .indexOf(dipoleInfo) >= 0);
528   }
529 
getDipoleIndex(int atomIndex1, int atomIndex2)530   private int getDipoleIndex(int atomIndex1, int atomIndex2) {
531     for (int i = dipoleCount; --i >= 0;) {
532       if (dipoles[i] != null
533           && dipoles[i].atoms[0] != null
534           && dipoles[i].atoms[1] != null
535           && (dipoles[i].atoms[0].i == atomIndex1
536               && dipoles[i].atoms[1].i == atomIndex2 || dipoles[i].atoms[1]
537               .i == atomIndex1
538               && dipoles[i].atoms[0].i == atomIndex2))
539         return i;
540     }
541     return -1;
542   }
543 
deleteDipole(Dipole dipole)544   private void deleteDipole(Dipole dipole) {
545     if (dipole == null)
546       return;
547     if (currentDipole == dipole)
548       currentDipole = null;
549     int i;
550     for (i = dipoleCount; dipoles[--i] != dipole;) {
551     }
552     if (i < 0)
553       return;
554     for (int j = i + 1; j < dipoleCount; ++j)
555       dipoles[j - 1] = dipoles[j];
556     dipoles[--dipoleCount] = null;
557   }
558 
findDipole(String thisID)559   private Dipole findDipole(String thisID) {
560     int dipoleIndex = getIndexFromName(thisID);
561     if (dipoleIndex >= 0) {
562       return dipoles[dipoleIndex];
563     }
564     return null;
565   }
566 
findAtomDipole(Atom atom1, Atom atom2, boolean doAllocate)567   private Dipole findAtomDipole(Atom atom1, Atom atom2, boolean doAllocate) {
568     int dipoleIndex = getDipoleIndex(atom1.i, atom2.i);
569     if (dipoleIndex >= 0) {
570       return dipoles[dipoleIndex];
571     }
572     return (doAllocate ? allocDipole("", "") : null);
573   }
574 
findBondDipole(Bond bond)575   private Dipole findBondDipole(Bond bond) {
576     Dipole d = findAtomDipole(bond.atom1, bond.atom2, false);
577     return (d == null || d.atoms[0] == null ? null : d);
578   }
579 
findDipoleFor(String thisID, String dipoleInfo)580   private Dipole findDipoleFor(String thisID, String dipoleInfo) {
581     // must be able to identify a dipole from its ID only SECONDARILY,
582     // as we want one dipole per bond. So we look for coord ID.
583     int dipoleIndex = getDipoleIndexFor(dipoleInfo, thisID);
584     if (dipoleIndex >= 0) {
585       if (thisID.length() > 0)
586         dipoles[dipoleIndex].thisID = thisID;
587       return dipoles[dipoleIndex];
588     }
589     return allocDipole(thisID, dipoleInfo);
590   }
591 
allocDipole(String thisID, String dipoleInfo)592   private Dipole allocDipole(String thisID, String dipoleInfo) {
593     dipoles = (Dipole[]) AU.ensureLength(dipoles, dipoleCount + 1);
594     if (thisID == null || thisID.length() == 0)
595       thisID = "dipole" + (dipoleCount + 1);
596     Dipole d = dipoles[dipoleCount++] = new Dipole().init(vwr.am.cmi, thisID,
597         dipoleInfo, colix, DEFAULT_MAD, true);
598     return d;
599   }
600 
dumpDipoles(String msg)601   private void dumpDipoles(String msg) {
602     for (int i = dipoleCount; --i >= 0;) {
603       Dipole dipole = dipoles[i];
604       Logger.info("\n\n" + msg + " dump dipole " + i + " " + dipole + " "
605           + dipole.thisID + " " + dipole.dipoleInfo + " "
606           + dipole.visibilityFlags + " mad=" + dipole.mad + " vis="
607           + dipole.visible + "\n orig" + dipole.origin + " " + " vect"
608           + dipole.vector + " val=" + dipole.dipoleValue);
609     }
610     if (currentDipole != null)
611       Logger.info(" current = " + currentDipole + currentDipole.origin);
612     if (tempDipole != null)
613       Logger.info(" temp = " + tempDipole + " " + tempDipole.origin);
614   }
615 
clear(boolean clearBondDipolesOnly)616   private void clear(boolean clearBondDipolesOnly) {
617     if (clearBondDipolesOnly) {
618       for (int i = dipoleCount; --i >= 0;)
619         if (isBondDipole(i))
620           deleteDipole(dipoles[i]);
621       return;
622     }
623     for (int i = dipoleCount; --i >= 0;)
624       if (!isBond || isBondDipole(i))
625         deleteDipole(dipoles[i]);
626   }
627 
628   @Override
getIndexFromName(String thisID)629   public int getIndexFromName(String thisID) {
630     if (thisID == null)
631       return -1;
632     for (int i = dipoleCount; --i >= 0;) {
633       if (dipoles[i] != null && thisID.equals(dipoles[i].thisID))
634         return i;
635     }
636     return -1;
637   }
638 
639   @Override
getShapeDetail()640   public Object getShapeDetail() {
641     Lst<Map<String, Object>> V = new  Lst<Map<String,Object>>();
642     Map<String, Object> atomInfo;
643     P3 ptTemp = new P3();
644     for (int i = 0; i < dipoleCount; i++) {
645       Map<String, Object> info = new Hashtable<String, Object>();
646       Dipole dipole = dipoles[i];
647       info.put("ID", dipole.thisID);
648       info.put("vector", dipole.vector);
649       info.put("origin", dipole.origin);
650       if (dipole.bsMolecule != null) {
651         info.put("bsMolecule", dipole.bsMolecule);
652       } else if (dipole.atoms[0] != null) {
653         atomInfo = new Hashtable<String, Object>();
654         ms.getAtomIdentityInfo(dipole.atoms[0].i, atomInfo, ptTemp);
655         Lst<Map<String, Object>> atoms = new  Lst<Map<String,Object>>();
656         atoms.addLast(atomInfo);
657         atomInfo = new Hashtable<String, Object>();
658         ms.getAtomIdentityInfo(dipole.atoms[1].i, atomInfo, ptTemp);
659         atoms.addLast(atomInfo);
660         info.put("atoms", atoms);
661         info.put("magnitude", Float.valueOf(dipole.vector.length()));
662       }
663       V.addLast(info);
664     }
665     return V;
666   }
667 
setModelIndex()668   private void setModelIndex() {
669     if (currentDipole == null)
670       return;
671     currentDipole.visible = true;
672     currentDipole.modelIndex = vwr.am.cmi;
673   }
674 
675   @Override
setModelVisibilityFlags(BS bsModels)676   public void setModelVisibilityFlags(BS bsModels) {
677     /*
678      * set all fixed objects visible; others based on model being displayed
679      *
680      */
681     for (int i = dipoleCount; --i >= 0;) {
682       Dipole dipole = dipoles[i];
683       dipole.visibilityFlags = ((dipole.modelIndex < 0 || bsModels
684           .get(dipole.modelIndex))
685           && dipole.mad != 0
686           && dipole.visible
687           && dipole.origin != null
688           && dipole.vector != null
689           && dipole.vector.length() != 0
690           && dipole.dipoleValue != 0 ? vf : 0);
691     }
692     //dumpDipoles("setVis");
693   }
694 
695   @Override
getShapeState()696   public String getShapeState() {
697     if (dipoleCount == 0)
698       return "";
699     SB s = new SB();
700     int thisModel = -1;
701     int modelCount = vwr.ms.mc;
702     for (int i = 0; i < dipoleCount; i++) {
703       Dipole dipole = dipoles[i];
704       if (dipole.isValid) {
705         if (modelCount > 1 && dipole.modelIndex != thisModel)
706           appendCmd(s, "frame "
707               + vwr.getModelNumberDotted(thisModel = dipole.modelIndex));
708         s.append(dipole.getShapeState());
709         appendCmd(s, getColorCommandUnk("dipole", dipole.colix, translucentAllowed));
710       }
711     }
712     return s.toString();
713   }
714 }
715