1 // Created on: 2016-04-19
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15 
16 #include <BRepMesh_ShapeTool.hxx>
17 #include <IMeshData_Edge.hxx>
18 #include <IMeshData_PCurve.hxx>
19 #include <TopoDS_Vertex.hxx>
20 #include <TopExp.hxx>
21 #include <TopExp_Explorer.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRep_Builder.hxx>
24 #include <ShapeAnalysis_Edge.hxx>
25 #include <BRepAdaptor_Curve.hxx>
26 #include <Precision.hxx>
27 #include <Bnd_Box.hxx>
28 
29 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_ShapeTool, Standard_Transient)
30 
31 namespace
32 {
33   //! Auxiliary struct to take a tolerance of edge.
34   struct EdgeTolerance
35   {
Get__anon3614a4520111::EdgeTolerance36     static Standard_Real Get(const TopoDS_Shape& theEdge)
37     {
38       return BRep_Tool::Tolerance(TopoDS::Edge(theEdge));
39     }
40   };
41 
42   //! Auxiliary struct to take a tolerance of vertex.
43   struct VertexTolerance
44   {
Get__anon3614a4520111::VertexTolerance45     static Standard_Real Get(const TopoDS_Shape& theVertex)
46     {
47       return BRep_Tool::Tolerance(TopoDS::Vertex(theVertex));
48     }
49   };
50 
51   //! Returns maximum tolerance of face element of the specified type.
52   template<TopAbs_ShapeEnum ShapeType, class ToleranceExtractor>
MaxTolerance(const TopoDS_Face & theFace)53   Standard_Real MaxTolerance(const TopoDS_Face& theFace)
54   {
55     Standard_Real aMaxTolerance = RealFirst();
56     TopExp_Explorer aExplorer(theFace, ShapeType);
57     for (; aExplorer.More(); aExplorer.Next())
58     {
59       Standard_Real aTolerance = ToleranceExtractor::Get(aExplorer.Current());
60       if (aTolerance > aMaxTolerance)
61         aMaxTolerance = aTolerance;
62     }
63 
64     return aMaxTolerance;
65   }
66 }
67 
68 //=======================================================================
69 //function : MaxFaceTolerance
70 //purpose  :
71 //=======================================================================
MaxFaceTolerance(const TopoDS_Face & theFace)72 Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace)
73 {
74   Standard_Real aMaxTolerance = BRep_Tool::Tolerance(theFace);
75 
76   Standard_Real aTolerance = Max(
77     MaxTolerance<TopAbs_EDGE,   EdgeTolerance  >(theFace),
78     MaxTolerance<TopAbs_VERTEX, VertexTolerance>(theFace));
79 
80   return Max(aMaxTolerance, aTolerance);
81 }
82 
83 //=======================================================================
84 //function : BoxMaxDimension
85 //purpose  :
86 //=======================================================================
BoxMaxDimension(const Bnd_Box & theBox,Standard_Real & theMaxDimension)87 void BRepMesh_ShapeTool::BoxMaxDimension(const Bnd_Box& theBox,
88                                          Standard_Real& theMaxDimension)
89 {
90   if (theBox.IsVoid())
91     return;
92 
93   Standard_Real aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
94   theBox.Get(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
95 
96   theMaxDimension = Max(aMaxX - aMinX, Max(aMaxY - aMinY, aMaxZ - aMinZ));
97 }
98 
99 //=======================================================================
100 //function : CheckAndUpdateFlags
101 //purpose  :
102 //=======================================================================
CheckAndUpdateFlags(const IMeshData::IEdgeHandle & theEdge,const IMeshData::IPCurveHandle & thePCurve)103 void BRepMesh_ShapeTool::CheckAndUpdateFlags (
104   const IMeshData::IEdgeHandle&   theEdge,
105   const IMeshData::IPCurveHandle& thePCurve)
106 {
107   if (!theEdge->GetSameParam () &&
108       !theEdge->GetSameRange () &&
109        theEdge->GetDegenerated ())
110   {
111     // Nothing to do worse.
112     return;
113   }
114 
115   const TopoDS_Edge& aEdge = theEdge->GetEdge ();
116   const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace ();
117 
118   Handle (Geom_Curve) aCurve;
119   Standard_Real aFirstParam, aLastParam;
120   Range (aEdge, aCurve, aFirstParam, aLastParam);
121   if (aCurve.IsNull())
122   {
123     theEdge->SetDegenerated(Standard_True);
124     return;
125   }
126 
127   BRepAdaptor_Curve aCurveOnSurf(aEdge, aFace);
128   if (theEdge->GetSameParam () || theEdge->GetSameRange ())
129   {
130     if (theEdge->GetSameRange ())
131     {
132       const Standard_Real aDiffFirst = aCurveOnSurf.FirstParameter () - aFirstParam;
133       const Standard_Real aDiffLast  = aCurveOnSurf.LastParameter ()  - aLastParam;
134       theEdge->SetSameRange (
135         Abs (aDiffFirst) < Precision::PConfusion () &&
136         Abs (aDiffLast ) < Precision::PConfusion ());
137 
138       if (!theEdge->GetSameRange())
139       {
140         theEdge->SetSameParam(Standard_False);
141       }
142     }
143   }
144 
145   if (!theEdge->GetDegenerated ()/* || theEdge->GetSameParam ()*/)
146   {
147     TopoDS_Vertex aStartVertex, aEndVertex;
148     TopExp::Vertices (aEdge, aStartVertex, aEndVertex);
149     if (aStartVertex.IsNull() || aEndVertex.IsNull())
150     {
151       theEdge->SetDegenerated(Standard_True);
152       return;
153     }
154 
155     if (aStartVertex.IsSame(aEndVertex))
156     {
157       const Standard_Integer aPointsNb          = 20;
158       const Standard_Real    aVertexTolerance   = BRep_Tool::Tolerance (aStartVertex);
159       const Standard_Real    aDu                = (aLastParam - aFirstParam) / aPointsNb;
160       //const Standard_Real    aEdgeTolerance     = BRep_Tool::Tolerance (aEdge);
161       //const Standard_Real    aSqEdgeTolerance   = aEdgeTolerance * aEdgeTolerance;
162 
163       gp_Pnt aPrevPnt;
164       aCurve->D0 (aFirstParam, aPrevPnt);
165 
166       Standard_Real aLength = 0.0;
167       for (Standard_Integer i = 1; i <= aPointsNb; ++i)
168       {
169         const Standard_Real aParameter = aFirstParam + i * aDu;
170         // Calculation of the length of the edge in 3D
171         // in order to check degenerativity
172         gp_Pnt aPnt;
173         aCurve->D0 (aParameter, aPnt);
174         aLength += aPrevPnt.Distance (aPnt);
175 
176         //if (theEdge->GetSameParam ())
177         //{
178         //  // Check that points taken at the 3d and pcurve using
179         //  // same parameter are within tolerance of an edge.
180         //  gp_Pnt aPntOnSurf;
181         //  aCurveOnSurf.D0 (aParameter, aPntOnSurf);
182         //  theEdge->SetSameParam (aPnt.SquareDistance (aPntOnSurf) < aSqEdgeTolerance);
183         //}
184 
185         if (aLength > aVertexTolerance /*&& !theEdge->GetSameParam()*/)
186         {
187           break;
188         }
189 
190         aPrevPnt = aPnt;
191       }
192 
193       theEdge->SetDegenerated (aLength < aVertexTolerance);
194     }
195   }
196 }
197 
198 //=======================================================================
199 //function : AddInFace
200 //purpose  :
201 //=======================================================================
AddInFace(const TopoDS_Face & theFace,Handle (Poly_Triangulation)& theTriangulation)202 void BRepMesh_ShapeTool::AddInFace(
203   const TopoDS_Face&          theFace,
204   Handle(Poly_Triangulation)& theTriangulation)
205 {
206   const TopLoc_Location& aLoc = theFace.Location();
207   if (!aLoc.IsIdentity())
208   {
209     gp_Trsf aTrsf = aLoc.Transformation();
210     aTrsf.Invert();
211     for (Standard_Integer aNodeIter = 1; aNodeIter <= theTriangulation->NbNodes(); ++aNodeIter)
212     {
213       gp_Pnt aNode = theTriangulation->Node (aNodeIter);
214       aNode.Transform (aTrsf);
215       theTriangulation->SetNode (aNodeIter, aNode);
216     }
217   }
218 
219   BRep_Builder aBuilder;
220   aBuilder.UpdateFace(theFace, theTriangulation);
221 }
222 
223 
224 //=======================================================================
225 //function : NullifyFace
226 //purpose  :
227 //=======================================================================
NullifyFace(const TopoDS_Face & theFace)228 void BRepMesh_ShapeTool::NullifyFace (const TopoDS_Face& theFace)
229 {
230   BRep_Builder aBuilder;
231   aBuilder.UpdateFace (theFace, Handle (Poly_Triangulation)());
232 }
233 
234 //=======================================================================
235 //function : NullifyEdge
236 //purpose  :
237 //=======================================================================
NullifyEdge(const TopoDS_Edge & theEdge,const Handle (Poly_Triangulation)& theTriangulation,const TopLoc_Location & theLocation)238 void BRepMesh_ShapeTool::NullifyEdge (
239   const TopoDS_Edge&                 theEdge,
240   const Handle (Poly_Triangulation)& theTriangulation,
241   const TopLoc_Location&             theLocation)
242 {
243   UpdateEdge (theEdge, Handle (Poly_PolygonOnTriangulation)(),
244     theTriangulation, theLocation);
245 }
246 
247 //=======================================================================
248 //function : NullifyEdge
249 //purpose  :
250 //=======================================================================
NullifyEdge(const TopoDS_Edge & theEdge,const TopLoc_Location & theLocation)251 void BRepMesh_ShapeTool::NullifyEdge (
252   const TopoDS_Edge&     theEdge,
253   const TopLoc_Location& theLocation)
254 {
255   BRep_Builder aBuilder;
256   aBuilder.UpdateEdge (theEdge, Handle (Poly_Polygon3D)(), theLocation);
257 }
258 
259 //=======================================================================
260 //function : UpdateEdge
261 //purpose  :
262 //=======================================================================
UpdateEdge(const TopoDS_Edge & theEdge,const Handle (Poly_PolygonOnTriangulation)& thePolygon,const Handle (Poly_Triangulation)& theTriangulation,const TopLoc_Location & theLocation)263 void BRepMesh_ShapeTool::UpdateEdge (
264   const TopoDS_Edge&                          theEdge,
265   const Handle (Poly_PolygonOnTriangulation)& thePolygon,
266   const Handle (Poly_Triangulation)&          theTriangulation,
267   const TopLoc_Location&                      theLocation)
268 {
269   BRep_Builder aBuilder;
270   aBuilder.UpdateEdge (theEdge, thePolygon, theTriangulation, theLocation);
271 }
272 
273 //=======================================================================
274 //function : UpdateEdge
275 //purpose  :
276 //=======================================================================
UpdateEdge(const TopoDS_Edge & theEdge,const Handle (Poly_PolygonOnTriangulation)& thePolygon1,const Handle (Poly_PolygonOnTriangulation)& thePolygon2,const Handle (Poly_Triangulation)& theTriangulation,const TopLoc_Location & theLocation)277 void BRepMesh_ShapeTool::UpdateEdge (
278   const TopoDS_Edge&                          theEdge,
279   const Handle (Poly_PolygonOnTriangulation)& thePolygon1,
280   const Handle (Poly_PolygonOnTriangulation)& thePolygon2,
281   const Handle (Poly_Triangulation)&          theTriangulation,
282   const TopLoc_Location&                      theLocation)
283 {
284   BRep_Builder aBuilder;
285   aBuilder.UpdateEdge (theEdge, thePolygon1, thePolygon2,
286     theTriangulation, theLocation);
287 }
288 
289 //=======================================================================
290 //function : UpdateEdge
291 //purpose  :
292 //=======================================================================
UpdateEdge(const TopoDS_Edge & theEdge,const Handle (Poly_Polygon3D)& thePolygon)293 void BRepMesh_ShapeTool::UpdateEdge(
294   const TopoDS_Edge&            theEdge,
295   const Handle(Poly_Polygon3D)& thePolygon)
296 {
297   BRep_Builder aBuilder;
298   aBuilder.UpdateEdge(theEdge, thePolygon);
299 }
300 
301 //=======================================================================
302 //function : UseLocation
303 //purpose  :
304 //=======================================================================
UseLocation(const gp_Pnt & thePnt,const TopLoc_Location & theLoc)305 gp_Pnt BRepMesh_ShapeTool::UseLocation (
306   const gp_Pnt&          thePnt,
307   const TopLoc_Location& theLoc)
308 {
309   if (theLoc.IsIdentity())
310   {
311     return thePnt;
312   }
313 
314   return thePnt.Transformed (theLoc.Transformation ());
315 }
316 
317 //=======================================================================
318 //function : UVPoints
319 //purpose  :
320 //=======================================================================
UVPoints(const TopoDS_Edge & theEdge,const TopoDS_Face & theFace,gp_Pnt2d & theFirstPoint2d,gp_Pnt2d & theLastPoint2d,const Standard_Boolean isConsiderOrientation)321 Standard_Boolean BRepMesh_ShapeTool::UVPoints (
322   const TopoDS_Edge&      theEdge,
323   const TopoDS_Face&      theFace,
324   gp_Pnt2d&               theFirstPoint2d,
325   gp_Pnt2d&               theLastPoint2d,
326   const Standard_Boolean  isConsiderOrientation)
327 {
328 
329   Handle (Geom2d_Curve) aCurve2d;
330   Standard_Real aFirstParam, aLastParam;
331   if (!Range(theEdge, theFace, aCurve2d, aFirstParam, aLastParam, isConsiderOrientation))
332   {
333     return Standard_False;
334   }
335 
336   aCurve2d->D0 (aFirstParam, theFirstPoint2d);
337   aCurve2d->D0 (aLastParam,  theLastPoint2d);
338   return Standard_True;
339 }
340 
341 //=======================================================================
342 //function : Range
343 //purpose  :
344 //=======================================================================
Range(const TopoDS_Edge & theEdge,const TopoDS_Face & theFace,Handle (Geom2d_Curve)& thePCurve,Standard_Real & theFirstParam,Standard_Real & theLastParam,const Standard_Boolean isConsiderOrientation)345 Standard_Boolean BRepMesh_ShapeTool::Range (
346   const TopoDS_Edge&      theEdge,
347   const TopoDS_Face&      theFace,
348   Handle (Geom2d_Curve)&  thePCurve,
349   Standard_Real&          theFirstParam,
350   Standard_Real&          theLastParam,
351   const Standard_Boolean  isConsiderOrientation)
352 {
353 
354   ShapeAnalysis_Edge aEdge;
355   return aEdge.PCurve (theEdge, theFace, thePCurve,
356     theFirstParam, theLastParam,
357     isConsiderOrientation);
358 }
359 
360 //=======================================================================
361 //function : Range
362 //purpose  :
363 //=======================================================================
Range(const TopoDS_Edge & theEdge,Handle (Geom_Curve)& theCurve,Standard_Real & theFirstParam,Standard_Real & theLastParam,const Standard_Boolean isConsiderOrientation)364 Standard_Boolean BRepMesh_ShapeTool::Range (
365   const TopoDS_Edge&      theEdge,
366   Handle (Geom_Curve)&    theCurve,
367   Standard_Real&          theFirstParam,
368   Standard_Real&          theLastParam,
369   const Standard_Boolean  isConsiderOrientation)
370 {
371 
372   ShapeAnalysis_Edge aEdge;
373   return aEdge.Curve3d (theEdge, theCurve,
374     theFirstParam, theLastParam,
375     isConsiderOrientation);
376 }
377