]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.opencascade.vtk/src/org/simantics/opencascade/vtk/vtkSolidObject.java
Created Mesh API for Plant3D objects
[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                 if (ren == null)
184                         return;
185                 panel.lock();
186                 for (vtkProp3D act : actors) {
187                         if (act.GetVTKId() != 0) {
188                                 ren.RemoveActor(act);
189                                 act.Delete();
190                         }
191                 }
192                 panel.unlock();
193                 actors.clear();
194                 solid.clear();
195                 edges.clear();
196         }
197         
198         private void clearActorsAWT(List<vtkProp3D> actors) {
199                 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
200                 
201                 if (actors.size() == 0)
202                         return;
203                 vtkRenderer ren = panel.GetRenderer();
204                 if (ren == null)
205                         return;
206                 panel.lock();
207                 for (vtkProp3D act : actors) {
208                         if (act.GetVTKId() != 0) {
209                                 ren.RemoveActor(act);
210                                 act.Delete();
211                         }
212                 }
213                 panel.unlock();
214         }
215         
216         public void clearActors() {
217                 if (actors.size() == 0)
218                         return;
219                 final List<vtkProp3D> temp = new ArrayList<vtkProp3D>(actors.size());
220                 temp.addAll(actors);
221                 actors.clear();
222                 solid.clear();
223                 edges.clear();
224                 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
225                         
226                         @Override
227                         public void run() {
228                                 clearActorsAWT(temp);
229                         }
230                 });
231         }
232         
233         public void dispose() {
234                 if (shape != null) {
235                         shape.delete();
236                         shape = null;
237                 }
238                 clearActors();
239         }
240         
241         public void delete() {
242                 if (shape != null) {
243                         shape.delete();
244                         shape = null;
245                 }
246                 clearActorsAWT();
247         }
248         
249         private static double TOLERANCE = 0.01;
250         
251         public static Pair<vtkPolyData, Boolean> createSolidMesh(TopoDS_Shape shape) {
252                 
253                 boolean success = true;
254                 
255                 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
256                 if (volume < TOLERANCE)
257                         return null;
258                 
259                 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
260         
261                 TopExp_Explorer expFace = new TopExp_Explorer();
262                 
263                 List<Double> meshPoints = new ArrayList<Double>();
264                 List<Integer> meshTriangles = new ArrayList<Integer>();
265                 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
266                         TopoDS_Face face = (TopoDS_Face) expFace.current();
267                         if (!OCCTTool.appendToMesh(face, meshPoints, meshTriangles))
268                                 success = false;
269                         face.delete();
270                 }
271                 if (meshPoints.size() == 0 || meshTriangles.size() == 0)
272                         return null;
273                         
274                 vtkPolyData data = VTKOCCTool.createPartGrid(meshPoints, meshTriangles);
275                 
276                 expFace.delete();
277                 mesh.delete();
278                 
279                 return new Pair<vtkPolyData, Boolean>(data, success);
280         }
281         
282         public static Collection<vtkPolyData> createFaceMeshes(TopoDS_Shape shape) {
283                 
284                 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
285                 Collection<vtkPolyData> faces = new ArrayList<vtkPolyData>();
286                 
287                 if (volume > TOLERANCE) {
288                 
289                         BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
290                 
291                         TopExp_Explorer expFace = new TopExp_Explorer();
292                         
293                         
294                         for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
295                                 TopoDS_Face face = (TopoDS_Face) expFace.current();
296                                 vtkPolyData data = VTKOCCTool.createPartGrid(face);
297                                 face.delete();
298                                 faces.add(data);
299                         }
300                         
301                         expFace.delete();
302                         mesh.delete();
303                 }
304                 
305                 return faces;
306         }
307         
308         
309         
310         public static vtkActor createActor(vtkPolyData partGrid) {
311                 
312                 
313             vtkDataSetMapper partMapper = new vtkDataSetMapper();
314             
315             vtkCleanPolyData partCleaner = null;       
316             if (cleanPart)
317             {
318                 partCleaner = new vtkCleanPolyData();
319                 partCleaner.SetInputData(partGrid);
320                 if(mergePoints) {
321                   partCleaner.PointMergingOn();
322                 } else {
323                   partCleaner.PointMergingOff();
324                 }
325             }
326             
327             if (computeNormals)
328             {
329                 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
330              
331                 if (cleanPart)
332                 {
333                         vtkAlgorithmOutput out = partCleaner.GetOutputPort();
334                     partNormals.SetInputConnection(out);
335                     out.Delete();
336                 }
337                 else partNormals.SetInputData(partGrid);
338                     
339                 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
340                 vtkAlgorithmOutput out = partNormals.GetOutputPort();
341                 partMapper.SetInputConnection(out);
342                 out.Delete();
343                 partNormals.Delete();          
344             }
345             else
346             {
347                 if (cleanPart) {
348                         vtkAlgorithmOutput out = partCleaner.GetOutputPort();
349                         partMapper.SetInputConnection(out); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
350                         out.Delete();
351                 }
352                 else partMapper.SetInputData(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
353             }
354             partMapper.ScalarVisibilityOn();
355             
356             vtkActor partActor = new vtkActor();
357            // partActor.SetPickable(1);
358             vtkProperty prop = partActor.GetProperty();
359             prop.SetColor(1, 1, 0);
360             prop.Delete();
361             partActor.SetMapper(partMapper);
362             
363             partMapper.Delete();
364             
365             if (cleanPart)
366                 partCleaner.Delete();
367             
368             return partActor;
369         }
370         
371         public static vtkActor createEdgesActor(vtkPolyData partGrid) {
372                 vtkCleanPolyData partCleaner = null;       
373            
374                 if (cleanPart)
375             {
376                         partCleaner = new vtkCleanPolyData();
377                 partCleaner.SetInputData(partGrid);
378                 if(mergePoints) {
379                   partCleaner.PointMergingOn();
380                 } else {
381                   partCleaner.PointMergingOff();
382                 }
383             }
384             
385                 vtkFeatureEdges partEdges = new vtkFeatureEdges();
386             if (cleanPart) {
387                 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
388                 partEdges.SetInputConnection(out);
389                 out.Delete();
390             }
391             else partEdges.SetInputData(partGrid); 
392            // partEdges.SetFeatureAngle(featureAngle);  // this do not have to be neccesarily called
393             partEdges.FeatureEdgesOn();
394             partEdges.BoundaryEdgesOn();
395             partEdges.NonManifoldEdgesOn();
396             partEdges.ManifoldEdgesOn();
397         
398             vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
399             vtkAlgorithmOutput out = partEdges.GetOutputPort();
400             partEdgesMapper.SetInputConnection(out);
401             out.Delete();
402             partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
403             partEdgesMapper.ScalarVisibilityOff();
404             
405             vtkActor partEdgesActor = new vtkActor();
406            
407             vtkProperty prop = partEdgesActor.GetProperty();
408             prop.SetColor(0, 0, 0);
409             prop.SetLineWidth(2.0);
410             prop.Delete();
411             partEdgesActor.SetMapper(partEdgesMapper);
412
413             partEdgesMapper.Delete();
414             partEdges.Delete();
415             
416             if (cleanPart)
417                 partCleaner.Delete();
418             
419             return partEdgesActor;
420         }
421         
422         public static vtkActor createVerticesActor(vtkActor partEdgesActor) {
423                 vtkDataSetMapper partEdgesMapper = (vtkDataSetMapper) partEdgesActor.GetMapper();
424                 vtkAlgorithmOutput out = partEdgesMapper.GetInputConnection(0, 0);
425                 vtkFeatureEdges partEdges = (vtkFeatureEdges)out.GetProducer();
426                 
427                 vtkActor edgePointsActor = createVerticesActor(partEdges);
428                 
429                 partEdges.Delete();
430                 //out.Delete();
431                 partEdgesMapper.Delete();
432                 return edgePointsActor;
433         }
434         
435         public static vtkActor createVerticesActor(vtkFeatureEdges partEdges) {
436                 EdgePointsFilter edgePoints = new EdgePointsFilter();
437         
438          
439         vtkAlgorithmOutput out = partEdges.GetOutputPort();
440             edgePoints.SetInputConnection(out);
441             out.Delete();
442             
443             vtkSphereSource sphereSource = new vtkSphereSource();
444             vtkGlyph3D glyph3D = new vtkGlyph3D();
445             out = sphereSource.GetOutputPort();
446             glyph3D.SetSourceConnection(out);
447             out.Delete();
448             
449             out = edgePoints.GetOutputPort();
450             glyph3D.SetInputConnection(out);
451             out.Delete();
452             
453             glyph3D.SetScaleFactor(0.03);
454             
455             glyph3D.Update();
456             
457             vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
458             out = glyph3D.GetOutputPort();
459             partEdgePointsMapper.SetInputConnection(out);
460             out.Delete();
461             
462             vtkActor edgePointsActor = new vtkActor();
463            
464             vtkProperty prop = edgePointsActor.GetProperty();
465             prop.SetColor(0, 0, 1);
466             prop.Delete();
467             edgePointsActor.SetMapper(partEdgePointsMapper);
468            
469             edgePointsActor.PickableOn();
470
471             
472             partEdgePointsMapper.Delete();
473             edgePoints.Delete();
474             sphereSource.Delete();
475             
476             return edgePointsActor;
477         }
478         
479         public static vtkActor createSilhouette(vtkRenderer ren, vtkPolyData data) {
480                 
481                 
482                 vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();
483                 
484                 silhouette.SetInputData(data);
485                 silhouette.SetCamera(ren.GetActiveCamera());
486                 silhouette.SetEnableFeatureAngle(0);
487                 vtkPolyDataMapper mapper = new vtkPolyDataMapper();
488                 
489                 mapper.SetInputConnection(silhouette.GetOutputPort());
490                 
491                 vtkActor actor = new vtkActor();
492                 actor.SetMapper(mapper);
493                 
494                 actor.GetProperty().SetColor(0,0,1);
495                 actor.GetProperty().SetLineWidth(6);
496                 
497                 return actor;
498                 
499                 
500                 
501         }
502
503 }