1 package org.jmol.shapesurface; 2 3 import javajs.util.OC; 4 import javajs.util.T3; 5 6 import javajs.util.BS; 7 import org.jmol.util.C; 8 import org.jmol.util.MeshSurface; 9 10 /** 11 * A class called by reflection from IsosurfaceMesh from the Jmol command 12 * 13 * WRITE xxxx.pmesh (ascii) 14 * 15 * or 16 * 17 * WRITE xxxx.pmb (binary) 18 * 19 * 20 */ 21 public class PMeshWriter { 22 23 private IsosurfaceMesh imesh; 24 boolean isBinary; 25 private OC oc; 26 private int i0; 27 private int[][] polygonIndexes; 28 private boolean selectedPolyOnly; 29 private BS bsPolygons; 30 private boolean haveBsDisplay; 31 private boolean colorSolid; 32 private boolean colorArrayed; 33 private short cx; 34 private short[] vertexColixes; 35 private boolean noColor; 36 private short[] contourColixes; 37 private float[] vertexValues; 38 private int vertexCount; 39 private int[] imap; 40 PMeshWriter()41 public PMeshWriter() { 42 // for reflection 43 } 44 write(IsosurfaceMesh isosurfaceMesh, boolean isBinary)45 Object write(IsosurfaceMesh isosurfaceMesh, boolean isBinary) { 46 imesh = isosurfaceMesh; 47 this.isBinary = isBinary; 48 49 // Get all the needed information. Based IsosurfaceRenderer.renderTriangles. 50 // Just contours right now. 51 52 BS bsPoly = new BS(); 53 BS bsVert = new BS(); 54 BS bsPoints = new BS(); 55 56 if (imesh.showPoints || imesh.pc <= 0) 57 checkPoints(bsPoints); 58 bsVert.or(bsPoints); 59 if (imesh.drawTriangles) 60 checkTriangles(false, bsPoly, bsVert); 61 if (imesh.pc > 0 && imesh.fillTriangles) 62 checkTriangles(true, bsPoly, bsVert); 63 64 imap = new int[vertexCount]; 65 int[] iimap = new int[vertexCount]; 66 int nV = 0; 67 for (int i = bsVert.nextSetBit(0); i >= 0; i = bsVert.nextSetBit(i + 1)) { 68 iimap[nV] = i; 69 imap[i] = nV++; 70 } 71 72 writePmeshHeader(nV); 73 if (!isBinary) 74 outputInt(nV); 75 for (int i = 0; i < nV; i++) 76 outputXYZ(imesh.vs[iimap[i]]); 77 if (!isBinary) 78 outputInt(-1); // null-terminated 79 80 if (imesh.showPoints || imesh.pc <= 0) 81 outputPoints(bsPoints); 82 bsVert.or(bsPoints); 83 BS bsDone = new BS(); 84 if (imesh.drawTriangles) 85 outputTriangles(false, bsPoly, bsDone); 86 if (imesh.pc > 0 && imesh.fillTriangles) 87 outputTriangles(true, bsPoly, bsDone); 88 89 if (isBinary) 90 oc.writeInt(0); 91 else 92 oc.append("0\n"); 93 oc.closeChannel(); 94 return (isBinary ? oc.toByteArray() : oc.toString()); 95 } 96 outputPoints(BS bsPoints)97 private void outputPoints(BS bsPoints) { 98 int color = C.getArgb(cx); 99 for (int i = bsPoints.nextSetBit(0); i >= 0; i = bsPoints.nextSetBit(i + 1)) { 100 if (!imesh.isColorSolid && imesh.vcs != null) { 101 cx = imesh.vcs[i]; 102 color = C.getArgb(cx); 103 } 104 outputPoint(imap[i], color); 105 } 106 } 107 outputTriangles(boolean fill, BS bsPoly, BS bsDone)108 private void outputTriangles(boolean fill, BS bsPoly, BS bsDone) { 109 int color = C.getArgb(cx); 110 for (int i = bsPoly.nextSetBit(0); i >= 0; i = bsPoly.nextSetBit(i + 1)) { 111 int[] polygon = polygonIndexes[i]; 112 int iA = imap[polygon[0]]; 113 int iB = imap[polygon[1]]; 114 int iC = imap[polygon[2]]; 115 if (colorSolid) { 116 if (colorArrayed && i < imesh.pcs.length) 117 cx = imesh.pcs[i]; 118 } else { 119 cx = vertexColixes[polygon[0]]; 120 } 121 color = C.getArgb(cx); 122 if (fill) { 123 if (iB == iC) { 124 if (iA == iB) 125 outputPoint(iA, color); 126 else 127 outputEdge(iA, iB, color); 128 bsDone.set(i); 129 } else { 130 if (imesh.colorsExplicit) 131 color = polygon[MeshSurface.P_EXPLICIT_COLOR]; 132 outputTriangle(iA, iB, iC, color, 999); 133 } 134 } else if (!bsDone.get(i)) { 135 // mesh only 136 // check: 1 (ab) | 2(bc) | 4(ac) 137 int check = 7 & polygon[MeshSurface.P_CHECK]; 138 if (check == 0) 139 continue; 140 if (noColor) { 141 } else if (colorArrayed) { 142 color = C.getArgb(imesh.fillTriangles ? C.BLACK 143 : contourColixes[polygon[MeshSurface.P_CONTOUR] 144 % contourColixes.length]); 145 } 146 outputTriangle(iA, iB, iC, color, check); 147 } 148 } 149 } 150 checkPoints(BS bsVert)151 private void checkPoints(BS bsVert) { 152 boolean slabPoints = ((imesh.pc == 0) && selectedPolyOnly); 153 int incr = imesh.vertexIncrement; 154 for (int i = (!imesh.hasGridPoints || imesh.firstRealVertex < 0 ? 0 155 : imesh.firstRealVertex); i < vertexCount; i += incr) { 156 if (vertexValues != null && Float.isNaN(vertexValues[i]) 157 || imesh.jvxlData.thisSet != null 158 && !imesh.jvxlData.thisSet.get(imesh.vertexSets[i]) 159 || !imesh.isColorSolid || haveBsDisplay && !imesh.bsDisplay.get(i) 160 || slabPoints && !bsPolygons.get(i)) 161 continue; 162 bsVert.set(i); 163 } 164 } 165 checkTriangles(boolean fill, BS bsPoly, BS bsVert)166 private void checkTriangles(boolean fill, BS bsPoly, BS bsVert) { 167 168 setup(fill); 169 170 for (int i = imesh.pc; --i >= 0;) { 171 int[] polygon = polygonIndexes[i]; 172 if (polygon == null || selectedPolyOnly && !bsPolygons.get(i)) 173 continue; 174 int iA = polygon[0]; 175 if (imesh.jvxlData.thisSet != null && imesh.vertexSets != null 176 && !imesh.jvxlData.thisSet.get(imesh.vertexSets[iA])) 177 continue; 178 int iB = polygon[1]; 179 int iC = polygon[2]; 180 if (haveBsDisplay 181 && (!imesh.bsDisplay.get(iA) || !imesh.bsDisplay.get(iB) || !imesh.bsDisplay.get(iC))) 182 continue; 183 if (colorSolid && colorArrayed && i < imesh.pcs.length && imesh.pcs[i] == 0) 184 continue; 185 bsPoly.set(i); 186 bsVert.set(iA); 187 bsVert.set(iB); 188 bsVert.set(iC); 189 } 190 } 191 setup(boolean fill)192 private void setup(boolean fill) { 193 vertexCount = imesh.vc; 194 vertexValues = imesh.vvs; 195 polygonIndexes = imesh.pis; 196 cx = (!fill && imesh.meshColix != 0 ? imesh.meshColix : imesh.colix); 197 vertexColixes = (!fill && imesh.meshColix != 0 ? null : imesh.vcs); 198 colorSolid = (vertexColixes == null); 199 noColor = (vertexColixes == null || !fill && imesh.meshColix != 0); 200 colorArrayed = (colorSolid && imesh.pcs != null); 201 if (colorArrayed && !fill && imesh.fillTriangles) 202 colorArrayed = false; 203 contourColixes = imesh.jvxlData.contourColixes; 204 haveBsDisplay = (imesh.bsDisplay != null); 205 selectedPolyOnly = (imesh.bsSlabDisplay != null); 206 bsPolygons = (selectedPolyOnly ? imesh.bsSlabDisplay : null); 207 208 } 209 writePmeshHeader(int nV)210 private void writePmeshHeader(int nV) { 211 oc = imesh.vwr.getOutputChannel(null, null); 212 if (isBinary) { 213 oc.writeByteAsInt(80); 214 oc.writeByteAsInt(77); 215 oc.writeByteAsInt(1); 216 oc.writeByteAsInt(0); 217 oc.writeInt(1); 218 oc.writeInt(nV); 219 oc.writeInt(-1); 220 for (int i = 0; i < 16; i++) 221 oc.writeInt(0); 222 } else { 223 oc.append("#JmolPmesh\n"); 224 } 225 } 226 outputInt(int i)227 private void outputInt(int i) { 228 if (isBinary) 229 oc.writeInt(i); 230 else 231 oc.append("" + i + "\n"); 232 } 233 outputPoint(int iA, int color)234 private int outputPoint(int iA, int color) { 235 outputInt(-1); 236 outputInt(iA); 237 outputInt(color); 238 return 1; 239 } 240 outputXYZ(T3 pt)241 private void outputXYZ(T3 pt) { 242 if (isBinary) { 243 oc.writeFloat(pt.x); 244 oc.writeFloat(pt.y); 245 oc.writeFloat(pt.z); 246 } else { 247 oc.append(pt.x + " " + pt.y + " " + pt.z + "\n"); 248 } 249 } 250 outputEdge(int iA, int iB, int color)251 private void outputEdge(int iA, int iB, int color) { 252 outputInt(-2); 253 outputInt(iA); 254 outputInt(iB); 255 outputInt(color); 256 } 257 outputTriangle(int iA, int iB, int iC, int color, int check)258 private void outputTriangle(int iA, int iB, int iC, int color, int check) { 259 if (check == 999) { 260 outputInt(-3); 261 outputInt(iA); 262 outputInt(iB); 263 outputInt(iC); 264 outputInt(color); 265 return; 266 } 267 if ((check & 1) != 0) 268 outputEdge(iA, iB, color); 269 if ((check & 2) != 0) 270 outputEdge(iB, iC, color); 271 if ((check & 4) != 0) 272 outputEdge(iC, iA, color); 273 } 274 }