Revision: 5185
Author:   hansonr
Date:     2006-05-27 20:37:57 -0700 (Sat, 27 May 2006)
ViewCVS:  http://svn.sourceforge.net/jmol/?rev=5185&view=rev

Log Message:
-----------
bob200603 isosurface upgrade includes color X~nnn compression
and vertex normal grouping. Still a few bugs relating to 

isosurface delete not really doing the job. I'm forgetting to 
clear out one or more global settings in Isosurface.java, I think. 

Modified Paths:
--------------
    branches/bob200603/Jmol/src/org/jmol/viewer/ColorManager.java
    branches/bob200603/Jmol/src/org/jmol/viewer/Isosurface.java
    branches/bob200603/Jmol/src/org/jmol/viewer/MeshCollection.java
    branches/bob200603/Jmol/src/org/jmol/viewer/MeshRenderer.java
Modified: branches/bob200603/Jmol/src/org/jmol/viewer/ColorManager.java
===================================================================
--- branches/bob200603/Jmol/src/org/jmol/viewer/ColorManager.java       
2006-05-28 03:35:37 UTC (rev 5184)
+++ branches/bob200603/Jmol/src/org/jmol/viewer/ColorManager.java       
2006-05-28 03:37:57 UTC (rev 5185)
@@ -29,7 +29,6 @@
 
   Viewer viewer;
   Graphics3D g3d;
