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.opencascade.OCCTTool;
24 import org.simantics.utils.datastructures.Pair;
25 import org.simantics.utils.threads.AWTThread;
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;
35 import vtk.vtkPolyData;
36 import vtk.vtkPolyDataMapper;
37 import vtk.vtkPolyDataNormals;
38 import vtk.vtkPolyDataSilhouette;
40 import vtk.vtkProperty;
41 import vtk.vtkRenderer;
42 import vtk.vtkSphereSource;
44 public class vtkSolidObject {
46 public static double deflection = 0.001;
48 public static double featureAngle = 30;
49 public static boolean computeNormals = true;
50 public static boolean cleanPart = false;
51 public static boolean mergePoints = false;
53 private vtkPanel panel;
54 private TopoDS_Shape shape;
56 private List<vtkProp3D> actors = new ArrayList<vtkProp3D>(2);
58 private List<vtkProp3D> solid = new ArrayList<vtkProp3D>(1);
59 private List<vtkProp3D> edges = new ArrayList<vtkProp3D>(1);
60 private vtkActor silhouette = null;
62 private boolean errors = false;
64 public vtkSolidObject(vtkPanel panel,TopoDS_Shape shape) {
69 public void visualizeSolid(boolean showEdges, boolean showVertices) {
70 visualizeSolid(true, showEdges, showVertices);
73 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices) {
74 visualizeSolid(showFaces, showEdges, showVertices, false);
77 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices, boolean showSilhouette) {
80 Pair<vtkPolyData, Boolean> res = createSolidMesh(shape);
85 vtkPolyData data = res.first;
89 solid.add(createActor(data));
92 vtkActor edge = createEdgesActor(data);
95 actors.add(createVerticesActor(edge));
99 silhouette = createSilhouette(panel.GetRenderer(), data);
101 actors.addAll(solid);
102 actors.addAll(edges);
103 if (silhouette != null)
104 actors.add(silhouette);
109 public void visualizeFaces(boolean showEdges, boolean showVertices) {
112 Collection<vtkPolyData> datas = createFaceMeshes(shape);
113 for (vtkPolyData data : datas) {
119 solid.add(createActor(data));
122 vtkActor edgesActor = createEdgesActor(data);
123 edges.add(edgesActor);
125 actors.add(createVerticesActor(edgesActor));
130 actors.addAll(solid);
131 actors.addAll(edges);
136 public boolean hasErrors() {
140 public List<vtkProp3D> getActors() {
141 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
145 public List<vtkProp3D> getSolid() {
146 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
150 public List<vtkProp3D> getEdges() {
151 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
155 public vtkActor getSilhouette() {
156 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
160 public void showActorsAWT() {
161 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
162 vtkRenderer ren = panel.GetRenderer();
163 for (vtkProp3D act : actors) {
168 public void showActors() {
169 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
178 public void clearActorsAWT() {
179 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
180 if (actors.size() == 0)
182 vtkRenderer ren = panel.GetRenderer();
186 for (vtkProp3D act : actors) {
187 if (act.GetVTKId() != 0) {
188 ren.RemoveActor(act);
198 private void clearActorsAWT(List<vtkProp3D> actors) {
199 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
201 if (actors.size() == 0)
203 vtkRenderer ren = panel.GetRenderer();
207 for (vtkProp3D act : actors) {
208 if (act.GetVTKId() != 0) {
209 ren.RemoveActor(act);
216 public void clearActors() {
217 if (actors.size() == 0)
219 final List<vtkProp3D> temp = new ArrayList<vtkProp3D>(actors.size());
224 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
228 clearActorsAWT(temp);
233 public void dispose() {
241 public void delete() {
249 private static double TOLERANCE = 0.01;
251 public static Pair<vtkPolyData, Boolean> createSolidMesh(TopoDS_Shape shape) {
253 boolean success = true;
255 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
256 if (volume < TOLERANCE)
259 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
261 TopExp_Explorer expFace = new TopExp_Explorer();
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))
271 if (meshPoints.size() == 0 || meshTriangles.size() == 0)
274 vtkPolyData data = VTKOCCTool.createPartGrid(meshPoints, meshTriangles);
279 return new Pair<vtkPolyData, Boolean>(data, success);
282 public static Collection<vtkPolyData> createFaceMeshes(TopoDS_Shape shape) {
284 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
285 Collection<vtkPolyData> faces = new ArrayList<vtkPolyData>();
287 if (volume > TOLERANCE) {
289 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
291 TopExp_Explorer expFace = new TopExp_Explorer();
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);
310 public static vtkActor createActor(vtkPolyData partGrid) {
313 vtkDataSetMapper partMapper = new vtkDataSetMapper();
315 vtkCleanPolyData partCleaner = null;
318 partCleaner = new vtkCleanPolyData();
319 partCleaner.SetInputData(partGrid);
321 partCleaner.PointMergingOn();
323 partCleaner.PointMergingOff();
329 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
333 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
334 partNormals.SetInputConnection(out);
337 else partNormals.SetInputData(partGrid);
339 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
340 vtkAlgorithmOutput out = partNormals.GetOutputPort();
341 partMapper.SetInputConnection(out);
343 partNormals.Delete();
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
352 else partMapper.SetInputData(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
354 partMapper.ScalarVisibilityOn();
356 vtkActor partActor = new vtkActor();
357 // partActor.SetPickable(1);
358 vtkProperty prop = partActor.GetProperty();
359 prop.SetColor(1, 1, 0);
361 partActor.SetMapper(partMapper);
366 partCleaner.Delete();
371 public static vtkActor createEdgesActor(vtkPolyData partGrid) {
372 vtkCleanPolyData partCleaner = null;
376 partCleaner = new vtkCleanPolyData();
377 partCleaner.SetInputData(partGrid);
379 partCleaner.PointMergingOn();
381 partCleaner.PointMergingOff();
385 vtkFeatureEdges partEdges = new vtkFeatureEdges();
387 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
388 partEdges.SetInputConnection(out);
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();
398 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
399 vtkAlgorithmOutput out = partEdges.GetOutputPort();
400 partEdgesMapper.SetInputConnection(out);
402 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
403 partEdgesMapper.ScalarVisibilityOff();
405 vtkActor partEdgesActor = new vtkActor();
407 vtkProperty prop = partEdgesActor.GetProperty();
408 prop.SetColor(0, 0, 0);
409 prop.SetLineWidth(2.0);
411 partEdgesActor.SetMapper(partEdgesMapper);
413 partEdgesMapper.Delete();
417 partCleaner.Delete();
419 return partEdgesActor;
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();
427 vtkActor edgePointsActor = createVerticesActor(partEdges);
431 partEdgesMapper.Delete();
432 return edgePointsActor;
435 public static vtkActor createVerticesActor(vtkFeatureEdges partEdges) {
436 EdgePointsFilter edgePoints = new EdgePointsFilter();
439 vtkAlgorithmOutput out = partEdges.GetOutputPort();
440 edgePoints.SetInputConnection(out);
443 vtkSphereSource sphereSource = new vtkSphereSource();
444 vtkGlyph3D glyph3D = new vtkGlyph3D();
445 out = sphereSource.GetOutputPort();
446 glyph3D.SetSourceConnection(out);
449 out = edgePoints.GetOutputPort();
450 glyph3D.SetInputConnection(out);
453 glyph3D.SetScaleFactor(0.03);
457 vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
458 out = glyph3D.GetOutputPort();
459 partEdgePointsMapper.SetInputConnection(out);
462 vtkActor edgePointsActor = new vtkActor();
464 vtkProperty prop = edgePointsActor.GetProperty();
465 prop.SetColor(0, 0, 1);
467 edgePointsActor.SetMapper(partEdgePointsMapper);
469 edgePointsActor.PickableOn();
472 partEdgePointsMapper.Delete();
474 sphereSource.Delete();
476 return edgePointsActor;
479 public static vtkActor createSilhouette(vtkRenderer ren, vtkPolyData data) {
482 vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();
484 silhouette.SetInputData(data);
485 silhouette.SetCamera(ren.GetActiveCamera());
486 silhouette.SetEnableFeatureAngle(0);
487 vtkPolyDataMapper mapper = new vtkPolyDataMapper();
489 mapper.SetInputConnection(silhouette.GetOutputPort());
491 vtkActor actor = new vtkActor();
492 actor.SetMapper(mapper);
494 actor.GetProperty().SetColor(0,0,1);
495 actor.GetProperty().SetLineWidth(6);