1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.opencascade.vtk;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.List;
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;
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;
39 import vtk.vtkProperty;
40 import vtk.vtkRenderer;
41 import vtk.vtkSphereSource;
43 public class vtkSolidObject {
45 public static double deflection = 0.001;
47 public static double featureAngle = 30;
48 public static boolean computeNormals = true;
49 public static boolean cleanPart = false;
50 public static boolean mergePoints = false;
52 private VtkView panel;
53 private TopoDS_Shape shape;
55 private List<vtkProp3D> actors = new ArrayList<vtkProp3D>(2);
57 private List<vtkProp3D> solid = new ArrayList<vtkProp3D>(1);
58 private List<vtkProp3D> edges = new ArrayList<vtkProp3D>(1);
59 private vtkActor silhouette = null;
61 private boolean errors = false;
63 public vtkSolidObject(VtkView panel,TopoDS_Shape shape) {
68 public void visualizeSolid(boolean showEdges, boolean showVertices) {
69 visualizeSolid(true, showEdges, showVertices);
72 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices) {
73 visualizeSolid(showFaces, showEdges, showVertices, false);
76 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices, boolean showSilhouette) {
79 Pair<vtkPolyData, Boolean> res = createSolidMesh(shape);
84 vtkPolyData data = res.first;
88 solid.add(createActor(data));
91 vtkActor edge = createEdgesActor(data);
94 actors.add(createVerticesActor(edge));
98 silhouette = createSilhouette(panel.getRenderer(), data);
100 actors.addAll(solid);
101 actors.addAll(edges);
102 if (silhouette != null)
103 actors.add(silhouette);
108 public void visualizeFaces(boolean showEdges, boolean showVertices) {
111 Collection<vtkPolyData> datas = createFaceMeshes(shape);
112 for (vtkPolyData data : datas) {
118 solid.add(createActor(data));
121 vtkActor edgesActor = createEdgesActor(data);
122 edges.add(edgesActor);
124 actors.add(createVerticesActor(edgesActor));
129 actors.addAll(solid);
130 actors.addAll(edges);
135 public boolean hasErrors() {
139 public List<vtkProp3D> getActors() {
140 assert (Thread.currentThread() == panel.getThreadQueue().getThread());
144 public List<vtkProp3D> getSolid() {
145 assert (Thread.currentThread() == panel.getThreadQueue().getThread());
149 public List<vtkProp3D> getEdges() {
150 assert (Thread.currentThread() == panel.getThreadQueue().getThread());
154 public vtkActor getSilhouette() {
155 assert (Thread.currentThread() == panel.getThreadQueue().getThread());
159 public void showActorsVTK() {
160 assert (Thread.currentThread() == panel.getThreadQueue().getThread());
162 vtkRenderer ren = panel.getRenderer();
163 for (vtkProp3D act : actors) {
169 public void showActors() {
170 ThreadUtils.asyncExec(panel.getThreadQueue(), new Runnable() {
179 public void clearActorsVTK() {
180 assert (Thread.currentThread() == panel.getThreadQueue().getThread());
181 if (actors.size() == 0)
183 vtkRenderer ren = panel.getRenderer();
187 for (vtkProp3D act : actors) {
188 if (act.GetVTKId() != 0) {
189 ren.RemoveActor(act);
199 private void clearActorsAWT(List<vtkProp3D> actors) {
200 assert (Thread.currentThread() == panel.getThreadQueue().getThread());
202 if (actors.size() == 0)
204 vtkRenderer ren = panel.getRenderer();
208 for (vtkProp3D act : actors) {
209 if (act.GetVTKId() != 0) {
210 ren.RemoveActor(act);
217 public void clearActors() {
218 if (actors.size() == 0)
220 final List<vtkProp3D> temp = new ArrayList<vtkProp3D>(actors.size());
225 ThreadUtils.asyncExec(panel.getThreadQueue(), new Runnable() {
229 clearActorsAWT(temp);
234 public void dispose() {
242 public void delete() {
250 private static double TOLERANCE = 0.01;
252 public static Pair<vtkPolyData, Boolean> createSolidMesh(TopoDS_Shape shape) {
254 boolean success = true;
256 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
257 if (volume < TOLERANCE)
260 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
262 TopExp_Explorer expFace = new TopExp_Explorer();
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))
272 if (meshPoints.size() == 0 || meshTriangles.size() == 0)
275 vtkPolyData data = VTKOCCTool.createPartGrid(meshPoints, meshTriangles);
280 return new Pair<vtkPolyData, Boolean>(data, success);
283 public static Collection<vtkPolyData> createFaceMeshes(TopoDS_Shape shape) {
285 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
286 Collection<vtkPolyData> faces = new ArrayList<vtkPolyData>();
288 if (volume > TOLERANCE) {
290 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
292 TopExp_Explorer expFace = new TopExp_Explorer();
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);
311 public static vtkActor createActor(vtkPolyData partGrid) {
314 vtkDataSetMapper partMapper = new vtkDataSetMapper();
316 vtkCleanPolyData partCleaner = null;
319 partCleaner = new vtkCleanPolyData();
320 partCleaner.SetInputData(partGrid);
322 partCleaner.PointMergingOn();
324 partCleaner.PointMergingOff();
330 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
334 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
335 partNormals.SetInputConnection(out);
338 else partNormals.SetInputData(partGrid);
340 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
341 vtkAlgorithmOutput out = partNormals.GetOutputPort();
342 partMapper.SetInputConnection(out);
344 partNormals.Delete();
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
353 else partMapper.SetInputData(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
355 partMapper.ScalarVisibilityOn();
357 vtkActor partActor = new vtkActor();
358 // partActor.SetPickable(1);
359 vtkProperty prop = partActor.GetProperty();
360 prop.SetColor(1, 1, 0);
362 partActor.SetMapper(partMapper);
367 partCleaner.Delete();
372 public static vtkActor createEdgesActor(vtkPolyData partGrid) {
373 vtkCleanPolyData partCleaner = null;
377 partCleaner = new vtkCleanPolyData();
378 partCleaner.SetInputData(partGrid);
380 partCleaner.PointMergingOn();
382 partCleaner.PointMergingOff();
386 vtkFeatureEdges partEdges = new vtkFeatureEdges();
388 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
389 partEdges.SetInputConnection(out);
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();
399 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
400 vtkAlgorithmOutput out = partEdges.GetOutputPort();
401 partEdgesMapper.SetInputConnection(out);
403 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
404 partEdgesMapper.ScalarVisibilityOff();
406 vtkActor partEdgesActor = new vtkActor();
408 vtkProperty prop = partEdgesActor.GetProperty();
409 prop.SetColor(0, 0, 0);
410 prop.SetLineWidth(2.0);
412 partEdgesActor.SetMapper(partEdgesMapper);
414 partEdgesMapper.Delete();
418 partCleaner.Delete();
420 return partEdgesActor;
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();
428 vtkActor edgePointsActor = createVerticesActor(partEdges);
432 partEdgesMapper.Delete();
433 return edgePointsActor;
436 public static vtkActor createVerticesActor(vtkFeatureEdges partEdges) {
437 EdgePointsFilter edgePoints = new EdgePointsFilter();
440 vtkAlgorithmOutput out = partEdges.GetOutputPort();
441 edgePoints.SetInputConnection(out);
444 vtkSphereSource sphereSource = new vtkSphereSource();
445 vtkGlyph3D glyph3D = new vtkGlyph3D();
446 out = sphereSource.GetOutputPort();
447 glyph3D.SetSourceConnection(out);
450 out = edgePoints.GetOutputPort();
451 glyph3D.SetInputConnection(out);
454 glyph3D.SetScaleFactor(0.03);
458 vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
459 out = glyph3D.GetOutputPort();
460 partEdgePointsMapper.SetInputConnection(out);
463 vtkActor edgePointsActor = new vtkActor();
465 vtkProperty prop = edgePointsActor.GetProperty();
466 prop.SetColor(0, 0, 1);
468 edgePointsActor.SetMapper(partEdgePointsMapper);
470 edgePointsActor.PickableOn();
473 partEdgePointsMapper.Delete();
475 sphereSource.Delete();
477 return edgePointsActor;
480 public static vtkActor createSilhouette(vtkRenderer ren, vtkPolyData data) {
483 vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();
485 silhouette.SetInputData(data);
486 silhouette.SetCamera(ren.GetActiveCamera());
487 silhouette.SetEnableFeatureAngle(0);
488 vtkPolyDataMapper mapper = new vtkPolyDataMapper();
490 mapper.SetInputConnection(silhouette.GetOutputPort());
492 vtkActor actor = new vtkActor();
493 actor.SetMapper(mapper);
495 actor.GetProperty().SetColor(0,0,1);
496 actor.GetProperty().SetLineWidth(6);