1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2007-04-25 11:08:02 -0500 (Wed, 25 Apr 2007) $ 4 * $Revision: 7492 $ 5 * 6 * Copyright (C) 2005 Miguel, Jmol Development 7 * 8 * Contact: jmol-developers@lists.sf.net,jmol-developers@lists.sourceforge.net 9 * Contact: hansonr@stolaf.edu 10 * 11 * This library is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * This library is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with this library; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 24 */ 25 26 /* 27 * miguel 2005 07 17 28 * 29 * System and method for the display of surface structures 30 * contained within the interior region of a solid body 31 * United States Patent Number 4,710,876 32 * Granted: Dec 1, 1987 33 * Inventors: Cline; Harvey E. (Schenectady, NY); 34 * Lorensen; William E. (Ballston Lake, NY) 35 * Assignee: General Electric Company (Schenectady, NY) 36 * Appl. No.: 741390 37 * Filed: June 5, 1985 38 * 39 * 40 * Patents issuing prior to June 8, 1995 can last up to 17 41 * years from the date of issuance. 42 * 43 * Dec 1 1987 + 17 yrs = Dec 1 2004 44 */ 45 46 /* 47 * Bob Hanson May 22, 2006 48 * 49 * implementing marching squares; see 50 * http://www.secam.ex.ac.uk/teaching/ug/studyres/COM3404/COM3404-2006-Lecture15.pdf 51 * 52 * inventing "Jmol Voxel File" format, *.jvxl 53 * 54 * see http://www.stolaf.edu/academics/chemapps/jmol/docs/misc/JVXL-format.pdf 55 * 56 * lines through coordinates are identical to CUBE files 57 * after that, we have a line that starts with a negative number to indicate this 58 * is a JVXL file: 59 * 60 * line1: (int)-nSurfaces (int)edgeFractionBase (int)edgeFractionRange 61 * (nSurface lines): (float)cutoff (int)nBytesData (int)nBytesFractions 62 * 63 * definition1 64 * edgedata1 65 * fractions1 66 * colordata1 67 * .... 68 * definition2 69 * edgedata2 70 * fractions2 71 * colordata2 72 * .... 73 * 74 * definitions: a line with detail about what sort of compression follows 75 * 76 * edgedata: a list of the count of vertices ouside and inside the cutoff, whatever 77 * that may be, ordered by nested for loops for(x){for(y){for(z)}}}. 78 * 79 * nOutside nInside nOutside nInside... 80 * 81 * fractions: an ascii list of characters represting the fraction of distance each 82 * encountered surface point is along each voxel cube edge found to straddle the 83 * surface. The order written is dictated by the reader algorithm and is not trivial 84 * to describe. Each ascii character is constructed by taking a base character and 85 * adding onto it the fraction times a range. This gives a character that can be 86 * quoted EXCEPT for backslash, which MAY be substituted for by '!'. Jmol uses the 87 * range # - | (35 - 124), reserving ! and } for special meanings. 88 * 89 * colordata: same deal here, but with possibility of "double precision" using two bytes. 90 * 91 */ 92 93 package org.jmol.shapesurface; 94 95 import java.io.BufferedInputStream; 96 import java.io.BufferedReader; 97 import java.io.IOException; 98 import java.util.Hashtable; 99 import java.util.Map; 100 101 import javajs.api.GenericBinaryDocument; 102 import javajs.util.A4; 103 import javajs.util.AU; 104 import javajs.util.CU; 105 import javajs.util.Lst; 106 import javajs.util.M3; 107 import javajs.util.M4; 108 import javajs.util.OC; 109 import javajs.util.P3; 110 import javajs.util.P3i; 111 import javajs.util.P4; 112 import javajs.util.PT; 113 import javajs.util.Quat; 114 import javajs.util.Rdr; 115 import javajs.util.SB; 116 import javajs.util.T3; 117 import javajs.util.V3; 118 119 import javajs.util.BS; 120 import org.jmol.jvxl.api.MeshDataServer; 121 import org.jmol.jvxl.data.JvxlCoder; 122 import org.jmol.jvxl.data.JvxlData; 123 import org.jmol.jvxl.data.MeshData; 124 import org.jmol.jvxl.readers.Parameters; 125 import org.jmol.jvxl.readers.SurfaceGenerator; 126 import org.jmol.script.T; 127 import org.jmol.shape.Mesh; 128 import org.jmol.shape.MeshCollection; 129 import org.jmol.util.C; 130 import org.jmol.util.ColorEncoder; 131 import org.jmol.util.Escape; 132 import org.jmol.util.Logger; 133 import org.jmol.util.MeshSurface; 134 import org.jmol.util.TempArray; 135 import org.jmol.viewer.ActionManager; 136 import org.jmol.viewer.JC; 137 import org.jmol.viewer.Viewer; 138 139 140 public class Isosurface extends MeshCollection implements MeshDataServer { 141 142 protected IsosurfaceMesh[] isomeshes = new IsosurfaceMesh[4]; 143 protected IsosurfaceMesh thisMesh; 144 145 @Override allocMesh(String thisID, Mesh m)146 public void allocMesh(String thisID, Mesh m) { 147 int index = meshCount++; 148 meshes = isomeshes = (IsosurfaceMesh[]) AU.ensureLength(isomeshes, 149 meshCount * 2); 150 currentMesh = thisMesh = isomeshes[index] = (m == null ? new IsosurfaceMesh(vwr, 151 thisID, colix, index) : (IsosurfaceMesh) m); 152 currentMesh.index = index; 153 if (sg != null) 154 sg.setJvxlData(jvxlData = thisMesh.jvxlData); 155 } 156 157 @Override initShape()158 public void initShape() { 159 super.initShape(); 160 myType = "isosurface"; 161 newSg(); 162 } 163 newSg()164 protected void newSg() { 165 sg = new SurfaceGenerator(vwr, this, null, jvxlData = new JvxlData()); 166 sg.params.showTiming = vwr.getBoolean(T.showtiming); 167 sg.version = "Jmol " + Viewer.getJmolVersion(); 168 } 169 clearSg()170 protected void clearSg() { 171 sg = null; // not Molecular Orbitals 172 } 173 //private boolean logMessages; 174 private String actualID; 175 protected boolean iHaveBitSets; 176 private boolean explicitContours; 177 private int atomIndex; 178 private int moNumber; 179 private float[] moLinearCombination; 180 private int colorType; 181 private short defaultColix; 182 private short meshColix; 183 private P3 center; 184 private float scale3d; 185 private boolean isPhaseColored; 186 private boolean isColorExplicit; 187 private String scriptAppendix = ""; 188 189 protected SurfaceGenerator sg; 190 191 private float withinDistance2; 192 private boolean isWithinNot; 193 private Lst<P3> withinPoints; 194 private float[] cutoffRange; 195 196 //private boolean allowContourLines; 197 boolean allowMesh = true; 198 199 @Override setProperty(String propertyName, Object value, BS bs)200 public void setProperty(String propertyName, Object value, BS bs) { 201 setPropI(propertyName, value, bs); 202 } 203 204 @SuppressWarnings("unchecked") setPropI(String propertyName, Object value, BS bs)205 protected void setPropI(String propertyName, Object value, BS bs) { 206 207 //System.out.println("isosurface testing " + propertyName + " " + value + (propertyName == "token" ? " " + T.nameOf(((Integer)value).intValue()) : "")); 208 209 //isosurface-only (no calculation required; no calc parameters to set) 210 211 // if ("navigate" == propertyName) { 212 // navigate(((Integer) value).intValue()); 213 // return; 214 // } 215 if ("cache" == propertyName) { 216 if (currentMesh == null) 217 return; 218 String id = currentMesh.thisID; 219 int imodel = currentMesh.modelIndex; 220 vwr.cachePut("cache://isosurface_" + id, 221 ((String) getPropI("jvxlDataXml", -1)).getBytes()); 222 deleteMeshI(currentMesh.index); 223 setPropI("init", null, null); 224 setPropI("thisID", id, null); 225 setPropI("modelIndex", Integer.valueOf(imodel), null); 226 setPropI("fileName", "cache://isosurface_" + id, null); 227 setPropI("readFile", null, null); 228 setPropI("finalize", 229 "isosurface ID " + PT.esc(id) 230 + (imodel >= 0 ? " modelIndex " + imodel : "") + " /*file*/" 231 + PT.esc("cache://isosurface_" + id), 232 null); 233 setPropI("clear", null, null); 234 return; 235 } 236 if ("delete" == propertyName) { 237 setPropertySuper(propertyName, value, bs); 238 if (!explicitID) 239 nLCAO = nUnnamed = 0; 240 currentMesh = thisMesh = null; 241 return; 242 } 243 244 if ("remapInherited" == propertyName) { 245 for (int i = meshCount; --i >= 0;) { 246 if (isomeshes[i] != null 247 && "#inherit;".equals(isomeshes[i].colorCommand)) 248 isomeshes[i].remapColors(vwr, null, Float.NaN); 249 } 250 return; 251 } 252 253 if ("remapColor" == propertyName) { 254 if (thisMesh != null) 255 thisMesh.remapColors(vwr, (ColorEncoder) value, translucentLevel); 256 return; 257 } 258 259 if ("thisID" == propertyName) { 260 if (actualID != null) 261 value = actualID; 262 setPropertySuper("thisID", value, null); 263 return; 264 } 265 266 if ("params" == propertyName) { 267 if (thisMesh != null) { 268 ensureMeshSource(); 269 thisMesh.checkAllocColixes(); 270 Object[] data = (Object[]) value; 271 short[] colixes = (short[]) data[0]; 272 int[] atomMap = null; 273 //float[] atrans = (float[]) data[1]; 274 if (colixes != null) { 275 for (int i = 0; i < colixes.length; i++) { 276 short colix = colixes[i]; 277 float f = 0;//(atrans == null ? 0 : atrans[pt]); 278 if (f > 0.01f) 279 colix = C.getColixTranslucent3(colix, true, f); 280 colixes[i] = colix; 281 } 282 atomMap = new int[bs.length()]; 283 for (int pt = 0, i = bs.nextSetBit(0); i >= 0; i = bs 284 .nextSetBit(i + 1), pt++) 285 atomMap[i] = pt; 286 } 287 thisMesh.setVertexColixesForAtoms(vwr, colixes, atomMap, bs); 288 thisMesh.setVertexColorMap(); 289 } 290 return; 291 } 292 if ("atomcolor" == propertyName) { 293 // color $id red ({0:30 ....}) (atoms) 294 // color $id red [{0:30 ....}] (vertices) 295 if (thisMesh != null) { 296 ensureMeshSource(); 297 thisMesh.colorVertices(C.getColixO(value), bs, true); 298 } 299 return; 300 } 301 302 if ("pointSize" == propertyName) { 303 if (thisMesh != null) { 304 thisMesh.volumeRenderPointSize = ((Float) value).floatValue(); 305 } 306 return; 307 } 308 309 if ("vertexcolor" == propertyName) { 310 if (thisMesh != null) { 311 thisMesh.colorVertices(C.getColixO(value), bs, false); 312 } 313 return; 314 } 315 316 if ("colorPhase" == propertyName) { 317 // from color isosurface phase color1 color2 Jmol 12.3.5 318 Object[] colors = (Object[]) value; 319 short colix0 = C.getColix(((Integer) colors[0]).intValue()); 320 short colix1 = C.getColix(((Integer) colors[1]).intValue()); 321 String id = (thisMesh != null ? thisMesh.thisID 322 : PT.isWild(previousMeshID) ? previousMeshID : null); 323 Lst<Mesh> list = getMeshList(id, false); 324 for (int i = list.size(); --i >= 0;) 325 setColorPhase((IsosurfaceMesh) list.get(i), colix0, colix1); 326 return; 327 } 328 if ("color" == propertyName) { 329 String color = C.getHexCode(C.getColixO(value)); 330 if (thisMesh != null) { 331 setIsoMeshColor(thisMesh, color); 332 } else { 333 Lst<Mesh> list = getMeshList( 334 PT.isWild(previousMeshID) ? previousMeshID : null, false); 335 for (int i = list.size(); --i >= 0;) 336 setIsoMeshColor((IsosurfaceMesh) list.get(i), color); 337 } 338 setPropertySuper(propertyName, value, bs); 339 return; 340 } 341 342 if ("nocontour" == propertyName) { 343 // recontouring 344 if (thisMesh != null) { 345 thisMesh.deleteContours(); 346 } 347 return; 348 } 349 if ("fixed" == propertyName) { 350 isFixed = ((Boolean) value).booleanValue(); 351 setMeshI(); 352 return; 353 } 354 355 if ("newObject" == propertyName) { 356 if (thisMesh != null) 357 thisMesh.clearType(thisMesh.meshType, false); 358 return; 359 } 360 361 if ("moveIsosurface" == propertyName) { 362 if (thisMesh != null && !thisMesh.isModelConnected) { 363 thisMesh.updateCoordinates((M4) value, null); 364 thisMesh.altVertices = null; 365 } 366 return; 367 } 368 369 if ("refreshTrajectories" == propertyName) { 370 int m = ((Integer) ((Object[]) value)[0]).intValue(); 371 for (int i = meshCount; --i >= 0;) 372 if (meshes[i].modelIndex == m 373 && (meshes[i].connectedAtoms != null || meshes[i].isModelConnected)) 374 ((IsosurfaceMesh) meshes[i]).updateCoordinates( 375 (M4) ((Object[]) value)[2], (BS) ((Object[]) value)[1]); 376 return; 377 } 378 379 if ("modelIndex" == propertyName) { 380 if (!iHaveModelIndex) { 381 modelIndex = ((Integer) value).intValue(); 382 isFixed = (modelIndex < 0); 383 sg.params.modelIndex = Math.abs(modelIndex); 384 } 385 return; 386 } 387 388 if ("lcaoCartoon" == propertyName || "lonePair" == propertyName 389 || "radical" == propertyName) { 390 // z x center rotationAxis (only one of x, y, or z is nonzero; in radians) 391 V3[] info = (V3[]) value; 392 if (!explicitID) { 393 setPropertySuper("thisID", null, null); 394 } 395 // center (info[2]) is set in SurfaceGenerator 396 if (!sg.setProp("lcaoCartoonCenter", info[2], null)) 397 drawLcaoCartoon(info[0], info[1], info[3], 398 ("lonePair" == propertyName ? 2 399 : "radical" == propertyName ? 1 : 0)); 400 return; 401 } 402 403 if ("select" == propertyName) { 404 if (iHaveBitSets) 405 return; 406 } 407 408 if ("ignore" == propertyName) { 409 if (iHaveBitSets) 410 return; 411 } 412 413 if ("meshcolor" == propertyName) { 414 int rgb = ((Integer) value).intValue(); 415 meshColix = C.getColix(rgb); 416 if (thisMesh != null) 417 thisMesh.meshColix = meshColix; 418 return; 419 } 420 421 if ("offset" == propertyName) { 422 P3 offset = P3.newP((P3) value); 423 if (offset.equals(JC.center)) 424 offset = null; 425 if (thisMesh != null) { 426 thisMesh.rotateTranslate(null, offset, true); 427 thisMesh.altVertices = null; 428 } 429 return; 430 } 431 432 if ("rotate" == propertyName) { 433 P4 pt4 = (P4) value; 434 if (thisMesh != null) { 435 thisMesh.rotateTranslate(Quat.newP4(pt4), null, true); 436 thisMesh.altVertices = null; 437 } 438 return; 439 } 440 441 if ("bsDisplay" == propertyName) { 442 bsDisplay = (BS) value; 443 return; 444 } 445 if ("displayWithin" == propertyName) { 446 Object[] o = (Object[]) value; 447 displayWithinDistance2 = ((Float) o[0]).floatValue(); 448 isDisplayWithinNot = (displayWithinDistance2 < 0); 449 displayWithinDistance2 *= displayWithinDistance2; 450 displayWithinPoints = (Lst<P3>) o[3]; 451 if (displayWithinPoints.size() == 0) 452 displayWithinPoints = vwr.ms.getAtomPointVector((BS) o[2]); 453 return; 454 } 455 456 if ("finalize" == propertyName) { 457 if (thisMesh != null) { 458 String cmd = (String) value; 459 if (cmd != null && !cmd.startsWith("; isosurface map")) { 460 thisMesh.setDiscreteColixes(sg.params.contoursDiscrete, 461 sg.params.contourColixes); 462 setJvxlInfo(); 463 } 464 setScriptInfo(cmd); 465 } 466 clearSg(); 467 return; 468 } 469 470 if ("connections" == propertyName) { 471 if (currentMesh != null) { 472 connections = (int[]) value; 473 if (connections[0] >= 0 && connections[0] < vwr.ms.ac) 474 currentMesh.connectedAtoms = connections; 475 else 476 connections = currentMesh.connectedAtoms = null; 477 } 478 return; 479 } 480 481 if ("cutoffRange" == propertyName) { 482 cutoffRange = (float[]) value; 483 return; 484 } 485 486 if ("fixLattice" == propertyName) { 487 if (thisMesh != null) 488 thisMesh.fixLattice(); 489 return; 490 } 491 492 // Isosurface / SurfaceGenerator both interested 493 494 if ("slab" == propertyName) { 495 if (value instanceof Integer) { 496 if (thisMesh != null) 497 thisMesh.jvxlData.slabValue = ((Integer) value).intValue(); 498 return; 499 } 500 if (thisMesh != null) { 501 Object[] slabInfo = (Object[]) value; 502 int tok = ((Integer) slabInfo[0]).intValue(); 503 switch (tok) { 504 case T.mesh: 505 Object[] data = (Object[]) slabInfo[1]; 506 Mesh m = getMesh((String) data[1]); 507 if (m == null) 508 return; 509 data[1] = m; 510 break; 511 } 512 slabPolygons(slabInfo); 513 return; 514 } 515 } 516 517 if ("cap" == propertyName) { 518 if (thisMesh != null && thisMesh.pc != 0) { 519 thisMesh.getMeshSlicer().slabPolygons((Object[]) value, true); 520 thisMesh.initialize(thisMesh.lighting, null, null); 521 return; 522 } 523 } 524 if ("map" == propertyName) { 525 if (sg != null) 526 sg.params.isMapped = true; 527 setProperty("squareData", Boolean.FALSE, null); 528 if (thisMesh == null || thisMesh.vc == 0) 529 return; 530 } 531 532 if ("probes" == propertyName) { 533 if (sg != null) { 534 sg.params.probes = (P3[]) value; 535 sg.params.probeValues = new float[sg.params.probes.length]; 536 } 537 return; 538 } 539 540 if ("deleteVdw" == propertyName) { 541 for (int i = meshCount; --i >= 0;) 542 if (isomeshes[i].bsVdw != null 543 && (bs == null || bs.intersects(isomeshes[i].bsVdw))) 544 deleteMeshI(i); 545 currentMesh = thisMesh = null; 546 return; 547 } 548 if ("mapColor" == propertyName || "readFile" == propertyName) { 549 if (value == null) { 550 // ScriptEvaluator has passed the filename to us as the value of the 551 // "fileName" property. We retrieve that from the surfaceGenerator 552 // and open a BufferedReader for it. Or not. But that would be 553 // unlikely since we have just checked it in ScriptEvaluator 554 555 if (sg.params.filesData == null) { 556 value = getFileReader(sg.params.fileName); 557 } else { 558 value = sg.params.filesData; 559 String[] a = (String[]) sg.params.filesData[0]; 560 Object[] b = new Object[a.length]; 561 for (int i = b.length; --i >= 0 && value != null;) 562 if ((b[i] = getFileReader(a[i])) == null) 563 value = null; 564 if (value != null) 565 sg.params.filesData[0] = b; 566 } 567 if (value == null) 568 return; 569 } 570 } else if ("atomIndex" == propertyName) { 571 atomIndex = ((Integer) value).intValue(); 572 if (thisMesh != null) 573 thisMesh.atomIndex = atomIndex; 574 } else if ("center" == propertyName) { 575 center.setT((P3) value); 576 } else if ("colorRGB" == propertyName) { 577 int rgb = ((Integer) value).intValue(); 578 if (rgb == T.symop) { 579 colorType = rgb; 580 } else { 581 colorType = 0; 582 defaultColix = C.getColix(rgb); 583 } 584 } else if ("contour" == propertyName) { 585 explicitContours = true; 586 } else if ("functionXY" == propertyName) { 587 //allowContourLines = false; 588 if (sg.params.state == Parameters.STATE_DATA_READ) 589 setScriptInfo(null); // for script DATA1 590 } else if ("init" == propertyName) { 591 newSg(); 592 } else if ("getSurfaceSets" == propertyName) { 593 if (thisMesh != null) { 594 BS bsSets; 595 if (value instanceof BS) { 596 bsSets = ((BS) value); 597 if (bsSets.cardinality() == 0) 598 bsSets = null; 599 } else { 600 bsSets = new BS(); 601 int[] a = (int[]) value; 602 for (int i = a.length; --i >= 0;) { 603 if (a[i] > 0) 604 bsSets.set(a[i] - 1); 605 } 606 } 607 thisMesh.jvxlData.thisSet = bsSets; 608 thisMesh.calculatedVolume = null; 609 thisMesh.calculatedArea = null; 610 } 611 } else if ("localName" == propertyName) { 612 value = vwr.getOutputChannel((String) value, null); 613 propertyName = "outputChannel"; 614 } else if ("molecularOrbital" == propertyName) { 615 isFixed = false; 616 setMeshI(); 617 if (value instanceof Integer) { 618 moNumber = ((Integer) value).intValue(); 619 moLinearCombination = null; 620 } else { 621 moLinearCombination = (float[]) value; 622 moNumber = 0; 623 } 624 if (!isColorExplicit) 625 isPhaseColored = true; 626 if (sg == null || !sg.params.isMapped) { 627 M4 mat4 = ms.am[currentMesh.modelIndex].mat4; 628 if (mat4 != null) { 629 M4 minv = M4.newM4(mat4); 630 minv.invert(); 631 setPropI("modelInvRotation", minv, null); 632 } 633 } 634 } else if ("phase" == propertyName) { 635 isPhaseColored = true; 636 } else if ("plane" == propertyName) { 637 //allowContourLines = false; 638 } else if ("pocket" == propertyName) { 639 // Boolean pocket = (Boolean) value; 640 // lighting = (pocket.booleanValue() ? JmolConstants.FULLYLIT 641 // : JmolConstants.FRONTLIT); 642 } else if ("scale3d" == propertyName) { 643 scale3d = ((Float) value).floatValue(); 644 if (thisMesh != null) { 645 thisMesh.scale3d = thisMesh.jvxlData.scale3d = scale3d; 646 thisMesh.altVertices = null; 647 } 648 } else if ("title" == propertyName) { 649 if (value instanceof String && "-".equals(value)) 650 value = null; 651 setPropertySuper(propertyName, value, bs); 652 value = title; 653 } else if ("withinPoints" == propertyName) { 654 Object[] o = (Object[]) value; 655 withinDistance2 = ((Float) o[0]).floatValue(); 656 isWithinNot = (withinDistance2 < 0); 657 withinDistance2 *= withinDistance2; 658 withinPoints = (Lst<P3>) o[3]; 659 if (withinPoints.size() == 0) 660 withinPoints = vwr.ms.getAtomPointVector((BS) o[2]); 661 } else if (("nci" == propertyName || "orbital" == propertyName) 662 && sg != null) { 663 sg.params.testFlags = (vwr.getBoolean(T.testflag2) ? 2 : 0); 664 } 665 666 // surface Export3D only (return TRUE) or shared (return FALSE) 667 668 if (sg != null && sg.setProp(propertyName, value, bs)) { 669 if (sg.isValid) { 670 if ("molecularOrbital" == propertyName) { 671 currentMesh.isModelConnected = true; 672 currentMesh.mat4 = ms.am[currentMesh.modelIndex].mat4; 673 } 674 return; 675 } 676 propertyName = "delete"; 677 } 678 679 // ///////////// isosurface LAST, shared 680 681 if ("init" == propertyName) { 682 explicitID = false; 683 scriptAppendix = ""; 684 String script = (value instanceof String ? (String) value : null); 685 int pt = (script == null ? -1 : script.indexOf("# ID=")); 686 actualID = (pt >= 0 ? PT.getQuotedStringAt(script, pt) : null); 687 setPropertySuper("thisID", MeshCollection.PREVIOUS_MESH_ID, null); 688 if (script != null && !(iHaveBitSets = getScriptBitSets(script, null))) 689 sg.setProp("select", bs, null); 690 initializeIsosurface(); 691 sg.params.modelIndex = (isFixed ? -1 : modelIndex); 692 return; 693 } 694 695 if ("clear" == propertyName) { 696 discardTempData(true); 697 return; 698 } 699 700 if ("colorDensity" == propertyName) { 701 if (value != null && currentMesh != null) 702 currentMesh.volumeRenderPointSize = ((Float) value).floatValue(); 703 return; 704 } 705 /* 706 * if ("background" == propertyName) { boolean doHide = !((Boolean) 707 * value).booleanValue(); if (thisMesh != null) thisMesh.hideBackground = 708 * doHide; else { for (int i = meshCount; --i >= 0;) 709 * meshes[i].hideBackground = doHide; } return; } 710 */ 711 712 if (propertyName == "deleteModelAtoms") { 713 int modelIndex = ((int[]) ((Object[]) value)[2])[0]; 714 int firstAtomDeleted = ((int[]) ((Object[]) value)[2])[1]; 715 int nAtomsDeleted = ((int[]) ((Object[]) value)[2])[2]; 716 for (int i = meshCount; --i >= 0;) { 717 Mesh m = meshes[i]; 718 if (m == null) 719 continue; 720 if (m.connectedAtoms != null) { 721 int iAtom = m.connectedAtoms[0]; 722 if (iAtom >= firstAtomDeleted + nAtomsDeleted) 723 m.connectedAtoms[0] = iAtom - nAtomsDeleted; 724 else if (iAtom >= firstAtomDeleted) 725 m.connectedAtoms = null; 726 } 727 m.connectedAtoms = null; // just no way to 728 if (m.modelIndex == modelIndex) { 729 meshCount--; 730 if (m == currentMesh) 731 currentMesh = thisMesh = null; 732 meshes = isomeshes = (IsosurfaceMesh[]) AU.deleteElements(meshes, i, 733 1); 734 } else if (m.modelIndex > modelIndex) { 735 m.modelIndex--; 736 if (m.atomIndex >= firstAtomDeleted) 737 m.atomIndex -= nAtomsDeleted; 738 } 739 } 740 return; 741 } 742 743 // processing by meshCollection: 744 setPropertySuper(propertyName, value, bs); 745 } 746 getFileReader(String fileName)747 private Object getFileReader(String fileName) { 748 Object value = vwr.fm.getBufferedReaderOrErrorMessageFromName( 749 fileName, null, true, true); 750 if (value instanceof String) { 751 Logger.error("Isosurface: could not open file " + fileName 752 + " -- " + value); 753 return null; 754 } 755 if (!(value instanceof BufferedReader)) 756 try { 757 value = Rdr.getBufferedReader((BufferedInputStream) value, 758 "ISO-8859-1"); 759 } catch (IOException e) { 760 // ignore 761 } 762 return value; 763 } 764 setIsoMeshColor(IsosurfaceMesh m, String color)765 private void setIsoMeshColor(IsosurfaceMesh m, String color) { 766 // thisMesh.vertexColixes = null; 767 m.jvxlData.baseColor = color; 768 m.isColorSolid = true; 769 m.pcs = null; 770 m.colorsExplicit = false; 771 m.colorEncoder = null; 772 m.vertexColorMap = null; 773 } 774 setColorPhase(IsosurfaceMesh m, short colix0, short colix1)775 private void setColorPhase(IsosurfaceMesh m, short colix0, 776 short colix1) { 777 m.colorPhased = true; 778 m.colix = m.jvxlData.minColorIndex = colix0; 779 m.jvxlData.maxColorIndex = colix1; 780 m.jvxlData.isBicolorMap = true; 781 m.jvxlData.colorDensity = false; 782 m.isColorSolid = false; 783 m.remapColors(vwr, null, translucentLevel); 784 } 785 ensureMeshSource()786 private void ensureMeshSource() { 787 boolean haveColors = (thisMesh.vertexSource != null); 788 if (haveColors) 789 for (int i = thisMesh.vc; --i >= 0;) 790 if (thisMesh.vertexSource[i] < 0) { 791 haveColors = false; 792 break; 793 } 794 if (!haveColors) { 795 int[] source = thisMesh.vertexSource; 796 short[] vertexColixes = thisMesh.vcs; 797 short colix = (thisMesh.isColorSolid ? thisMesh.colix : 0); 798 setProperty("init", null, null); 799 setProperty("map", Boolean.FALSE, null); 800 setProperty("property", new float[vwr.ms.ac], null); 801 if (colix != 0) { 802 thisMesh.colorCommand = "color isosurface " 803 + C.getHexCode(colix); 804 setProperty("color", Integer.valueOf(C.getArgb(colix)), null); 805 } 806 if (source != null) { 807 for (int i = thisMesh.vc; --i >= 0;) 808 if (source[i] < 0) 809 source[i] = thisMesh.vertexSource[i]; 810 thisMesh.vertexSource = source; 811 thisMesh.vcs = vertexColixes; 812 } 813 } 814 } 815 slabPolygons(Object[] slabInfo)816 protected void slabPolygons(Object[] slabInfo) { 817 thisMesh.calculatedVolume = null; 818 thisMesh.calculatedArea = null; 819 thisMesh.getMeshSlicer().slabPolygons(slabInfo, false); 820 thisMesh.reinitializeLightingAndColor(vwr); 821 } 822 setPropertySuper(String propertyName, Object value, BS bs)823 private void setPropertySuper(String propertyName, Object value, BS bs) { 824 if (propertyName == "thisID" && currentMesh != null 825 && currentMesh.thisID != null && currentMesh.thisID.equals(value)) { 826 checkExplicit((String) value); 827 return; 828 } 829 currentMesh = thisMesh; 830 setPropMC(propertyName, value, bs); 831 thisMesh = (IsosurfaceMesh) currentMesh; 832 jvxlData = (thisMesh == null ? null : thisMesh.jvxlData); 833 if (sg != null) 834 sg.setJvxlData(jvxlData); 835 } 836 837 838 @SuppressWarnings("unchecked") 839 @Override getPropertyData(String property, Object[] data)840 public boolean getPropertyData(String property, Object[] data) { 841 IsosurfaceMesh m; 842 if (property == "keys") { 843 Lst<String> keys = (data[1] instanceof Lst<?> ? (Lst<String>) data[1] : new Lst<String>()); 844 data[1] = keys; 845 keys.addLast("info"); 846 keys.addLast("data"); 847 keys.addLast("atoms"); 848 // will continue on to super 849 } 850 if (property == "colorEncoder") { 851 m = (IsosurfaceMesh) getMesh((String) data[0]); 852 return (m != null && (data[1] = m.colorEncoder) != null); 853 } 854 if (property == "intersectPlane") { 855 m = (IsosurfaceMesh) getMesh((String) data[0]); 856 if (m == null || data.length < 4) 857 return false; 858 data[3] = Integer.valueOf(m.modelIndex); 859 m.getMeshSlicer().getIntersection(0, (P4) data[1], null, (Lst<P3[]>) data[2], null, null, null, false, false, T.plane, false); 860 return true; 861 } 862 if (property == "getBoundingBox") { 863 String id = (String) data[0]; 864 m = (IsosurfaceMesh) getMesh(id); 865 if (m == null || m.vs == null) 866 return false; 867 data[2] = m.jvxlData.boundingBox; 868 if (m.mat4 != null) { 869 P3[] d = new P3[2]; 870 d[0] = P3.newP(m.jvxlData.boundingBox[0]); 871 d[1] = P3.newP(m.jvxlData.boundingBox[1]); 872 V3 v = new V3(); 873 m.mat4.getTranslation(v); 874 d[0].add(v); 875 d[1].add(v); 876 data[2] = d; 877 } 878 return true; 879 } 880 if (property == "unitCell") { 881 m = (IsosurfaceMesh) getMesh((String) data[0]); 882 return (m != null && (data[1] = m.getUnitCell()) != null); 883 } 884 if (property == "getCenter") { 885 int index = ((Integer)data[1]).intValue(); 886 if (index == Integer.MIN_VALUE) { 887 String id = (String) data[0]; 888 m = (IsosurfaceMesh) getMesh(id); 889 if (m == null || m.vs == null) 890 return false; 891 P3 p = P3.newP(m.jvxlData.boundingBox[0]); 892 p.add(m.jvxlData.boundingBox[1]); 893 p.scale(0.5f); 894 if (m.mat4 != null) { 895 V3 v = new V3(); 896 m.mat4.getTranslation(v); 897 p.add(v); 898 } 899 data[2] = p; 900 return true; 901 } 902 // continue to super 903 } 904 905 return getPropDataMC(property, data); 906 } 907 908 @Override getProperty(String property, int index)909 public Object getProperty(String property, int index) { 910 return getPropI(property, index); 911 } 912 getPropI(String property, int index)913 protected Object getPropI(String property, int index) { 914 IsosurfaceMesh m = thisMesh; 915 if (index >= 0 && (index >= meshCount || (m = isomeshes[index]) == null)) 916 return null; 917 Object ret = getPropMC(property, index); 918 if (ret != null) 919 return ret; 920 if (property == "message") { 921 String s = ""; 922 if (!jvxlData.isValid) 923 return "invalid! (no atoms selected?)"; 924 if (!Float.isNaN(jvxlData.integration)) 925 s += "integration " + jvxlData.integration; 926 if (shapeID == JC.SHAPE_ISOSURFACE || shapeID == JC.SHAPE_MO || shapeID == JC.SHAPE_NBO) 927 s += " with cutoff=" + jvxlData.cutoff; 928 if (shapeID == JC.SHAPE_MO || shapeID == JC.SHAPE_NBO) 929 return s; 930 if (jvxlData.dataMin != Float.MAX_VALUE) 931 s += " min=" + jvxlData.dataMin + " max=" + jvxlData.dataMax; 932 933 s += "; " + JC.shapeClassBases[shapeID].toLowerCase() + " count: " 934 + getPropMC("count", index); 935 return s + getPropI("dataRangeStr", index) + jvxlData.msg; 936 } 937 if (property == "dataRange") 938 return getDataRange(m); 939 if (property == "dataRangeStr") { 940 float[] dataRange = getDataRange(m); 941 return (dataRange != null && dataRange[0] != Float.MAX_VALUE 942 && dataRange[0] != dataRange[1] ? "\nisosurface" 943 + " full data range " + dataRange[0] + " to " + dataRange[1] 944 + " with color scheme spanning " + dataRange[2] + " to " + dataRange[3] 945 : ""); 946 } 947 if (property == "moNumber") 948 return Integer.valueOf(moNumber); 949 if (property == "moLinearCombination") 950 return moLinearCombination; 951 if (property == "nSets") { 952 int n = (m == null ? Integer.MIN_VALUE : m.nSets); 953 if (n == 0) { 954 calculateVolumeOrArea(m, true); 955 n = m.nSets; 956 } 957 return Integer.valueOf(n == Integer.MIN_VALUE ? 0 : Math.abs(m.nSets)); 958 } 959 if (property == "area") // could be Float or double[] 960 return (m == null ? Float.valueOf(Float.NaN) : calculateVolumeOrArea(m, true)); 961 if (property == "volume") // could be Float or double[] 962 return (m == null ? Float.valueOf(Float.NaN) : calculateVolumeOrArea(m, false)); 963 if (m == null) 964 return null;//"no current isosurface"; 965 if (property == "output") { 966 return (m.jvxlData.sbOut == null && m.jvxlData.jvxlFileTitle == null ? null : 967 m.jvxlData.jvxlFileTitle + "\n" + (m.jvxlData.sbOut == null ? "" : m.jvxlData.sbOut.toString())); 968 } 969 if (property == "cutoff") 970 return Float.valueOf(jvxlData.cutoff); 971 if (property == "minMaxInfo") 972 return new float[] { jvxlData.dataMin, jvxlData.dataMax }; 973 if (property == "plane") 974 return jvxlData.jvxlPlane; 975 if (property == "contours") 976 return m.getContours(); 977 if (property == "pmesh" || property == "pmeshbin") 978 return m.getPmeshData(property == "pmeshbin"); 979 if (property == "jvxlDataXml" || property == "jvxlMeshXml") { 980 MeshData meshData = null; 981 jvxlData.slabInfo = null; 982 if (property == "jvxlMeshXml" || jvxlData.vertexDataOnly || m.bsSlabDisplay != null && m.bsSlabGhost == null) { 983 meshData = new MeshData(); 984 fillMeshData(meshData, MeshData.MODE_GET_VERTICES, m); 985 meshData.polygonColorData = getPolygonColorData(meshData.pc, meshData.pcs, (meshData.colorsExplicit ? meshData.pis : null), meshData.bsSlabDisplay); 986 } else if (m.bsSlabGhost != null) { 987 jvxlData.slabInfo = m.slabOptions.toString(); 988 } 989 SB sb = new SB(); 990 getMeshCommand(sb, m.index); 991 m.setJvxlColorMap(true); 992 return JvxlCoder.jvxlGetFile(jvxlData, meshData, title, "", true, 1, sb.toString(), null); 993 } 994 if (property == "jvxlFileInfo") { 995 return JvxlCoder.jvxlGetInfo(jvxlData); 996 } 997 if (property == "command") { 998 SB sb = new SB(); 999 Lst<Mesh> list = getMeshList((index < 0 ? previousMeshID : m.thisID), false); 1000 for (int i = list.size(); --i >= 0;) 1001 getMeshCommand(sb, i); 1002 return sb.toString(); 1003 } 1004 if (property == "atoms") { 1005 return m.surfaceAtoms; 1006 } 1007 if (property == "colorEncoder") 1008 return m.colorEncoder; 1009 if (property == "values" || property == "value") { 1010 return m.probeValues; 1011 } 1012 1013 return null; 1014 } 1015 getDataRange(IsosurfaceMesh mesh)1016 private float[] getDataRange(IsosurfaceMesh mesh) { 1017 return (mesh == null ? null : mesh.getDataRange()); 1018 } 1019 calculateVolumeOrArea(IsosurfaceMesh mesh, boolean isArea)1020 private Object calculateVolumeOrArea(IsosurfaceMesh mesh, boolean isArea) { 1021 if (isArea) { 1022 if (mesh.calculatedArea != null) 1023 return mesh.calculatedArea; 1024 } else { 1025 if (mesh.calculatedVolume != null) 1026 return mesh.calculatedVolume; 1027 } 1028 MeshData meshData = new MeshData(); 1029 fillMeshData(meshData, MeshData.MODE_GET_VERTICES, mesh); 1030 meshData.nSets = mesh.nSets; 1031 meshData.vertexSets = mesh.vertexSets; 1032 if (!isArea && mesh.jvxlData.colorDensity) { 1033 float f = mesh.jvxlData.voxelVolume; 1034 f *= (mesh.bsSlabDisplay == null ? mesh.vc : mesh.bsSlabDisplay.cardinality()); 1035 return mesh.calculatedVolume = Float.valueOf(f); 1036 } 1037 Object ret = MeshData.calculateVolumeOrArea(meshData, mesh.jvxlData.thisSet, isArea, false); 1038 if (mesh.nSets <= 0) 1039 mesh.nSets = -meshData.nSets; 1040 if (isArea) 1041 mesh.calculatedArea = ret; 1042 else 1043 mesh.calculatedVolume = ret; 1044 return ret; 1045 } 1046 getPolygonColorData(int ccount, short[] colixes, int[][] polygons, BS bsSlabDisplay)1047 public static String getPolygonColorData(int ccount, short[] colixes, int[][] polygons, BS bsSlabDisplay) { 1048 boolean isExplicit = (polygons != null); 1049 if (colixes == null && polygons == null) 1050 return null; 1051 SB list1 = new SB(); 1052 int count = 0; 1053 short colix = 0; 1054 int color = 0, colorNext = 0; 1055 boolean done = false; 1056 for (int i = 0; i < ccount || (done = true) == true; i++) { 1057 if (!done && bsSlabDisplay != null && !bsSlabDisplay.get(i)) 1058 continue; 1059 if (done || (isExplicit ? (colorNext = polygons[i][MeshSurface.P_EXPLICIT_COLOR]) != color : colixes[i] != colix)) { 1060 if (count != 0) 1061 list1.append(" ").appendI(count).append(" ").appendI( 1062 (isExplicit ? color : colix == 0 ? 0 : C.getArgb(colix))); 1063 if (done) 1064 break; 1065 if (isExplicit) 1066 color = colorNext; 1067 else 1068 colix = colixes[i]; 1069 count = 1; 1070 } else { 1071 count++; 1072 } 1073 } 1074 list1.append("\n"); 1075 return list1.toString(); 1076 } 1077 1078 @Override getShapeState()1079 public String getShapeState() { 1080 clean(); 1081 SB sb = new SB(); 1082 sb.append("\n"); 1083 for (int i = 0; i < meshCount; i++) 1084 getMeshCommand(sb, i); 1085 return sb.toString(); 1086 } 1087 getMeshCommand(SB sb, int i)1088 private void getMeshCommand(SB sb, int i) { 1089 IsosurfaceMesh imesh = (IsosurfaceMesh) meshes[i]; 1090 if (imesh == null || imesh.scriptCommand == null) 1091 return; 1092 String cmd = imesh.scriptCommand; 1093 int modelCount = vwr.ms.mc; 1094 if (modelCount > 1) 1095 appendCmd(sb, "frame " + vwr.getModelNumberDotted(imesh.modelIndex)); 1096 cmd = PT.rep(cmd, ";; isosurface map"," map"); 1097 cmd = PT.rep(cmd, "; isosurface map", " map"); 1098 if (cmd.endsWith(" map")) // isosurface map colorscheme "rwb" bug 1099 cmd = cmd.substring(0, cmd.length() - 4); 1100 cmd = cmd.replace('\t', ' '); 1101 cmd = PT.rep(cmd, ";#", "; #"); 1102 int pt = cmd.indexOf("; #"); 1103 if (pt >= 0) 1104 cmd = cmd.substring(0, pt); 1105 if (imesh.connectedAtoms != null) 1106 cmd += " connect " + Escape.eAI(imesh.connectedAtoms); 1107 cmd = PT.trim(cmd, ";"); 1108 if (imesh.linkedMesh != null) 1109 cmd += " LINK"; // for lcaoCartoon state 1110 if (myType == "lcaoCartoon" && imesh.atomIndex >= 0) 1111 cmd += " ATOMINDEX " + imesh.atomIndex; 1112 appendCmd(sb, cmd); 1113 String id = myType + " ID " + PT.esc(imesh.thisID); 1114 if (imesh.jvxlData.thisSet != null && imesh.jvxlData.thisSet.cardinality() > 0) { 1115 appendCmd(sb, id + (imesh.jvxlData.thisSet.cardinality() == 1 ? " set " + (imesh.jvxlData.thisSet.nextSetBit(0)+1) 1116 : " subset " + imesh.jvxlData.thisSet)); 1117 } 1118 if (imesh.mat4 != null && !imesh.isModelConnected) 1119 appendCmd(sb, id + " move " + Escape.matrixToScript(imesh.mat4)); 1120 if (imesh.scale3d != 0) 1121 appendCmd(sb, id + " scale3d " + imesh.scale3d); 1122 if (imesh.jvxlData.slabValue != Integer.MIN_VALUE) 1123 appendCmd(sb, id + " slab " + imesh.jvxlData.slabValue); 1124 if (imesh.slabOptions != null) 1125 appendCmd(sb, imesh.slabOptions.toString()); 1126 if (cmd.charAt(0) != '#') { 1127 if (allowMesh) 1128 appendCmd(sb, imesh.getState(myType)); 1129 if (!imesh.isColorSolid && imesh.colorType == 0 && C.isColixTranslucent(imesh.colix)) 1130 appendCmd(sb, "color " + myType + " " + getTranslucentLabel(imesh.colix)); 1131 if (imesh.colorCommand != null && imesh.colorType == 0 && !imesh.colorCommand.equals("#inherit;")) { 1132 appendCmd(sb, imesh.colorCommand); 1133 } 1134 boolean colorArrayed = (imesh.isColorSolid && imesh.pcs != null); 1135 if (imesh.isColorSolid && imesh.colorType == 0 && !imesh.colorsExplicit && !colorArrayed) { 1136 appendCmd(sb, getColorCommandUnk(myType, imesh.colix, translucentAllowed)); 1137 } else if (imesh.jvxlData.isBicolorMap && imesh.colorPhased) { 1138 appendCmd(sb, "color isosurface phase " 1139 + encodeColor(imesh.jvxlData.minColorIndex) + " " 1140 + encodeColor(imesh.jvxlData.maxColorIndex)); 1141 } 1142 if (imesh.vertexColorMap != null) 1143 for (Map.Entry<String, BS> entry : imesh.vertexColorMap.entrySet()) { 1144 BS bs = entry.getValue(); 1145 if (!bs.isEmpty()) 1146 appendCmd(sb, "color " + myType + " " + Escape.eBS(bs) 1147 + " " + entry.getKey()); 1148 } 1149 } 1150 } 1151 1152 1153 private String script; 1154 getScriptBitSets(String script, BS[] bsCmd)1155 private boolean getScriptBitSets(String script, BS[] bsCmd) { 1156 this.script = script; 1157 int i; 1158 iHaveModelIndex = false; 1159 modelIndex = -1; 1160 if (script != null && (i = script.indexOf("MODEL({")) >= 0) { 1161 int j = script.indexOf("})", i); 1162 if (j > 0) { 1163 BS bs = BS.unescape(script.substring(i + 3, j + 1)); 1164 modelIndex = (bs == null ? -1 : bs.nextSetBit(0)); 1165 iHaveModelIndex = (modelIndex >= 0); 1166 } 1167 } 1168 if (script == null) 1169 return false; 1170 getCapSlabInfo(script); 1171 i = script.indexOf("# ({"); 1172 if (i < 0) 1173 return false; 1174 int j = script.indexOf("})", i); 1175 if (j < 0) 1176 return false; 1177 BS bs = BS.unescape(script.substring(i + 2, j + 2)); 1178 if (bsCmd == null) 1179 sg.setProp("select", bs, null); 1180 else 1181 bsCmd[0] = bs; 1182 if ((i = script.indexOf("({", j)) < 0) 1183 return true; 1184 j = script.indexOf("})", i); 1185 if (j < 0) 1186 return false; 1187 bs = BS.unescape(script.substring(i + 1, j + 1)); 1188 if (bsCmd == null) 1189 sg.setProp("ignore", bs, null); 1190 else 1191 bsCmd[1] = bs; 1192 if ((i = script.indexOf("/({", j)) == j + 2) { 1193 if ((j = script.indexOf("})", i)) < 0) 1194 return false; 1195 bs = BS.unescape(script.substring(i + 3, j + 1)); 1196 if (bsCmd == null) 1197 vwr.ms.setTrajectoryBs(bs); 1198 else 1199 bsCmd[2] = bs; 1200 } 1201 return true; 1202 } 1203 getCapSlabInfo(String script)1204 protected void getCapSlabInfo(String script) { 1205 int i = script.indexOf("# SLAB="); 1206 if (i >= 0) 1207 sg.setProp("slab", getCapSlabObject(PT.getQuotedStringAt(script, i), false), null); 1208 i = script.indexOf("# CAP="); 1209 if (i >= 0) 1210 sg.setProp("slab", getCapSlabObject(PT.getQuotedStringAt(script, i), true), null); 1211 } 1212 1213 /** 1214 * legacy -- for some scripts with early isosurface slabbing 1215 * 1216 * @param s 1217 * @param isCap 1218 * @return slabInfo object 1219 */ getCapSlabObject(String s, boolean isCap)1220 private Object[] getCapSlabObject(String s, boolean isCap) { 1221 try { 1222 if (s.indexOf("array") == 0) { 1223 String[] pts = PT.split(s.substring(6, s.length() - 1), ","); 1224 return TempArray.getSlabObjectType(T.boundbox, 1225 new P3[] { (P3) Escape.uP(pts[0]), (P3) Escape.uP(pts[1]), 1226 (P3) Escape.uP(pts[2]), (P3) Escape.uP(pts[3]) }, isCap, null); 1227 } 1228 Object plane = Escape.uP(s); 1229 if (plane instanceof P4) 1230 return TempArray.getSlabObjectType(T.plane, plane, isCap, null); 1231 } catch (Exception e) { 1232 // 1233 } 1234 return null; 1235 } 1236 1237 1238 private boolean iHaveModelIndex; 1239 initializeIsosurface()1240 private void initializeIsosurface() { 1241 //System.out.println("isosurface initializing " + thisMesh); 1242 if (!iHaveModelIndex) 1243 modelIndex = vwr.am.cmi; 1244 atomIndex = -1; 1245 //allowContourLines = true; //but not for f(x,y) or plane, which use mesh 1246 bsDisplay = null; 1247 center = P3.new3(Float.NaN, 0, 0); 1248 colix = C.ORANGE; 1249 connections = null; 1250 cutoffRange = null; 1251 colorType = defaultColix = meshColix = 0; 1252 displayWithinPoints = null; 1253 explicitContours = false; 1254 isFixed = (modelIndex < 0); 1255 isPhaseColored = isColorExplicit = false; 1256 linkedMesh = null; 1257 if (modelIndex < 0) 1258 modelIndex = 0; 1259 // but note that modelIndex = -1 1260 // is critical for surfaceGenerator. Setting this equal to 1261 // 0 indicates only surfaces for model 0. 1262 scale3d = 0; 1263 title = null; 1264 translucentLevel = 0; 1265 withinPoints = null; 1266 initState(); 1267 } 1268 initState()1269 private void initState() { 1270 associateNormals = true; 1271 sg.initState(); 1272 //TODO need to pass assocCutoff to sg 1273 } 1274 setMeshI()1275 private void setMeshI() { 1276 thisMesh.visible = true; 1277 if ((thisMesh.atomIndex = atomIndex) >= 0) 1278 thisMesh.modelIndex = vwr.ms.at[atomIndex].mi; 1279 else if (isFixed) 1280 thisMesh.modelIndex = -1; 1281 else if (modelIndex >= 0) 1282 thisMesh.modelIndex = modelIndex; 1283 else 1284 thisMesh.modelIndex = vwr.am.cmi; 1285 thisMesh.scriptCommand = script; 1286 thisMesh.ptCenter.setT(center); 1287 thisMesh.scale3d = (thisMesh.jvxlData.jvxlPlane == null ? 0 : scale3d); 1288 // if (thisMesh.bsSlabDisplay != null) 1289 // thisMesh.jvxlData.vertexDataOnly = true; 1290 // thisMesh.bsSlabDisplay = thisMesh.jvxlData.bsSlabDisplay; 1291 } 1292 1293 /* 1294 void checkFlags() { 1295 if (vwr.getTestFlag2()) 1296 associateNormals = false; 1297 if (!logMessages) 1298 return; 1299 Logger.info("Isosurface using testflag2: no associative grouping = " 1300 + !associateNormals); 1301 Logger.info("IsosurfaceRenderer using testflag4: show vertex normals = " 1302 + vwr.getTestFlag4()); 1303 Logger 1304 .info("For grid points, use: isosurface delete myiso gridpoints \"\""); 1305 } 1306 */ 1307 discardTempData(boolean discardAll)1308 protected void discardTempData(boolean discardAll) { 1309 if (!discardAll) 1310 return; 1311 title = null; 1312 if (thisMesh == null) 1313 return; 1314 thisMesh.surfaceSet = null; 1315 } 1316 1317 //////////////////////////////////////////////////////////////// 1318 // default color stuff (deprecated in 11.2) 1319 //////////////////////////////////////////////////////////////// 1320 getDefaultColix()1321 private short getDefaultColix() { 1322 if (defaultColix != 0) 1323 return defaultColix; 1324 if (!sg.jvxlData.wasCubic) 1325 return colix; // orange 1326 int argb = (sg.params.cutoff >= 0 ? JC.argbsIsosurfacePositive 1327 : JC.argbsIsosurfaceNegative); 1328 return C.getColix(argb); 1329 } 1330 1331 /////////////////////////////////////////////////// 1332 //// LCAO Cartoons are sets of lobes //// 1333 1334 private int nLCAO = 0; 1335 drawLcaoCartoon(V3 z, V3 x, V3 rotAxis, int nElectrons)1336 private void drawLcaoCartoon(V3 z, V3 x, V3 rotAxis, int nElectrons) { 1337 String lcaoCartoon = sg.setLcao(); 1338 //really rotRadians is just one of these -- x, y, or z -- not all 1339 float rotRadians = rotAxis.x + rotAxis.y + rotAxis.z; 1340 defaultColix = C.getColix(sg.params.colorPos); 1341 short colixNeg = C.getColix(sg.params.colorNeg); 1342 V3 y = new V3(); 1343 boolean isReverse = (lcaoCartoon.length() > 0 && lcaoCartoon.charAt(0) == '-'); 1344 if (isReverse) 1345 lcaoCartoon = lcaoCartoon.substring(1); 1346 int sense = (isReverse ? -1 : 1); 1347 y.cross(z, x); 1348 if (rotRadians != 0) { 1349 A4 a = new A4(); 1350 if (rotAxis.x != 0) 1351 a.setVA(x, rotRadians); 1352 else if (rotAxis.y != 0) 1353 a.setVA(y, rotRadians); 1354 else 1355 a.setVA(z, rotRadians); 1356 M3 m = new M3().setAA(a); 1357 m.rotate(x); 1358 m.rotate(y); 1359 m.rotate(z); 1360 } 1361 if (thisMesh == null && nLCAO == 0) 1362 nLCAO = meshCount; 1363 String id = (thisMesh == null ? (nElectrons > 0 ? "lp" : "lcao") + (++nLCAO) + "_" + lcaoCartoon 1364 : thisMesh.thisID); 1365 if (thisMesh == null) 1366 allocMesh(id, null); 1367 if (lcaoCartoon.equals("px")) { 1368 thisMesh.thisID += "a"; 1369 Mesh meshA = thisMesh; 1370 createLcaoLobe(x, sense, nElectrons); 1371 if (nElectrons > 0) 1372 return; 1373 setProperty("thisID", id + "b", null); 1374 createLcaoLobe(x, -sense, nElectrons); 1375 thisMesh.colix = colixNeg; 1376 linkedMesh = thisMesh.linkedMesh = meshA; 1377 return; 1378 } 1379 if (lcaoCartoon.equals("py")) { 1380 thisMesh.thisID += "a"; 1381 Mesh meshA = thisMesh; 1382 createLcaoLobe(y, sense, nElectrons); 1383 if (nElectrons > 0) 1384 return; 1385 setProperty("thisID", id + "b", null); 1386 createLcaoLobe(y, -sense, nElectrons); 1387 thisMesh.colix = colixNeg; 1388 linkedMesh = thisMesh.linkedMesh = meshA; 1389 return; 1390 } 1391 if (lcaoCartoon.equals("pz")) { 1392 thisMesh.thisID += "a"; 1393 Mesh meshA = thisMesh; 1394 createLcaoLobe(z, sense, nElectrons); 1395 if (nElectrons > 0) 1396 return; 1397 setProperty("thisID", id + "b", null); 1398 createLcaoLobe(z, -sense, nElectrons); 1399 thisMesh.colix = colixNeg; 1400 linkedMesh = thisMesh.linkedMesh = meshA; 1401 return; 1402 } 1403 if (lcaoCartoon.equals("pza") 1404 || lcaoCartoon.indexOf("sp") == 0 1405 || lcaoCartoon.indexOf("d") == 0 1406 || lcaoCartoon.indexOf("lp") == 0) { 1407 createLcaoLobe(z, sense, nElectrons); 1408 return; 1409 } 1410 if (lcaoCartoon.equals("pzb")) { 1411 createLcaoLobe(z, -sense, nElectrons); 1412 return; 1413 } 1414 if (lcaoCartoon.equals("pxa")) { 1415 createLcaoLobe(x, sense, nElectrons); 1416 return; 1417 } 1418 if (lcaoCartoon.equals("pxb")) { 1419 createLcaoLobe(x, -sense, nElectrons); 1420 return; 1421 } 1422 if (lcaoCartoon.equals("pya")) { 1423 createLcaoLobe(y, sense, nElectrons); 1424 return; 1425 } 1426 if (lcaoCartoon.equals("pyb")) { 1427 createLcaoLobe(y, -sense, nElectrons); 1428 return; 1429 } 1430 if (lcaoCartoon.equals("spacefill") || lcaoCartoon.equals("cpk")) { 1431 createLcaoLobe(null, 2 * vwr.ms.at[atomIndex].getRadius(), nElectrons); 1432 return; 1433 } 1434 1435 // assume s 1436 createLcaoLobe(null, 1, nElectrons); 1437 return; 1438 } 1439 1440 private P4 lcaoDir = new P4(); 1441 createLcaoLobe(V3 lobeAxis, float factor, int nElectrons)1442 private void createLcaoLobe(V3 lobeAxis, float factor, int nElectrons) { 1443 initState(); 1444 if (Logger.debugging) { 1445 Logger.debug("creating isosurface ID " + thisMesh.thisID); 1446 } 1447 if (lobeAxis == null) { 1448 setProperty("sphere", Float.valueOf(factor / 2f), null); 1449 } else { 1450 lcaoDir.x = lobeAxis.x * factor; 1451 lcaoDir.y = lobeAxis.y * factor; 1452 lcaoDir.z = lobeAxis.z * factor; 1453 lcaoDir.w = 0.7f; 1454 setProperty(nElectrons == 2 ? "lp" : nElectrons == 1 ? "rad" : "lobe", 1455 lcaoDir, null); 1456 } 1457 thisMesh.colix = defaultColix; 1458 setScriptInfo(null); 1459 } 1460 1461 /////////////// meshDataServer interface ///////////////// 1462 1463 @Override invalidateTriangles()1464 public void invalidateTriangles() { 1465 thisMesh.invalidatePolygons(); 1466 } 1467 1468 @Override setOutputChannel(GenericBinaryDocument binaryDoc, OC out)1469 public void setOutputChannel(GenericBinaryDocument binaryDoc, OC out) { 1470 binaryDoc.setOutputChannel(out); 1471 } 1472 1473 @Override fillMeshData(MeshData meshData, int mode, IsosurfaceMesh mesh)1474 public void fillMeshData(MeshData meshData, int mode, IsosurfaceMesh mesh) { 1475 if (meshData == null) { 1476 if (thisMesh == null) 1477 allocMesh(null, null); 1478 if (!thisMesh.isMerged) 1479 thisMesh.clearType(myType, sg.params.iAddGridPoints); 1480 thisMesh.connectedAtoms = connections; 1481 thisMesh.colix = getDefaultColix(); 1482 thisMesh.colorType = colorType; 1483 thisMesh.meshColix = meshColix; 1484 if (isPhaseColored || thisMesh.jvxlData.isBicolorMap) 1485 thisMesh.isColorSolid = false; 1486 return; 1487 } 1488 if (mesh == null) 1489 mesh = thisMesh; 1490 if (mesh == null) 1491 return; 1492 //System.out.println("isosurface _get " + mode + " " + MeshData.MODE_GET_VERTICES + " " + MeshData.MODE_PUT_VERTICES + " vc=" + mesh.vertexCount + " pc=" + mesh.polygonCount + " " + mesh +" " 1493 // + (mesh.bsSlabDisplay == null ? "" : 1494 //" bscard=" + mesh.bsSlabDisplay.cardinality() + 1495 //" " + mesh.bsSlabDisplay.hashCode() + " " + mesh.bsSlabDisplay)); 1496 switch (mode) { 1497 case MeshData.MODE_GET_VERTICES: 1498 meshData.mergeVertexCount0 = mesh.mergeVertexCount0; 1499 meshData.vs = mesh.vs; 1500 meshData.vertexSource = mesh.vertexSource; 1501 meshData.vvs = mesh.vvs; 1502 meshData.vc = mesh.vc; 1503 meshData.vertexIncrement = mesh.vertexIncrement; 1504 meshData.pc = mesh.pc; 1505 meshData.pis = mesh.pis; 1506 meshData.pcs = mesh.pcs; 1507 meshData.bsSlabDisplay = mesh.bsSlabDisplay; 1508 meshData.bsSlabGhost = mesh.bsSlabGhost; 1509 meshData.slabColix = mesh.slabColix; 1510 meshData.slabMeshType = mesh.slabMeshType; 1511 meshData.polygonCount0 = mesh.polygonCount0; 1512 meshData.vertexCount0 = mesh.vertexCount0; 1513 meshData.slabOptions = mesh.slabOptions; 1514 meshData.colorsExplicit = mesh.colorsExplicit; 1515 return; 1516 case MeshData.MODE_GET_COLOR_INDEXES: 1517 if (mesh.vcs == null 1518 || mesh.vc > mesh.vcs.length) 1519 mesh.vcs = new short[mesh.vc]; 1520 meshData.vcs = mesh.vcs; 1521 //meshData.polygonIndexes = null; 1522 return; 1523 case MeshData.MODE_PUT_SETS: 1524 mesh.surfaceSet = meshData.surfaceSet; 1525 mesh.vertexSets = meshData.vertexSets; 1526 mesh.nSets = meshData.nSets; 1527 return; 1528 case MeshData.MODE_PUT_VERTICES: 1529 mesh.vs = meshData.vs; 1530 mesh.vvs = meshData.vvs; 1531 mesh.vc = meshData.vc; 1532 mesh.vertexIncrement = meshData.vertexIncrement; 1533 mesh.vertexSource = meshData.vertexSource; 1534 mesh.pc = meshData.pc; 1535 mesh.pis = meshData.pis; 1536 mesh.pcs = meshData.pcs; 1537 mesh.bsSlabDisplay = meshData.bsSlabDisplay; 1538 mesh.bsSlabGhost = meshData.bsSlabGhost; 1539 mesh.slabColix = meshData.slabColix; 1540 mesh.slabMeshType = meshData.slabMeshType; 1541 mesh.polygonCount0 = meshData.polygonCount0; 1542 mesh.vertexCount0 = meshData.vertexCount0; 1543 mesh.mergeVertexCount0 = meshData.mergeVertexCount0; 1544 mesh.slabOptions = meshData.slabOptions; 1545 mesh.colorsExplicit = meshData.colorsExplicit; 1546 return; 1547 } 1548 } 1549 1550 @Override notifySurfaceGenerationCompleted()1551 public boolean notifySurfaceGenerationCompleted() { 1552 setMeshI(); 1553 setBsVdw(); 1554 thisMesh.surfaceAtoms = sg.params.bsSelected; 1555 thisMesh.insideOut = sg.params.isInsideOut(); 1556 thisMesh.isModelConnected = sg.params.isModelConnected; 1557 thisMesh.vertexSource = sg.params.vertexSource; 1558 thisMesh.oabc = sg.getOriginVaVbVc(); 1559 thisMesh.calculatedArea = null; 1560 thisMesh.calculatedVolume = null; 1561 thisMesh.probeValues = sg.params.probeValues; 1562 // from JVXL file: 1563 if (!thisMesh.isMerged) { 1564 thisMesh.initialize(sg.params.isFullyLit() ? T.fullylit 1565 : T.frontlit, null, sg.params.thePlane); 1566 if (jvxlData.fixedLattice != null) { 1567 thisMesh.lattice = jvxlData.fixedLattice; 1568 thisMesh.fixLattice(); 1569 } 1570 return thisMesh.setColorsFromJvxlData(sg.params.colorRgb); 1571 } 1572 if (!sg.params.allowVolumeRender) 1573 thisMesh.jvxlData.allowVolumeRender = false; 1574 thisMesh.setColorsFromJvxlData(sg.params.colorRgb); 1575 if (thisMesh.jvxlData.slabInfo != null) 1576 vwr.runScriptCautiously("isosurface " + thisMesh.jvxlData.slabInfo); 1577 1578 if (sg.params.psi_monteCarloCount > 0) 1579 thisMesh.diameter = -1; // use set DOTSCALE 1580 return false; 1581 1582 } 1583 1584 @Override notifySurfaceMappingCompleted()1585 public void notifySurfaceMappingCompleted() { 1586 if (!thisMesh.isMerged) 1587 thisMesh.initialize(sg.params.isFullyLit() ? T.fullylit : T.frontlit, null, 1588 sg.params.thePlane); 1589 setBsVdw(); 1590 thisMesh.isColorSolid = false; 1591 thisMesh.colorDensity = jvxlData.colorDensity; 1592 thisMesh.volumeRenderPointSize = jvxlData.pointSize; 1593 thisMesh.colorEncoder = sg.params.colorEncoder; 1594 thisMesh.getContours(); 1595 if (thisMesh.jvxlData.nContours != 0 && thisMesh.jvxlData.nContours != -1) 1596 explicitContours = true; 1597 if (explicitContours && thisMesh.jvxlData.jvxlPlane != null) 1598 thisMesh.havePlanarContours = true; 1599 setPropertySuper("token", 1600 Integer.valueOf(explicitContours ? T.nofill : T.fill), null); 1601 setPropertySuper("token", 1602 Integer.valueOf(explicitContours ? T.contourlines : T.nocontourlines), 1603 null); 1604 if (!thisMesh.isMerged) 1605 thisMesh.setJvxlDataRendering(); 1606 if (sg.params.slabInfo != null) { 1607 thisMesh.slabPolygonsList(sg.params.slabInfo, false); 1608 thisMesh.reinitializeLightingAndColor(vwr); 1609 } 1610 // may not be the final color scheme, though. 1611 thisMesh.setColorCommand(); 1612 } 1613 setBsVdw()1614 private void setBsVdw() { 1615 if (sg.bsVdw == null) 1616 return; 1617 if (thisMesh.bsVdw == null) 1618 thisMesh.bsVdw = new BS(); 1619 thisMesh.bsVdw.or(sg.bsVdw); 1620 } 1621 1622 @Override calculateGeodesicSurface(BS bsSelected, float envelopeRadius)1623 public P3[] calculateGeodesicSurface(BS bsSelected, 1624 float envelopeRadius) { 1625 return vwr.calculateSurface(bsSelected, envelopeRadius); 1626 } 1627 1628 ///////////// VertexDataServer interface methods //////////////// 1629 1630 @Override getSurfacePointIndexAndFraction(float cutoff, boolean isCutoffAbsolute, int x, int y, int z, P3i offset, int vA, int vB, float valueA, float valueB, T3 pointA, V3 edgeVector, boolean isContourType, float[] fReturn)1631 public int getSurfacePointIndexAndFraction(float cutoff, boolean isCutoffAbsolute, 1632 int x, int y, int z, P3i offset, int vA, 1633 int vB, float valueA, float valueB, 1634 T3 pointA, V3 edgeVector, 1635 boolean isContourType, float[] fReturn) { 1636 return 0; 1637 } 1638 1639 private boolean associateNormals; 1640 private String oldFileName; 1641 private String newFileName; 1642 1643 @Override addVertexCopy(T3 vertexXYZ, float value, int assocVertex, boolean asCopy)1644 public int addVertexCopy(T3 vertexXYZ, float value, int assocVertex, boolean asCopy) { 1645 if (cutoffRange != null && (value < cutoffRange[0] || value > cutoffRange[1])) 1646 return -1; 1647 return (withinPoints != null && !Mesh.checkWithin(vertexXYZ, withinPoints, withinDistance2, isWithinNot) ? -1 1648 : thisMesh.addVertexCopy(vertexXYZ, value, assocVertex, 1649 associateNormals, asCopy)); 1650 } 1651 1652 @Override addTriangleCheck(int iA, int iB, int iC, int check, int iContour, boolean isAbsolute, int color)1653 public int addTriangleCheck(int iA, int iB, int iC, int check, 1654 int iContour, boolean isAbsolute, int color) { 1655 return (iA < 0 || iB < 0 || iC < 0 1656 || isAbsolute && !MeshData.checkCutoff(iA, iB, iC, thisMesh.vvs) 1657 ? -1 : thisMesh.addTriangleCheck(iA, iB, iC, check, iContour, color)); 1658 } 1659 setScriptInfo(String strCommand)1660 protected void setScriptInfo(String strCommand) { 1661 // also from lcaoCartoon 1662 String script = (strCommand == null ? sg.params.script : strCommand); 1663 int pt = (script == null ? -1 : script.indexOf("; isosurface map")); 1664 if (pt == 0) { 1665 // remapping surface 1666 if (thisMesh.scriptCommand == null) 1667 return; 1668 pt = thisMesh.scriptCommand.indexOf("; isosurface map"); 1669 if (pt >= 0) 1670 thisMesh.scriptCommand = thisMesh.scriptCommand.substring(0, pt); 1671 thisMesh.scriptCommand += script; 1672 return; 1673 } 1674 thisMesh.title = sg.params.title; 1675 thisMesh.dataType = sg.params.dataType; 1676 thisMesh.scale3d = sg.params.scale3d; 1677 if (script != null) { 1678 if (oldFileName != null) { 1679 script = script.replace(oldFileName, newFileName); 1680 } 1681 if (script.charAt(0) == ' ') { 1682 script = myType + " ID " + PT.esc(thisMesh.thisID) + script; 1683 pt = script.indexOf("; isosurface map"); 1684 } 1685 } 1686 if (pt > 0 && scriptAppendix.length() > 0) 1687 thisMesh.scriptCommand = script.substring(0, pt) + scriptAppendix + script.substring(pt); 1688 else 1689 thisMesh.scriptCommand = script + scriptAppendix; 1690 if (!explicitID && script != null && (pt = script.indexOf("# ID=")) >= 0) 1691 thisMesh.thisID = PT.getQuotedStringAt(script, pt); 1692 } 1693 1694 @Override addRequiredFile(String fileName)1695 public void addRequiredFile(String fileName) { 1696 fileName = " # /*file*/\"" + fileName + "\""; 1697 if (scriptAppendix.indexOf(fileName) < 0) 1698 scriptAppendix += fileName; 1699 } 1700 1701 @Override setRequiredFile(String oldName, String fileName)1702 public void setRequiredFile(String oldName, String fileName) { 1703 oldFileName = oldName; 1704 newFileName = fileName; 1705 } 1706 setJvxlInfo()1707 private void setJvxlInfo() { 1708 if (sg.jvxlData != jvxlData || sg.jvxlData != thisMesh.jvxlData) 1709 jvxlData = thisMesh.jvxlData = sg.jvxlData; 1710 } 1711 1712 @Override getShapeDetail()1713 public Object getShapeDetail() { 1714 Lst<Map<String, Object>> V = new Lst<Map<String, Object>>(); 1715 for (int i = 0; i < meshCount; i++) { 1716 Map<String, Object> info = new Hashtable<String, Object>(); 1717 IsosurfaceMesh mesh = isomeshes[i]; 1718 if (mesh == null || mesh.vs == null 1719 || mesh.vc == 0 && mesh.pc == 0) 1720 continue; 1721 addMeshInfo(mesh, info); 1722 V.addLast(info); 1723 } 1724 return V; 1725 } 1726 addMeshInfo(IsosurfaceMesh mesh, Map<String, Object> info)1727 protected void addMeshInfo(IsosurfaceMesh mesh, Map<String, Object> info) { 1728 info.put("ID", (mesh.thisID == null ? "<noid>" : mesh.thisID)); 1729 info.put("visible", Boolean.valueOf(mesh.visible)); 1730 info.put("vertexCount", Integer.valueOf(mesh.vc)); 1731 if (mesh.calculatedVolume != null) 1732 info.put("volume", mesh.calculatedVolume); 1733 if (mesh.calculatedArea != null) 1734 info.put("area", mesh.calculatedArea); 1735 if (!Float.isNaN(mesh.ptCenter.x)) 1736 info.put("center", mesh.ptCenter); 1737 if (mesh.mat4 != null) 1738 info.put("mat4", mesh.mat4); 1739 if (mesh.scale3d != 0) 1740 info.put("scale3d", Float.valueOf(mesh.scale3d)); 1741 info.put("xyzMin", mesh.jvxlData.boundingBox[0]); 1742 info.put("xyzMax", mesh.jvxlData.boundingBox[1]); 1743 String s = JvxlCoder.jvxlGetInfo(mesh.jvxlData); 1744 if (s != null) 1745 info.put("jvxlInfo", s.replace('\n', ' ')); 1746 info.put("modelIndex", Integer.valueOf(mesh.modelIndex)); 1747 info.put("color", CU.colorPtFromInt(C 1748 .getArgb(mesh.colix), null)); 1749 if (mesh.colorEncoder != null) 1750 info.put("colorKey", mesh.colorEncoder.getColorKey()); 1751 if (mesh.title != null) 1752 info.put("title", mesh.title); 1753 if (mesh.jvxlData.contourValues != null 1754 || mesh.jvxlData.contourValuesUsed != null) 1755 info.put("contours", mesh.getContourList(vwr)); 1756 } 1757 1758 @Override getPlane(int x)1759 public float[] getPlane(int x) { 1760 // only for surface readers 1761 return null; 1762 } 1763 1764 @Override getValue(int x, int y, int z, int ptyz)1765 public float getValue(int x, int y, int z, int ptyz) { 1766 return 0; 1767 } 1768 1769 @Override checkObjectHovered(int x, int y, BS bsVisible)1770 public boolean checkObjectHovered(int x, int y, BS bsVisible) { 1771 if (keyXy != null && x >= keyXy[0] && y >= keyXy[1] && x < keyXy[2] && y < keyXy[3]) { 1772 hoverKey(x, y); 1773 return true; 1774 } 1775 if (!vwr.getDrawHover()) 1776 return false; 1777 String s = findValue(x, y, false, bsVisible); 1778 if (s == null) 1779 return false; 1780 if (vwr.gdata.antialiasEnabled) { 1781 //because hover rendering is done in FIRST pass only 1782 x <<= 1; 1783 y <<= 1; 1784 } 1785 vwr.hoverOnPt(x, y, s, pickedMesh.thisID, pickedPt); 1786 return true; 1787 } 1788 hoverKey(int x, int y)1789 private void hoverKey(int x, int y) { 1790 try { 1791 String s; 1792 float f = 1 - 1.0f * (y - keyXy[1]) / (keyXy[3] - keyXy[1]); 1793 if (thisMesh.showContourLines) { 1794 Lst<Object>[] vContours = thisMesh.getContours(); 1795 if (vContours == null) { 1796 if (thisMesh.jvxlData.contourValues == null) 1797 return; 1798 int i = (int) Math.floor(f * thisMesh.jvxlData.contourValues.length); 1799 if (i < 0 || i > thisMesh.jvxlData.contourValues.length) 1800 return; 1801 s = "" + thisMesh.jvxlData.contourValues[i]; 1802 } else { 1803 int i = (int) Math.floor(f * vContours.length); 1804 if (i < 0 || i > vContours.length) 1805 return; 1806 s = "" 1807 + ((Float) vContours[i].get(JvxlCoder.CONTOUR_VALUE)) 1808 .floatValue(); 1809 } 1810 } else { 1811 float g = thisMesh.colorEncoder.quantize(f, true); 1812 f = thisMesh.colorEncoder.quantize(f, false); 1813 s = "" + g + " - " + f; 1814 } 1815 if (vwr.gdata.isAntialiased()) { 1816 x <<= 1; 1817 y <<= 1; 1818 } 1819 vwr.hoverOnPt(x, y, s, null, null); 1820 } catch (Exception e) { 1821 // never mind! 1822 } 1823 } 1824 private final static int MAX_OBJECT_CLICK_DISTANCE_SQUARED = 10 * 10; 1825 private final P3i ptXY = new P3i(); 1826 public int[] keyXy; 1827 1828 @Override checkObjectClicked(int x, int y, int action, BS bsVisible, boolean drawPicking)1829 public Map<String, Object> checkObjectClicked(int x, int y, int action, BS bsVisible, boolean drawPicking) { 1830 if (!drawPicking)// || vwr.getNavigationMode() && vwr.getNavigateSurface())) 1831 return null; 1832 if (!vwr.isBound(action, ActionManager.ACTION_pickIsosurface)) 1833 return null; 1834 int dmin2 = MAX_OBJECT_CLICK_DISTANCE_SQUARED; 1835 if (vwr.gdata.isAntialiased()) { 1836 x <<= 1; 1837 y <<= 1; 1838 dmin2 <<= 1; 1839 } 1840 int imesh = -1; 1841 int jmaxz = -1; 1842 int jminz = -1; 1843 int maxz = Integer.MIN_VALUE; 1844 int minz = Integer.MAX_VALUE; 1845 boolean pickFront = true; 1846 for (int i = 0; i < meshCount; i++) { 1847 IsosurfaceMesh m = isomeshes[i]; 1848 if (!isPickable(m, bsVisible)) 1849 continue; 1850 T3[] centers = (pickFront ? m.vs : m.getCenters()); 1851 if (centers == null) 1852 continue; 1853 for (int j = centers.length; --j >= 0; ) { 1854 T3 v = centers[j]; 1855 if (v == null) 1856 continue; 1857 int d2 = coordinateInRange(x, y, v, dmin2, ptXY); 1858 if (d2 >= 0) { 1859 if (ptXY.z < minz) { 1860 if (pickFront) 1861 imesh = i; 1862 minz = ptXY.z; 1863 jminz = j; 1864 } 1865 if (ptXY.z > maxz) { 1866 if (!pickFront) 1867 imesh = i; 1868 maxz = ptXY.z; 1869 jmaxz = j; 1870 } 1871 } 1872 } 1873 } 1874 if (imesh < 0) 1875 return null; 1876 pickedMesh = isomeshes[imesh]; 1877 setPropertySuper("thisID", pickedMesh.thisID, null); 1878 int iFace = pickedVertex = (pickFront ? jminz : jmaxz); 1879 P3 ptRet = new P3(); 1880 ptRet.setT((pickFront ? pickedMesh.vs[pickedVertex] : ((IsosurfaceMesh)pickedMesh).centers[iFace])); 1881 pickedModel = (short) pickedMesh.modelIndex; 1882 Map<String, Object> map = getPickedPoint(ptRet, pickedModel); 1883 // if (pickFront) { 1884 setStatusPicked(-4, ptRet, map); 1885 // } else { 1886 // Vector3f vNorm = new Vector3f(); 1887 // ((IsosurfaceMesh)pickedMesh).getFacePlane(iFace, vNorm); 1888 // // get normal to surface 1889 // vNorm.scale(-1); 1890 // // setHeading(ptRet, vNorm, 2); 1891 // } 1892 return map; 1893 } 1894 isPickable(IsosurfaceMesh m, BS bsVisible)1895 private boolean isPickable(IsosurfaceMesh m, BS bsVisible) { 1896 return m.visibilityFlags != 0 && (m.modelIndex < 0 1897 || bsVisible.get(m.modelIndex)) && !C 1898 .isColixTranslucent(m.colix); 1899 } 1900 1901 // private void navigate(int dz) { 1902 // if (thisMesh == null) 1903 // return; 1904 // Point3f navPt = Point3f.newP(vwr.getNavigationOffset()); 1905 // Point3f toPt = new Point3f(); 1906 // vwr.unTransformPoint(navPt, toPt); 1907 // navPt.z += dz; 1908 // vwr.unTransformPoint(navPt, toPt); 1909 // Point3f ptRet = new Point3f(); 1910 // Vector3f vNorm = new Vector3f(); 1911 // if (!getClosestNormal(thisMesh, toPt, ptRet, vNorm)) 1912 // return; 1913 // Point3f pt2 = Point3f.newP(ptRet); 1914 // pt2.add(vNorm); 1915 // Point3f pt2s = new Point3f(); 1916 // vwr.tm.transformPt3f(pt2, pt2s); 1917 // if (pt2s.y > navPt.y) 1918 // vNorm.scale(-1); 1919 // setHeading(ptRet, vNorm, 0); 1920 // } 1921 1922 // private void setHeading(Point3f pt, Vector3f vNorm, int nSeconds) { 1923 // // general trick here is to save the original orientation, 1924 // // then do all the changes and save the new orientation. 1925 // // Then just do a timed restore. 1926 // 1927 // Orientation o1 = vwr.getOrientation(); 1928 // 1929 // // move to point 1930 // vwr.navigatePt(pt); 1931 // 1932 // Point3f toPts = new Point3f(); 1933 // 1934 // // get screen point along normal 1935 // Point3f toPt = Point3f.newP(vNorm); 1936 // //vwr.script("draw test2 vector " + Escape.escape(pt) + " " + Escape.escape(toPt)); 1937 // toPt.add(pt); 1938 // vwr.tm.transformPt3f(toPt, toPts); 1939 // 1940 // // subtract the navigation point to get a relative point 1941 // // that we can project into the xy plane by setting z = 0 1942 // Point3f navPt = Point3f.newP(vwr.getNavigationOffset()); 1943 // toPts.sub(navPt); 1944 // toPts.z = 0; 1945 // 1946 // // set the directed angle and rotate normal into yz plane, 1947 // // less 20 degrees for the normal upward sloping view 1948 // float angle = Measure.computeTorsion(JmolConstants.axisNY, 1949 // JmolConstants.center, JmolConstants.axisZ, toPts, true); 1950 // vwr.navigateAxis(JmolConstants.axisZ, angle); 1951 // toPt.setT(vNorm); 1952 // toPt.add(pt); 1953 // vwr.tm.transformPt3f(toPt, toPts); 1954 // toPts.sub(navPt); 1955 // angle = Measure.computeTorsion(JmolConstants.axisNY, 1956 // JmolConstants.center, JmolConstants.axisX, toPts, true); 1957 // vwr.navigateAxis(JmolConstants.axisX, 20 - angle); 1958 // 1959 // // save this orientation, restore the first, and then 1960 // // use TransformManager.moveto to smoothly transition to it 1961 // // a script is necessary here because otherwise the application 1962 // // would hang. 1963 // 1964 // navPt = Point3f.newP(vwr.getNavigationOffset()); 1965 // if (nSeconds <= 0) 1966 // return; 1967 // vwr.saveOrientation("_navsurf"); 1968 // o1.restore(0, true); 1969 // vwr.script("restore orientation _navsurf " + nSeconds); 1970 // } 1971 1972 // private boolean getClosestNormal(IsosurfaceMesh m, Point3f toPt, Point3f ptRet, Vector3f normalRet) { 1973 // Point3f[] centers = m.getCenters(); 1974 // float d; 1975 // float dmin = Float.MAX_VALUE; 1976 // int imin = -1; 1977 // for (int i = centers.length; --i >= 0; ) { 1978 // if ((d = centers[i].distance(toPt)) >= dmin) 1979 // continue; 1980 // dmin = d; 1981 // imin = i; 1982 // } 1983 // if (imin < 0) 1984 // return false; 1985 // getClosestPoint(m, imin, toPt, ptRet, normalRet); 1986 // return true; 1987 // } 1988 1989 // private void getClosestPoint(IsosurfaceMesh m, int imin, Point3f toPt, Point3f ptRet, 1990 // Vector3f normalRet) { 1991 // Point4f plane = m.getFacePlane(imin, normalRet); 1992 // float dist = Measure.distanceToPlane(plane, toPt); 1993 // normalRet.scale(-dist); 1994 // ptRet.setT(toPt); 1995 // ptRet.add(normalRet); 1996 // dist = Measure.distanceToPlane(plane, ptRet); 1997 // if (m.centers[imin].distance(toPt) < ptRet.distance(toPt)) 1998 // ptRet.setT(m.centers[imin]); 1999 // } 2000 2001 /** 2002 * 2003 * @param x 2004 * @param y 2005 * @param isPicking 2006 * IGNORED 2007 * @param bsVisible 2008 * @return value found 2009 */ findValue(int x, int y, boolean isPicking, BS bsVisible)2010 private String findValue(int x, int y, boolean isPicking, BS bsVisible) { 2011 int dmin2 = MAX_OBJECT_CLICK_DISTANCE_SQUARED; 2012 if (vwr.gdata.isAntialiased()) { 2013 x <<= 1; 2014 y <<= 1; 2015 dmin2 <<= 1; 2016 } 2017 int pickedVertex = -1; 2018 Lst<Object> pickedContour = null; 2019 IsosurfaceMesh m = null; 2020 for (int i = 0; i < meshCount; i++) { 2021 m = isomeshes[i]; 2022 if (!isPickable(m, bsVisible)) 2023 continue; 2024 Lst<Object>[] vs = m.jvxlData.vContours; 2025 int ilast = (m.firstRealVertex < 0 ? 0 : m.firstRealVertex); 2026 int pickedJ = 0; 2027 if (vs != null && vs.length > 0) { 2028 for (int j = 0; j < vs.length; j++) { 2029 Lst<Object> vc = vs[j]; 2030 int n = vc.size() - 1; 2031 for (int k = JvxlCoder.CONTOUR_POINTS; k < n; k++) { 2032 T3 v = (T3) vc.get(k); 2033 int d2 = coordinateInRange(x, y, v, dmin2, ptXY); 2034 if (d2 >= 0) { 2035 dmin2 = d2; 2036 pickedContour = vc; 2037 pickedJ = j; 2038 pickedMesh = m; 2039 pickedPt = v; 2040 } 2041 } 2042 } 2043 if (pickedContour != null) 2044 return pickedContour.get(JvxlCoder.CONTOUR_VALUE).toString() 2045 + (Logger.debugging ? " " + pickedJ : ""); 2046 } else if (m.jvxlData.jvxlPlane != null && m.vvs != null) { 2047 T3[] vertices = (m.mat4 == null && m.scale3d == 0 ? m.vs : m 2048 .getOffsetVertices(m.jvxlData.jvxlPlane)); 2049 for (int k = m.vc; --k >= ilast;) { 2050 T3 v = vertices[k]; 2051 int d2 = coordinateInRange(x, y, v, dmin2, ptXY); 2052 if (d2 >= 0) { 2053 dmin2 = d2; 2054 pickedVertex = k; 2055 pickedMesh = m; 2056 pickedPt = v; 2057 } 2058 } 2059 if (pickedVertex != -1) 2060 break; 2061 } else if (m.vvs != null) { 2062 if (m.bsSlabDisplay != null) { 2063 for (int k = m.bsSlabDisplay.nextSetBit(0); k >= 0; k = m.bsSlabDisplay 2064 .nextSetBit(k + 1)) { 2065 int[] p = m.pis[k]; 2066 if (p != null) 2067 for (int l = 0; l < 3; l++) { 2068 T3 v = m.vs[p[l]]; 2069 int d2 = coordinateInRange(x, y, v, dmin2, ptXY); 2070 if (d2 >= 0) { 2071 dmin2 = d2; 2072 pickedVertex = p[l]; 2073 pickedMesh = m; 2074 pickedPt = v; 2075 } 2076 } 2077 } 2078 } else { 2079 for (int k = m.vc; --k >= ilast;) { 2080 T3 v = m.vs[k]; 2081 int d2 = coordinateInRange(x, y, v, dmin2, ptXY); 2082 if (d2 >= 0) { 2083 dmin2 = d2; 2084 pickedVertex = k; 2085 pickedMesh = m; 2086 pickedPt = v; 2087 } 2088 } 2089 } 2090 if (pickedVertex != -1) 2091 break; 2092 } 2093 } 2094 return (pickedVertex == -1 ? null : (Logger.debugging ? "$" + m.thisID 2095 + "[" + (pickedVertex + 1) + "] " + m.vs[pickedVertex] + ": " 2096 : m.thisID + ": ") 2097 + m.vvs[pickedVertex]); 2098 } 2099 getCmd(int index)2100 public String getCmd(int index){ 2101 SB sb = new SB().append("\n"); 2102 // result = this.isomeshes[index].scriptCommand; 2103 getMeshCommand(sb, index); 2104 return (sb.toString()); 2105 } 2106 2107 @Override getValues(Mesh mesh)2108 protected Object getValues(Mesh mesh) { 2109 return (mesh == null ? null : ((IsosurfaceMesh) mesh).getValidValues(null)); 2110 } 2111 2112 2113 @Override getVertices(Mesh mesh)2114 protected Object getVertices(Mesh mesh) { 2115 return (mesh == null ? null : ((IsosurfaceMesh) mesh).getValidVertices(null)); 2116 } 2117 2118 } 2119