-
   int[] argbsCpk;
 
   ColorManager(Viewer viewer, Graphics3D g3d) {
@@ -227,6 +226,46 @@
   }
 
   int quantize(float val, float lo, float hi, int segmentCount) {
+    /* oy! Say you have an array with 10 values, so segmentCount=10
+     * then we expect 0,1,2,...,9  EVENLY
+     * If f = fractional distance from lo to hi, say 0.0 to 10.0 again,
+     * then one might expect 10 even placements. BUT:
+     * (int) (f * segmentCount + 0.5) gives
+     * 
+     * 0.0 ---> 0
+     * 0.5 ---> 1
+     * 1.0 ---> 1
+     * 1.5 ---> 2
+     * 2.0 ---> 2
+     * ...
+     * 8.5 ---> 9
+     * 9.0 ---> 9
+     * 9.5 ---> 10 --> 9
+     * 
+     * so the first bin is underloaded, and the last bin is overloaded.
+     * With integer quantities, one would not notice this, because
+     * 0, 1, 2, 3, .... --> 0, 1, 2, 3, .....
+     * 
+     * but with fractional quantities, it will be noticeable.
+     * 
+     * What we really want is:
+     * 
+     * 0.0 ---> 0
+     * 0.5 ---> 0
+     * 1.0 ---> 1
+     * 1.5 ---> 1
+     * 2.0 ---> 2
+     * ...
+     * 8.5 ---> 8
+     * 9.0 ---> 9
+     * 9.5 ---> 9
+     * 
+     * that is, no addition of 0.5. 
+     * Instead, I add 0.0001, just for discreteness sake.
+     * 
+     * Bob Hanson, 5/2006
+     * 
+     */
     float range = hi - lo;
     if (range <= 0 || Float.isNaN(val))
       return segmentCount / 2;
@@ -234,7 +273,7 @@
     if (t <= 0)
       return 0;
     float quanta = range / segmentCount;
-    int q = (int)(t / quanta + 0.5f);
+    int q = (int)(t / quanta + 0.0001f);  //was 0.5f!
     if (q >= segmentCount)
       q = segmentCount - 1;
     return q;

Modified: branches/bob200603/Jmol/src/org/jmol/viewer/Isosurface.java
===================================================================
--- branches/bob200603/Jmol/src/org/jmol/viewer/Isosurface.java 2006-05-28 
03:35:37 UTC (rev 5184)
+++ branches/bob200603/Jmol/src/org/jmol/viewer/Isosurface.java 2006-05-28 
03:37:57 UTC (rev 5185)
@@ -88,11 +88,12 @@
 class Isosurface extends MeshCollection {
 
   final static boolean logMessages = false;
+  final static boolean logCompression = false;
 
   final float ANGSTROMS_PER_BOHR = JmolConstants.ANGSTROMS_PER_BOHR;
-  final static char defaultEdgeFractionBase = 35; //#$%.......
+  final static int defaultEdgeFractionBase = 35; //#$%.......
   final static float defaultEdgeFractionRange = 90f;
-  final static char defaultColorFractionBase = 35;
+  final static int defaultColorFractionBase = 35;
   final static float defaultColorFractionRange = 
JmolConstants.argbsRoygbScale.length;
 
   final Point3f volumetricOrigin = new Point3f();
@@ -112,9 +113,7 @@
   final Matrix3f volumetricMatrix = new Matrix3f();
   float[][][] voxelData;
 
-  int edgePointCount = 0;
   int fileIndex = 0; //one-based
-  Point3f[] edgePoints;
 
   float cutoff = 0.02f;
   boolean rangeDefined = false;
@@ -126,6 +125,8 @@
   boolean endOfData;
   BufferedReader br;
 
+  int testCount;
+
   void setProperty(String propertyName, Object value, BitSet bs) {
 
     System.out.println("isosurface setProperty: " + propertyName + " = "
@@ -164,19 +165,19 @@
       System.out
           .println("For grid points, use: isosurface delete; isosurface myiso 
gridpoints \"\"");
 
-      associateNormals = ! viewer.getTestFlag2();
-      
+      associateNormals = !viewer.getTestFlag2();
+
       br = (BufferedReader) value;
       if (currentMesh == null)
         allocMesh(null);
       currentMesh.clear("isosurface");
-      if (addGridPoints)
+      if (addGridPoints) {
         currentMesh.showPoints = true;
-
+        currentMesh.hasGridPoints = true;
+      }
       readData(false);
       calcVoxelVertexVectors();
-      thePlane = null;
-      constructTessellatedSurface();
+      generateSurfaceData();
       currentMesh.colix = getDefaultColix();
       initializeMesh(viewer.getTestFlag1()); // see below
       currentMesh.visible = true;
@@ -187,7 +188,6 @@
     }
     if ("plane" == propertyName) {
       thePlane = (Point4f) value;
-      cutoff = 0f;
       return;
     }
     if ("cutoff" == propertyName) {
@@ -215,7 +215,6 @@
         minRange = getMinMappedValue();
         maxRange = getMaxMappedValue();
       }
-      System.out.println(" minRange=" + minRange + " maxRange=" + maxRange);
       applyColorScale(minRange, maxRange, "roygb");
       discardTempData();
       System.out.println("\n" + getJvxlFile(currentMesh, "mapped"));
@@ -225,10 +224,19 @@
   }
 
   boolean isJvxl;
+  int[][] edgeInfo;
+  int edgeCount;
 
   void readData(boolean isMapData) {
     isJvxl = false;
     endOfData = false;
+    if (!isMapData) {
+      currentMesh.surfaceData = "";
+      currentMesh.edgeData = "";
+      edgeInfo = null;
+      edgeCount = 0;
+    }
+
     int nSurfaces = readVolumetricHeader();
     if (nSurfaces < fileIndex) {
       System.out
@@ -246,8 +254,6 @@
   }
 
   void discardTempData() {
-    edgePointCount = 0;
-    edgePoints = null;
     voxelData = null;
     assocGridPointMap = null;
     assocGridPointNormals = null;
@@ -301,6 +307,7 @@
   void readTitleLines() throws Exception {
     jvxlFileHeader = br.readLine() + "\n";
     jvxlFileHeader += br.readLine() + "\n";
+    System.out.println(jvxlFileHeader);
   }
 
   int atomCount;
@@ -318,9 +325,9 @@
       atomCount = -atomCount;
 
     int jvxlAtoms = (atomCount == 0 ? -1 : -atomCount);
-    volumetricOrigin.x = parseFloat(line, ichNextParse);
-    volumetricOrigin.y = parseFloat(line, ichNextParse);
-    volumetricOrigin.z = parseFloat(line, ichNextParse);
+    volumetricOrigin.x = parseFloat();
+    volumetricOrigin.y = parseFloat();
+    volumetricOrigin.z = parseFloat();
     volumetricOrigin.scale(ANGSTROMS_PER_BOHR);
     jvxlFileHeader += jvxlAtoms + " " + atomLine + "\n";
   }
@@ -335,9 +342,9 @@
     jvxlFileHeader += line + "\n";
     Vector3f voxelVector = volumetricVectors[voxelVectorIndex];
     voxelCounts[voxelVectorIndex] = parseInt(line);
-    voxelVector.x = parseFloat(line, ichNextParse);
-    voxelVector.y = parseFloat(line, ichNextParse);
-    voxelVector.z = parseFloat(line, ichNextParse);
+    voxelVector.x = parseFloat();
+    voxelVector.y = parseFloat();
+    voxelVector.z = parseFloat();
     voxelVector.scale(ANGSTROMS_PER_BOHR);
     volumetricVectorLengths[voxelVectorIndex] = voxelVector.length();
     unitVolumetricVectors[voxelVectorIndex].normalize(voxelVector);
@@ -349,10 +356,10 @@
       /*
        Atom atom = atomSetCollection.addNewAtom();
        atom.elementNumber = (byte)parseInt(line);
-       atom.partialCharge = parseFloat(line, ichNextParse);
-       atom.x = parseFloat(line, ichNextParse) * ANGSTROMS_PER_BOHR;
-       atom.y = parseFloat(line, ichNextParse) * ANGSTROMS_PER_BOHR;
-       atom.z = parseFloat(line, ichNextParse) * ANGSTROMS_PER_BOHR;
+       atom.partialCharge = parseFloat();
+       atom.x = parseFloat() * ANGSTROMS_PER_BOHR;
+       atom.y = parseFloat() * ANGSTROMS_PER_BOHR;
+       atom.z = parseFloat() * ANGSTROMS_PER_BOHR;
        */
     }
     if (atomCount == 0)
@@ -369,23 +376,24 @@
 
     if (negativeAtomCount) {
       nSurfaces = parseInt(line = br.readLine());
-      System.out.println("Reading extra orbital information line: " + line);
+      System.out
+          .println("Reading extra orbital/JVXL information line: " + line);
       isJvxl = (nSurfaces < 0);
       if (isJvxl) {
         nSurfaces = -nSurfaces;
         System.out.println("jvxl file surfaces: " + nSurfaces);
-        int ich = parseInt(line, ichNextParse);
+        int ich = parseInt();
         if (ich == Integer.MIN_VALUE) {
           System.out.println("using default edge fraction base and range");
         } else {
           edgeFractionBase = (char) ich;
-          edgeFractionRange = parseFloat(line, ichNextParse);
+          edgeFractionRange = parseFloat();
         }
         if (ich == Integer.MIN_VALUE) {
           System.out.println("using default color fraction base and range");
         } else {
           colorFractionBase = (char) ich;
-          colorFractionRange = parseFloat(line, ichNextParse);
+          colorFractionRange = parseFloat();
         }
       }
     } else {
@@ -393,11 +401,10 @@
     }
     jvxlFileHeader += "-1 " + (int) edgeFractionBase + " "
         + (int) edgeFractionRange + " " + (int) colorFractionBase + " "
-        + (int) colorFractionRange + " Jmol voxel format version 0.9b\n";
+        + (int) colorFractionRange + " Jmol voxel format version 0.9c\n";
     return nSurfaces;
   }
 
-  String line;
   int nBytes;
   int nDataPoints;
   String surfaceData;
@@ -413,7 +420,7 @@
     strFractionTemp = "";
     fractionData = "";
     iHaveColorData = false;
-    thisInside = true;
+    thisInside = (!isJvxl || thePlane == null);
     nDataPoints = 0;
     int nPointsX = voxelCounts[0];
     int nPointsY = voxelCounts[1];
@@ -433,7 +440,9 @@
         thePlane.z = 1; //{0 0 0 w} becomes {0 0 1 w}
       vTemp.set(thePlane.x, thePlane.y, thePlane.z);
       vTempMag = vTemp.length();
+      cutoff = 0f;
     }
