1 package org.simantics.opencascade.vtk;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Collection;
\r
5 import java.util.List;
\r
7 import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;
\r
8 import org.jcae.opencascade.jni.TopAbs_ShapeEnum;
\r
9 import org.jcae.opencascade.jni.TopExp_Explorer;
\r
10 import org.jcae.opencascade.jni.TopoDS_Face;
\r
11 import org.jcae.opencascade.jni.TopoDS_Shape;
\r
12 import org.simantics.opencascade.OCCTTool;
\r
13 import org.simantics.utils.threads.AWTThread;
\r
14 import org.simantics.utils.threads.ThreadUtils;
\r
16 import vtk.vtkActor;
\r
17 import vtk.vtkAlgorithmOutput;
\r
18 import vtk.vtkCleanPolyData;
\r
19 import vtk.vtkDataSetMapper;
\r
20 import vtk.vtkFeatureEdges;
\r
21 import vtk.vtkGlyph3D;
\r
22 import vtk.vtkPanel;
\r
23 import vtk.vtkPolyData;
\r
24 import vtk.vtkPolyDataMapper;
\r
25 import vtk.vtkPolyDataNormals;
\r
26 import vtk.vtkPolyDataSilhouette;
\r
27 import vtk.vtkProp3D;
\r
28 import vtk.vtkProperty;
\r
29 import vtk.vtkRenderer;
\r
30 import vtk.vtkSphereSource;
\r
32 public class vtkSolidObject {
\r
34 public static double deflection = 0.001;
\r
36 public static double featureAngle = 30;
\r
37 public static boolean computeNormals = true;
\r
38 public static boolean cleanPart = false;
\r
39 public static boolean mergePoints = false;
\r
41 private vtkPanel panel;
\r
42 private TopoDS_Shape shape;
\r
44 private List<vtkProp3D> actors = new ArrayList<vtkProp3D>(2);
\r
46 private List<vtkProp3D> solid = new ArrayList<vtkProp3D>(1);
\r
47 private List<vtkProp3D> edges = new ArrayList<vtkProp3D>(1);
\r
48 private vtkActor silhouette = null;
\r
50 public vtkSolidObject(vtkPanel panel,TopoDS_Shape shape) {
\r
55 public void visualizeSolid(boolean showEdges, boolean showVertices) {
\r
56 visualizeSolid(true, showEdges, showVertices);
\r
59 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices) {
\r
60 visualizeSolid(showFaces, showEdges, showVertices, false);
\r
63 public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices, boolean showSilhouette) {
\r
65 vtkPolyData data = createSolidMesh(shape);
\r
69 solid.add(createActor(data));
\r
72 vtkActor edge = createEdgesActor(data);
\r
75 actors.add(createVerticesActor(edge));
\r
78 if (showSilhouette) {
\r
79 silhouette = createSilhouette(panel.GetRenderer(), data);
\r
81 actors.addAll(solid);
\r
82 actors.addAll(edges);
\r
83 if (silhouette != null)
\r
84 actors.add(silhouette);
\r
89 public void visualizeFaces(boolean showEdges, boolean showVertices) {
\r
91 Collection<vtkPolyData> datas = createFaceMeshes(shape);
\r
92 for (vtkPolyData data : datas) {
\r
93 solid.add(createActor(data));
\r
96 vtkActor edgesActor = createEdgesActor(data);
\r
97 edges.add(edgesActor);
\r
99 actors.add(createVerticesActor(edgesActor));
\r
104 actors.addAll(solid);
\r
105 actors.addAll(edges);
\r
110 public List<vtkProp3D> getActors() {
\r
111 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
115 public List<vtkProp3D> getSolid() {
\r
116 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
120 public List<vtkProp3D> getEdges() {
\r
121 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
125 public vtkActor getSilhouette() {
\r
126 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
130 public void showActorsAWT() {
\r
131 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
132 vtkRenderer ren = panel.GetRenderer();
\r
133 for (vtkProp3D act : actors) {
\r
138 public void showActors() {
\r
139 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
\r
142 public void run() {
\r
148 public void clearActorsAWT() {
\r
149 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
150 if (actors.size() == 0)
\r
152 vtkRenderer ren = panel.GetRenderer();
\r
153 for (vtkProp3D act : actors) {
\r
154 if (act.GetVTKId() != 0) {
\r
155 ren.RemoveActor(act);
\r
164 private void clearActorsAWT(List<vtkProp3D> actors) {
\r
165 assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());
\r
167 if (actors.size() == 0)
\r
169 vtkRenderer ren = panel.GetRenderer();
\r
171 for (vtkProp3D act : actors) {
\r
172 if (act.GetVTKId() != 0) {
\r
173 ren.RemoveActor(act);
\r
180 public void clearActors() {
\r
181 if (actors.size() == 0)
\r
183 final List<vtkProp3D> temp = new ArrayList<vtkProp3D>(actors.size());
\r
184 temp.addAll(actors);
\r
188 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
\r
191 public void run() {
\r
192 clearActorsAWT(temp);
\r
197 public void dispose() {
\r
198 if (shape != null) {
\r
205 public void delete() {
\r
206 if (shape != null) {
\r
213 private static double TOLERANCE = 0.01;
\r
215 public static vtkPolyData createSolidMesh(TopoDS_Shape shape) {
\r
217 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
\r
218 if (volume < TOLERANCE)
\r
221 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
\r
223 TopExp_Explorer expFace = new TopExp_Explorer();
\r
225 List<Double> meshPoints = new ArrayList<Double>();
\r
226 List<Integer> meshTriangles = new ArrayList<Integer>();
\r
227 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
\r
228 TopoDS_Face face = (TopoDS_Face) expFace.current();
\r
229 OCCTTool.appendToMesh(face, meshPoints, meshTriangles);
\r
232 if (meshPoints.size() == 0 || meshTriangles.size() == 0)
\r
235 vtkPolyData data = VTKOCCTool.createPartGrid(meshPoints, meshTriangles);
\r
243 public static Collection<vtkPolyData> createFaceMeshes(TopoDS_Shape shape) {
\r
245 double volume = OCCTTool.getBoundingBoxDiagonal(shape);
\r
246 Collection<vtkPolyData> faces = new ArrayList<vtkPolyData>();
\r
248 if (volume > TOLERANCE) {
\r
250 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);
\r
252 TopExp_Explorer expFace = new TopExp_Explorer();
\r
255 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
\r
256 TopoDS_Face face = (TopoDS_Face) expFace.current();
\r
257 vtkPolyData data = VTKOCCTool.createPartGrid(face);
\r
271 public static vtkActor createActor(vtkPolyData partGrid) {
\r
274 vtkDataSetMapper partMapper = new vtkDataSetMapper();
\r
276 vtkCleanPolyData partCleaner = null;
\r
279 partCleaner = new vtkCleanPolyData();
\r
280 partCleaner.SetInput(partGrid);
\r
282 partCleaner.PointMergingOn();
\r
284 partCleaner.PointMergingOff();
\r
288 if (computeNormals)
\r
290 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
\r
294 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
295 partNormals.SetInputConnection(out);
\r
298 else partNormals.SetInput(partGrid);
\r
300 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
\r
301 vtkAlgorithmOutput out = partNormals.GetOutputPort();
\r
302 partMapper.SetInputConnection(out);
\r
304 partNormals.Delete();
\r
309 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
310 partMapper.SetInputConnection(out); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
\r
313 else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
\r
315 partMapper.ScalarVisibilityOn();
\r
317 vtkActor partActor = new vtkActor();
\r
318 // partActor.SetPickable(1);
\r
319 vtkProperty prop = partActor.GetProperty();
\r
320 prop.SetColor(1, 1, 0);
\r
322 partActor.SetMapper(partMapper);
\r
324 partMapper.Delete();
\r
327 partCleaner.Delete();
\r
332 public static vtkActor createEdgesActor(vtkPolyData partGrid) {
\r
333 vtkCleanPolyData partCleaner = null;
\r
337 partCleaner = new vtkCleanPolyData();
\r
338 partCleaner.SetInput(partGrid);
\r
340 partCleaner.PointMergingOn();
\r
342 partCleaner.PointMergingOff();
\r
346 vtkFeatureEdges partEdges = new vtkFeatureEdges();
\r
348 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
349 partEdges.SetInputConnection(out);
\r
352 else partEdges.SetInput(partGrid);
\r
353 // partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
\r
354 partEdges.FeatureEdgesOn();
\r
355 partEdges.BoundaryEdgesOn();
\r
356 partEdges.NonManifoldEdgesOn();
\r
357 partEdges.ManifoldEdgesOn();
\r
359 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
\r
360 vtkAlgorithmOutput out = partEdges.GetOutputPort();
\r
361 partEdgesMapper.SetInputConnection(out);
\r
363 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
\r
364 partEdgesMapper.ScalarVisibilityOff();
\r
366 vtkActor partEdgesActor = new vtkActor();
\r
368 vtkProperty prop = partEdgesActor.GetProperty();
\r
369 prop.SetColor(0, 0, 0);
\r
370 prop.SetLineWidth(2.0);
\r
372 partEdgesActor.SetMapper(partEdgesMapper);
\r
374 partEdgesMapper.Delete();
\r
375 partEdges.Delete();
\r
378 partCleaner.Delete();
\r
380 return partEdgesActor;
\r
383 public static vtkActor createVerticesActor(vtkActor partEdgesActor) {
\r
384 vtkDataSetMapper partEdgesMapper = (vtkDataSetMapper) partEdgesActor.GetMapper();
\r
385 vtkAlgorithmOutput out = partEdgesMapper.GetInputConnection(0, 0);
\r
386 vtkFeatureEdges partEdges = (vtkFeatureEdges)out.GetProducer();
\r
388 vtkActor edgePointsActor = createVerticesActor(partEdges);
\r
390 partEdges.Delete();
\r
392 partEdgesMapper.Delete();
\r
393 return edgePointsActor;
\r
396 public static vtkActor createVerticesActor(vtkFeatureEdges partEdges) {
\r
397 EdgePointsFilter edgePoints = new EdgePointsFilter();
\r
400 vtkAlgorithmOutput out = partEdges.GetOutputPort();
\r
401 edgePoints.SetInputConnection(out);
\r
404 vtkSphereSource sphereSource = new vtkSphereSource();
\r
405 vtkGlyph3D glyph3D = new vtkGlyph3D();
\r
406 out = sphereSource.GetOutputPort();
\r
407 glyph3D.SetSourceConnection(out);
\r
410 out = edgePoints.GetOutputPort();
\r
411 glyph3D.SetInputConnection(out);
\r
414 glyph3D.SetScaleFactor(0.03);
\r
418 vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
\r
419 out = glyph3D.GetOutputPort();
\r
420 partEdgePointsMapper.SetInputConnection(out);
\r
423 vtkActor edgePointsActor = new vtkActor();
\r
425 vtkProperty prop = edgePointsActor.GetProperty();
\r
426 prop.SetColor(0, 0, 1);
\r
428 edgePointsActor.SetMapper(partEdgePointsMapper);
\r
430 edgePointsActor.PickableOn();
\r
433 partEdgePointsMapper.Delete();
\r
434 edgePoints.Delete();
\r
435 sphereSource.Delete();
\r
437 return edgePointsActor;
\r
440 public static vtkActor createSilhouette(vtkRenderer ren, vtkPolyData data) {
\r
443 vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();
\r
445 silhouette.SetInput(data);
\r
446 silhouette.SetCamera(ren.GetActiveCamera());
\r
447 silhouette.SetEnableFeatureAngle(0);
\r
448 vtkPolyDataMapper mapper = new vtkPolyDataMapper();
\r
450 mapper.SetInputConnection(silhouette.GetOutputPort());
\r
452 vtkActor actor = new vtkActor();
\r
453 actor.SetMapper(mapper);
\r
455 actor.GetProperty().SetColor(0,0,1);
\r
456 actor.GetProperty().SetLineWidth(6);
\r