Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jmol.jvxl.data.JvxlCoder Maven / Gradle / Ivy
Go to download
Jmol: an open-source Java viewer for chemical structures in 3D
/* $RCSfile$
* $Author: hansonr $
* $Date: 2007-03-30 11:40:16 -0500 (Fri, 30 Mar 2007) $
* $Revision: 7273 $
*
* Copyright (C) 2007 Miguel, Bob, Jmol Development
*
* Contact: [email protected]
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jmol.jvxl.data;
import javax.vecmath.Point3f;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Map;
import org.jmol.g3d.Graphics3D;
import org.jmol.util.BitSetUtil;
import org.jmol.util.Escape;
import org.jmol.util.Logger;
import org.jmol.util.Parser;
import org.jmol.util.TextFormat;
import org.jmol.util.XmlUtil;
public class JvxlCoder {
//TODO -- need to escapeXml for text data
final public static String JVXL_VERSION1 = "2.0";
final public static String JVXL_VERSION_XML = "2.2";
// 1.4 adds -nContours to indicate contourFromZero for MEP data mapped onto planes
// 2.0 adds vertex/triangle compression when no grid is present
// Jmol 11.7.25 -- recoded so that we do not create voxelData[nx][ny][nz] and instead
// simply create a BitSet of length nx * ny * nz. This saves memory hugely.
// 2.1 adds JvxlXmlReader
// 2.2 adds color density Jmol 12.0.15/12.1.13
public static String jvxlGetFile(VolumeData volumeData, JvxlData jvxlData,
String[] title) {
// for the simple writer
int[] counts = volumeData.getVoxelCounts();
jvxlData.nPointsX = counts[0];
jvxlData.nPointsY = counts[1];
jvxlData.nPointsZ = counts[2];
jvxlData.jvxlVolumeDataXml = volumeData.setVolumetricXml();
return jvxlGetFile(jvxlData, null, title, null, true, 1, null, null);
}
public static String jvxlGetFile(JvxlData jvxlData, MeshData meshData,
String[] title, String msg,
boolean includeHeader, int nSurfaces,
String state, String comment) {
return jvxlGetFileXml(jvxlData, meshData, title, msg, includeHeader, nSurfaces, state, comment);
// version1 decomissioned because of jvxlExcluded[] performing so well
// if (meshData != null || jvxlData == null || jvxlData.asXml
// || jvxlData.vContours != null || jvxlData.contourValues != null
// || jvxlData.jvxlExcluded[0] != null || jvxlData.jvxlExcluded[1] != null )
// return jvxlGetFileXml(jvxlData, meshData, title, msg, includeHeader, nSurfaces, state, comment);
//return jvxlGetFileVersion1(jvxlData, meshData, title, msg, includeHeader, nSurfaces, state, comment);
}
private static String jvxlGetFileXml(JvxlData jvxlData, MeshData meshData,
String[] title, String msg,
boolean includeHeader, int nSurfaces,
String state, String comment) {
StringBuffer data = new StringBuffer();
if ("TRAILERONLY".equals(msg)) {
XmlUtil.closeTag(data, "jvxlSurfaceSet");
XmlUtil.closeTag(data, "jvxl");
return data.toString();
}
boolean vertexDataOnly = (meshData != null);
boolean isHeaderOnly = ("HEADERONLY".equals(msg));
if (includeHeader) {
XmlUtil.openDocument(data);
XmlUtil.openTag(data, "jvxl", new String[] {
"version", JVXL_VERSION_XML,
"jmolVersion", jvxlData.version,
"xmlns", "http://jmol.org/jvxl_schema",
"xmlns:cml", "http://www.xml-cml.org/schema" });
if (jvxlData.jvxlFileTitle != null)
XmlUtil.appendCdata(data, "jvxlFileTitle", null, "\n" + jvxlData.jvxlFileTitle);
if (jvxlData.moleculeXml != null)
data.append(jvxlData.moleculeXml);
String volumeDataXml = (vertexDataOnly ? null : jvxlData.jvxlVolumeDataXml);
if (volumeDataXml == null)
volumeDataXml = (new VolumeData()).setVolumetricXml();
data.append(volumeDataXml);
XmlUtil.openTag(data,"jvxlSurfaceSet",
new String[] { "count", "" + (nSurfaces > 0 ? nSurfaces : 1) });
if (isHeaderOnly)
return data.toString();
}
StringBuffer sb;
String type = (vertexDataOnly ? "pmesh"
: jvxlData.jvxlPlane == null ? "isosurface" : "plane");
// TODO: contours mentioned here? when discrete?
if (jvxlData.jvxlColorData != null && jvxlData.jvxlColorData.length() > 0)
type = "mapped " + type;
XmlUtil.openTag(data, "jvxlSurface", new String[] { "type", type });
data.append(jvxlGetInfo(jvxlData, vertexDataOnly));
jvxlAppendCommandState(data, comment, state);
if (title != null || msg != null && msg.length() > 0) {
sb = new StringBuffer();
if (msg != null && msg.length() > 0)
sb.append(msg).append("\n");
if (title != null)
for (int i = 0; i < title.length; i++)
sb.append(title[i]).append('\n');
XmlUtil.appendCdata(data, "jvxlSurfaceTitle", null, sb.toString());
}
sb = new StringBuffer();
XmlUtil.openTag(sb, "jvxlSurfaceData", (vertexDataOnly || jvxlData.jvxlPlane == null ? null :
new String[] { "plane", Escape.escape(jvxlData.jvxlPlane) }));
if (vertexDataOnly) {
appendXmlVertexOnlyData(sb, jvxlData, meshData, true);
} else if (jvxlData.jvxlPlane == null) {
if (jvxlData.jvxlEdgeData == null)
return "";
appendXmlEdgeData(sb, jvxlData);
appendXmlColorData(sb, "jvxlColorData", jvxlData.jvxlColorData,
jvxlData.isJvxlPrecisionColor, jvxlData.valueMappedToRed,
jvxlData.valueMappedToBlue);
} else {
appendXmlColorData(sb, "jvxlColorData", jvxlData.jvxlColorData,
jvxlData.isJvxlPrecisionColor, jvxlData.valueMappedToRed,
jvxlData.valueMappedToBlue);
}
appendEncodedBitSetTag(sb, "jvxlInvalidatedVertexData", jvxlData.jvxlExcluded[1], -1, null);
if (jvxlData.excludedVertexCount > 0) {
appendEncodedBitSetTag(sb, "jvxlExcludedVertexData", jvxlData.jvxlExcluded[0], jvxlData.excludedVertexCount, null);
appendEncodedBitSetTag(sb, "jvxlExcludedPlaneData", jvxlData.jvxlExcluded[2], -1, null);
}
appendEncodedBitSetTag(sb, "jvxlExcludedTriangleData", jvxlData.jvxlExcluded[3], jvxlData.excludedTriangleCount, null);
XmlUtil.closeTag(sb, "jvxlSurfaceData");
int len = sb.length();
data.append(sb);
if (jvxlData.vContours != null && jvxlData.vContours.length > 0) {
jvxlEncodeContourData(jvxlData.vContours, data);
}
if (jvxlData.vertexColorMap != null) {
XmlUtil.openTag(data, "jvxlVertexColorData");
for (Map.Entry entry : jvxlData.vertexColorMap.entrySet())
appendEncodedBitSetTag(data, "jvxlColorMap", entry.getValue(), -1, new Object[] { "color", entry.getKey() });
jvxlData.vertexColorMap = null;
XmlUtil.closeTag(data, "jvxlVertexColorData");
}
XmlUtil.closeTag(data, "jvxlSurface");
if (includeHeader) {
XmlUtil.closeTag(data, "jvxlSurfaceSet");
XmlUtil.closeTag(data, "jvxl");
}
return jvxlSetCompressionRatio(data, jvxlData, len);
}
private static void appendEncodedBitSetTag(StringBuffer sb, String name, BitSet bs, int count, Object[] attribs) {
if (count < 0)
count = BitSetUtil.cardinalityOf(bs);
if (count == 0)
return;
StringBuffer sb1 = new StringBuffer("\n ");
jvxlEncodeBitSet(bs, -1, sb1);
XmlUtil.appendTag(sb, name, new Object[] {
attribs,
"bsEncoding", "base90+35",
"count", "" + count,
"len", "" + bs.length() },
jvxlCompressString(sb1.toString(), true));
}
private static String jvxlSetCompressionRatio(StringBuffer data,
JvxlData jvxlData, int len) {
String s = data.toString();
int r = (int) (jvxlData.nBytes > 0 ? ((float) jvxlData.nBytes) / len
: ((float) (jvxlData.nPointsX
* jvxlData.nPointsY * jvxlData.nPointsZ * 13)) / len);
return TextFormat.simpleReplace(s, "\"not calculated\"", (r > 0 ? "\"" + r +":1\"": "\"?\""));
}
private static void appendXmlEdgeData(StringBuffer sb, JvxlData jvxlData) {
XmlUtil.appendTag(sb, "jvxlEdgeData", new String[] {
"count", "" + (jvxlData.jvxlEdgeData.length() - 1),
"encoding", "base90f1",
"bsEncoding", "base90+35c",
"isXLowToHigh", "" + jvxlData.isXLowToHigh,
"data", jvxlCompressString(jvxlData.jvxlEdgeData, true) }, "\n"
+ jvxlCompressString(jvxlData.jvxlSurfaceData, true));
}
private static void jvxlAppendCommandState(StringBuffer data, String cmd,
String state) {
if (cmd != null)
XmlUtil.appendCdata(data, "jvxlIsosurfaceCommand", null,
"\n" + (cmd.indexOf("#") < 0 ? cmd : cmd.substring(0, cmd.indexOf("#"))) + "\n");
if (state != null) {
if (state.indexOf("** XML ** ") >=0) {
state = TextFormat.split(state, "** XML **")[1].trim();
XmlUtil.appendTag(data, "jvxlIsosurfaceState", "\n" + state + "\n");
} else {
XmlUtil.appendCdata(data, "jvxlIsosurfaceState", null, "\n" + state);
}
}
}
private static void appendXmlColorData(StringBuffer sb, String key,
String data,
boolean isPrecisionColor,
float value1,
float value2) {
int n;
if (data == null || (n = data.length() - 1) < 0)
return;
if (isPrecisionColor)
n /= 2;
XmlUtil.appendTag(sb, key, new String[] {
"count", "" + n,
"encoding", "base90f" + (isPrecisionColor ? "2" : "1"),
"min", "" + value1,
"max", "" + value2,
"data", jvxlCompressString(data, true) }, null);
}
public static String jvxlGetInfo(JvxlData jvxlData) {
return jvxlGetInfo(jvxlData, jvxlData.vertexDataOnly);
}
public static String jvxlGetInfo(JvxlData jvxlData, boolean vertexDataOnly) {
if (jvxlData.jvxlSurfaceData == null)
return "";
List attribs = new ArrayList();
int nSurfaceInts = jvxlData.nSurfaceInts;// jvxlData.jvxlSurfaceData.length();
int bytesUncompressedEdgeData = (vertexDataOnly ? 0
: jvxlData.jvxlEdgeData.length() - 1);
int nColorData = (jvxlData.jvxlColorData == null ? -1 : (jvxlData.jvxlColorData.length() - 1));
if (!vertexDataOnly) {
// informational only:
addAttrib(attribs, "\n cutoff", "" + jvxlData.cutoff);
addAttrib(attribs, "\n isCutoffAbsolute", "" + jvxlData.isCutoffAbsolute);
addAttrib(attribs, "\n pointsPerAngstrom", "" + jvxlData.pointsPerAngstrom);
int n = jvxlData.jvxlSurfaceData.length()
+ bytesUncompressedEdgeData + nColorData + 1;
if (n > 0)
addAttrib(attribs, "\n nBytesData", "" + n);
//TODO: these should only be for information purposes, but are not:
addAttrib(attribs, "\n isXLowToHigh", "" + jvxlData.isXLowToHigh);
if (jvxlData.jvxlPlane == null) {
addAttrib(attribs, "\n nSurfaceInts", "" + nSurfaceInts);
addAttrib(attribs, "\n nBytesUncompressedEdgeData", "" + bytesUncompressedEdgeData);
}
if (nColorData > 0)
addAttrib(attribs, "\n nBytesUncompressedColorData", "" + nColorData); // TODO: later?
}
jvxlData.excludedVertexCount = BitSetUtil.cardinalityOf(jvxlData.jvxlExcluded[0]);
jvxlData.excludedTriangleCount = BitSetUtil.cardinalityOf(jvxlData.jvxlExcluded[3]);
if (jvxlData.excludedVertexCount > 0)
addAttrib(attribs, "\n nExcludedVertexes", "" + jvxlData.excludedVertexCount);
if (jvxlData.excludedTriangleCount > 0)
addAttrib(attribs, "\n nExcludedTriangles", "" + jvxlData.excludedTriangleCount);
int n = BitSetUtil.cardinalityOf(jvxlData.jvxlExcluded[1]);
if (n > 0)
addAttrib(attribs, "\n nInvalidatedVertexes", "" + n);
if (jvxlData.slabInfo != null)
addAttrib(attribs, "\n slabInfo", jvxlData.slabInfo);
//next is for information only -- will be superceded by "encoding" attribute of jvxlColorData
if (jvxlData.isJvxlPrecisionColor)
addAttrib(attribs, "\n precisionColor", "true");
if (jvxlData.colorDensity)
addAttrib(attribs, "\n colorDensity", "true");
else if (jvxlData.diameter != 0)
addAttrib(attribs, "\n diameter", "" + jvxlData.diameter);
if (!jvxlData.allowVolumeRender)
addAttrib(attribs, "\n allowVolumeRender", "false");
if (jvxlData.jvxlPlane == null || vertexDataOnly) {
if (jvxlData.isContoured) {
addAttrib(attribs, "\n contoured", "true");
addAttrib(attribs, "\n colorMapped", "true");
} else if (jvxlData.isBicolorMap) {
addAttrib(attribs, "\n bicolorMap", "true");
addAttrib(attribs, "\n colorNegative", Graphics3D.getHexCode(jvxlData.minColorIndex));
addAttrib(attribs, "\n colorPositive", Graphics3D.getHexCode(jvxlData.maxColorIndex));
} else if (nColorData > 0) {
addAttrib(attribs, "\n colorMapped", "true");
}
if (jvxlData.vContours != null && jvxlData.vContours.length > 0)
addAttrib(attribs, "\n nContourData", "" + jvxlData.vContours.length);
} else {
if (jvxlData.scale3d != 0)
addAttrib(attribs, "\n scale3d", "" + jvxlData.scale3d);
if (nColorData > 0)
addAttrib(attribs, "\n colorMapped", "true");
addAttrib(attribs, "\n plane", Escape.escape(jvxlData.jvxlPlane));
}
if (jvxlData.color != null && jvxlData.color.indexOf("null") < 0)
addAttrib(attribs, "\n color", jvxlData.color);
addAttrib(attribs, "\n translucency", "" + jvxlData.translucency);
if (jvxlData.meshColor != null)
addAttrib(attribs, "\n meshColor", jvxlData.meshColor);
if (jvxlData.colorScheme != null)
addAttrib(attribs, "\n colorScheme", jvxlData.colorScheme);
if (jvxlData.rendering != null)
addAttrib(attribs, "\n rendering", jvxlData.rendering);
if (jvxlData.thisSet >= 0)
addAttrib(attribs, "\n set", "" + (jvxlData.thisSet + 1));
if (jvxlData.slabValue != Integer.MIN_VALUE)
addAttrib(attribs, "\n slabValue", "" + jvxlData.slabValue);
if (jvxlData.isSlabbable)
addAttrib(attribs, "\n slabbable", "true");
if (jvxlData.nVertexColors > 0)
addAttrib(attribs, "\n nVertexColors", "" + jvxlData.nVertexColors);
float min = (jvxlData.mappedDataMin == Float.MAX_VALUE ? 0f
: jvxlData.mappedDataMin);
float blue = (jvxlData.isColorReversed ? jvxlData.valueMappedToRed : jvxlData.valueMappedToBlue);
float red = (jvxlData.isColorReversed ? jvxlData.valueMappedToBlue : jvxlData.valueMappedToRed);
if (jvxlData.jvxlColorData != null && jvxlData.jvxlColorData.length() > 0 && !jvxlData.isBicolorMap) {
addAttrib(attribs, "\n dataMinimum", "" + min);
addAttrib(attribs, "\n dataMaximum", "" + jvxlData.mappedDataMax);
addAttrib(attribs, "\n valueMappedToRed", "" + red);
addAttrib(attribs, "\n valueMappedToBlue", "" + blue);
}
if (jvxlData.isContoured) {
if (jvxlData.contourValues == null || jvxlData.contourColixes == null) {
if (jvxlData.vContours == null)
addAttrib(attribs, "\n nContours", "" + Math.abs(jvxlData.nContours));
} else {
if (jvxlData.jvxlPlane != null)
addAttrib(attribs, "\n contoured", "true");
addAttrib(attribs, "\n nContours", "" + jvxlData.contourValues.length);
addAttrib(attribs, "\n contourValues", Escape.escapeArray(jvxlData.contourValuesUsed == null ? jvxlData.contourValues : jvxlData.contourValuesUsed));
addAttrib(attribs, "\n contourColors", jvxlData.contourColors);
}
}
//TODO: confusing flag insideOut:
if (jvxlData.insideOut)
addAttrib(attribs, "\n insideOut", "true");
// rest is information only:
if (jvxlData.vertexDataOnly)
addAttrib(attribs, "\n note", "vertex/face data only");
else if (jvxlData.isXLowToHigh)
addAttrib(attribs, "\n note", "progressive JVXL+ -- X values read from low(0) to high("
+ (jvxlData.nPointsX - 1) + ")");
addAttrib(attribs, "\n xyzMin", Escape.escape(jvxlData.boundingBox[0]));
addAttrib(attribs, "\n xyzMax", Escape.escape(jvxlData.boundingBox[1]));
addAttrib(attribs, "\n approximateCompressionRatio", "not calculated");
addAttrib(attribs, "\n jmolVersion", jvxlData.version);
StringBuffer info = new StringBuffer();
XmlUtil.openTag(info, "jvxlSurfaceInfo", attribs.toArray());
XmlUtil.closeTag(info, "jvxlSurfaceInfo");
return info.toString();
}
private static void addAttrib(List attribs, String name, String value) {
attribs.add(new String[] { name, value });
}
public static final int CONTOUR_NPOLYGONS = 0;
public static final int CONTOUR_BITSET = 1;
public static final int CONTOUR_VALUE = 2;
public static final int CONTOUR_COLIX = 3;
public static final int CONTOUR_COLOR = 4;
public static final int CONTOUR_FDATA = 5;
public static final int CONTOUR_POINTS = 6; // must be last
/**
* contour data are appended to a string buffer in the form of a
*
* triangle bitset data
* triangle bitset data
* triangle bitset data
* ...
*
*
* One presumes an ordered set of triangles.
* The contour intersects these triangles along two edges or at two vertices.
* (see IsosurfaceMesh for details)
* Each contour is a Vector containing:
* 0 Integer number of polygons (length of BitSet)
* 1 BitSet of critical triangles
* 2 Float value
* 3 int[] [colorArgb]
* 4 StringBuffer containing encoded data for each segment:
* char type ('3', '6', '5') indicating which two edges
* of the triangle are connected:
* '3' 0x011 AB-BC
* '5' 0x101 AB-CA
* '6' 0x110 BC-CA
* char fraction along first edge (jvxlFractionToCharacter)
* char fraction along second edge (jvxlFractionToCharacter)
* 5- stream of pairs of points for rendering (created
*
*
* @param contours
* @param sb
*/
private static void jvxlEncodeContourData(List[] contours, StringBuffer sb) {
XmlUtil.openTag(sb, "jvxlContourData", new String[] { "count", "" + contours.length });
for (int i = 0; i < contours.length; i++) {
if (contours[i].size() < CONTOUR_POINTS) {
continue;
}
int nPolygons = ((Integer) contours[i].get(CONTOUR_NPOLYGONS)).intValue();
StringBuffer sb1 = new StringBuffer("\n");
BitSet bs = (BitSet) contours[i].get(CONTOUR_BITSET);
jvxlEncodeBitSet(bs, nPolygons, sb1);
XmlUtil.appendTag(sb, "jvxlContour", new String[] {
"index", "" + i,
"value", "" + contours[i].get(CONTOUR_VALUE),
"color", Escape.escapeColor(((int[]) contours[i]
.get(CONTOUR_COLOR))[0]),
"count", "" + bs.length(),
"encoding", "base90iff1",
"bsEncoding", "base90+35c",
"data", jvxlCompressString(contours[i].get(CONTOUR_FDATA).toString(), true) },
jvxlCompressString(sb1.toString(), true));
}
XmlUtil.closeTag(sb, "jvxlContourData");
}
/**
* Interpret fractional data in terms of actual vertex positions and
* create the elements of a Vector in Vector[] vContours starting at
* the CONTOUR_POINTS position.
*
* @param v
* @param polygonIndexes
* @param vertices
*/
public static void set3dContourVector(List v, int[][] polygonIndexes, Point3f[] vertices) {
// we must add points only after the MarchingCubes process has completed.
if (v.size() < CONTOUR_POINTS)
return;
StringBuffer fData = (StringBuffer) v.get(CONTOUR_FDATA);
BitSet bs = (BitSet) v.get(CONTOUR_BITSET);
//int nPolygons = ((Integer)v.get(CONTOUR_NPOLYGONS)).intValue();
int pt = 0;
int nBuf = fData.length();
int type = 0;
char c1 = ' ';
char c2 = ' ';
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
int[] vertexIndexes = polygonIndexes[i];
while (pt < nBuf && !Character.isDigit(c1 = fData.charAt(pt++))) {
// skip non-digit data
}
type = c1 - 48;
while (pt < nBuf && Character.isWhitespace(c1 = fData.charAt(pt++))) {
// skip whitespace
}
while (pt < nBuf && Character.isWhitespace(c2 = fData.charAt(pt++))) {
// skip whitespace
}
float f1 = jvxlFractionFromCharacter(c1, defaultEdgeFractionBase, defaultEdgeFractionRange, 0);
float f2 = jvxlFractionFromCharacter(c2, defaultEdgeFractionBase, defaultEdgeFractionRange, 0);
int i1, i2, i3, i4;
/*
* char type ('3', '6', '5') indicating which two edges
* of the triangle are connected:
* '3' 0x011 AB-BC
* '5' 0x101 AB-CA
* '6' 0x110 BC-CA
*/
if ((type & 1) == 0) { //BC-CA
i1 = vertexIndexes[1];
i2 = i3 = vertexIndexes[2];
i4 = vertexIndexes[0];
} else { //AB-BC or //AB-CA
i1 = vertexIndexes[0];
i2 = vertexIndexes[1];
if ((type & 2) != 0) {
i3 = i2;
i4 = vertexIndexes[2];
} else {
i3 = vertexIndexes[2];
i4 = i1;
}
}
v.add(getContourPoint(vertices, i1, i2, f1));
v.add(getContourPoint(vertices, i3, i4, f2));
}
}
private static Point3f getContourPoint(Point3f[] vertices, int i, int j, float f) {
Point3f pt = new Point3f();
pt.set(vertices[j]);
pt.sub(vertices[i]);
pt.scale(f);
pt.add(vertices[i]);
return pt;
}
/**
* appends an integer (3, 5, or 6) representing two sides of a triangle ABC --
* AB/BC(3), AB/CA(5), or BC/CA(6) -- along with two fractions along the edges
* for the intersection point base-90-encoded. This version is single precision.
*
* type f1 f2
* 3 AB BC
* 5 AB CA
* 6 BC CA
*
* @param type
* @param f1 -- character-encoded fraction
* @param f2 -- character-encoded fraction
* @param fData
*/
public static void appendContourTriangleIntersection(int type, float f1, float f2, StringBuffer fData) {
fData.append(type);
fData.append(jvxlFractionAsCharacter(f1));
fData.append(jvxlFractionAsCharacter(f2));
}
/**
*
* @param jvxlData
* @param vertexValues
*/
public static void jvxlCreateColorData(JvxlData jvxlData, float[] vertexValues) {
if (vertexValues == null) {
jvxlData.jvxlColorData = "";
return;
}
boolean writePrecisionColor = jvxlData.isJvxlPrecisionColor;
boolean doTruncate = jvxlData.isTruncated;
int colorFractionBase = jvxlData.colorFractionBase;
int colorFractionRange = jvxlData.colorFractionRange;
float valueBlue = jvxlData.valueMappedToBlue;
float valueRed = jvxlData.valueMappedToRed;
int vertexCount = (jvxlData.saveVertexCount > 0 ? jvxlData.saveVertexCount
: jvxlData.vertexCount);
if(vertexCount > vertexValues.length)
System.out.println("JVXLCODER ERROR");
float min = jvxlData.mappedDataMin;
float max = jvxlData.mappedDataMax;
StringBuffer list1 = new StringBuffer();
StringBuffer list2 = new StringBuffer();
if (vertexValues.length < vertexCount)
System.out.println("JVXLCOLOR OHOHO");
for (int i = 0; i < vertexCount; i++) {
float value = vertexValues[i];
if (Float.isNaN(value))
value = min;
if (doTruncate)
value = (value > 0 ? 0.999f : -0.999f);
if (writePrecisionColor)
jvxlAppendCharacter2(value, min, max, colorFractionBase,
colorFractionRange, list1, list2);
else
list1.append(jvxlValueAsCharacter(value, valueRed, valueBlue,
colorFractionBase, colorFractionRange));
}
jvxlData.jvxlColorData = list1.append(list2).append('\n').toString();
}
/* ******************************************************************
*
* JVXL 2.0 encoding of vertices, triangles, and vertex values:
*
*
*
*
*
*
*
*
*
*
*
**********************************************************/
private static void appendXmlVertexOnlyData(StringBuffer sb,
JvxlData jvxlData, MeshData meshData, boolean escapeXml) {
int[] vertexIdNew = new int[meshData.vertexCount];
if (appendXmlTriangleData(sb, meshData.polygonIndexes,
meshData.polygonCount, meshData.bsSlabDisplay,
vertexIdNew, escapeXml))
appendXmlVertexData(sb, jvxlData, vertexIdNew,
meshData.vertices, meshData.vertexValues, meshData.vertexCount,
meshData.polygonColorData, meshData.polygonCount,
meshData.bsSlabDisplay,
jvxlData.jvxlColorData.length() > 0, escapeXml);
}
/**
* encode triangle data -- [ia ib ic] [ia ib ic] [ia ib ic] ...
* algorithm written by Bob Hanson, 11/2008. The principle is that
* not all vertices may be represented -- we only need the
* used vertices here. Capitalizing on the fact that triangle sets
* tend to have common edges and similar numbers for sequential triangles.
*
* a) Renumbering vertices as they appear in the triangle set
*
* [2456 2457 2458] [2456 2459 2458]
*
* becomes
*
* [ 1 2 3] [ 1 4 3]
*
* b) This allows efficient encoding of differences, not absolute numbers.
*
* 0 1 2 -2 3 -1
*
* c) Which can then be represented often using a single ASCII character.
* I chose \ to be 0, and replace that with !.
*
* ASCII:
* -30 -20 -10 0 +10 +20 +30
* <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
*
* So the above sequence would simply be:
*
* !]^Z_[
*
* When the range falls outside of +/-32, we simply use a number.
* When a positive number follows another number, we add a "+" to it.
*
* !]^Z_[-33+250]230-210]]
*
* Preliminary trials indicated that on average a triangle
* can be encoded in about 7 bytes, or roughly half the 12 bytes
* necessary for standard binary encoding of integers. The advantage
* here is that we have an ASCII-readable file and no little-/big-endian issue.
*
* @param sb
* @param triangles
* @param nData
* @param bsSlabDisplay
* @param vertexIdNew
* @param escapeXml
* @return (triangles are present)
*/
private static boolean appendXmlTriangleData(StringBuffer sb, int[][] triangles, int nData,
BitSet bsSlabDisplay,
int[] vertexIdNew, boolean escapeXml) {
StringBuffer list1 = new StringBuffer();
StringBuffer list2 = new StringBuffer();
int ilast = 1;
int p = 0;
int inew = 0;
boolean addPlus = false;
int nTri = 0;
// note that the slabbing present becomes irreversible if there is no ghosting.
boolean removeSlabbed = (bsSlabDisplay != null);
for (int i = 0; i < nData;) {
if (triangles[i] == null || (removeSlabbed && !bsSlabDisplay.get(i))) {
i++;
continue;
}
int idata = triangles[i][p];
if (vertexIdNew[idata] > 0) {
idata = vertexIdNew[idata];
} else {
idata = vertexIdNew[idata] = ++inew;
}
int diff = idata - ilast;
ilast = idata;
if (diff == 0) {
list1.append('!');
addPlus = false;
} else if (diff > 32) {
if (addPlus)
list1.append('+');
list1.append(diff);
addPlus = true;
} else if (diff < -32) {
list1.append(diff);
addPlus = true;
} else {
list1.append((char) ('\\' + diff));
addPlus = false;
}
if (++p % 3 == 0) {
list2.append(triangles[i][3]);
p = 0;
i++;
nTri++;
}
}
if (list1.length() == 0)
return true;
XmlUtil.appendTag(sb, "jvxlTriangleData", new String[] {
"count", "" + nTri,
"encoding", "jvxltdiff",
"data" , jvxlCompressString(list1.toString(), escapeXml),
}, null);
XmlUtil.appendTag(sb, "jvxlTriangleEdgeData", new String[] { // Jmol 12.1.50
"count", "" + nTri,
"encoding", "jvxlsc",
"data" , jvxlCompressString(list2.toString(), escapeXml) }, null);
return true;
}
/**
* encode the vertex data. This must be done AFTER encoding the triangles,
* because the triangles redefine the order of vertices.
*
* Bob Hanson 11/2008
*
* If another program has created the triangles, we probably do not know the
* grid that was used for Marching Cubes, or quite possibly no grid was used.
* In that case, we just save the vertex/triangle/value data in a compact
* form.
*
* For the we use an extension of the way edge points are encoded. We simply
* identify the minimum and maximum x, y, and z coordinates and then express
* the point as a fraction along each of those directions. Thus, the x, y, and
* z coordinate are within the interval [0,1].
*
* We opt for the two-byte double-precision JVXL character compression. This
* allows a 1 part in 8100 resolution, which is plenty for these purposes.
*
* The tag will indicate the minimum and maximum values:
*
*
*
* The resultant string is really two strings of length nData where the first
* string lists the "high" part of the positions, and the second string lists
* the "low" part of the positions.
*
* @param sb
* @param jvxlData
* @param vertexIdNew
* @param vertices
* @param vertexValues
* @param vertexCount
* @param polygonColorData
* @param polygonCount
* @param bsSlabDisplay
* @param addColorData
* @param escapeXml
*/
private static void appendXmlVertexData(StringBuffer sb, JvxlData jvxlData,
int[] vertexIdNew,
Point3f[] vertices,
float[] vertexValues,
int vertexCount,
String polygonColorData,
int polygonCount,
BitSet bsSlabDisplay,
boolean addColorData, boolean escapeXml) {
int colorFractionBase = jvxlData.colorFractionBase;
int colorFractionRange = jvxlData.colorFractionRange;
Point3f p;
Point3f min = jvxlData.boundingBox[0];
Point3f max = jvxlData.boundingBox[1];
StringBuffer list1 = new StringBuffer();
StringBuffer list2 = new StringBuffer();
int[] vertexIdOld = null;
boolean removeSlabbed = (bsSlabDisplay != null);
if (polygonCount > 0) {
if (removeSlabbed)
polygonCount = bsSlabDisplay.cardinality();
removeSlabbed = false;
vertexIdOld = new int[vertexCount];
for (int i = 0; i < vertexCount; i++)
if (vertexIdNew[i] > 0) // not all vertices may be in triangle -- that's OK
vertexIdOld[vertexIdNew[i] - 1] = i;
}
int n = 0;
for (int i = 0; i < vertexCount; i++)
if (!removeSlabbed || bsSlabDisplay.get(i)) {
n++;
p = vertices[(polygonCount == 0 ? i : vertexIdOld[i])];
jvxlAppendCharacter2(p.x, min.x, max.x, colorFractionBase,
colorFractionRange, list1, list2);
jvxlAppendCharacter2(p.y, min.y, max.y, colorFractionBase,
colorFractionRange, list1, list2);
jvxlAppendCharacter2(p.z, min.z, max.z, colorFractionBase,
colorFractionRange, list1, list2);
}
list1.append(list2);
XmlUtil.appendTag(sb, "jvxlVertexData",
new String[] {
"count", "" + n,
"min", Escape.escape(min),
"max", Escape.escape(max),
"encoding", "base90xyz2",
"data", jvxlCompressString(list1.toString(), escapeXml),
}, null);
if (polygonColorData != null)
XmlUtil.appendTag(sb, "jvxlPolygonColorData", new String[] { "encoding",
"jvxlnc", "count", "" + polygonCount }, "\n" + polygonColorData);
if (!addColorData)
return;
// now add the color data, again as a double-precision value.
list1 = new StringBuffer();
list2 = new StringBuffer();
for (int i = 0; i < vertexCount; i++) {
float value = vertexValues[polygonCount == 0 ? i : vertexIdOld[i]];
jvxlAppendCharacter2(value, jvxlData.mappedDataMin,
jvxlData.mappedDataMax, colorFractionBase, colorFractionRange, list1,
list2);
}
appendXmlColorData(sb, "jvxlColorData", list1.append(list2).append("\n")
.toString(), true, jvxlData.valueMappedToRed,
jvxlData.valueMappedToBlue);
}
////////// character - fraction encoding and decoding
// NEVER change the numbers for these next defaults
final public static int defaultEdgeFractionBase = 35; //#$%.......
final public static int defaultEdgeFractionRange = 90;
final public static int defaultColorFractionBase = 35;
final public static int defaultColorFractionRange = 90;
/* character-encoding of factions in base 90:
*
* characters ASC(35) - ASC(124) are used for this encoding with the
* exception of ASC(92)'\\', which is encoded as ASC(33)'!'.
* ASC(125)'}' is reserved for "NaN".
* Double-quote is not in this range, but '<' and '>' are, so this
* is only XML-safe when quoted as an attribute.
*
*/
public static char jvxlFractionAsCharacter(float fraction) {
return jvxlFractionAsCharacter(fraction, defaultEdgeFractionBase, defaultEdgeFractionRange);
}
public static char jvxlFractionAsCharacter(float fraction, int base, int range) {
if (fraction > 0.9999f)
fraction = 0.9999f;
else if (Float.isNaN(fraction))
fraction = 1.0001f;
int ich = (int) (fraction * range + base);
if (ich < base)
return (char) base;
if (ich == 92)
return 33; // \ --> !
//if (logCompression)
//Logger.info("fac: " + fraction + " --> " + ich + " " + (char) ich);
return (char) ich;
}
private static void jvxlAppendCharacter2(float value, float min, float max,
int base, int range,
StringBuffer list1,
StringBuffer list2) {
float fraction = (min == max ? value : (value - min) / (max - min));
char ch1 = jvxlFractionAsCharacter(fraction, base, range);
list1.append(ch1);
fraction -= jvxlFractionFromCharacter(ch1, base, range, 0);
list2.append(jvxlFractionAsCharacter(fraction * range, base, range));
}
public static float jvxlFractionFromCharacter(int ich, int base, int range,
float fracOffset) {
if (ich == base + range)
return Float.NaN;
if (ich < base)
ich = 92; // ! --> \
float fraction = (ich - base + fracOffset) / range;
if (fraction < 0f)
return 0f;
if (fraction > 1f)
return 0.999999f;
// System.out.println("ffc: " + fraction + " <-- " + ich + " " + (char)
// ich);
return fraction;
}
public static float jvxlFractionFromCharacter2(int ich1, int ich2, int base,
int range) {
float fraction = jvxlFractionFromCharacter(ich1, base, range, 0);
float remains = jvxlFractionFromCharacter(ich2, base, range, 0.5f);
return fraction + remains / range;
}
public static char jvxlValueAsCharacter(float value, float min, float max, int base,
int range) {
float fraction = (min == max ? value : (value - min) / (max - min));
return jvxlFractionAsCharacter(fraction, base, range);
}
protected static float jvxlValueFromCharacter2(int ich, int ich2, float min,
float max, int base, int range) {
float fraction = jvxlFractionFromCharacter2(ich, ich2, base, range);
return (max == min ? fraction : min + fraction * (max - min));
}
// /// differential bitset encoding and decoding (Bob Hanson [email protected] for Jmol)
public static int jvxlEncodeBitSet0(BitSet bs, int nPoints, StringBuffer sb) {
// nunset nset nunset ...
// for repeated numbers:
// 3 3 3 3 3 3 3 becomes 3 -6
int dataCount = 0;
int prevCount = -1;
int nPrev = 0;
if (nPoints < 0)
nPoints = bs.length();
int n = 0;
boolean isset = false;
int lastPoint = nPoints - 1;
for (int i = 0; i < nPoints; ++i) {
if (isset == bs.get(i)) {
dataCount++;
} else {
if (dataCount == prevCount && i != lastPoint) {
nPrev++;
} else {
if (nPrev > 0) {
sb.append(' ').append(-nPrev);
nPrev = 0;
n++;
}
sb.append(' ').append(dataCount);
n++;
prevCount = dataCount;
}
dataCount = 1;
isset = !isset;
}
}
sb.append(' ').append(dataCount).append('\n');
return n;
}
public static String jvxlEncodeBitSet(BitSet bs) {
StringBuffer sb = new StringBuffer();
jvxlEncodeBitSet(bs, -1, sb);
return sb.toString();
}
public static int jvxlEncodeBitSet(BitSet bs, int nPoints, StringBuffer sb) {
//System.out.println("jvxlcoder " + Escape.escape(bs));
int dataCount = 0;
int n = 0;
boolean isset = false;
if (nPoints < 0)
nPoints = bs.length();
if (nPoints == 0)
return 0;
sb.append("-");
for (int i = 0; i < nPoints; ++i) {
if (isset == bs.get(i)) {
dataCount++;
} else {
jvxlAppendEncodedNumber(sb, dataCount, defaultEdgeFractionBase, defaultEdgeFractionRange);
n++;
dataCount = 1;
isset = !isset;
}
}
jvxlAppendEncodedNumber(sb, dataCount, defaultEdgeFractionBase, defaultEdgeFractionRange);
sb.append('\n');
return n;
}
public static void jvxlAppendEncodedNumber(StringBuffer sb, int n, int base, int range) {
boolean isInRange = (n < range);
if (n == 0)
sb.append((char) base);
else if (!isInRange)
sb.append((char)(base + range));
while (n > 0) {
int n1 = n / range;
int x = base + n - n1 * range;
if (x == 92)
x = 33; // \ --> !
sb.append((char) x);
n = n1;
}
if (!isInRange)
sb.append(" ");
}
public static BitSet jvxlDecodeBitSet(String data, int base, int range) {
BitSet bs = new BitSet();
int dataCount = 0;
int ptr = 0;
boolean isset = false;
int[] next = new int[1];
while ((dataCount = jvxlParseEncodedInt(data, base, range, next)) != Integer.MIN_VALUE) {
if (isset)
bs.set(ptr, ptr + dataCount);
ptr += dataCount;
isset = !isset;
}
return bs;
}
public static int jvxlParseEncodedInt(String str, int offset, int base, int[] next) {
boolean digitSeen = false;
int value = 0;
int ich = next[0];
int ichMax = str.length();
if (ich < 0)
return Integer.MIN_VALUE;
while (ich < ichMax && Character.isWhitespace(str.charAt(ich)))
++ich;
if (ich >= ichMax)
return Integer.MIN_VALUE;
int factor = 1;
boolean isLong = (str.charAt(ich) == (offset + base));
if (isLong)
ich++;
while (ich < ichMax && !Character.isWhitespace(str.charAt(ich))) {
int i = str.charAt(ich);
if (i < offset)
i = 92; // ! --> \
value += (i - offset) * factor;
digitSeen = true;
++ich;
if (!isLong)
break;
factor *= base;
}
if (!digitSeen)
value = Integer.MIN_VALUE;
next[0] = ich;
return value;
}
public static BitSet jvxlDecodeBitSet(String data) {
if (data.startsWith("-"))
return jvxlDecodeBitSet(jvxlUncompressString(data.substring(1)), defaultEdgeFractionBase, defaultEdgeFractionRange);
// nunset nset nunset ...
BitSet bs = new BitSet();
int dataCount = 0;
int lastCount = 0;
int nPrev = 0;
int ptr = 0;
boolean isset = false;
int[] next = new int[1];
while (true) {
dataCount = (nPrev++ < 0 ? dataCount : Parser.parseInt(data, next));
if (dataCount == Integer.MIN_VALUE)
break;
if (dataCount < 0) {
nPrev = dataCount;
dataCount = lastCount;
continue;
}
if (isset)
bs.set(ptr, ptr + dataCount);
ptr += dataCount;
lastCount = dataCount;
isset = !isset;
}
return bs;
}
/////// string data compression/decompression
public static String jvxlCompressString(String data, boolean escapeXml) {
/* just a simple compression, but allows 2000-6000:1 CUBE:JVXL for planes!
*
* "X~nnn " means "nnn copies of character X"
*
* ########## becomes "#~10 "
*
* ~ is not encoded, as it is ASC(126), outside the range of 33--125.
*
* for escaping XML, we also do:
*
* < becomes "~;0 "
* & becomes "~%0 "
*
* and repeats of those become:
*
* "~;nnn "
* "~%nnn "
*
*/
if (data.indexOf("~") >= 0)
return data;
StringBuffer dataOut = new StringBuffer();
char chLast = '\0';
boolean escaped = false;
boolean lastEscaped = false;
int nLast = 0;
int n = data.length();
for (int i = 0; i <= n; i++) {
char ch = (i == n ? '\0' : data.charAt(i));
switch (ch) {
case '\n':
case '\r':
continue;
case '&':
case '<':
escaped = escapeXml;
break;
default:
escaped = false;
}
if (ch == chLast) {
++nLast;
ch = '\0';
} else if (nLast > 0 || lastEscaped) {
if (nLast < 4 && !lastEscaped || chLast == ' '
|| chLast == '\t') {
while (--nLast >= 0)
dataOut.append(chLast);
} else {
if (lastEscaped)
lastEscaped = false;
else
dataOut.append('~');
dataOut.append(nLast);
dataOut.append(' ');
}
nLast = 0;
}
if (ch != '\0') {
if (escaped) {
lastEscaped = true;
escaped = false;
dataOut.append('~');
chLast = ch;
--ch;
} else {
chLast = ch;
}
dataOut.append(ch);
}
}
return dataOut.toString();
}
public static String jvxlUncompressString(String data) {
if (data.indexOf("~") < 0)
return data;
StringBuffer dataOut = new StringBuffer();
char chLast = '\0';
int[] next = new int[1];
for (int i = 0; i < data.length(); i++) {
char ch = data.charAt(i);
if (ch == '~') {
next[0] = ++i;
switch (ch = data.charAt(i)) {
case ';':
case '%':
next[0]++;
dataOut.append(chLast = ++ch);
//$FALL-THROUGH$
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
int nChar = Parser.parseInt(data, next);
for (int c = 0; c < nChar; c++)
dataOut.append(chLast);
i = next[0];
continue;
case '~':
--i;
break;
default:
Logger.error("Error uncompressing string " + data.substring(0, i) + "?");
}
}
dataOut.append(ch);
chLast = ch;
}
return dataOut.toString();
}
// VERSION 1 methods -- deprecated but still available through Jmol 11.9.18
public static void jvxlCreateHeaderWithoutTitleOrAtoms(VolumeData v, StringBuffer bs) {
jvxlCreateHeader(v, bs);
}
/**
* Creates a two-line header for the XJVXL file. It is no longer necessary
* to create the atom set or generate the vectors here. Please leave the
* commented code for posterity.
*
* @param v
* @param sb
*/
public static void jvxlCreateHeader(VolumeData v, StringBuffer sb) {
// if the StringBuffer comes in non-empty, it should have two lines
// that do not start with # already present.
v.setVolumetricXml();
if (sb.length() == 0)
sb.append("Line 1\nLine 2\n");
/* no longer necessary
sb.append(nAtoms == Integer.MIN_VALUE ? "+2"
: nAtoms == Integer.MAX_VALUE ? "-2" : "" + (-nAtoms))
.append(' ')
.append(v.volumetricOrigin.x).append(' ')
.append(v.volumetricOrigin.y).append(' ')
.append(v.volumetricOrigin.z).append(" ANGSTROMS\n");
for (int i = 0; i < 3; i++)
sb.append(v.voxelCounts[i]).append(' ')
.append(v.volumetricVectors[i].x).append(' ')
.append(v.volumetricVectors[i].y).append(' ')
.append(v.volumetricVectors[i].z).append('\n');
if (nAtoms != Integer.MAX_VALUE && nAtoms != Integer.MIN_VALUE) {
nAtoms = Math.abs(nAtoms);
for (int i = 0, n = 0; i < nAtoms; i++)
sb.append((n = Math.abs(atomNo[i])) + " " + n + ".0 "
+ atomXyz[i].x + " " + atomXyz[i].y + " " + atomXyz[i].z + "\n");
return;
}
Point3f pt = new Point3f(v.volumetricOrigin);
sb.append("1 1.0 ").append(pt.x).append(' ').append(pt.y).append(' ')
.append(pt.z).append(" //BOGUS H ATOM ADDED FOR JVXL FORMAT\n");
for (int i = 0; i < 3; i++)
pt.scaleAdd(v.voxelCounts[i] - 1, v.volumetricVectors[i], pt);
sb.append("2 2.0 ").append(pt.x).append(' ').append(pt.y).append(' ')
.append(pt.z).append(" //BOGUS He ATOM ADDED FOR JVXL FORMAT\n");
*/
}
/*
private static String jvxlGetFileVersion1(JvxlData jvxlData,
MeshData meshData, String[] title,
String msg, boolean includeHeader,
int nSurfaces, String state,
String comment) {
// pre-XML
if ("TRAILERONLY".equals(msg))
return "";
StringBuffer data = new StringBuffer();
if (includeHeader) {
String s = jvxlData.jvxlFileHeader
+ (nSurfaces > 0 ? -nSurfaces : -1) +" " + jvxlData.edgeFractionBase + " "
+ jvxlData.edgeFractionRange + " " + jvxlData.colorFractionBase + " "
+ jvxlData.colorFractionRange + " Jmol voxel format version " + JVXL_VERSION1 + "\n";
if (s.indexOf("#JVXL") != 0)
data.append("#JVXL").append(jvxlData.isXLowToHigh ? "+" : "").append(
" VERSION ").append(JVXL_VERSION1).append("\n");
data.append(s);
}
if ("HEADERONLY".equals(msg))
return data.toString();
data.append("# ").append(msg).append('\n');
if (title != null)
for (int i = 0; i < title.length; i++)
data.append("# ").append(title[i]).append('\n');
state = (state == null ? "" : " rendering:" + state);
String definitionLine = jvxlGetDefinitionLineVersion1(jvxlData);
data.append(definitionLine).append(state).append('\n');
StringBuffer sb = new StringBuffer();
String colorData = (jvxlData.jvxlColorData == null ? "" : jvxlData.jvxlColorData);
// if (jvxlData.vertexDataOnly) { // see XML version
// sb.append("\n");
// jvxlAppendMeshXml(sb, jvxlData, meshData, false);
// sb.append(" \n");
//} else
if (jvxlData.jvxlPlane == null) {
if (jvxlData.jvxlEdgeData == null)
return "";
//no real point in compressing this unless it's a sign-based coloring
sb.append(jvxlData.jvxlSurfaceData);
sb.append(jvxlCompressString(jvxlData.jvxlEdgeData, false)).append('\n').append(
jvxlCompressString(colorData, false)).append('\n');
} else if (colorData != null) {
sb.append(jvxlCompressString(colorData, false)).append('\n');
}
int len = sb.length();
data.append(sb);
if (includeHeader) {
if (msg != null && !jvxlData.vertexDataOnly)
data.append("#-------end of jvxl file data-------\n");
data.append(jvxlGetInfo(jvxlData, false)).append('\n');
jvxlAppendCommandState(data, comment, state, false);
if (includeHeader)
XmlUtil.appendTag(data, "jvxlFileTitle", null, null, jvxlData.jvxlFileTitle, false, true);
}
return jvxlSetCompressionRatio(data, jvxlData, len);
}
private static String jvxlGetDefinitionLineVersion1(JvxlData jvxlData) {
String definitionLine =
//(jvxlData.vContours == null ? "" : "#+contourlines\n")+
jvxlData.cutoff + " ";
// optional comment line for compatibility with earlier Jmol versions:
// #+contourlines (no longer used -- see XML version)
// cutoff nInts (+/-)bytesEdgeData (+/-)bytesColorData
// param1 param2 param3
// | | |
// when | | > 0 ==> jvxlDataIsColorMapped
// when | | == -1 ==> not color mapped
// when | | < -1 ==> jvxlDataIsPrecisionColor
// when == -1 && == -1 ==> noncontoured plane
// when == -1 && == -2 ==> contourable plane
// when < -1* && > 0 ==> contourable functionXY
// when > 0 && < 0 ==> jvxlDataisBicolorMap
// nInts saved as -1 - nInts
if (jvxlData.jvxlSurfaceData == null)
return "";
int nSurfaceInts = jvxlData.nSurfaceInts;// jvxlData.jvxlSurfaceData.length();
int bytesUncompressedEdgeData = (jvxlData.vertexDataOnly ? 0
: jvxlData.jvxlEdgeData.length() - 1);
int nColorData = (jvxlData.jvxlColorData == null ? -1 : (jvxlData.jvxlColorData.length() - 1));
if (jvxlData.jvxlPlane == null) {
if (jvxlData.isContoured) {
definitionLine += (-1 - nSurfaceInts) + " " + bytesUncompressedEdgeData;
} else if (jvxlData.isBicolorMap) {
definitionLine += (nSurfaceInts) + " " + (-bytesUncompressedEdgeData);
} else {
definitionLine += nSurfaceInts + " " + bytesUncompressedEdgeData;
}
definitionLine += " "
+ (jvxlData.isJvxlPrecisionColor && nColorData != -1 ? -nColorData
: nColorData);
} else {
String s = " " + jvxlData.jvxlPlane.x + " " + jvxlData.jvxlPlane.y + " "
+ jvxlData.jvxlPlane.z + " " + jvxlData.jvxlPlane.w;
definitionLine += (jvxlData.isContoured ? "-1 -2 " + (-nColorData)
: "-1 -1 " + nColorData)
+ s;
}
if (jvxlData.isContoured) {
if (jvxlData.contourValues == null || jvxlData.contourColixes == null) {
definitionLine += " " + jvxlData.nContours;
} else {
definitionLine += " " + Escape.escapeArray(jvxlData.contourValues)
+ " \"" + jvxlData.contourColors + "\"";
}
}
// ... mappedDataMin mappedDataMax valueMappedToRed valueMappedToBlue ...
float min = (jvxlData.mappedDataMin == Float.MAX_VALUE ? 0f
: jvxlData.mappedDataMin);
definitionLine += " " + min + " " + jvxlData.mappedDataMax + " "
+ jvxlData.valueMappedToRed + " " + jvxlData.valueMappedToBlue;
if (jvxlData.insideOut) {
definitionLine += " insideOut";
}
return definitionLine;
}
*/
}