1 /*******************************************************************************
\r
2 * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.opencascade.vtk;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Collection;
\r
16 import java.util.List;
\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
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
43 public class vtkSolidObject {
\r
45 public static double deflection = 0.001;
\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
52 private vtkPanel panel;
\r
53 private TopoDS_Shape shape;
\r
55 private List<vtkProp3D> actors = new ArrayList<vtkProp3D>(2);
\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
61 public vtkSolidObject(vtkPanel panel,TopoDS_Shape shape) {
\r
66 public void visualizeSolid(boolean showEdges, boolean showVertices) {
\r
67 visualizeSolid(true, showEdges, showVertices);
\r
70 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices) {
\r
71 visualizeSolid(showFaces, showEdges, showVertices, false);
\r
74 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices, boolean showSilhouette) {
\r
76 vtkPolyData data = createSolidMesh(shape);
\r
80 solid.add(createActor(data));
\r
83 vtkActor edge = createEdgesActor(data);
\r
86 actors.add(createVerticesActor(edge));
\r
89 if (showSilhouette) {
\r
90 silhouette = createSilhouette(panel.GetRenderer(), data);
\r
92 actors.addAll(solid);
\r
93 actors.addAll(edges);
\r
94 if (silhouette != null)
\r
95 actors.add(silhouette);
\r
100 public void visualizeFaces(boolean showEdges, boolean showVertices) {
\r
102 Collection<vtkPolyData> datas = createFaceMeshes(shape);
\r
103 for (vtkPolyData data : datas) {
\r
104 solid.add(createActor(data));
\r
107 vtkActor edgesActor = createEdgesActor(data);
\r
108 edges.add(edgesActor);
\r
109 if (showVertices) {
\r
110 actors.add(createVerticesActor(edgesActor));
\r
115 actors.addAll(solid);
\r
116 actors.addAll(edges);
\r
121 public List<vtkProp3D> getActors() {
\r
122 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
126 public List<vtkProp3D> getSolid() {
\r
127 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
131 public List<vtkProp3D> getEdges() {
\r
132 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
136 public vtkActor getSilhouette() {
\r
137 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\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
149 public void showActors() {
\r
150 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
\r
153 public void run() {
\r
159 public void clearActorsAWT() {
\r
160 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
161 if (actors.size() == 0)
\r
163 vtkRenderer ren = panel.GetRenderer();
\r
164 for (vtkProp3D act : actors) {
\r
165 if (act.GetVTKId() != 0) {
\r
166 ren.RemoveActor(act);
\r
175 private void clearActorsAWT(List<vtkProp3D> actors) {
\r
176 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
178 if (actors.size() == 0)
\r
180 vtkRenderer ren = panel.GetRenderer();
\r
182 for (vtkProp3D act : actors) {
\r
183 if (act.GetVTKId() != 0) {
\r
184 ren.RemoveActor(act);
\r
191 public void clearActors() {
\r
192 if (actors.size() == 0)
\r
194 final List<vtkProp3D> temp = new ArrayList<vtkProp3D>(actors.size());
\r
195 temp.addAll(actors);
\r
199 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
\r
202 public void run() {
\r
203 clearActorsAWT(temp);
\r
208 public void dispose() {
\r
209 if (shape != null) {
\r
216 public void delete() {
\r
217 if (shape != null) {
\r
224 private static double TOLERANCE = 0.01;
\r
226 public static vtkPolyData createSolidMesh(TopoDS_Shape shape) {
\r
228 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
\r
229 if (volume < TOLERANCE)
\r
232 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
\r
234 TopExp_Explorer expFace = new TopExp_Explorer();
\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
243 if (meshPoints.size() == 0 || meshTriangles.size() == 0)
\r
246 vtkPolyData data = VTKOCCTool.createPartGrid(meshPoints, meshTriangles);
\r
254 public static Collection<vtkPolyData> createFaceMeshes(TopoDS_Shape shape) {
\r
256 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
\r
257 Collection<vtkPolyData> faces = new ArrayList<vtkPolyData>();
\r
259 if (volume > TOLERANCE) {
\r
261 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
\r
263 TopExp_Explorer expFace = new TopExp_Explorer();
\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
282 public static vtkActor createActor(vtkPolyData partGrid) {
\r
285 vtkDataSetMapper partMapper = new vtkDataSetMapper();
\r
287 vtkCleanPolyData partCleaner = null;
\r
290 partCleaner = new vtkCleanPolyData();
\r
291 partCleaner.SetInput(partGrid);
\r
293 partCleaner.PointMergingOn();
\r
295 partCleaner.PointMergingOff();
\r
299 if (computeNormals)
\r
301 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
\r
305 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
306 partNormals.SetInputConnection(out);
\r
309 else partNormals.SetInput(partGrid);
\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
315 partNormals.Delete();
\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
324 else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
\r
326 partMapper.ScalarVisibilityOn();
\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
333 partActor.SetMapper(partMapper);
\r
335 partMapper.Delete();
\r
338 partCleaner.Delete();
\r
343 public static vtkActor createEdgesActor(vtkPolyData partGrid) {
\r
344 vtkCleanPolyData partCleaner = null;
\r
348 partCleaner = new vtkCleanPolyData();
\r
349 partCleaner.SetInput(partGrid);
\r
351 partCleaner.PointMergingOn();
\r
353 partCleaner.PointMergingOff();
\r
357 vtkFeatureEdges partEdges = new vtkFeatureEdges();
\r
359 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
360 partEdges.SetInputConnection(out);
\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
370 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
\r
371 vtkAlgorithmOutput out = partEdges.GetOutputPort();
\r
372 partEdgesMapper.SetInputConnection(out);
\r
374 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
\r
375 partEdgesMapper.ScalarVisibilityOff();
\r
377 vtkActor partEdgesActor = new vtkActor();
\r
379 vtkProperty prop = partEdgesActor.GetProperty();
\r
380 prop.SetColor(0, 0, 0);
\r
381 prop.SetLineWidth(2.0);
\r
383 partEdgesActor.SetMapper(partEdgesMapper);
\r
385 partEdgesMapper.Delete();
\r
386 partEdges.Delete();
\r
389 partCleaner.Delete();
\r
391 return partEdgesActor;
\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
399 vtkActor edgePointsActor = createVerticesActor(partEdges);
\r
401 partEdges.Delete();
\r
403 partEdgesMapper.Delete();
\r
404 return edgePointsActor;
\r
407 public static vtkActor createVerticesActor(vtkFeatureEdges partEdges) {
\r
408 EdgePointsFilter edgePoints = new EdgePointsFilter();
\r
411 vtkAlgorithmOutput out = partEdges.GetOutputPort();
\r
412 edgePoints.SetInputConnection(out);
\r
415 vtkSphereSource sphereSource = new vtkSphereSource();
\r
416 vtkGlyph3D glyph3D = new vtkGlyph3D();
\r
417 out = sphereSource.GetOutputPort();
\r
418 glyph3D.SetSourceConnection(out);
\r
421 out = edgePoints.GetOutputPort();
\r
422 glyph3D.SetInputConnection(out);
\r
425 glyph3D.SetScaleFactor(0.03);
\r
429 vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
\r
430 out = glyph3D.GetOutputPort();
\r
431 partEdgePointsMapper.SetInputConnection(out);
\r
434 vtkActor edgePointsActor = new vtkActor();
\r
436 vtkProperty prop = edgePointsActor.GetProperty();
\r
437 prop.SetColor(0, 0, 1);
\r
439 edgePointsActor.SetMapper(partEdgePointsMapper);
\r
441 edgePointsActor.PickableOn();
\r
444 partEdgePointsMapper.Delete();
\r
445 edgePoints.Delete();
\r
446 sphereSource.Delete();
\r
448 return edgePointsActor;
\r
451 public static vtkActor createSilhouette(vtkRenderer ren, vtkPolyData data) {
\r
454 vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();
\r
456 silhouette.SetInput(data);
\r
457 silhouette.SetCamera(ren.GetActiveCamera());
\r
458 silhouette.SetEnableFeatureAngle(0);
\r
459 vtkPolyDataMapper mapper = new vtkPolyDataMapper();
\r
461 mapper.SetInputConnection(silhouette.GetOutputPort());
\r
463 vtkActor actor = new vtkActor();
\r
464 actor.SetMapper(mapper);
\r
466 actor.GetProperty().SetColor(0,0,1);
\r
467 actor.GetProperty().SetLineWidth(6);
\r