+    System.out.println("cutoff = " + cutoff);
     for (int x = 0; x < nPointsX; ++x) {
       float[][] plane = new float[nPointsY][];
       voxelData[x] = plane;
@@ -442,11 +451,11 @@
         plane[y] = strip;
         for (int z = 0; z < nPointsZ; ++z) {
           float voxelValue = getNextVoxelValue();
-          if (thePlane != null)
+          if (!isMapData && thePlane != null)
             voxelValue = calcVoxelPlaneDistance(x, y, z);
           strip[z] = voxelValue;
           ++nDataPoints;
-          if (isJvxl || isMapData)
+          if (isJvxl && thePlane == null || isMapData)
             continue;
           boolean isInside = ((cutoff > 0 && voxelValue >= cutoff) || (cutoff 
<= 0 && voxelValue <= cutoff));
           if (inside == isInside) {
@@ -462,10 +471,12 @@
     }
     if (!isJvxl)
       surfaceData += " " + dataCount + "\n";
-    if (!isMapData)
-      currentMesh.surfaceData = surfaceData;
+    if (!isMapData) {
+      currentMesh.surfaceData = (thePlane == null ? surfaceData : "");
+      currentMesh.jvxlPlane = thePlane;
+    }
     System.out.println("Successfully read " + nPointsX + " x " + nPointsY
-        + " x " + nPointsZ + " data points");
+        + " x " + nPointsZ + " data points; " + edgeCount + " edges");
   }
 
   float calcVoxelPlaneDistance(int x, int y, int z) {
@@ -493,9 +504,21 @@
     if (showMsg)
       System.out.println("reading jvxl data set: " + line);
     jvxlCutoff = parseFloat(line);
-    nStructureData = parseInt(line, ichNextParse); //nStructure
-    nEdgeData = parseInt(line, ichNextParse); //nEdgeData
-    nColorData = parseInt(line, ichNextParse);
+    nStructureData = parseInt(); //nStructure
+    nEdgeData = parseInt(); //nEdgeData
+    nColorData = parseInt();
+    if (nStructureData < 0) {
+      nEdgeData = -1;
+      try {
+        thePlane = new Point4f(parseFloat(), parseFloat(), parseFloat(),
+            parseFloat());
+      } catch (Exception e) {
+        System.out
+            .println("Error reading 4 floats for PLANE definition -- setting 
to 0 0 1 0  (z=0)");
+        thePlane = new Point4f(0, 0, 1, 0);
+      }
+      System.out.println("plane read: " + thePlane);
+    }
     iHaveColorData = (nColorData > 0);
   }
 
@@ -505,8 +528,10 @@
 
   float getNextVoxelValue() throws Exception {
     if (isJvxl) {
+      if (nStructureData <= 0)
+        return 0f; //unnecessary -- probably a plane
       if (nThisValue == 0) {
-        nThisValue = parseInt(line, ichNextParse);
+        nThisValue = parseInt();
         if (nThisValue == Integer.MIN_VALUE) {
           line = br.readLine();
           if (line == null
@@ -527,7 +552,7 @@
       --nThisValue;
       return (thisInside ? 1f : 0f);
     }
-    float voxelValue = parseFloat(line, ichNextParse);
+    float voxelValue = parseFloat();
     if (Float.isNaN(voxelValue)) {
       line = br.readLine();
       if (line == null || Float.isNaN(voxelValue = parseFloat(line))) {
@@ -538,40 +563,42 @@
         line = "0 0 0 0 0 0 0 0 0 0";
         //throw new NullPointerException();
       }
-      if (ntest++ < 3) {
-        System.out.println("READING " + nBytes + " " + voxelValue + " " + 
line);
-      }
+      //if (ntest++ < 3) {
+      //System.out.println("READING " + nBytes + " " + voxelValue + " " + 
line);
+      // }
       nBytes += line.length() + 1;
     }
     return voxelValue;
   }
 
-  int ntest = 100;
+  //int ntest = 100;
 
   void skipData(int n, int nPoints) throws Exception {
-    ntest = 100;
-    if (n == 0)
+    //ntest = 100;
+    if (n <= 0)
       return;
     System.out.println("skipping " + n + " data sets, " + nPoints
         + " points each");
-    for (int i = 0; i < n; i++) {
-      if (isJvxl)
+    for (int i = 0; i < n; i++)
+      if (isJvxl) {
         readJvxlDefinitionLine(false);
-      skipData(nPoints, true);
-      if (isJvxl) {
-        skipData(nEdgeData, false);
+        if (nStructureData > 0)
+          skipData(nPoints, true);
+        if (nEdgeData > 0)
+          skipData(nEdgeData, false);
         if (iHaveColorData)
           skipData(nColorData, false);
+      } else {
+        skipData(nPoints, true);
       }
-    }
   }
 
   void skipData(int nPoints, boolean isInt) throws Exception {
     int iV = 0;
     while (iV < nPoints) {
       line = br.readLine();
-      if (iV < 1000 || nPoints - iV < 1000)
-        System.out.println(iV + " skip " + nPoints + " " + line);
+      //if (iV < 1000 || nPoints - iV < 1000)
+      //System.out.println(iV + " skip " + nPoints + " " + line);
       iV += (isInt ? countData(line) : line.length());
     }
   }
@@ -614,23 +641,19 @@
   final int[] surfacePointIndexes = new int[12];
 
   int voxelCountX, voxelCountY, voxelCountZ;
+  float minMappedValue;
+  float maxMappedValue;
 
-  void constructTessellatedSurface() {
+  void generateSurfaceData() {
     voxelCountX = voxelData.length - 1;
     voxelCountY = voxelData[0].length - 1;
     voxelCountZ = voxelData[0][0].length - 1;
     strFractionTemp = "";
+    fractionPtr = 0;
     int[][] isoPointIndexes = new int[voxelCountY * voxelCountZ][12];
     for (int i = voxelCountY * voxelCountZ; --i >= 0;)
       isoPointIndexes[i] = new int[12];
-
-    /*
-     * for (int x = 0; x < voxelCountX; ++x) for (int y = 0; y < voxelCountY;
-     * ++y) for (int z = 0; z < voxelCountZ; ++z) System.out.println("" + x +
-     * "," + y + "," + z + " = " + voxelData[x][y][z]);
-     */
     try {
-
       int insideCount = 0, outsideCount = 0, surfaceCount = 0;
       for (int x = voxelCountX; --x >= 0;) {
         for (int y = voxelCountY; --y >= 0;) {
@@ -645,13 +668,6 @@
                   || (cutoff <= 0 && vertexValue <= cutoff))
                 insideMask |= 1 << i;
             }
-
-            /*
-             * for (int i = 0; i < 8; ++i ) System.out.println("vertexValues[" 
+ i +
-             * "]=" + vertexValues[i]); System.out.println("insideMask=" +
-             * Integer.toHexString(insideMask));
-             */
-
             if (insideMask == 0) {
               ++outsideCount;
               continue;
@@ -665,7 +681,6 @@
             int[] voxelPointIndexes = propogateNeighborPointIndexes(x, y, z,
                 isoPointIndexes);
             processOneVoxel(insideMask, cutoff, voxelPointIndexes, x, y, z);
-
           }
         }
       }
@@ -673,12 +688,12 @@
         fractionData += "\n";
         currentMesh.nBytes = nBytes;
       }
+      currentMesh.jvxlFileHeader = jvxlFileHeader;
+      currentMesh.cutoff = (isJvxl ? jvxlCutoff : cutoff);
+      currentMesh.colorData = "";
       currentMesh.edgeData = fractionData;
-      currentMesh.jvxlFileHeader = jvxlFileHeader;
       fractionData = "";
       strFractionTemp = "";
-      currentMesh.cutoff = (isJvxl ? jvxlCutoff : cutoff);
-      currentMesh.colorData = "";
       System.out.println("volumetric=" + voxelCountX + "," + voxelCountY + ","
           + voxelCountZ + "," + " total="
           + (voxelCountX * voxelCountY * voxelCountZ) + "\n" + " insideCount="
@@ -686,6 +701,7 @@
           + surfaceCount + " total="
           + (insideCount + outsideCount + surfaceCount));
       if (iHaveColorData) {
+        fractionPtr = 0;
         setJvxlColixes(currentMesh, "roygb");
         currentMesh.colorData = fractionData;
       }
@@ -693,24 +709,8 @@
       e.printStackTrace();
       throw new NullPointerException();
     }
-
   }
 
-  String getJvxlFile(Mesh mesh, String msg) {
-    String data = mesh.jvxlFileHeader;
-    data += "# " + msg + "\n" + mesh.cutoff + " " + mesh.surfaceData.length()
-        + " " + (mesh.edgeData.length() - 1) + " "
-        + (mesh.colorData.length() - 1);
-    if (!isJvxl)
-      data += " compressionRatio="
-          + (mesh.nBytes * 1f / (mesh.surfaceData.length()
-              + mesh.edgeData.length() + mesh.colorData.length()));
-    data += "\n" + mesh.surfaceData + mesh.edgeData + mesh.colorData;
-    if (msg != null)
-      data += "#-------end of jvxl file " + msg + " data-------\n";
-    return data;
-  }
-
   final int[] nullNeighbor = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 
};
 
   int[] propogateNeighborPointIndexes(int x, int y, int z,
@@ -784,17 +784,18 @@
       float valueA = vertexValues[vertexA];
       float valueB = vertexValues[vertexB];
       calcVertexPoints(vertexA, vertexB);
-      addEdgePoint(pointA);
-      addEdgePoint(pointB);
-      int assocVertex = calcSurfacePoint(cutoff, valueA, valueB,
+      addEdgeInfo(x, y, z, vertexA, vertexB);
+      float fraction = calcSurfacePoint(cutoff, valueA, valueB,
           surfacePoints[iEdge]);
+      int assocVertex = (fraction < assocCutoff ? -1
+          : fraction > 1 - assocCutoff ? 1 : 0);
       String sKey = (assocVertex == 0 ? "" : calcDataKey(x, y, z,
           assocVertex < 0 ? vertexA : vertexB));
       voxelPointIndexes[iEdge] = addVertexCopy(surfacePoints[iEdge],
           (assocVertex != 0), sKey);
       if (addGridPoints) {
-        addVertexCopy(pointA, false, "");
-        addVertexCopy(pointB, false, "");
+        addVertexCopy(valueA < valueB ? pointA : pointB, false, "");
+        addVertexCopy(valueA < valueB ? pointB : pointA, false, "");
       }
     }
 
@@ -811,19 +812,25 @@
     return (x + offset.x) + "_" + (y + offset.y) + "_" + (z + offset.z);
   }
 
-  char edgeFractionBase;
+  int edgeFractionBase;
   float edgeFractionRange;
-  char colorFractionBase;
+  int colorFractionBase;
   float colorFractionRange;
   int fractionPtr;
+  int edgePtr;
+  Point3i[] edgesA;
+  Point3i[] edgesB;
+
   String strFractionTemp = "";
   String fractionData = "";
 
-  float getNextFraction(char base, float range) throws Exception {
+  float getNextFraction(int base, float range, float fracOffset)
+      throws Exception {
     if (strFractionTemp == null)
       return 0;
     if (fractionPtr >= strFractionTemp.length()) {
       strFractionTemp = br.readLine();
+      System.out.println(strFractionTemp);
       if (strFractionTemp == null) {
         if (!endOfData)
           System.out
@@ -832,26 +839,24 @@
         endOfData = true;
         strFractionTemp = "" + base;
         //throw new NullPointerException();
+      } else {
+        strFractionTemp = uncompressString(strFractionTemp);
       }
       fractionData += strFractionTemp + "\n";
+      System.out.println(fractionData);
       fractionPtr = 0;
     }
-    int ich = (int) strFractionTemp.charAt(fractionPtr++);
-    if (ich < base)
-      ich = 92; // ! --> \
-    float fraction = (ich - base + 0.5f) / range;
-    if (logMessages)
-      System.out.println(fraction + " <-- " + ich + " " + (char) ich);
-    return fraction;
+    return fractionFromCharacter((int) strFractionTemp.charAt(fractionPtr++),
+        base, range, fracOffset);
   }
 
   final static float assocCutoff = 0.3f;
 
-  int calcSurfacePoint(float cutoff, float valueA, float valueB,
-                       Point3f surfacePoint) throws Exception {
+  float calcSurfacePoint(float cutoff, float valueA, float valueB,
+                         Point3f surfacePoint) throws Exception {
     float fraction;
-    if (isJvxl) {
-      fraction = getNextFraction(edgeFractionBase, edgeFractionRange);
+    if (isJvxl && nEdgeData > 0) {
+      fraction = getNextFraction(edgeFractionBase, edgeFractionRange, 0.5f);
     } else {
       float diff = valueB - valueA;
       fraction = (cutoff - valueA) / diff;
@@ -860,53 +865,76 @@
             + " cutoff=" + cutoff + " A:" + valueA + " B:" + valueB);
         fraction = 0;
       }
-      if (!isJvxl) {
-        int ich = (int) (fraction * edgeFractionRange + edgeFractionBase);
-        if (ich == 92)
-          ich = 33; // \ --> !
-        if (logMessages)
-          System.out.println(fraction + " --> " + ich + " " + (char) ich);
-        fractionData += (char) (ich);
-      }
+      if (!isJvxl)
+        fractionData += fractionAsCharacter(fraction, edgeFractionBase,
+            edgeFractionRange);
     }
     edgeVector.sub(pointB, pointA);
     surfacePoint.scaleAdd(fraction, edgeVector, pointA);
-    return (fraction < assocCutoff ? -1 : fraction > 1 - assocCutoff ? 1 : 0);
+    return fraction;
   }
 
+  float fractionFromCharacter(int ich, int base, float range, float 
fracOffset) {
+    if (ich < base)
+      ich = 92; // ! --> \
+    float fraction = (ich - base + fracOffset) / range;
+    if (fraction < 0f)
+      fraction = 0f;
+    if (fraction >= 1f)
+      fraction = 0.999999f;
+    if (logMessages)
+      System.out.println("ffc: " + fraction + " <-- " + ich + " " + (char) 
ich);
+    return fraction;
+  }
+
+  char valueAsCharacter(float value, float min, float max, int base, float 
range) {
+    float fraction = (min == max ? 0.5f : (value - min) / (max - min));
+    return fractionAsCharacter(fraction, base, range);
+  }
+
+  char fractionAsCharacter(float fraction, int base, float range) {
+    if (fraction > 0.9999f)
+      fraction = 0.9999f;
+    int ich = (int) (fraction * range + base);
+    if (ich < base)
+      ich = base;
+    if (ich == 92)
+      ich = 33; // \ --> !
+    if (logMessages)
+      System.out.println("fac: " + fraction + " --> " + ich + " " + (char) 
ich);
+    return (char) ich;
+  }
+
   final Point3f voxelOrigin = new Point3f();
   final Point3f voxelT = new Point3f();
   final Point3f pointA = new Point3f();
   final Point3f pointB = new Point3f();
-  // edgeVector should be a table lookup based upon edge number
-  // vectors should be derived from the volumetric vectors in the file
   final Vector3f edgeVector = new Vector3f();
 
   void calcVertexPoints(int vertexA, int vertexB) {
     pointA.add(voxelOrigin, voxelVertexVectors[vertexA]);
     pointB.add(voxelOrigin, voxelVertexVectors[vertexB]);
-    /*
-     System.out.println("calcVertexPoints(" + vertexA + "," + vertexB + ")\n" +
-     " pointA=" + pointA +
-     " pointB=" + pointB);
-     */
   }
 
   void calcVoxelOrigin(int x, int y, int z) {
     voxelOrigin.scaleAdd(x, volumetricVectors[0], volumetricOrigin);
     voxelOrigin.scaleAdd(y, volumetricVectors[1], voxelOrigin);
     voxelOrigin.scaleAdd(z, volumetricVectors[2], voxelOrigin);
-    /*
-     System.out.println("voxelOrigin=" + voxelOrigin);
-     */
   }
 
-  void addEdgePoint(Point3f point) {
-    if (edgePoints == null)
-      edgePoints = new Point3f[256];
-    else if (edgePointCount == edgePoints.length)
-      edgePoints = (Point3f[]) Util.doubleLength(edgePoints);
-    edgePoints[edgePointCount++] = new Point3f(point);
+  void addEdgeInfo(int x, int y, int z, int vertexA, int vertexB) {
+    if (edgeInfo == null)
+      edgeInfo = new int[256][];
+    else if (edgeCount == edgeInfo.length)
+      edgeInfo = (int[][]) Util.doubleLength(edgeInfo);
+    int i = edgeCount++;
+    edgeInfo[i] = new int[6];
+    edgeInfo[i][0] = x + cubeVertexOffsets[vertexA].x;
+    edgeInfo[i][1] = y + cubeVertexOffsets[vertexA].y;
+    edgeInfo[i][2] = z + cubeVertexOffsets[vertexA].z;
+    edgeInfo[i][3] = x + cubeVertexOffsets[vertexB].x;
+    edgeInfo[i][4] = y + cubeVertexOffsets[vertexB].y;
+    edgeInfo[i][5] = z + cubeVertexOffsets[vertexB].z;
   }
 
   final static Point3i[] cubeVertexOffsets = { new Point3i(0, 0, 0),
@@ -1135,9 +1163,183 @@
       { 1, 3, 8, 9, 1, 8 }, { 0, 9, 1 }, { 0, 3, 8 }, null };
 
   ////////////////////////////////////////////////////////////////
-  // color scale stuff
+  // JVXL colors and normalization
   ////////////////////////////////////////////////////////////////
 
+  void setJvxlColixes(Mesh mesh, String scaleName) throws Exception {
+    int vertexCount = mesh.vertexCount;
+    short[] colixes = mesh.vertexColixes;
+    System.out.println("setting colors: minRange=" + minRange + " maxRange="
+        + maxRange);
+    fractionData = "";
+    fractionPtr = 0;
+    if (colixes == null)
+      mesh.vertexColixes = colixes = new short[vertexCount];
+    for (int i = 0; i < vertexCount; i++) {
+      float fraction = getNextFraction(colorFractionBase, colorFractionRange,
+          0.5f);
+      colixes[i] = viewer.getColixFromPalette(fraction, 0f, 1f, scaleName);
+
+      //System.out.println("setJvxlColixes " + fraction + " "  
+      //  +" "+viewer.colorManager.quantize(fraction,0f, 
1f,(int)colorFractionRange));
+      if (mesh.hasGridPoints) {
+        colixes[++i] = viewer.getColixFromPalette(0.2f, 0f, 1f, scaleName);
+        colixes[++i] = viewer.getColixFromPalette(0.8f, 0f, 1f, scaleName);
+      }
+    }
+  }
+
+  void initializeMesh(boolean use2Sided) {
+    int vertexCount = currentMesh.vertexCount;
+    Vector3f[] vectorSums = new Vector3f[vertexCount];
+
+    /* 
+     * OK, so if there is an associated grid point (because the 
+     * point is so close to one), we now declare that associated
+     * point to be used for the vectorSum instead of a new, 
+     * independent one for the point itself.
+     *  
+     *  Bob Hanson, 05/2006
+     *  
+     *  2-sided normixes don't seem to be necessary 
+     *  
+     */
+
+    for (int i = vertexCount; --i >= 0;) {
+      vectorSums[i] = (assocGridPointMap.containsKey("" + i) ? (Vector3f) 
assocGridPointNormals
+          .get((String) assocGridPointMap.get("" + i))
+          : new Vector3f());
+    }
+    currentMesh.sumVertexNormals(vectorSums);
+    short[] norm = currentMesh.normixes = new short[vertexCount];
+    if (use2Sided)
+      for (int i = vertexCount; --i >= 0;)
+        norm[i] = g3d.get2SidedNormix(vectorSums[i]);
+    else
+      for (int i = vertexCount; --i >= 0;)
+        norm[i] = g3d.getNormix(vectorSums[i]);
+  }
+
+  Hashtable assocGridPointMap;
+  Hashtable assocGridPointNormals;
+
+  int addVertexCopy(Point3f vertex, boolean iHaveAssociation, String sKey) {
+    int vPt = currentMesh.addVertexCopy(vertex);
+    if (vPt == 0) {
+      assocGridPointMap = new Hashtable();
+      assocGridPointNormals = new Hashtable();
+    }
+    if (associateNormals && iHaveAssociation) {
+      assocGridPointMap.put("" + vPt, sKey);
+      if (!assocGridPointNormals.containsKey(sKey))
+        assocGridPointNormals.put(sKey, new Vector3f(0, 0, 0));
+    }
+    return vPt;
+  }
+
+  ////////// JVXL FILE WRITING ////////////
+
+  String getJvxlFile(Mesh mesh, String msg) {
+    String data = mesh.jvxlFileHeader;
+    data += "# " + msg + "\n" + mesh.cutoff + " ";
+    String compressedData = "";
+    if (thePlane == null) {
+      compressedData = mesh.edgeData + mesh.colorData;
+      data += mesh.surfaceData.length() + " " + (mesh.edgeData.length() - 1)
+          + " " + (mesh.colorData.length() - 1);
+    } else {
+      data += "-1 -1 " + (mesh.colorData.length() - 1) + " " + thePlane.x + " "
+          + thePlane.y + " " + thePlane.z + " " + thePlane.w + " PLANE "
+          + thePlane;
+      compressedData = compressString(mesh.colorData);
+    }
+    if (!isJvxl)
+      data += " compressionRatio="
+          + (int) (mesh.nBytes * 1f / (mesh.surfaceData.length() + 
compressedData
+              .length())) + ":1";
+    data += "\n" + (thePlane == null ? mesh.surfaceData : "") + compressedData;
+    if (msg != null)
+      data += "#-------end of jvxl file " + msg + " data-------\n";
+    return data;
+  }
+
+  String compressString(String data) {
+    /* just a simple compression, but allows 2000-6000:1 CUBE:JVXL for planes!
+     * 
+     *   "X~nnn " means "nnn copies of character X" 
+     *   
+     *   ########## becomes "#~10 " 
+     *   ~ becomes "~~" 
+     *
+     */
+    if (logCompression)
+      System.out.println(data.length() + " compressing\n" + data);
+    String dataOut = "";
+    String dataBuffer = "";
+    char chLast = '\0';
+    data += '\0';
+    int nLast = 0;
+    for (int i = 0; i < data.length(); i++) {
+      char ch = data.charAt(i);
+      if (ch == chLast) {
+        ++nLast;
+        dataBuffer += ch;
+        if (ch != '~')
+          ch = '\0';
+      } else if (nLast > 0) {
+        dataOut += (nLast < 4 || chLast == '~' || chLast == ' '
+            || chLast == '\t' ? dataBuffer : "~" + nLast + " ");
+        dataBuffer = "";
+        nLast = 0;
+      }
+      if (ch != '\0') {
+        dataOut += ch;
+        chLast = ch;
+      }
+    }
+    if (logCompression) {
+      System.out.println(dataOut.length() + "\n" + dataOut);
+      data = uncompressString(dataOut);
+      System.out.println(data.length() + " uncompressing\n" + data);
+    }
+    return dataOut;
+  }
+
+  String uncompressString(String data) {
+    if (data.indexOf("~") < 0)
+      return data;
+    if (logCompression)
+      System.out.println(data.length() + " uncompressing\n" + data);
+    String dataOut = "";
+    char chLast = '\0';
+    for (int i = 0; i < data.length(); i++) {
+      char ch = data.charAt(i);
+      if (ch == '~') {
+        int nChar = parseInt(data, ++i);
+        if (nChar == Integer.MIN_VALUE) {
+          if (chLast == '~') {
+            dataOut += '~';
+            while ((ch = data.charAt(++i)) == '~')
+              dataOut += '~';
+          } else {
+            System.out.println("Error uncompressing string "
+                + data.substring(0, i) + "?");
+          }
+        } else {
+          for (int c = 0; c < nChar; c++)
+            dataOut += chLast;
+          i = ichNextParse;
+        }
+      } else {
+        dataOut += ch;
+        chLast = ch;
+      }
+    }
+    if (logCompression)
+      System.out.println(dataOut.length() + "\n" + dataOut);
+    return dataOut;
+  }
+
   void applyColorScale(float min, float max, String scaleName) {
     if (currentMesh != null)
       applyColorScale(currentMesh, min, max, scaleName);
@@ -1171,23 +1373,6 @@
     return max;
   }
 
-  void setJvxlColixes(Mesh mesh, String scaleName) throws Exception {
-    int vertexCount = mesh.vertexCount;
-    short[] colixes = mesh.vertexColixes;
-    strFractionTemp = "";
-    fractionData = "";
-    if (colixes == null)
-      mesh.vertexColixes = colixes = new short[vertexCount];
-    for (int i = 0; i < vertexCount; i++) {
-      float fraction = getNextFraction(colorFractionBase, colorFractionRange);
-      colixes[i] = viewer.getColixFromPalette(fraction, 0f, 1f, scaleName);
-      if (addGridPoints) {
-        colixes[++i] = viewer.getColixFromPalette(0.2f, 0f, 1f, scaleName);
-        colixes[++i] = viewer.getColixFromPalette(0.8f, 0f, 1f, scaleName);
-      }
-    }
-  }
-
   void applyColorScale(Mesh mesh, float min, float max, String scaleName) {
     int vertexCount = mesh.vertexCount;
     Point3f[] vertexes = mesh.vertices;
@@ -1204,9 +1389,12 @@
       if (value >= max) {
         value = min + diff * 0.9999f;
       }
-      int ich = (int) ((value - min) / diff * colorFractionRange + 
colorFractionBase);
+      float fraction = (value - min) / diff;
+      int ich = colorFractionBase + (int) (fraction * colorFractionRange);
       list += (char) ich;
       colixes[i] = viewer.getColixFromPalette(value, min, max, scaleName);
+      //System.out.println("applycolor " + fraction + " " + 
(((int)ich)-colorFractionBase) 
+      //  +" 
"+viewer.colorManager.quantize(value,min,max,(int)colorFractionRange));
     }
     mesh.colorData = list + "\n";
   }
