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