1 // Created on: 1996-09-03
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAlgo_AsDes.hxx>
23 #include <BRepAlgo_Image.hxx>
24 #include <BRepLib_MakeVertex.hxx>
25 #include <BRepOffset_Analyse.hxx>
26 #include <BRepOffset_DataMapOfShapeOffset.hxx>
27 #include <BRepOffset_Inter3d.hxx>
28 #include <BRepOffset_Interval.hxx>
29 #include <BRepOffset_ListOfInterval.hxx>
30 #include <BRepOffset_Offset.hxx>
31 #include <BRepOffset_Tool.hxx>
32 #include <Extrema_ExtPC.hxx>
33 #include <GeomAPI_ProjectPointOnCurve.hxx>
34 #include <Precision.hxx>
36 #include <TopExp_Explorer.hxx>
38 #include <TopoDS_Compound.hxx>
39 #include <TopoDS_Edge.hxx>
40 #include <TopoDS_Face.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Vertex.hxx>
43 #include <TopTools_IndexedMapOfShape.hxx>
44 #include <TopTools_ListIteratorOfListOfShape.hxx>
45 #include <TopTools_MapIteratorOfMapOfShape.hxx>
46 #include <TopTools_MapOfShape.hxx>
48 #include <BRepBndLib.hxx>
49 #include <BOPTools_BoxBndTree.hxx>
50 #include <NCollection_UBTreeFiller.hxx>
52 #include <BOPTools_AlgoTools.hxx>
54 //=======================================================================
55 //function : BRepOffset_Inter3d
57 //=======================================================================
58 BRepOffset_Inter3d::BRepOffset_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes,
59 const TopAbs_State Side ,
60 const Standard_Real Tol)
68 //=======================================================================
69 //function : ExtentEdge
71 //=======================================================================
73 static void ExtentEdge(const TopoDS_Face& /*F*/,
77 TopoDS_Shape aLocalShape = E.EmptyCopied();
78 NE = TopoDS::Edge(aLocalShape);
79 // NE = TopoDS::Edge(E.EmptyCopied());
82 // Enough for analytic edges, in general case reconstruct the
83 // geometry of the edge recalculating the intersection of surfaces.
85 NE.Orientation(TopAbs_FORWARD);
87 BRep_Tool::Range(E,f,l);
88 Standard_Real length = l-f;
94 BRepAdaptor_Curve CE(E);
95 TopoDS_Vertex V1 = BRepLib_MakeVertex(CE.Value(f));
96 TopoDS_Vertex V2 = BRepLib_MakeVertex(CE.Value(l));
97 B.Add(NE,V1.Oriented(TopAbs_FORWARD));
98 B.Add(NE,V2.Oriented(TopAbs_REVERSED));
99 NE.Orientation(E.Orientation());
103 //=======================================================================
104 //function : CompletInt
106 //=======================================================================
108 void BRepOffset_Inter3d::CompletInt(const TopTools_ListOfShape& SetOfFaces,
109 const BRepAlgo_Image& InitOffsetFace)
111 //---------------------------------------------------------------
112 // Calculate the intersections of offset faces
113 // Distinction of intersection between faces // tangents.
114 //---------------------------------------------------------------
116 // Prepare tools for sorting the bounding boxes
117 BOPTools_BoxBndTree aBBTree;
118 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
120 NCollection_IndexedDataMap<TopoDS_Shape, Bnd_Box, TopTools_ShapeMapHasher> aMFaces;
121 // Construct bounding boxes for faces and add them to the tree
122 TopTools_ListIteratorOfListOfShape aItL(SetOfFaces);
123 for (; aItL.More(); aItL.Next()) {
124 const TopoDS_Face& aF = TopoDS::Face(aItL.Value());
126 // compute bounding box
128 BRepBndLib::Add(aF, aBoxF);
130 Standard_Integer i = aMFaces.Add(aF, aBoxF);
132 aTreeFiller.Add(i, aBoxF);
138 // get faces with interfering bounding boxes
139 aItL.Initialize(SetOfFaces);
140 for (; aItL.More(); aItL.Next()) {
141 const TopoDS_Face& aF1 = TopoDS::Face(aItL.Value());
142 const Bnd_Box& aBoxF1 = aMFaces.FindFromKey(aF1);
144 BOPTools_BoxBndTreeSelector aSelector;
145 aSelector.SetBox(aBoxF1);
146 aBBTree.Select(aSelector);
148 const TColStd_ListOfInteger& aLI = aSelector.Indices();
149 TColStd_ListIteratorOfListOfInteger aItLI(aLI);
150 for (; aItLI.More(); aItLI.Next()) {
151 Standard_Integer i = aItLI.Value();
152 const TopoDS_Face& aF2 = TopoDS::Face(aMFaces.FindKey(i));
155 FaceInter(aF1, aF2, InitOffsetFace);
161 //=======================================================================
162 //function : FaceInter
163 //purpose : Performs intersection of the given faces
164 //=======================================================================
166 void BRepOffset_Inter3d::FaceInter(const TopoDS_Face& F1,
167 const TopoDS_Face& F2,
168 const BRepAlgo_Image& InitOffsetFace)
170 TopTools_ListOfShape LInt1, LInt2;
171 TopoDS_Edge NullEdge;
173 if (F1.IsSame(F2)) return;
174 if (IsDone(F1,F2)) return;
176 const TopoDS_Shape& InitF1 = InitOffsetFace.ImageFrom(F1);
177 const TopoDS_Shape& InitF2 = InitOffsetFace.ImageFrom(F2);
178 if (InitF1.IsSame(InitF2)) return;
180 Standard_Boolean InterPipes = (InitF2.ShapeType() == TopAbs_EDGE &&
181 InitF1.ShapeType() == TopAbs_EDGE );
182 Standard_Boolean InterFaces = (InitF1.ShapeType() == TopAbs_FACE &&
183 InitF2.ShapeType() == TopAbs_FACE);
184 TopTools_ListOfShape LE,LV;
185 LInt1.Clear(); LInt2.Clear();
186 if (BRepOffset_Tool::FindCommonShapes(F1,F2,LE,LV) ||
187 myAsDes->HasCommonDescendant(F1,F2,LE)) {
188 //-------------------------------------------------
189 // F1 and F2 share shapes.
190 //-------------------------------------------------
191 if ( LE.IsEmpty() && !LV.IsEmpty()) {
193 //----------------------
194 // tubes share a vertex.
195 //----------------------
196 const TopoDS_Edge& EE1 = TopoDS::Edge(InitF1);
197 const TopoDS_Edge& EE2 = TopoDS::Edge(InitF2);
198 TopoDS_Vertex VE1[2],VE2[2];
199 TopExp::Vertices(EE1,VE1[0],VE1[1]);
200 TopExp::Vertices(EE2,VE2[0],VE2[1]);
202 for (Standard_Integer i = 0 ; i < 2; i++) {
203 for (Standard_Integer j = 0 ; j < 2; j++) {
204 if (VE1[i].IsSame(VE2[j])) {
209 if (!InitOffsetFace.HasImage(V)) { //no sphere
210 BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide);
214 //--------------------------------------------------------
215 // Intersection having only common vertices
216 // and supports having common edges.
217 // UNSUFFICIENT, but a larger criterion shakes too
219 //--------------------------------------------------------
221 if (BRepOffset_Tool::FindCommonShapes(TopoDS::Face(InitF1),
222 TopoDS::Face(InitF2),LE,LV)) {
224 BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
228 BRepOffset_Tool::Inter3D(F1,F2,LInt1,LInt2,mySide,NullEdge);
236 BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide);
239 BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
242 Store (F1,F2,LInt1,LInt2);
246 //=======================================================================
247 //function : ConnexIntByArc
249 //=======================================================================
251 void BRepOffset_Inter3d::ConnexIntByArc(const TopTools_ListOfShape& /*SetOfFaces*/,
252 const TopoDS_Shape& ShapeInit,
253 const BRepOffset_Analyse& Analyse,
254 const BRepAlgo_Image& InitOffsetFace)
256 BRepOffset_Type OT = BRepOffset_Concave;
257 if (mySide == TopAbs_OUT) OT = BRepOffset_Convex;
258 TopExp_Explorer Exp(ShapeInit,TopAbs_EDGE);
259 TopTools_ListOfShape LInt1,LInt2;
261 TopoDS_Edge NullEdge;
263 //---------------------------------------------------------------------
264 // etape 1 : Intersection of faces // corresponding to the initial faces
265 // separated by a concave edge if offset > 0, otherwise convex.
266 //---------------------------------------------------------------------
267 for (; Exp.More(); Exp.Next()) {
268 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
269 const BRepOffset_ListOfInterval& L = Analyse.Type(E);
270 if (!L.IsEmpty() && L.First().Type() == OT) {
271 //-----------------------------------------------------------
272 // edge is of the proper type , return adjacent faces.
273 //-----------------------------------------------------------
274 const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
275 if (Anc.Extent() == 2) {
276 F1 = TopoDS::Face(InitOffsetFace.Image(Anc.First()).First());
277 F2 = TopoDS::Face(InitOffsetFace.Image(Anc.Last ()).First());
278 if (!IsDone(F1,F2)) {
279 BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,E,Standard_True);
280 Store (F1,F2,LInt1,LInt2);
285 //---------------------------------------------------------------------
286 // etape 2 : Intersections of tubes sharing a vertex without sphere with:
287 // - tubes on each other edge sharing the vertex
288 // - faces containing an edge connected to vertex that has no tubes.
289 //---------------------------------------------------------------------
291 TopTools_ListIteratorOfListOfShape it;
293 for (Exp.Init(ShapeInit,TopAbs_EDGE); Exp.More(); Exp.Next()) {
294 const TopoDS_Edge& E1 = TopoDS::Edge(Exp.Current());
295 if (InitOffsetFace.HasImage(E1)) {
296 //---------------------------
297 // E1 generated a tube.
298 //---------------------------
299 F1 = TopoDS::Face(InitOffsetFace.Image(E1).First());;
300 TopExp::Vertices(E1,V[0],V[1]);
301 const TopTools_ListOfShape& AncE1 = Analyse.Ancestors(E1);
303 for (Standard_Integer i = 0; i < 2; i++) {
304 if (!InitOffsetFace.HasImage(V[i])) {
305 //-----------------------------
306 // the vertex has no sphere.
307 //-----------------------------
308 const TopTools_ListOfShape& Anc = Analyse.Ancestors(V[i]);
309 TopTools_ListOfShape TangOnV;
310 Analyse.TangentEdges(E1,V[i],TangOnV);
311 TopTools_MapOfShape MTEV;
312 for (it.Initialize(TangOnV); it.More(); it.Next()) {
313 MTEV.Add(it.Value());
315 for (it.Initialize(Anc); it.More(); it.Next()) {
316 const TopoDS_Edge& E2 = TopoDS::Edge(it.Value());
317 // Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 Begin
318 // if (E1.IsSame(E2) || MTEV.Contains(E2)) continue;
319 Standard_Boolean isToSkip = Standard_False;
321 if (!E1.IsSame(E2)) {
322 const BRepOffset_ListOfInterval& aL = Analyse.Type(E2);
324 isToSkip = (MTEV.Contains(E2) &&
326 (!aL.IsEmpty() && aL.First().Type() != OT)));
329 if (E1.IsSame(E2) || isToSkip)
331 // Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 End
332 if (InitOffsetFace.HasImage(E2)) {
333 //-----------------------------
334 // E2 generated a tube.
335 //-----------------------------
336 F2 = TopoDS::Face(InitOffsetFace.Image(E2).First());
337 if (!IsDone(F1,F2)) {
338 //---------------------------------------------------------------------
339 // Intersection tube/tube if the edges are not tangent (AFINIR).
340 //----------------------------------------------------------------------
341 BRepOffset_Tool::PipeInter (F1,F2,LInt1,LInt2,mySide);
342 Store (F1,F2,LInt1,LInt2);
346 //-------------------------------------------------------
347 // Intersection of the tube of E1 with faces //
348 // to face containing E2 if they are not tangent
349 // to the tube or if E2 is not a tangent edge.
350 //-------------------------------------------------------
351 const BRepOffset_ListOfInterval& L = Analyse.Type(E2);
352 if (!L.IsEmpty() && L.First().Type() == BRepOffset_Tangent) {
355 const TopTools_ListOfShape& AncE2 = Analyse.Ancestors(E2);
356 Standard_Boolean TangentFaces = Standard_False;
357 if (AncE2.Extent() == 2) {
358 TopoDS_Face InitF2 = TopoDS::Face(AncE2.First ());
359 TangentFaces = (InitF2.IsSame(AncE1.First()) ||
360 InitF2.IsSame(AncE1.Last()));
362 F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First());
363 if (!IsDone(F1,F2)) {
364 BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
365 Store (F1,F2,LInt1,LInt2);
368 InitF2 = TopoDS::Face(AncE2.Last ());
369 TangentFaces = (InitF2.IsSame(AncE1.First()) ||
370 InitF2.IsSame(AncE1.Last()));
372 F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First());
373 if (!IsDone(F1,F2)) {
374 BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
375 Store (F1,F2,LInt1,LInt2);
388 //=======================================================================
389 //function : ConnexIntByInt
391 //=======================================================================
393 void BRepOffset_Inter3d::ConnexIntByInt
394 (const TopoDS_Shape& SI,
395 const BRepOffset_DataMapOfShapeOffset& MapSF,
396 const BRepOffset_Analyse& Analyse,
397 TopTools_DataMapOfShapeShape& MES,
398 TopTools_DataMapOfShapeShape& Build,
399 TopTools_ListOfShape& Failed,
400 const Standard_Boolean bIsPlanar)
402 //TopExp_Explorer Exp(SI,TopAbs_EDGE);
403 TopTools_IndexedMapOfShape VEmap;
404 TopTools_IndexedDataMapOfShapeListOfShape aMVF;
405 TopoDS_Face F1,F2,OF1,OF2,NF1,NF2;
406 TopAbs_State CurSide = mySide;
408 Standard_Boolean bEdge;
409 Standard_Integer i, aNb;
410 TopTools_ListIteratorOfListOfShape it, it1, itF1, itF2;
412 TopExp::MapShapes(SI, TopAbs_EDGE , VEmap);
413 // map the shape for vertices
415 TopExp::MapShapes(SI, TopAbs_VERTEX, VEmap);
417 // make vertex-faces connexity map with unique ancestors
418 TopExp::MapShapesAndUniqueAncestors(SI, TopAbs_VERTEX, TopAbs_FACE, aMVF);
421 TopTools_DataMapOfShapeListOfShape aDMVLF1, aDMVLF2, aDMIntFF;
422 TopTools_IndexedDataMapOfShapeListOfShape aDMIntE;
425 aNb = VEmap.Extent();
426 for (i = 1; i <= aNb; ++i) {
427 const TopoDS_Shape& aS = VEmap(i);
428 if (aS.ShapeType() != TopAbs_VERTEX) {
432 // faces connected by the vertex
433 const TopTools_ListOfShape& aLF = aMVF.FindFromKey(aS);
434 if (aLF.Extent() < 2) {
437 // build lists of faces connected to the same vertex by looking for
438 // the pairs in which the vertex is alone (not connected to shared edges)
439 TopTools_ListOfShape aLF1, aLF2;
442 for (; it.More(); it.Next()) {
443 const TopoDS_Shape& aFV1 = it.Value();
445 // get edges of first face connected to current vertex
446 TopTools_MapOfShape aME;
447 TopExp_Explorer aExp(aFV1, TopAbs_EDGE);
448 for (; aExp.More(); aExp.Next()) {
449 const TopoDS_Shape& aE = aExp.Current();
450 TopoDS_Iterator aItV(aE);
451 for (; aItV.More(); aItV.Next()) {
452 if (aS.IsSame(aItV.Value())) {
459 // get to the next face in the list
461 for (it1.Next(); it1.More(); it1.Next()) {
462 const TopoDS_Shape& aFV2 = it1.Value();
464 aExp.Init(aFV2, TopAbs_EDGE);
465 for (; aExp.More(); aExp.Next()) {
466 const TopoDS_Shape& aEV2 = aExp.Current();
467 if (aME.Contains(aEV2)) {
473 // faces share only vertex - make pair for intersection
481 aDMVLF1.Bind(aS, aLF1);
482 aDMVLF2.Bind(aS, aLF2);
487 aNb = VEmap.Extent();
488 for (i = 1; i <= aNb; ++i) {
489 const TopoDS_Shape& aS = VEmap(i);
492 TopTools_ListOfShape aLF1, aLF2;
494 bEdge = (aS.ShapeType() == TopAbs_EDGE);
496 // faces connected by the edge
497 E = *(TopoDS_Edge*)&aS;
499 const BRepOffset_ListOfInterval& L = Analyse.Type(E);
504 BRepOffset_Type OT = L.First().Type();
505 if (OT != BRepOffset_Convex && OT != BRepOffset_Concave) {
509 if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
510 else CurSide = TopAbs_OUT;
511 //-----------------------------------------------------------
512 // edge is of the proper type, return adjacent faces.
513 //-----------------------------------------------------------
514 const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
515 if (Anc.Extent() != 2) {
519 F1 = TopoDS::Face(Anc.First());
520 F2 = TopoDS::Face(Anc.Last ());
526 if (!aDMVLF1.IsBound(aS)) {
530 aLF1 = aDMVLF1.Find(aS);
531 aLF2 = aDMVLF2.Find(aS);
536 itF1.Initialize(aLF1);
537 itF2.Initialize(aLF2);
538 for (; itF1.More() && itF2.More(); itF1.Next(), itF2.Next()) {
539 F1 = TopoDS::Face(itF1.Value());
540 F2 = TopoDS::Face(itF2.Value());
542 OF1 = TopoDS::Face(MapSF(F1).Face());
543 OF2 = TopoDS::Face(MapSF(F2).Face());
544 if (!MES.IsBound(OF1)) {
545 Standard_Boolean enlargeU = Standard_True;
546 Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
547 BRepOffset_Tool::CheckBounds( F1, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
548 BRepOffset_Tool::EnLargeFace(OF1,NF1,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
552 NF1 = TopoDS::Face(MES(OF1));
555 if (!MES.IsBound(OF2)) {
556 Standard_Boolean enlargeU = Standard_True;
557 Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
558 BRepOffset_Tool::CheckBounds( F2, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
559 BRepOffset_Tool::EnLargeFace(OF2,NF2,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
563 NF2 = TopoDS::Face(MES(OF2));
566 if (!IsDone(NF1,NF2)) {
567 TopTools_ListOfShape LInt1,LInt2;
568 BRepOffset_Tool::Inter3D (NF1,NF2,LInt1,LInt2,CurSide,E,bEdge);
570 if (!LInt1.IsEmpty()) {
571 Store (NF1,NF2,LInt1,LInt2);
576 if (Build.IsBound(aS)) {
577 const TopoDS_Shape& aSE = Build(aS);
578 TopExp_Explorer aExp(aSE, TopAbs_EDGE);
579 for (; aExp.More(); aExp.Next()) {
580 const TopoDS_Shape& aNE = aExp.Current();
585 it.Initialize(LInt1);
586 for (; it.More(); it.Next()) {
587 const TopoDS_Shape& aNE = it.Value();
590 // keep connection from new edge to shape from which it was created
591 TopTools_ListOfShape *pLS = &aDMIntE(aDMIntE.Add(aNE, TopTools_ListOfShape()));
593 // keep connection to faces created the edge as well
594 TopTools_ListOfShape* pLFF = aDMIntFF.Bound(aNE, TopTools_ListOfShape());
604 } else { // IsDone(NF1,NF2)
605 // Modified by skv - Fri Dec 26 12:20:13 2003 OCC4455 Begin
606 const TopTools_ListOfShape &aLInt1 = myAsDes->Descendant(NF1);
607 const TopTools_ListOfShape &aLInt2 = myAsDes->Descendant(NF2);
609 if (!aLInt1.IsEmpty()) {
613 if (Build.IsBound(aS)) {
614 const TopoDS_Shape& aSE = Build(aS);
615 TopExp_Explorer aExp(aSE, TopAbs_EDGE);
616 for (; aExp.More(); aExp.Next()) {
617 const TopoDS_Shape& aNE = aExp.Current();
622 for (it.Initialize(aLInt1) ; it.More(); it.Next()) {
623 const TopoDS_Shape &anE1 = it.Value();
625 for (it1.Initialize(aLInt2) ; it1.More(); it1.Next()) {
626 const TopoDS_Shape &anE2 = it1.Value();
627 if (anE1.IsSame(anE2)) {
630 TopTools_ListOfShape *pLS = aDMIntE.ChangeSeek(anE1);
644 // Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End
647 // create unique intersection for each localized shared part
648 aNb = aDMIntE.Extent();
649 for (i = 1; i <= aNb; ++i) {
650 const TopTools_ListOfShape& aLS = aDMIntE(i);
651 if (aLS.Extent() < 2) {
656 const TopoDS_Edge& aE = TopoDS::Edge(aDMIntE.FindKey(i));
657 // faces created the edge
658 const TopTools_ListOfShape& aLFF = aDMIntFF.Find(aE);
659 const TopoDS_Shape& aF1 = aLFF.First();
660 const TopoDS_Shape& aF2 = aLFF.Last();
662 // Build really localized blocks from the original shapes in <aLS>:
663 // 1. Find edges from original faces connected to two or more shapes in <aLS>;
664 // 2. Make connexity blocks from edges in <aLS> and found connection edges;
665 // 3. Check if the vertices from <aLS> are not connected by these connection edges:
666 // a. If so - add these vertices to Connexity Block containing the corresponding
668 // b. If not - add this vertex to list of connexity blocks
669 // 4. Create unique intersection edge for each connexity block
672 TopTools_ListOfShape aLV;
673 // compound of edges to build connexity blocks
676 TopTools_MapOfShape aMS;
677 TopTools_ListIteratorOfListOfShape aItLS(aLS);
678 for (; aItLS.More(); aItLS.Next()) {
679 const TopoDS_Shape& aS = aItLS.Value();
681 if (aS.ShapeType() == TopAbs_EDGE) {
689 // look for additional edges to connect the shared parts
690 TopTools_MapOfShape aMEConnection;
691 for (Standard_Integer j = 0; j < 2; ++j) {
692 const TopoDS_Shape& aF = !j ? aF1 : aF2;
694 TopExp_Explorer aExp(aF, TopAbs_EDGE);
695 for (; aExp.More(); aExp.Next()) {
696 const TopoDS_Shape& aEF = aExp.Current();
697 if (aMS.Contains(aEF) || aMEConnection.Contains(aEF)) {
701 TopoDS_Vertex aV1, aV2;
702 TopExp::Vertices(TopoDS::Edge(aEF), aV1, aV2);
704 // find parts to which the edge is connected
705 Standard_Integer iCounter = 0;
706 aItLS.Initialize(aLS);
707 for (; aItLS.More(); aItLS.Next()) {
708 const TopoDS_Shape& aS = aItLS.Value();
709 // iterator is not suitable here, because aS may be a vertex
710 TopExp_Explorer aExpV(aS, TopAbs_VERTEX);
711 for (; aExpV.More(); aExpV.Next()) {
712 const TopoDS_Shape& aV = aExpV.Current();
713 if (aV.IsSame(aV1) || aV.IsSame(aV2)) {
722 aMEConnection.Add(aEF);
727 TopTools_ListOfShape aLCBE;
728 BOPTools_AlgoTools::MakeConnexityBlocks(aCE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
730 // create connexity blocks for alone vertices
731 TopTools_ListOfShape aLCBV;
732 TopTools_ListIteratorOfListOfShape aItLV(aLV);
733 for (; aItLV.More(); aItLV.Next()) {
734 const TopoDS_Shape& aV = aItLV.Value();
735 // check if this vertex is contained in some connexity block of edges
736 TopTools_ListIteratorOfListOfShape aItLCB(aLCBE);
737 for (; aItLCB.More(); aItLCB.Next()) {
738 TopoDS_Shape& aCB = aItLCB.ChangeValue();
739 TopExp_Explorer aExpV(aCB, TopAbs_VERTEX);
740 for (; aExpV.More(); aExpV.Next()) {
741 if (aV.IsSame(aExpV.Current())) {
751 if (!aItLCB.More()) {
761 if (aLCBE.Extent() == 1) {
765 const TopoDS_Shape& aNF1 = MES(MapSF(aF1).Face());
766 const TopoDS_Shape& aNF2 = MES(MapSF(aF2).Face());
768 TopTools_ListIteratorOfListOfShape aItLCB(aLCBE);
769 for (aItLCB.Next(); aItLCB.More(); aItLCB.Next()) {
770 // make new edge with different tedge instance
771 TopoDS_Edge aNewEdge;
772 TopoDS_Vertex aV1, aV2;
773 Standard_Real aT1, aT2;
775 TopExp::Vertices(aE, aV1, aV2);
776 BRep_Tool::Range(aE, aT1, aT2);
778 BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aNewEdge);
780 myAsDes->Add(aNF1, aNewEdge);
781 myAsDes->Add(aNF2, aNewEdge);
783 const TopoDS_Shape& aCB = aItLCB.Value();
784 TopoDS_Iterator aItCB(aCB);
785 for (; aItCB.More(); aItCB.Next()) {
786 const TopoDS_Shape& aS = aItCB.Value();
787 if (aMEConnection.Contains(aS)) {
790 TopoDS_Shape& aCI = Build.ChangeFind(aS);
792 TopoDS_Compound aNewCI;
793 B.MakeCompound(aNewCI);
794 TopExp_Explorer aExp(aCI, TopAbs_EDGE);
795 for (; aExp.More(); aExp.Next()) {
796 const TopoDS_Shape& aSx = aExp.Current();
797 if (!aSx.IsSame(aE)) {
801 B.Add(aNewCI, aNewEdge);
808 //=======================================================================
809 //function : ContextIntByInt
811 //=======================================================================
813 void BRepOffset_Inter3d::ContextIntByInt
814 (const TopTools_IndexedMapOfShape& ContextFaces,
815 const Standard_Boolean ExtentContext,
816 const BRepOffset_DataMapOfShapeOffset& MapSF,
817 const BRepOffset_Analyse& Analyse,
818 TopTools_DataMapOfShapeShape& MES,
819 TopTools_DataMapOfShapeShape& Build,
820 TopTools_ListOfShape& Failed,
821 const Standard_Boolean bIsPlanar)
823 TopTools_MapOfShape MV;
825 TopoDS_Face OF,NF,WCF;
829 TopTools_ListIteratorOfListOfShape it, itF;
830 Standard_Integer i, j, aNb, aNbVE;
831 Standard_Boolean bEdge;
833 aNb = ContextFaces.Extent();
834 for (i = 1; i <= aNb; i++) {
835 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i));
838 BRepOffset_Tool::EnLargeFace(CF,NF,0,0);
842 TopAbs_State Side = TopAbs_OUT;
844 for (i = 1; i <= aNb; i++) {
845 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i));
846 if (ExtentContext) WCF = TopoDS::Face(MES(CF));
849 TopTools_IndexedMapOfShape VEmap;
850 TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_EDGE , VEmap);
853 TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
856 aNbVE = VEmap.Extent();
857 for (j = 1; j <= aNbVE; ++j) {
858 const TopoDS_Shape& aS = VEmap(j);
860 bEdge = (aS.ShapeType() == TopAbs_EDGE);
863 TopTools_ListOfShape Anc;
866 // faces connected by the edge
868 E = *(TopoDS_Edge*)&aS;
869 if (!Analyse.HasAncestor(E)) {
870 //----------------------------------------------------------------
871 // the edges of faces of context that are not in the initial shape
872 // can appear in the result.
873 //----------------------------------------------------------------
874 if (!ExtentContext) {
879 if (!MES.IsBound(E)) {
881 Standard_Real f,l,Tol;
882 BRep_Tool::Range(E,f,l);
883 Tol = BRep_Tool::Tolerance(E);
886 TopExp::Vertices(E,V1,V2);
887 NE.Orientation(TopAbs_FORWARD);
888 myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
889 myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
890 TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
891 B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
892 aLocalShape = V2.Oriented(TopAbs_INTERNAL);
893 B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
894 // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
895 // B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
896 NE.Orientation(E.Orientation());
902 TopoDS_Shape NE = MES(E);
903 TopoDS_Shape aLocalShape = NE.Oriented(E.Orientation());
904 myAsDes->Add(CF,aLocalShape);
905 // myAsDes->Add(CF,NE.Oriented(E.Orientation()));
910 Anc = Analyse.Ancestors(E);
913 // faces connected by the vertex
915 if (!Analyse.HasAncestor(aS)) {
919 const TopTools_ListOfShape& aLE = Analyse.Ancestors(aS);
921 for (; it.More(); it.Next()) {
922 const TopoDS_Edge& aE = *(TopoDS_Edge*)&it.Value();
924 if (BRep_Tool::Degenerated(aE)) {
928 if (VEmap.Contains(aE)) {
932 const TopTools_ListOfShape& aLF = Analyse.Ancestors(aE);
934 for (; itF.More(); itF.Next()) {
935 const TopoDS_Shape& aF = itF.Value();
936 Standard_Boolean bAdd = Standard_True;
937 exp.Init(aF, TopAbs_EDGE);
938 for (; exp.More() && bAdd; exp.Next()) {
939 const TopoDS_Shape& aEF = exp.Current();
940 bAdd = !VEmap.Contains(aEF);
950 for (; itF.More(); itF.Next()) {
951 const TopoDS_Face& F = TopoDS::Face(itF.Value());
952 OF = TopoDS::Face(MapSF(F).Face());
953 TopoDS_Shape aLocalShape = MapSF(F).Generated(E);
954 OE = TopoDS::Edge(aLocalShape);
955 // OE = TopoDS::Edge(MapSF(F).Generated(E));
956 if (!MES.IsBound(OF)) {
957 BRepOffset_Tool::EnLargeFace(OF,NF,1,1);
961 NF = TopoDS::Face(MES(OF));
963 if (!IsDone(NF,CF)) {
964 TopTools_ListOfShape LInt1,LInt2;
965 TopTools_ListOfShape LOE;
967 BRepOffset_Tool::Inter3D (WCF,NF,LInt1,LInt2,Side,E,bEdge);
969 if (!LInt1.IsEmpty()) {
970 Store (CF,NF,LInt1,LInt2);
971 if ((LInt1.Extent() == 1) && !Build.IsBound(aS)) {
972 Build.Bind(aS,LInt1.First());
976 if (Build.IsBound(aS)) {
977 const TopoDS_Shape& aSE = Build(aS);
978 exp.Init(aSE, TopAbs_EDGE);
979 for (; exp.More(); exp.Next()) {
980 const TopoDS_Shape& aNE = exp.Current();
985 for (it.Initialize(LInt1) ; it.More(); it.Next()) {
1000 //=======================================================================
1001 //function : ContextIntByArc
1003 //=======================================================================
1005 void BRepOffset_Inter3d::ContextIntByArc(const TopTools_IndexedMapOfShape& ContextFaces,
1006 const Standard_Boolean InSide,
1007 const BRepOffset_Analyse& Analyse,
1008 const BRepAlgo_Image& InitOffsetFace,
1009 BRepAlgo_Image& InitOffsetEdge)
1012 TopTools_ListOfShape LInt1,LInt2;
1013 TopTools_MapOfShape MV;
1014 TopExp_Explorer exp;
1015 TopoDS_Face OF1,OF2;
1018 TopoDS_Edge NullEdge;
1021 for (j = 1; j <= ContextFaces.Extent(); j++) {
1022 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
1026 for (j = 1; j <= ContextFaces.Extent(); j++) {
1027 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
1028 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1029 exp.More(); exp.Next()) {
1030 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1031 if (!Analyse.HasAncestor(E)) {
1036 if (!InitOffsetEdge.HasImage(E)) {
1037 Standard_Real f,l,Tol;
1038 BRep_Tool::Range(E,f,l);
1039 Tol = BRep_Tool::Tolerance(E);
1040 ExtentEdge(CF,E,NE);
1041 TopoDS_Vertex V1,V2;
1042 TopExp::Vertices(E,V1,V2);
1043 NE.Orientation(TopAbs_FORWARD);
1044 myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
1045 myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
1046 TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
1047 B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
1048 aLocalShape = V2.Oriented(TopAbs_INTERNAL);
1049 B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
1050 // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
1051 // B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
1052 NE.Orientation(E.Orientation());
1053 myAsDes->Add(CF,NE);
1054 InitOffsetEdge.Bind(E,NE);
1057 NE = TopoDS::Edge(InitOffsetEdge.Image(E).First());
1058 myAsDes->Add(CF,NE.Oriented(E.Orientation()));
1064 //---------------------------------------------------
1065 // OF1 parallel facee generated by the ancestor of E.
1066 //---------------------------------------------------
1067 const TopoDS_Shape SI = Analyse.Ancestors(E).First();
1068 OF1 = TopoDS::Face(InitOffsetFace.Image(SI).First());
1069 OE = TopoDS::Edge(InitOffsetEdge.Image(E).First());
1072 //Check if OE has pcurve in CF
1076 Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l);
1077 Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l);
1079 if(C1.IsNull() || C2.IsNull())
1085 //--------------------------------------------------
1086 // MAJ of OE on cap CF.
1087 //--------------------------------------------------
1088 // TopTools_ListOfShape LOE; LOE.Append(OE);
1089 // BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
1091 // StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
1093 LInt1.Clear(); LInt1.Append(OE);
1095 TopAbs_Orientation anOri1, anOri2;
1096 BRepOffset_Tool::OrientSection(OE,CF,OF1, anOri1,anOri2);
1097 // if (mySide == TopAbs_OUT);
1098 anOri1 = TopAbs::Reverse(anOri1);
1099 LInt1.First().Orientation(anOri1);
1100 Store(CF,OF1,LInt1,LInt2);
1102 //------------------------------------------------------
1103 // Processing of offsets on the ancestors of vertices.
1104 //------------------------------------------------------
1106 TopExp::Vertices (E,V[0],V[1]);
1107 for (Standard_Integer i = 0; i < 2; i++) {
1108 if (!MV.Add(V[i])) continue;
1110 const TopTools_ListOfShape& LE = Analyse.Ancestors(V[i]);
1111 TopTools_ListIteratorOfListOfShape itLE(LE);
1112 for ( ; itLE.More(); itLE.Next()) {
1113 const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
1114 if (InitOffsetFace.HasImage(EV)) {
1115 //-------------------------------------------------
1116 // OF1 parallel face generated by an ancester edge of V[i].
1117 //-------------------------------------------------
1118 OF1 = TopoDS::Face(InitOffsetFace.Image(EV).First());
1119 OE = TopoDS::Edge(InitOffsetEdge.Image(V[i]).First());
1122 //Check if OE has pcurve in CF and OF1
1126 Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l);
1127 Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l);
1129 if(C1.IsNull() || C2.IsNull())
1135 //--------------------------------------------------
1136 // MAj of OE on cap CF.
1137 //--------------------------------------------------
1138 // LOE.Clear(); LOE.Append(OE);
1139 // BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
1141 // StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
1143 LInt1.Clear(); LInt1.Append(OE);
1145 TopAbs_Orientation O1,O2;
1146 BRepOffset_Tool::OrientSection(OE,CF,OF1,O1,O2);
1147 // if (mySide == TopAbs_OUT);
1148 O1 = TopAbs::Reverse(O1);
1149 LInt1.First().Orientation(O1);
1150 Store(CF,OF1,LInt1,LInt2);
1156 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_VERTEX);
1157 exp.More(); exp.Next()) {
1158 const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
1159 if (!Analyse.HasAncestor(V)) {
1162 const TopTools_ListOfShape& LE = Analyse.Ancestors(V);
1163 TopTools_ListIteratorOfListOfShape itLE(LE);
1164 for (; itLE.More(); itLE.Next()) {
1165 const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
1166 const TopTools_ListOfShape& LF = Analyse.Ancestors(EV);
1167 TopTools_ListIteratorOfListOfShape itLF(LF);
1168 for ( ; itLF.More(); itLF.Next()) {
1169 const TopoDS_Face& FEV = TopoDS::Face(itLF.Value());
1170 //-------------------------------------------------
1171 // OF1 parallel face generated by uneFace ancestor of V[i].
1172 //-------------------------------------------------
1173 OF1 = TopoDS::Face(InitOffsetFace.Image(FEV).First());
1174 if (!IsDone(OF1,CF)) {
1175 //-------------------------------------------------------
1176 // Find if one of edges of OF1 has no trace in CF.
1177 //-------------------------------------------------------
1178 TopTools_ListOfShape LOE;
1179 TopExp_Explorer exp2(OF1.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1180 for ( ;exp2.More(); exp2.Next()) {
1181 LOE.Append(exp2.Current());
1183 BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide,myTol);
1184 //-------------------------------------------------------
1185 // If no trace try intersection.
1186 //-------------------------------------------------------
1187 if (LInt1.IsEmpty()) {
1188 BRepOffset_Tool::Inter3D (CF,OF1,LInt1,LInt2,mySide,NullEdge);
1190 Store (CF,OF1,LInt1,LInt2);
1198 //=======================================================================
1199 //function : AddCommonEdges
1201 //=======================================================================
1203 void BRepOffset_Inter3d::AddCommonEdges(const TopTools_ListOfShape&)
1208 //=======================================================================
1209 //function : SetDone
1211 //=======================================================================
1213 void BRepOffset_Inter3d::SetDone(const TopoDS_Face& F1,
1214 const TopoDS_Face& F2)
1216 if (!myDone.IsBound(F1)) {
1217 TopTools_ListOfShape empty;
1218 myDone.Bind(F1,empty);
1220 myDone(F1).Append(F2);
1221 if (!myDone.IsBound(F2)) {
1222 TopTools_ListOfShape empty;
1223 myDone.Bind(F2,empty);
1225 myDone(F2).Append(F1);
1229 //=======================================================================
1232 //=======================================================================
1234 Standard_Boolean BRepOffset_Inter3d::IsDone(const TopoDS_Face& F1,
1235 const TopoDS_Face& F2)
1238 if (myDone.IsBound(F1)) {
1239 TopTools_ListIteratorOfListOfShape it (myDone(F1));
1240 for (; it.More(); it.Next()) {
1241 if (it.Value().IsSame(F2)) return Standard_True;
1244 return Standard_False;
1248 //=======================================================================
1249 //function : TouchedFaces
1251 //=======================================================================
1253 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::TouchedFaces()
1259 //=======================================================================
1262 //=======================================================================
1264 Handle(BRepAlgo_AsDes) BRepOffset_Inter3d::AsDes() const
1270 //=======================================================================
1271 //function : NewEdges
1273 //=======================================================================
1275 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::NewEdges()
1282 //=======================================================================
1285 //=======================================================================
1287 void BRepOffset_Inter3d::Store(const TopoDS_Face& F1,
1288 const TopoDS_Face& F2,
1289 const TopTools_ListOfShape& LInt1,
1290 const TopTools_ListOfShape& LInt2)
1292 if (!LInt1.IsEmpty()) {
1295 myAsDes->Add( F1,LInt1);
1296 myAsDes->Add( F2,LInt2);
1297 TopTools_ListIteratorOfListOfShape it(LInt1);
1298 for (; it.More(); it.Next()) {
1299 myNewEdges.Add(it.Value());