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