]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.opencascade.vtk/src/org/simantics/opencascade/vtk/vtkSolidObject.java
3D framework (Simca 2012)
[simantics/3d.git] / org.simantics.opencascade.vtk / src / org / simantics / opencascade / vtk / vtkSolidObject.java
1 package org.simantics.opencascade.vtk;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.List;\r
6 \r
7 import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;\r
8 import org.jcae.opencascade.jni.TopAbs_ShapeEnum;\r
9 import org.jcae.opencascade.jni.TopExp_Explorer;\r
10 import org.jcae.opencascade.jni.TopoDS_Face;\r
11 import org.jcae.opencascade.jni.TopoDS_Shape;\r
12 import org.simantics.opencascade.OCCTTool;\r
13 import org.simantics.utils.threads.AWTThread;\r
14 import org.simantics.utils.threads.ThreadUtils;\r
15 \r
16 import vtk.vtkActor;\r
17 import vtk.vtkAlgorithmOutput;\r
18 import vtk.vtkCleanPolyData;\r
19 import vtk.vtkDataSetMapper;\r
20 import vtk.vtkFeatureEdges;\r
21 import vtk.vtkGlyph3D;\r
22 import vtk.vtkPanel;\r
23 import vtk.vtkPolyData;\r
24 import vtk.vtkPolyDataMapper;\r
25 import vtk.vtkPolyDataNormals;\r
26 import vtk.vtkPolyDataSilhouette;\r
27 import vtk.vtkProp3D;\r
28 import vtk.vtkProperty;\r
29 import vtk.vtkRenderer;\r
30 import vtk.vtkSphereSource;\r
31 \r
32 public class vtkSolidObject {\r
33         \r
34         public static double deflection = 0.001;\r
35         \r
36         public static double featureAngle = 30;\r
37         public static boolean computeNormals = true;\r
38         public static boolean cleanPart = false;\r
39         public static boolean mergePoints = false;\r
40         \r
41         private vtkPanel panel;\r
42         private TopoDS_Shape shape;\r
43         \r
44         private List<vtkProp3D> actors = new ArrayList<vtkProp3D>(2);\r
45         \r
46         private List<vtkProp3D> solid = new ArrayList<vtkProp3D>(1);\r
47         private List<vtkProp3D> edges =  new ArrayList<vtkProp3D>(1);\r
48         private vtkActor silhouette = null;\r
49         \r
50         public vtkSolidObject(vtkPanel panel,TopoDS_Shape shape) {\r
51                 this.shape = shape;\r
52                 this.panel = panel;\r
53         }\r
54         \r
55         public void visualizeSolid(boolean showEdges, boolean showVertices) {\r
56                 visualizeSolid(true, showEdges, showVertices);\r
57         }\r
58         \r
59         public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices) {\r
60                 visualizeSolid(showFaces, showEdges, showVertices, false);\r
61         }\r
62         \r
63         public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices, boolean showSilhouette) {\r
64                 clearActorsAWT();\r
65                 vtkPolyData data = createSolidMesh(shape);\r
66                 if (data == null)\r
67                         return;\r
68                 if (showFaces) {\r
69                         solid.add(createActor(data));           \r
70                 }\r
71                 if (showEdges) {\r
72                         vtkActor edge = createEdgesActor(data);\r
73                         edges.add(edge);                        \r
74                         if (showVertices) {\r
75                                 actors.add(createVerticesActor(edge));\r
76                         }\r
77                 }\r
78                 if (showSilhouette) {\r
79                         silhouette = createSilhouette(panel.GetRenderer(), data);\r
80                 }\r
81                 actors.addAll(solid);\r
82                 actors.addAll(edges);\r
83                 if (silhouette != null)\r
84                         actors.add(silhouette);\r
85                 data.Delete();\r
86                 showActorsAWT();\r
87         }\r
88         \r
89         public void visualizeFaces(boolean showEdges, boolean showVertices) {\r
90                 clearActorsAWT();\r
91                 Collection<vtkPolyData> datas = createFaceMeshes(shape);\r
92                 for (vtkPolyData data : datas) {\r
93                         solid.add(createActor(data));\r
94                         \r
95                         if (showEdges) {\r
96                                 vtkActor edgesActor = createEdgesActor(data); \r
97                                 edges.add(edgesActor);\r
98                                 if (showVertices) {\r
99                                         actors.add(createVerticesActor(edgesActor));\r
100                                 }\r
101                         }\r
102                         data.Delete();\r
103                 }\r
104                 actors.addAll(solid);\r
105                 actors.addAll(edges);\r
106                 \r
107                 showActorsAWT();\r
108         }\r
109         \r
110         public List<vtkProp3D> getActors() {\r
111                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
112                 return actors;\r
113         }\r
114         \r
115         public List<vtkProp3D> getSolid() {\r
116                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
117                 return solid;\r
118         }\r
119         \r
120         public List<vtkProp3D> getEdges() {\r
121                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
122                 return edges;\r
123         }\r
124         \r
125         public vtkActor getSilhouette() {\r
126                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
127                 return silhouette;\r
128         }\r
129         \r
130         public void showActorsAWT() {\r
131                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
132                 vtkRenderer ren = panel.GetRenderer();\r
133                 for (vtkProp3D act : actors) {\r
134                         ren.AddActor(act);\r
135                 }\r
136         }\r
137         \r
138         public void showActors() {\r
139                 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
140                         \r
141                         @Override\r
142                         public void run() {\r
143                                 showActorsAWT();\r
144                         }\r
145                 });\r
146         }\r
147         \r
148         public void clearActorsAWT() {\r
149                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
150                 if (actors.size() == 0)\r
151                         return;\r
152                 vtkRenderer ren = panel.GetRenderer();\r
153                 for (vtkProp3D act : actors) {\r
154                         if (act.GetVTKId() != 0) {\r
155                                 ren.RemoveActor(act);\r
156                                 act.Delete();\r
157                         }\r
158                 }\r
159                 actors.clear();\r
160                 solid.clear();\r
161                 edges.clear();\r
162         }\r
163         \r
164         private void clearActorsAWT(List<vtkProp3D> actors) {\r
165                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
166                 \r
167                 if (actors.size() == 0)\r
168                         return;\r
169                 vtkRenderer ren = panel.GetRenderer();\r
170                 panel.lock();\r
171                 for (vtkProp3D act : actors) {\r
172                         if (act.GetVTKId() != 0) {\r
173                                 ren.RemoveActor(act);\r
174                                 act.Delete();\r
175                         }\r
176                 }\r
177                 panel.unlock();\r
178         }\r
179         \r
180         public void clearActors() {\r
181                 if (actors.size() == 0)\r
182                         return;\r
183                 final List<vtkProp3D> temp = new ArrayList<vtkProp3D>(actors.size());\r
184                 temp.addAll(actors);\r
185                 actors.clear();\r
186                 solid.clear();\r
187                 edges.clear();\r
188                 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
189                         \r
190                         @Override\r
191                         public void run() {\r
192                                 clearActorsAWT(temp);\r
193                         }\r
194                 });\r
195         }\r
196         \r
197         public void dispose() {\r
198                 if (shape != null) {\r
199                         shape.delete();\r
200                         shape = null;\r
201                 }\r
202                 clearActors();\r
203         }\r
204         \r
205         public void delete() {\r
206                 if (shape != null) {\r
207                         shape.delete();\r
208                         shape = null;\r
209                 }\r
210                 clearActorsAWT();\r
211         }\r
212         \r
213         private static double TOLERANCE = 0.01;\r
214         \r
215         public static vtkPolyData createSolidMesh(TopoDS_Shape shape) {\r
216                 \r
217                 double volume = OCCTTool.getBoundingBoxDiagonal(shape);\r
218                 if (volume < TOLERANCE)\r
219                         return null;\r
220                 \r
221                 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);\r
222         \r
223                 TopExp_Explorer expFace = new TopExp_Explorer();\r
224                 \r
225                 List<Double> meshPoints = new ArrayList<Double>();\r
226                 List<Integer> meshTriangles = new ArrayList<Integer>();\r
227                 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
228                         TopoDS_Face face = (TopoDS_Face) expFace.current();\r
229                         OCCTTool.appendToMesh(face, meshPoints, meshTriangles);\r
230                         face.delete();\r
231                 }\r
232                 if (meshPoints.size() == 0 || meshTriangles.size() == 0)\r
233                         return null;\r
234                         \r
235                 vtkPolyData data = VTKOCCTool.createPartGrid(meshPoints, meshTriangles);\r
236                 \r
237                 expFace.delete();\r
238                 mesh.delete();\r
239                 \r
240                 return data;\r
241         }\r
242         \r
243         public static Collection<vtkPolyData> createFaceMeshes(TopoDS_Shape shape) {\r
244                 \r
245                 double volume = OCCTTool.getBoundingBoxDiagonal(shape);\r
246                 Collection<vtkPolyData> faces = new ArrayList<vtkPolyData>();\r
247                 \r
248                 if (volume > TOLERANCE) {\r
249                 \r
250                         BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);\r
251                 \r
252                         TopExp_Explorer expFace = new TopExp_Explorer();\r
253                         \r
254                         \r
255                         for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
256                                 TopoDS_Face face = (TopoDS_Face) expFace.current();\r
257                                 vtkPolyData data = VTKOCCTool.createPartGrid(face);\r
258                                 face.delete();\r
259                                 faces.add(data);\r
260                         }\r
261                         \r
262                         expFace.delete();\r
263                         mesh.delete();\r
264                 }\r
265                 \r
266                 return faces;\r
267         }\r
268         \r
269         \r
270         \r
271         public static vtkActor createActor(vtkPolyData partGrid) {\r
272                 \r
273                 \r
274             vtkDataSetMapper partMapper = new vtkDataSetMapper();\r
275             \r
276             vtkCleanPolyData partCleaner = null;       \r
277             if (cleanPart)\r
278             {\r
279                 partCleaner = new vtkCleanPolyData();\r
280                 partCleaner.SetInput(partGrid);\r
281                 if(mergePoints) {\r
282                   partCleaner.PointMergingOn();\r
283                 } else {\r
284                   partCleaner.PointMergingOff();\r
285                 }\r
286             }\r
287             \r
288             if (computeNormals)\r
289             {\r
290                 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();\r
291              \r
292                 if (cleanPart)\r
293                 {\r
294                         vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
295                     partNormals.SetInputConnection(out);\r
296                     out.Delete();\r
297                 }\r
298                 else partNormals.SetInput(partGrid);\r
299                     \r
300                 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called\r
301                 vtkAlgorithmOutput out = partNormals.GetOutputPort();\r
302                 partMapper.SetInputConnection(out);\r
303                 out.Delete();\r
304                 partNormals.Delete();          \r
305             }\r
306             else\r
307             {\r
308                 if (cleanPart) {\r
309                         vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
310                         partMapper.SetInputConnection(out); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
311                         out.Delete();\r
312                 }\r
313                 else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
314             }\r
315             partMapper.ScalarVisibilityOn();\r
316             \r
317             vtkActor partActor = new vtkActor();\r
318            // partActor.SetPickable(1);\r
319             vtkProperty prop = partActor.GetProperty();\r
320             prop.SetColor(1, 1, 0);\r
321             prop.Delete();\r
322             partActor.SetMapper(partMapper);\r
323             \r
324             partMapper.Delete();\r
325             \r
326             if (cleanPart)\r
327                 partCleaner.Delete();\r
328             \r
329             return partActor;\r
330         }\r
331         \r
332         public static vtkActor createEdgesActor(vtkPolyData partGrid) {\r
333                 vtkCleanPolyData partCleaner = null;       \r
334            \r
335                 if (cleanPart)\r
336             {\r
337                         partCleaner = new vtkCleanPolyData();\r
338                 partCleaner.SetInput(partGrid);\r
339                 if(mergePoints) {\r
340                   partCleaner.PointMergingOn();\r
341                 } else {\r
342                   partCleaner.PointMergingOff();\r
343                 }\r
344             }\r
345             \r
346                 vtkFeatureEdges partEdges = new vtkFeatureEdges();\r
347             if (cleanPart) {\r
348                 vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
349                 partEdges.SetInputConnection(out);\r
350                 out.Delete();\r
351             }\r
352             else partEdges.SetInput(partGrid); \r
353            // partEdges.SetFeatureAngle(featureAngle);  // this do not have to be neccesarily called\r
354             partEdges.FeatureEdgesOn();\r
355             partEdges.BoundaryEdgesOn();\r
356             partEdges.NonManifoldEdgesOn();\r
357             partEdges.ManifoldEdgesOn();\r
358         \r
359             vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();\r
360             vtkAlgorithmOutput out = partEdges.GetOutputPort();\r
361             partEdgesMapper.SetInputConnection(out);\r
362             out.Delete();\r
363             partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();\r
364             partEdgesMapper.ScalarVisibilityOff();\r
365             \r
366             vtkActor partEdgesActor = new vtkActor();\r
367            \r
368             vtkProperty prop = partEdgesActor.GetProperty();\r
369             prop.SetColor(0, 0, 0);\r
370             prop.SetLineWidth(2.0);\r
371             prop.Delete();\r
372             partEdgesActor.SetMapper(partEdgesMapper);\r
373 \r
374             partEdgesMapper.Delete();\r
375             partEdges.Delete();\r
376             \r
377             if (cleanPart)\r
378                 partCleaner.Delete();\r
379             \r
380             return partEdgesActor;\r
381         }\r
382         \r
383         public static vtkActor createVerticesActor(vtkActor partEdgesActor) {\r
384                 vtkDataSetMapper partEdgesMapper = (vtkDataSetMapper) partEdgesActor.GetMapper();\r
385                 vtkAlgorithmOutput out = partEdgesMapper.GetInputConnection(0, 0);\r
386                 vtkFeatureEdges partEdges = (vtkFeatureEdges)out.GetProducer();\r
387                 \r
388                 vtkActor edgePointsActor = createVerticesActor(partEdges);\r
389                 \r
390                 partEdges.Delete();\r
391                 //out.Delete();\r
392                 partEdgesMapper.Delete();\r
393                 return edgePointsActor;\r
394         }\r
395         \r
396         public static vtkActor createVerticesActor(vtkFeatureEdges partEdges) {\r
397                 EdgePointsFilter edgePoints = new EdgePointsFilter();\r
398         \r
399          \r
400         vtkAlgorithmOutput out = partEdges.GetOutputPort();\r
401             edgePoints.SetInputConnection(out);\r
402             out.Delete();\r
403             \r
404             vtkSphereSource sphereSource = new vtkSphereSource();\r
405             vtkGlyph3D glyph3D = new vtkGlyph3D();\r
406             out = sphereSource.GetOutputPort();\r
407             glyph3D.SetSourceConnection(out);\r
408             out.Delete();\r
409             \r
410             out = edgePoints.GetOutputPort();\r
411             glyph3D.SetInputConnection(out);\r
412             out.Delete();\r
413             \r
414             glyph3D.SetScaleFactor(0.03);\r
415             \r
416             glyph3D.Update();\r
417             \r
418             vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();\r
419             out = glyph3D.GetOutputPort();\r
420             partEdgePointsMapper.SetInputConnection(out);\r
421             out.Delete();\r
422             \r
423             vtkActor edgePointsActor = new vtkActor();\r
424            \r
425             vtkProperty prop = edgePointsActor.GetProperty();\r
426             prop.SetColor(0, 0, 1);\r
427             prop.Delete();\r
428             edgePointsActor.SetMapper(partEdgePointsMapper);\r
429            \r
430             edgePointsActor.PickableOn();\r
431 \r
432             \r
433             partEdgePointsMapper.Delete();\r
434             edgePoints.Delete();\r
435             sphereSource.Delete();\r
436             \r
437             return edgePointsActor;\r
438         }\r
439         \r
440         public static vtkActor createSilhouette(vtkRenderer ren, vtkPolyData data) {\r
441                 \r
442                 \r
443                 vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();\r
444                 \r
445                 silhouette.SetInput(data);\r
446                 silhouette.SetCamera(ren.GetActiveCamera());\r
447                 silhouette.SetEnableFeatureAngle(0);\r
448                 vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
449                 \r
450                 mapper.SetInputConnection(silhouette.GetOutputPort());\r
451                 \r
452                 vtkActor actor = new vtkActor();\r
453                 actor.SetMapper(mapper);\r
454                 \r
455                 actor.GetProperty().SetColor(0,0,1);\r
456                 actor.GetProperty().SetLineWidth(6);\r
457                 \r
458                 return actor;\r
459                 \r
460                 \r
461                 \r
462         }\r
463 \r
464 }\r