1 // Created on: 2011-10-14
2 // Created by: Roman KOZLOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <Adaptor3d_IsoCurve.hxx>
17 #include <Bnd_Box.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepBndLib.hxx>
20 #include <BRepMesh_DiscretFactory.hxx>
21 #include <BRepMesh_DiscretRoot.hxx>
22 #include <BRepTools.hxx>
23 #include <Hatch_Hatcher.hxx>
24 #include <GCPnts_QuasiUniformDeflection.hxx>
25 #include <GCPnts_TangentialDeflection.hxx>
26 #include <Geom_BezierSurface.hxx>
27 #include <Geom_BSplineSurface.hxx>
28 #include <Geom2dAdaptor_Curve.hxx>
29 #include <GeomAdaptor_Curve.hxx>
30 #include <gp_Dir2d.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <IVtkOCC_ShapeMesher.hxx>
33 #include <NCollection_Array1.hxx>
34 #include <Poly_Polygon3D.hxx>
35 #include <Poly_PolygonOnTriangulation.hxx>
36 #include <Poly_Triangulation.hxx>
37 #include <Precision.hxx>
39 #include <Prs3d_Drawer.hxx>
40 #include <Prs3d_IsoAspect.hxx>
41 #include <Standard_ErrorHandler.hxx>
42 #include <StdPrs_Isolines.hxx>
43 #include <StdPrs_ToolTriangulatedShape.hxx>
44 #include <TColgp_SequenceOfPnt2d.hxx>
45 #include <TColStd_Array1OfReal.hxx>
47 #include <TopExp_Explorer.hxx>
49 IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_ShapeMesher,IVtk_IShapeMesher)
51 // Handle implementation
54 //================================================================
55 // Function : internalBuild
57 //================================================================
58 void IVtkOCC_ShapeMesher::internalBuild()
60 // TODO: do we need any protection here so as not to triangualte
61 // the shape twice??? This can be done e.g. by checking if
62 // triangulation exists for TopoDS_Shape..
65 // Free vertices and free edges should always be shown.
66 // Shared edges are needed in WF representation only.
67 // TODO: how to filter free edges at visualization level????
71 // Build wireframe points and cells (lines for isolines)
74 // Build shaded representation (based on Poly_Triangulation)
78 //================================================================
79 // Function : GetShapeObj
81 //================================================================
82 const IVtkOCC_Shape::Handle IVtkOCC_ShapeMesher::GetShapeObj() const
84 return (IVtkOCC_Shape::Handle::DownCast(myShapeObj));
87 //================================================================
88 // Function : GetDeflection
89 // Purpose : Returns absolute deflection used by this algorithm.
90 //================================================================
91 Standard_Real IVtkOCC_ShapeMesher::GetDeflection() const
93 if (myDeflection < Precision::Confusion()) // if not yet initialized
95 Handle(Prs3d_Drawer) aDefDrawer = new Prs3d_Drawer();
96 aDefDrawer->SetTypeOfDeflection (Aspect_TOD_RELATIVE);
97 aDefDrawer->SetDeviationCoefficient (GetDeviationCoeff());
98 myDeflection = StdPrs_ToolTriangulatedShape::GetDeflection (GetShapeObj()->GetShape(), aDefDrawer);
104 //================================================================
105 // Function : meshShape
107 //================================================================
108 void IVtkOCC_ShapeMesher::meshShape()
110 const TopoDS_Shape& anOcctShape = GetShapeObj()->GetShape();
111 if (anOcctShape.IsNull())
116 //Clean triangulation before compute incremental mesh
117 BRepTools::Clean (anOcctShape);
119 //Compute triangulation
120 Standard_Real aDeflection = GetDeflection();
121 if (aDeflection < Precision::Confusion())
130 Handle(BRepMesh_DiscretRoot) anAlgo;
131 anAlgo = BRepMesh_DiscretFactory::Get().Discret (anOcctShape,
133 GetDeviationAngle());
134 if (!anAlgo.IsNull())
139 catch (Standard_Failure)
143 //================================================================
144 // Function : addFreeVertices
146 //================================================================
147 void IVtkOCC_ShapeMesher::addFreeVertices()
149 TopTools_IndexedDataMapOfShapeListOfShape aVertexMap;
150 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
155 Standard_Integer aVertNum = aVertexMap.Extent();
157 for (Standard_Integer anIt = 1; anIt <= aVertNum; anIt++)
159 if (aVertexMap.FindFromIndex(anIt).IsEmpty())
161 aType = MT_FreeVertex;
165 aType = MT_SharedVertex;
167 const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexMap.FindKey (anIt));
168 addVertex (aVertex, GetShapeObj()->GetSubShapeId (aVertex), aType);
172 //================================================================
173 // Function : addEdges
175 //================================================================
176 void IVtkOCC_ShapeMesher::addEdges()
178 TopTools_IndexedDataMapOfShapeListOfShape anEdgesMap;
179 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
185 myEdgesTypes.Clear();
187 TopTools_IndexedDataMapOfShapeListOfShape::Iterator aEdgeIt(anEdgesMap);
188 for (; aEdgeIt.More(); aEdgeIt.Next())
190 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (aEdgeIt.Key());
191 const TopTools_ListOfShape& aFaceList = aEdgeIt.Value();
192 aNbFaces = aFaceList.Extent();
197 else if (aNbFaces == 1)
199 aType = MT_BoundaryEdge;
203 aType = (aNbFaces >= 2) && (BRep_Tool::MaxContinuity(anOcctEdge) > GeomAbs_G2) ?
204 MT_SeamEdge : MT_SharedEdge;
206 addEdge (anOcctEdge, GetShapeObj()->GetSubShapeId (anOcctEdge), aType);
207 myEdgesTypes.Bind (anOcctEdge, aType);
211 //================================================================
212 // Function : addWireFrameFaces
214 //================================================================
215 void IVtkOCC_ShapeMesher::addWireFrameFaces()
217 // Check the deflection value once for all faces
218 if (GetDeflection() < Precision::Confusion())
223 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
224 for (; aFaceIter.More(); aFaceIter.Next())
226 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
230 addWFFace (anOcctFace,
231 GetShapeObj()->GetSubShapeId (anOcctFace));
233 catch (Standard_Failure)
238 //================================================================
239 // Function : addShadedFaces
241 //================================================================
242 void IVtkOCC_ShapeMesher::addShadedFaces()
244 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
245 for (; aFaceIter.More(); aFaceIter.Next())
247 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
248 addShadedFace (anOcctFace,
249 GetShapeObj()->GetSubShapeId (anOcctFace));
253 //================================================================
254 // Function : addVertex
256 //================================================================
257 void IVtkOCC_ShapeMesher::addVertex (const TopoDS_Vertex& theVertex,
258 const IVtk_IdType theShapeId,
259 const IVtk_MeshType theMeshType)
261 if (theVertex.IsNull())
266 gp_Pnt aPnt3d = BRep_Tool::Pnt (theVertex);
269 myShapeData->InsertCoordinate (aPnt3d.X(), aPnt3d.Y(), aPnt3d.Z());
270 myShapeData->InsertVertex (theShapeId, anId, theMeshType);
274 //================================================================
275 // Function : processPolyline
277 //================================================================
278 void IVtkOCC_ShapeMesher::processPolyline (Standard_Integer theNbNodes,
279 const TColgp_Array1OfPnt& thePoints,
280 const TColStd_Array1OfInteger& thePointIds,
281 const IVtk_IdType theOcctId,
283 gp_Trsf theTransformation,
284 const IVtk_MeshType theMeshType)
291 IVtk_PointIdList aPolyPointIds;
294 for (Standard_Integer aJ = 0; aJ < theNbNodes; aJ++)
296 Standard_Integer aPntId = thePointIds (aJ + 1);
297 gp_Pnt point = thePoints (aPntId);
301 // Apply the transformation to points
302 point.Transform (theTransformation);
305 anId = myShapeData->InsertCoordinate (point.X(), point.Y(), point.Z());
306 aPolyPointIds.Append (anId);
309 myShapeData->InsertLine (theOcctId, &aPolyPointIds, theMeshType);
312 //================================================================
313 // Function : addEdge
315 //================================================================
316 void IVtkOCC_ShapeMesher::addEdge (const TopoDS_Edge& theEdge,
317 const IVtk_IdType theShapeId,
318 const IVtk_MeshType theMeshType)
320 if (theEdge.IsNull() || BRep_Tool::Degenerated (theEdge))
325 // Two discrete representations of an OCCT edge are possible:
326 // 1. Polygon on trinagulation - holds Ids of points
327 // contained in Poly_Triangulation object
328 Handle(Poly_PolygonOnTriangulation) aPolyOnTriangulation;
329 Handle(Poly_Triangulation) aTriangulation;
330 TopLoc_Location aLocation;
331 BRep_Tool::PolygonOnTriangulation (theEdge,
332 aPolyOnTriangulation,
337 // 2. 3D polygon - holds 3D points
338 Handle(Poly_Polygon3D) aPoly3d;
339 if (aPolyOnTriangulation.IsNull())
341 aPoly3d = BRep_Tool::Polygon3D (theEdge, aLocation);
344 if (aPoly3d.IsNull() && aPolyOnTriangulation.IsNull())
349 // Handle a non-identity transofmation applied to the edge
350 gp_Trsf anEdgeTransf;
351 bool noTransform = true;
352 if (!aLocation.IsIdentity())
355 anEdgeTransf = aLocation.Transformation();
358 if (!aPoly3d.IsNull())
360 Standard_Integer aNbNodes = aPoly3d->NbNodes();
361 const TColgp_Array1OfPnt& aPoints = aPoly3d->Nodes();
362 TColStd_Array1OfInteger aPointIds (1, aNbNodes);
364 for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
366 aPointIds.SetValue (anI, anI);
369 processPolyline (aNbNodes,
379 Standard_Integer aNbNodes = aPolyOnTriangulation->NbNodes();
380 const TColStd_Array1OfInteger& aPointIds = aPolyOnTriangulation->Nodes();
381 const TColgp_Array1OfPnt& aPoints = aTriangulation->Nodes();
383 processPolyline (aNbNodes,
393 //================================================================
394 // Function : addWFFace
396 //================================================================
397 void IVtkOCC_ShapeMesher::addWFFace (const TopoDS_Face& theFace,
398 const IVtk_IdType theShapeId)
400 if (theFace.IsNull())
405 TopoDS_Face aFaceToMesh = theFace;
406 aFaceToMesh.Orientation (TopAbs_FORWARD);
408 // The code that builds wireframe representation for a TopoDS_Face
409 // has been adapted from some OCCT 6.5.1 methods:
410 // - Prs3d_WFShape::Add()
411 // - StdPrs_WFDeflectionRestrictedFace::Add()
412 // - StdPrs_DeflectionCurve::Add()
414 // Add face's edges here but with the face ID
415 for (TopExp_Explorer anEdgeIter (aFaceToMesh, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next())
417 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
418 addEdge (anOcctEdge, theShapeId, myEdgesTypes (anOcctEdge));
421 TopLoc_Location aLoc;
422 const Handle(Geom_Surface)& aGeomSurf = BRep_Tool::Surface (aFaceToMesh, aLoc);
423 if (aGeomSurf.IsNull())
428 const Standard_Real aDeflection = GetDeflection();
429 Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer();
430 aDrawer->SetUIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[0]));
431 aDrawer->SetVIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[1]));
432 aDrawer->SetDeviationAngle (myDevAngle);
433 aDrawer->SetDeviationCoefficient (myDevCoeff);
434 aDrawer->SetMaximalChordialDeviation (aDeflection);
436 Prs3d_NListOfSequenceOfPnt aPolylines;
437 StdPrs_Isolines::Add (theFace, aDrawer, aDeflection, aPolylines, aPolylines);
438 for (Prs3d_NListOfSequenceOfPnt::Iterator aPolyIter (aPolylines); aPolyIter.More(); aPolyIter.Next())
440 const Handle(TColgp_HSequenceOfPnt)& aPoints = aPolyIter.Value();
441 const Standard_Integer theNbNodes = aPoints->Length();
447 IVtk_PointIdList aPolyPointIds;
448 for (TColgp_HSequenceOfPnt::Iterator aNodeIter (*aPoints); aNodeIter.More(); aNodeIter.Next())
450 const gp_Pnt& aPnt = aNodeIter.Value();
451 const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt.X(), aPnt.Y(), aPnt.Z());
452 aPolyPointIds.Append (anId);
455 myShapeData->InsertLine (theShapeId, &aPolyPointIds, MT_IsoLine);
459 //================================================================
460 // Function : addShadedFace
462 //================================================================
463 void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace,
464 const IVtk_IdType theShapeId)
466 if (theFace.IsNull())
471 // Build triangulation of the face.
472 TopLoc_Location aLoc;
473 Handle(Poly_Triangulation) anOcctTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
474 if (anOcctTriangulation.IsNull())
479 gp_Trsf aPntTransform;
480 Standard_Boolean noTransform = Standard_True;
481 if (!aLoc.IsIdentity())
483 noTransform = Standard_False;
484 aPntTransform = aLoc.Transformation();
487 // Get triangulation points.
488 const TColgp_Array1OfPnt& aPoints = anOcctTriangulation->Nodes();
489 Standard_Integer aNbPoints = anOcctTriangulation->NbNodes();
491 // Keep inserted points id's of triangulation in an array.
492 NCollection_Array1<IVtk_PointId> aPointIds (1, aNbPoints);
495 Standard_Integer anI;
496 for (anI = 1; anI <= aNbPoints; anI++)
498 gp_Pnt aPoint = aPoints (anI);
502 aPoint.Transform (aPntTransform);
505 // Add a point into output shape data and keep its id in the array.
506 anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z());
507 aPointIds.SetValue (anI, anId);
510 // Create triangles on the created triangulation points.
511 const Poly_Array1OfTriangle& aTriangles = anOcctTriangulation->Triangles();
512 Standard_Integer aNbTriangles = anOcctTriangulation->NbTriangles();
513 Standard_Integer aN1, aN2, aN3;
514 for (anI = 1; anI <= aNbTriangles; anI++)
516 aTriangles(anI).Get (aN1, aN2, aN3); // get indexes of triangle's points
517 // Insert new triangle on these points into output shape data.
518 myShapeData->InsertTriangle (
519 theShapeId, aPointIds(aN1), aPointIds(aN2), aPointIds(aN3), MT_ShadedFace);