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