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