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 <Bnd_Tools.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepAdaptor_Curve.hxx>
23 #include <BRepAlgo_AsDes.hxx>
24 #include <BRepAlgo_Image.hxx>
25 #include <BRepLib_MakeVertex.hxx>
26 #include <BRepOffset_Analyse.hxx>
27 #include <BRepOffset_DataMapOfShapeOffset.hxx>
28 #include <BRepOffset_Inter3d.hxx>
29 #include <BRepOffset_Interval.hxx>
30 #include <BRepOffset_ListOfInterval.hxx>
31 #include <BRepOffset_Offset.hxx>
32 #include <BRepOffset_Tool.hxx>
33 #include <Extrema_ExtPC.hxx>
34 #include <GeomAPI_ProjectPointOnCurve.hxx>
35 #include <Precision.hxx>
37 #include <TopExp_Explorer.hxx>
39 #include <TopoDS_Compound.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <TopTools_IndexedMapOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46 #include <TopTools_MapIteratorOfMapOfShape.hxx>
47 #include <TopTools_MapOfShape.hxx>
49 #include <BRepBndLib.hxx>
50 #include <BOPTools_BoxTree.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_BoxTree aBBTree;
118 aBBTree.SetSize (SetOfFaces.Extent());
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 aBBTree.Add(i, Bnd_Tools::Bnd2BVH(aBoxF));
138 // Perform selection of the pairs
139 BOPTools_BoxPairSelector aSelector;
140 aSelector.SetBVHSets (&aBBTree, &aBBTree);
141 aSelector.SetSame (Standard_True);
145 // Treat the selected pairs
146 const std::vector<BOPTools_BoxPairSelector::PairIDs>& aPairs = aSelector.Pairs();
147 const Standard_Integer aNbPairs = static_cast<Standard_Integer> (aPairs.size());
149 for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair)
151 const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair];
153 const TopoDS_Face& aF1 = TopoDS::Face (aMFaces.FindKey (Min (aPair.ID1, aPair.ID2)));
154 const TopoDS_Face& aF2 = TopoDS::Face (aMFaces.FindKey (Max (aPair.ID1, aPair.ID2)));
157 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 if (aE.Orientation() != TopAbs_FORWARD &&
451 aE.Orientation() != TopAbs_REVERSED)
452 // Face is connected to the vertex through internal edge
455 TopoDS_Iterator aItV(aE);
456 for (; aItV.More(); aItV.Next()) {
457 if (aS.IsSame(aItV.Value())) {
466 // get to the next face in the list
468 for (it1.Next(); it1.More(); it1.Next()) {
469 const TopoDS_Shape& aFV2 = it1.Value();
471 aExp.Init(aFV2, TopAbs_EDGE);
472 for (; aExp.More(); aExp.Next()) {
473 const TopoDS_Shape& aEV2 = aExp.Current();
474 if (aME.Contains(aEV2) &&
475 (Analyse.Ancestors(aEV2).Extent() == 2 || // Multi-connexity is not supported in Analyzer
476 (aEV2.Orientation() != TopAbs_FORWARD && // Avoid intersection of faces connected by internal edge
477 aEV2.Orientation() != TopAbs_REVERSED))) {
483 // faces share only vertex - make pair for intersection
491 aDMVLF1.Bind(aS, aLF1);
492 aDMVLF2.Bind(aS, aLF2);
497 aNb = VEmap.Extent();
498 for (i = 1; i <= aNb; ++i) {
499 const TopoDS_Shape& aS = VEmap(i);
502 TopTools_ListOfShape aLF1, aLF2;
504 bEdge = (aS.ShapeType() == TopAbs_EDGE);
506 // faces connected by the edge
507 E = *(TopoDS_Edge*)&aS;
509 const BRepOffset_ListOfInterval& L = Analyse.Type(E);
514 BRepOffset_Type OT = L.First().Type();
515 if (OT != BRepOffset_Convex && OT != BRepOffset_Concave) {
519 if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
520 else CurSide = TopAbs_OUT;
521 //-----------------------------------------------------------
522 // edge is of the proper type, return adjacent faces.
523 //-----------------------------------------------------------
524 const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
525 if (Anc.Extent() != 2) {
529 F1 = TopoDS::Face(Anc.First());
530 F2 = TopoDS::Face(Anc.Last ());
536 if (!aDMVLF1.IsBound(aS)) {
540 aLF1 = aDMVLF1.Find(aS);
541 aLF2 = aDMVLF2.Find(aS);
546 itF1.Initialize(aLF1);
547 itF2.Initialize(aLF2);
548 for (; itF1.More() && itF2.More(); itF1.Next(), itF2.Next()) {
549 F1 = TopoDS::Face(itF1.Value());
550 F2 = TopoDS::Face(itF2.Value());
552 OF1 = TopoDS::Face(MapSF(F1).Face());
553 OF2 = TopoDS::Face(MapSF(F2).Face());
554 if (!MES.IsBound(OF1)) {
555 Standard_Boolean enlargeU = Standard_True;
556 Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
557 BRepOffset_Tool::CheckBounds( F1, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
558 BRepOffset_Tool::EnLargeFace(OF1,NF1,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
562 NF1 = TopoDS::Face(MES(OF1));
565 if (!MES.IsBound(OF2)) {
566 Standard_Boolean enlargeU = Standard_True;
567 Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
568 BRepOffset_Tool::CheckBounds( F2, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
569 BRepOffset_Tool::EnLargeFace(OF2,NF2,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
573 NF2 = TopoDS::Face(MES(OF2));
576 if (!IsDone(NF1,NF2)) {
577 TopTools_ListOfShape LInt1,LInt2;
578 BRepOffset_Tool::Inter3D (NF1,NF2,LInt1,LInt2,CurSide,E,bEdge);
580 if (!LInt1.IsEmpty()) {
581 Store (NF1,NF2,LInt1,LInt2);
586 if (Build.IsBound(aS)) {
587 const TopoDS_Shape& aSE = Build(aS);
588 TopExp_Explorer aExp(aSE, TopAbs_EDGE);
589 for (; aExp.More(); aExp.Next()) {
590 const TopoDS_Shape& aNE = aExp.Current();
595 it.Initialize(LInt1);
596 for (; it.More(); it.Next()) {
597 const TopoDS_Shape& aNE = it.Value();
600 // keep connection from new edge to shape from which it was created
601 TopTools_ListOfShape *pLS = &aDMIntE(aDMIntE.Add(aNE, TopTools_ListOfShape()));
603 // keep connection to faces created the edge as well
604 TopTools_ListOfShape* pLFF = aDMIntFF.Bound(aNE, TopTools_ListOfShape());
614 } else { // IsDone(NF1,NF2)
615 // Modified by skv - Fri Dec 26 12:20:13 2003 OCC4455 Begin
616 const TopTools_ListOfShape &aLInt1 = myAsDes->Descendant(NF1);
617 const TopTools_ListOfShape &aLInt2 = myAsDes->Descendant(NF2);
619 if (!aLInt1.IsEmpty()) {
623 if (Build.IsBound(aS)) {
624 const TopoDS_Shape& aSE = Build(aS);
625 TopExp_Explorer aExp(aSE, TopAbs_EDGE);
626 for (; aExp.More(); aExp.Next()) {
627 const TopoDS_Shape& aNE = aExp.Current();
632 for (it.Initialize(aLInt1) ; it.More(); it.Next()) {
633 const TopoDS_Shape &anE1 = it.Value();
635 for (it1.Initialize(aLInt2) ; it1.More(); it1.Next()) {
636 const TopoDS_Shape &anE2 = it1.Value();
637 if (anE1.IsSame(anE2)) {
640 TopTools_ListOfShape *pLS = aDMIntE.ChangeSeek(anE1);
654 // Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End
657 // create unique intersection for each localized shared part
658 aNb = aDMIntE.Extent();
659 for (i = 1; i <= aNb; ++i) {
660 const TopTools_ListOfShape& aLS = aDMIntE(i);
661 if (aLS.Extent() < 2) {
666 const TopoDS_Edge& aE = TopoDS::Edge(aDMIntE.FindKey(i));
667 // faces created the edge
668 const TopTools_ListOfShape& aLFF = aDMIntFF.Find(aE);
669 const TopoDS_Shape& aF1 = aLFF.First();
670 const TopoDS_Shape& aF2 = aLFF.Last();
672 // Build really localized blocks from the original shapes in <aLS>:
673 // 1. Find edges from original faces connected to two or more shapes in <aLS>;
674 // 2. Make connexity blocks from edges in <aLS> and found connection edges;
675 // 3. Check if the vertices from <aLS> are not connected by these connection edges:
676 // a. If so - add these vertices to Connexity Block containing the corresponding
678 // b. If not - add this vertex to list of connexity blocks
679 // 4. Create unique intersection edge for each connexity block
682 TopTools_ListOfShape aLV;
683 // compound of edges to build connexity blocks
686 TopTools_MapOfShape aMS;
687 TopTools_ListIteratorOfListOfShape aItLS(aLS);
688 for (; aItLS.More(); aItLS.Next()) {
689 const TopoDS_Shape& aS = aItLS.Value();
691 if (aS.ShapeType() == TopAbs_EDGE) {
699 // look for additional edges to connect the shared parts
700 TopTools_MapOfShape aMEConnection;
701 for (Standard_Integer j = 0; j < 2; ++j) {
702 const TopoDS_Shape& aF = !j ? aF1 : aF2;
704 TopExp_Explorer aExp(aF, TopAbs_EDGE);
705 for (; aExp.More(); aExp.Next()) {
706 const TopoDS_Shape& aEF = aExp.Current();
707 if (aMS.Contains(aEF) || aMEConnection.Contains(aEF)) {
711 TopoDS_Vertex aV1, aV2;
712 TopExp::Vertices(TopoDS::Edge(aEF), aV1, aV2);
714 // find parts to which the edge is connected
715 Standard_Integer iCounter = 0;
716 aItLS.Initialize(aLS);
717 for (; aItLS.More(); aItLS.Next()) {
718 const TopoDS_Shape& aS = aItLS.Value();
719 // iterator is not suitable here, because aS may be a vertex
720 TopExp_Explorer aExpV(aS, TopAbs_VERTEX);
721 for (; aExpV.More(); aExpV.Next()) {
722 const TopoDS_Shape& aV = aExpV.Current();
723 if (aV.IsSame(aV1) || aV.IsSame(aV2)) {
732 aMEConnection.Add(aEF);
737 TopTools_ListOfShape aLCBE;
738 BOPTools_AlgoTools::MakeConnexityBlocks(aCE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
740 // create connexity blocks for alone vertices
741 TopTools_ListOfShape aLCBV;
742 TopTools_ListIteratorOfListOfShape aItLV(aLV);
743 for (; aItLV.More(); aItLV.Next()) {
744 const TopoDS_Shape& aV = aItLV.Value();
745 // check if this vertex is contained in some connexity block of edges
746 TopTools_ListIteratorOfListOfShape aItLCB(aLCBE);
747 for (; aItLCB.More(); aItLCB.Next()) {
748 TopoDS_Shape& aCB = aItLCB.ChangeValue();
749 TopExp_Explorer aExpV(aCB, TopAbs_VERTEX);
750 for (; aExpV.More(); aExpV.Next()) {
751 if (aV.IsSame(aExpV.Current())) {
761 if (!aItLCB.More()) {
771 if (aLCBE.Extent() == 1) {
775 const TopoDS_Shape& aNF1 = MES(MapSF(aF1).Face());
776 const TopoDS_Shape& aNF2 = MES(MapSF(aF2).Face());
778 TopTools_ListIteratorOfListOfShape aItLCB(aLCBE);
779 for (aItLCB.Next(); aItLCB.More(); aItLCB.Next()) {
780 // make new edge with different tedge instance
781 TopoDS_Edge aNewEdge;
782 TopoDS_Vertex aV1, aV2;
783 Standard_Real aT1, aT2;
785 TopExp::Vertices(aE, aV1, aV2);
786 BRep_Tool::Range(aE, aT1, aT2);
788 BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aNewEdge);
790 myAsDes->Add(aNF1, aNewEdge);
791 myAsDes->Add(aNF2, aNewEdge);
793 const TopoDS_Shape& aCB = aItLCB.Value();
794 TopoDS_Iterator aItCB(aCB);
795 for (; aItCB.More(); aItCB.Next()) {
796 const TopoDS_Shape& aS = aItCB.Value();
797 if (aMEConnection.Contains(aS)) {
800 TopoDS_Shape& aCI = Build.ChangeFind(aS);
802 TopoDS_Compound aNewCI;
803 B.MakeCompound(aNewCI);
804 TopExp_Explorer aExp(aCI, TopAbs_EDGE);
805 for (; aExp.More(); aExp.Next()) {
806 const TopoDS_Shape& aSx = aExp.Current();
807 if (!aSx.IsSame(aE)) {
811 B.Add(aNewCI, aNewEdge);
818 //=======================================================================
819 //function : ContextIntByInt
821 //=======================================================================
823 void BRepOffset_Inter3d::ContextIntByInt
824 (const TopTools_IndexedMapOfShape& ContextFaces,
825 const Standard_Boolean ExtentContext,
826 const BRepOffset_DataMapOfShapeOffset& MapSF,
827 const BRepOffset_Analyse& Analyse,
828 TopTools_DataMapOfShapeShape& MES,
829 TopTools_DataMapOfShapeShape& Build,
830 TopTools_ListOfShape& Failed,
831 const Standard_Boolean bIsPlanar)
833 TopTools_MapOfShape MV;
835 TopoDS_Face OF,NF,WCF;
839 TopTools_ListIteratorOfListOfShape it, itF;
840 Standard_Integer i, j, aNb, aNbVE;
841 Standard_Boolean bEdge;
843 aNb = ContextFaces.Extent();
844 for (i = 1; i <= aNb; i++) {
845 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i));
848 BRepOffset_Tool::EnLargeFace(CF,NF,0,0);
852 TopAbs_State Side = TopAbs_OUT;
854 for (i = 1; i <= aNb; i++) {
855 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i));
856 if (ExtentContext) WCF = TopoDS::Face(MES(CF));
859 TopTools_IndexedMapOfShape VEmap;
860 TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_EDGE , VEmap);
863 TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
866 aNbVE = VEmap.Extent();
867 for (j = 1; j <= aNbVE; ++j) {
868 const TopoDS_Shape& aS = VEmap(j);
870 bEdge = (aS.ShapeType() == TopAbs_EDGE);
873 TopTools_ListOfShape Anc;
876 // faces connected by the edge
878 E = *(TopoDS_Edge*)&aS;
879 if (!Analyse.HasAncestor(E)) {
880 //----------------------------------------------------------------
881 // the edges of faces of context that are not in the initial shape
882 // can appear in the result.
883 //----------------------------------------------------------------
884 if (!ExtentContext) {
889 if (!MES.IsBound(E)) {
891 Standard_Real f,l,Tol;
892 BRep_Tool::Range(E,f,l);
893 Tol = BRep_Tool::Tolerance(E);
896 TopExp::Vertices(E,V1,V2);
897 NE.Orientation(TopAbs_FORWARD);
898 myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
899 myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
900 TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
901 B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
902 aLocalShape = V2.Oriented(TopAbs_INTERNAL);
903 B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
904 // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
905 // B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
906 NE.Orientation(E.Orientation());
912 TopoDS_Shape NE = MES(E);
913 TopoDS_Shape aLocalShape = NE.Oriented(E.Orientation());
914 myAsDes->Add(CF,aLocalShape);
915 // myAsDes->Add(CF,NE.Oriented(E.Orientation()));
920 Anc = Analyse.Ancestors(E);
923 // faces connected by the vertex
925 if (!Analyse.HasAncestor(aS)) {
929 const TopTools_ListOfShape& aLE = Analyse.Ancestors(aS);
931 for (; it.More(); it.Next()) {
932 const TopoDS_Edge& aE = *(TopoDS_Edge*)&it.Value();
934 if (BRep_Tool::Degenerated(aE)) {
938 if (VEmap.Contains(aE)) {
942 const TopTools_ListOfShape& aLF = Analyse.Ancestors(aE);
944 for (; itF.More(); itF.Next()) {
945 const TopoDS_Shape& aF = itF.Value();
946 Standard_Boolean bAdd = Standard_True;
947 exp.Init(aF, TopAbs_EDGE);
948 for (; exp.More() && bAdd; exp.Next()) {
949 const TopoDS_Shape& aEF = exp.Current();
950 bAdd = !VEmap.Contains(aEF);
960 for (; itF.More(); itF.Next()) {
961 const TopoDS_Face& F = TopoDS::Face(itF.Value());
962 OF = TopoDS::Face(MapSF(F).Face());
963 TopoDS_Shape aLocalShape = MapSF(F).Generated(E);
964 OE = TopoDS::Edge(aLocalShape);
965 // OE = TopoDS::Edge(MapSF(F).Generated(E));
966 if (!MES.IsBound(OF)) {
967 BRepOffset_Tool::EnLargeFace(OF,NF,1,1);
971 NF = TopoDS::Face(MES(OF));
973 if (!IsDone(NF,CF)) {
974 TopTools_ListOfShape LInt1,LInt2;
975 TopTools_ListOfShape LOE;
977 BRepOffset_Tool::Inter3D (WCF,NF,LInt1,LInt2,Side,E,bEdge);
979 if (!LInt1.IsEmpty()) {
980 Store (CF,NF,LInt1,LInt2);
981 if ((LInt1.Extent() == 1) && !Build.IsBound(aS)) {
982 Build.Bind(aS,LInt1.First());
986 if (Build.IsBound(aS)) {
987 const TopoDS_Shape& aSE = Build(aS);
988 exp.Init(aSE, TopAbs_EDGE);
989 for (; exp.More(); exp.Next()) {
990 const TopoDS_Shape& aNE = exp.Current();
995 for (it.Initialize(LInt1) ; it.More(); it.Next()) {
1010 //=======================================================================
1011 //function : ContextIntByArc
1013 //=======================================================================
1015 void BRepOffset_Inter3d::ContextIntByArc(const TopTools_IndexedMapOfShape& ContextFaces,
1016 const Standard_Boolean InSide,
1017 const BRepOffset_Analyse& Analyse,
1018 const BRepAlgo_Image& InitOffsetFace,
1019 BRepAlgo_Image& InitOffsetEdge)
1022 TopTools_ListOfShape LInt1,LInt2;
1023 TopTools_MapOfShape MV;
1024 TopExp_Explorer exp;
1025 TopoDS_Face OF1,OF2;
1028 TopoDS_Edge NullEdge;
1031 for (j = 1; j <= ContextFaces.Extent(); j++) {
1032 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
1036 for (j = 1; j <= ContextFaces.Extent(); j++) {
1037 const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
1038 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1039 exp.More(); exp.Next()) {
1040 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1041 if (!Analyse.HasAncestor(E)) {
1046 if (!InitOffsetEdge.HasImage(E)) {
1047 Standard_Real f,l,Tol;
1048 BRep_Tool::Range(E,f,l);
1049 Tol = BRep_Tool::Tolerance(E);
1050 ExtentEdge(CF,E,NE);
1051 TopoDS_Vertex V1,V2;
1052 TopExp::Vertices(E,V1,V2);
1053 NE.Orientation(TopAbs_FORWARD);
1054 myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
1055 myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
1056 TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
1057 B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
1058 aLocalShape = V2.Oriented(TopAbs_INTERNAL);
1059 B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
1060 // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
1061 // B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
1062 NE.Orientation(E.Orientation());
1063 myAsDes->Add(CF,NE);
1064 InitOffsetEdge.Bind(E,NE);
1067 NE = TopoDS::Edge(InitOffsetEdge.Image(E).First());
1068 myAsDes->Add(CF,NE.Oriented(E.Orientation()));
1074 //---------------------------------------------------
1075 // OF1 parallel facee generated by the ancestor of E.
1076 //---------------------------------------------------
1077 const TopoDS_Shape SI = Analyse.Ancestors(E).First();
1078 OF1 = TopoDS::Face(InitOffsetFace.Image(SI).First());
1079 OE = TopoDS::Edge(InitOffsetEdge.Image(E).First());
1082 //Check if OE has pcurve in CF
1086 Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l);
1087 Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l);
1089 if(C1.IsNull() || C2.IsNull())
1095 //--------------------------------------------------
1096 // MAJ of OE on cap CF.
1097 //--------------------------------------------------
1098 // TopTools_ListOfShape LOE; LOE.Append(OE);
1099 // BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
1101 // StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
1103 LInt1.Clear(); LInt1.Append(OE);
1105 TopAbs_Orientation anOri1, anOri2;
1106 BRepOffset_Tool::OrientSection(OE,CF,OF1, anOri1,anOri2);
1107 // if (mySide == TopAbs_OUT);
1108 anOri1 = TopAbs::Reverse(anOri1);
1109 LInt1.First().Orientation(anOri1);
1110 Store(CF,OF1,LInt1,LInt2);
1112 //------------------------------------------------------
1113 // Processing of offsets on the ancestors of vertices.
1114 //------------------------------------------------------
1116 TopExp::Vertices (E,V[0],V[1]);
1117 for (Standard_Integer i = 0; i < 2; i++) {
1118 if (!MV.Add(V[i])) continue;
1120 const TopTools_ListOfShape& LE = Analyse.Ancestors(V[i]);
1121 TopTools_ListIteratorOfListOfShape itLE(LE);
1122 for ( ; itLE.More(); itLE.Next()) {
1123 const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
1124 if (InitOffsetFace.HasImage(EV)) {
1125 //-------------------------------------------------
1126 // OF1 parallel face generated by an ancester edge of V[i].
1127 //-------------------------------------------------
1128 OF1 = TopoDS::Face(InitOffsetFace.Image(EV).First());
1129 OE = TopoDS::Edge(InitOffsetEdge.Image(V[i]).First());
1132 //Check if OE has pcurve in CF and OF1
1136 Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l);
1137 Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l);
1139 if(C1.IsNull() || C2.IsNull())
1145 //--------------------------------------------------
1146 // MAj of OE on cap CF.
1147 //--------------------------------------------------
1148 // LOE.Clear(); LOE.Append(OE);
1149 // BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
1151 // StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
1153 LInt1.Clear(); LInt1.Append(OE);
1155 TopAbs_Orientation O1,O2;
1156 BRepOffset_Tool::OrientSection(OE,CF,OF1,O1,O2);
1157 // if (mySide == TopAbs_OUT);
1158 O1 = TopAbs::Reverse(O1);
1159 LInt1.First().Orientation(O1);
1160 Store(CF,OF1,LInt1,LInt2);
1166 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_VERTEX);
1167 exp.More(); exp.Next()) {
1168 const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
1169 if (!Analyse.HasAncestor(V)) {
1172 const TopTools_ListOfShape& LE = Analyse.Ancestors(V);
1173 TopTools_ListIteratorOfListOfShape itLE(LE);
1174 for (; itLE.More(); itLE.Next()) {
1175 const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
1176 const TopTools_ListOfShape& LF = Analyse.Ancestors(EV);
1177 TopTools_ListIteratorOfListOfShape itLF(LF);
1178 for ( ; itLF.More(); itLF.Next()) {
1179 const TopoDS_Face& FEV = TopoDS::Face(itLF.Value());
1180 //-------------------------------------------------
1181 // OF1 parallel face generated by uneFace ancestor of V[i].
1182 //-------------------------------------------------
1183 OF1 = TopoDS::Face(InitOffsetFace.Image(FEV).First());
1184 if (!IsDone(OF1,CF)) {
1185 //-------------------------------------------------------
1186 // Find if one of edges of OF1 has no trace in CF.
1187 //-------------------------------------------------------
1188 TopTools_ListOfShape LOE;
1189 TopExp_Explorer exp2(OF1.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1190 for ( ;exp2.More(); exp2.Next()) {
1191 LOE.Append(exp2.Current());
1193 BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide,myTol);
1194 //-------------------------------------------------------
1195 // If no trace try intersection.
1196 //-------------------------------------------------------
1197 if (LInt1.IsEmpty()) {
1198 BRepOffset_Tool::Inter3D (CF,OF1,LInt1,LInt2,mySide,NullEdge);
1200 Store (CF,OF1,LInt1,LInt2);
1208 //=======================================================================
1209 //function : AddCommonEdges
1211 //=======================================================================
1213 void BRepOffset_Inter3d::AddCommonEdges(const TopTools_ListOfShape&)
1218 //=======================================================================
1219 //function : SetDone
1221 //=======================================================================
1223 void BRepOffset_Inter3d::SetDone(const TopoDS_Face& F1,
1224 const TopoDS_Face& F2)
1226 if (!myDone.IsBound(F1)) {
1227 TopTools_ListOfShape empty;
1228 myDone.Bind(F1,empty);
1230 myDone(F1).Append(F2);
1231 if (!myDone.IsBound(F2)) {
1232 TopTools_ListOfShape empty;
1233 myDone.Bind(F2,empty);
1235 myDone(F2).Append(F1);
1239 //=======================================================================
1242 //=======================================================================
1244 Standard_Boolean BRepOffset_Inter3d::IsDone(const TopoDS_Face& F1,
1245 const TopoDS_Face& F2)
1248 if (myDone.IsBound(F1)) {
1249 TopTools_ListIteratorOfListOfShape it (myDone(F1));
1250 for (; it.More(); it.Next()) {
1251 if (it.Value().IsSame(F2)) return Standard_True;
1254 return Standard_False;
1258 //=======================================================================
1259 //function : TouchedFaces
1261 //=======================================================================
1263 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::TouchedFaces()
1269 //=======================================================================
1272 //=======================================================================
1274 Handle(BRepAlgo_AsDes) BRepOffset_Inter3d::AsDes() const
1280 //=======================================================================
1281 //function : NewEdges
1283 //=======================================================================
1285 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::NewEdges()
1292 //=======================================================================
1295 //=======================================================================
1297 void BRepOffset_Inter3d::Store(const TopoDS_Face& F1,
1298 const TopoDS_Face& F2,
1299 const TopTools_ListOfShape& LInt1,
1300 const TopTools_ListOfShape& LInt2)
1302 if (!LInt1.IsEmpty()) {
1305 myAsDes->Add( F1,LInt1);
1306 myAsDes->Add( F2,LInt2);
1307 TopTools_ListIteratorOfListOfShape it(LInt1);
1308 for (; it.More(); it.Next()) {
1309 myNewEdges.Add(it.Value());