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 }