@@ -1308,53 +1496,6 @@
       delta = 0.5f;
     }
     return valueDown + delta * valueDelta;
-  }
 
-  void initializeMesh(boolean use2Sided) {
-    int vertexCount = currentMesh.vertexCount;
-    Vector3f[] vectorSums = new Vector3f[vertexCount];
-
-    /* 
-     * OK, so if there is an associated grid point (because the 
-     * point is so close to one), we now declare that associated
-     * point to be used for the vectorSum instead of a new, 
-     * independent one for the point itself.
-     *  
-     *  Bob Hanson, 05/2006
-     *  
-     *  2-sided normixes don't seem to be necessary 
-     *  
-     */
-
-    for (int i = vertexCount; --i >= 0;) {
-      vectorSums[i] = (assocGridPointMap.containsKey("" + i) ? (Vector3f) 
assocGridPointNormals
-          .get((String) assocGridPointMap.get("" + i))
-          : new Vector3f());
-    }
-    currentMesh.sumVertexNormals(vectorSums);
-    short[] norm = currentMesh.normixes = new short[vertexCount];
-    if (use2Sided)
-      for (int i = vertexCount; --i >= 0;)
-        norm[i] = g3d.get2SidedNormix(vectorSums[i]);
-    else
-      for (int i = vertexCount; --i >= 0;)
-        norm[i] = g3d.getNormix(vectorSums[i]);
   }
