b311480e |
1 | // Copyright (c) 1995-1999 Matra Datavision |
973c2be1 |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
b311480e |
5 | // |
d5f74e42 |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
b311480e |
14 | |
fc9b36d6 |
15 | #include <BRepMesh_ShapeTool.hxx> |
16 | |
17 | #include <Bnd_Box.hxx> |
18 | #include <TopoDS_Edge.hxx> |
7fd59977 |
19 | #include <BRepBndLib.hxx> |
fc9b36d6 |
20 | #include <TopoDS.hxx> |
21 | #include <BRep_Tool.hxx> |
22 | #include <TopExp_Explorer.hxx> |
23 | #include <BRepAdaptor_HSurface.hxx> |
24 | #include <TColgp_Array1OfPnt.hxx> |
25 | #include <Poly_Triangulation.hxx> |
7fd59977 |
26 | #include <BRep_Builder.hxx> |
ceb418e1 |
27 | #include <TopExp.hxx> |
28 | #include <BRepAdaptor_Curve.hxx> |
7fd59977 |
29 | |
fc9b36d6 |
30 | namespace { |
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 | }; |
7fd59977 |
39 | |
fc9b36d6 |
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 | }; |
7fd59977 |
48 | |
fc9b36d6 |
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; |
7fd59977 |
63 | } |
7fd59977 |
64 | } |
65 | |
fc9b36d6 |
66 | //======================================================================= |
67 | //function : BoxMaxDimension |
68 | //purpose : |
69 | //======================================================================= |
70 | Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace) |
7fd59977 |
71 | { |
fc9b36d6 |
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); |
7fd59977 |
79 | } |
80 | |
fc9b36d6 |
81 | //======================================================================= |
82 | //function : BoxMaxDimension |
83 | //purpose : |
84 | //======================================================================= |
85 | void BRepMesh_ShapeTool::BoxMaxDimension(const Bnd_Box& theBox, |
86 | Standard_Real& theMaxDimension) |
7fd59977 |
87 | { |
fc9b36d6 |
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)); |
7fd59977 |
95 | } |
96 | |
fc9b36d6 |
97 | //======================================================================= |
98 | //function : RelativeEdgeDeflection |
99 | //purpose : |
100 | //======================================================================= |
101 | Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection( |
102 | const TopoDS_Edge& theEdge, |
103 | const Standard_Real theDeflection, |
104 | const Standard_Real theMaxShapeSize, |
105 | Standard_Real& theAdjustmentCoefficient) |
7fd59977 |
106 | { |
fc9b36d6 |
107 | theAdjustmentCoefficient = 1.; |
108 | Standard_Real aDefEdge = theDeflection; |
109 | if(theEdge.IsNull()) |
110 | return aDefEdge; |
111 | |
112 | Bnd_Box aBox; |
ceb418e1 |
113 | BRepBndLib::Add(theEdge, aBox, Standard_False); |
fc9b36d6 |
114 | BoxMaxDimension(aBox, aDefEdge); |
115 | |
116 | // Adjust resulting value in relation to the total size |
117 | theAdjustmentCoefficient = theMaxShapeSize / (2 * aDefEdge); |
118 | if (theAdjustmentCoefficient < 0.5) |
119 | theAdjustmentCoefficient = 0.5; |
120 | else if (theAdjustmentCoefficient > 2.) |
121 | theAdjustmentCoefficient = 2.; |
122 | |
123 | return (theAdjustmentCoefficient * aDefEdge * theDeflection); |
7fd59977 |
124 | } |
125 | |
fc9b36d6 |
126 | //======================================================================= |
127 | //function : FindUV |
128 | //purpose : |
129 | //======================================================================= |
130 | gp_XY BRepMesh_ShapeTool::FindUV( |
ceb418e1 |
131 | const Standard_Integer theIndexOfPnt3d, |
132 | const gp_Pnt2d& thePnt2d, |
ceb418e1 |
133 | const Standard_Real theMinDistance, |
134 | const Handle(BRepMesh_FaceAttribute)& theFaceAttribute) |
7fd59977 |
135 | { |
fc9b36d6 |
136 | const gp_XY& aPnt2d = thePnt2d.Coord(); |
2caff0b3 |
137 | BRepMesh::HDMapOfIntegerListOfXY& aLocation2D = |
ceb418e1 |
138 | theFaceAttribute->ChangeLocation2D(); |
139 | |
2caff0b3 |
140 | if (!aLocation2D->IsBound(theIndexOfPnt3d)) |
fc9b36d6 |
141 | { |
848fa7e3 |
142 | BRepMesh::ListOfXY aPoints2d; |
fc9b36d6 |
143 | aPoints2d.Append(aPnt2d); |
2caff0b3 |
144 | aLocation2D->Bind(theIndexOfPnt3d, aPoints2d); |
fc9b36d6 |
145 | return aPnt2d; |
146 | } |
147 | |
2caff0b3 |
148 | BRepMesh::ListOfXY& aPoints2d = aLocation2D->ChangeFind(theIndexOfPnt3d); |
fc9b36d6 |
149 | |
150 | // Find the most closest 2d point to the given one. |
151 | gp_XY aUV; |
152 | Standard_Real aMinDist = RealLast(); |
848fa7e3 |
153 | BRepMesh::ListOfXY::Iterator aPoint2dIt(aPoints2d); |
fc9b36d6 |
154 | for (; aPoint2dIt.More(); aPoint2dIt.Next()) |
155 | { |
156 | const gp_XY& aCurPnt2d = aPoint2dIt.Value(); |
157 | |
158 | Standard_Real aDist = (aPnt2d - aCurPnt2d).Modulus(); |
159 | if (aDist < aMinDist) |
160 | { |
161 | aUV = aCurPnt2d; |
162 | aMinDist = aDist; |
163 | } |
164 | } |
165 | |
81093856 |
166 | const Standard_Real aTolerance = theMinDistance; |
fc9b36d6 |
167 | |
168 | // Get face limits |
ceb418e1 |
169 | Standard_Real aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin(); |
170 | Standard_Real aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin(); |
fc9b36d6 |
171 | |
172 | const Standard_Real Utol2d = .5 * aDiffU; |
173 | const Standard_Real Vtol2d = .5 * aDiffV; |
174 | |
ceb418e1 |
175 | const Handle(BRepAdaptor_HSurface)& aSurface = theFaceAttribute->Surface(); |
176 | const gp_Pnt aPnt1 = aSurface->Value(aUV.X(), aUV.Y()); |
177 | const gp_Pnt aPnt2 = aSurface->Value(aPnt2d.X(), aPnt2d.Y()); |
fc9b36d6 |
178 | |
179 | //! If selected point is too far from the given one in parametric space |
180 | //! or their positions in 3d are different, add the given point as unique. |
181 | if (Abs(aUV.X() - aPnt2d.X()) > Utol2d || |
182 | Abs(aUV.Y() - aPnt2d.Y()) > Vtol2d || |
183 | !aPnt1.IsEqual(aPnt2, aTolerance)) |
184 | { |
185 | aUV = aPnt2d; |
186 | aPoints2d.Append(aUV); |
187 | } |
188 | |
189 | return aUV; |
7fd59977 |
190 | } |
191 | |
fc9b36d6 |
192 | //======================================================================= |
193 | //function : AddInFace |
194 | //purpose : |
195 | //======================================================================= |
196 | void BRepMesh_ShapeTool::AddInFace( |
197 | const TopoDS_Face& theFace, |
198 | Handle(Poly_Triangulation)& theTriangulation) |
7fd59977 |
199 | { |
fc9b36d6 |
200 | const TopLoc_Location& aLoc = theFace.Location(); |
201 | if (!aLoc.IsIdentity()) |
202 | { |
203 | gp_Trsf aTrsf = aLoc.Transformation(); |
204 | aTrsf.Invert(); |
205 | |
206 | TColgp_Array1OfPnt& aNodes = theTriangulation->ChangeNodes(); |
207 | for (Standard_Integer i = aNodes.Lower(); i <= aNodes.Upper(); ++i) |
208 | aNodes(i).Transform(aTrsf); |
209 | } |
210 | |
211 | BRep_Builder aBuilder; |
212 | aBuilder.UpdateFace(theFace, theTriangulation); |
7fd59977 |
213 | } |
214 | |
fc9b36d6 |
215 | //======================================================================= |
216 | //function : NullifyFace |
217 | //purpose : |
218 | //======================================================================= |
219 | void BRepMesh_ShapeTool::NullifyFace(const TopoDS_Face& theFace) |
7fd59977 |
220 | { |
fc9b36d6 |
221 | BRep_Builder aBuilder; |
222 | aBuilder.UpdateFace(theFace, Handle(Poly_Triangulation)()); |
7fd59977 |
223 | } |
224 | |
fc9b36d6 |
225 | //======================================================================= |
226 | //function : NullifyEdge |
227 | //purpose : |
228 | //======================================================================= |
229 | void BRepMesh_ShapeTool::NullifyEdge( |
230 | const TopoDS_Edge& theEdge, |
231 | const Handle(Poly_Triangulation)& theTriangulation, |
232 | const TopLoc_Location& theLocation) |
7fd59977 |
233 | { |
fc9b36d6 |
234 | UpdateEdge(theEdge, Handle(Poly_PolygonOnTriangulation)(), |
235 | theTriangulation, theLocation); |
7fd59977 |
236 | } |
237 | |
fc9b36d6 |
238 | //======================================================================= |
239 | //function : UpdateEdge |
240 | //purpose : |
241 | //======================================================================= |
242 | void BRepMesh_ShapeTool::UpdateEdge( |
243 | const TopoDS_Edge& theEdge, |
244 | const Handle(Poly_PolygonOnTriangulation)& thePolygon, |
245 | const Handle(Poly_Triangulation)& theTriangulation, |
246 | const TopLoc_Location& theLocation) |
247 | { |
248 | BRep_Builder aBuilder; |
249 | aBuilder.UpdateEdge(theEdge, thePolygon, theTriangulation, theLocation); |
250 | } |
7fd59977 |
251 | |
fc9b36d6 |
252 | //======================================================================= |
253 | //function : UpdateEdge |
254 | //purpose : |
255 | //======================================================================= |
256 | void BRepMesh_ShapeTool::UpdateEdge( |
257 | const TopoDS_Edge& theEdge, |
258 | const Handle(Poly_PolygonOnTriangulation)& thePolygon1, |
259 | const Handle(Poly_PolygonOnTriangulation)& thePolygon2, |
260 | const Handle(Poly_Triangulation)& theTriangulation, |
261 | const TopLoc_Location& theLocation) |
7fd59977 |
262 | { |
fc9b36d6 |
263 | BRep_Builder aBuilder; |
264 | aBuilder.UpdateEdge(theEdge, thePolygon1, thePolygon2, |
265 | theTriangulation, theLocation); |
7fd59977 |
266 | } |
ceb418e1 |
267 | |
268 | //======================================================================= |
269 | //function : UseLocation |
270 | //purpose : |
271 | //======================================================================= |
272 | gp_Pnt BRepMesh_ShapeTool::UseLocation(const gp_Pnt& thePnt, |
273 | const TopLoc_Location& theLoc) |
274 | { |
275 | if (theLoc.IsIdentity()) |
276 | return thePnt; |
277 | |
278 | return thePnt.Transformed(theLoc.Transformation()); |
279 | } |
280 | |
281 | //======================================================================= |
282 | //function : IsDegenerated |
283 | //purpose : |
284 | //======================================================================= |
285 | Standard_Boolean BRepMesh_ShapeTool::IsDegenerated( |
286 | const TopoDS_Edge& theEdge, |
287 | const TopoDS_Face& theFace) |
288 | { |
289 | // Get vertices |
290 | TopoDS_Vertex pBegin, pEnd; |
291 | TopExp::Vertices(theEdge, pBegin, pEnd); |
292 | if (pBegin.IsNull() || pEnd.IsNull()) |
293 | return Standard_True; |
294 | |
295 | if (BRep_Tool::Degenerated(theEdge)) |
296 | return Standard_True; |
297 | |
298 | if (!pBegin.IsSame(pEnd)) |
299 | return Standard_False; |
300 | |
301 | Standard_Real wFirst, wLast; |
302 | BRep_Tool::Range(theEdge, theFace, wFirst, wLast); |
303 | |
304 | // calculation of the length of the edge in 3D |
305 | Standard_Real longueur = 0.0; |
306 | Standard_Real du = (wLast - wFirst) * 0.05; |
307 | gp_Pnt P1, P2; |
308 | BRepAdaptor_Curve BC(theEdge); |
309 | BC.D0(wFirst, P1); |
310 | Standard_Real tolV = BRep_Tool::Tolerance(pBegin); |
311 | Standard_Real tolV2 = 1.2 * tolV; |
312 | |
313 | for (Standard_Integer l = 1; l <= 20; ++l) |
314 | { |
315 | BC.D0(wFirst + l * du, P2); |
316 | longueur += P1.Distance(P2); |
317 | |
318 | if (longueur > tolV2) |
319 | break; |
320 | |
321 | P1 = P2; |
322 | } |
323 | |
324 | if (longueur < tolV2) |
325 | return Standard_True; |
326 | |
327 | return Standard_False; |
328 | } |