92686696c97a952093fb0618df1e967c3fcb4eaa
[occt.git] / src / BRepOffset / BRepOffset_Inter3d.cxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //  Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455
18
19 #include <BRepOffset_Inter3d.ixx>
20 #include <BRepOffset_Tool.hxx>
21 #include <BRepOffset_Interval.hxx>
22 #include <BRepOffset_ListOfInterval.hxx>
23 #include <BRepOffset_DataMapOfShapeOffset.hxx>
24 #include <BRepOffset_Offset.hxx>
25 #include <BRepAdaptor_Curve.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepLib_MakeVertex.hxx>
29
30 #include <TopExp.hxx>
31 #include <TopExp_Explorer.hxx>
32 #include <TopoDS.hxx>
33 #include <TopoDS_Compound.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Vertex.hxx>
36 #include <TopOpeBRepTool_BoxSort.hxx>
37 #include <TopTools_ListIteratorOfListOfShape.hxx>
38 #include <TopTools_MapIteratorOfMapOfShape.hxx>
39 #include <TopTools_IndexedMapOfShape.hxx>
40 #include <Extrema_ExtPC.hxx>
41 #include <TopTools_MapOfShape.hxx>
42 #include <Precision.hxx>
43
44
45
46 //=======================================================================
47 //function : BRepOffset_Inter3d
48 //purpose  : 
49 //=======================================================================
50
51 BRepOffset_Inter3d::BRepOffset_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes, 
52                                        const TopAbs_State              Side ,
53                                        const Standard_Real             Tol)
54 :myAsDes(AsDes),
55 mySide(Side),
56 myTol(Tol)
57 {
58 }
59
60
61 //=======================================================================
62 //function : ExtentEdge
63 //purpose  : 
64 //=======================================================================
65
66 static void ExtentEdge(const TopoDS_Face& /*F*/,
67                        const TopoDS_Edge& E,
68                        TopoDS_Edge& NE) 
69 {
70   TopoDS_Shape aLocalShape = E.EmptyCopied();
71   NE = TopoDS::Edge(aLocalShape); 
72 //  NE = TopoDS::Edge(E.EmptyCopied()); 
73   
74
75   // Enough for analytic edges, in general case reconstruct the 
76   // geometry of the edge recalculating the intersection of surfaces.  
77
78   NE.Orientation(TopAbs_FORWARD);
79   Standard_Real f,l;
80   BRep_Tool::Range(E,f,l);
81   Standard_Real length = l-f;
82   f -=  100*length;
83   l +=  100*length;
84
85   BRep_Builder B;
86   B.Range(NE,f,l);
87   BRepAdaptor_Curve CE(E);
88   TopoDS_Vertex V1 = BRepLib_MakeVertex(CE.Value(f));
89   TopoDS_Vertex V2 = BRepLib_MakeVertex(CE.Value(l));
90   B.Add(NE,V1.Oriented(TopAbs_FORWARD));
91   B.Add(NE,V2.Oriented(TopAbs_REVERSED));
92   NE.Orientation(E.Orientation());
93
94 }
95
96 //=======================================================================
97 //function : SelectEdge
98 //purpose  : 
99 //=======================================================================
100
101 static void SelectEdge (const TopoDS_Face& /*F*/,
102                         const TopoDS_Face& /*EF*/,
103                         const TopoDS_Edge& E,
104                         TopTools_ListOfShape& LInt)
105 {
106   //------------------------------------------------------------
107   // Proofing on the intersections on periodical faces
108   //------------------------------------------------------------
109    TopTools_ListIteratorOfListOfShape it(LInt);
110 //  Modified by Sergey KHROMOV - Wed Jun  5 11:43:04 2002 Begin
111 //   Standard_Real dU = 1.0e100;
112   Standard_Real dU = RealLast();
113 //  Modified by Sergey KHROMOV - Wed Jun  5 11:43:05 2002 End
114   TopoDS_Edge   GE;
115
116   Standard_Real Fst, Lst, tmp;
117   BRep_Tool::Range(E, Fst, Lst);
118   BRepAdaptor_Curve  Ad1(E);
119  
120   gp_Pnt PFirst = Ad1.Value( Fst );  
121   gp_Pnt PLast  = Ad1.Value( Lst );  
122
123 //  Modified by Sergey KHROMOV - Wed Jun  5 11:23:10 2002 Begin
124    Extrema_ExtPC anExt;
125 //  Modified by Sergey KHROMOV - Wed Jun  5 11:23:11 2002 End
126   //----------------------------------------------------------------------
127   // Selection of edge that coversmost of the domain of the initial edge.
128   //---------------------------------------------------------------------- 
129   for (; it.More(); it.Next()) {
130     const TopoDS_Edge& EI = TopoDS::Edge(it.Value());
131
132     BRep_Tool::Range(EI, Fst, Lst);
133     BRepAdaptor_Curve  Ad2(EI);
134
135 //  Modified by Sergey KHROMOV - Wed Jun  5 11:25:03 2002 Begin
136     Standard_Integer i;
137     Standard_Real    aTol       = BRep_Tool::Tolerance(EI);
138     Standard_Boolean isMinFound = Standard_False;
139     Standard_Real    aSqrDist1  = Precision::Infinite();
140     Standard_Real    aSqrDist2  = Precision::Infinite();
141
142     anExt.Initialize(Ad2, Fst, Lst, aTol);
143
144 // Seek for the min distance for PFirst:
145     anExt.Perform(PFirst);
146     if (anExt.IsDone()) {
147       for (i = 1; i <= anExt.NbExt(); i++) {
148         if (anExt.IsMin(i)) {
149           const gp_Pnt &aPMin = anExt.Point(i).Value();
150
151           aSqrDist1  = PFirst.SquareDistance(aPMin);
152           isMinFound = Standard_True;
153
154           break;
155         }
156       }
157     }
158     if (!isMinFound) {
159       gp_Pnt aP1 = Ad2.Value(Fst);
160       gp_Pnt aP2 = Ad2.Value(Lst);
161
162       aSqrDist1 = Min(aP1.SquareDistance(PFirst), aP2.SquareDistance(PFirst));
163     }
164
165 // Seek for the min distance for PLast:
166     isMinFound = Standard_False;
167     anExt.Perform(PLast);
168     if (anExt.IsDone()) {
169       for (i = 1; i <= anExt.NbExt(); i++) {
170         if (anExt.IsMin(i)) {
171           const gp_Pnt &aPMin = anExt.Point(i).Value();
172
173           aSqrDist2  = PLast.SquareDistance(aPMin);
174           isMinFound = Standard_True;
175
176           break;
177         }
178       }
179     }
180     if (!isMinFound) {
181       gp_Pnt aP1 = Ad2.Value(Fst);
182       gp_Pnt aP2 = Ad2.Value(Lst);
183
184       aSqrDist2 = Min(aP1.SquareDistance(PLast), aP2.SquareDistance(PLast));
185     }
186
187     tmp = aSqrDist1 + aSqrDist2;
188 //     gp_Pnt P1 = Ad2.Value(Fst);
189 //     gp_Pnt P2 = Ad2.Value(Lst);
190        
191 //     tmp = P1.Distance(PFirst) + P2.Distance(PLast);
192     if( tmp <= dU ) {
193       dU = tmp;
194       GE = EI;
195     } 
196 //  Modified by Sergey KHROMOV - Wed Jun  5 11:24:54 2002 End
197
198   }
199   LInt.Clear(); 
200   LInt.Append(GE);
201 }
202
203
204 //=======================================================================
205 //function : CompletInt
206 //purpose  : 
207 //=======================================================================
208
209 void BRepOffset_Inter3d::CompletInt(const TopTools_ListOfShape& SetOfFaces,
210                                     const BRepAlgo_Image&     InitOffsetFace)
211 {
212   //---------------------------------------------------------------
213   // Calculate the intersections of offset faces 
214   // Distinction of intersection between faces // tangents.
215   //---------------------------------------------------------------
216   TopoDS_Face                        F1,F2;
217   TopTools_ListIteratorOfListOfShape it;
218
219   //---------------------------------------------------------------
220   // Construction of bounding boxes
221   //---------------------------------------------------------------
222   TopOpeBRepTool_BoxSort BOS;
223   BRep_Builder B;
224   TopoDS_Compound CompOS;
225   B.MakeCompound(CompOS);
226   
227   for (it.Initialize(SetOfFaces); it.More(); it.Next()) {
228     const TopoDS_Shape& OS = it.Value();
229     B.Add(CompOS,OS);
230   }
231   BOS.AddBoxesMakeCOB(CompOS,TopAbs_FACE);
232
233   //---------------------------
234   // Intersection of faces // 
235   //---------------------------
236   for (it.Initialize(SetOfFaces); it.More(); it.Next()) {
237     const TopoDS_Face& F1  = TopoDS::Face(it.Value());
238     TColStd_ListIteratorOfListOfInteger itLI = BOS.Compare(F1);
239     for (; itLI.More(); itLI.Next()) {
240       F2     = TopoDS::Face(BOS.TouchedShape(itLI));
241       FaceInter(F1,F2,InitOffsetFace);
242     }
243   }
244 }
245
246
247 //=======================================================================
248 //function : CompletInt
249 //purpose  : 
250 //=======================================================================
251
252 void BRepOffset_Inter3d::FaceInter(const TopoDS_Face& F1,
253                                    const TopoDS_Face& F2,
254                                    const BRepAlgo_Image&     InitOffsetFace)
255 {
256   TopTools_ListOfShape LInt1, LInt2;
257   TopoDS_Edge NullEdge;
258
259   if (F1.IsSame(F2)) return;
260   if (IsDone(F1,F2)) return;
261   const TopoDS_Shape& InitF1 = InitOffsetFace.ImageFrom(F1);
262   const TopoDS_Shape& InitF2 = InitOffsetFace.ImageFrom(F2);
263   Standard_Boolean InterPipes = (InitF2.ShapeType() == TopAbs_EDGE &&
264                                  InitF1.ShapeType() == TopAbs_EDGE );
265   Standard_Boolean InterFaces = (InitF1.ShapeType() == TopAbs_FACE && 
266                                  InitF2.ShapeType() == TopAbs_FACE);
267   TopTools_ListOfShape LE,LV;
268   LInt1.Clear(); LInt2.Clear(); 
269   if (BRepOffset_Tool::HasCommonShapes(F1,F2,LE,LV) ||
270       myAsDes->HasCommonDescendant(F1,F2,LE)) {
271     //-------------------------------------------------
272     // F1 and F2 share shapes.
273     //-------------------------------------------------
274     if ( LE.IsEmpty() && !LV.IsEmpty()) {
275       if (InterPipes) {
276         //----------------------
277         // tubes share a vertex.
278         //----------------------
279         const TopoDS_Edge& EE1 = TopoDS::Edge(InitF1);
280         const TopoDS_Edge& EE2 = TopoDS::Edge(InitF2);
281         TopoDS_Vertex VE1[2],VE2[2];
282         TopExp::Vertices(EE1,VE1[0],VE1[1]);
283         TopExp::Vertices(EE2,VE2[0],VE2[1]);
284         TopoDS_Vertex V;
285         for (Standard_Integer i = 0 ; i < 2; i++) {
286           for (Standard_Integer j = 0 ; j < 2; j++) {
287             if (VE1[i].IsSame(VE2[j])) {
288               V = VE1[i];
289             }
290           }
291         }
292         if (!InitOffsetFace.HasImage(V)) { //no sphere
293           BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide);
294         }               
295       }
296       else {
297         //--------------------------------------------------------
298         // Intersection having only common vertices
299         // and supports having common edges.
300         // UNSUFFICIENT, but a larger criterion shakes too
301         // many sections.
302         //--------------------------------------------------------
303         if (InterFaces && 
304             BRepOffset_Tool::HasCommonShapes(TopoDS::Face(InitF1),
305                                              TopoDS::Face(InitF2),LE,LV)) 
306           if (!LE.IsEmpty())
307             BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
308       }
309     }
310   }
311   else {
312     if (InterPipes) {
313       BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide);
314     }
315     else {
316       BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
317     }
318   }
319   Store (F1,F2,LInt1,LInt2);
320 }
321
322
323 //=======================================================================
324 //function : ConnexIntByArc
325 //purpose  : 
326 //=======================================================================
327
328 void BRepOffset_Inter3d::ConnexIntByArc(const TopTools_ListOfShape& /*SetOfFaces*/, 
329                                         const TopoDS_Shape&         ShapeInit, 
330                                         const BRepOffset_Analyse&   Analyse, 
331                                         const BRepAlgo_Image&       InitOffsetFace)
332 {
333   BRepOffset_Type    OT   = BRepOffset_Concave;
334   if (mySide == TopAbs_OUT) OT   = BRepOffset_Convex;
335   TopExp_Explorer                Exp(ShapeInit,TopAbs_EDGE);
336   TopTools_ListOfShape           LInt1,LInt2;
337   TopoDS_Face                    F1,F2;
338   TopoDS_Edge                    NullEdge;
339
340   //---------------------------------------------------------------------
341   // etape 1 : Intersection of faces // corresponding to the initial faces 
342   //           separated by a concave edge if offset > 0, otherwise convex.
343   //---------------------------------------------------------------------  
344   for (; Exp.More(); Exp.Next()) {
345     const TopoDS_Edge&               E = TopoDS::Edge(Exp.Current());
346     const BRepOffset_ListOfInterval& L = Analyse.Type(E);
347     if (!L.IsEmpty() && L.First().Type() == OT) {
348       //-----------------------------------------------------------
349       // edge is of the proper type , return adjacent faces.
350       //-----------------------------------------------------------
351       const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
352       if (Anc.Extent() == 2) {
353         F1 = TopoDS::Face(InitOffsetFace.Image(Anc.First()).First());
354         F2 = TopoDS::Face(InitOffsetFace.Image(Anc.Last ()).First());
355         if (!IsDone(F1,F2)) {
356           BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,E,Standard_True);
357           Store (F1,F2,LInt1,LInt2);
358         }
359       }   
360     }
361   }
362   //---------------------------------------------------------------------
363   // etape 2 : Intersections of tubes sharing a vertex without sphere with:
364   //           - tubes on each other edge sharing the vertex
365   //           - faces containing an edge connected to vertex that has no tubes.
366   //---------------------------------------------------------------------
367   TopoDS_Vertex                      V[2];
368   TopTools_ListIteratorOfListOfShape it; 
369   
370   for (Exp.Init(ShapeInit,TopAbs_EDGE); Exp.More(); Exp.Next()) {
371     const TopoDS_Edge& E1 = TopoDS::Edge(Exp.Current());
372     if (InitOffsetFace.HasImage(E1)) {
373       //---------------------------
374       // E1 generated a tube.
375       //---------------------------
376       F1 = TopoDS::Face(InitOffsetFace.Image(E1).First());;
377       TopExp::Vertices(E1,V[0],V[1]);
378       const TopTools_ListOfShape& AncE1 = Analyse.Ancestors(E1);
379       
380       for (Standard_Integer i = 0; i < 2; i++) {
381         if (!InitOffsetFace.HasImage(V[i])) {
382           //-----------------------------
383           // the vertex has no sphere.
384           //-----------------------------
385           const TopTools_ListOfShape& Anc     = Analyse.Ancestors(V[i]);
386           TopTools_ListOfShape TangOnV;
387           Analyse.TangentEdges(E1,V[i],TangOnV);
388           TopTools_MapOfShape MTEV;
389           for (it.Initialize(TangOnV); it.More(); it.Next()) {
390             MTEV.Add(it.Value());
391           }
392           for (it.Initialize(Anc); it.More(); it.Next()) {
393             const TopoDS_Edge& E2 = TopoDS::Edge(it.Value());
394 //  Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 Begin
395 //          if (E1.IsSame(E2) || MTEV.Contains(E2)) continue;
396             Standard_Boolean isToSkip = Standard_False;
397
398             if (!E1.IsSame(E2)) {
399               const BRepOffset_ListOfInterval& aL = Analyse.Type(E2);
400
401               isToSkip = (MTEV.Contains(E2) && 
402                           (aL.IsEmpty() ||
403                           (!aL.IsEmpty() && aL.First().Type() != OT)));
404             }
405
406             if (E1.IsSame(E2) || isToSkip)
407               continue;
408 //  Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 End
409             if (InitOffsetFace.HasImage(E2)) {
410               //-----------------------------
411               // E2 generated a tube.
412               //-----------------------------
413               F2 = TopoDS::Face(InitOffsetFace.Image(E2).First());      
414               if (!IsDone(F1,F2)) {
415                 //---------------------------------------------------------------------
416                 // Intersection tube/tube if the edges are not tangent (AFINIR).
417                 //----------------------------------------------------------------------
418                 BRepOffset_Tool::PipeInter (F1,F2,LInt1,LInt2,mySide);
419                 Store (F1,F2,LInt1,LInt2);
420               }
421             }
422             else {
423               //-------------------------------------------------------
424               // Intersection of the tube of E1 with faces //
425               // to face containing E2 if they are not tangent
426               // to the tube or if E2 is not a tangent edge.
427               //-------------------------------------------------------
428               const BRepOffset_ListOfInterval& L = Analyse.Type(E2);
429               if (!L.IsEmpty() && L.First().Type() == BRepOffset_Tangent) {
430                 continue;
431               }
432               const TopTools_ListOfShape& AncE2        = Analyse.Ancestors(E2);
433               Standard_Boolean            TangentFaces = Standard_False;
434               if (AncE2.Extent() == 2) {
435                 TopoDS_Face InitF2 = TopoDS::Face(AncE2.First ());
436                 TangentFaces = (InitF2.IsSame(AncE1.First()) || 
437                                 InitF2.IsSame(AncE1.Last()));
438                 if (!TangentFaces) {
439                   F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First());
440                   if (!IsDone(F1,F2)) {
441                     BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
442                     Store (F1,F2,LInt1,LInt2);
443                   }
444                 }
445                 InitF2 = TopoDS::Face(AncE2.Last ());
446                 TangentFaces = (InitF2.IsSame(AncE1.First()) || 
447                                 InitF2.IsSame(AncE1.Last()));
448                 if (!TangentFaces) {
449                   F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First());
450                   if (!IsDone(F1,F2)) {
451                     BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
452                     Store (F1,F2,LInt1,LInt2);
453                   }
454                 }
455               }
456             }
457           }
458         }
459       }
460     }
461   }
462 }
463
464
465 //=======================================================================
466 //function : ConnexIntByInt
467 //purpose  : 
468 //=======================================================================
469
470 void BRepOffset_Inter3d::ConnexIntByInt
471 (const TopoDS_Shape&                    SI,
472  const BRepOffset_DataMapOfShapeOffset& MapSF,
473  const BRepOffset_Analyse&              Analyse,
474  TopTools_DataMapOfShapeShape&          MES,
475  TopTools_DataMapOfShapeShape&          Build,
476  TopTools_ListOfShape&                  Failed)
477 {
478   //TopExp_Explorer Exp(SI,TopAbs_EDGE);
479   TopTools_IndexedMapOfShape Emap;
480   TopExp::MapShapes( SI, TopAbs_EDGE, Emap );
481   TopoDS_Face     F1,F2,OF1,OF2,NF1,NF2;
482   TopAbs_State    CurSide = mySide;
483   BRep_Builder    B;
484   TopTools_ListIteratorOfListOfShape it;
485
486   //for (; Exp.More(); Exp.Next()) {
487   for (Standard_Integer i = 1; i <= Emap.Extent(); i++) {
488     //const TopoDS_Edge&               E = TopoDS::Edge(Exp.Current());
489     const TopoDS_Edge& E = TopoDS::Edge(Emap(i));
490     const BRepOffset_ListOfInterval& L = Analyse.Type(E);
491     if (!L.IsEmpty()) {
492       BRepOffset_Type    OT   = L.First().Type();
493       if (OT == BRepOffset_Convex || OT == BRepOffset_Concave) {
494         if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
495         else                          CurSide = TopAbs_OUT;
496         //-----------------------------------------------------------
497         // edge is of the proper type, return adjacent faces.
498         //-----------------------------------------------------------
499         const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
500         if (Anc.Extent() != 2) continue;
501         F1  = TopoDS::Face(Anc.First());
502         F2  = TopoDS::Face(Anc.Last ());
503         OF1 = TopoDS::Face(MapSF(F1).Face()); OF2 = TopoDS::Face(MapSF(F2).Face());
504         if (!MES.IsBound(OF1)) {
505           Standard_Boolean enlargeU = Standard_True;
506           Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
507           BRepOffset_Tool::CheckBounds( F1, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
508           BRepOffset_Tool::EnLargeFace(OF1,NF1,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
509           MES.Bind(OF1,NF1);
510         }
511         else {
512           NF1 = TopoDS::Face(MES(OF1));
513         }
514         if (!MES.IsBound(OF2)) {
515           Standard_Boolean enlargeU = Standard_True;
516           Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
517           BRepOffset_Tool::CheckBounds( F2, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
518           BRepOffset_Tool::EnLargeFace(OF2,NF2,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
519           MES.Bind(OF2,NF2); 
520         }
521         else {
522           NF2 = TopoDS::Face(MES(OF2));
523         }
524         if (!IsDone(NF1,NF2)) {
525           TopTools_ListOfShape LInt1,LInt2;
526           BRepOffset_Tool::Inter3D (NF1,NF2,LInt1,LInt2,CurSide,E,Standard_True);
527           if (LInt1.Extent() > 1)
528             { 
529               // intersection is in seceral edges (free sewing)
530               SelectEdge( NF1, NF2, E, LInt1 );
531               SelectEdge( NF1, NF2, E, LInt2 );
532             }
533           SetDone(NF1,NF2);
534           if (!LInt1.IsEmpty()) {
535             Store (NF1,NF2,LInt1,LInt2);
536             TopoDS_Compound C;
537             B.MakeCompound(C);
538             for (it.Initialize(LInt1) ; it.More(); it.Next()) {
539               B.Add(C,it.Value());
540             }
541             Build.Bind(E,C);
542           }
543           else {
544             Failed.Append(E);
545           }
546         } else { // IsDone(NF1,NF2)
547           //  Modified by skv - Fri Dec 26 12:20:13 2003 OCC4455 Begin
548           const TopTools_ListOfShape &aLInt1 = myAsDes->Descendant(NF1);
549           const TopTools_ListOfShape &aLInt2 = myAsDes->Descendant(NF2);
550
551           if (!aLInt1.IsEmpty()) {
552             TopoDS_Compound C;
553             TopTools_ListIteratorOfListOfShape anIt2;
554
555             B.MakeCompound(C);
556
557             for (it.Initialize(aLInt1) ; it.More(); it.Next()) {
558               const TopoDS_Shape &anE1 = it.Value();
559
560               for (anIt2.Initialize(aLInt2) ; anIt2.More(); anIt2.Next()) {
561                 const TopoDS_Shape &anE2 = anIt2.Value();
562
563                 if (anE1.IsSame(anE2))
564                   B.Add(C, anE1);
565               }
566             }
567             Build.Bind(E,C);
568           }
569           else {
570             Failed.Append(E);
571           }
572         }
573         //  Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End
574       }   
575     }
576   }
577 }
578
579 //=======================================================================
580 //function : ContextIntByInt
581 //purpose  : 
582 //=======================================================================
583
584 void BRepOffset_Inter3d::ContextIntByInt
585 (const TopTools_IndexedMapOfShape&      ContextFaces, 
586  const Standard_Boolean                 ExtentContext,
587  const BRepOffset_DataMapOfShapeOffset& MapSF,
588  const BRepOffset_Analyse&              Analyse,
589  TopTools_DataMapOfShapeShape&          MES,
590  TopTools_DataMapOfShapeShape&          Build,
591  TopTools_ListOfShape&                  Failed)
592 {
593   TopTools_ListOfShape             LInt1,LInt2;
594   TopTools_MapOfShape              MV;
595   TopExp_Explorer                  exp;
596   TopoDS_Face                      OF,NF,WCF;
597   TopoDS_Edge                      OE;
598   TopoDS_Compound                  C;
599   BRep_Builder                     B;
600   TopTools_ListIteratorOfListOfShape it;
601   Standard_Integer i;
602   
603   for (i = 1; i <= ContextFaces.Extent(); i++) {
604     const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i));
605     myTouched.Add(CF);
606     if (ExtentContext) {
607       BRepOffset_Tool::EnLargeFace(CF,NF,0,0);
608       MES.Bind(CF,NF);
609     }
610   }
611   TopAbs_State Side = TopAbs_OUT;
612  
613   for (i = 1; i <= ContextFaces.Extent(); i++) {
614     const TopoDS_Face& CF  = TopoDS::Face(ContextFaces(i));
615     if (ExtentContext) WCF = TopoDS::Face(MES(CF));
616     else               WCF = CF;
617
618     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
619          exp.More(); exp.Next()) {
620       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
621       if (!Analyse.HasAncestor(E)) {
622         //----------------------------------------------------------------
623         // the edges of faces of context that are not in the initial shape
624         // can appear in the result.
625         //----------------------------------------------------------------
626         if (!ExtentContext) {
627           myAsDes->Add(CF,E);
628           myNewEdges.Add(E);
629         }
630         else {
631           if (!MES.IsBound(E)) {
632             TopoDS_Edge NE;
633             Standard_Real f,l,Tol;
634             BRep_Tool::Range(E,f,l);
635             Tol = BRep_Tool::Tolerance(E);
636             ExtentEdge(CF,E,NE);
637             TopoDS_Vertex V1,V2;
638             TopExp::Vertices(E,V1,V2);
639             NE.Orientation(TopAbs_FORWARD);
640             myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
641             myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
642             TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
643             B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
644             aLocalShape = V2.Oriented(TopAbs_INTERNAL);
645             B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
646 //          B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
647 //          B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
648             NE.Orientation(E.Orientation());
649             myAsDes->Add(CF,NE);
650             myNewEdges.Add(NE);
651             MES.Bind(E,NE);
652           }
653           else {
654             TopoDS_Shape NE = MES(E);
655             TopoDS_Shape aLocalShape = NE.Oriented(E.Orientation());
656             myAsDes->Add(CF,aLocalShape);
657 //          myAsDes->Add(CF,NE.Oriented(E.Orientation()));
658           }
659         }
660         continue;
661       } 
662       const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
663       const TopoDS_Face&          F   = TopoDS::Face(Anc.First());
664       OF = TopoDS::Face(MapSF(F).Face());
665       TopoDS_Shape aLocalShape = MapSF(F).Generated(E);
666       OE = TopoDS::Edge(aLocalShape);
667 //      OE = TopoDS::Edge(MapSF(F).Generated(E));
668       if (!MES.IsBound(OF)) {
669         BRepOffset_Tool::EnLargeFace(OF,NF,1,1);
670         MES.Bind(OF,NF);
671       }
672       else {
673         NF = TopoDS::Face(MES(OF));
674       }
675       if (!IsDone(NF,CF)) {
676         TopTools_ListOfShape LInt1,LInt2;
677         TopTools_ListOfShape LOE;
678         LOE.Append(OE);
679         BRepOffset_Tool::Inter3D (WCF,NF,LInt1,LInt2,Side,E,Standard_True);
680         SetDone(NF,CF);
681         if (!LInt1.IsEmpty()) {
682           Store (CF,NF,LInt1,LInt2);
683           if (LInt1.Extent() == 1) {
684             Build.Bind(E,LInt1.First());
685           }
686           else {
687             B.MakeCompound(C);
688             for (it.Initialize(LInt1) ; it.More(); it.Next()) {
689               B.Add(C,it.Value());
690             }
691             Build.Bind(E,C);
692           }
693         }
694         else {
695           Failed.Append(E);
696         }
697       }
698     }
699   }
700 }
701
702 //=======================================================================
703 //function : ContextIntByArc
704 //purpose  : 
705 //=======================================================================
706
707 void BRepOffset_Inter3d::ContextIntByArc(const TopTools_IndexedMapOfShape& ContextFaces, 
708                                          const Standard_Boolean            InSide,
709                                          const BRepOffset_Analyse&         Analyse, 
710                                          const BRepAlgo_Image&             InitOffsetFace, 
711                                                BRepAlgo_Image&             InitOffsetEdge)
712
713
714   TopTools_ListOfShape                      LInt1,LInt2;
715   TopTools_MapOfShape                       MV;
716   TopExp_Explorer                           exp;
717   TopoDS_Face                               OF1,OF2;
718   TopoDS_Edge                               OE;
719   BRep_Builder                              B;  
720   TopoDS_Edge                               NullEdge;
721   Standard_Integer j;
722
723   for (j = 1; j <= ContextFaces.Extent(); j++) {
724     const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
725     myTouched.Add(CF);
726   }
727
728   for (j = 1; j <= ContextFaces.Extent(); j++) {
729     const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
730     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
731          exp.More(); exp.Next()) {
732       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
733       if (!Analyse.HasAncestor(E)) {
734         if (InSide)
735           myAsDes->Add(CF,E);
736         else {
737           TopoDS_Edge NE;
738           if (!InitOffsetEdge.HasImage(E)) {
739             Standard_Real f,l,Tol;
740             BRep_Tool::Range(E,f,l);
741             Tol = BRep_Tool::Tolerance(E);
742             ExtentEdge(CF,E,NE);
743             TopoDS_Vertex V1,V2;
744             TopExp::Vertices(E,V1,V2);
745             NE.Orientation(TopAbs_FORWARD);
746             myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
747             myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
748             TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
749             B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
750             aLocalShape = V2.Oriented(TopAbs_INTERNAL);
751             B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
752 //          B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
753 //          B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
754             NE.Orientation(E.Orientation());
755             myAsDes->Add(CF,NE);
756             InitOffsetEdge.Bind(E,NE);
757           }
758           else {
759             NE = TopoDS::Edge(InitOffsetEdge.Image(E).First());
760             myAsDes->Add(CF,NE.Oriented(E.Orientation()));
761           }
762         }
763         continue;
764       }
765       OE.Nullify();
766       //---------------------------------------------------
767       // OF1 parallel facee generated by the ancestor of E.
768       //---------------------------------------------------
769       const TopoDS_Shape SI = Analyse.Ancestors(E).First();
770       OF1 = TopoDS::Face(InitOffsetFace.Image(SI).First());
771       OE  = TopoDS::Edge(InitOffsetEdge.Image(E).First());      
772       //--------------------------------------------------
773       // MAJ of OE on cap CF.
774       //--------------------------------------------------
775 //      TopTools_ListOfShape LOE; LOE.Append(OE);             
776 //      BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
777 //      LInt2.Clear();
778 //      StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
779 //                 LInt1,LInt2);
780       LInt1.Clear(); LInt1.Append(OE);
781       LInt2.Clear();    
782       TopAbs_Orientation O1,O2;
783       BRepOffset_Tool::OrientSection(OE,CF,OF1,O1,O2);
784 //      if (mySide == TopAbs_OUT) O1 = TopAbs::Reverse(O1);
785       O1 = TopAbs::Reverse(O1);
786       LInt1.First().Orientation(O1);
787       Store(CF,OF1,LInt1,LInt2);
788       
789       //------------------------------------------------------
790       // Processing of offsets on the ancestors of vertices.
791       //------------------------------------------------------
792       TopoDS_Vertex V[2];
793       TopExp::Vertices (E,V[0],V[1]);
794       for (Standard_Integer i = 0; i < 2; i++) {
795         if (!MV.Add(V[i])) continue;
796         OF1.Nullify(); 
797         const TopTools_ListOfShape& LE =  Analyse.Ancestors(V[i]);
798         TopTools_ListIteratorOfListOfShape itLE(LE);
799         for ( ; itLE.More(); itLE.Next()) {
800           const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
801           if (InitOffsetFace.HasImage(EV)) {
802             //-------------------------------------------------
803             // OF1 parallel face generated by an ancester edge of V[i].
804             //-------------------------------------------------
805             OF1 = TopoDS::Face(InitOffsetFace.Image(EV).First());
806             OE  = TopoDS::Edge(InitOffsetEdge.Image(V[i]).First());
807             //--------------------------------------------------
808             // MAj of OE on cap CF.
809             //--------------------------------------------------
810             //        LOE.Clear(); LOE.Append(OE);
811             //        BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
812             //        LInt2.Clear();
813             //        StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
814             //                     LInt1,LInt2);
815             LInt1.Clear(); LInt1.Append(OE);
816             LInt2.Clear();    
817             TopAbs_Orientation O1,O2;
818             BRepOffset_Tool::OrientSection(OE,CF,OF1,O1,O2);      
819 //          if (mySide == TopAbs_OUT);
820             O1 = TopAbs::Reverse(O1);
821             LInt1.First().Orientation(O1);
822             Store(CF,OF1,LInt1,LInt2);
823           }
824         }
825       }
826     }
827     
828     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_VERTEX); 
829          exp.More(); exp.Next()) {
830       const TopoDS_Vertex&        V  = TopoDS::Vertex(exp.Current());
831       if (!Analyse.HasAncestor(V)) {
832         continue;
833       }
834       const TopTools_ListOfShape& LE =  Analyse.Ancestors(V);
835       TopTools_ListIteratorOfListOfShape itLE(LE);
836       for (; itLE.More(); itLE.Next()) {
837         const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
838         const TopTools_ListOfShape& LF = Analyse.Ancestors(EV);
839         TopTools_ListIteratorOfListOfShape itLF(LF);
840         for ( ; itLF.More(); itLF.Next()) {
841           const TopoDS_Face& FEV = TopoDS::Face(itLF.Value());
842           //-------------------------------------------------
843           // OF1 parallel face generated by uneFace ancestor of V[i].
844           //-------------------------------------------------
845           OF1 = TopoDS::Face(InitOffsetFace.Image(FEV).First());
846           if (!IsDone(OF1,CF)) {
847             //-------------------------------------------------------
848             // Find if one of edges of OF1 has no trace in CF.
849             //-------------------------------------------------------
850             TopTools_ListOfShape LOE;
851             TopExp_Explorer exp2(OF1.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
852             for ( ;exp2.More(); exp2.Next()) {
853               LOE.Append(exp2.Current());
854             }
855             BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide,myTol);
856             //-------------------------------------------------------
857             // If no trace try intersection.
858             //-------------------------------------------------------
859             if (LInt1.IsEmpty()) {
860               BRepOffset_Tool::Inter3D (CF,OF1,LInt1,LInt2,mySide,NullEdge);
861             }
862             Store (CF,OF1,LInt1,LInt2);
863           }
864         }
865       }
866     } 
867   }
868 }
869
870 //=======================================================================
871 //function : AddCommonEdges
872 //purpose  : 
873 //=======================================================================
874
875 void BRepOffset_Inter3d::AddCommonEdges(const TopTools_ListOfShape&)
876 {
877 }
878
879
880 //=======================================================================
881 //function : SetDone
882 //purpose  : 
883 //=======================================================================
884
885 void BRepOffset_Inter3d::SetDone(const TopoDS_Face& F1, 
886                                  const TopoDS_Face& F2)
887 {
888   if (!myDone.IsBound(F1)) {
889     TopTools_ListOfShape empty;
890     myDone.Bind(F1,empty);
891   }
892   myDone(F1).Append(F2);
893   if (!myDone.IsBound(F2)) {
894     TopTools_ListOfShape empty;
895     myDone.Bind(F2,empty);
896   }
897   myDone(F2).Append(F1);
898 }
899
900
901 //=======================================================================
902 //function : IsDone
903 //purpose  : 
904 //=======================================================================
905
906 Standard_Boolean BRepOffset_Inter3d::IsDone(const TopoDS_Face& F1, 
907                                             const TopoDS_Face& F2) 
908 const 
909 {
910   if (myDone.IsBound(F1)) {
911     TopTools_ListIteratorOfListOfShape it (myDone(F1));
912     for (; it.More(); it.Next()) {
913       if (it.Value().IsSame(F2)) return Standard_True;
914     }
915   }
916   return Standard_False;
917 }
918
919
920 //=======================================================================
921 //function : TouchedFaces
922 //purpose  : 
923 //=======================================================================
924
925 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::TouchedFaces()
926 {
927   return myTouched;
928 }
929
930
931 //=======================================================================
932 //function : AsDes
933 //purpose  : 
934 //=======================================================================
935
936 Handle(BRepAlgo_AsDes) BRepOffset_Inter3d::AsDes() const 
937 {
938   return myAsDes;
939 }
940
941
942 //=======================================================================
943 //function : NewEdges
944 //purpose  : 
945 //=======================================================================
946
947 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::NewEdges() 
948 {
949   return myNewEdges;
950 }
951
952
953
954 //=======================================================================
955 //function : Store
956 //purpose  : 
957 //=======================================================================
958
959 void BRepOffset_Inter3d::Store(const TopoDS_Face& F1, 
960                                const TopoDS_Face& F2, 
961                                const TopTools_ListOfShape& LInt1, 
962                                const TopTools_ListOfShape& LInt2)
963 {
964   if (!LInt1.IsEmpty()) {
965     myTouched.Add(F1);
966     myTouched.Add(F2);
967     myAsDes->Add( F1,LInt1);
968     myAsDes->Add( F2,LInt2);
969     TopTools_ListIteratorOfListOfShape it(LInt1);
970     for (; it.More(); it.Next()) {
971       myNewEdges.Add(it.Value());
972     }
973   }
974   SetDone(F1,F2);
975 }
976
977
978