-
-  Hashtable assocGridPointMap;
-  Hashtable assocGridPointNormals;
-
-  int addVertexCopy(Point3f vertex, boolean iHaveAssociation, String sKey) {
-    int vPt = currentMesh.addVertexCopy(vertex);
-    if (vPt == 0) {
-      assocGridPointMap = new Hashtable();
-      assocGridPointNormals = new Hashtable();
-    }
-    if (associateNormals && iHaveAssociation) {
-      assocGridPointMap.put("" + vPt, sKey);
-      if (!assocGridPointNormals.containsKey(sKey))
-        assocGridPointNormals.put(sKey, new Vector3f(0, 0, 0));
-    }
-    return vPt;
-  }
 }

Modified: branches/bob200603/Jmol/src/org/jmol/viewer/MeshCollection.java
===================================================================
--- branches/bob200603/Jmol/src/org/jmol/viewer/MeshCollection.java     
2006-05-28 03:35:37 UTC (rev 5184)
+++ branches/bob200603/Jmol/src/org/jmol/viewer/MeshCollection.java     
2006-05-28 03:37:57 UTC (rev 5185)
@@ -36,11 +36,11 @@
   Mesh[] meshes = new Mesh[4];
   Mesh currentMesh;
   boolean isValid = false;
-
+ 
   void initShape() {
     colix = Graphics3D.ORANGE;
   }
