Jmol developers. Whew! OK, that's about done, I hope. This message 
explains what I was up to this last week.

I've refactored the isosurface code into a set of packages all under 
org.jmol.jvxl:

+---org.jmol.jvxl
|   |
|   +---api
|   |       AtomDataServer.java
|   |       AtomIndexIterator.java
|   |       MeshDataServer.java
|   |       VertexDataServer.java
|   |      
|   +---calc
|   |       MarchingCubes.java
|   |       MarchingSquares.java
|   |      
|   +---data
|   |       AtomData.java
|   |       JvxlData.java
|   |       MeshData.java
|   |       VolumeData.java
|   |      
|   +---readers
|   |     SurfaceGenerator.java
|   |     Parameters.java
|   |     VoxelReader.java
|   |         VolumeDataReader.java
|   |             IsoFxyReader.java
|   |             IsoShapeReader.java
|   |             AtomDataReader.java
|   |                 IsoMepReader.java
|   |                 IsoMOReader.java
|   |                 IsoSolventReader.java
|   |                 IsoPlaneReader.java
|   |         VolumeFileReader.java
|   |             ApbsReader.java
|   |             CubeReader.java
|   |             JvxlReader.java
|   |      

This was quite a bit of work, and there is definitely good news and bad 
news.

The good news is that the entire surface creation functionality of Jmol 
is now isolated from the Viewer class. That of course means that if ever 
anyone wants to use this code in other contexts, it should be quite 
straightforward. There are four interfaces:

     AtomDataServer.java     (provides atom coordinates, radii, etc. -- 
Viewer)
     AtomIndexIterator.java  (provides a fast binary tree iterator for 
atoms -- Viewer)
     VertexDataServer.java   (returns vertex indices as they are created 
-- Isosurface)
     MeshDataServer.java     (access to storage for triangles data -- 
Isosurface)

Four public data structures are utilized:

     AtomData.java
     JvxlData.java
     MeshData.java
     VolumeData.java

These pretty much hold what you would expect them to. Mostly they are 
just pointers to data held elsewhere, but these classes also now contain 
several methods that are intrinsic to their data type. For example, 
VolumeData.voxelPtToXYZ(int x, int y, int z) provides a means of quickly 
finding out where in space a voxel is based on its integer "CUBE file" 
coordinates.

In addition, there is a special parameter class,

     Parameters.java

which stores ALL of the various parameters necessary for isosurface 
creation and rendering. The main function of the surface generator:

     SurfaceGenerator.java

is to set up these parameters, select the right voxel reader (see 
below), and then either run generateSurface() or mapColors().

To do an isosurface calculation we need voxel data. That comes from the 
readers. As you can see from the hierarchy, there are several types. 
Basically we have readers that read file data (APBS, CUBE, JVXL) and 
readers that either consume already-prepared data (VolumeDataReader) or 
create their own on the fly (IsoMepReader, IsoMOReader, 
IsoSurfaceReader, etc.). Some of these rely on an AtomDataServer to 
provide atom positions, atomic numbers, and radii. What's interesting, I 
think, is that this would not have to be Jmol. It could be any simple 
program that can deliver such data. Other readers, such as 
IsoShapeReader (for atomic orbitals, spheres, and ellipses) don't need 
any additional data. A reader can look as simple as this:

class IsoPlaneReader extends AtomDataReader {

  IsoPlaneReader(SurfaceGenerator sg) {
    super(sg);
    precalculateVoxelData = false;
  }

  protected void setup() {
    super.setup();
    doAddHydrogens = false;
    getAtoms(params.mep_marginAngstroms, false, false);
    setHeader("PLANE", params.thePlane.toString());
    setRangesAndAddAtoms(params.solvent_ptsPerAngstrom, 
params.solvent_gridMax, Math.min(myAtomCount, 100));
    params.cutoff = 0;
  }

  protected float getValue(int x, int y, int z) {   
    return  volumeData.calcVoxelPlaneDistance(x, y, z);
  }

}

So I think you can see that you could add a new "shape" pretty easily. 
Just define a getValue() method, provide a keyword for the isosurface 
command, and that's about it. In contrast, IsoSurfaceReader is by far 
the most involved. This class creates all the 
solvent/molecular/cavity/pocket/etc. surfaces you see in Jmol. I don't 
want to think about it!

The twin calculation engines

     MarchingCubes.java
     MarchingSquares.java

are entirely separated from the rest of the business by interfaces. 
Their constructors set up the calculation, and a single method does the 
rest. For example, a VoxelReader simply does this once the volume data 
have been read and parameters are set:

    marchingCubes = new MarchingCubes(this, volumeData,
        params.isContoured, contourType,
        params.cutoff, params.isCutoffAbsolute);

    edgeCount = marchingCubes.generateSurfaceData(isXLowToHigh);

That's it. Those two calls deliver a full set of vertices and triangles 
to the MeshDataServer (the Isosurface class). I think it's interesting 
that only four parameters are sent to the Marching Cubes class -- two to 
indicate that we are just using the Marching Cubes to set up a planar 
surface that will later be contoured by the Marching Squares algorithm, 
a third that is the cutoff all isosurfaces involve, and the last, 
whether that cutoff is an absolute value -- for example, when a 
CUBE-file based molecular orbital has two phases, positive and negative.

To generate a contoured plane, all we need (after the vertices are 
assigned by the Marching Cubes algorithm) is:

    marchingSquares = new MarchingSquares(this, volumeData, params.thePlane,
        params.nContours, params.thisContour);

    marchingSquares.setMinMax(params.valueMappedToRed, 
params.valueMappedToBlue);

    contourVertexCount = 
marchingSquares.generateContourData(jvxlDataIs2dContour);

Miguel pretty much wrote the MarchingCubes code from scratch. I added 
the Marching Squares. What that is for is the creation of contours in 
planes and f(x,y) curved surfaces. It basically does a 2D version of 
Marching Cubes. We use Marching Cubes in the 2D-surface contouring just 
to set up the vertexes on the surface that then provide the basis for 
"marching". It's kind of neat that this works. I'm have to say I'm 
really pleased how it turned out. If you ever need curved-surface 
contouring, look no further!

So, overall, it feels great that this is a well-defined separate entity 
now -- a real "package" -- a "product" of the Jmol Project that is 
basically independent of Jmol itself. I'm not aware of anything out 
there quite like it.

Now the bad news.

I'm TIRED!!! I feel like I took Jmol completely apart and put it back 
together again. Almost certainly I forgot a nut or a bolt in the 
processes. You will find them for me, I am certain. :) Just tonight I 
think I have Jmol back together in a way that others can test. So please 
do that. Let's call it 11.1.29 and see how it goes.

When you look at that list, it's probably not so surprising that the 
"old" Isosurface.java was 5800 lines and 230K of code. I'm happy to say 
that this is down to 600 lines and only 20K. But the bad news is that 
all that interfacing did cost some file size. The debug-free Jar files 
are now about 38K larger than they were before I started hacking (988K 
instead of 950K for the applet). I'm quite sensitive to that, but it's 
just the way it had to be. I trust people will feel that the benefit of 
well-organized code outweighs the compact efficiency of what we had.

Bob Hanson



-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Jmol-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jmol-developers

Reply via email to