0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / BRepOffset / BRepOffset_Analyse.cxx
CommitLineData
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 53static 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
66BRepOffset_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 75BRepOffset_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 86static 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 130static 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 142void 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 207void 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//=======================================================================
574const 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//=======================================================================
592TopoDS_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 603const 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//=======================================================================
635void 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//=======================================================================
652const 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 661void 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 693void 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 715void 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 752void 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 778void 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 805void 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 838void 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}