-
+  
   void setProperty(String propertyName, Object value, BitSet bs) {
 
     /*
@@ -177,8 +177,13 @@
     currentMesh = meshes[meshCount++] = new Mesh(viewer, meshID, g3d, colix);
   }
 
+  String line;
   int ichNextParse;
   
+  float parseFloat() {
+    return parseFloat(line, ichNextParse);
+  }
+  
   float parseFloat(String str) {
     return parseFloatChecked(str, 0, str.length());
   }
@@ -260,6 +265,10 @@
     return value;
   }
   
+  int parseInt() {
+    return parseInt(line, ichNextParse);
+  }
+  
   int parseInt(String str) {
     return parseIntChecked(str, 0, str.length());
   }

Modified: branches/bob200603/Jmol/src/org/jmol/viewer/MeshRenderer.java
===================================================================
--- branches/bob200603/Jmol/src/org/jmol/viewer/MeshRenderer.java       
2006-05-28 03:35:37 UTC (rev 5184)
+++ branches/bob200603/Jmol/src/org/jmol/viewer/MeshRenderer.java       
2006-05-28 03:37:57 UTC (rev 5185)
@@ -38,7 +38,6 @@
     if (vertexCount == 0)
       return;
     Point3f[] vertices = mesh.vertices;
-
     Point3i[] screens = viewer.allocTempScreens(vertexCount);
 
     for (int i = vertexCount; --i >= 0;)
@@ -48,6 +47,8 @@
 
     if (mesh.showPoints)
       renderPoints(mesh, screens, vertexCount);
+    if (iShowNormals)
+      renderNormals(mesh, screens, vertexCount);
     if (mesh.drawTriangles)
       renderTriangles(mesh, screens, false);
     if (mesh.fillTriangles)
@@ -56,16 +57,26 @@
     viewer.freeTempScreens(screens);
   }
 
-  final Point3f ptTemp = new Point3f();
-  final Point3i ptTempi = new Point3i();
   void renderPoints(Mesh mesh, Point3i[] screens, int vertexCount) {
     short colix = mesh.colix;
     short[] vertexColixes = mesh.vertexColixes;
-    //System.out.println("mesh renderPoints: " + vertexCount);
-    for (int i = vertexCount; --i >= 0;) {
+    for (int i = vertexCount; --i >= 0;)
       g3d.fillSphereCentered(vertexColixes != null ? vertexColixes[i] : colix,
           4, screens[i]);
-      if (iShowNormals && (i % 3) == 0) { //investigate vertex normixes
+    if (mesh.hasGridPoints) {
+      for (int i = 1; i < vertexCount; i+=3)
+        g3d.fillCylinder(Graphics3D.GRAY, Graphics3D.ENDCAPS_SPHERICAL, 1,
+            screens[i], screens[i + 1]);      
+    }
+  }
+
+  
+  final Point3f ptTemp = new Point3f();
+  final Point3i ptTempi = new Point3i();
+  void renderNormals(Mesh mesh, Point3i[] screens, int vertexCount) {
+    //System.out.println("mesh renderPoints: " + vertexCount);
+    for (int i = vertexCount; --i >= 0;)
+      if ((i % 3) == 0) { //investigate vertex normixes
         ptTemp.set(mesh.vertices[i]);
         short n = mesh.normixes[i];
         if (n < 0)
@@ -78,9 +89,6 @@
         } catch (Exception e) {
         }
       }
-
-    }
-
   }
 
   void renderTriangles(Mesh mesh, Point3i[] screens, boolean fill) {


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



-------------------------------------------------------
All the advantages of Linux Managed Hosting--Without the Cost and Risk!
Fully trained technicians. The highest number of Red Hat certifications in
the hosting industry. Fanatical Support. Click to learn more
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642
_______________________________________________
Jmol-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jmol-commits

Reply via email to