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 <TColgp_SequenceOfPnt2d.hxx>
44 #include <TColStd_Array1OfReal.hxx>
46 #include <TopExp_Explorer.hxx>
48 IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_ShapeMesher,IVtk_IShapeMesher)
50 // Handle implementation
53 //================================================================
54 // Function : internalBuild
56 //================================================================
57 void IVtkOCC_ShapeMesher::internalBuild()
59 // TODO: do we need any protection here so as not to triangualte
60 // the shape twice??? This can be done e.g. by checking if
61 // triangulation exists for TopoDS_Shape..
64 // Free vertices and free edges should always be shown.
65 // Shared edges are needed in WF representation only.
66 // TODO: how to filter free edges at visualization level????
70 // Build wireframe points and cells (lines for isolines)
73 // Build shaded representation (based on Poly_Triangulation)
77 //================================================================
78 // Function : GetShapeObj
80 //================================================================
81 const IVtkOCC_Shape::Handle IVtkOCC_ShapeMesher::GetShapeObj() const
83 return (IVtkOCC_Shape::Handle::DownCast(myShapeObj));
86 //================================================================
87 // Function : GetDeflection
88 // Purpose : Returns absolute deflection used by this algorithm.
89 //================================================================
90 Standard_Real IVtkOCC_ShapeMesher::GetDeflection() const
92 if (myDeflection < Precision::Confusion()) // if not yet initialized
94 Handle(Prs3d_Drawer) aDefDrawer = new Prs3d_Drawer();
95 aDefDrawer->SetTypeOfDeflection (Aspect_TOD_RELATIVE);
96 aDefDrawer->SetDeviationCoefficient (GetDeviationCoeff());
97 myDeflection = Prs3d::GetDeflection (GetShapeObj()->GetShape(), aDefDrawer);
103 //================================================================
104 // Function : meshShape
106 //================================================================
107 void IVtkOCC_ShapeMesher::meshShape()
109 const TopoDS_Shape& anOcctShape = GetShapeObj()->GetShape();
110 if (anOcctShape.IsNull())
115 //Clean triangulation before compute incremental mesh
116 BRepTools::Clean (anOcctShape);
118 //Compute triangulation
119 Standard_Real aDeflection = GetDeflection();
120 if (aDeflection < Precision::Confusion())
129 Handle(BRepMesh_DiscretRoot) anAlgo;
130 anAlgo = BRepMesh_DiscretFactory::Get().Discret (anOcctShape,
132 GetDeviationAngle());
133 if (!anAlgo.IsNull())
138 catch (Standard_Failure)
142 //================================================================
143 // Function : addFreeVertices
145 //================================================================
146 void IVtkOCC_ShapeMesher::addFreeVertices()
148 TopTools_IndexedDataMapOfShapeListOfShape aVertexMap;
149 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
154 Standard_Integer aVertNum = aVertexMap.Extent();
156 for (Standard_Integer anIt = 1; anIt <= aVertNum; anIt++)
158 if (aVertexMap.FindFromIndex(anIt).IsEmpty())
160 aType = MT_FreeVertex;
164 aType = MT_SharedVertex;
166 const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexMap.FindKey (anIt));
167 addVertex (aVertex, GetShapeObj()->GetSubShapeId (aVertex), aType);
171 //================================================================
172 // Function : addEdges
174 //================================================================
175 void IVtkOCC_ShapeMesher::addEdges()
177 TopTools_IndexedDataMapOfShapeListOfShape anEdgesMap;
178 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
185 myEdgesTypes.Clear();
187 TopExp_Explorer anEdgeIter (GetShapeObj()->GetShape(), TopAbs_EDGE);
188 for (; anEdgeIter.More(); anEdgeIter.Next())
190 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
191 aNbFaces = anEdgesMap.FindFromKey (anOcctEdge).Extent();
196 else if (aNbFaces == 1)
198 aType = MT_BoundaryEdge;
202 aType = MT_SharedEdge;
204 addEdge (anOcctEdge, GetShapeObj()->GetSubShapeId (anOcctEdge), aType);
205 myEdgesTypes.Bind (anOcctEdge, aType);
209 //================================================================
210 // Function : addWireFrameFaces
212 //================================================================
213 void IVtkOCC_ShapeMesher::addWireFrameFaces()
215 // Check the deflection value once for all faces
216 if (GetDeflection() < Precision::Confusion())
221 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
222 for (; aFaceIter.More(); aFaceIter.Next())
224 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
228 addWFFace (anOcctFace,
229 GetShapeObj()->GetSubShapeId (anOcctFace));
231 catch (Standard_Failure)
236 //================================================================
237 // Function : addShadedFaces
239 //================================================================
240 void IVtkOCC_ShapeMesher::addShadedFaces()
242 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
243 for (; aFaceIter.More(); aFaceIter.Next())
245 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
246 addShadedFace (anOcctFace,
247 GetShapeObj()->GetSubShapeId (anOcctFace));
251 //================================================================
252 // Function : addVertex
254 //================================================================
255 void IVtkOCC_ShapeMesher::addVertex (const TopoDS_Vertex& theVertex,
256 const IVtk_IdType theShapeId,
257 const IVtk_MeshType theMeshType)
259 if (theVertex.IsNull())
264 gp_Pnt aPnt3d = BRep_Tool::Pnt (theVertex);
267 myShapeData->InsertCoordinate (aPnt3d.X(), aPnt3d.Y(), aPnt3d.Z());
268 myShapeData->InsertVertex (theShapeId, anId, theMeshType);
272 //================================================================
273 // Function : processPolyline
275 //================================================================
276 void IVtkOCC_ShapeMesher::processPolyline (Standard_Integer theNbNodes,
277 const TColgp_Array1OfPnt& thePoints,
278 const TColStd_Array1OfInteger& thePointIds,
279 const IVtk_IdType theOcctId,
281 gp_Trsf theTransformation,
282 const IVtk_MeshType theMeshType)
289 IVtk_PointIdList aPolyPointIds;
292 for (Standard_Integer aJ = 0; aJ < theNbNodes; aJ++)
294 Standard_Integer aPntId = thePointIds (aJ + 1);
295 gp_Pnt point = thePoints (aPntId);
299 // Apply the transformation to points
300 point.Transform (theTransformation);
303 anId = myShapeData->InsertCoordinate (point.X(), point.Y(), point.Z());
304 aPolyPointIds.Append (anId);
307 myShapeData->InsertLine (theOcctId, &aPolyPointIds, theMeshType);
310 //================================================================
311 // Function : addEdge
313 //================================================================
314 void IVtkOCC_ShapeMesher::addEdge (const TopoDS_Edge& theEdge,
315 const IVtk_IdType theShapeId,
316 const IVtk_MeshType theMeshType)
318 if (theEdge.IsNull() || BRep_Tool::Degenerated (theEdge))
323 // Two discrete representations of an OCCT edge are possible:
324 // 1. Polygon on trinagulation - holds Ids of points
325 // contained in Poly_Triangulation object
326 Handle(Poly_PolygonOnTriangulation) aPolyOnTriangulation;
327 Handle(Poly_Triangulation) aTriangulation;
328 TopLoc_Location aLocation;
329 BRep_Tool::PolygonOnTriangulation (theEdge,
330 aPolyOnTriangulation,
335 // 2. 3D polygon - holds 3D points
336 Handle(Poly_Polygon3D) aPoly3d;
337 if (aPolyOnTriangulation.IsNull())
339 aPoly3d = BRep_Tool::Polygon3D (theEdge, aLocation);
342 if (aPoly3d.IsNull() && aPolyOnTriangulation.IsNull())
347 // Handle a non-identity transofmation applied to the edge
348 gp_Trsf anEdgeTransf;
349 bool noTransform = true;
350 if (!aLocation.IsIdentity())
353 anEdgeTransf = aLocation.Transformation();
356 if (!aPoly3d.IsNull())
358 Standard_Integer aNbNodes = aPoly3d->NbNodes();
359 const TColgp_Array1OfPnt& aPoints = aPoly3d->Nodes();
360 TColStd_Array1OfInteger aPointIds (1, aNbNodes);
362 for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
364 aPointIds.SetValue (anI, anI);
367 processPolyline (aNbNodes,
377 Standard_Integer aNbNodes = aPolyOnTriangulation->NbNodes();
378 const TColStd_Array1OfInteger& aPointIds = aPolyOnTriangulation->Nodes();
379 const TColgp_Array1OfPnt& aPoints = aTriangulation->Nodes();
381 processPolyline (aNbNodes,
391 //================================================================
392 // Function : addWFFace
394 //================================================================
395 void IVtkOCC_ShapeMesher::addWFFace (const TopoDS_Face& theFace,
396 const IVtk_IdType theShapeId)
398 if (theFace.IsNull())
403 TopoDS_Face aFaceToMesh = theFace;
404 aFaceToMesh.Orientation (TopAbs_FORWARD);
406 // The code that builds wireframe representation for a TopoDS_Face
407 // has been adapted from some OCCT 6.5.1 methods:
408 // - Prs3d_WFShape::Add()
409 // - StdPrs_WFDeflectionRestrictedFace::Add()
410 // - StdPrs_DeflectionCurve::Add()
412 // Add face's edges here but with the face ID
413 for (TopExp_Explorer anEdgeIter (aFaceToMesh, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next())
415 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
416 addEdge (anOcctEdge, theShapeId, myEdgesTypes (anOcctEdge));
419 TopLoc_Location aLoc;
420 const Handle(Geom_Surface)& aGeomSurf = BRep_Tool::Surface (aFaceToMesh, aLoc);
421 if (aGeomSurf.IsNull())
426 const Standard_Real aDeflection = GetDeflection();
427 Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer();
428 aDrawer->SetUIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[0]));
429 aDrawer->SetVIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[1]));
430 aDrawer->SetDeviationAngle (myDevAngle);
431 aDrawer->SetDeviationCoefficient (myDevCoeff);
432 aDrawer->SetMaximalChordialDeviation (aDeflection);
434 Prs3d_NListOfSequenceOfPnt aPolylines;
435 StdPrs_Isolines::Add (theFace, aDrawer, aDeflection, aPolylines, aPolylines);
436 for (Prs3d_NListOfSequenceOfPnt::Iterator aPolyIter (aPolylines); aPolyIter.More(); aPolyIter.Next())
438 const Handle(TColgp_HSequenceOfPnt)& aPoints = aPolyIter.Value();
439 const Standard_Integer theNbNodes = aPoints->Length();
445 IVtk_PointIdList aPolyPointIds;
446 for (TColgp_HSequenceOfPnt::Iterator aNodeIter (*aPoints); aNodeIter.More(); aNodeIter.Next())
448 const gp_Pnt& aPnt = aNodeIter.Value();
449 const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt.X(), aPnt.Y(), aPnt.Z());
450 aPolyPointIds.Append (anId);
453 myShapeData->InsertLine (theShapeId, &aPolyPointIds, MT_IsoLine);
457 //================================================================
458 // Function : addShadedFace
460 //================================================================
461 void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace,
462 const IVtk_IdType theShapeId)
464 if (theFace.IsNull())
469 // Build triangulation of the face.
470 TopLoc_Location aLoc;
471 Handle(Poly_Triangulation) anOcctTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
472 if (anOcctTriangulation.IsNull())
477 gp_Trsf aPntTransform;
478 Standard_Boolean noTransform = Standard_True;
479 if (!aLoc.IsIdentity())
481 noTransform = Standard_False;
482 aPntTransform = aLoc.Transformation();
485 // Get triangulation points.
486 const TColgp_Array1OfPnt& aPoints = anOcctTriangulation->Nodes();
487 Standard_Integer aNbPoints = anOcctTriangulation->NbNodes();
489 // Keep inserted points id's of triangulation in an array.
490 NCollection_Array1<IVtk_PointId> aPointIds (1, aNbPoints);
493 Standard_Integer anI;
494 for (anI = 1; anI <= aNbPoints; anI++)
496 gp_Pnt aPoint = aPoints (anI);
500 aPoint.Transform (aPntTransform);
503 // Add a point into output shape data and keep its id in the array.
504 anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z());
505 aPointIds.SetValue (anI, anId);
508 // Create triangles on the created triangulation points.
509 const Poly_Array1OfTriangle& aTriangles = anOcctTriangulation->Triangles();
510 Standard_Integer aNbTriangles = anOcctTriangulation->NbTriangles();
511 Standard_Integer aN1, aN2, aN3;
512 for (anI = 1; anI <= aNbTriangles; anI++)
514 aTriangles(anI).Get (aN1, aN2, aN3); // get indexes of triangle's points
515 // Insert new triangle on these points into output shape data.
516 myShapeData->InsertTriangle (
517 theShapeId, aPointIds(aN1), aPointIds(aN2), aPointIds(aN3), MT_ShadedFace);