0028577: Get rid of the TopOpeBRep* algorithms in TKOffset toolkit
[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 <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>
35 #include <TopExp.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopoDS.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>
47 //
48 #include <BRepBndLib.hxx>
49 #include <BOPCol_BoxBndTree.hxx>
50 #include <NCollection_UBTreeFiller.hxx>
51 //
52 #include <BOPTools_AlgoTools.hxx>
53
54 //=======================================================================
55 //function : BRepOffset_Inter3d
56 //purpose  : 
57 //=======================================================================
58 BRepOffset_Inter3d::BRepOffset_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes, 
59                                        const TopAbs_State            Side ,
60                                        const Standard_Real           Tol)
61 :myAsDes(AsDes),
62 mySide(Side),
63 myTol(Tol)
64 {
65 }
66
67
68 //=======================================================================
69 //function : ExtentEdge
70 //purpose  : 
71 //=======================================================================
72
73 static void ExtentEdge(const TopoDS_Face& /*F*/,
74                        const TopoDS_Edge& E,
75                        TopoDS_Edge& NE) 
76 {
77   TopoDS_Shape aLocalShape = E.EmptyCopied();
78   NE = TopoDS::Edge(aLocalShape); 
79 //  NE = TopoDS::Edge(E.EmptyCopied()); 
80   
81
82   // Enough for analytic edges, in general case reconstruct the 
83   // geometry of the edge recalculating the intersection of surfaces.  
84
85   NE.Orientation(TopAbs_FORWARD);
86   Standard_Real f,l;
87   BRep_Tool::Range(E,f,l);
88   Standard_Real length = l-f;
89   f -=  100*length;
90   l +=  100*length;
91
92   BRep_Builder B;
93   B.Range(NE,f,l);
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());
100
101 }
102
103 //=======================================================================
104 //function : SelectEdge
105 //purpose  : 
106 //=======================================================================
107 static void SelectEdge (const TopoDS_Shape& theS,
108                         TopTools_ListOfShape& theLE)
109 {
110   Standard_Real aT1, aT2, aDist, aDistMin;
111   TopExp_Explorer aExp;
112   TopTools_ListIteratorOfListOfShape aIt;
113   GeomAPI_ProjectPointOnCurve aProjPC;
114   gp_Pnt aPE1, aPE2;
115   TopoDS_Edge aRE;
116   //
117   aDistMin = RealLast();
118   //
119   aIt.Initialize(theLE);
120   for (; aIt.More(); aIt.Next()) {
121     const TopoDS_Edge& aE = *(TopoDS_Edge*)&aIt.Value();
122     //
123     const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2);
124     //
125     aProjPC.Init(aC, aT1, aT2);
126     aPE1 = aC->Value(aT1);
127     aPE2 = aC->Value(aT2);
128     //
129     aDist = 0.;
130     aExp.Init(theS, TopAbs_VERTEX);
131     for (; aExp.More(); aExp.Next()) {
132       const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExp.Current();
133       const gp_Pnt aP = BRep_Tool::Pnt(aV);
134       //
135       aProjPC.Perform(aP);
136       if (aProjPC.NbPoints()) {
137         aDist += aProjPC.LowerDistance();
138       }
139       else {
140         aDist += Min(aP.Distance(aPE1), aP.Distance(aPE2));
141       }
142     }
143     //
144     if (aDist < aDistMin) {
145       aDistMin = aDist;
146       aRE = aE;
147     }
148   }
149   //
150   theLE.Clear();
151   theLE.Append(aRE);
152 }
153
154 //=======================================================================
155 //function : CompletInt
156 //purpose  : 
157 //=======================================================================
158
159 void BRepOffset_Inter3d::CompletInt(const TopTools_ListOfShape& SetOfFaces,
160                                     const BRepAlgo_Image&     InitOffsetFace)
161 {
162   //---------------------------------------------------------------
163   // Calculate the intersections of offset faces 
164   // Distinction of intersection between faces // tangents.
165   //---------------------------------------------------------------
166
167   // Prepare tools for sorting the bounding boxes
168   BOPCol_BoxBndTree aBBTree;
169   NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
170   //
171   NCollection_IndexedDataMap<TopoDS_Shape, Bnd_Box, TopTools_ShapeMapHasher> aMFaces;
172   // Construct bounding boxes for faces and add them to the tree
173   TopTools_ListIteratorOfListOfShape aItL(SetOfFaces);
174   for (; aItL.More(); aItL.Next()) {
175     const TopoDS_Face& aF = TopoDS::Face(aItL.Value());
176     //
177     // compute bounding box
178     Bnd_Box aBoxF;
179     BRepBndLib::Add(aF, aBoxF);
180     //
181     Standard_Integer i = aMFaces.Add(aF, aBoxF);
182     //
183     aTreeFiller.Add(i, aBoxF);
184   }
185   //
186   // shake tree filler
187   aTreeFiller.Fill();
188   //
189   // get faces with interfering bounding boxes
190   aItL.Initialize(SetOfFaces);
191   for (; aItL.More(); aItL.Next()) {
192     const TopoDS_Face& aF1 = TopoDS::Face(aItL.Value());
193     const Bnd_Box& aBoxF1 = aMFaces.FindFromKey(aF1);
194     //
195     BOPCol_BoxBndTreeSelector aSelector;
196     aSelector.SetBox(aBoxF1);
197     aBBTree.Select(aSelector);
198     //
199     const BOPCol_ListOfInteger& aLI = aSelector.Indices();
200     BOPCol_ListIteratorOfListOfInteger aItLI(aLI);
201     for (; aItLI.More(); aItLI.Next()) {
202       Standard_Integer i = aItLI.Value();
203       const TopoDS_Face& aF2 = TopoDS::Face(aMFaces.FindKey(i));
204       //
205       // intersect faces
206       FaceInter(aF1, aF2, InitOffsetFace);
207     }
208   }
209 }
210
211
212 //=======================================================================
213 //function : FaceInter
214 //purpose  : Performs intersection of the given faces
215 //=======================================================================
216
217 void BRepOffset_Inter3d::FaceInter(const TopoDS_Face& F1,
218                                    const TopoDS_Face& F2,
219                                    const BRepAlgo_Image&     InitOffsetFace)
220 {
221   TopTools_ListOfShape LInt1, LInt2;
222   TopoDS_Edge NullEdge;
223
224   if (F1.IsSame(F2)) return;
225   if (IsDone(F1,F2)) return;
226   const TopoDS_Shape& InitF1 = InitOffsetFace.ImageFrom(F1);
227   const TopoDS_Shape& InitF2 = InitOffsetFace.ImageFrom(F2);
228   Standard_Boolean InterPipes = (InitF2.ShapeType() == TopAbs_EDGE &&
229                                  InitF1.ShapeType() == TopAbs_EDGE );
230   Standard_Boolean InterFaces = (InitF1.ShapeType() == TopAbs_FACE && 
231                                  InitF2.ShapeType() == TopAbs_FACE);
232   TopTools_ListOfShape LE,LV;
233   LInt1.Clear(); LInt2.Clear(); 
234   if (BRepOffset_Tool::FindCommonShapes(F1,F2,LE,LV) ||
235       myAsDes->HasCommonDescendant(F1,F2,LE)) {
236     //-------------------------------------------------
237     // F1 and F2 share shapes.
238     //-------------------------------------------------
239     if ( LE.IsEmpty() && !LV.IsEmpty()) {
240       if (InterPipes) {
241         //----------------------
242         // tubes share a vertex.
243         //----------------------
244         const TopoDS_Edge& EE1 = TopoDS::Edge(InitF1);
245         const TopoDS_Edge& EE2 = TopoDS::Edge(InitF2);
246         TopoDS_Vertex VE1[2],VE2[2];
247         TopExp::Vertices(EE1,VE1[0],VE1[1]);
248         TopExp::Vertices(EE2,VE2[0],VE2[1]);
249         TopoDS_Vertex V;
250         for (Standard_Integer i = 0 ; i < 2; i++) {
251           for (Standard_Integer j = 0 ; j < 2; j++) {
252             if (VE1[i].IsSame(VE2[j])) {
253               V = VE1[i];
254             }
255           }
256         }
257         if (!InitOffsetFace.HasImage(V)) { //no sphere
258           BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide);
259         }                
260       }
261       else {
262         //--------------------------------------------------------
263         // Intersection having only common vertices
264         // and supports having common edges.
265         // UNSUFFICIENT, but a larger criterion shakes too
266         // many sections.
267         //--------------------------------------------------------
268         if (InterFaces) {
269           if (BRepOffset_Tool::FindCommonShapes(TopoDS::Face(InitF1),
270                                                 TopoDS::Face(InitF2),LE,LV)) {
271             if (!LE.IsEmpty()) {
272               BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
273             }
274           }
275           else {
276             BRepOffset_Tool::Inter3D(F1,F2,LInt1,LInt2,mySide,NullEdge);
277           }
278         }
279       }
280     }
281   }
282   else {
283     if (InterPipes) {
284       BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide);
285     }
286     else {
287       BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
288     }
289   }
290   Store (F1,F2,LInt1,LInt2);
291 }
292
293
294 //=======================================================================
295 //function : ConnexIntByArc
296 //purpose  : 
297 //=======================================================================
298
299 void BRepOffset_Inter3d::ConnexIntByArc(const TopTools_ListOfShape& /*SetOfFaces*/, 
300                                         const TopoDS_Shape&         ShapeInit, 
301                                         const BRepOffset_Analyse&   Analyse, 
302                                         const BRepAlgo_Image&       InitOffsetFace)
303 {
304   BRepOffset_Type    OT   = BRepOffset_Concave;
305   if (mySide == TopAbs_OUT) OT   = BRepOffset_Convex;
306   TopExp_Explorer                Exp(ShapeInit,TopAbs_EDGE);
307   TopTools_ListOfShape           LInt1,LInt2;
308   TopoDS_Face                    F1,F2;
309   TopoDS_Edge                    NullEdge;
310
311   //---------------------------------------------------------------------
312   // etape 1 : Intersection of faces // corresponding to the initial faces 
313   //           separated by a concave edge if offset > 0, otherwise convex.
314   //---------------------------------------------------------------------  
315   for (; Exp.More(); Exp.Next()) {
316     const TopoDS_Edge&               E = TopoDS::Edge(Exp.Current());
317     const BRepOffset_ListOfInterval& L = Analyse.Type(E);
318     if (!L.IsEmpty() && L.First().Type() == OT) {
319       //-----------------------------------------------------------
320       // edge is of the proper type , return adjacent faces.
321       //-----------------------------------------------------------
322       const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
323       if (Anc.Extent() == 2) {
324         F1 = TopoDS::Face(InitOffsetFace.Image(Anc.First()).First());
325         F2 = TopoDS::Face(InitOffsetFace.Image(Anc.Last ()).First());
326         if (!IsDone(F1,F2)) {
327           BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,E,Standard_True);
328           Store (F1,F2,LInt1,LInt2);
329         }
330       }          
331     }
332   }
333   //---------------------------------------------------------------------
334   // etape 2 : Intersections of tubes sharing a vertex without sphere with:
335   //           - tubes on each other edge sharing the vertex
336   //           - faces containing an edge connected to vertex that has no tubes.
337   //---------------------------------------------------------------------
338   TopoDS_Vertex                      V[2];
339   TopTools_ListIteratorOfListOfShape it; 
340   
341   for (Exp.Init(ShapeInit,TopAbs_EDGE); Exp.More(); Exp.Next()) {
342     const TopoDS_Edge& E1 = TopoDS::Edge(Exp.Current());
343     if (InitOffsetFace.HasImage(E1)) {
344       //---------------------------
345       // E1 generated a tube.
346       //---------------------------
347       F1 = TopoDS::Face(InitOffsetFace.Image(E1).First());;
348       TopExp::Vertices(E1,V[0],V[1]);
349       const TopTools_ListOfShape& AncE1 = Analyse.Ancestors(E1);
350       
351       for (Standard_Integer i = 0; i < 2; i++) {
352         if (!InitOffsetFace.HasImage(V[i])) {
353           //-----------------------------
354           // the vertex has no sphere.
355           //-----------------------------
356           const TopTools_ListOfShape& Anc     = Analyse.Ancestors(V[i]);
357           TopTools_ListOfShape TangOnV;
358           Analyse.TangentEdges(E1,V[i],TangOnV);
359           TopTools_MapOfShape MTEV;
360           for (it.Initialize(TangOnV); it.More(); it.Next()) {
361             MTEV.Add(it.Value());
362           }
363           for (it.Initialize(Anc); it.More(); it.Next()) {
364             const TopoDS_Edge& E2 = TopoDS::Edge(it.Value());
365 //  Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 Begin
366 //            if (E1.IsSame(E2) || MTEV.Contains(E2)) continue;
367             Standard_Boolean isToSkip = Standard_False;
368
369             if (!E1.IsSame(E2)) {
370               const BRepOffset_ListOfInterval& aL = Analyse.Type(E2);
371
372               isToSkip = (MTEV.Contains(E2) && 
373                           (aL.IsEmpty() ||
374                           (!aL.IsEmpty() && aL.First().Type() != OT)));
375             }
376
377             if (E1.IsSame(E2) || isToSkip)
378               continue;
379 //  Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 End
380             if (InitOffsetFace.HasImage(E2)) {
381               //-----------------------------
382               // E2 generated a tube.
383               //-----------------------------
384               F2 = TopoDS::Face(InitOffsetFace.Image(E2).First());        
385               if (!IsDone(F1,F2)) {
386                 //---------------------------------------------------------------------
387                 // Intersection tube/tube if the edges are not tangent (AFINIR).
388                 //----------------------------------------------------------------------
389                 BRepOffset_Tool::PipeInter (F1,F2,LInt1,LInt2,mySide);
390                 Store (F1,F2,LInt1,LInt2);
391               }
392             }
393             else {
394               //-------------------------------------------------------
395               // Intersection of the tube of E1 with faces //
396               // to face containing E2 if they are not tangent
397               // to the tube or if E2 is not a tangent edge.
398               //-------------------------------------------------------
399               const BRepOffset_ListOfInterval& L = Analyse.Type(E2);
400                if (!L.IsEmpty() && L.First().Type() == BRepOffset_Tangent) {
401                 continue;
402               }
403               const TopTools_ListOfShape& AncE2        = Analyse.Ancestors(E2);
404               Standard_Boolean            TangentFaces = Standard_False;
405               if (AncE2.Extent() == 2) {
406                 TopoDS_Face InitF2 = TopoDS::Face(AncE2.First ());
407                 TangentFaces = (InitF2.IsSame(AncE1.First()) || 
408                                 InitF2.IsSame(AncE1.Last()));
409                 if (!TangentFaces) {
410                   F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First());
411                   if (!IsDone(F1,F2)) {
412                     BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
413                     Store (F1,F2,LInt1,LInt2);
414                   }
415                 }
416                 InitF2 = TopoDS::Face(AncE2.Last ());
417                 TangentFaces = (InitF2.IsSame(AncE1.First()) || 
418                                 InitF2.IsSame(AncE1.Last()));
419                 if (!TangentFaces) {
420                   F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First());
421                   if (!IsDone(F1,F2)) {
422                     BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge);
423                     Store (F1,F2,LInt1,LInt2);
424                   }
425                 }
426               }
427             }
428           }
429         }
430       }
431     }
432   }
433 }
434
435
436 //=======================================================================
437 //function : ConnexIntByInt
438 //purpose  : 
439 //=======================================================================
440
441 void BRepOffset_Inter3d::ConnexIntByInt
442 (const TopoDS_Shape&                    SI,
443  const BRepOffset_DataMapOfShapeOffset& MapSF,
444  const BRepOffset_Analyse&              Analyse,
445  TopTools_DataMapOfShapeShape&          MES,
446  TopTools_DataMapOfShapeShape&          Build,
447  TopTools_ListOfShape&                  Failed,
448  const Standard_Boolean                 bIsPlanar)
449 {
450   //TopExp_Explorer Exp(SI,TopAbs_EDGE);
451   TopTools_IndexedMapOfShape VEmap;
452   TopTools_IndexedDataMapOfShapeListOfShape aMVF;
453   TopoDS_Face     F1,F2,OF1,OF2,NF1,NF2;
454   TopAbs_State    CurSide = mySide;
455   BRep_Builder    B;
456   Standard_Boolean bEdge;
457   Standard_Integer i, aNb;
458   TopTools_ListIteratorOfListOfShape it, it1, itF1, itF2;
459   //
460   TopExp::MapShapes(SI, TopAbs_EDGE  , VEmap);
461   // map the shape for vertices
462   if (bIsPlanar) {
463     TopExp::MapShapes(SI, TopAbs_VERTEX, VEmap);
464     //
465     // make vertex-faces connexity map with unique ancestors
466     TopExp::MapShapesAndUniqueAncestors(SI, TopAbs_VERTEX, TopAbs_FACE, aMVF);
467   }
468   //
469   TopTools_DataMapOfShapeListOfShape aDMVLF1, aDMVLF2, aDMIntFF;
470   TopTools_IndexedDataMapOfShapeListOfShape aDMIntE;
471   //
472   if (bIsPlanar) {
473     aNb = VEmap.Extent();
474     for (i = 1; i <= aNb; ++i) {
475       const TopoDS_Shape& aS = VEmap(i);
476       if (aS.ShapeType() != TopAbs_VERTEX) {
477         continue;
478       }
479       //
480       // faces connected by the vertex
481       const TopTools_ListOfShape& aLF = aMVF.FindFromKey(aS);
482       if (aLF.Extent() < 2) {
483         continue;
484       }
485       // build lists of faces connected to the same vertex by looking for
486       // the pairs in which the vertex is alone (not connected to shared edges)
487       TopTools_ListOfShape aLF1, aLF2;
488       //
489       it.Initialize(aLF);
490       for (; it.More(); it.Next()) {
491         const TopoDS_Shape& aFV1 = it.Value();
492         //
493         // get edges of first face connected to current vertex
494         TopTools_MapOfShape aME;
495         TopExp_Explorer aExp(aFV1, TopAbs_EDGE);
496         for (; aExp.More(); aExp.Next()) {
497           const TopoDS_Shape& aE = aExp.Current();
498           TopoDS_Iterator aItV(aE);
499           for (; aItV.More(); aItV.Next()) {
500             if (aS.IsSame(aItV.Value())) {
501               aME.Add(aE);
502               break;
503             }
504           }
505         }
506         //
507         // get to the next face in the list
508         it1 = it;
509         for (it1.Next(); it1.More(); it1.Next()) {
510           const TopoDS_Shape& aFV2 = it1.Value();
511           //
512           aExp.Init(aFV2, TopAbs_EDGE);
513           for (; aExp.More(); aExp.Next()) {
514             const TopoDS_Shape& aEV2 = aExp.Current();
515             if (aME.Contains(aEV2)) {
516               break;
517             }
518           }
519           //
520           if (!aExp.More()) {
521             // faces share only vertex - make pair for intersection
522             aLF1.Append(aFV1);
523             aLF2.Append(aFV2);
524           }
525         }
526       }
527       //
528       if (aLF1.Extent()) {
529         aDMVLF1.Bind(aS, aLF1);
530         aDMVLF2.Bind(aS, aLF2);
531       }
532     }
533   }
534   //
535   aNb = VEmap.Extent();
536   for (i = 1; i <= aNb; ++i) {
537     const TopoDS_Shape& aS = VEmap(i);
538     //
539     TopoDS_Edge E;
540     TopTools_ListOfShape aLF1, aLF2;
541     //
542     bEdge = (aS.ShapeType() == TopAbs_EDGE);
543     if (bEdge) {
544       // faces connected by the edge
545       E = *(TopoDS_Edge*)&aS;
546       //
547       const BRepOffset_ListOfInterval& L = Analyse.Type(E);
548       if (L.IsEmpty()) {
549         continue;
550       }
551       //
552       BRepOffset_Type    OT   = L.First().Type();
553       if (OT != BRepOffset_Convex && OT != BRepOffset_Concave) {
554         continue;
555       }
556       //
557       if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
558       else                          CurSide = TopAbs_OUT;
559       //-----------------------------------------------------------
560       // edge is of the proper type, return adjacent faces.
561       //-----------------------------------------------------------
562       const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
563       if (Anc.Extent() != 2) {
564         continue;
565       }
566       //
567       F1  = TopoDS::Face(Anc.First());
568       F2  = TopoDS::Face(Anc.Last ());
569       //
570       aLF1.Append(F1);
571       aLF2.Append(F2);
572     }
573     else {
574       if (!aDMVLF1.IsBound(aS)) {
575         continue;
576       }
577       //
578       aLF1 = aDMVLF1.Find(aS);
579       aLF2 = aDMVLF2.Find(aS);
580       //
581       CurSide = mySide;
582     }
583     //
584     itF1.Initialize(aLF1);
585     itF2.Initialize(aLF2);
586     for (; itF1.More() && itF2.More(); itF1.Next(), itF2.Next()) {
587       F1 = TopoDS::Face(itF1.Value());
588       F2 = TopoDS::Face(itF2.Value());
589       //
590       OF1 = TopoDS::Face(MapSF(F1).Face());
591       OF2 = TopoDS::Face(MapSF(F2).Face());
592       if (!MES.IsBound(OF1)) {
593         Standard_Boolean enlargeU = Standard_True;
594         Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
595         BRepOffset_Tool::CheckBounds( F1, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
596         BRepOffset_Tool::EnLargeFace(OF1,NF1,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
597         MES.Bind(OF1,NF1);
598       }
599       else {
600         NF1 = TopoDS::Face(MES(OF1));
601       }
602       //
603       if (!MES.IsBound(OF2)) {
604         Standard_Boolean enlargeU = Standard_True;
605         Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
606         BRepOffset_Tool::CheckBounds( F2, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
607         BRepOffset_Tool::EnLargeFace(OF2,NF2,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
608         MES.Bind(OF2,NF2); 
609       }
610       else {
611         NF2 = TopoDS::Face(MES(OF2));
612       }
613       //
614       if (!IsDone(NF1,NF2)) {
615         TopTools_ListOfShape LInt1,LInt2;
616         BRepOffset_Tool::Inter3D (NF1,NF2,LInt1,LInt2,CurSide,E,bEdge);
617         if (LInt1.Extent() > 1) { 
618           // intersection is in seceral edges (free sewing)
619           SelectEdge(aS, LInt1);
620           SelectEdge(aS, LInt2);
621         }
622         SetDone(NF1,NF2);
623         if (!LInt1.IsEmpty()) {
624           Store (NF1,NF2,LInt1,LInt2);
625           //
626           TopoDS_Compound C;
627           B.MakeCompound(C);
628           //
629           if (Build.IsBound(aS)) {
630             const TopoDS_Shape& aSE = Build(aS);
631             TopExp_Explorer aExp(aSE, TopAbs_EDGE);
632             for (; aExp.More(); aExp.Next()) {
633               const TopoDS_Shape& aNE = aExp.Current();
634               B.Add(C, aNE);
635             }
636           }
637           //
638           it.Initialize(LInt1);
639           for (; it.More(); it.Next()) {
640             const TopoDS_Shape& aNE = it.Value();
641             B.Add(C, aNE);
642             //
643             // keep connection from new edge to shape from which it was created
644             TopTools_ListOfShape *pLS = &aDMIntE(aDMIntE.Add(aNE, TopTools_ListOfShape()));
645             pLS->Append(aS);
646             // keep connection to faces created the edge as well
647             TopTools_ListOfShape* pLFF = aDMIntFF.Bound(aNE, TopTools_ListOfShape());
648             pLFF->Append(F1);
649             pLFF->Append(F2);
650           }
651           //
652           Build.Bind(aS,C);
653         }
654         else {
655           Failed.Append(aS);
656         }
657       } else { // IsDone(NF1,NF2)
658         //  Modified by skv - Fri Dec 26 12:20:13 2003 OCC4455 Begin
659         const TopTools_ListOfShape &aLInt1 = myAsDes->Descendant(NF1);
660         const TopTools_ListOfShape &aLInt2 = myAsDes->Descendant(NF2);
661         
662         if (!aLInt1.IsEmpty()) {
663           TopoDS_Compound C;
664           B.MakeCompound(C);
665           //
666           if (Build.IsBound(aS)) {
667             const TopoDS_Shape& aSE = Build(aS);
668             TopExp_Explorer aExp(aSE, TopAbs_EDGE);
669             for (; aExp.More(); aExp.Next()) {
670               const TopoDS_Shape& aNE = aExp.Current();
671               B.Add(C, aNE);
672             }
673           }
674           //
675           for (it.Initialize(aLInt1) ; it.More(); it.Next()) {
676             const TopoDS_Shape &anE1 = it.Value();
677             //
678             for (it1.Initialize(aLInt2) ; it1.More(); it1.Next()) {
679               const TopoDS_Shape &anE2 = it1.Value();
680               if (anE1.IsSame(anE2)) {
681                 B.Add(C, anE1);
682                 //
683                 TopTools_ListOfShape *pLS = aDMIntE.ChangeSeek(anE1);
684                 if (pLS) {
685                   pLS->Append(aS);
686                 }
687               }
688             }
689           }
690           Build.Bind(aS,C);
691         }
692         else {
693           Failed.Append(aS);
694         }
695       }
696     }
697     //  Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End
698   }
699   //
700   // create unique intersection for each localized shared part
701   aNb = aDMIntE.Extent();
702   for (i = 1; i <= aNb; ++i) {
703     const TopTools_ListOfShape& aLS = aDMIntE(i);
704     if (aLS.Extent() < 2) {
705       continue;
706     }
707     //
708     // intersection edge
709     const TopoDS_Edge& aE = TopoDS::Edge(aDMIntE.FindKey(i));
710     // faces created the edge
711     const TopTools_ListOfShape& aLFF = aDMIntFF.Find(aE);
712     const TopoDS_Shape& aF1 = aLFF.First();
713     const TopoDS_Shape& aF2 = aLFF.Last();
714
715     // Build really localized blocks from the original shapes in <aLS>:
716     // 1. Find edges from original faces connected to two or more shapes in <aLS>;
717     // 2. Make connexity blocks from edges in <aLS> and found connection edges;
718     // 3. Check if the vertices from <aLS> are not connected by these connection edges:
719     //    a. If so - add these vertices to Connexity Block containing the corresponding
720     //       connexity edge;
721     //    b. If not - add this vertex to list of connexity blocks
722     // 4. Create unique intersection edge for each connexity block
723
724     // list of vertices
725     TopTools_ListOfShape aLV;
726     // compound of edges to build connexity blocks
727     TopoDS_Compound aCE;
728     B.MakeCompound(aCE);
729     TopTools_MapOfShape aMS;
730     TopTools_ListIteratorOfListOfShape aItLS(aLS);
731     for (; aItLS.More(); aItLS.Next()) {
732       const TopoDS_Shape& aS = aItLS.Value();
733       aMS.Add(aS);
734       if (aS.ShapeType() == TopAbs_EDGE) {
735         B.Add(aCE, aS);
736       }
737       else {
738         aLV.Append(aS);
739       }
740     }
741     //
742     // look for additional edges to connect the shared parts
743     TopTools_MapOfShape aMEConnection;
744     for (Standard_Integer j = 0; j < 2; ++j) {
745       const TopoDS_Shape& aF = !j ? aF1 : aF2;
746       //
747       TopExp_Explorer aExp(aF, TopAbs_EDGE);
748       for (; aExp.More(); aExp.Next()) {
749         const TopoDS_Shape& aEF = aExp.Current();
750         if (aMS.Contains(aEF) || aMEConnection.Contains(aEF)) {
751           continue;
752         }
753         //
754         TopoDS_Vertex aV1, aV2;
755         TopExp::Vertices(TopoDS::Edge(aEF), aV1, aV2);
756         //
757         // find parts to which the edge is connected
758         Standard_Integer iCounter = 0;
759         aItLS.Initialize(aLS);
760         for (; aItLS.More(); aItLS.Next()) {
761           const TopoDS_Shape& aS = aItLS.Value();
762           // iterator is not suitable here, because aS may be a vertex
763           TopExp_Explorer aExpV(aS, TopAbs_VERTEX);
764           for (; aExpV.More(); aExpV.Next()) {
765             const TopoDS_Shape& aV = aExpV.Current();
766             if (aV.IsSame(aV1) || aV.IsSame(aV2)) {
767               ++iCounter;
768               break;
769             }
770           }
771         }
772         //
773         if (iCounter >= 2) {
774           B.Add(aCE, aEF);
775           aMEConnection.Add(aEF);
776         }
777       }
778     }
779     //
780     TopTools_ListOfShape aLCBE;
781     BOPTools_AlgoTools::MakeConnexityBlocks(aCE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
782     //
783     // create connexity blocks for alone vertices
784     TopTools_ListOfShape aLCBV;
785     TopTools_ListIteratorOfListOfShape aItLV(aLV);
786     for (; aItLV.More(); aItLV.Next()) {
787       const TopoDS_Shape& aV = aItLV.Value();
788       // check if this vertex is contained in some connexity block of edges
789       TopTools_ListIteratorOfListOfShape aItLCB(aLCBE);
790       for (; aItLCB.More(); aItLCB.Next()) {
791         TopoDS_Shape& aCB = aItLCB.ChangeValue();
792         TopExp_Explorer aExpV(aCB, TopAbs_VERTEX);
793         for (; aExpV.More(); aExpV.Next()) {
794           if (aV.IsSame(aExpV.Current())) {
795             B.Add(aCB, aV);
796             break;
797           }
798         }
799         if (aExpV.More()) {
800           break;
801         }
802       }
803       //
804       if (!aItLCB.More()) {
805         TopoDS_Compound aCV;
806         B.MakeCompound(aCV);
807         B.Add(aCV, aV);
808         aLCBV.Append(aCV);
809       }
810     }
811     //
812     aLCBE.Append(aLCBV);
813     //
814     if (aLCBE.Extent() == 1) {
815       continue;
816     }
817     //
818     const TopoDS_Shape& aNF1 = MES(MapSF(aF1).Face());
819     const TopoDS_Shape& aNF2 = MES(MapSF(aF2).Face());
820     //
821     TopTools_ListIteratorOfListOfShape aItLCB(aLCBE);
822     for (aItLCB.Next(); aItLCB.More(); aItLCB.Next()) {
823       // make new edge with different tedge instance
824       TopoDS_Edge aNewEdge;
825       TopoDS_Vertex aV1, aV2;
826       Standard_Real aT1, aT2;
827       //
828       TopExp::Vertices(aE, aV1, aV2);
829       BRep_Tool::Range(aE, aT1, aT2);
830       //
831       BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aNewEdge);
832       //
833       myAsDes->Add(aNF1, aNewEdge);
834       myAsDes->Add(aNF2, aNewEdge);
835       //
836       const TopoDS_Shape& aCB = aItLCB.Value();
837       TopoDS_Iterator aItCB(aCB);
838       for (; aItCB.More(); aItCB.Next()) {
839         const TopoDS_Shape& aS = aItCB.Value();
840         if (aMEConnection.Contains(aS)) {
841           continue;
842         }
843         TopoDS_Shape& aCI = Build.ChangeFind(aS);
844         //
845         TopoDS_Compound aNewCI;
846         B.MakeCompound(aNewCI);
847         TopExp_Explorer aExp(aCI, TopAbs_EDGE);
848         for (; aExp.More(); aExp.Next()) {
849           const TopoDS_Shape& aSx = aExp.Current();
850           if (!aSx.IsSame(aE)) {
851             B.Add(aNewCI, aSx);
852           }
853         }
854         B.Add(aNewCI, aNewEdge);
855         aCI = aNewCI;
856       }
857     }
858   }
859 }
860
861 //=======================================================================
862 //function : ContextIntByInt
863 //purpose  : 
864 //=======================================================================
865
866 void BRepOffset_Inter3d::ContextIntByInt
867 (const TopTools_IndexedMapOfShape&      ContextFaces, 
868  const Standard_Boolean                 ExtentContext,
869  const BRepOffset_DataMapOfShapeOffset& MapSF,
870  const BRepOffset_Analyse&              Analyse,
871  TopTools_DataMapOfShapeShape&          MES,
872  TopTools_DataMapOfShapeShape&          Build,
873  TopTools_ListOfShape&                  Failed,
874  const Standard_Boolean                 bIsPlanar)
875 {
876   TopTools_MapOfShape              MV;
877   TopExp_Explorer                  exp;
878   TopoDS_Face                      OF,NF,WCF;
879   TopoDS_Edge                      OE;
880   TopoDS_Compound                  C;
881   BRep_Builder                     B;
882   TopTools_ListIteratorOfListOfShape it, itF;
883   Standard_Integer i, j, aNb, aNbVE;
884   Standard_Boolean bEdge;
885
886   aNb = ContextFaces.Extent();
887   for (i = 1; i <= aNb; i++) {
888     const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i));
889     myTouched.Add(CF);
890     if (ExtentContext) {
891       BRepOffset_Tool::EnLargeFace(CF,NF,0,0);
892       MES.Bind(CF,NF);
893     }
894   }
895   TopAbs_State Side = TopAbs_OUT;
896  
897   for (i = 1; i <= aNb; i++) {
898     const TopoDS_Face& CF  = TopoDS::Face(ContextFaces(i));
899     if (ExtentContext) WCF = TopoDS::Face(MES(CF));
900     else               WCF = CF;
901
902     TopTools_IndexedMapOfShape VEmap;
903     TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
904     //
905     if (bIsPlanar) {
906       TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
907     }
908     //
909     aNbVE = VEmap.Extent();
910     for (j = 1; j <= aNbVE; ++j) {
911       const TopoDS_Shape& aS = VEmap(j);
912       //
913       bEdge = (aS.ShapeType() == TopAbs_EDGE);
914       //
915       TopoDS_Edge E;
916       TopTools_ListOfShape Anc;
917       //
918       if (bEdge) {
919         // faces connected by the edge
920         //
921         E = *(TopoDS_Edge*)&aS;
922         if (!Analyse.HasAncestor(E)) {
923           //----------------------------------------------------------------
924           // the edges of faces of context that are not in the initial shape
925           // can appear in the result.
926           //----------------------------------------------------------------
927           if (!ExtentContext) {
928             myAsDes->Add(CF,E);
929             myNewEdges.Add(E);
930           }
931           else {
932             if (!MES.IsBound(E)) {
933               TopoDS_Edge NE;
934               Standard_Real f,l,Tol;
935               BRep_Tool::Range(E,f,l);
936               Tol = BRep_Tool::Tolerance(E);
937               ExtentEdge(CF,E,NE);
938               TopoDS_Vertex V1,V2;
939               TopExp::Vertices(E,V1,V2);
940               NE.Orientation(TopAbs_FORWARD);
941               myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
942               myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
943               TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
944               B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
945               aLocalShape = V2.Oriented(TopAbs_INTERNAL);
946               B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
947 //            B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
948 //            B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
949               NE.Orientation(E.Orientation());
950               myAsDes->Add(CF,NE);
951               myNewEdges.Add(NE);
952               MES.Bind(E,NE);
953             }
954             else {
955               TopoDS_Shape NE = MES(E);
956               TopoDS_Shape aLocalShape = NE.Oriented(E.Orientation());
957               myAsDes->Add(CF,aLocalShape);
958 //            myAsDes->Add(CF,NE.Oriented(E.Orientation()));
959             }
960           }
961           continue;
962         } 
963         Anc = Analyse.Ancestors(E);
964       }
965       else {
966         // faces connected by the vertex
967         //
968         if (!Analyse.HasAncestor(aS)) {
969           continue;
970         }
971         //
972         const TopTools_ListOfShape& aLE = Analyse.Ancestors(aS);
973         it.Initialize(aLE);
974         for (; it.More(); it.Next()) {
975           const TopoDS_Edge& aE = *(TopoDS_Edge*)&it.Value();
976           //
977           if (BRep_Tool::Degenerated(aE)) {
978             continue;
979           }
980           //
981           if (VEmap.Contains(aE)) {
982             continue;
983           }
984           //
985           const TopTools_ListOfShape& aLF = Analyse.Ancestors(aE);
986           itF.Initialize(aLF);
987           for (; itF.More(); itF.Next()) {
988             const TopoDS_Shape& aF = itF.Value();
989             Standard_Boolean bAdd = Standard_True;
990             exp.Init(aF, TopAbs_EDGE);
991             for (; exp.More() && bAdd; exp.Next()) {
992               const TopoDS_Shape& aEF = exp.Current();
993               bAdd = !VEmap.Contains(aEF);
994             }
995             if (bAdd) {
996               Anc.Append(aF);
997             }
998           }
999         }
1000       }
1001       //
1002       itF.Initialize(Anc);
1003       for (; itF.More(); itF.Next()) {
1004         const TopoDS_Face& F = TopoDS::Face(itF.Value());
1005         OF = TopoDS::Face(MapSF(F).Face());
1006         TopoDS_Shape aLocalShape = MapSF(F).Generated(E);
1007         OE = TopoDS::Edge(aLocalShape);
1008 //      OE = TopoDS::Edge(MapSF(F).Generated(E));
1009         if (!MES.IsBound(OF)) {
1010           BRepOffset_Tool::EnLargeFace(OF,NF,1,1);
1011           MES.Bind(OF,NF);
1012         }
1013         else {
1014           NF = TopoDS::Face(MES(OF));
1015         }
1016         if (!IsDone(NF,CF)) {
1017           TopTools_ListOfShape LInt1,LInt2;
1018           TopTools_ListOfShape LOE;
1019           LOE.Append(OE);
1020           BRepOffset_Tool::Inter3D (WCF,NF,LInt1,LInt2,Side,E,bEdge);
1021           SetDone(NF,CF);
1022           if (!LInt1.IsEmpty()) {
1023             Store (CF,NF,LInt1,LInt2);
1024             if ((LInt1.Extent() == 1) && !Build.IsBound(aS)) {
1025               Build.Bind(aS,LInt1.First());
1026             }
1027             else {
1028               B.MakeCompound(C);
1029               if (Build.IsBound(aS)) {
1030                 const TopoDS_Shape& aSE = Build(aS);
1031                 exp.Init(aSE, TopAbs_EDGE);
1032                 for (; exp.More(); exp.Next()) {
1033                   const TopoDS_Shape& aNE = exp.Current();
1034                   B.Add(C, aNE);
1035                 }
1036               }
1037               //
1038               for (it.Initialize(LInt1) ; it.More(); it.Next()) {
1039                 B.Add(C,it.Value());
1040               }
1041               Build.Bind(aS,C);
1042             }
1043           }
1044           else {
1045             Failed.Append(aS);
1046           }
1047         }
1048       }
1049     }
1050   }
1051 }
1052
1053 //=======================================================================
1054 //function : ContextIntByArc
1055 //purpose  : 
1056 //=======================================================================
1057
1058 void BRepOffset_Inter3d::ContextIntByArc(const TopTools_IndexedMapOfShape& ContextFaces, 
1059                                          const Standard_Boolean            InSide,
1060                                          const BRepOffset_Analyse&         Analyse, 
1061                                          const BRepAlgo_Image&             InitOffsetFace, 
1062                                                BRepAlgo_Image&             InitOffsetEdge)
1063
1064
1065   TopTools_ListOfShape                      LInt1,LInt2;
1066   TopTools_MapOfShape                       MV;
1067   TopExp_Explorer                           exp;
1068   TopoDS_Face                               OF1,OF2;
1069   TopoDS_Edge                               OE;
1070   BRep_Builder                              B;  
1071   TopoDS_Edge                               NullEdge;
1072   Standard_Integer j;
1073
1074   for (j = 1; j <= ContextFaces.Extent(); j++) {
1075     const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
1076     myTouched.Add(CF);
1077   }
1078
1079   for (j = 1; j <= ContextFaces.Extent(); j++) {
1080     const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j));
1081     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1082          exp.More(); exp.Next()) {
1083       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1084       if (!Analyse.HasAncestor(E)) {
1085         if (InSide)
1086           myAsDes->Add(CF,E);
1087         else {
1088           TopoDS_Edge NE;
1089           if (!InitOffsetEdge.HasImage(E)) {
1090             Standard_Real f,l,Tol;
1091             BRep_Tool::Range(E,f,l);
1092             Tol = BRep_Tool::Tolerance(E);
1093             ExtentEdge(CF,E,NE);
1094             TopoDS_Vertex V1,V2;
1095             TopExp::Vertices(E,V1,V2);
1096             NE.Orientation(TopAbs_FORWARD);
1097             myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
1098             myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
1099             TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
1100             B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
1101             aLocalShape = V2.Oriented(TopAbs_INTERNAL);
1102             B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
1103 //            B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
1104 //            B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
1105             NE.Orientation(E.Orientation());
1106             myAsDes->Add(CF,NE);
1107             InitOffsetEdge.Bind(E,NE);
1108           }
1109           else {
1110             NE = TopoDS::Edge(InitOffsetEdge.Image(E).First());
1111             myAsDes->Add(CF,NE.Oriented(E.Orientation()));
1112           }
1113         }
1114         continue;
1115       }
1116       OE.Nullify();
1117       //---------------------------------------------------
1118       // OF1 parallel facee generated by the ancestor of E.
1119       //---------------------------------------------------
1120       const TopoDS_Shape SI = Analyse.Ancestors(E).First();
1121       OF1 = TopoDS::Face(InitOffsetFace.Image(SI).First());
1122       OE  = TopoDS::Edge(InitOffsetEdge.Image(E).First());     
1123
1124       {
1125         //Check if OE has pcurve in CF
1126
1127         Standard_Real   f,l;
1128
1129         Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l);
1130         Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l); 
1131
1132         if(C1.IsNull() || C2.IsNull())
1133         {
1134           continue;
1135         }
1136       }
1137
1138       //--------------------------------------------------
1139       // MAJ of OE on cap CF.
1140       //--------------------------------------------------
1141 //      TopTools_ListOfShape LOE; LOE.Append(OE);              
1142 //      BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
1143 //      LInt2.Clear();
1144 //      StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
1145 //                   LInt1,LInt2);
1146       LInt1.Clear(); LInt1.Append(OE);
1147       LInt2.Clear();    
1148       TopAbs_Orientation anOri1, anOri2;
1149       BRepOffset_Tool::OrientSection(OE,CF,OF1, anOri1,anOri2);
1150 //    if (mySide == TopAbs_OUT);
1151       anOri1 = TopAbs::Reverse(anOri1);
1152       LInt1.First().Orientation(anOri1);
1153       Store(CF,OF1,LInt1,LInt2);
1154       
1155       //------------------------------------------------------
1156       // Processing of offsets on the ancestors of vertices.
1157       //------------------------------------------------------
1158       TopoDS_Vertex V[2];
1159       TopExp::Vertices (E,V[0],V[1]);
1160       for (Standard_Integer i = 0; i < 2; i++) {
1161         if (!MV.Add(V[i])) continue;
1162         OF1.Nullify(); 
1163         const TopTools_ListOfShape& LE =  Analyse.Ancestors(V[i]);
1164         TopTools_ListIteratorOfListOfShape itLE(LE);
1165         for ( ; itLE.More(); itLE.Next()) {
1166           const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
1167           if (InitOffsetFace.HasImage(EV)) {
1168             //-------------------------------------------------
1169             // OF1 parallel face generated by an ancester edge of V[i].
1170             //-------------------------------------------------
1171             OF1 = TopoDS::Face(InitOffsetFace.Image(EV).First());
1172             OE  = TopoDS::Edge(InitOffsetEdge.Image(V[i]).First());
1173
1174       {
1175         //Check if OE has pcurve in CF and OF1
1176
1177         Standard_Real   f,l;
1178
1179         Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l);
1180         Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l); 
1181
1182         if(C1.IsNull() || C2.IsNull())
1183         {
1184           continue;
1185         }
1186       }
1187
1188             //--------------------------------------------------
1189             // MAj of OE on cap CF.
1190             //--------------------------------------------------
1191             //              LOE.Clear(); LOE.Append(OE);
1192             //              BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide);
1193             //              LInt2.Clear();
1194             //              StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes,
1195             //                           LInt1,LInt2);
1196             LInt1.Clear(); LInt1.Append(OE);
1197             LInt2.Clear();    
1198             TopAbs_Orientation O1,O2;
1199             BRepOffset_Tool::OrientSection(OE,CF,OF1,O1,O2);      
1200 //            if (mySide == TopAbs_OUT);
1201             O1 = TopAbs::Reverse(O1);
1202             LInt1.First().Orientation(O1);
1203             Store(CF,OF1,LInt1,LInt2);
1204           }
1205         }
1206       }
1207     }
1208     
1209     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_VERTEX); 
1210          exp.More(); exp.Next()) {
1211       const TopoDS_Vertex&        V  = TopoDS::Vertex(exp.Current());
1212       if (!Analyse.HasAncestor(V)) {
1213         continue;
1214       }
1215       const TopTools_ListOfShape& LE =  Analyse.Ancestors(V);
1216       TopTools_ListIteratorOfListOfShape itLE(LE);
1217       for (; itLE.More(); itLE.Next()) {
1218         const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value());
1219         const TopTools_ListOfShape& LF = Analyse.Ancestors(EV);
1220         TopTools_ListIteratorOfListOfShape itLF(LF);
1221         for ( ; itLF.More(); itLF.Next()) {
1222           const TopoDS_Face& FEV = TopoDS::Face(itLF.Value());
1223           //-------------------------------------------------
1224           // OF1 parallel face generated by uneFace ancestor of V[i].
1225           //-------------------------------------------------
1226           OF1 = TopoDS::Face(InitOffsetFace.Image(FEV).First());
1227           if (!IsDone(OF1,CF)) {
1228             //-------------------------------------------------------
1229             // Find if one of edges of OF1 has no trace in CF.
1230             //-------------------------------------------------------
1231             TopTools_ListOfShape LOE;
1232             TopExp_Explorer exp2(OF1.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1233             for ( ;exp2.More(); exp2.Next()) {
1234               LOE.Append(exp2.Current());
1235             }
1236             BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide,myTol);
1237             //-------------------------------------------------------
1238             // If no trace try intersection.
1239             //-------------------------------------------------------
1240             if (LInt1.IsEmpty()) {
1241               BRepOffset_Tool::Inter3D (CF,OF1,LInt1,LInt2,mySide,NullEdge);
1242             }
1243             Store (CF,OF1,LInt1,LInt2);
1244           }
1245         }
1246       }
1247     } 
1248   }
1249 }
1250
1251 //=======================================================================
1252 //function : AddCommonEdges
1253 //purpose  : 
1254 //=======================================================================
1255
1256 void BRepOffset_Inter3d::AddCommonEdges(const TopTools_ListOfShape&)
1257 {
1258 }
1259
1260
1261 //=======================================================================
1262 //function : SetDone
1263 //purpose  : 
1264 //=======================================================================
1265
1266 void BRepOffset_Inter3d::SetDone(const TopoDS_Face& F1, 
1267                                  const TopoDS_Face& F2)
1268 {
1269   if (!myDone.IsBound(F1)) {
1270     TopTools_ListOfShape empty;
1271     myDone.Bind(F1,empty);
1272   }
1273   myDone(F1).Append(F2);
1274   if (!myDone.IsBound(F2)) {
1275     TopTools_ListOfShape empty;
1276     myDone.Bind(F2,empty);
1277   }
1278   myDone(F2).Append(F1);
1279 }
1280
1281
1282 //=======================================================================
1283 //function : IsDone
1284 //purpose  : 
1285 //=======================================================================
1286
1287 Standard_Boolean BRepOffset_Inter3d::IsDone(const TopoDS_Face& F1, 
1288                                             const TopoDS_Face& F2) 
1289 const 
1290 {
1291   if (myDone.IsBound(F1)) {
1292     TopTools_ListIteratorOfListOfShape it (myDone(F1));
1293     for (; it.More(); it.Next()) {
1294       if (it.Value().IsSame(F2)) return Standard_True;
1295     }
1296   }
1297   return Standard_False;
1298 }
1299
1300
1301 //=======================================================================
1302 //function : TouchedFaces
1303 //purpose  : 
1304 //=======================================================================
1305
1306 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::TouchedFaces()
1307 {
1308   return myTouched;
1309 }
1310
1311
1312 //=======================================================================
1313 //function : AsDes
1314 //purpose  : 
1315 //=======================================================================
1316
1317 Handle(BRepAlgo_AsDes) BRepOffset_Inter3d::AsDes() const 
1318 {
1319   return myAsDes;
1320 }
1321
1322
1323 //=======================================================================
1324 //function : NewEdges
1325 //purpose  : 
1326 //=======================================================================
1327
1328 TopTools_IndexedMapOfShape& BRepOffset_Inter3d::NewEdges() 
1329 {
1330   return myNewEdges;
1331 }
1332
1333
1334
1335 //=======================================================================
1336 //function : Store
1337 //purpose  : 
1338 //=======================================================================
1339
1340 void BRepOffset_Inter3d::Store(const TopoDS_Face& F1, 
1341                                const TopoDS_Face& F2, 
1342                                const TopTools_ListOfShape& LInt1, 
1343                                const TopTools_ListOfShape& LInt2)
1344 {
1345   if (!LInt1.IsEmpty()) {
1346     myTouched.Add(F1);
1347     myTouched.Add(F2);
1348     myAsDes->Add( F1,LInt1);
1349     myAsDes->Add( F2,LInt2);
1350     TopTools_ListIteratorOfListOfShape it(LInt1);
1351     for (; it.More(); it.Next()) {
1352       myNewEdges.Add(it.Value());
1353     }
1354   }
1355   SetDone(F1,F2);
1356 }