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