Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 1995-10-20 |
2 | // Created by: Yves FRICAUD | |
3 | // Copyright (c) 1995-1999 Matra Datavision | |
973c2be1 | 4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e | 5 | // |
973c2be1 | 6 | // This file is part of Open CASCADE Technology software library. |
b311480e | 7 | // |
d5f74e42 | 8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
12 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 13 | // |
973c2be1 | 14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. | |
7fd59977 | 16 | |
42cf5bc1 | 17 | |
18 | #include <Adaptor3d_Surface.hxx> | |
420b38fd | 19 | #include <BOPTools_AlgoTools.hxx> |
20 | #include <BOPTools_AlgoTools3D.hxx> | |
42cf5bc1 | 21 | #include <BRep_Builder.hxx> |
22 | #include <BRep_Tool.hxx> | |
23 | #include <BRepAdaptor_Curve.hxx> | |
24 | #include <BRepAdaptor_Surface.hxx> | |
25 | #include <BRepOffset_Analyse.hxx> | |
7fd59977 | 26 | #include <BRepOffset_Interval.hxx> |
7fd59977 | 27 | #include <BRepOffset_ListIteratorOfListOfInterval.hxx> |
42cf5bc1 | 28 | #include <BRepOffset_Tool.hxx> |
420b38fd | 29 | #include <BRepPrimAPI_MakePrism.hxx> |
7fd59977 | 30 | #include <BRepTools.hxx> |
42cf5bc1 | 31 | #include <Geom2d_Curve.hxx> |
32 | #include <Geom_Curve.hxx> | |
33 | #include <Geom_Surface.hxx> | |
7fd59977 | 34 | #include <gp.hxx> |
7fd59977 | 35 | #include <gp_Dir.hxx> |
36 | #include <gp_Pnt.hxx> | |
37 | #include <gp_Pnt2d.hxx> | |
42cf5bc1 | 38 | #include <gp_Vec.hxx> |
420b38fd | 39 | #include <IntTools_Context.hxx> |
42cf5bc1 | 40 | #include <Precision.hxx> |
7fd59977 | 41 | #include <TopExp.hxx> |
42 | #include <TopExp_Explorer.hxx> | |
7fd59977 | 43 | #include <TopoDS.hxx> |
42cf5bc1 | 44 | #include <TopoDS_Compound.hxx> |
7fd59977 | 45 | #include <TopoDS_Edge.hxx> |
42cf5bc1 | 46 | #include <TopoDS_Face.hxx> |
47 | #include <TopoDS_Shape.hxx> | |
48 | #include <TopoDS_Vertex.hxx> | |
7fd59977 | 49 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
50 | #include <TopTools_MapOfShape.hxx> | |
eff3eff9 | 51 | #include <ChFi3d.hxx> |
7fd59977 | 52 | |
d804b26d | 53 | static void CorrectOrientationOfTangent(gp_Vec& TangVec, |
54 | const TopoDS_Vertex& aVertex, | |
55 | const TopoDS_Edge& anEdge) | |
56 | { | |
57 | TopoDS_Vertex Vlast = TopExp::LastVertex(anEdge); | |
58 | if (aVertex.IsSame(Vlast)) | |
59 | TangVec.Reverse(); | |
60 | } | |
7fd59977 | 61 | //======================================================================= |
62 | //function : BRepOffset_Analyse | |
63 | //purpose : | |
64 | //======================================================================= | |
65 | ||
66 | BRepOffset_Analyse::BRepOffset_Analyse() | |
420b38fd | 67 | : myOffset (0.0), myDone (Standard_False) |
7fd59977 | 68 | { |
69 | } | |
70 | ||
7fd59977 | 71 | //======================================================================= |
72 | //function : BRepOffset_Analyse | |
73 | //purpose : | |
74 | //======================================================================= | |
7fd59977 | 75 | BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S, |
420b38fd | 76 | const Standard_Real Angle) |
77 | : myOffset (0.0), myDone (Standard_False) | |
7fd59977 | 78 | { |
79 | Perform( S, Angle); | |
80 | } | |
81 | ||
82 | //======================================================================= | |
83 | //function : EdgeAnlyse | |
84 | //purpose : | |
85 | //======================================================================= | |
7fd59977 | 86 | static void EdgeAnalyse(const TopoDS_Edge& E, |
b0091bc9 | 87 | const TopoDS_Face& F1, |
88 | const TopoDS_Face& F2, | |
89 | const Standard_Real SinTol, | |
90 | BRepOffset_ListOfInterval& LI) | |
7fd59977 | 91 | { |
7fd59977 | 92 | Standard_Real f,l; |
b0091bc9 | 93 | BRep_Tool::Range(E, F1, f, l); |
94 | BRepOffset_Interval I; | |
95 | I.First(f); I.Last(l); | |
3f54cc41 | 96 | // |
97 | BRepAdaptor_Surface aBAsurf1(F1, Standard_False); | |
98 | GeomAbs_SurfaceType aSurfType1 = aBAsurf1.GetType(); | |
99 | ||
100 | BRepAdaptor_Surface aBAsurf2(F2, Standard_False); | |
101 | GeomAbs_SurfaceType aSurfType2 = aBAsurf2.GetType(); | |
102 | ||
103 | Standard_Boolean isTwoPlanes = (aSurfType1 == GeomAbs_Plane && aSurfType2 == GeomAbs_Plane); | |
104 | ||
105 | ChFiDS_TypeOfConcavity ConnectType = ChFiDS_Other; | |
106 | ||
107 | if (isTwoPlanes) //then use only strong condition | |
108 | { | |
109 | if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) | |
110 | ConnectType = ChFiDS_Tangential; | |
111 | else | |
112 | ConnectType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_False); | |
7fd59977 | 113 | } |
3f54cc41 | 114 | else |
b0091bc9 | 115 | { |
3f54cc41 | 116 | if (ChFi3d::IsTangentFaces(E, F1, F2)) //weak condition |
117 | ConnectType = ChFiDS_Tangential; | |
118 | else | |
119 | ConnectType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_False); | |
7fd59977 | 120 | } |
3f54cc41 | 121 | |
122 | I.Type(ConnectType); | |
7fd59977 | 123 | LI.Append(I); |
124 | } | |
125 | ||
126 | //======================================================================= | |
127 | //function : BuildAncestors | |
128 | //purpose : | |
129 | //======================================================================= | |
7fd59977 | 130 | static void BuildAncestors (const TopoDS_Shape& S, |
f1191d30 | 131 | TopTools_IndexedDataMapOfShapeListOfShape& MA) |
7fd59977 | 132 | { |
133 | MA.Clear(); | |
f1191d30 | 134 | TopExp::MapShapesAndUniqueAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA); |
135 | TopExp::MapShapesAndUniqueAncestors(S,TopAbs_EDGE ,TopAbs_FACE,MA); | |
7fd59977 | 136 | } |
137 | ||
7fd59977 | 138 | //======================================================================= |
139 | //function : Perform | |
140 | //purpose : | |
141 | //======================================================================= | |
7fd59977 | 142 | void BRepOffset_Analyse::Perform (const TopoDS_Shape& S, |
420b38fd | 143 | const Standard_Real Angle) |
7fd59977 | 144 | { |
145 | myShape = S; | |
420b38fd | 146 | myNewFaces .Clear(); |
147 | myGenerated.Clear(); | |
148 | myReplacement.Clear(); | |
149 | myDescendants.Clear(); | |
7fd59977 | 150 | |
420b38fd | 151 | myAngle = Angle; |
152 | Standard_Real SinTol = Abs (Sin(Angle)); | |
7fd59977 | 153 | |
154 | // Build ancestors. | |
420b38fd | 155 | BuildAncestors (S,myAncestors); |
156 | ||
157 | TopTools_ListOfShape aLETang; | |
7fd59977 | 158 | |
7fd59977 | 159 | TopExp_Explorer Exp(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); |
160 | for ( ; Exp.More(); Exp.Next()) { | |
161 | const TopoDS_Edge& E = TopoDS::Edge(Exp.Current()); | |
420b38fd | 162 | if (!myMapEdgeType.IsBound(E)) { |
7fd59977 | 163 | BRepOffset_ListOfInterval LI; |
420b38fd | 164 | myMapEdgeType.Bind(E,LI); |
7fd59977 | 165 | |
166 | const TopTools_ListOfShape& L = Ancestors(E); | |
167 | if ( L.IsEmpty()) | |
420b38fd | 168 | continue; |
7fd59977 | 169 | |
170 | if (L.Extent() == 2) { | |
420b38fd | 171 | const TopoDS_Face& F1 = TopoDS::Face (L.First()); |
172 | const TopoDS_Face& F2 = TopoDS::Face (L.Last()); | |
173 | EdgeAnalyse (E, F1, F2, SinTol, myMapEdgeType (E)); | |
174 | ||
175 | // For tangent faces add artificial perpendicular face | |
176 | // to close the gap between them (if they have different offset values) | |
177 | if (myMapEdgeType(E).Last().Type() == ChFiDS_Tangential) | |
178 | aLETang.Append (E); | |
7fd59977 | 179 | } |
180 | else if (L.Extent() == 1) { | |
420b38fd | 181 | Standard_Real U1, U2; |
182 | const TopoDS_Face& F = TopoDS::Face (L.First()); | |
183 | BRep_Tool::Range (E, F, U1, U2); | |
184 | BRepOffset_Interval Inter (U1, U2, ChFiDS_Other); | |
185 | ||
186 | if (!BRepTools::IsReallyClosed (E, F)) { | |
187 | Inter.Type (ChFiDS_FreeBound); | |
188 | } | |
189 | myMapEdgeType (E).Append (Inter); | |
7fd59977 | 190 | } |
191 | else { | |
0797d9d3 | 192 | #ifdef OCCT_DEBUG |
04232180 | 193 | std::cout <<"edge shared by more than two faces"<<std::endl; |
7fd59977 | 194 | #endif |
195 | } | |
196 | } | |
197 | } | |
420b38fd | 198 | |
199 | TreatTangentFaces (aLETang); | |
7fd59977 | 200 | myDone = Standard_True; |
201 | } | |
202 | ||
203 | //======================================================================= | |
420b38fd | 204 | //function : Generated |
7fd59977 | 205 | //purpose : |
206 | //======================================================================= | |
420b38fd | 207 | void BRepOffset_Analyse::TreatTangentFaces (const TopTools_ListOfShape& theLE) |
7fd59977 | 208 | { |
420b38fd | 209 | if (theLE.IsEmpty() || myFaceOffsetMap.IsEmpty()) |
210 | { | |
211 | // Noting to do: either there are no tangent faces in the shape or | |
212 | // the face offset map has not been provided | |
213 | return; | |
214 | } | |
215 | ||
216 | // Select the edges which connect faces with different offset values | |
217 | TopoDS_Compound aCETangent; | |
218 | BRep_Builder().MakeCompound (aCETangent); | |
219 | // Bind to each tangent edge a max offset value of its faces | |
220 | TopTools_DataMapOfShapeReal anEdgeOffsetMap; | |
221 | // Bind vertices of the tangent edges with connected edges | |
222 | // of the face with smaller offset value | |
223 | TopTools_DataMapOfShapeShape aDMVEMin; | |
224 | for (TopTools_ListOfShape::Iterator it (theLE); it.More(); it.Next()) | |
225 | { | |
226 | const TopoDS_Shape& aE = it.Value(); | |
227 | const TopTools_ListOfShape& aLA = Ancestors (aE); | |
228 | ||
229 | const TopoDS_Shape& aF1 = aLA.First(), aF2 = aLA.Last(); | |
230 | ||
231 | const Standard_Real *pOffsetVal1 = myFaceOffsetMap.Seek (aF1); | |
232 | const Standard_Real *pOffsetVal2 = myFaceOffsetMap.Seek (aF2); | |
233 | const Standard_Real anOffsetVal1 = pOffsetVal1 ? Abs (*pOffsetVal1) : myOffset; | |
234 | const Standard_Real anOffsetVal2 = pOffsetVal2 ? Abs (*pOffsetVal2) : myOffset; | |
235 | if (anOffsetVal1 != anOffsetVal2) | |
236 | { | |
237 | BRep_Builder().Add (aCETangent, aE); | |
238 | anEdgeOffsetMap.Bind (aE, Max (anOffsetVal1, anOffsetVal2)); | |
239 | ||
240 | const TopoDS_Shape& aFMin = anOffsetVal1 < anOffsetVal2 ? aF1 : aF2; | |
241 | for (TopoDS_Iterator itV (aE); itV.More(); itV.Next()) | |
242 | { | |
243 | const TopoDS_Shape& aV = itV.Value(); | |
244 | if (Ancestors (aV).Extent() == 3) | |
245 | { | |
246 | for (TopExp_Explorer expE (aFMin, TopAbs_EDGE); expE.More(); expE.Next()) | |
247 | { | |
248 | const TopoDS_Shape& aEMin = expE.Current(); | |
249 | if (aEMin.IsSame (aE)) | |
250 | continue; | |
251 | for (TopoDS_Iterator itV1 (aEMin); itV1.More(); itV1.Next()) | |
252 | { | |
253 | const TopoDS_Shape& aVx = itV1.Value(); | |
254 | if (aV.IsSame (aVx)) | |
255 | aDMVEMin.Bind (aV, aEMin); | |
256 | } | |
257 | } | |
258 | } | |
259 | } | |
260 | } | |
261 | } | |
262 | ||
263 | if (anEdgeOffsetMap.IsEmpty()) | |
264 | return; | |
265 | ||
266 | // Create map of Face ancestors for the vertices on tangent edges | |
267 | TopTools_DataMapOfShapeListOfShape aDMVFAnc; | |
268 | ||
269 | for (TopTools_ListOfShape::Iterator itE (theLE); itE.More(); itE.Next()) | |
270 | { | |
271 | const TopoDS_Shape& aE = itE.Value(); | |
272 | if (!anEdgeOffsetMap.IsBound (aE)) | |
273 | continue; | |
274 | ||
275 | TopTools_MapOfShape aMFence; | |
276 | { | |
277 | const TopTools_ListOfShape& aLEA = Ancestors (aE); | |
278 | for (TopTools_ListOfShape::Iterator itLEA (aLEA); itLEA.More(); itLEA.Next()) | |
279 | aMFence.Add (itLEA.Value()); | |
280 | } | |
281 | ||
282 | for (TopoDS_Iterator itV (aE); itV.More(); itV.Next()) | |
283 | { | |
284 | const TopoDS_Shape& aV = itV.Value(); | |
285 | TopTools_ListOfShape* pLFA = aDMVFAnc.Bound (aV, TopTools_ListOfShape()); | |
286 | const TopTools_ListOfShape& aLVA = Ancestors (aV); | |
287 | for (TopTools_ListOfShape::Iterator itLVA (aLVA); itLVA.More(); itLVA.Next()) | |
288 | { | |
289 | const TopoDS_Edge& aEA = TopoDS::Edge (itLVA.Value()); | |
290 | const BRepOffset_ListOfInterval* pIntervals = myMapEdgeType.Seek (aEA); | |
291 | if (!pIntervals || pIntervals->IsEmpty()) | |
292 | continue; | |
293 | if (pIntervals->First().Type() == ChFiDS_Tangential) | |
294 | continue; | |
295 | ||
296 | const TopTools_ListOfShape& aLEA = Ancestors (aEA); | |
297 | for (TopTools_ListOfShape::Iterator itLEA (aLEA); itLEA.More(); itLEA.Next()) | |
298 | { | |
299 | const TopoDS_Shape& aFA = itLEA.Value(); | |
300 | if (aMFence.Add (aFA)) | |
301 | pLFA->Append (aFA); | |
302 | } | |
303 | } | |
304 | } | |
305 | } | |
306 | ||
307 | Handle(IntTools_Context) aCtx = new IntTools_Context(); | |
308 | // Tangency criteria | |
309 | Standard_Real aSinTol = Abs (Sin (myAngle)); | |
310 | ||
311 | // Make blocks of connected edges | |
312 | TopTools_ListOfListOfShape aLCB; | |
313 | TopTools_IndexedDataMapOfShapeListOfShape aMVEMap; | |
314 | ||
315 | BOPTools_AlgoTools::MakeConnexityBlocks (aCETangent, TopAbs_VERTEX, TopAbs_EDGE, aLCB, aMVEMap); | |
316 | ||
317 | // Analyze each block to find co-planar edges | |
318 | for (TopTools_ListOfListOfShape::Iterator itLCB (aLCB); itLCB.More(); itLCB.Next()) | |
319 | { | |
320 | const TopTools_ListOfShape& aCB = itLCB.Value(); | |
321 | ||
322 | TopTools_MapOfShape aMFence; | |
323 | for (TopTools_ListOfShape::Iterator itCB1 (aCB); itCB1.More(); itCB1.Next()) | |
324 | { | |
325 | const TopoDS_Edge& aE1 = TopoDS::Edge (itCB1.Value()); | |
326 | if (!aMFence.Add (aE1)) | |
327 | continue; | |
328 | ||
329 | TopoDS_Compound aBlock; | |
330 | BRep_Builder().MakeCompound (aBlock); | |
331 | BRep_Builder().Add (aBlock, aE1.Oriented (TopAbs_FORWARD)); | |
332 | ||
333 | Standard_Real anOffset = anEdgeOffsetMap.Find (aE1); | |
334 | const TopTools_ListOfShape& aLF1 = Ancestors (aE1); | |
335 | ||
336 | gp_Dir aDN1; | |
337 | BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE1, TopoDS::Face (aLF1.First()), aDN1); | |
338 | ||
339 | TopTools_ListOfShape::Iterator itCB2 = itCB1; | |
340 | for (itCB2.Next(); itCB2.More(); itCB2.Next()) | |
341 | { | |
342 | const TopoDS_Edge& aE2 = TopoDS::Edge (itCB2.Value()); | |
343 | if (aMFence.Contains (aE2)) | |
344 | continue; | |
345 | ||
346 | const TopTools_ListOfShape& aLF2 = Ancestors (aE2); | |
347 | ||
348 | gp_Dir aDN2; | |
349 | BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE2, TopoDS::Face (aLF2.First()), aDN2); | |
350 | ||
351 | if (aDN1.XYZ().Crossed (aDN2.XYZ()).Modulus() < aSinTol) | |
352 | { | |
353 | BRep_Builder().Add (aBlock, aE2.Oriented (TopAbs_FORWARD)); | |
354 | aMFence.Add (aE2); | |
355 | anOffset = Max (anOffset, anEdgeOffsetMap.Find (aE2)); | |
356 | } | |
357 | } | |
358 | ||
359 | // Make the prism | |
360 | BRepPrimAPI_MakePrism aMP (aBlock, gp_Vec (aDN1.XYZ()) * anOffset); | |
361 | if (!aMP.IsDone()) | |
362 | continue; | |
363 | ||
364 | TopTools_IndexedDataMapOfShapeListOfShape aPrismAncestors; | |
365 | TopExp::MapShapesAndAncestors (aMP.Shape(), TopAbs_EDGE, TopAbs_FACE, aPrismAncestors); | |
366 | TopExp::MapShapesAndAncestors (aMP.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aPrismAncestors); | |
367 | ||
368 | for (TopoDS_Iterator itE (aBlock); itE.More(); itE.Next()) | |
369 | { | |
370 | const TopoDS_Edge& aE = TopoDS::Edge (itE.Value()); | |
371 | const TopTools_ListOfShape& aLG = aMP.Generated (aE); | |
372 | TopoDS_Face aFNew = TopoDS::Face (aLG.First()); | |
373 | ||
374 | TopTools_ListOfShape& aLA = myAncestors.ChangeFromKey (aE); | |
375 | ||
376 | TopoDS_Shape aF1 = aLA.First(); | |
377 | TopoDS_Shape aF2 = aLA.Last(); | |
378 | ||
379 | const Standard_Real *pOffsetVal1 = myFaceOffsetMap.Seek (aF1); | |
380 | const Standard_Real *pOffsetVal2 = myFaceOffsetMap.Seek (aF2); | |
381 | const Standard_Real anOffsetVal1 = pOffsetVal1 ? Abs (*pOffsetVal1) : myOffset; | |
382 | const Standard_Real anOffsetVal2 = pOffsetVal2 ? Abs (*pOffsetVal2) : myOffset; | |
383 | ||
384 | const TopoDS_Shape& aFToRemove = anOffsetVal1 > anOffsetVal2 ? aF1 : aF2; | |
385 | const TopoDS_Shape& aFOpposite = anOffsetVal1 > anOffsetVal2 ? aF2 : aF1; | |
386 | ||
387 | // Orient the face so its normal is directed to smaller offset face | |
388 | { | |
389 | // get normal of the new face | |
390 | gp_Dir aDN; | |
391 | BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aFNew, aDN); | |
392 | ||
393 | // get bi-normal for the aFOpposite | |
394 | TopoDS_Edge aEInF; | |
395 | for (TopExp_Explorer aExpE (aFOpposite, TopAbs_EDGE); aExpE.More(); aExpE.Next()) | |
396 | { | |
397 | if (aE.IsSame (aExpE.Current())) | |
398 | { | |
399 | aEInF = TopoDS::Edge (aExpE.Current()); | |
400 | break; | |
401 | } | |
402 | } | |
403 | ||
404 | gp_Pnt2d aP2d; | |
405 | gp_Pnt aPInF; | |
406 | Standard_Real f, l; | |
407 | const Handle(Geom_Curve)& aC3D = BRep_Tool::Curve (aEInF, f, l); | |
408 | gp_Pnt aPOnE = aC3D->Value ((f + l) / 2.); | |
409 | BOPTools_AlgoTools3D::PointNearEdge (aEInF, TopoDS::Face (aFOpposite), (f + l) / 2., 1.e-5, aP2d, aPInF); | |
410 | ||
411 | gp_Vec aBN (aPOnE, aPInF); | |
412 | ||
413 | if (aBN.Dot (aDN) < 0) | |
414 | aFNew.Reverse(); | |
415 | } | |
416 | ||
417 | // Remove the face with bigger offset value from edge ancestors | |
418 | for (TopTools_ListOfShape::Iterator itA (aLA); itA.More();itA.Next()) | |
419 | { | |
420 | if (itA.Value().IsSame (aFToRemove)) | |
421 | { | |
422 | aLA.Remove (itA); | |
423 | break; | |
424 | } | |
425 | } | |
426 | aLA.Append (aFNew); | |
427 | ||
428 | myMapEdgeType (aE).Clear(); | |
429 | // Analyze edge again | |
430 | EdgeAnalyse (aE, TopoDS::Face (aFOpposite), aFNew, aSinTol, myMapEdgeType (aE)); | |
431 | ||
432 | // Analyze vertices | |
433 | TopTools_MapOfShape aFNewEdgeMap; | |
434 | aFNewEdgeMap.Add (aE); | |
435 | for (TopoDS_Iterator itV (aE); itV.More(); itV.Next()) | |
436 | { | |
437 | const TopoDS_Shape& aV = itV.Value(); | |
438 | // Add Side edge to map of Ancestors with the correct orientation | |
439 | TopoDS_Edge aEG = TopoDS::Edge (aMP.Generated (aV).First()); | |
440 | myGenerated.Bind (aV, aEG); | |
441 | { | |
442 | for (TopExp_Explorer anExpEg (aFNew, TopAbs_EDGE); anExpEg.More(); anExpEg.Next()) | |
443 | { | |
444 | if (anExpEg.Current().IsSame (aEG)) | |
445 | { | |
446 | aEG = TopoDS::Edge (anExpEg.Current()); | |
447 | break; | |
448 | } | |
449 | } | |
450 | } | |
451 | ||
452 | if (aDMVEMin.IsBound (aV)) | |
453 | { | |
454 | const TopTools_ListOfShape* pSA = aDMVFAnc.Seek (aV); | |
455 | if (pSA && pSA->Extent() == 1) | |
456 | { | |
457 | // Adjust orientation of generated edge to its new ancestor | |
458 | TopoDS_Edge aEMin = TopoDS::Edge (aDMVEMin.Find (aV)); | |
459 | for (TopExp_Explorer expEx (pSA->First(), TopAbs_EDGE); expEx.More(); expEx.Next()) | |
460 | { | |
461 | if (expEx.Current().IsSame (aEMin)) | |
462 | { | |
463 | aEMin = TopoDS::Edge (expEx.Current()); | |
464 | break; | |
465 | } | |
466 | } | |
467 | ||
468 | TopAbs_Orientation anOriInEMin (TopAbs_FORWARD), anOriInEG (TopAbs_FORWARD); | |
469 | ||
470 | for (TopoDS_Iterator itx (aEMin); itx.More(); itx.Next()) | |
471 | { | |
472 | if (itx.Value().IsSame (aV)) | |
473 | { | |
474 | anOriInEMin = itx.Value().Orientation(); | |
475 | break; | |
476 | } | |
477 | } | |
478 | ||
479 | for (TopoDS_Iterator itx (aEG); itx.More(); itx.Next()) | |
480 | { | |
481 | if (itx.Value().IsSame (aV)) | |
482 | { | |
483 | anOriInEG = itx.Value().Orientation(); | |
484 | break; | |
485 | } | |
486 | } | |
487 | ||
488 | if (anOriInEG == anOriInEMin) | |
489 | aEG.Reverse(); | |
490 | } | |
491 | } | |
492 | ||
493 | TopTools_ListOfShape& aLVA = myAncestors.ChangeFromKey (aV); | |
494 | if (!aLVA.Contains (aEG)) | |
495 | aLVA.Append (aEG); | |
496 | aFNewEdgeMap.Add (aEG); | |
497 | ||
498 | TopTools_ListOfShape& aLEGA = | |
499 | myAncestors (myAncestors.Add (aEG, aPrismAncestors.FindFromKey (aEG))); | |
500 | { | |
501 | // Add ancestors from the shape | |
502 | const TopTools_ListOfShape* pSA = aDMVFAnc.Seek (aV); | |
503 | if (pSA && !pSA->IsEmpty()) | |
504 | { | |
505 | TopTools_ListOfShape aLSA = *pSA; | |
506 | aLEGA.Append (aLSA); | |
507 | } | |
508 | } | |
509 | ||
510 | myMapEdgeType.Bind (aEG, BRepOffset_ListOfInterval()); | |
511 | if (aLEGA.Extent() == 2) | |
512 | { | |
513 | EdgeAnalyse (aEG, TopoDS::Face (aLEGA.First()), TopoDS::Face (aLEGA.Last()), | |
514 | aSinTol, myMapEdgeType (aEG)); | |
515 | } | |
516 | } | |
517 | ||
518 | // Find an edge opposite to tangential one and add ancestors for it | |
519 | TopoDS_Edge aEOpposite; | |
520 | for (TopExp_Explorer anExpE (aFNew, TopAbs_EDGE); anExpE.More(); anExpE.Next()) | |
521 | { | |
522 | if (!aFNewEdgeMap.Contains (anExpE.Current())) | |
523 | { | |
524 | aEOpposite = TopoDS::Edge (anExpE.Current()); | |
525 | break; | |
526 | } | |
527 | } | |
528 | ||
529 | { | |
530 | // Find it in aFOpposite | |
531 | for (TopExp_Explorer anExpE (aFToRemove, TopAbs_EDGE); anExpE.More(); anExpE.Next()) | |
532 | { | |
533 | const TopoDS_Shape& aEInFToRem = anExpE.Current(); | |
534 | if (aE.IsSame (aEInFToRem)) | |
535 | { | |
536 | if (BOPTools_AlgoTools::IsSplitToReverse (aEOpposite, aEInFToRem, aCtx)) | |
537 | aEOpposite.Reverse(); | |
538 | break; | |
539 | } | |
540 | } | |
541 | } | |
542 | ||
543 | TopTools_ListOfShape aLFOpposite; | |
544 | aLFOpposite.Append (aFNew); | |
545 | aLFOpposite.Append (aFToRemove); | |
546 | myAncestors.Add (aEOpposite, aLFOpposite); | |
547 | myMapEdgeType.Bind (aEOpposite, BRepOffset_ListOfInterval()); | |
548 | EdgeAnalyse (aEOpposite, aFNew, TopoDS::Face (aFToRemove), aSinTol, myMapEdgeType (aEOpposite)); | |
549 | ||
550 | TopTools_DataMapOfShapeShape* pEEMap = myReplacement.ChangeSeek (aFToRemove); | |
551 | if (!pEEMap) | |
552 | pEEMap = myReplacement.Bound (aFToRemove, TopTools_DataMapOfShapeShape()); | |
553 | pEEMap->Bind (aE, aEOpposite); | |
554 | ||
555 | // Add ancestors for the vertices | |
556 | for (TopoDS_Iterator itV (aEOpposite); itV.More(); itV.Next()) | |
557 | { | |
558 | const TopoDS_Shape& aV = itV.Value(); | |
559 | const TopTools_ListOfShape& aLVA = aPrismAncestors.FindFromKey (aV); | |
560 | myAncestors.Add (aV, aLVA); | |
561 | } | |
562 | ||
563 | myNewFaces.Append (aFNew); | |
564 | myGenerated.Bind (aE, aFNew); | |
565 | } | |
566 | } | |
567 | } | |
7fd59977 | 568 | } |
569 | ||
420b38fd | 570 | //======================================================================= |
571 | //function : EdgeReplacement | |
572 | //purpose : | |
573 | //======================================================================= | |
574 | const TopoDS_Edge& BRepOffset_Analyse::EdgeReplacement (const TopoDS_Face& theF, | |
575 | const TopoDS_Edge& theE) const | |
576 | { | |
577 | const TopTools_DataMapOfShapeShape* pEE = myReplacement.Seek (theF); | |
578 | if (!pEE) | |
579 | return theE; | |
7fd59977 | 580 | |
420b38fd | 581 | const TopoDS_Shape* pE = pEE->Seek (theE); |
582 | if (!pE) | |
583 | return theE; | |
7fd59977 | 584 | |
420b38fd | 585 | return TopoDS::Edge (*pE); |
586 | } | |
7fd59977 | 587 | |
420b38fd | 588 | //======================================================================= |
589 | //function : Generated | |
590 | //purpose : | |
591 | //======================================================================= | |
592 | TopoDS_Shape BRepOffset_Analyse::Generated (const TopoDS_Shape& theS) const | |
593 | { | |
594 | static TopoDS_Shape aNullShape; | |
595 | const TopoDS_Shape* pGenS = myGenerated.Seek (theS); | |
596 | return pGenS ? *pGenS : aNullShape; | |
597 | } | |
7fd59977 | 598 | |
599 | //======================================================================= | |
420b38fd | 600 | //function : Descendants |
7fd59977 | 601 | //purpose : |
602 | //======================================================================= | |
420b38fd | 603 | const TopTools_ListOfShape* BRepOffset_Analyse::Descendants (const TopoDS_Shape& theS, |
604 | const Standard_Boolean theUpdate) const | |
605 | { | |
606 | if (myDescendants.IsEmpty() || theUpdate) | |
607 | { | |
608 | myDescendants.Clear(); | |
609 | const Standard_Integer aNbA = myAncestors.Extent(); | |
610 | for (Standard_Integer i = 1; i <= aNbA; ++i) | |
611 | { | |
612 | const TopoDS_Shape& aSS = myAncestors.FindKey (i); | |
613 | const TopTools_ListOfShape& aLA = myAncestors (i); | |
614 | ||
615 | for (TopTools_ListOfShape::Iterator it (aLA); it.More(); it.Next()) | |
616 | { | |
617 | const TopoDS_Shape& aSA = it.Value(); | |
618 | ||
619 | TopTools_ListOfShape* pLD = myDescendants.ChangeSeek (aSA); | |
620 | if (!pLD) | |
621 | pLD = myDescendants.Bound (aSA, TopTools_ListOfShape()); | |
622 | if (!pLD->Contains (aSS)) | |
623 | pLD->Append (aSS); | |
624 | } | |
625 | } | |
626 | } | |
7fd59977 | 627 | |
420b38fd | 628 | return myDescendants.Seek (theS); |
629 | } | |
630 | ||
631 | //======================================================================= | |
632 | //function : Clear | |
633 | //purpose : | |
634 | //======================================================================= | |
635 | void BRepOffset_Analyse::Clear() | |
7fd59977 | 636 | { |
420b38fd | 637 | myDone = Standard_False; |
638 | myShape .Nullify(); | |
639 | myMapEdgeType.Clear(); | |
640 | myAncestors .Clear(); | |
641 | myFaceOffsetMap.Clear(); | |
642 | myReplacement.Clear(); | |
643 | myDescendants.Clear(); | |
644 | myNewFaces .Clear(); | |
645 | myGenerated.Clear(); | |
7fd59977 | 646 | } |
647 | ||
420b38fd | 648 | //======================================================================= |
649 | //function : BRepOffset_ListOfInterval& | |
650 | //purpose : | |
651 | //======================================================================= | |
652 | const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E) const | |
653 | { | |
654 | return myMapEdgeType (E); | |
655 | } | |
7fd59977 | 656 | |
657 | //======================================================================= | |
658 | //function : Edges | |
659 | //purpose : | |
660 | //======================================================================= | |
7fd59977 | 661 | void BRepOffset_Analyse::Edges(const TopoDS_Vertex& V, |
420b38fd | 662 | const ChFiDS_TypeOfConcavity T, |
663 | TopTools_ListOfShape& LE) const | |
7fd59977 | 664 | { |
665 | LE.Clear(); | |
666 | const TopTools_ListOfShape& L = Ancestors (V); | |
667 | TopTools_ListIteratorOfListOfShape it(L); | |
668 | ||
669 | for ( ;it.More(); it.Next()) { | |
670 | const TopoDS_Edge& E = TopoDS::Edge(it.Value()); | |
420b38fd | 671 | const BRepOffset_ListOfInterval *pIntervals = myMapEdgeType.Seek (E); |
672 | if (pIntervals && pIntervals->Extent() > 0) | |
673 | { | |
674 | TopoDS_Vertex V1,V2; | |
675 | BRepOffset_Tool::EdgeVertices (E,V1,V2); | |
676 | if (V1.IsSame(V)) { | |
677 | if (pIntervals->Last().Type() == T) | |
678 | LE.Append (E); | |
679 | } | |
680 | if (V2.IsSame(V)) { | |
681 | if (pIntervals->First().Type() == T) | |
682 | LE.Append (E); | |
683 | } | |
7fd59977 | 684 | } |
685 | } | |
686 | } | |
687 | ||
688 | ||
689 | //======================================================================= | |
690 | //function : Edges | |
691 | //purpose : | |
692 | //======================================================================= | |
7fd59977 | 693 | void BRepOffset_Analyse::Edges(const TopoDS_Face& F, |
420b38fd | 694 | const ChFiDS_TypeOfConcavity T, |
695 | TopTools_ListOfShape& LE) const | |
7fd59977 | 696 | { |
697 | LE.Clear(); | |
698 | TopExp_Explorer exp(F, TopAbs_EDGE); | |
420b38fd | 699 | |
7fd59977 | 700 | for ( ;exp.More(); exp.Next()) { |
701 | const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); | |
702 | ||
703 | const BRepOffset_ListOfInterval& Lint = Type(E); | |
704 | BRepOffset_ListIteratorOfListOfInterval it(Lint); | |
705 | for ( ;it.More(); it.Next()) { | |
706 | if (it.Value().Type() == T) LE.Append(E); | |
707 | } | |
708 | } | |
709 | } | |
710 | ||
711 | //======================================================================= | |
712 | //function : TangentEdges | |
713 | //purpose : | |
714 | //======================================================================= | |
7fd59977 | 715 | void BRepOffset_Analyse::TangentEdges(const TopoDS_Edge& Edge , |
716 | const TopoDS_Vertex& Vertex, | |
717 | TopTools_ListOfShape& Edges ) const | |
718 | { | |
719 | gp_Vec V,VRef; | |
720 | ||
7fd59977 | 721 | Standard_Real U,URef; |
722 | BRepAdaptor_Curve C3d, C3dRef; | |
723 | ||
724 | URef = BRep_Tool::Parameter(Vertex,Edge); | |
725 | C3dRef = BRepAdaptor_Curve(Edge); | |
726 | VRef = C3dRef.DN(URef,1); | |
d804b26d | 727 | CorrectOrientationOfTangent(VRef, Vertex, Edge); |
7fd59977 | 728 | if (VRef.SquareMagnitude() < gp::Resolution()) return; |
729 | ||
730 | Edges.Clear(); | |
731 | ||
732 | const TopTools_ListOfShape& Anc = Ancestors(Vertex); | |
733 | TopTools_ListIteratorOfListOfShape it(Anc); | |
734 | for ( ; it.More(); it.Next()) { | |
735 | const TopoDS_Edge& CurE = TopoDS::Edge(it.Value()); | |
736 | if ( CurE.IsSame(Edge)) continue; | |
737 | U = BRep_Tool::Parameter(Vertex,CurE); | |
738 | C3d = BRepAdaptor_Curve(CurE); | |
739 | V = C3d.DN(U,1); | |
d804b26d | 740 | CorrectOrientationOfTangent(V, Vertex, CurE); |
7fd59977 | 741 | if (V.SquareMagnitude() < gp::Resolution()) continue; |
420b38fd | 742 | if (V.IsOpposite(VRef,myAngle)) { |
7fd59977 | 743 | Edges.Append(CurE); |
744 | } | |
745 | } | |
746 | } | |
747 | ||
7fd59977 | 748 | //======================================================================= |
749 | //function : Explode | |
750 | //purpose : | |
751 | //======================================================================= | |
420b38fd | 752 | void BRepOffset_Analyse::Explode (TopTools_ListOfShape& List, |
753 | const ChFiDS_TypeOfConcavity T) const | |
7fd59977 | 754 | { |
755 | List.Clear(); | |
756 | BRep_Builder B; | |
757 | TopTools_MapOfShape Map; | |
420b38fd | 758 | |
7fd59977 | 759 | TopExp_Explorer Fexp; |
760 | for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) { | |
761 | if ( Map.Add(Fexp.Current())) { | |
762 | TopoDS_Face Face = TopoDS::Face(Fexp.Current()); | |
763 | TopoDS_Compound Co; | |
764 | B.MakeCompound(Co); | |
765 | B.Add(Co,Face); | |
0d969553 Y |
766 | // add to Co all faces from the cloud of faces |
767 | // G1 created from <Face> | |
7fd59977 | 768 | AddFaces(Face,Co,Map,T); |
769 | List.Append(Co); | |
770 | } | |
771 | } | |
772 | } | |
773 | ||
774 | //======================================================================= | |
775 | //function : Explode | |
776 | //purpose : | |
777 | //======================================================================= | |
420b38fd | 778 | void BRepOffset_Analyse::Explode (TopTools_ListOfShape& List, |
779 | const ChFiDS_TypeOfConcavity T1, | |
780 | const ChFiDS_TypeOfConcavity T2) const | |
7fd59977 | 781 | { |
782 | List.Clear(); | |
783 | BRep_Builder B; | |
784 | TopTools_MapOfShape Map; | |
785 | ||
786 | TopExp_Explorer Fexp; | |
787 | for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) { | |
788 | if ( Map.Add(Fexp.Current())) { | |
789 | TopoDS_Face Face = TopoDS::Face(Fexp.Current()); | |
790 | TopoDS_Compound Co; | |
791 | B.MakeCompound(Co); | |
792 | B.Add(Co,Face); | |
0d969553 Y |
793 | // add to Co all faces from the cloud of faces |
794 | // G1 created from <Face> | |
7fd59977 | 795 | AddFaces(Face,Co,Map,T1,T2); |
796 | List.Append(Co); | |
797 | } | |
798 | } | |
799 | } | |
800 | ||
7fd59977 | 801 | //======================================================================= |
802 | //function : AddFaces | |
803 | //purpose : | |
804 | //======================================================================= | |
7fd59977 | 805 | void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face, |
420b38fd | 806 | TopoDS_Compound& Co, |
807 | TopTools_MapOfShape& Map, | |
808 | const ChFiDS_TypeOfConcavity T) const | |
7fd59977 | 809 | { |
810 | BRep_Builder B; | |
420b38fd | 811 | const TopTools_ListOfShape *pLE = Descendants (Face); |
812 | if (!pLE) | |
813 | return; | |
814 | for (TopTools_ListOfShape::Iterator it (*pLE); it.More(); it.Next()) | |
815 | { | |
816 | const TopoDS_Edge& E = TopoDS::Edge (it.Value()); | |
7fd59977 | 817 | const BRepOffset_ListOfInterval& LI = Type(E); |
818 | if (!LI.IsEmpty() && LI.First().Type() == T) { | |
0d969553 | 819 | // so <NewFace> is attached to G1 by <Face> |
7fd59977 | 820 | const TopTools_ListOfShape& L = Ancestors(E); |
821 | if (L.Extent() == 2) { | |
420b38fd | 822 | TopoDS_Face F1 = TopoDS::Face (L.First()); |
823 | if (F1.IsSame (Face)) | |
824 | F1 = TopoDS::Face (L.Last()); | |
825 | if (Map.Add (F1)) { | |
826 | B.Add (Co, F1); | |
827 | AddFaces (F1, Co, Map, T); | |
828 | } | |
7fd59977 | 829 | } |
830 | } | |
831 | } | |
832 | } | |
420b38fd | 833 | |
7fd59977 | 834 | //======================================================================= |
835 | //function : AddFaces | |
836 | //purpose : | |
837 | //======================================================================= | |
7fd59977 | 838 | void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face, |
420b38fd | 839 | TopoDS_Compound& Co, |
840 | TopTools_MapOfShape& Map, | |
841 | const ChFiDS_TypeOfConcavity T1, | |
842 | const ChFiDS_TypeOfConcavity T2) const | |
7fd59977 | 843 | { |
844 | BRep_Builder B; | |
420b38fd | 845 | const TopTools_ListOfShape *pLE = Descendants (Face); |
846 | if (!pLE) | |
847 | return; | |
848 | for (TopTools_ListOfShape::Iterator it (*pLE); it.More(); it.Next()) | |
849 | { | |
850 | const TopoDS_Edge& E = TopoDS::Edge (it.Value()); | |
7fd59977 | 851 | const BRepOffset_ListOfInterval& LI = Type(E); |
852 | if (!LI.IsEmpty() && | |
420b38fd | 853 | (LI.First().Type() == T1 || LI.First().Type() == T2)) { |
0d969553 | 854 | // so <NewFace> is attached to G1 by <Face> |
7fd59977 | 855 | const TopTools_ListOfShape& L = Ancestors(E); |
856 | if (L.Extent() == 2) { | |
420b38fd | 857 | TopoDS_Face F1 = TopoDS::Face (L.First()); |
858 | if (F1.IsSame (Face)) | |
859 | F1 = TopoDS::Face (L.Last()); | |
860 | if (Map.Add (F1)) { | |
861 | B.Add (Co, F1); | |
862 | AddFaces (F1, Co, Map, T1, T2); | |
863 | } | |
7fd59977 | 864 | } |
865 | } | |
866 | } | |
867 | } |