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.List;
16 import javax.vecmath.Matrix4d;
17 import javax.vecmath.Point3d;
19 import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;
20 import org.jcae.opencascade.jni.BRep_Tool;
21 import org.jcae.opencascade.jni.GP_Trsf;
22 import org.jcae.opencascade.jni.Poly_Triangulation;
23 import org.jcae.opencascade.jni.TopAbs_Orientation;
24 import org.jcae.opencascade.jni.TopAbs_ShapeEnum;
25 import org.jcae.opencascade.jni.TopExp_Explorer;
26 import org.jcae.opencascade.jni.TopLoc_Location;
27 import org.jcae.opencascade.jni.TopoDS_Face;
28 import org.jcae.opencascade.jni.TopoDS_Shape;
29 import org.simantics.opencascade.OCCTTool;
32 import vtk.vtkAlgorithmOutput;
33 import vtk.vtkAppendPolyData;
34 import vtk.vtkAssembly;
35 import vtk.vtkCleanPolyData;
36 import vtk.vtkDataSetMapper;
37 import vtk.vtkFeatureEdges;
38 import vtk.vtkGlyph3D;
41 import vtk.vtkPolyData;
42 import vtk.vtkPolyDataMapper;
43 import vtk.vtkPolyDataNormals;
45 import vtk.vtkPropCollection;
46 import vtk.vtkProperty;
47 import vtk.vtkSphereSource;
48 import vtk.vtkTriangle;
50 public class VTKOCCTool {
51 public static vtkAssembly vtkTestAssembly() {
52 vtkAssembly assemblies = new vtkAssembly();
53 vtkPolyData partGrid = createTestPartGrid();
54 gridToAssembly(assemblies, partGrid);
58 public static vtkAssembly vtkOCCShapeToAssembly(TopoDS_Shape shape) {
59 double deflection = 0.001;
61 if (deflection <= 0.0) {
63 System.out.println("Bad value for deflection. Using: " + deflection);
66 // FIXME : leaks memory!
67 //BRepTools.clean(shape);
69 double mass = OCCTTool.getMass(shape);
72 System.out.println("Non 3D-shape detected");
73 System.out.println("The cad import features are currently limited to 3D models.");
76 double length = OCCTTool.getBoundingBoxDiagonal(shape);
77 deflection *= length; // use relative units
79 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection);
82 TopExp_Explorer expFace = new TopExp_Explorer();
84 vtkAssembly assemblies = new vtkAssembly();
85 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
86 TopoDS_Face face = (TopoDS_Face) expFace.current();
87 vtkPolyData partGrid = createPartGrid(face);
92 //gridToAssembly(assemblies, partGrid, stlSurfaceData, stlEdgeData);
93 gridToAssembly(assemblies, partGrid);
99 if (faceNumber == 0) {
101 .println("Cad import: error: no surface triangulation was generated.");
108 @SuppressWarnings("unused")
109 private static void gridToAssembly(vtkAssembly assemblies, vtkPolyData partGrid, vtkAppendPolyData stlSurfaceData, vtkAppendPolyData stlEdgeData) {
111 double featureAngle = 30;
114 vtkDataSetMapper partMapper = new vtkDataSetMapper();
116 boolean computeNormals = true;
117 boolean cleanPart = true;
118 boolean mergePoints = false;
120 vtkCleanPolyData partCleaner = new vtkCleanPolyData();
123 partCleaner.SetInputData(partGrid);
125 partCleaner.PointMergingOn();
127 partCleaner.PointMergingOff();
133 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
137 partNormals.SetInputConnection(partCleaner.GetOutputPort());
139 else partNormals.SetInputData(partGrid);
141 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
142 partMapper.SetInputConnection(partNormals.GetOutputPort());
143 partNormals.Delete();
147 if (cleanPart) partMapper.SetInputConnection(partCleaner.GetOutputPort()); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
148 else partMapper.SetInputData(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
150 partMapper.ScalarVisibilityOn();
152 vtkActor partActor = new vtkActor();
154 partActor.SetPickable(1);
155 partActor.GetProperty().SetColor(1, 1, 0);
156 partActor.SetMapper(partMapper);
158 // EDGES OF PARTS DETECTION
159 vtkFeatureEdges partEdges = new vtkFeatureEdges();
160 if (cleanPart) partEdges.SetInputConnection(partCleaner.GetOutputPort());
161 else partEdges.SetInputData(partGrid);
162 partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
163 partEdges.FeatureEdgesOn();
164 partEdges.BoundaryEdgesOn();
165 partEdges.NonManifoldEdgesOn();
166 partEdges.ManifoldEdgesOn();
168 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
169 partEdgesMapper.SetInputConnection(partEdges.GetOutputPort());
170 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
171 partEdgesMapper.ScalarVisibilityOff();
173 vtkActor partEdgesActor = new vtkActor();
174 partEdgesActor.SetPickable(0);
175 partEdgesActor.GetProperty().SetColor(1, 0, 1);
176 partEdgesActor.SetMapper(partEdgesMapper);
179 // Add triangles and edges to STL structures:
180 //--------------------------------------------
181 if (cleanPart) stlSurfaceData.AddInputData(partCleaner.GetOutput());
182 else stlSurfaceData.AddInputData(partGrid);
183 stlEdgeData.AddInputData(partEdges.GetOutput());
185 assemblies.AddPart(partActor);
186 assemblies.AddPart(partEdgesActor);
190 partEdgesActor.Delete();
191 partEdgesMapper.Delete();
196 partCleaner.Delete();
199 public static void gridToAssembly(vtkAssembly assemblies, vtkPolyData partGrid) {
201 double featureAngle = 30;
204 vtkDataSetMapper partMapper = new vtkDataSetMapper();
206 boolean computeNormals = true;
207 boolean cleanPart = false;
208 boolean mergePoints = false;
210 vtkCleanPolyData partCleaner = new vtkCleanPolyData();
213 partCleaner.SetInputData(partGrid);
215 partCleaner.PointMergingOn();
217 partCleaner.PointMergingOff();
223 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
227 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
228 partNormals.SetInputConnection(out);
231 else partNormals.SetInputData(partGrid);
233 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
234 vtkAlgorithmOutput out = partNormals.GetOutputPort();
235 partMapper.SetInputConnection(out);
237 partNormals.Delete();
242 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
243 partMapper.SetInputConnection(out); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
246 else partMapper.SetInputData(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
248 partMapper.ScalarVisibilityOn();
250 vtkActor partActor = new vtkActor();
251 partActor.SetPickable(1);
252 vtkProperty prop = partActor.GetProperty();
253 prop.SetColor(1, 1, 0);
255 partActor.SetMapper(partMapper);
257 assemblies.AddPart(partActor);
260 // EDGES OF PARTS DETECTION
261 vtkFeatureEdges partEdges = new vtkFeatureEdges();
263 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
264 partEdges.SetInputConnection(out);
267 else partEdges.SetInputData(partGrid);
268 // partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
269 partEdges.FeatureEdgesOn();
270 partEdges.BoundaryEdgesOn();
271 partEdges.NonManifoldEdgesOn();
272 partEdges.ManifoldEdgesOn();
274 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
275 vtkAlgorithmOutput out = partEdges.GetOutputPort();
276 partEdgesMapper.SetInputConnection(out);
278 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
279 partEdgesMapper.ScalarVisibilityOff();
281 vtkActor partEdgesActor = new vtkActor();
283 prop = partEdgesActor.GetProperty();
284 prop.SetColor(0, 0, 0);
285 prop.SetLineWidth(2.0);
287 partEdgesActor.SetMapper(partEdgesMapper);
288 partEdgesActor.PickableOn();
290 assemblies.AddPart(partEdgesActor);
294 EdgePointsFilter edgePoints = new EdgePointsFilter();
297 out = partEdges.GetOutputPort();
298 edgePoints.SetInputConnection(out);
301 // vtkDataSetMapper partEdgePointsMapper = new vtkDataSetMapper();
302 // out = edgePoints.GetOutputPort();
303 // partEdgePointsMapper.SetInputConnection(out);
306 // vtkVertexGlyphFilter glyphFilter = new vtkVertexGlyphFilter();
307 // out = edgePoints.GetOutputPort();
308 // glyphFilter.SetInputConnection(out);
309 // glyphFilter.Update();
312 // vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
313 // out = glyphFilter.GetOutputPort();
314 // partEdgePointsMapper.SetInputConnection(out);
317 vtkSphereSource sphereSource = new vtkSphereSource();
318 vtkGlyph3D glyph3D = new vtkGlyph3D();
319 out = sphereSource.GetOutputPort();
320 glyph3D.SetSourceConnection(out);
323 out = edgePoints.GetOutputPort();
324 glyph3D.SetInputConnection(out);
327 //glyph3D.ScalingOff();
328 glyph3D.SetScaleFactor(0.03);
332 vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
333 out = glyph3D.GetOutputPort();
334 partEdgePointsMapper.SetInputConnection(out);
337 vtkActor edgePointsActor = new vtkActor();
339 prop = edgePointsActor.GetProperty();
340 prop.SetColor(0, 0, 1);
341 //prop.SetPointSize(10.0);
342 //prop.SetRepresentationToPoints();
344 edgePointsActor.SetMapper(partEdgePointsMapper);
346 edgePointsActor.PickableOn();
347 assemblies.AddPart(edgePointsActor);
350 edgePointsActor.Delete();
351 partEdgePointsMapper.Delete();
352 // edgePoints.Delete();
356 partEdgesActor.Delete();
357 partEdgesMapper.Delete();
364 partCleaner.Delete();
369 public static vtkPolyData createPartGrid ( TopoDS_Face face)
371 TopLoc_Location Location = new TopLoc_Location();
373 Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);
375 if(triangulation == null) {
377 System.out.println("Encountered empty triangulation after face");
381 boolean reverse = face.orientation()==TopAbs_Orientation.REVERSED;
383 int[]triangles = triangulation.triangles();
384 double[]nodes = triangulation.nodes();
386 int nofTriangles = triangulation.nbTriangles();
387 int nofNodes = triangulation.nbNodes();
389 triangulation.delete();
391 if(nofTriangles < 1) {
392 System.out.println("No triangles for mesh on face");
398 System.out.println("No nodes for mesh on face:");
402 //System.out.println("v " + nofNodes + " t " +nofTriangles);
403 vtkPolyData partGrid = new vtkPolyData();
404 partGrid.Allocate(nofTriangles, nofTriangles);
406 vtkTriangle triangle = new vtkTriangle();
407 vtkIdList list = triangle.GetPointIds();
408 for(int i = 0; i < nofTriangles; i++)
412 n0 = triangles[3 * i];
413 n1 = triangles[3 * i + 1];
414 n2 = triangles[3 * i + 2];
416 n0 = triangles[3 * i + 2];
417 n1 = triangles[3 * i + 1];
418 n2 = triangles[3 * i];
424 partGrid.InsertNextCell(triangle.GetCellType(), list);
430 GP_Trsf transformation = Location.transformation();
433 double d_mat[] = new double[16];
434 double d_p[] = new double[3];
435 transformation.getValues(d_mat);
436 Matrix4d mat = new Matrix4d(d_mat);
438 vtkPoints partPoints = new vtkPoints();
440 for(int i = 0; i < nofNodes; i++) {
441 // FIXME: GP_Trsf.transform(double[]) leaks memory
443 //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};
444 //transformation.transforms(xyz);
445 //partPoints.InsertPoint(i, xyz);
446 Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);
451 partPoints.InsertPoint(i, d_p);
454 transformation.delete();
456 partGrid.SetPoints(partPoints);
464 public static vtkPolyData createPartGrid ( List<Double> meshPoints, List<Integer> meshTriangles)
471 int nofTriangles = meshTriangles.size() / 3;
472 int nofNodes = meshPoints.size() /3;
475 if(nofTriangles < 1) {
476 System.out.println("No triangles for mesh on face");
481 System.out.println("No nodes for mesh on face:");
484 //System.out.println("v " + nofNodes + " t " +nofTriangles);
485 vtkPolyData partGrid = new vtkPolyData();
486 partGrid.Allocate(nofTriangles, nofTriangles);
488 vtkTriangle triangle = new vtkTriangle();
489 vtkIdList list = triangle.GetPointIds();
490 for(int i = 0; i < nofTriangles; i++)
493 n0 = meshTriangles.get(3 * i);
494 n1 = meshTriangles.get(3 * i + 1);
495 n2 = meshTriangles.get(3 * i + 2);
501 partGrid.InsertNextCell(triangle.GetCellType(), list);
509 double d_p[] = new double[3];
512 vtkPoints partPoints = new vtkPoints();
514 for(int i = 0; i < nofNodes; i++) {
516 d_p[0] = meshPoints.get(3*i);
517 d_p[1] = meshPoints.get(3*i+1);
518 d_p[2] = meshPoints.get(3*i+2);
519 partPoints.InsertPoint(i, d_p);
522 partGrid.SetPoints(partPoints);
528 private static vtkPolyData createTestPartGrid ()
532 double[] nodes = new double[(size+1)*(size+1)*3];
533 int[] triangles = new int[3 * size * size * 2];
536 for (int i = 0; i <= size; i++) {
537 for (int j = 0; j <= size; j++) {
538 int index = j * size + i;
540 double x = (double)i * es;
541 double y = (Math.sin((double)i/(double)size) + Math.sin((double)j/(double)size)) * es;
542 double z = (double)j * es;
549 for (int i = 0; i < size; i++) {
550 for (int j = 0; j < size; j++) {
551 int index = j * size + i;
554 triangles[index ] = (j * (size+1) + i );
555 triangles[index+1] = (j * (size+1) + i+1);
556 triangles[index+2] = ((j+1) * (size+1) + i );
557 triangles[index+3] = ((j+1) * (size+1) + i );
558 triangles[index+4] = ((j ) * (size+1) + i +1 );
559 triangles[index+5] = ((j+1) * (size+1) + i +1 );
563 int nofTriangles = triangles.length / 3;
564 int nofNodes = nodes.length / 3;
566 if(nofTriangles < 1) {
575 //System.out.println("v " + nofNodes + " t " +nofTriangles);
576 vtkPolyData partGrid = new vtkPolyData();
577 partGrid.Allocate(nofTriangles, nofTriangles);
579 vtkTriangle triangle = new vtkTriangle();
580 vtkIdList list = triangle.GetPointIds();
581 for(int i = 0; i < nofTriangles; i++)
584 n0 = triangles[3 * i]; n1 = triangles[3 * i + 1]; n2 = triangles[3 * i + 2]; // triangles(i).Get(n0, n1, n2);
586 // if(face.orientation() != TopAbs_Orientation.FORWARD) {
587 // int tmp = n2; n2 = n1; n1 = tmp;
593 partGrid.InsertNextCell(triangle.GetCellType(), list);
599 vtkPoints partPoints = new vtkPoints();
600 for(int i = 0; i < nofNodes; i++) {
601 double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};
602 partPoints.InsertPoint(i, xyz);
605 partGrid.SetPoints(partPoints);
612 public static void test() {
613 TopoDS_Shape shape = null;
614 //shape = OccTriangulator.makeCylinder(new double[]{0,0,0}, new double[]{0,1,0}, 1, 1);
615 for (int t = 0; t < 5000; t++) {
616 //shape = OccTriangulator.makeCylinder(new double[]{0,0,0}, new double[]{0,1,0}, 1, 1);
619 vtkAssembly ass = VTKOCCTool.vtkOCCShapeToAssembly(shape);
620 vtkPropCollection col;
621 col = ass.GetParts();
622 for (int i = 0; i < col.GetNumberOfItems(); i++)
624 vtkProp prop = (vtkProp) col.GetItemAsObject(i);
625 //System.out.println(prop.Print());
631 else if (test == 1) {
632 //BRepTools.clean(shape);
635 vtkAssembly ass = new vtkAssembly();
637 double vol = OCCTTool.getBoundingBoxDiagonal(shape);
638 double d = 0.001 * vol;
639 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,d);
640 TopExp_Explorer expFace = new TopExp_Explorer();
641 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
642 TopoDS_Face face = (TopoDS_Face) expFace.current();
644 // TopLoc_Location Location = new TopLoc_Location();
645 // Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);
646 // if (triangulation != null) {
648 // int[]triangles = triangulation.triangles();
649 // double[]nodes = triangulation.nodes();
650 // int nofTriangles = triangulation.nbTriangles();
651 // int nofNodes = triangulation.nbNodes();
653 // triangulation.delete();
655 // GP_Trsf transformation = Location.transformation();
656 // double d_mat[] = new double[16];
657 // transformation.getValues(d_mat);
658 // Matrix4d mat = new Matrix4d(d_mat);
659 // for(int i = 0; i < nofNodes; i++) {
660 // //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};
661 // Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);
662 // //transformation.transforms(xyz);
665 // transformation.delete();
668 // Location.delete();
669 vtkPolyData data = VTKOCCTool.createPartGrid(face);
670 VTKOCCTool.gridToAssembly(ass, data);
678 vtkPropCollection col;
679 col = ass.GetParts();
680 for (int i = 0; i < col.GetNumberOfItems(); i++)
682 vtkProp prop = (vtkProp) col.GetItemAsObject(i);
683 //System.out.println(prop.Print());
688 } else if (test == 2) {
689 double[] pointStruct = new double[]{0,0,0}, dirStruct = new double[]{0,1,0};
693 double[] axe = new double[6];
695 System.arraycopy(pointStruct, 0, axe, 0, 3);
696 System.arraycopy(dirStruct, 0, axe, 3, 3);
697 org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder cyl = new org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder(axe, radius, height, 2 * Math.PI);
698 org.jcae.opencascade.jni.TopoDS_Shape tds = cyl.shape();
701 double vol = OCCTTool.getBoundingBoxDiagonal(tds);
702 double d = 0.001 * vol;
703 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(tds,d);
704 // TopExp_Explorer expFace = new TopExp_Explorer();
705 // for (expFace.init(tds, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
706 // TopoDS_Face face = (TopoDS_Face) expFace.current();
717 System.out.println(t);