1 package org.simantics.opencascade.vtk;
\r
3 import java.util.List;
\r
5 import javax.vecmath.Matrix4d;
\r
6 import javax.vecmath.Point3d;
\r
8 import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;
\r
9 import org.jcae.opencascade.jni.BRep_Tool;
\r
10 import org.jcae.opencascade.jni.GP_Trsf;
\r
11 import org.jcae.opencascade.jni.Poly_Triangulation;
\r
12 import org.jcae.opencascade.jni.TopAbs_Orientation;
\r
13 import org.jcae.opencascade.jni.TopAbs_ShapeEnum;
\r
14 import org.jcae.opencascade.jni.TopExp_Explorer;
\r
15 import org.jcae.opencascade.jni.TopLoc_Location;
\r
16 import org.jcae.opencascade.jni.TopoDS_Face;
\r
17 import org.jcae.opencascade.jni.TopoDS_Shape;
\r
18 import org.simantics.opencascade.OCCTTool;
\r
20 import vtk.vtkActor;
\r
21 import vtk.vtkAlgorithmOutput;
\r
22 import vtk.vtkAppendPolyData;
\r
23 import vtk.vtkAssembly;
\r
24 import vtk.vtkCleanPolyData;
\r
25 import vtk.vtkDataSetMapper;
\r
26 import vtk.vtkFeatureEdges;
\r
27 import vtk.vtkGlyph3D;
\r
28 import vtk.vtkIdList;
\r
29 import vtk.vtkPoints;
\r
30 import vtk.vtkPolyData;
\r
31 import vtk.vtkPolyDataMapper;
\r
32 import vtk.vtkPolyDataNormals;
\r
34 import vtk.vtkPropCollection;
\r
35 import vtk.vtkProperty;
\r
36 import vtk.vtkSphereSource;
\r
37 import vtk.vtkTriangle;
\r
39 public class VTKOCCTool {
\r
40 public static vtkAssembly vtkTestAssembly() {
\r
41 vtkAssembly assemblies = new vtkAssembly();
\r
42 vtkPolyData partGrid = createTestPartGrid();
\r
43 gridToAssembly(assemblies, partGrid);
\r
47 public static vtkAssembly vtkOCCShapeToAssembly(TopoDS_Shape shape) {
\r
48 double deflection = 0.001;
\r
50 if (deflection <= 0.0) {
\r
51 deflection = 0.0005;
\r
52 System.out.println("Bad value for deflection. Using: " + deflection);
\r
55 // FIXME : leaks memory!
\r
56 //BRepTools.clean(shape);
\r
58 double mass = OCCTTool.getMass(shape);
\r
60 if (mass < 1.0e-12) {
\r
61 System.out.println("Non 3D-shape detected");
\r
62 System.out.println("The cad import features are currently limited to 3D models.");
\r
65 double length = OCCTTool.getBoundingBoxDiagonal(shape);
\r
66 deflection *= length; // use relative units
\r
68 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection);
\r
71 TopExp_Explorer expFace = new TopExp_Explorer();
\r
73 vtkAssembly assemblies = new vtkAssembly();
\r
74 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
\r
75 TopoDS_Face face = (TopoDS_Face) expFace.current();
\r
76 vtkPolyData partGrid = createPartGrid(face);
\r
78 if (partGrid == null)
\r
81 //gridToAssembly(assemblies, partGrid, stlSurfaceData, stlEdgeData);
\r
82 gridToAssembly(assemblies, partGrid);
\r
88 if (faceNumber == 0) {
\r
90 .println("Cad import: error: no surface triangulation was generated.");
\r
97 private static void gridToAssembly(vtkAssembly assemblies, vtkPolyData partGrid, vtkAppendPolyData stlSurfaceData, vtkAppendPolyData stlEdgeData) {
\r
99 double featureAngle = 30;
\r
102 vtkDataSetMapper partMapper = new vtkDataSetMapper();
\r
104 boolean computeNormals = true;
\r
105 boolean cleanPart = true;
\r
106 boolean mergePoints = false;
\r
108 vtkCleanPolyData partCleaner = new vtkCleanPolyData();
\r
111 partCleaner.SetInput(partGrid);
\r
113 partCleaner.PointMergingOn();
\r
115 partCleaner.PointMergingOff();
\r
119 if (computeNormals)
\r
121 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
\r
125 partNormals.SetInputConnection(partCleaner.GetOutputPort());
\r
127 else partNormals.SetInput(partGrid);
\r
129 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
\r
130 partMapper.SetInputConnection(partNormals.GetOutputPort());
\r
131 partNormals.Delete();
\r
135 if (cleanPart) partMapper.SetInputConnection(partCleaner.GetOutputPort()); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
\r
136 else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
\r
138 partMapper.ScalarVisibilityOn();
\r
140 vtkActor partActor = new vtkActor();
\r
142 partActor.SetPickable(1);
\r
143 partActor.GetProperty().SetColor(1, 1, 0);
\r
144 partActor.SetMapper(partMapper);
\r
146 // EDGES OF PARTS DETECTION
\r
147 vtkFeatureEdges partEdges = new vtkFeatureEdges();
\r
148 if (cleanPart) partEdges.SetInputConnection(partCleaner.GetOutputPort());
\r
149 else partEdges.SetInput(partGrid);
\r
150 partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
\r
151 partEdges.FeatureEdgesOn();
\r
152 partEdges.BoundaryEdgesOn();
\r
153 partEdges.NonManifoldEdgesOn();
\r
154 partEdges.ManifoldEdgesOn();
\r
156 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
\r
157 partEdgesMapper.SetInputConnection(partEdges.GetOutputPort());
\r
158 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
\r
159 partEdgesMapper.ScalarVisibilityOff();
\r
161 vtkActor partEdgesActor = new vtkActor();
\r
162 partEdgesActor.SetPickable(0);
\r
163 partEdgesActor.GetProperty().SetColor(1, 0, 1);
\r
164 partEdgesActor.SetMapper(partEdgesMapper);
\r
167 // Add triangles and edges to STL structures:
\r
168 //--------------------------------------------
\r
169 if (cleanPart) stlSurfaceData.AddInput(partCleaner.GetOutput());
\r
170 else stlSurfaceData.AddInput(partGrid);
\r
171 stlEdgeData.AddInput(partEdges.GetOutput());
\r
173 assemblies.AddPart(partActor);
\r
174 assemblies.AddPart(partEdgesActor);
\r
178 partEdgesActor.Delete();
\r
179 partEdgesMapper.Delete();
\r
180 partEdges.Delete();
\r
181 partActor.Delete();
\r
182 partMapper.Delete();
\r
184 partCleaner.Delete();
\r
187 public static void gridToAssembly(vtkAssembly assemblies, vtkPolyData partGrid) {
\r
189 double featureAngle = 30;
\r
192 vtkDataSetMapper partMapper = new vtkDataSetMapper();
\r
194 boolean computeNormals = true;
\r
195 boolean cleanPart = false;
\r
196 boolean mergePoints = false;
\r
198 vtkCleanPolyData partCleaner = new vtkCleanPolyData();
\r
201 partCleaner.SetInput(partGrid);
\r
203 partCleaner.PointMergingOn();
\r
205 partCleaner.PointMergingOff();
\r
209 if (computeNormals)
\r
211 vtkPolyDataNormals partNormals = new vtkPolyDataNormals();
\r
215 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
216 partNormals.SetInputConnection(out);
\r
219 else partNormals.SetInput(partGrid);
\r
221 partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
\r
222 vtkAlgorithmOutput out = partNormals.GetOutputPort();
\r
223 partMapper.SetInputConnection(out);
\r
225 partNormals.Delete();
\r
230 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
231 partMapper.SetInputConnection(out); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
\r
234 else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681
\r
236 partMapper.ScalarVisibilityOn();
\r
238 vtkActor partActor = new vtkActor();
\r
239 partActor.SetPickable(1);
\r
240 vtkProperty prop = partActor.GetProperty();
\r
241 prop.SetColor(1, 1, 0);
\r
243 partActor.SetMapper(partMapper);
\r
245 assemblies.AddPart(partActor);
\r
248 // EDGES OF PARTS DETECTION
\r
249 vtkFeatureEdges partEdges = new vtkFeatureEdges();
\r
251 vtkAlgorithmOutput out = partCleaner.GetOutputPort();
\r
252 partEdges.SetInputConnection(out);
\r
255 else partEdges.SetInput(partGrid);
\r
256 // partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called
\r
257 partEdges.FeatureEdgesOn();
\r
258 partEdges.BoundaryEdgesOn();
\r
259 partEdges.NonManifoldEdgesOn();
\r
260 partEdges.ManifoldEdgesOn();
\r
262 vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();
\r
263 vtkAlgorithmOutput out = partEdges.GetOutputPort();
\r
264 partEdgesMapper.SetInputConnection(out);
\r
266 partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();
\r
267 partEdgesMapper.ScalarVisibilityOff();
\r
269 vtkActor partEdgesActor = new vtkActor();
\r
271 prop = partEdgesActor.GetProperty();
\r
272 prop.SetColor(0, 0, 0);
\r
273 prop.SetLineWidth(2.0);
\r
275 partEdgesActor.SetMapper(partEdgesMapper);
\r
276 partEdgesActor.PickableOn();
\r
278 assemblies.AddPart(partEdgesActor);
\r
282 EdgePointsFilter edgePoints = new EdgePointsFilter();
\r
285 out = partEdges.GetOutputPort();
\r
286 edgePoints.SetInputConnection(out);
\r
289 // vtkDataSetMapper partEdgePointsMapper = new vtkDataSetMapper();
\r
290 // out = edgePoints.GetOutputPort();
\r
291 // partEdgePointsMapper.SetInputConnection(out);
\r
294 // vtkVertexGlyphFilter glyphFilter = new vtkVertexGlyphFilter();
\r
295 // out = edgePoints.GetOutputPort();
\r
296 // glyphFilter.SetInputConnection(out);
\r
297 // glyphFilter.Update();
\r
300 // vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
\r
301 // out = glyphFilter.GetOutputPort();
\r
302 // partEdgePointsMapper.SetInputConnection(out);
\r
305 vtkSphereSource sphereSource = new vtkSphereSource();
\r
306 vtkGlyph3D glyph3D = new vtkGlyph3D();
\r
307 out = sphereSource.GetOutputPort();
\r
308 glyph3D.SetSourceConnection(out);
\r
311 out = edgePoints.GetOutputPort();
\r
312 glyph3D.SetInputConnection(out);
\r
315 //glyph3D.ScalingOff();
\r
316 glyph3D.SetScaleFactor(0.03);
\r
320 vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();
\r
321 out = glyph3D.GetOutputPort();
\r
322 partEdgePointsMapper.SetInputConnection(out);
\r
325 vtkActor edgePointsActor = new vtkActor();
\r
327 prop = edgePointsActor.GetProperty();
\r
328 prop.SetColor(0, 0, 1);
\r
329 //prop.SetPointSize(10.0);
\r
330 //prop.SetRepresentationToPoints();
\r
332 edgePointsActor.SetMapper(partEdgePointsMapper);
\r
334 edgePointsActor.PickableOn();
\r
335 assemblies.AddPart(edgePointsActor);
\r
338 edgePointsActor.Delete();
\r
339 partEdgePointsMapper.Delete();
\r
340 // edgePoints.Delete();
\r
344 partEdgesActor.Delete();
\r
345 partEdgesMapper.Delete();
\r
346 partEdges.Delete();
\r
349 partActor.Delete();
\r
350 partMapper.Delete();
\r
352 partCleaner.Delete();
\r
357 public static vtkPolyData createPartGrid ( TopoDS_Face face)
\r
359 TopLoc_Location Location = new TopLoc_Location();
\r
361 Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);
\r
363 if(triangulation == null) {
\r
365 System.out.println("Encountered empty triangulation after face");
\r
369 boolean reverse = face.orientation()==TopAbs_Orientation.REVERSED;
\r
371 int[]triangles = triangulation.triangles();
\r
372 double[]nodes = triangulation.nodes();
\r
374 int nofTriangles = triangulation.nbTriangles();
\r
375 int nofNodes = triangulation.nbNodes();
\r
377 triangulation.delete();
\r
379 if(nofTriangles < 1) {
\r
380 System.out.println("No triangles for mesh on face");
\r
386 System.out.println("No nodes for mesh on face:");
\r
390 //System.out.println("v " + nofNodes + " t " +nofTriangles);
\r
391 vtkPolyData partGrid = new vtkPolyData();
\r
392 partGrid.Allocate(nofTriangles, nofTriangles);
\r
394 vtkTriangle triangle = new vtkTriangle();
\r
395 vtkIdList list = triangle.GetPointIds();
\r
396 for(int i = 0; i < nofTriangles; i++)
\r
400 n0 = triangles[3 * i];
\r
401 n1 = triangles[3 * i + 1];
\r
402 n2 = triangles[3 * i + 2];
\r
404 n0 = triangles[3 * i + 2];
\r
405 n1 = triangles[3 * i + 1];
\r
406 n2 = triangles[3 * i];
\r
412 partGrid.InsertNextCell(triangle.GetCellType(), list);
\r
416 triangle.Delete();
\r
418 GP_Trsf transformation = Location.transformation();
\r
421 double d_mat[] = new double[16];
\r
422 double d_p[] = new double[3];
\r
423 transformation.getValues(d_mat);
\r
424 Matrix4d mat = new Matrix4d(d_mat);
\r
426 vtkPoints partPoints = new vtkPoints();
\r
428 for(int i = 0; i < nofNodes; i++) {
\r
429 // FIXME: GP_Trsf.transform(double[]) leaks memory
\r
431 //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};
\r
432 //transformation.transforms(xyz);
\r
433 //partPoints.InsertPoint(i, xyz);
\r
434 Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);
\r
439 partPoints.InsertPoint(i, d_p);
\r
442 transformation.delete();
\r
444 partGrid.SetPoints(partPoints);
\r
445 partPoints.Delete();
\r
452 public static vtkPolyData createPartGrid ( List<Double> meshPoints, List<Integer> meshTriangles)
\r
459 int nofTriangles = meshTriangles.size() / 3;
\r
460 int nofNodes = meshPoints.size() /3;
\r
463 if(nofTriangles < 1) {
\r
464 System.out.println("No triangles for mesh on face");
\r
469 System.out.println("No nodes for mesh on face:");
\r
472 //System.out.println("v " + nofNodes + " t " +nofTriangles);
\r
473 vtkPolyData partGrid = new vtkPolyData();
\r
474 partGrid.Allocate(nofTriangles, nofTriangles);
\r
476 vtkTriangle triangle = new vtkTriangle();
\r
477 vtkIdList list = triangle.GetPointIds();
\r
478 for(int i = 0; i < nofTriangles; i++)
\r
481 n0 = meshTriangles.get(3 * i);
\r
482 n1 = meshTriangles.get(3 * i + 1);
\r
483 n2 = meshTriangles.get(3 * i + 2);
\r
489 partGrid.InsertNextCell(triangle.GetCellType(), list);
\r
493 triangle.Delete();
\r
497 double d_p[] = new double[3];
\r
500 vtkPoints partPoints = new vtkPoints();
\r
502 for(int i = 0; i < nofNodes; i++) {
\r
504 d_p[0] = meshPoints.get(3*i);
\r
505 d_p[1] = meshPoints.get(3*i+1);
\r
506 d_p[2] = meshPoints.get(3*i+2);
\r
507 partPoints.InsertPoint(i, d_p);
\r
510 partGrid.SetPoints(partPoints);
\r
511 partPoints.Delete();
\r
516 private static vtkPolyData createTestPartGrid ()
\r
520 double[] nodes = new double[(size+1)*(size+1)*3];
\r
521 int[] triangles = new int[3 * size * size * 2];
\r
524 for (int i = 0; i <= size; i++) {
\r
525 for (int j = 0; j <= size; j++) {
\r
526 int index = j * size + i;
\r
528 double x = (double)i * es;
\r
529 double y = (Math.sin((double)i/(double)size) + Math.sin((double)j/(double)size)) * es;
\r
530 double z = (double)j * es;
\r
532 nodes[index+1] = y;
\r
533 nodes[index+2] = z;
\r
537 for (int i = 0; i < size; i++) {
\r
538 for (int j = 0; j < size; j++) {
\r
539 int index = j * size + i;
\r
542 triangles[index ] = (j * (size+1) + i );
\r
543 triangles[index+1] = (j * (size+1) + i+1);
\r
544 triangles[index+2] = ((j+1) * (size+1) + i );
\r
545 triangles[index+3] = ((j+1) * (size+1) + i );
\r
546 triangles[index+4] = ((j ) * (size+1) + i +1 );
\r
547 triangles[index+5] = ((j+1) * (size+1) + i +1 );
\r
551 int nofTriangles = triangles.length / 3;
\r
552 int nofNodes = nodes.length / 3;
\r
554 if(nofTriangles < 1) {
\r
563 //System.out.println("v " + nofNodes + " t " +nofTriangles);
\r
564 vtkPolyData partGrid = new vtkPolyData();
\r
565 partGrid.Allocate(nofTriangles, nofTriangles);
\r
567 vtkTriangle triangle = new vtkTriangle();
\r
568 vtkIdList list = triangle.GetPointIds();
\r
569 for(int i = 0; i < nofTriangles; i++)
\r
572 n0 = triangles[3 * i]; n1 = triangles[3 * i + 1]; n2 = triangles[3 * i + 2]; // triangles(i).Get(n0, n1, n2);
\r
574 // if(face.orientation() != TopAbs_Orientation.FORWARD) {
\r
575 // int tmp = n2; n2 = n1; n1 = tmp;
\r
581 partGrid.InsertNextCell(triangle.GetCellType(), list);
\r
585 triangle.Delete();
\r
587 vtkPoints partPoints = new vtkPoints();
\r
588 for(int i = 0; i < nofNodes; i++) {
\r
589 double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};
\r
590 partPoints.InsertPoint(i, xyz);
\r
593 partGrid.SetPoints(partPoints);
\r
595 partPoints.Delete();
\r
600 public static void test() {
\r
601 TopoDS_Shape shape = null;
\r
602 //shape = OccTriangulator.makeCylinder(new double[]{0,0,0}, new double[]{0,1,0}, 1, 1);
\r
603 for (int t = 0; t < 5000; t++) {
\r
604 //shape = OccTriangulator.makeCylinder(new double[]{0,0,0}, new double[]{0,1,0}, 1, 1);
\r
607 vtkAssembly ass = VTKOCCTool.vtkOCCShapeToAssembly(shape);
\r
608 vtkPropCollection col;
\r
609 col = ass.GetParts();
\r
610 for (int i = 0; i < col.GetNumberOfItems(); i++)
\r
612 vtkProp prop = (vtkProp) col.GetItemAsObject(i);
\r
613 //System.out.println(prop.Print());
\r
619 else if (test == 1) {
\r
620 //BRepTools.clean(shape);
\r
623 vtkAssembly ass = new vtkAssembly();
\r
625 double vol = OCCTTool.getBoundingBoxDiagonal(shape);
\r
626 double d = 0.001 * vol;
\r
627 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,d);
\r
628 TopExp_Explorer expFace = new TopExp_Explorer();
\r
629 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
\r
630 TopoDS_Face face = (TopoDS_Face) expFace.current();
\r
632 // TopLoc_Location Location = new TopLoc_Location();
\r
633 // Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);
\r
634 // if (triangulation != null) {
\r
636 // int[]triangles = triangulation.triangles();
\r
637 // double[]nodes = triangulation.nodes();
\r
638 // int nofTriangles = triangulation.nbTriangles();
\r
639 // int nofNodes = triangulation.nbNodes();
\r
641 // triangulation.delete();
\r
643 // GP_Trsf transformation = Location.transformation();
\r
644 // double d_mat[] = new double[16];
\r
645 // transformation.getValues(d_mat);
\r
646 // Matrix4d mat = new Matrix4d(d_mat);
\r
647 // for(int i = 0; i < nofNodes; i++) {
\r
648 // //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};
\r
649 // Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);
\r
650 // //transformation.transforms(xyz);
\r
651 // mat.transform(p);
\r
653 // transformation.delete();
\r
656 // Location.delete();
\r
657 vtkPolyData data = VTKOCCTool.createPartGrid(face);
\r
658 VTKOCCTool.gridToAssembly(ass, data);
\r
666 vtkPropCollection col;
\r
667 col = ass.GetParts();
\r
668 for (int i = 0; i < col.GetNumberOfItems(); i++)
\r
670 vtkProp prop = (vtkProp) col.GetItemAsObject(i);
\r
671 //System.out.println(prop.Print());
\r
676 } else if (test == 2) {
\r
677 double[] pointStruct = new double[]{0,0,0}, dirStruct = new double[]{0,1,0};
\r
678 double radius = 1.0;
\r
679 double height = 1.0;
\r
681 double[] axe = new double[6];
\r
683 System.arraycopy(pointStruct, 0, axe, 0, 3);
\r
684 System.arraycopy(dirStruct, 0, axe, 3, 3);
\r
685 org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder cyl = new org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder(axe, radius, height, 2 * Math.PI);
\r
686 org.jcae.opencascade.jni.TopoDS_Shape tds = cyl.shape();
\r
689 double vol = OCCTTool.getBoundingBoxDiagonal(tds);
\r
690 double d = 0.001 * vol;
\r
691 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(tds,d);
\r
692 // TopExp_Explorer expFace = new TopExp_Explorer();
\r
693 // for (expFace.init(tds, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {
\r
694 // TopoDS_Face face = (TopoDS_Face) expFace.current();
\r
705 System.out.println(t);
\r