0022823: Exception in thickshell operation
[occt.git] / src / BRepOffset / BRepOffset_MakeOffset.cxx
1 // File:        BRepOffset_MakeOffset.cxx
2 // Created:     Fri Oct 27 10:30:44 1995
3 // Author:      Yves FRICAUD
4 //              <yfr@stylox>
5
6
7 //  Modified by skv - Tue Mar 15 16:20:43 2005
8 // Add methods for supporting history.
9
10 //  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455
11
12 #include <BRepOffset_MakeOffset.ixx>
13 #include <BRepOffset_Analyse.hxx>
14 #include <BRepOffset_DataMapOfShapeOffset.hxx> 
15 #include <BRepOffset_DataMapOfShapeMapOfShape.hxx>
16 #include <BRepOffset_DataMapIteratorOfDataMapOfShapeOffset.hxx>
17 #include <BRepOffset_Interval.hxx>
18 #include <BRepOffset_ListOfInterval.hxx>
19 #include <BRepOffset_Offset.hxx>
20 #include <BRepOffset_Tool.hxx>
21 #include <BRepOffset_Inter2d.hxx>
22 #include <BRepOffset_Inter3d.hxx>
23 #include <BRepOffset_MakeLoops.hxx>
24
25
26 #include <BRepAdaptor_Surface.hxx>
27 #include <BRepCheck_Edge.hxx>
28 #include <BRepCheck_Vertex.hxx>
29 #include <BRepLib.hxx>
30 #include <BRepLib_MakeVertex.hxx>
31 #include <BRep_Builder.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRep_TVertex.hxx>
34 #include <BRepTools_Quilt.hxx>
35 #include <BRepClass3d_SolidClassifier.hxx>
36 #include <gp_Pnt.hxx>
37
38 #include <TopExp.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Solid.hxx>
42 #include <TopoDS_Shell.hxx>
43 #include <TopoDS_Compound.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Vertex.hxx>
47
48 #include <TopTools_MapOfShape.hxx>
49 #include <TopTools_MapIteratorOfMapOfShape.hxx>
50 #include <TopTools_ListOfShape.hxx>
51 #include <TopTools_ListIteratorOfListOfShape.hxx>
52 #include <TopTools_DataMapOfShapeShape.hxx>
53 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
54 #include <TopTools_DataMapIteratorOfDataMapOfShapeReal.hxx>
55 #include <TColStd_ListIteratorOfListOfInteger.hxx>
56
57 #include <Standard_NotImplemented.hxx>
58 #include <Standard_ConstructionError.hxx>
59 #include <Precision.hxx>
60
61 #include <TopTools_SequenceOfShape.hxx>
62 #include <Geom_OffsetSurface.hxx>
63 #include <Geom_ConicalSurface.hxx>
64 #include <TopTools_IndexedMapOfShape.hxx>
65 #include <BRep_TEdge.hxx>
66 #include <BRepTools.hxx>
67 #include <gp_Cone.hxx>
68 #include <ElSLib.hxx>
69 #include <ElCLib.hxx>
70 #include <gp_Lin2d.hxx>
71 #include <GCE2d_MakeLine.hxx>
72 #include <Geom2d_Line.hxx>
73 #include <TopoDS_Iterator.hxx>
74 #include <BRepLib_MakeFace.hxx>
75 #include <Geom_Circle.hxx>
76
77 #include <BRep_PointRepresentation.hxx>
78 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
79 #include <GeomAPI_ProjectPointOnCurve.hxx>
80
81 #include <BRepAdaptor_Curve.hxx>
82 #include <BRepAdaptor_Curve2d.hxx>
83 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
84 #include <Geom_SphericalSurface.hxx>
85 #include <TopoDS_Wire.hxx>
86 #include <BRepTools_Substitution.hxx>
87 #include <Geom_TrimmedCurve.hxx>
88 #include <Geom2d_TrimmedCurve.hxx>
89
90 #include <BRepTools_WireExplorer.hxx>
91 #include <BRepLib_MakeEdge.hxx>
92 #include <gce_MakeDir.hxx>
93 #include <GC_MakeCylindricalSurface.hxx>
94 #include <gce_MakeCone.hxx>
95 #include <Geom_SurfaceOfLinearExtrusion.hxx>
96
97 #include <Geom2dAdaptor_HCurve.hxx>
98 #include <GeomAdaptor_HSurface.hxx>
99 #include <Adaptor3d_CurveOnSurface.hxx>
100 #include <GeomLib.hxx>
101 #include <GeomFill_Generator.hxx>
102
103
104 // POP for NT
105 #include <stdio.h>
106
107 #ifdef DRAW
108
109 #include <DBRep.hxx>
110 #endif
111 #ifdef DEB
112 #include <OSD_Chronometer.hxx>
113
114   Standard_Boolean AffichInt2d = Standard_False;       
115   Standard_Boolean AffichOffC  = Standard_False;       
116   Standard_Boolean ChronBuild  = Standard_False;
117   Standard_Integer NbAE        = 0;
118   Standard_Integer NbAF        = 0;  
119   static OSD_Chronometer  Clock;
120   char name[100];
121
122
123
124
125 //=======================================================================
126 //function :  DEBVerticesControl
127 //purpose  : 
128 //=======================================================================
129
130 static void DEBVerticesControl (const TopTools_MapOfShape&    NewEdges,
131                                       Handle(BRepAlgo_AsDes)  AsDes)
132 {
133   Standard_Integer NVP = 0;
134   Standard_Integer NVM = 0;
135   Standard_Integer NVN = 0;
136
137   TopTools_ListOfShape               LVP;
138   TopTools_MapIteratorOfMapOfShape   it;
139   TopTools_ListIteratorOfListOfShape it1LE ;    
140   TopTools_ListIteratorOfListOfShape it2LE ;
141   
142   for (it.Initialize(NewEdges) ; it.More(); it.Next()) {
143     const TopoDS_Edge& NE = TopoDS::Edge(it.Key());
144     if (AsDes->HasDescendant(NE)) {
145       for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) {
146         if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
147           LVP.Append(it1LE.Value());
148           cout <<"Vertex on at least 3 edges."<<endl;
149 #ifdef DRAW
150           if (AffichInt2d) {
151             sprintf (name,"VP_%d",NVP++);
152             DBRep::Set(name,it1LE.Value());
153           }
154 #endif
155         }
156         else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
157           cout <<"Vertex on more than 3 edges."<<endl;
158 #ifdef DRAW
159           if (AffichInt2d) {
160             sprintf (name,"VM_%d",NVM++);
161             DBRep::Set(name,it1LE.Value());
162           }
163 #endif
164           
165         }
166         else {
167 #ifdef DRAW
168           if (AffichInt2d) {
169             sprintf (name,"VN_%d",NVN++);
170             DBRep::Set(name,it1LE.Value());
171           }
172 #endif
173         }
174       }
175     }
176   }
177   //------------------------------------------------
178   // Try to mix spoiled vertices.
179   //------------------------------------------------
180   BRep_Builder B;
181   TopTools_ListIteratorOfListOfShape it1(LVP);
182   Standard_Real                      TolConf = 1.e-5;
183   Standard_Real                      Tol     = Precision::Confusion();
184   Standard_Integer                   i = 1;
185
186   for ( ; it1.More(); it1.Next()) {
187     TopoDS_Shape   V1 = it1.Value();
188     gp_Pnt         P1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
189     Standard_Real  distmin = Precision::Infinite();
190     TopTools_ListIteratorOfListOfShape it2(LVP);
191     Standard_Integer j = 1;
192
193     for ( ; it2.More(); it2.Next()) {
194       if (j > i) {
195         TopoDS_Shape V2 = it2.Value();
196         gp_Pnt       P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
197         if (!V1.IsSame(V2)) {
198           Standard_Real       dist    = P1.Distance(P2);
199           if (dist < distmin) distmin = dist;
200           if (dist < TolConf) {
201             Standard_Real UV2;
202             TopoDS_Edge   EWE2;
203             const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
204             TopTools_ListIteratorOfListOfShape itAsDes;
205             for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
206               EWE2  = TopoDS::Edge(itAsDes.Value());
207               TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
208               UV2   = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
209               aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
210               B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
211 //            UV2   = 
212 //              BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
213 //            B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
214 //                           UV2,EWE2,Tol);
215             }
216             AsDes->Replace(V2,V1);
217           }
218         }
219       }
220       j++;
221     }
222     i++;
223     cout <<" distmin between VP : "<<distmin<<endl;
224   }
225 }  
226 #endif
227
228
229 static void UpdateTolerance (      TopoDS_Shape&        myShape,
230                              const TopTools_MapOfShape& myFaces);
231
232
233 static Standard_Boolean FindParameter(const TopoDS_Vertex& V, 
234                                       const TopoDS_Edge& E,
235                                       Standard_Real& U)
236 {
237   // Search the vertex in the edge
238
239   Standard_Boolean rev = Standard_False;
240   TopoDS_Shape VF;
241   TopAbs_Orientation orient = TopAbs_INTERNAL;
242
243   TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
244
245   // if the edge has no vertices
246   // and is degenerated use the vertex orientation
247   // RLE, june 94
248
249   if (!itv.More() && BRep_Tool::Degenerated(E)) {
250     orient = V.Orientation();
251   }
252
253   while (itv.More()) {
254     const TopoDS_Shape& Vcur = itv.Value();
255     if (V.IsSame(Vcur)) {
256       if (VF.IsNull()) {
257         VF = Vcur;
258       }
259       else {
260         rev = E.Orientation() == TopAbs_REVERSED;
261         if (Vcur.Orientation() == V.Orientation()) {
262           VF = Vcur;
263         }
264       }
265     }
266     itv.Next();
267   }
268   
269   if (!VF.IsNull()) orient = VF.Orientation();
270  
271   Standard_Real f,l;
272
273   if (orient ==  TopAbs_FORWARD) {
274     BRep_Tool::Range(E,f,l);
275     //return (rev) ? l : f;
276     U = (rev) ? l : f;
277     return Standard_True;
278   }
279  
280   else if (orient ==  TopAbs_REVERSED) {
281     BRep_Tool::Range(E,f,l);
282     //return (rev) ? f : l;
283     U = (rev) ? f : l;
284     return Standard_True;
285    }
286
287   else {
288     TopLoc_Location L;
289     const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
290     L = L.Predivided(V.Location());
291     if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
292       BRep_ListIteratorOfListOfPointRepresentation itpr
293         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
294
295       while (itpr.More()) {
296         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
297         if (pr->IsPointOnCurve(C,L)) {
298           Standard_Real p = pr->Parameter();
299           Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
300           if (!C.IsNull()) {
301             // Closed curves RLE 16 june 94
302             if (Precision::IsNegativeInfinite(f))
303               {
304                 //return pr->Parameter();//p;
305                 U = pr->Parameter();
306                 return Standard_True;
307               }
308             if (Precision::IsPositiveInfinite(l))
309               {
310                 //return pr->Parameter();//p;
311                 U = pr->Parameter();
312                 return Standard_True;
313               }
314             gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
315             gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
316             Standard_Real tol = BRep_Tool::Tolerance(V);
317             if (Pf.Distance(Pl) < tol) {
318               if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
319                 if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
320                 else                                   res = l;//p = l;
321               }
322             }
323           }
324           //return res;//p;
325           U = res;
326           return Standard_True;
327         }
328         itpr.Next();
329       }
330     }
331     else {
332       // no 3d curve !!
333       // let us try with the first pcurve
334       Handle(Geom2d_Curve) PC;
335       Handle(Geom_Surface) S;
336       BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
337       L = L.Predivided(V.Location()); 
338       BRep_ListIteratorOfListOfPointRepresentation itpr
339         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
340
341       while (itpr.More()) {
342         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
343         if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
344           Standard_Real p = pr->Parameter();
345           // Closed curves RLE 16 june 94
346           if (PC->IsClosed()) {
347             if ((p == PC->FirstParameter()) || 
348                 (p == PC->LastParameter())) {
349               if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
350               else                                   p = PC->LastParameter();
351             }
352           }
353           //return p;
354           U = p;
355           return Standard_True;
356         }
357         itpr.Next();
358       }
359     }
360   }
361   
362   //Standard_NoSuchObject::Raise("BRep_Tool:: no parameter on edge");
363   return Standard_False;
364 }
365
366 //=======================================================================
367 //function : GetEdgePoints
368 //purpose  : gets the first, last and middle points of the edge
369 //=======================================================================
370 static void GetEdgePoints(const TopoDS_Edge& anEdge,
371                                       const TopoDS_Face& aFace,
372                                       gp_Pnt& fPnt, gp_Pnt& mPnt,
373                                       gp_Pnt& lPnt)
374 {
375   Standard_Real f, l;
376   Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
377   gp_Pnt2d fPnt2d = theCurve->Value(f);
378   gp_Pnt2d lPnt2d = theCurve->Value(l);
379   gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
380   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
381   fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
382   lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
383   mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
384 }
385
386 //=======================================================================
387 //function : FillContours
388 //purpose  : fills free boundary contours and faces connected (MapEF)
389 //=======================================================================
390 static void FillContours(const TopoDS_Shape& aShape,
391                          const BRepOffset_Analyse& Analyser,
392                          TopTools_DataMapOfShapeListOfShape& Contours,
393                          TopTools_DataMapOfShapeShape& MapEF)
394 {
395   TopTools_ListOfShape Edges;
396
397   TopExp_Explorer Explo(aShape, TopAbs_FACE);
398   BRepTools_WireExplorer Wexp;
399
400   for (; Explo.More(); Explo.Next())
401     {
402       TopoDS_Face aFace = TopoDS::Face(Explo.Current());
403       TopoDS_Iterator itf(aFace);
404       for (; itf.More(); itf.Next())
405         {
406           TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
407           for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
408             {
409               TopoDS_Edge anEdge = Wexp.Current();
410               if (BRep_Tool::Degenerated(anEdge))
411                 continue;
412               const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
413               if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary)
414                 {
415                   MapEF.Bind(anEdge, aFace);
416                   Edges.Append(anEdge);
417                 }
418             }
419         }
420     }
421
422   TopTools_ListIteratorOfListOfShape itl;
423   while (!Edges.IsEmpty())
424     {
425       TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
426       Edges.RemoveFirst();
427       TopoDS_Vertex StartVertex, CurVertex;
428       TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
429       TopTools_ListOfShape aContour;
430       aContour.Append(StartEdge);
431       while (!CurVertex.IsSame(StartVertex))
432         for (itl.Initialize(Edges); itl.More(); itl.Next())
433           {
434             TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
435             TopoDS_Vertex V1, V2;
436             TopExp::Vertices(anEdge, V1, V2);
437             if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
438               {
439                 aContour.Append(anEdge);
440                 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
441                 Edges.Remove(itl);
442                 break;
443               }
444           }
445       Contours.Bind(StartVertex, aContour);
446     }
447 }
448
449 //=======================================================================
450 //function : BRepOffset_MakeOffset
451 //purpose  : 
452 //=======================================================================
453
454 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
455 {
456   myAsDes = new BRepAlgo_AsDes();
457 }
458
459
460 //=======================================================================
461 //function : BRepOffset_MakeOffset
462 //purpose  : 
463 //=======================================================================
464
465 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape&    S, 
466                                              const Standard_Real    Offset, 
467                                              const Standard_Real    Tol, 
468                                              const BRepOffset_Mode  Mode, 
469                                              const Standard_Boolean Inter, 
470                                              const Standard_Boolean SelfInter, 
471                                              const GeomAbs_JoinType Join,
472                                              const Standard_Boolean Thickening)
473
474 myOffset     (Offset),
475 myTol        (Tol),
476 myShape      (S),
477 myMode       (Mode),
478 myInter      (Inter),
479 mySelfInter  (SelfInter),
480 myJoin       (Join),
481 myThickening (Thickening),
482 myDone     (Standard_False)
483
484 {
485   myAsDes = new BRepAlgo_AsDes();
486   MakeOffsetShape();
487 }
488
489
490 //=======================================================================
491 //function : Initialize
492 //purpose  : 
493 //=======================================================================
494
495 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S, 
496                                        const Standard_Real    Offset, 
497                                        const Standard_Real    Tol, 
498                                        const BRepOffset_Mode  Mode,
499                                        const Standard_Boolean Inter,
500                                        const Standard_Boolean SelfInter,
501                                        const GeomAbs_JoinType Join,
502                                        const Standard_Boolean Thickening)
503 {
504   myOffset     = Offset;
505   myShape      = S;
506   myTol        = Tol;
507   myMode       = Mode;
508   myInter      = Inter;
509   mySelfInter  = SelfInter;
510   myJoin       = Join;
511   myThickening = Thickening;
512   myDone     = Standard_False;
513   Clear();
514 }
515
516
517 //=======================================================================
518 //function : Clear
519 //purpose  : 
520 //=======================================================================
521
522 void BRepOffset_MakeOffset::Clear()
523 {
524   myOffsetShape.Nullify();
525   myInitOffsetFace .Clear();
526   myInitOffsetEdge .Clear();
527   myImageOffset    .Clear();
528   myFaces          .Clear();  
529   myFaceOffset     .Clear();
530   myAsDes          ->Clear();
531   myDone     = Standard_False;
532 }
533
534 //=======================================================================
535 //function : AddFace
536 //purpose  : 
537 //=======================================================================
538
539 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
540   myFaces.Add(F);    
541   //-------------
542   // MAJ SD.
543   //-------------
544   myInitOffsetFace.SetRoot (F)  ;    
545   myInitOffsetFace.Bind    (F,F);
546   myImageOffset.SetRoot    (F)  ;  
547 }
548
549 //=======================================================================
550 //function : SetOffsetOnFace
551 //purpose  : 
552 //=======================================================================
553
554 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F, 
555                                             const Standard_Real Off)
556 {
557   if ( myFaceOffset.IsBound(F)) myFaceOffset.UnBind(F);
558   myFaceOffset.Bind(F,Off);
559 }
560
561 //=======================================================================
562 //function : RemoveCorks
563 //purpose  : 
564 //=======================================================================
565
566 static void RemoveCorks (TopoDS_Shape&        S,
567                          TopTools_MapOfShape& Faces)
568 {  
569   TopoDS_Compound SS;
570   BRep_Builder    B;
571   B.MakeCompound (SS);
572   //-----------------------------------------------------
573   // Construction of a shape without caps.
574   // and Orientation of caps as in shape S.
575   //-----------------------------------------------------
576   TopExp_Explorer exp(S,TopAbs_FACE);
577   for (; exp.More(); exp.Next()) {
578     const TopoDS_Shape& Cork = exp.Current(); 
579     if (!Faces.Contains(Cork)) {
580       B.Add(SS,Cork);
581     }
582     else {
583       Faces.Remove (Cork);
584       Faces.Add    (Cork); // to reset it with proper orientation.
585     }
586   }
587   S = SS;
588 #ifdef DRAW
589   if ( AffichOffC) 
590     DBRep::Set("myInit", SS);
591 #endif
592
593 }
594
595 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
596 {  
597   BRepTools_Quilt Glue;
598   Glue.Add( S );
599
600   TopoDS_Shape SS = Glue.Shells();
601   TopExp_Explorer Explo( SS, TopAbs_SHELL );
602   Explo.Next();
603   if (Explo.More())
604     return Standard_False;
605   
606   return Standard_True;
607 }
608
609
610 //=======================================================================
611 //function : MakeList
612 //purpose  : 
613 //=======================================================================
614
615 static void MakeList (TopTools_ListOfShape&      OffsetFaces,
616                       const BRepAlgo_Image&    myInitOffsetFace,
617                       const TopTools_MapOfShape& myFaces)
618 {
619   TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
620   for ( ; itLOF.More(); itLOF.Next()) {
621     const TopoDS_Shape& Root = itLOF.Value();
622     if (!myFaces.Contains(Root))
623       OffsetFaces.Append(myInitOffsetFace.Image(Root).First());
624   }
625 }
626
627 //=======================================================================
628 //function : EvalMax
629 //purpose  : 
630 //=======================================================================
631
632 static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
633 {
634   TopExp_Explorer exp;
635   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
636     const TopoDS_Vertex& V    = TopoDS::Vertex(exp.Current());
637     Standard_Real        TolV = BRep_Tool::Tolerance(V); 
638     if (TolV > Tol) Tol = TolV;
639   }
640   //Patch
641   Tol *= 5.;
642 }
643
644 //=======================================================================
645 //function : MakeOffsetShape
646 //purpose  : 
647 //=======================================================================
648
649 void BRepOffset_MakeOffset::MakeOffsetShape()
650 {  
651   myDone     = Standard_False;
652   //------------------------------------------
653   // Construction of myShape without caps.
654   //------------------------------------------
655   RemoveCorks (myShape,myFaces);
656   
657   if (! IsConnectedShell(myShape))
658     Standard_ConstructionError::Raise("BRepOffset_MakeOffset : Incorrect set of faces to remove, the remaining shell is not connected");
659
660   if (Abs(myOffset) < myTol) return;
661
662   TopAbs_State       Side = TopAbs_IN;
663   if (myOffset < 0.) Side = TopAbs_OUT;
664   // ------------
665   // Preanalyse.
666   // ------------
667   EvalMax(myShape,myTol);
668   if (myTol > Abs(myOffset*0.5)) {
669     Standard_ConstructionError::Raise("BRepOffset_MakeOffset : Tol > Offset");
670   }
671   Standard_Real TolAngle = 4*ASin(myTol/Abs(myOffset*0.5));
672   myAnalyse.Perform(myShape,TolAngle);
673   //---------------------------------------------------
674   // Construction of Offset from preanalysis.
675   //---------------------------------------------------  
676   //----------------------------
677   // MaJ of SD Face - Offset
678   //----------------------------
679   UpdateFaceOffset();
680
681   if (myJoin == GeomAbs_Arc)          
682     BuildOffsetByArc();
683   else if (myJoin == GeomAbs_Intersection) 
684     BuildOffsetByInter();
685   //-----------------
686   // Auto unwinding.
687   //-----------------
688   // if (mySelfInter)  SelfInter(Modif);
689   //-----------------
690   // Intersection 3d .
691   //-----------------
692   BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
693   Intersection3D (Inter);
694   //-----------------
695   // Intersection2D
696   //-----------------
697   TopTools_MapOfShape& Modif    = Inter.TouchedFaces(); 
698   TopTools_MapOfShape& NewEdges = Inter.NewEdges();
699
700   if (!Modif.IsEmpty()) Intersection2D (Modif,NewEdges);
701   //-------------------------------------------------------
702   // Unwinding 2D and reconstruction of modified faces
703   //----------------------------------------------------
704   MakeLoops (Modif);
705   //-----------------------------------------------------
706   // Reconstruction of non modified faces sharing 
707   // reconstructed edges
708   //------------------------------------------------------
709   if (!Modif.IsEmpty()) MakeFaces (Modif);
710
711   if (myThickening)
712     MakeMissingWalls();
713
714   //-------------------------
715   // Construction of shells.
716   //-------------------------
717   MakeShells ();
718   //--------------
719   // Unwinding 3D.
720   //--------------
721   SelectShells ();
722   //----------------------------------
723   // Coding of regularities.
724   //----------------------------------
725   EncodeRegularity();
726   //----------------------
727   // Creation of solids.
728   //----------------------
729   MakeSolid ();
730
731   //-----------------------------
732   // MAJ Tolerance edge and Vertex
733   // ----------------------------
734   if (!myOffsetShape.IsNull()) {
735     UpdateTolerance (myOffsetShape,myFaces);
736     BRepLib::UpdateTolerances( myOffsetShape );
737   }
738
739   CorrectConicalFaces();
740
741   myDone = Standard_True;
742 }
743
744
745
746 //=======================================================================
747 //function : MakeThickSolid
748 //purpose  : 
749 //=======================================================================
750
751 void BRepOffset_MakeOffset::MakeThickSolid() 
752 {
753   //--------------------------------------------------------------
754   // Construction of shell parallel to shell (initial without cap).
755   //--------------------------------------------------------------
756   MakeOffsetShape ();
757
758   //--------------------------------------------------------------------
759   // Construction of a solid with the initial shell, parallel shell 
760   // limited by caps.
761   //--------------------------------------------------------------------
762   if (!myFaces.IsEmpty()) {
763     TopoDS_Solid    Res;
764     TopExp_Explorer exp;
765     BRep_Builder    B;
766     Standard_Integer NbF = myFaces.Extent();
767
768     B.MakeSolid(Res);
769
770     BRepTools_Quilt Glue;
771     for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
772       NbF++;
773       Glue.Add (exp.Current());
774     } 
775     Standard_Boolean YaResult = 0;
776     if (!myOffsetShape.IsNull()) {
777       for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next()) {
778         YaResult = 1;
779         Glue.Add (exp.Current().Reversed());
780       }
781     }
782     if (YaResult == 0) {
783       myDone = Standard_False;
784       return;
785     }
786     myOffsetShape = Glue.Shells();
787     for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
788       B.Add(Res,exp.Current());
789     }
790     Res.Closed(Standard_True);
791     myOffsetShape = Res;
792
793     // Test of Validity of the result of thick Solid 
794     // more face than the initial solid.
795         
796     Standard_Integer NbOF = 0;
797     for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next()) {
798       NbOF++;
799     }
800     if (NbOF <= NbF) {
801       myDone = Standard_False;
802       return;
803     }
804   }
805
806   if (myOffset > 0 ) myOffsetShape.Reverse();  
807
808   myDone = Standard_True;
809 }
810
811 //=======================================================================
812 //function : IsDone
813 //purpose  : 
814 //=======================================================================
815
816 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
817 {
818   return myDone;
819 }
820
821 //=======================================================================
822 //function : Error
823 //purpose  : 
824 //=======================================================================
825
826 BRepOffset_Error BRepOffset_MakeOffset::Error() const
827 {
828   return myError;
829 }
830
831 //=======================================================================
832 //function : Shape
833 //purpose  : 
834 //=======================================================================
835
836 const TopoDS_Shape&  BRepOffset_MakeOffset::Shape() const 
837 {
838   return myOffsetShape;
839 }
840
841 //=======================================================================
842 //function : TrimEdge
843 //purpose  : Trim the edge of the largest of descendants in AsDes2d.
844 //           Order in AsDes two vertices that have trimmed the edge.
845 //=======================================================================
846
847 static void TrimEdge (TopoDS_Edge&                  NE,
848                       const Handle(BRepAlgo_AsDes)& AsDes2d,
849                             Handle(BRepAlgo_AsDes)& AsDes)
850 {
851   Standard_Real aSameParTol = Precision::Confusion();
852   
853   TopoDS_Vertex V1,V2;
854   Standard_Real U;
855   Standard_Real UMin =  Precision::Infinite();
856   Standard_Real UMax = -UMin;
857
858   const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
859   
860   if (LE.Extent() > 1) {
861     TopTools_ListIteratorOfListOfShape it (LE);
862     for (; it.More(); it.Next()) {
863       TopoDS_Vertex V = TopoDS::Vertex(it.Value());
864       if (NE.Orientation() == TopAbs_REVERSED)
865         V.Reverse();
866       //V.Orientation(TopAbs_INTERNAL);
867       if (!FindParameter(V, NE, U))
868         {
869           Standard_Real f, l;
870           Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
871           gp_Pnt thePoint = BRep_Tool::Pnt(V);
872           GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
873           if (Projector.NbPoints() == 0)
874             Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
875           U = Projector.LowerDistanceParameter();
876         }
877       if (U < UMin) {
878         UMin = U; V1   = V;
879       }
880       if (U > UMax) {
881         UMax = U; V2   = V;
882       }
883     }
884     if (V1.IsNull() || V2.IsNull()) {
885       Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
886     }
887     if (!V1.IsSame(V2)) {
888       NE.Free( Standard_True );
889       BRep_Builder B;
890       TopAbs_Orientation Or = NE.Orientation();
891       NE.Orientation(TopAbs_FORWARD);
892       TopoDS_Vertex VF,VL;
893       TopExp::Vertices (NE,VF,VL);
894       B.Remove(NE,VF);
895       B.Remove(NE,VL);
896       B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
897       B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
898       B.Range(NE,UMin,UMax);
899       NE.Orientation(Or);
900       AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
901       AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
902       BRepLib::SameParameter(NE, aSameParTol, Standard_True);
903     }
904   }
905 }
906
907 //=======================================================================
908 //function : BuildOffsetByInter
909 //purpose  : 
910 //=======================================================================
911 void BRepOffset_MakeOffset::BuildOffsetByInter()
912 {
913 #ifdef  DEB
914   if ( ChronBuild) {
915     cout << " CONSTRUCTION OF OFFSETS :" << endl;
916     Clock.Reset();
917     Clock.Start();
918   }
919 #endif
920
921   BRepOffset_DataMapOfShapeOffset MapSF;
922   TopTools_MapOfShape             Done;
923   Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
924   //--------------------------------------------------------
925   // Construction of faces parallel to initial faces
926   //--------------------------------------------------------
927   TopExp_Explorer Exp;
928   TopTools_ListOfShape LF;
929   TopTools_ListIteratorOfListOfShape itLF;
930
931   BRepLib::SortFaces(myShape,LF);
932
933   TopTools_DataMapOfShapeShape ShapeTgt;
934   for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
935     const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
936     Standard_Real CurOffset = myOffset;
937     if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
938     BRepOffset_Offset    OF(F,CurOffset,ShapeTgt,OffsetOutside,myJoin);
939     TopTools_ListOfShape Let;
940     myAnalyse.Edges(F,BRepOffset_Tangent,Let);
941     TopTools_ListIteratorOfListOfShape itl(Let);
942     
943     for ( ; itl.More(); itl.Next()) {
944       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
945       if ( !ShapeTgt.IsBound(Cur)) {
946         TopoDS_Shape aLocalShape = OF.Generated(Cur);
947         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
948 //      const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
949         ShapeTgt.Bind(Cur,OF.Generated(Cur));
950         TopoDS_Vertex V1,V2,OV1,OV2;
951         TopExp::Vertices (Cur,V1,V2);
952         TopExp::Vertices (OTE,OV1,OV2);      
953         TopTools_ListOfShape LE;
954         if (!ShapeTgt.IsBound(V1)) {
955           myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
956           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
957           if (LE.Extent() == LA.Extent())
958             ShapeTgt.Bind(V1,OV1);
959         }
960         if (!ShapeTgt.IsBound(V2)) {
961           LE.Clear();
962           myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
963           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
964           if (LE.Extent() == LA.Extent())
965             ShapeTgt.Bind(V2,OV2);
966         }
967       }
968     }
969     MapSF.Bind(F,OF);
970   }
971   //--------------------------------------------------------------------
972   // MES   : Map of OffsetShape -> Extended Shapes.
973   // Build : Map of Initial SS  -> OffsetShape build by Inter.
974   //                               can be an edge or a compound of edges       
975   //---------------------------------------------------------------------
976   TopTools_DataMapOfShapeShape MES;  
977   TopTools_DataMapOfShapeShape Build; 
978   TopTools_ListOfShape         Failed;
979   TopAbs_State                 Side = TopAbs_IN;  
980   Handle(BRepAlgo_AsDes)       AsDes = new BRepAlgo_AsDes();
981
982   //-------------------------------------------------------------------
983   // Extension of faces and calculation of new edges of intersection.
984   //-------------------------------------------------------------------
985   Standard_Boolean  ExtentContext = 0;
986   if (myOffset > 0) ExtentContext = 1;
987
988   BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
989   // Intersection between parallel faces
990   Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed );
991   // Intersection with caps.
992   Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed );
993
994
995   //---------------------------------------------------------------------------------
996   // Extension of neighbor edges of new edges and intersection between neighbors.
997   //--------------------------------------------------------------------------------
998   Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
999   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1000     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
1001 //  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455 Begin
1002 //    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myTol);
1003     BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myOffset, myTol);
1004 //  Modified by skv - Mon Jan 12 11:50:03 2004 OCC4455 End
1005   }
1006   //-----------------------------------------------------------
1007   // Great restriction of new edges and update of AsDes.
1008   //------------------------------------------ ----------------
1009   TopTools_MapOfShape NewEdges;
1010   TopExp_Explorer Exp2,ExpC;
1011   TopoDS_Shape    NE;
1012   TopoDS_Edge     TNE;
1013   TopoDS_Face     NF;
1014 #ifdef DEB
1015   TopAbs_Orientation Or;
1016 #endif
1017   
1018   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1019     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
1020     NF = MapSF(FI).Face();
1021     if (MES.IsBound(NF)) {NF = TopoDS::Face(MES(NF));}
1022     TopTools_MapOfShape View;
1023     for (Exp2.Init(FI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); Exp2.More(); Exp2.Next()) {
1024       const TopoDS_Edge& EI = TopoDS::Edge(Exp2.Current());
1025       if (View.Add(EI)) {
1026         if (Build.IsBound(EI)) {
1027           NE = Build(EI);
1028           if (NE.ShapeType() == TopAbs_EDGE) {
1029             if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);}
1030           }
1031           else {
1032             //------------------------------------------------------------
1033             // The Intersections are on several edges.
1034             // The pieces without intersections with neighbors  
1035             // are removed from AsDes.
1036             //------------------------------------------------------------
1037             for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1038               if (NewEdges.Add(ExpC.Current())) {
1039                 TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
1040                 NEC.Free(Standard_True);
1041                 if (!AsDes2d->Descendant(NEC).IsEmpty()) {
1042                   TrimEdge (NEC,AsDes2d,AsDes);
1043                 }
1044                 else {
1045                   AsDes->Remove(NEC);
1046                 }
1047               }
1048             }
1049           }
1050         }
1051         else {
1052           NE = MapSF(FI).Generated(EI);
1053           //// modified by jgv, 19.12.03 for OCC4455 ////
1054           NE.Orientation( EI.Orientation() );
1055           ///////////////////////////////////////////////
1056           if (MES.IsBound(NE)) {
1057             NE = MES(NE);
1058             NE.Orientation(EI.Orientation());
1059             if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
1060           }
1061           AsDes->Add(NF,NE);
1062         } 
1063       }
1064     }
1065   }
1066   
1067   //--------------------------------- 
1068   // Intersection 2D on //
1069   //---------------------------------  
1070   TopTools_ListOfShape LFE; 
1071   BRepAlgo_Image     IMOE;
1072   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1073     const TopoDS_Shape& FI  = Exp.Current();
1074     const TopoDS_Shape& OFI = MapSF(FI).Face();
1075     if (MES.IsBound(OFI)) {
1076       const TopoDS_Face& NF = TopoDS::Face(MES(OFI));
1077       LFE.Append(NF);
1078       IMOE.SetRoot(NF);
1079     }
1080   }
1081   
1082   TopTools_ListIteratorOfListOfShape itLFE(LFE);
1083   for (; itLFE.More(); itLFE.Next()) {
1084     const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
1085     BRepOffset_Inter2d::Compute(AsDes,NEF,NewEdges,myTol);
1086   }
1087   //----------------------------------------------
1088   // Intersections 2d on caps.
1089   //----------------------------------------------
1090   TopTools_MapIteratorOfMapOfShape itCork(myFaces);
1091   for (; itCork.More(); itCork.Next()) {
1092     const TopoDS_Face& Cork = TopoDS::Face(itCork.Key());
1093     BRepOffset_Inter2d::Compute(AsDes,Cork,NewEdges,myTol);
1094   }
1095
1096   //-------------------------------
1097   // Unwinding of extended Faces.
1098   //-------------------------------
1099   myMakeLoops.Build(LFE  ,AsDes,IMOE);
1100
1101 #ifdef DEB
1102   TopTools_MapOfShape COES;
1103 #endif
1104   //---------------------------
1105   // MAJ SD. for faces //
1106   //---------------------------
1107   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1108     const TopoDS_Shape& FI   = Exp.Current();
1109     myInitOffsetFace.SetRoot(FI);
1110     TopoDS_Face  OF  = MapSF(FI).Face();
1111     if (MES.IsBound(OF)) {
1112       OF = TopoDS::Face(MES(OF));
1113       if (IMOE.HasImage(OF)) {
1114         const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
1115         myInitOffsetFace.Bind(FI,LOFE);
1116         for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
1117           const TopoDS_Shape& OFE =  itLF.Value();
1118           myImageOffset.SetRoot(OFE);
1119 #ifdef DRAW
1120           if (AffichInt2d) {
1121             sprintf(name,"AF_%d",NbAF++);
1122             DBRep::Set(name,OFE);
1123           }
1124 #endif
1125           TopTools_MapOfShape View;
1126           for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1127                Exp2.More(); Exp2.Next()) {
1128             const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1129             
1130             myAsDes->Add (OFE,COE);
1131 #ifdef DRAW
1132             if (AffichInt2d) {
1133               sprintf(name,"AE_%d",NbAE++);
1134               DBRep::Set(name,COE);
1135               COES.Add(COE);
1136             }
1137 #endif
1138             if (View.Add(COE)){
1139               if (!myAsDes->HasDescendant(COE)) {
1140                 TopoDS_Vertex CV1,CV2;
1141                 TopExp::Vertices(COE,CV1,CV2);
1142                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1143                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));     
1144               }
1145             }
1146           }
1147         }
1148       }
1149       else {
1150         myInitOffsetFace.Bind(FI,OF);
1151         myImageOffset.SetRoot(OF);
1152 #ifdef DRAW 
1153         if (AffichInt2d) {
1154           sprintf(name,"AF_%d",NbAF++);
1155           DBRep::Set(name,OF);
1156         }
1157 #endif
1158         const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
1159         for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1160           const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1161           if (IMOE.HasImage(OE)) {
1162             const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1163             TopTools_ListIteratorOfListOfShape itLOE(LOE);
1164             for (; itLOE.More(); itLOE.Next()) {
1165               TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
1166               const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
1167 //            const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
1168               myAsDes->Add(OF,COE);
1169 #ifdef DRAW
1170               if (AffichInt2d) {
1171                 sprintf(name,"AE_%d",NbAE++);
1172                 DBRep::Set(name,COE);
1173                 COES.Add(COE);
1174               }
1175 #endif
1176               
1177               if (!myAsDes->HasDescendant(COE)) {
1178                 TopoDS_Vertex CV1,CV2;
1179                 TopExp::Vertices(COE,CV1,CV2);
1180                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1181                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));     
1182               }
1183             }
1184           }
1185           else {
1186             myAsDes->Add(OF,OE);
1187 #ifdef DRAW
1188             if (AffichInt2d) {
1189               sprintf(name,"AE_%d",NbAE++);
1190               DBRep::Set(name,OE);
1191               COES.Add(OE);
1192             }
1193 #endif
1194
1195             const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
1196             myAsDes->Add(OE,LV);
1197           }
1198         }
1199       }
1200     }
1201     else {
1202       myInitOffsetFace.Bind(FI,OF);
1203       myImageOffset.SetRoot(OF);
1204       TopTools_MapOfShape View;
1205       for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1206            Exp2.More(); Exp2.Next()) {
1207
1208         const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1209         myAsDes->Add (OF,COE);
1210 #ifdef DRAW
1211         if (AffichInt2d) {
1212           sprintf(name,"AE_%d",NbAE++);
1213           DBRep::Set(name,COE);
1214           COES.Add(COE);
1215         }
1216 #endif
1217         
1218         if (View.Add(Exp2.Current())) {
1219           if (!myAsDes->HasDescendant(COE)) {
1220             TopoDS_Vertex CV1,CV2;
1221             TopExp::Vertices(COE,CV1,CV2);
1222             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1223             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED)); 
1224           }
1225         }
1226       } 
1227     }
1228   }
1229   //  Modified by skv - Tue Mar 15 16:20:43 2005
1230   // Add methods for supporting history.
1231   TopTools_MapOfShape aMapEdges;
1232
1233   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1234     const TopoDS_Shape& aFaceRef = Exp.Current();
1235
1236     Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1237
1238     for (; Exp2.More(); Exp2.Next()) {
1239       const TopoDS_Shape& anEdgeRef = Exp2.Current();
1240
1241       if (aMapEdges.Add(anEdgeRef)) {
1242         myInitOffsetEdge.SetRoot(anEdgeRef);
1243         if (Build.IsBound(anEdgeRef)) {
1244           TopoDS_Shape aNewShape = Build(anEdgeRef);
1245           
1246           if (aNewShape.ShapeType() == TopAbs_EDGE) {
1247             if (IMOE.HasImage(aNewShape)) {
1248               const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
1249               
1250               myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1251             } else
1252               myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
1253           } else { // aNewShape != TopAbs_EDGE
1254             TopTools_ListOfShape aListNewEdge;
1255             
1256             for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1257               const TopoDS_Shape &aResEdge = ExpC.Current();
1258               
1259               if (IMOE.HasImage(aResEdge)) {
1260                 const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
1261                 TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
1262                 
1263                 for (; aNewEIter.More(); aNewEIter.Next())
1264                   aListNewEdge.Append(aNewEIter.Value());
1265               } else
1266                 aListNewEdge.Append(aResEdge);
1267             }
1268             
1269             myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
1270           }
1271         } 
1272         else { // Free boundary.
1273           TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
1274
1275           if (MES.IsBound(aNewEdge))
1276             aNewEdge = MES(aNewEdge);
1277
1278           if (IMOE.HasImage(aNewEdge)) {
1279             const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
1280
1281             myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1282           } else
1283             myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
1284         }
1285       }
1286     }
1287   }
1288 //  Modified by skv - Tue Mar 15 16:20:43 2005
1289
1290   //---------------------------
1291   // MAJ SD. for caps 
1292   //---------------------------
1293   TopTools_MapOfShape View; 
1294   for (itCork.Initialize(myFaces); itCork.More(); itCork.Next()) {
1295     const TopoDS_Shape& Cork = itCork.Key();
1296     const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
1297     for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1298       const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1299       if (IMOE.HasImage(OE)) {
1300         const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1301         TopTools_ListIteratorOfListOfShape itLOE(LOE);
1302         for (; itLOE.More(); itLOE.Next()) {
1303           const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
1304           myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
1305 #ifdef DRAW
1306           if (AffichInt2d) {
1307             sprintf(name,"AE_%d",NbAE++);
1308             DBRep::Set(name,COE);
1309             COES.Add(COE);
1310           }
1311 #endif
1312           
1313           if (!myAsDes->HasDescendant(COE)) {
1314             TopoDS_Vertex CV1,CV2;
1315             TopExp::Vertices(COE,CV1,CV2);
1316             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1317             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));   
1318           }
1319         }
1320       }
1321       else {
1322         myAsDes->Add(Cork,OE);
1323         if (AsDes->HasDescendant(OE)) {
1324           myAsDes->Add(OE,AsDes->Descendant(OE));
1325         }
1326 #ifdef DRAW
1327         if (AffichInt2d) {
1328           sprintf(name,"AE_%d",NbAE++);
1329           DBRep::Set(name,OE);
1330           COES.Add(OE);
1331         }
1332 #endif
1333       }
1334     }
1335   }
1336   
1337 #ifdef DEB
1338   DEBVerticesControl (COES,myAsDes);
1339   if ( ChronBuild) Clock.Show();
1340 #endif
1341 }
1342
1343
1344 //=======================================================================
1345 //function : BuildOffsetByArc
1346 //purpose  : 
1347 //=======================================================================
1348 void BRepOffset_MakeOffset::BuildOffsetByArc()
1349 {
1350 #ifdef  DEB
1351   if ( ChronBuild) {
1352     cout << " CONSTRUCTION OF OFFSETS :" << endl;
1353     Clock.Reset();
1354     Clock.Start();
1355   }
1356 #endif
1357
1358   BRepOffset_DataMapOfShapeOffset MapSF;
1359   TopTools_MapOfShape             Done;
1360   Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
1361   //--------------------------------------------------------
1362   // Construction of faces parallel to initial faces
1363   //--------------------------------------------------------
1364   TopExp_Explorer Exp;
1365   TopTools_ListOfShape LF;
1366   TopTools_ListIteratorOfListOfShape itLF;
1367
1368   BRepLib::SortFaces(myShape,LF);
1369
1370   TopTools_DataMapOfShapeShape EdgeTgt;
1371   for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
1372     const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
1373     Standard_Real CurOffset = myOffset;
1374     if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
1375     BRepOffset_Offset    OF(F,CurOffset,EdgeTgt,OffsetOutside,myJoin);
1376     TopTools_ListOfShape Let;
1377     myAnalyse.Edges(F,BRepOffset_Tangent,Let);
1378     TopTools_ListIteratorOfListOfShape itl(Let);
1379     
1380     for ( ; itl.More(); itl.Next()) {
1381       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1382       if ( !EdgeTgt.IsBound(Cur)) {
1383         TopoDS_Shape aLocalShape = OF.Generated(Cur);
1384         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1385 //      const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
1386         EdgeTgt.Bind(Cur,OF.Generated(Cur));
1387         TopoDS_Vertex V1,V2,OV1,OV2;
1388         TopExp::Vertices (Cur,V1,V2);
1389         TopExp::Vertices (OTE,OV1,OV2);      
1390         TopTools_ListOfShape LE;
1391         if (!EdgeTgt.IsBound(V1)) {
1392           myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
1393           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
1394           if (LE.Extent() == LA.Extent())
1395             EdgeTgt.Bind(V1,OV1);
1396         }
1397         if (!EdgeTgt.IsBound(V2)) {
1398           LE.Clear();
1399           myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
1400           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
1401           if (LE.Extent() == LA.Extent())
1402               EdgeTgt.Bind(V2,OV2);
1403         }
1404       }
1405     }
1406     MapSF.Bind(F,OF);
1407   }
1408   //--------------------------------------------------------
1409   // Construction of tubes on edge.
1410   //--------------------------------------------------------
1411   BRepOffset_Type    OT = BRepOffset_Convex;
1412   if (myOffset < 0.) OT = BRepOffset_Concave; 
1413    
1414   for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) {
1415     const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1416     if (Done.Add(E)) {
1417       const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
1418       if (Anc.Extent() == 2) {
1419         const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1420         if (!L.IsEmpty() && L.First().Type() == OT) {
1421           Standard_Real CurOffset = myOffset;
1422           if ( myFaceOffset.IsBound(Anc.First()))
1423             CurOffset = myFaceOffset(Anc.First());
1424           TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1425           TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1426           aLocalShape = MapSF(Anc.Last()).Generated(E);
1427           TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShape);
1428 //        TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1429 //        TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
1430           // find if exits tangent edges in the original shape
1431           TopoDS_Edge E1f, E1l;
1432           TopoDS_Vertex V1f, V1l;
1433           TopExp::Vertices(E,V1f,V1l);
1434           TopTools_ListOfShape TangE;
1435           myAnalyse.TangentEdges(E,V1f,TangE);
1436           // find if the pipe on the tangent edges are soon created.
1437           TopTools_ListIteratorOfListOfShape itl(TangE);
1438           Standard_Boolean Find = Standard_False;
1439           for ( ; itl.More() && !Find; itl.Next()) {
1440             if ( MapSF.IsBound(itl.Value())) {
1441               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
1442               E1f  = TopoDS::Edge(aLocalShape);
1443 //            E1f  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
1444               Find = Standard_True;
1445             }
1446           }
1447           TangE.Clear();
1448           myAnalyse.TangentEdges(E,V1l,TangE);
1449           // find if the pipe on the tangent edges are soon created.
1450           itl.Initialize(TangE);
1451           Find = Standard_False;
1452           for ( ; itl.More() && !Find; itl.Next()) {
1453             if ( MapSF.IsBound(itl.Value())) {
1454               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
1455               E1l  = TopoDS::Edge(aLocalShape);
1456 //            E1l  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
1457               Find = Standard_True;
1458             }
1459           }
1460           BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
1461           MapSF.Bind(E,OF);
1462         }
1463       }
1464       else {
1465         // ----------------------
1466         // free border.
1467         // ----------------------
1468         TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1469         TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1470 ///     TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1471         myInitOffsetEdge.SetRoot(E); // skv: supporting history.
1472         myInitOffsetEdge.Bind (E,EOn1);      
1473       }
1474     }
1475   }
1476
1477   //--------------------------------------------------------
1478   // Construction of spheres on vertex.
1479   //--------------------------------------------------------
1480   Done.Clear();
1481   TopTools_ListIteratorOfListOfShape it;
1482
1483   for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) {
1484     const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
1485     if (Done.Add(V)) {
1486       const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
1487       TopTools_ListOfShape LE;
1488       myAnalyse.Edges(V,OT,LE);
1489
1490       if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
1491         TopTools_ListOfShape LOE;
1492         //--------------------------------------------------------
1493         // Return connected edges on tubes.
1494         //--------------------------------------------------------
1495         for (it.Initialize(LE) ; it.More(); it.Next()) {
1496           LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
1497         }
1498         //----------------------
1499         // construction sphere.
1500         //-----------------------
1501         const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
1502         const TopoDS_Shape& FF = LLA.First();
1503         Standard_Real CurOffset = myOffset;
1504         if ( myFaceOffset.IsBound(FF))
1505           CurOffset = myFaceOffset(FF);
1506         
1507         BRepOffset_Offset OF(V,LOE,CurOffset);
1508         MapSF.Bind(V,OF);
1509       }
1510       //--------------------------------------------------------------
1511       // Particular processing if V is at least a free border.
1512       //-------------------------------------------------------------
1513       TopTools_ListOfShape LBF;
1514       myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF);
1515       if (!LBF.IsEmpty()) {     
1516         Standard_Boolean First = Standard_True;
1517         for (it.Initialize(LE) ; it.More(); it.Next()) {
1518           if (First) {
1519             myInitOffsetEdge.SetRoot(V); // skv: supporting history.
1520             myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
1521             First = Standard_False;
1522           }
1523           else {
1524             myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
1525           }
1526         } 
1527       }
1528     }
1529   }
1530
1531   //------------------------------------------------------------
1532   // Extension of parallel faces to the context.
1533   // Extended faces are ordered in DS and removed from MapSF.
1534   //------------------------------------------------------------
1535   if (!myFaces.IsEmpty()) ToContext (MapSF);
1536
1537   //------------------------------------------------------
1538   // MAJ SD.
1539   //------------------------------------------------------
1540   BRepOffset_Type    RT = BRepOffset_Concave;
1541   if (myOffset < 0.) RT = BRepOffset_Convex;
1542   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
1543 #ifdef DEB
1544   Standard_Integer MapSFNb = MapSF.Extent();
1545 #endif
1546   for ( ; It.More(); It.Next()) {
1547     const TopoDS_Shape& SI = It.Key(); 
1548     const BRepOffset_Offset& SF = It.Value();
1549     if (SF.Status() == BRepOffset_Reversed ||
1550         SF.Status() == BRepOffset_Degenerated ) {
1551       //------------------------------------------------
1552       // Degenerated or returned faces are not stored.
1553       //------------------------------------------------
1554       continue; 
1555     }   
1556
1557     const TopoDS_Face&  OF = It.Value().Face();
1558     myInitOffsetFace.Bind    (SI,OF);      
1559     myInitOffsetFace.SetRoot (SI);      // Initial<-> Offset
1560     myImageOffset.SetRoot    (OF);      // FaceOffset root of images
1561     
1562     if (SI.ShapeType() == TopAbs_FACE) {
1563       for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1564            Exp.More(); Exp.Next()) {
1565         //--------------------------------------------------------------------
1566         // To each face are associatedthe edges that restrict that 
1567         // The edges that do not generate tubes or are not tangent
1568         // to two faces are removed.
1569         //--------------------------------------------------------------------
1570         const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1571         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
1572         if (!L.IsEmpty() && L.First().Type() != RT) {
1573           TopAbs_Orientation OO  = E.Orientation();
1574           TopoDS_Shape aLocalShape = It.Value().Generated(E);
1575           TopoDS_Edge        OE  = TopoDS::Edge(aLocalShape);
1576 //        TopoDS_Edge        OE  = TopoDS::Edge(It.Value().Generated(E));
1577           myAsDes->Add (OF,OE.Oriented(OO));
1578         }
1579       }
1580     }
1581     else {
1582       for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1583            Exp.More(); Exp.Next()) {
1584         myAsDes->Add (OF,Exp.Current());
1585       }
1586     }
1587   }
1588
1589 #ifdef DEB
1590   if ( ChronBuild) Clock.Show();
1591 #endif
1592 }
1593
1594
1595
1596 //=======================================================================
1597 //function : SelfInter
1598 //purpose  : 
1599 //=======================================================================
1600
1601 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& Modif)
1602 {
1603 #ifdef DEB
1604   if ( ChronBuild) {
1605     cout << " AUTODEBOUCLAGE:" << endl;
1606     Clock.Reset();
1607     Clock.Start();
1608   }    
1609 #endif  
1610
1611   Standard_NotImplemented::Raise();
1612
1613 #ifdef DEB
1614   if ( ChronBuild) Clock.Show();
1615 #endif
1616 }
1617
1618
1619 //=======================================================================
1620 //function : ToContext
1621 //purpose  : 
1622 //=======================================================================
1623
1624 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
1625 {
1626   TopTools_DataMapOfShapeShape        Created;   
1627   TopTools_DataMapOfShapeShape        MEF;
1628   TopTools_MapOfShape                 FacesToBuild;
1629   TopTools_MapIteratorOfMapOfShape    it(myFaces); 
1630   TopTools_ListIteratorOfListOfShape  itl;
1631   TopExp_Explorer                     exp;
1632
1633 //  TopAbs_State       Side = TopAbs_IN;  
1634 //  if (myOffset < 0.) Side = TopAbs_OUT;
1635
1636   TopAbs_State       Side = TopAbs_OUT; 
1637  
1638   for (; it.More(); it.Next()) {
1639     const TopoDS_Face& CF = TopoDS::Face(it.Key());
1640     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1641          exp.More(); exp.Next()) {
1642       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1643       if (!myAnalyse.HasAncestor(E)) {
1644         //----------------------------------------------------------------
1645         // The edges of context faces that are not in the initial shape
1646         // can appear in the result.
1647         //----------------------------------------------------------------
1648         //myAsDes->Add(CF,E);
1649       }  
1650     }
1651   }
1652   //-------------------------------------------------------
1653   // Determine the edges and faces reconstructed by  
1654   // intersection.
1655   //---------------------------------------------------------
1656   for ( it.Initialize(myFaces); it.More(); it.Next()) {
1657     const TopoDS_Face& CF = TopoDS::Face(it.Key());
1658     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1659          exp.More(); exp.Next()) {
1660       const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); 
1661       if (myAnalyse.HasAncestor(E)) {
1662         const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
1663         for (itl.Initialize(LEA); itl.More(); itl.Next()) {
1664           const BRepOffset_Offset& OF = MapSF(itl.Value());
1665           FacesToBuild.Add(itl.Value());
1666           MEF.Bind(OF.Generated(E),CF);
1667         }
1668         TopoDS_Vertex V[2];
1669         TopExp::Vertices(E,V[0],V[1]);
1670         for (Standard_Integer i = 0; i < 2; i++) {
1671           const TopTools_ListOfShape& LVA =  myAnalyse.Ancestors(V[i]);
1672           for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
1673             const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
1674             if (MapSF.IsBound(EV)) {
1675               const BRepOffset_Offset& OF = MapSF(EV);
1676               FacesToBuild.Add(EV);
1677               MEF.Bind(OF.Generated(V[i]),CF);
1678             }
1679           }
1680         }
1681       }
1682     }
1683   }
1684   //---------------------------
1685   // Reconstruction of faces.
1686   //---------------------------
1687   TopoDS_Face        F,NF;
1688   BRepOffset_Type    RT = BRepOffset_Concave;
1689   if (myOffset < 0.) RT = BRepOffset_Convex;
1690   TopoDS_Shape       OE,NE;
1691   TopAbs_Orientation Or;
1692
1693   for (it.Initialize(FacesToBuild); it.More(); it.Next()) {
1694     const TopoDS_Shape& S   = it.Key();
1695     BRepOffset_Offset   BOF;
1696     BOF = MapSF(S);
1697     F = TopoDS::Face(BOF.Face());
1698     BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF);
1699     MapSF.UnBind(S);
1700     //--------------
1701     // MAJ SD.
1702     //--------------
1703     myInitOffsetFace.Bind    (S,NF);      
1704     myInitOffsetFace.SetRoot (S);      // Initial<-> Offset
1705     myImageOffset.SetRoot    (NF);
1706
1707     if (S.ShapeType() == TopAbs_FACE) {
1708       for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1709            exp.More(); exp.Next()) {
1710         
1711         const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1712         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
1713         OE = BOF.Generated(E);
1714         Or = E.Orientation();
1715         OE.Orientation(Or);
1716         if (!L.IsEmpty() && L.First().Type() != RT) {
1717           if (Created.IsBound(OE)) {
1718             NE = Created(OE); 
1719             if (NE.Orientation() == TopAbs_REVERSED) 
1720               NE.Orientation(TopAbs::Reverse(Or));
1721             else
1722               NE.Orientation(Or);
1723             myAsDes->Add(NF,NE);
1724           }
1725           else {
1726             myAsDes->Add(NF,OE);
1727           }
1728         }
1729       }
1730     }
1731     else {
1732       //------------------
1733       // Tube
1734       //---------------------
1735       for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1736            exp.More(); exp.Next()) {
1737         myAsDes->Add (NF,exp.Current());
1738       }
1739     }    
1740     MapSF.UnBind(S);
1741   }
1742
1743   //------------------
1744   // MAJ free borders
1745   //------------------
1746   TopTools_DataMapIteratorOfDataMapOfShapeShape itc;
1747   for (itc.Initialize(Created); itc.More(); itc.Next()) {
1748     OE = itc.Key();
1749     NE = itc.Value();
1750     if (myInitOffsetEdge.IsImage(OE)) {
1751       TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
1752       Or = myInitOffsetEdge.Image(E).First().Orientation();
1753       if (NE.Orientation() == TopAbs_REVERSED) 
1754         NE.Orientation(TopAbs::Reverse(Or));
1755       else
1756         NE.Orientation(Or);
1757       myInitOffsetEdge.Remove(OE);
1758       myInitOffsetEdge.Bind(E,NE);
1759     }
1760   }
1761 }
1762
1763
1764 //=======================================================================
1765 //function : UpdateFaceOffset
1766 //purpose  : 
1767 //=======================================================================
1768
1769 void BRepOffset_MakeOffset::UpdateFaceOffset()
1770 {
1771   TopTools_MapOfShape M;
1772   TopTools_DataMapOfShapeReal CopiedMap;
1773   CopiedMap.Assign(myFaceOffset);
1774   TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
1775
1776   BRepOffset_Type    RT = BRepOffset_Convex;
1777   if (myOffset < 0.) RT = BRepOffset_Concave;
1778
1779   for ( ; it.More(); it.Next()) {
1780     const TopoDS_Face& F = TopoDS::Face(it.Key());
1781     Standard_Real CurOffset = CopiedMap(F);
1782     if ( !M.Add(F)) continue;
1783     TopoDS_Compound Co;
1784     BRep_Builder Build;
1785     Build.MakeCompound(Co);
1786     TopTools_MapOfShape Dummy;
1787     Build.Add(Co,F);
1788     if (myJoin == GeomAbs_Arc)
1789       myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent,RT);
1790     else   
1791       myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent);
1792
1793     TopExp_Explorer exp(Co,TopAbs_FACE);
1794     for (; exp.More(); exp.Next()) {
1795       const TopoDS_Face& FF = TopoDS::Face(exp.Current());
1796       if ( !M.Add(FF)) continue;
1797       if ( myFaceOffset.IsBound(FF))
1798         myFaceOffset.UnBind(FF);
1799       myFaceOffset.Bind(FF,CurOffset);
1800     }
1801   }
1802 }
1803
1804 //=======================================================================
1805 //function : CorrectConicalFaces
1806 //purpose  : 
1807 //=======================================================================
1808
1809 void BRepOffset_MakeOffset::CorrectConicalFaces()
1810 {
1811   TopTools_SequenceOfShape Cones;
1812   TopTools_SequenceOfShape Circs;
1813   TopTools_SequenceOfShape Seams;
1814   Standard_Real TolApex = 1.e-5;
1815
1816   Standard_Integer i;
1817
1818   TopTools_DataMapOfShapeListOfShape FacesOfCone;
1819   //TopTools_DataMapOfShapeShape DegEdges;
1820   TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE );
1821   if (myJoin == GeomAbs_Arc)
1822     {
1823       for (; Explo.More(); Explo.Next())
1824         {
1825           TopoDS_Face aFace = TopoDS::Face( Explo.Current() );
1826           Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace );
1827           //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
1828           //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //???
1829           
1830           TopTools_IndexedMapOfShape Emap;
1831           TopExp::MapShapes( aFace, TopAbs_EDGE, Emap );
1832           for (i = 1; i <= Emap.Extent(); i++)
1833             {
1834               TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) );
1835               //Standard_Real f, l;
1836               //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l );
1837               //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape());
1838               if (BRep_Tool::Degenerated(anEdge))
1839                 {
1840                   //Check if anEdge is a really degenerated edge or not
1841                   BRepAdaptor_Curve BACurve(anEdge, aFace);
1842                   gp_Pnt Pfirst, Plast, Pmid;
1843                   Pfirst = BACurve.Value(BACurve.FirstParameter());
1844                   Plast  = BACurve.Value(BACurve.LastParameter());
1845                   Pmid   = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.);
1846                   if (Pfirst.Distance(Plast) <= TolApex &&
1847                       Pfirst.Distance(Pmid)  <= TolApex)
1848                     continue;
1849                   //Cones.Append( aFace );
1850                   //Circs.Append( anEdge );
1851                   //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge );
1852                   TopoDS_Edge OrEdge = 
1853                     TopoDS::Edge( myInitOffsetEdge.Root( anEdge) );
1854                   TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1855                   if ( FacesOfCone.IsBound(VF) )
1856                     {
1857                       //add a face to the existing list
1858                       TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF);
1859                       aFaces.Append (aFace);
1860                       //DegEdges.Bind(aFace, anEdge);
1861                     }
1862                   else
1863                     {
1864                       //the vertex is not in the map => create a new key and items
1865                       TopTools_ListOfShape aFaces;
1866                       aFaces.Append (aFace);
1867                       FacesOfCone.Bind(VF, aFaces);
1868                       //DegEdges.Bind(aFace, anEdge);
1869                     }
1870                 }
1871             } //for (i = 1; i <= Emap.Extent(); i++)
1872         } //for (; fexp.More(); fexp.Next())
1873     } //if (myJoin == GeomAbs_Arc)
1874
1875   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone);
1876   BRep_Builder BB;
1877   TopLoc_Location L;
1878   for (; Cone.More(); Cone.Next() ) {
1879     gp_Sphere theSphere;
1880     Handle(Geom_SphericalSurface) aSphSurf;
1881     TopoDS_Wire SphereWire;
1882     BB.MakeWire(SphereWire);
1883     TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key());
1884     const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex);
1885     TopTools_ListIteratorOfListOfShape itFaces(Faces);
1886     Standard_Boolean isFirstFace = Standard_True;
1887     gp_Pnt FirstPoint;
1888     TopoDS_Vertex theFirstVertex, CurFirstVertex;
1889     for (; itFaces.More(); itFaces.Next())
1890       {
1891         TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First());
1892         TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace));
1893         for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
1894           {
1895             DegEdge = TopoDS::Edge(Explo.Current());
1896             if (BRep_Tool::Degenerated(DegEdge))
1897               {
1898                 TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) );
1899                 TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1900                 if (VF.IsSame(anApex))
1901                   break;
1902               }
1903           }
1904         TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD);
1905         TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape);
1906         BB.Degenerated(CurEdge, Standard_False);
1907         BB.SameRange(CurEdge, Standard_False);
1908         BB.SameParameter(CurEdge, Standard_False);
1909         gp_Pnt fPnt, lPnt, mPnt;
1910         GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt);
1911         Standard_Real f, l;
1912         BRep_Tool::Range(CurEdge, f, l);
1913         if (isFirstFace)
1914           {
1915             gp_Vec aVec1(fPnt, mPnt);
1916             gp_Vec aVec2(fPnt, lPnt);
1917             gp_Vec aNorm = aVec1.Crossed(aVec2);
1918             gp_Pnt theApex = BRep_Tool::Pnt(anApex);
1919             gp_Vec ApexToFpnt(theApex, fPnt);
1920             gp_Vec Ydir = aNorm ^ ApexToFpnt;
1921             gp_Vec Xdir = Ydir ^ aNorm;
1922             //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f);
1923             gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir));
1924             theSphere.SetRadius(myOffset);
1925             theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/);
1926             aSphSurf = new Geom_SphericalSurface(theSphere);
1927             FirstPoint = fPnt;
1928             theFirstVertex = BRepLib_MakeVertex(fPnt);
1929             CurFirstVertex = theFirstVertex;
1930           }
1931
1932         TopoDS_Vertex v1, v2, FirstVert, EndVert;
1933         TopExp::Vertices(CurEdge, v1, v2);
1934         FirstVert = CurFirstVertex;
1935         if (lPnt.Distance(FirstPoint) <= Precision::Confusion())
1936           EndVert = theFirstVertex;
1937         else
1938           EndVert = BRepLib_MakeVertex(lPnt);
1939         CurEdge.Free( Standard_True );
1940         BB.Remove(CurEdge, v1);
1941         BB.Remove(CurEdge, v2);
1942         BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD));
1943         BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED));
1944         //take the curve from sphere an put it to the edge
1945         Standard_Real Uf, Vf, Ul, Vl;
1946         ElSLib::Parameters( theSphere, fPnt, Uf, Vf );
1947         ElSLib::Parameters( theSphere, lPnt, Ul, Vl );
1948         if (Abs(Ul) <= Precision::Confusion())
1949           Ul = 2.*M_PI;
1950         Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
1951         /*
1952         if (!isFirstFace)
1953           {
1954             gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
1955             if (Abs(Uf - f) > Precision::Confusion())
1956               {
1957                 aCircle.Rotate(aCircle.Axis(), f - Uf);
1958                 aCurv = new Geom_Circle(aCircle);
1959               }
1960           }
1961         */
1962         Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul);
1963         BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion());
1964         BB.Range(CurEdge, Uf, Ul, Standard_True);
1965         Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() );
1966         Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul);
1967         BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion());
1968         BB.Range(CurEdge, aSphSurf, L, Uf, Ul);
1969         BRepLib::SameParameter(CurEdge);
1970         BB.Add(SphereWire, CurEdge);
1971         //Modifying correspondent edges in aFace: substitute vertices common with CurEdge
1972         BRepAdaptor_Curve2d BAc2d(CurEdge, aFace);
1973         gp_Pnt2d fPnt2d, lPnt2d;
1974         fPnt2d = BAc2d.Value(BAc2d.FirstParameter());
1975         lPnt2d = BAc2d.Value(BAc2d.LastParameter());
1976         TopTools_IndexedMapOfShape Emap;
1977         TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
1978         TopoDS_Edge EE [2];
1979         Standard_Integer j = 0, k;
1980         for (k = 1; k <= Emap.Extent(); k++)
1981           {
1982             const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k));
1983             if (!BRep_Tool::Degenerated(anEdge))
1984               {
1985                 TopoDS_Vertex V1, V2;
1986                 TopExp::Vertices(anEdge, V1, V2);
1987                 if (V1.IsSame(v1) || V2.IsSame(v1))
1988                   EE[j++] = anEdge;
1989               }
1990           }
1991         for (k = 0; k < j; k++)
1992           {
1993             TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD);
1994             TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
1995             Eforward.Free(Standard_True);
1996             TopoDS_Vertex V1, V2;
1997             TopExp::Vertices( Eforward, V1, V2 );
1998             BRepAdaptor_Curve2d EEc( Eforward, aFace );
1999             gp_Pnt2d p2d1, p2d2;
2000             p2d1 = EEc.Value(EEc.FirstParameter());
2001             p2d2 = EEc.Value(EEc.LastParameter());
2002             if (V1.IsSame(v1))
2003               {
2004                 TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())?
2005                   FirstVert : EndVert;
2006                 BB.Remove( Eforward, V1 );
2007                 BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) );
2008               }
2009             else
2010               {
2011                 TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())?
2012                   FirstVert : EndVert;
2013                 BB.Remove( Eforward, V2 );
2014                 BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) );
2015               }
2016           }
2017
2018         isFirstFace = Standard_False;
2019         CurFirstVertex = EndVert;
2020       }
2021     //Building new spherical face
2022     Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
2023     gp_Pnt2d p2d1, p2d2;
2024     TopTools_ListOfShape EdgesOfWire;
2025     TopoDS_Iterator itw(SphereWire);
2026     for (; itw.More(); itw.Next())
2027       {
2028         const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2029         EdgesOfWire.Append(anEdge);
2030         Standard_Real f, l;
2031         Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l);
2032         p2d1 = aC2d->Value(f);
2033         p2d2 = aC2d->Value(l);
2034         if (p2d1.X() < Ufirst)
2035           Ufirst = p2d1.X();
2036         if (p2d1.X() > Ulast)
2037           Ulast = p2d1.X();
2038         if (p2d2.X() < Ufirst)
2039           Ufirst = p2d2.X();
2040         if (p2d2.X() > Ulast)
2041           Ulast = p2d2.X();
2042       }
2043     TopTools_ListOfShape NewEdges;
2044     TopoDS_Edge FirstEdge;
2045     TopTools_ListIteratorOfListOfShape itl(EdgesOfWire);
2046     for (; itl.More(); itl.Next())
2047       {
2048         FirstEdge = TopoDS::Edge(itl.Value());
2049         Standard_Real f, l;
2050         Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l);
2051         p2d1 = aC2d->Value(f);
2052         p2d2 = aC2d->Value(l);
2053         if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion())
2054           {
2055             EdgesOfWire.Remove(itl);
2056             break;
2057           }
2058       }
2059     NewEdges.Append(FirstEdge);
2060     TopoDS_Vertex Vf1, CurVertex;
2061     TopExp::Vertices(FirstEdge, Vf1, CurVertex);
2062     itl.Initialize(EdgesOfWire);
2063     while (itl.More())
2064       {
2065         const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2066         TopoDS_Vertex V1, V2;
2067         TopExp::Vertices(anEdge, V1, V2);
2068         if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
2069           {
2070             NewEdges.Append(anEdge);
2071             CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
2072             EdgesOfWire.Remove(itl);
2073           }
2074         else
2075           itl.Next();
2076       }
2077
2078     Standard_Real Vfirst, Vlast;
2079     if (p2d1.Y() > 0.)
2080       {
2081         Vfirst = p2d1.Y(); Vlast = M_PI/2.;
2082       }
2083     else
2084       {
2085         Vfirst = -M_PI/2.; Vlast = p2d1.Y();
2086       }
2087     TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
2088     TopoDS_Edge OldEdge;
2089     for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2090       {
2091         OldEdge = TopoDS::Edge(Explo.Current());
2092         if (!BRep_Tool::Degenerated(OldEdge))
2093           {
2094             BRepAdaptor_Curve2d BAc2d(OldEdge, NewSphericalFace);
2095             p2d1 = BAc2d.Value(BAc2d.FirstParameter());
2096             p2d2 = BAc2d.Value(BAc2d.LastParameter());
2097             if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion() &&
2098                 Abs(p2d2.X() - Ulast)  <= Precision::Confusion())
2099               break;
2100           }
2101       }
2102     TopoDS_Vertex V1, V2;
2103     TopExp::Vertices(OldEdge, V1, V2);
2104     TopTools_ListOfShape LV1, LV2;
2105     LV1.Append(Vf1);
2106     LV2.Append(CurVertex);
2107     BRepTools_Substitution theSubstitutor;
2108     theSubstitutor.Substitute(V1, LV1);
2109     if (!V1.IsSame(V2))
2110       theSubstitutor.Substitute(V2, LV2);
2111     theSubstitutor.Substitute(OldEdge, NewEdges);
2112     theSubstitutor.Build(NewSphericalFace);
2113     if (theSubstitutor.IsCopied(NewSphericalFace))
2114       {
2115         const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace);
2116         NewSphericalFace = TopoDS::Face(listSh.First());
2117       }
2118
2119     //Adding NewSphericalFace to the shell
2120     Explo.Init( myOffsetShape, TopAbs_SHELL );
2121     TopoDS_Shape theShell = Explo.Current();
2122     theShell.Free( Standard_True );
2123     BB.Add( theShell, NewSphericalFace );
2124   }
2125
2126   Explo.Init( myOffsetShape, TopAbs_SHELL );
2127
2128   if (Explo.More()) {
2129     TopoDS_Shape theShell = Explo.Current();
2130     theShell.Closed( Standard_True );
2131   }
2132
2133 /*
2134   //Reconstructing
2135   BRep_Builder BB;
2136   for (i = 1; i <= Cones.Length(); i++)
2137     {
2138       TopoDS_Face Cone = TopoDS::Face( Cones(i) );
2139       TopoDS_Edge Circ = TopoDS::Edge( Circs(i) );
2140       TopoDS_Edge Seam = TopoDS::Edge( Seams(i) );
2141       if (Circ.IsNull()) //case 1 with big offset
2142         {
2143           //ExtraFace is absent
2144           
2145           Handle(Geom_Surface) aSurf = BRep_Tool::Surface( Cone ), OffSurf = aSurf;
2146
2147           if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2148             aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface();
2149           gp_Cone theCone = (Handle(Geom_ConicalSurface)::DownCast(aSurf))->Cone();
2150           gp_Pnt apex = theCone.Apex();
2151           Standard_Real Uapex, Vapex;
2152           ElSLib::Parameters( theCone, apex, Uapex, Vapex );
2153           if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2154             apex = OffSurf->Value( Uapex, Vapex );
2155
2156           //Making new degenerated edge
2157           Handle(Geom2d_Line) theLine = GCE2d_MakeLine( gp_Pnt2d( 0., Vapex ), gp_Pnt2d( 2.*M_PI, Vapex ) );
2158           TopoDS_Edge NewEdge;
2159           BB.MakeEdge( NewEdge );
2160           NewEdge.Orientation(TopAbs_FORWARD);
2161           BB.UpdateEdge( NewEdge, theLine, Cone, Precision::Confusion() );
2162           BB.Range( NewEdge, 0., 2.*M_PI );
2163           BB.SameParameter( NewEdge, Standard_True );
2164           BB.SameRange( NewEdge, Standard_True );
2165           BB.Degenerated( NewEdge, Standard_True );
2166           TopoDS_Vertex Apex = BRepLib_MakeVertex( apex );
2167           BB.Add( NewEdge, Apex.Oriented(TopAbs_FORWARD) );
2168           BB.Add( NewEdge, Apex.Oriented(TopAbs_REVERSED) );
2169
2170           //Reconstructing Seam
2171           Standard_Real f, l, par, cpar;
2172           Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( Seam, Cone, f, l );
2173           gp_Lin2d aLine = (Handle(Geom2d_Line)::DownCast(theCurve))->Lin2d();
2174           par = ElCLib::Parameter( aLine, gp_Pnt2d( Uapex, Vapex ) );
2175           TopoDS_Shape aLocalShape = Seam.Oriented(TopAbs_FORWARD);
2176           TopoDS_Vertex cver = TopExp::LastVertex( TopoDS::Edge(aLocalShape) );
2177           cpar = BRep_Tool::Parameter( cver, Seam, Cone );
2178           if (Abs(f-cpar) < Abs(l-cpar))
2179             BB.Range( Seam, par, l );
2180           else
2181             BB.Range( Seam, f, par );
2182           Seam.Free( Standard_True );
2183           TopoDS_Shape cver1;
2184           TopoDS_Iterator iter( Seam );
2185           for (; iter.More(); iter.Next())
2186             {
2187               cver1 = iter.Value();
2188               if (cver1.IsSame(cver))
2189                 break;
2190             }
2191           BB.Remove( Seam, cver1 );
2192           if (Abs(f-cpar) < Abs(l-cpar))
2193             BB.Add( Seam, Apex.Oriented( TopAbs::Compose(Seam.Orientation(),TopAbs_FORWARD) ) );
2194           else
2195             BB.Add( Seam, Apex.Oriented( TopAbs::Compose(Seam.Orientation(),TopAbs_REVERSED) ) );
2196
2197           //Adding NewEdge into Cone
2198           TopoDS_Shape theWire;
2199           for (fexp.Init( Cone, TopAbs_WIRE ); fexp.More(); fexp.Next())
2200             {
2201               theWire = fexp.Current();
2202               Standard_Boolean found = Standard_False;
2203               for (iter.Initialize( theWire ); iter.More(); iter.Next())
2204                 {
2205                   if (Seam.IsSame( iter.Value() ))
2206                     {
2207                       found = Standard_True;
2208                       break;
2209                     }
2210                 }
2211               if (found)
2212                 break;
2213             }
2214           theWire.Free( Standard_True );
2215           NewEdge.Orientation( TopAbs::Compose(theWire.Orientation(),TopAbs_REVERSED) );
2216           BB.Add( theWire, NewEdge );
2217         } //end of case 1 with big offset
2218       else
2219         {
2220           Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Circ.TShape());
2221           if (! TE->Degenerated()) //case 1
2222             {
2223               //Find ExtraFace
2224               TopoDS_Face ExtraFace;
2225               for (fexp.Init( myOffsetShape, TopAbs_FACE ); fexp.More(); fexp.Next())
2226                 {
2227                   ExtraFace = TopoDS::Face( fexp.Current() );
2228                   if (ExtraFace.IsSame( Cone ))
2229                     continue;
2230                   Standard_Boolean found = Standard_False;
2231                   TopExp_Explorer eexp( ExtraFace, TopAbs_EDGE );
2232                   for (; eexp.More(); eexp.Next())
2233                     if (Circ.IsSame( eexp.Current() ))
2234                       {
2235                         found = Standard_True;
2236                         break;
2237                       }
2238                   if (found)
2239                     break;
2240                 }
2241               
2242               Handle(Geom_Surface) aSurf = BRep_Tool::Surface( Cone ), OffSurf = aSurf;
2243               if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2244                 aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface();
2245               gp_Cone theCone = (Handle(Geom_ConicalSurface)::DownCast(aSurf))->Cone();
2246               gp_Pnt apex = theCone.Apex();
2247               Standard_Real Uapex, Vapex;
2248               ElSLib::Parameters( theCone, apex, Uapex, Vapex );
2249               if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2250                 apex = OffSurf->Value( Uapex, Vapex );
2251               
2252               //Making new degenerated edge
2253               Handle(Geom2d_Line) theLine = GCE2d_MakeLine( gp_Pnt2d( 0., Vapex ), gp_Pnt2d( 2.*M_PI, Vapex ) );
2254               TopoDS_Edge NewEdge;
2255               BB.MakeEdge( NewEdge );
2256               NewEdge.Orientation(TopAbs_FORWARD);
2257               BB.UpdateEdge( NewEdge, theLine, Cone, BRep_Tool::Tolerance( Circ ) );
2258               BB.Range( NewEdge, 0., 2.*M_PI );
2259               BB.SameParameter( NewEdge, Standard_True );
2260               BB.SameRange( NewEdge, Standard_True );
2261               BB.Degenerated( NewEdge, Standard_True );
2262               TopoDS_Vertex Apex = BRepLib_MakeVertex( apex );
2263               BB.Add( NewEdge, Apex.Oriented(TopAbs_FORWARD) );
2264               BB.Add( NewEdge, Apex.Oriented(TopAbs_REVERSED) );
2265               
2266               TopoDS_Vertex cver = TopExp::FirstVertex( Circ );
2267               
2268               //Reconstructing Seam
2269               Standard_Real f, l, par, cpar;
2270               Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( Seam, Cone, f, l );
2271               gp_Lin2d aLine = (Handle(Geom2d_Line)::DownCast(theCurve))->Lin2d();
2272               par = ElCLib::Parameter( aLine, gp_Pnt2d( Uapex, Vapex ) );
2273               cpar = BRep_Tool::Parameter( cver, Seam, Cone );
2274               if (Abs(f-cpar) < Abs(l-cpar))
2275                 BB.Range( Seam, par, l );
2276               else
2277                 BB.Range( Seam, f, par );
2278               Seam.Free( Standard_True );
2279               TopoDS_Shape cver1;
2280               TopoDS_Iterator iter( Seam );
2281               for (; iter.More(); iter.Next())
2282                 {
2283                   cver1 = iter.Value();
2284                   if (cver1.IsSame(cver))
2285                     break;
2286                 }
2287               BB.Remove( Seam, cver1 );
2288               if (Abs(f-cpar) < Abs(l-cpar))
2289                 BB.Add( Seam, Apex.Oriented( TopAbs::Compose(Seam.Orientation(),TopAbs_FORWARD) ) );
2290               else
2291                 BB.Add( Seam, Apex.Oriented( TopAbs::Compose(Seam.Orientation(),TopAbs_REVERSED) ) );
2292               
2293               //Removing ExtraFace from the shell
2294               fexp.Init( myOffsetShape, TopAbs_SHELL );
2295               TopoDS_Shape theShell = fexp.Current();
2296               theShell.Free( Standard_True );
2297               TopoDS_Shape ExtraFace1;
2298               for (iter.Initialize( theShell ); iter.More(); iter.Next())
2299                 {
2300                   ExtraFace1 = iter.Value();
2301                   if (ExtraFace1.IsSame(ExtraFace))
2302                     break;
2303                 }
2304               BB.Remove( theShell, ExtraFace1 );
2305               
2306               //Substitute Circ by NewEdge in Cone
2307               TopoDS_Shape theWire;
2308               TopoDS_Shape Circ1;
2309               for (fexp.Init( Cone, TopAbs_WIRE ); fexp.More(); fexp.Next())
2310                 {
2311                   theWire = fexp.Current();
2312                   Standard_Boolean found = Standard_False;
2313                   for (iter.Initialize( theWire ); iter.More(); iter.Next())
2314                     {
2315                       Circ1 = iter.Value();
2316                       if (Circ1.IsSame(Circ))
2317                         {
2318                           found = Standard_True;
2319                           break;
2320                         }
2321                     }
2322                   if (found)
2323                     break;
2324                 }
2325               TopAbs_Orientation Or = Circ1.Orientation();
2326               theWire.Free( Standard_True );
2327               BB.Remove( theWire, Circ1 );
2328               BB.Add( theWire, NewEdge.Oriented(Or) );
2329             } //end of case 1
2330           else // Circ is degenerated
2331             {
2332               if (myOffset > 0. && myJoin == GeomAbs_Arc) //case 2
2333                 {
2334                   TopoDS_Vertex cver = TopExp::FirstVertex( Circ );
2335                   
2336                   TopoDS_Face OrCone = TopoDS::Face( myInitOffsetFace.Root( Cone ) );
2337                   Handle(Geom_Surface) aSurf = BRep_Tool::Surface( OrCone ), OffSurf = aSurf;
2338                   if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2339                     aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface();
2340                   gp_Cone theCone = (Handle(Geom_ConicalSurface)::DownCast(aSurf))->Cone();
2341                   gp_Pnt apex = theCone.Apex();
2342                   if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2343                     {
2344                       Standard_Real Uapex, Vapex;
2345                       ElSLib::Parameters( theCone, apex, Uapex, Vapex );
2346                       apex = OffSurf->Value( Uapex, Vapex );
2347                     }
2348
2349                   Standard_Real f, l;
2350                   Handle(Geom_Curve) ccur = BRep_Tool::Curve( Circ, f, l );
2351                   gp_Ax2 Axe2 = (Handle(Geom_Circle)::DownCast(ccur))->Circ().Position();
2352                   gp_Ax3 Axe3( Axe2 );
2353                   Axe3.SetLocation( apex );
2354                   gp_Sphere theSphere( Axe3, myOffset );
2355
2356                   gp_Pnt OrPnt = BRep_Tool::Pnt(cver);
2357                   Standard_Real Uor, Vor;
2358                   ElSLib::Parameters( theSphere, OrPnt, Uor, Vor );
2359                   TopoDS_Face NewFace;
2360                   if (Vor > 0.)
2361                     NewFace = BRepLib_MakeFace( theSphere, 0., 2.*M_PI, Vor, M_PI/2. );
2362                   else
2363                     NewFace = BRepLib_MakeFace( theSphere, 0., 2.*M_PI, -M_PI/2., Vor );
2364                   
2365                   //Updating the bound of NewFace
2366                   TopoDS_Edge Bound;
2367                   TopExp_Explorer eexp( NewFace, TopAbs_EDGE );
2368                   for (; eexp.More(); eexp.Next())
2369                     {
2370                       Bound = TopoDS::Edge( eexp.Current() );
2371                       Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Bound.TShape());
2372                       if (!TE->Degenerated() && !BRepTools::IsReallyClosed( Bound, NewFace ))
2373                         break;
2374                     }
2375                   Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( Circ, Cone, f, l );
2376                   BB.UpdateEdge( Bound, pcurve, Cone, BRep_Tool::Tolerance(Circ) );
2377                   TopoDS_Vertex bver = TopExp::FirstVertex( Bound );
2378                   BB.UpdateVertex( bver, BRep_Tool::Tolerance(cver) );
2379                   
2380                   //Updating cver in Seam
2381                   TopoDS_Vertex cver1;
2382                   TopoDS_Iterator iter( Seam );
2383                   for (; iter.More(); iter.Next())
2384                     {
2385                       cver1 = TopoDS::Vertex( iter.Value() );
2386                       if (cver1.IsSame(cver))
2387                         break;
2388                     }
2389                   TopAbs_Orientation Or = cver1.Orientation();
2390                   Seam.Free( Standard_True );
2391                   BB.Remove( Seam, cver1 );
2392                   BB.Add( Seam, bver.Oriented(Or) );
2393                   
2394                   //Substitute Circ by Bound in Cone
2395                   TopoDS_Shape theWire;
2396                   TopoDS_Shape Circ1;
2397                   for (fexp.Init( Cone, TopAbs_WIRE ); fexp.More(); fexp.Next())
2398                     {
2399                       theWire = fexp.Current();
2400                       Standard_Boolean found = Standard_False;
2401                       for (iter.Initialize( theWire ); iter.More(); iter.Next())
2402                         {
2403                           Circ1 = iter.Value();
2404                           if (Circ1.IsSame(Circ))
2405                             {
2406                               found = Standard_True;
2407                               break;
2408                             }
2409                         }
2410                       if (found)
2411                         break;
2412                     }
2413                   Or = Circ1.Orientation();
2414                   theWire.Free( Standard_True );
2415                   BB.Remove( theWire, Circ1 );
2416                   BB.Add( theWire, Bound.Oriented(Or) );
2417                   
2418                   //Adding NewFace to the shell
2419                   fexp.Init( myOffsetShape, TopAbs_SHELL );
2420                   TopoDS_Shape theShell = fexp.Current();
2421                   theShell.Free( Standard_True );
2422                   BB.Add( theShell, NewFace );
2423                   
2424                   theShell.Closed( Standard_True );
2425                 } //end of case 2
2426               else // if ((myOffset > 0. && myJoin == GeomAbs_Intersection) || myOffset < 0.) //case 3, 4
2427                 {
2428                   Handle(Geom_Surface) aSurf = BRep_Tool::Surface( Cone ), OffSurf = aSurf;
2429                   if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2430                     aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface();
2431                   gp_Cone theCone = (Handle(Geom_ConicalSurface)::DownCast(aSurf))->Cone();
2432                   gp_Pnt apex = theCone.Apex();
2433                   Standard_Real Uapex, Vapex;
2434                   ElSLib::Parameters( theCone, apex, Uapex, Vapex );
2435                   if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2436                     apex = OffSurf->Value( Uapex, Vapex );
2437                   
2438                   //Making new degenerated edge
2439                   Handle(Geom2d_Line) theLine = GCE2d_MakeLine( gp_Pnt2d( 0., Vapex ), gp_Pnt2d( 2.*M_PI, Vapex ) );
2440                   TopoDS_Edge NewEdge;
2441                   BB.MakeEdge( NewEdge );
2442                   NewEdge.Orientation(TopAbs_FORWARD);
2443                   BB.UpdateEdge( NewEdge, theLine, Cone, BRep_Tool::Tolerance( Circ ) );
2444                   BB.Range( NewEdge, 0., 2.*M_PI );
2445                   BB.SameParameter( NewEdge, Standard_True );
2446                   BB.SameRange( NewEdge, Standard_True );
2447                   BB.Degenerated( NewEdge, Standard_True );
2448                   TopoDS_Vertex Apex = BRepLib_MakeVertex( apex );
2449                   BB.Add( NewEdge, Apex.Oriented(TopAbs_FORWARD) );
2450                   BB.Add( NewEdge, Apex.Oriented(TopAbs_REVERSED) );
2451                   
2452                   TopoDS_Vertex cver = TopExp::FirstVertex( Circ );
2453                   
2454                   //Reconstructing Seam
2455                   Standard_Real f, l, par, cpar;
2456                   Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( Seam, Cone, f, l );
2457                   gp_Lin2d aLine = (Handle(Geom2d_Line)::DownCast(theCurve))->Lin2d();
2458                   par = ElCLib::Parameter( aLine, gp_Pnt2d( Uapex, Vapex ) );
2459                   cpar = BRep_Tool::Parameter( cver, Seam, Cone );
2460                   if (Abs(f-cpar) < Abs(l-cpar))
2461                     BB.Range( Seam, par, l );
2462                   else
2463                     BB.Range( Seam, f, par );
2464                   Seam.Free( Standard_True );
2465                   TopoDS_Shape cver1;
2466                   TopoDS_Iterator iter( Seam );
2467                   for (; iter.More(); iter.Next())
2468                     {
2469                       cver1 = iter.Value();
2470                       if (cver1.IsSame(cver))
2471                         break;
2472                     }
2473                   BB.Remove( Seam, cver1 );
2474                   if (Abs(f-cpar) < Abs(l-cpar))
2475                     BB.Add( Seam, Apex.Oriented( TopAbs::Compose(Seam.Orientation(),TopAbs_FORWARD) ) );
2476                   else
2477                     BB.Add( Seam, Apex.Oriented( TopAbs::Compose(Seam.Orientation(),TopAbs_REVERSED) ) );
2478                   
2479                   //Substitute Circ by NewEdge in Cone
2480                   TopoDS_Shape theWire;
2481                   TopoDS_Shape Circ1;
2482                   for (fexp.Init( Cone, TopAbs_WIRE ); fexp.More(); fexp.Next())
2483                     {
2484                       theWire = fexp.Current();
2485                       Standard_Boolean found = Standard_False;
2486                       for (iter.Initialize( theWire ); iter.More(); iter.Next())
2487                         {
2488                           Circ1 = iter.Value();
2489                           if (Circ1.IsSame(Circ))
2490                             {
2491                               found = Standard_True;
2492                               break;
2493                             }
2494                         }
2495                       if (found)
2496                         break;
2497                     }
2498                   TopAbs_Orientation Or = Circ1.Orientation();
2499                   theWire.Free( Standard_True );
2500                   BB.Remove( theWire, Circ1 );
2501                   BB.Add( theWire, NewEdge.Oriented(Or) );
2502                   
2503                   fexp.Init( myOffsetShape, TopAbs_SHELL );
2504                   TopoDS_Shape theShell = fexp.Current();
2505                   theShell.Closed( Standard_True );
2506                 } //end of case 3, 4
2507             }
2508         } //else (! Circ.IsNull())
2509     }
2510 */
2511
2512   Standard_Integer            NbShell = 0;
2513   TopoDS_Compound             NC;
2514   TopoDS_Shape                S1;
2515   BB.MakeCompound (NC);
2516   
2517   for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) {
2518     const TopoDS_Shell& Sh = TopoDS::Shell(Explo.Current());
2519     NbShell++;
2520     if (Sh.Closed()) {
2521       TopoDS_Solid  Sol;
2522       BB.MakeSolid  (Sol);
2523       BB.Add        (Sol,Sh);
2524       Sol.Closed(Standard_True);
2525       BB.Add (NC,Sol);
2526       if (NbShell == 1) S1 = Sol;
2527     }
2528     else {
2529       BB.Add (NC,Sh);
2530       if (NbShell == 1) S1 = Sh;
2531     }
2532   }
2533   if (NbShell == 1) myOffsetShape = S1;
2534   else              myOffsetShape = NC;
2535 }
2536
2537
2538 //=======================================================================
2539 //function : Intersection3D
2540 //purpose  : 
2541 //=======================================================================
2542
2543 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
2544 {
2545 #ifdef DEB
2546   if (ChronBuild) {
2547     cout << " INTERSECTION 3D:" << endl;
2548     Clock.Reset();
2549     Clock.Start();  
2550   }
2551 #endif
2552   TopTools_ListOfShape OffsetFaces;  // list of faces // created.
2553   MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2554
2555   if (!myFaces.IsEmpty()) {     
2556     Standard_Boolean InSide = (myOffset < 0.); // Temporary
2557     // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2558     // between the cap and the part.
2559
2560     if (myJoin == GeomAbs_Arc) 
2561       Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge);
2562   }
2563   if (myInter) {
2564     //-------------
2565     //Complete.
2566     //-------------
2567     Inter.CompletInt (OffsetFaces,myInitOffsetFace);
2568     TopTools_MapOfShape& NewEdges = Inter.NewEdges();
2569     if (myJoin == GeomAbs_Intersection) {
2570       BRepOffset_Tool::CorrectOrientation (myShape,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2571     }
2572   }
2573   else {
2574     //--------------------------------
2575     // Only between neighbor faces.
2576     //--------------------------------
2577     Inter.ConnexIntByArc(OffsetFaces,myShape,myAnalyse,myInitOffsetFace);
2578   }
2579 #ifdef DEB
2580   if ( ChronBuild) Clock.Show();
2581 #endif
2582 }
2583
2584 //=======================================================================
2585 //function : Intersection2D
2586 //purpose  : 
2587 //=======================================================================
2588
2589 void BRepOffset_MakeOffset::Intersection2D(const TopTools_MapOfShape& Modif,
2590                                            const TopTools_MapOfShape& NewEdges)
2591 {
2592 #ifdef DEB
2593   if (ChronBuild) {
2594     cout << " INTERSECTION 2D:" << endl;
2595     Clock.Reset();
2596     Clock.Start();  
2597   }
2598 #endif
2599   //--------------------------------------------------------
2600   // calculate intersections2d on faces concerned by 
2601   // intersection3d
2602   //--------------------------------------------------------
2603   TopTools_MapIteratorOfMapOfShape it(Modif);
2604   //-----------------------------------------------
2605   // Intersection of edges 2 by 2.
2606   //-----------------------------------------------
2607   for ( it.Initialize(Modif); it.More(); it.Next()) {
2608     const TopoDS_Face&                 F  = TopoDS::Face(it.Key());
2609     BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol);
2610   }
2611
2612 #ifdef DEB
2613   if (AffichInt2d) {
2614     DEBVerticesControl (NewEdges,myAsDes);
2615   }
2616   if ( ChronBuild) Clock.Show();
2617 #endif
2618 }
2619
2620
2621 //=======================================================================
2622 //function : MakeLoops
2623 //purpose  : 
2624 //=======================================================================
2625
2626 void BRepOffset_MakeOffset::MakeLoops(TopTools_MapOfShape& Modif)
2627 {
2628 #ifdef DEB
2629   if (ChronBuild) {
2630      cout << " DEBOUCLAGE 2D:" << endl;
2631      Clock.Reset();
2632      Clock.Start(); 
2633   }
2634 #endif
2635   TopTools_MapIteratorOfMapOfShape    it(Modif);
2636   TopTools_ListOfShape                LF,LC;
2637   //-----------------------------------------
2638   // unwinding of faces // modified.
2639   //-----------------------------------------
2640   for (; it.More(); it.Next()) { 
2641     if (!myFaces.Contains(it.Key())) LF.Append(it.Key());
2642   }
2643   myMakeLoops.Build(LF,myAsDes,myImageOffset);
2644
2645   //-----------------------------------------
2646   // unwinding of caps.
2647   //-----------------------------------------
2648   for (it.Initialize(myFaces); it.More(); it.Next()) { 
2649     LC.Append(it.Key());
2650   }
2651   Standard_Boolean   InSide = 1;
2652   if (myOffset > 0 ) InSide = 0;
2653   myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide);
2654
2655 #ifdef DEB
2656   if ( ChronBuild) Clock.Show();
2657 #endif
2658 }
2659
2660 //=======================================================================
2661 //function : MakeFaces
2662 //purpose  : Reconstruction of topologically unchanged faces that
2663 //           share edges that were reconstructed.
2664 //=======================================================================
2665
2666 void BRepOffset_MakeOffset::MakeFaces(TopTools_MapOfShape& Modif)
2667 {
2668 #ifdef DEb
2669   if (ChronBuild) {  
2670     cout << " RECONSTRUCTION OF FACES:" << endl;
2671     Clock.Reset();
2672     Clock.Start();
2673   }
2674 #endif
2675   TopTools_ListIteratorOfListOfShape itr;
2676   const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
2677   TopTools_ListOfShape        LOF;
2678   //----------------------------------
2679   // Loop on all faces //.
2680   //----------------------------------
2681   for (itr.Initialize(Roots); itr.More(); itr.Next()) {
2682     TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
2683     LOF.Append(F);
2684   }
2685   myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
2686   
2687 #ifdef DEB
2688   if ( ChronBuild) Clock.Show();
2689 #endif
2690 }
2691
2692 //=======================================================================
2693 //function : UpdateInitOffset
2694 //purpose  : Update and cleaning of myInitOffset 
2695 //=======================================================================
2696
2697 static void UpdateInitOffset (BRepAlgo_Image&         myInitOffset,
2698                               BRepAlgo_Image&         myImageOffset,
2699                               const TopoDS_Shape&     myOffsetShape,
2700                               const TopAbs_ShapeEnum &theShapeType) // skv
2701 {
2702   BRepAlgo_Image NIOF;
2703   const TopTools_ListOfShape& Roots = myInitOffset.Roots();
2704   TopTools_ListIteratorOfListOfShape it(Roots);
2705   for (; it.More(); it.Next()) {
2706     NIOF.SetRoot (it.Value());    
2707   }
2708   for (it.Initialize(Roots); it.More(); it.Next()) {
2709     const TopoDS_Shape& SI = it.Value();
2710     TopTools_ListOfShape LI;
2711     TopTools_ListOfShape L1;
2712     myInitOffset.LastImage(SI,L1);
2713     TopTools_ListIteratorOfListOfShape itL1(L1);
2714     for (; itL1.More(); itL1.Next()) {
2715       const TopoDS_Shape& O1 = itL1.Value();
2716       TopTools_ListOfShape L2;
2717       myImageOffset.LastImage(O1,L2);
2718       LI.Append(L2);
2719     }
2720     NIOF.Bind(SI,LI);
2721   }
2722 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
2723 //  Supporting history.
2724 //   NIOF.Filter(myOffsetShape,TopAbs_FACE);
2725   NIOF.Filter(myOffsetShape, theShapeType);
2726 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
2727   myInitOffset = NIOF;
2728 }
2729
2730 //=======================================================================
2731 //function : MakeMissingWalls
2732 //purpose  : 
2733 //=======================================================================
2734
2735 void BRepOffset_MakeOffset::MakeMissingWalls ()
2736 {
2737   TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
2738   TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
2739   Standard_Real OffsetVal = Abs(myOffset);
2740
2741   FillContours(myShape, myAnalyse, Contours, MapEF);
2742
2743   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(Contours);
2744   for (; iter.More(); iter.Next())
2745     {
2746       TopoDS_Vertex StartVertex = TopoDS::Vertex(iter.Key());
2747       TopoDS_Edge StartEdge;
2748       const TopTools_ListOfShape& aContour = iter.Value();
2749       TopTools_ListIteratorOfListOfShape itl(aContour);
2750       Standard_Boolean FirstStep = Standard_True;
2751       TopoDS_Edge PrevEdge;
2752       TopoDS_Vertex PrevVertex = StartVertex;
2753       for (; itl.More(); itl.Next())
2754         {
2755           TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2756           if (!myInitOffsetEdge.HasImage(anEdge))
2757             continue;
2758           //if (BRep_Tool::Degenerated(anEdge))
2759             //continue;
2760           TopoDS_Face aFace = TopoDS::Face(MapEF(anEdge));
2761           //TopoDS_Edge OE = TopoDS::Edge(myInitOffsetEdge.Image(anEdge).First());
2762           TopTools_ListOfShape LOE, LOE2;
2763           myInitOffsetEdge.LastImage( anEdge, LOE );
2764           myImageOffset.LastImage( LOE.Last(), LOE2 );
2765           TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
2766           ////////////////////////////////////////////////////////////////////////
2767           TopoDS_Vertex V1, V2, V3, V4;
2768           TopExp::Vertices(anEdge, V1, V2/*, Standard_True*/);
2769           TopExp::Vertices(OE,     V4, V3/*, Standard_True*/);
2770           Standard_Boolean ToReverse = Standard_False;
2771           if (!V1.IsSame(PrevVertex))
2772             {
2773               TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
2774               aVtx = V3; V3 = V4; V4 = aVtx;
2775               ToReverse = Standard_True;
2776             }
2777           //Temporary
2778           //anEdge.Reverse();
2779           OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
2780           TopoDS_Edge E3, E4;
2781           if (FirstStep)
2782             {
2783               E4 = BRepLib_MakeEdge( V1, V4 );
2784               StartEdge = E4;
2785             }
2786           else
2787             E4 = PrevEdge;
2788           Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
2789           if (V2.IsSame(StartVertex) && !ArcOnV2)
2790             E3 = StartEdge;
2791           else
2792             E3 = BRepLib_MakeEdge( V2, V3 );
2793           E4.Reverse();
2794           TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
2795           const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
2796           Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
2797           Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
2798           BRep_Builder BB;
2799           TopoDS_Wire theWire;
2800           BB.MakeWire(theWire);
2801           if (ToReverse)
2802             {
2803               BB.Add(theWire, anEdge.Reversed());
2804               BB.Add(theWire, E3.Reversed());
2805               BB.Add(theWire, OE.Reversed());
2806               BB.Add(theWire, E4.Reversed());
2807             }
2808           else
2809             {
2810               BB.Add(theWire, anEdge);
2811               BB.Add(theWire, E3);
2812               BB.Add(theWire, OE);
2813               BB.Add(theWire, E4);
2814             }
2815           BRepLib::BuildCurves3d( theWire, myTol );
2816           theWire.Closed(Standard_True);
2817           TopoDS_Face NewFace;
2818           Handle(Geom_Surface) theSurf;
2819           BRepAdaptor_Curve BAcurve(anEdge);
2820           BRepAdaptor_Curve BAcurveOE(OE);
2821           Standard_Real fpar = BAcurve.FirstParameter();
2822           Standard_Real lpar = BAcurve.LastParameter();
2823           gp_Pnt PonE  = BAcurve.Value(fpar);
2824           gp_Pnt PonOE = BAcurveOE.Value(fpar);
2825           gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
2826           Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
2827           Standard_Boolean IsPlanar = Standard_False;
2828           if (BAcurve.GetType() == GeomAbs_Circle &&
2829               BAcurveOE.GetType() == GeomAbs_Circle)
2830           {
2831             gp_Circ aCirc = BAcurve.Circle();
2832             gp_Circ aCircOE = BAcurveOE.Circle();
2833             gp_Lin anAxisLine(aCirc.Axis());
2834             gp_Dir CircAxisDir = aCirc.Axis().Direction();
2835             if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
2836                 anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
2837             { //cylinder or cone
2838               if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
2839                 theSurf = GC_MakeCylindricalSurface(aCirc).Value();
2840               else //case of cone
2841               {
2842                 gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
2843                                                aCirc.Radius(), aCircOE.Radius());
2844                 gp_Ax3 theAx3(aCirc.Position());
2845                 if (CircAxisDir * theCone.Axis().Direction() < 0.)
2846                 {
2847                   theAx3.ZReverse();
2848                   CircAxisDir.Reverse();
2849                 }
2850                 theCone.SetPosition(theAx3);
2851                 theSurf = new Geom_ConicalSurface(theCone);
2852               }
2853               TopLoc_Location Loc;
2854               EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
2855               BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2856               Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
2857               OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
2858               BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2859               aLine2d  = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
2860               aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
2861               if (E3.IsSame(E4))
2862               {
2863                 if (Coeff > 0.)
2864                   BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2865                 else
2866                 {
2867                   BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
2868                   theWire.Nullify();
2869                   BB.MakeWire(theWire);
2870                   BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
2871                   BB.Add(theWire, E4);
2872                   BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
2873                   BB.Add(theWire, E3);
2874                   theWire.Closed(Standard_True);
2875                 }
2876               }
2877               else
2878               {
2879                 BB.SameParameter(E3, Standard_False);
2880                 BB.SameRange(E3, Standard_False);
2881                 BB.SameParameter(E4, Standard_False);
2882                 BB.SameRange(E4, Standard_False);
2883                 BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2884                 BB.Range(E3, theSurf, Loc, 0., OffsetVal);
2885                 BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2886                 BB.Range(E4, theSurf, Loc, 0., OffsetVal);
2887               }
2888               NewFace = BRepLib_MakeFace(theSurf, theWire);
2889             } //cylinder or cone
2890           } //if both edges are arcs of circles
2891           if (NewFace.IsNull())
2892             {
2893               BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
2894               if (MF.Error() == BRepLib_FaceDone)
2895                 {
2896                   NewFace = MF.Face();
2897                   IsPlanar = Standard_True;
2898                 }
2899               else //Extrusion (by thrusections)
2900                 {
2901                   Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
2902                   Handle(Geom_TrimmedCurve) TrEdgeCurve =
2903                     new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
2904                   Standard_Real fparOE, lparOE;
2905                   Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
2906                   Handle(Geom_TrimmedCurve) TrOffsetCurve =
2907                     new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
2908                   GeomFill_Generator ThrusecGenerator;
2909                   ThrusecGenerator.AddCurve( TrEdgeCurve );
2910                   ThrusecGenerator.AddCurve( TrOffsetCurve );
2911                   ThrusecGenerator.Perform( Precision::PConfusion() );
2912                   theSurf = ThrusecGenerator.Surface();
2913                   //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
2914                   Standard_Real Uf, Ul, Vf, Vl;
2915                   theSurf->Bounds(Uf, Ul, Vf, Vl);
2916                   TopLoc_Location Loc;
2917                   EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
2918                   BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2919                   OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
2920                   BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2921                   Standard_Real UonV1 = (ToReverse)? Ul : Uf;
2922                   Standard_Real UonV2 = (ToReverse)? Uf : Ul;
2923                   aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
2924                   aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
2925                   if (E3.IsSame(E4))
2926                     {
2927                       BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2928                       Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
2929                       BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
2930                       BB.Range(E3, Vf, Vl);
2931                     }
2932                   else
2933                     {
2934                       BB.SameParameter(E3, Standard_False);
2935                       BB.SameRange(E3, Standard_False);
2936                       BB.SameParameter(E4, Standard_False);
2937                       BB.SameRange(E4, Standard_False);
2938                       BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2939                       BB.Range(E3, theSurf, Loc, Vf, Vl);
2940                       BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2941                       BB.Range(E4, theSurf, Loc, Vf, Vl);
2942                       Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
2943                       BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
2944                       BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
2945                       Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
2946                       BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
2947                       BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
2948                     }
2949                   NewFace = BRepLib_MakeFace(theSurf, theWire);
2950                 }
2951             }
2952           if (!IsPlanar)
2953             {
2954               Standard_Real fparOE = BAcurveOE.FirstParameter();
2955               Standard_Real lparOE = BAcurveOE.LastParameter();
2956               TopLoc_Location Loc;
2957               if (Abs(fpar - fparOE) > Precision::Confusion())
2958                 {
2959                   const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
2960                   gp_Pnt2d fp2d   = EdgeLine2d->Value(fpar);
2961                   gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
2962                   aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
2963                   Handle(Geom_Curve) aCurve;
2964                   Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
2965                   Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
2966                   GeomAdaptor_Surface GAsurf( theSurf );
2967                   Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2968                   Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2969                   Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2970                   Standard_Real max_deviation = 0., average_deviation;
2971                   GeomLib::BuildCurve3d(Precision::Confusion(),
2972                                         ConS, FirstPar, LastPar,
2973                                         aCurve, max_deviation, average_deviation);
2974                   BB.UpdateEdge( anE4, aCurve, max_deviation );
2975                   BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
2976                   BB.Range( anE4, FirstPar, LastPar );
2977                 }
2978               if (Abs(lpar - lparOE) > Precision::Confusion())
2979                 {
2980                   const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
2981                   gp_Pnt2d lp2d   = EdgeLine2d->Value(lpar);
2982                   gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
2983                   aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
2984                   Handle(Geom_Curve) aCurve;
2985                   Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
2986                   Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
2987                   GeomAdaptor_Surface GAsurf( theSurf );
2988                   Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2989                   Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2990                   Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2991                   Standard_Real max_deviation = 0., average_deviation;
2992                   GeomLib::BuildCurve3d(Precision::Confusion(),
2993                                         ConS, FirstPar, LastPar,
2994                                         aCurve, max_deviation, average_deviation);
2995                   BB.UpdateEdge( anE3, aCurve, max_deviation );
2996                   BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
2997                   BB.Range( anE3, FirstPar, LastPar );
2998                 }
2999             }
3000           BRepLib::SameParameter(NewFace);
3001           BRepTools::Update(NewFace);
3002           myWalls.Append(NewFace);
3003           if (ArcOnV2)
3004             {
3005               TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
3006               TopoDS_Vertex arcV1, arcV2;
3007               TopExp::Vertices(anArc, arcV1, arcV2);
3008               Standard_Boolean ArcReverse = Standard_False;
3009               if (!arcV1.IsSame(V3))
3010                 {
3011                   TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
3012                   ArcReverse = Standard_True;
3013                 }
3014               TopoDS_Edge EA1, EA2;
3015               //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
3016               EA1 = E3;
3017               EA1.Reverse();
3018               if (ToReverse)
3019                 EA1.Reverse();
3020               //////////////////////////////////////////////////////
3021               if (V2.IsSame(StartVertex))
3022                 EA2 = StartEdge;
3023               else
3024                 EA2 = BRepLib_MakeEdge( V2, arcV2 );
3025               anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
3026               if (EA1.Orientation() == TopAbs_REVERSED)
3027                 anArc.Reverse();
3028               EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
3029               TopoDS_Wire arcWire;
3030               BB.MakeWire(arcWire);
3031               BB.Add(arcWire, EA1);
3032               BB.Add(arcWire, anArc);
3033               BB.Add(arcWire, EA2);
3034               BRepLib::BuildCurves3d( arcWire, myTol );
3035               arcWire.Closed(Standard_True);
3036               TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
3037               BRepTools::Update(arcFace);
3038               myWalls.Append(arcFace);
3039               TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
3040               const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
3041               PrevEdge = CEA2;
3042               PrevVertex = V2;
3043             }
3044           else
3045             {
3046               PrevEdge = E3;
3047               PrevVertex = V2;
3048             }
3049           FirstStep = Standard_False;
3050         }
3051     }
3052 }
3053
3054 //=======================================================================
3055 //function : MakeShells
3056 //purpose  : 
3057 //=======================================================================
3058
3059 void BRepOffset_MakeOffset::MakeShells ()
3060 {
3061 #ifdef DEB
3062   if (ChronBuild) {  
3063     cout << " RECONSTRUCTION OF SHELLS:" << endl;
3064     Clock.Reset();
3065     Clock.Start();
3066   }
3067 #endif
3068   BRepTools_Quilt Glue;
3069   const TopTools_ListOfShape& R = myImageOffset.Roots();
3070   TopTools_ListIteratorOfListOfShape it(R);
3071
3072   for ( ; it.More(); it.Next()) {
3073     TopTools_ListOfShape Image;
3074     myImageOffset.LastImage(it.Value(),Image);
3075     TopTools_ListIteratorOfListOfShape it2(Image);
3076     for ( ; it2.More(); it2.Next()) {
3077       Glue.Add(it2.Value());
3078     }
3079   }
3080
3081   if (myThickening)
3082     {
3083       TopExp_Explorer Explo(myShape, TopAbs_FACE);
3084       for (; Explo.More(); Explo.Next())
3085         Glue.Add(Explo.Current());
3086       
3087       for (it.Initialize(myWalls); it.More(); it.Next())
3088         Glue.Add(it.Value());
3089     }
3090
3091   myOffsetShape = Glue.Shells();
3092 }
3093
3094 //=======================================================================
3095 //function : MakeSolid
3096 //purpose  : 
3097 //=======================================================================
3098
3099 void BRepOffset_MakeOffset::MakeSolid ()
3100 {
3101  if (myOffsetShape.IsNull()) return;
3102
3103 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
3104 //  Supporting history.
3105   UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
3106   UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
3107 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
3108   TopExp_Explorer             exp;
3109   BRep_Builder                B;
3110   Standard_Integer            NbShell = 0;
3111   TopoDS_Compound             NC;
3112   TopoDS_Shape                S1;
3113   B.MakeCompound (NC);
3114
3115   for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
3116     TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
3117     if (myThickening && myOffset > 0.)
3118       Sh.Reverse();
3119     NbShell++;
3120     if (Sh.Closed()) {
3121       TopoDS_Solid  Sol;
3122       B.MakeSolid  (Sol);
3123       B.Add        (Sol,Sh);
3124       Sol.Closed(Standard_True);
3125       B.Add (NC,Sol);
3126       if (NbShell == 1) S1 = Sol;
3127     }
3128     else {
3129       B.Add (NC,Sh);
3130       if (NbShell == 1) S1 = Sh;
3131     }
3132   }
3133   if (NbShell == 1) myOffsetShape = S1;
3134   else              myOffsetShape = NC;
3135 }
3136
3137 //=======================================================================
3138 //function : SelectShells
3139 //purpose  : 
3140 //=======================================================================
3141
3142 void BRepOffset_MakeOffset::SelectShells ()
3143 {  
3144   TopTools_MapOfShape FreeEdges;
3145   TopExp_Explorer exp(myShape,TopAbs_EDGE);
3146   //-------------------------------------------------------------
3147   // FreeEdges all edges that can have free border in the  
3148   // parallel shell
3149   // 1 - free borders of myShape .
3150   //-------------------------------------------------------------
3151   for ( ; exp.More(); exp.Next()) {
3152     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3153     const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
3154     if (LA.Extent() < 2) {
3155       if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
3156         FreeEdges.Add(E);                       
3157       }
3158     }  
3159   }
3160   // myShape has free borders and there are no caps
3161   // no unwinding 3d.
3162   if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
3163
3164   myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
3165 }
3166
3167 //=======================================================================
3168 //function : OffsetFacesFromShapes
3169 //purpose  : 
3170 //=======================================================================
3171
3172 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
3173 {
3174   return myInitOffsetFace;
3175 }
3176
3177 //  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
3178
3179 //=======================================================================
3180 //function : GetJoinType
3181 //purpose  : Query offset join type.
3182 //=======================================================================
3183
3184 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
3185 {
3186   return myJoin;
3187 }
3188
3189 //=======================================================================
3190 //function : OffsetEdgesFromShapes
3191 //purpose  : 
3192 //=======================================================================
3193
3194 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
3195 {
3196   return myInitOffsetEdge;
3197 }
3198
3199 //  Modified by skv - Tue Mar 15 16:20:43 2005 End
3200
3201 //=======================================================================
3202 //function : ClosingFaces
3203 //purpose  : 
3204 //=======================================================================
3205
3206 const TopTools_MapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
3207 {
3208   return myFaces;
3209 }
3210
3211
3212
3213 //=======================================================================
3214 //function : EncodeRegularity
3215 //purpose  : 
3216 //=======================================================================
3217
3218 void BRepOffset_MakeOffset::EncodeRegularity ()
3219 {
3220 #ifdef DEB
3221   if (ChronBuild) {  
3222     cout << " CODING OF REGULARITIES:" << endl;
3223     Clock.Reset();
3224     Clock.Start();
3225   }
3226 #endif
3227
3228   if (myOffsetShape.IsNull()) return;
3229   // find edges G1 in the result
3230   TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
3231
3232   BRep_Builder B;
3233   TopTools_MapOfShape MS;
3234
3235   for ( ; exp.More(); exp.Next()) {
3236     TopoDS_Edge OE  = TopoDS::Edge(exp.Current());
3237     BRepLib::BuildCurve3d(OE,myTol);
3238     TopoDS_Edge ROE = OE;
3239     
3240     if ( !MS.Add(OE)) continue;
3241       
3242     if ( myImageOffset.IsImage(OE)) 
3243       ROE = TopoDS::Edge(myImageOffset.Root(OE));
3244
3245     const TopTools_ListOfShape& LofOF    = myAsDes->Ascendant(ROE);
3246     
3247     if (LofOF.Extent() != 2) {
3248 #ifdef DEB
3249       if ( Standard_False)
3250         cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
3251 #endif
3252       continue;
3253     }
3254
3255     const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
3256     const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
3257     
3258     if ( F1.IsNull() || F2.IsNull()) 
3259       continue;
3260    
3261     const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
3262     const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
3263
3264     TopAbs_ShapeEnum Type1 = Root1.ShapeType();
3265     TopAbs_ShapeEnum Type2 = Root2.ShapeType();
3266  
3267     if (F1.IsSame(F2)) {      
3268       if (BRep_Tool::IsClosed(OE,F1)) {
3269         // Temporary Debug for the Bench.
3270         // Check with YFR.
3271         // In mode intersection, the edges are not coded in myInitOffsetEdge
3272         // so, manage case by case
3273         // Note DUB; for Hidden parts, it is NECESSARY to code CN 
3274         // Analytic Surfaces.
3275         if (myJoin == GeomAbs_Intersection) {
3276           BRepAdaptor_Surface BS(F1,Standard_False);
3277           GeomAbs_SurfaceType SType = BS.GetType();
3278           if (SType == GeomAbs_Cylinder ||
3279               SType == GeomAbs_Cone     ||
3280               SType == GeomAbs_Sphere   ||
3281               SType == GeomAbs_Torus      ) {
3282             B.Continuity(OE,F1,F1,GeomAbs_CN);
3283           }
3284           else {
3285             // See YFR : MaJ of myInitOffsetFace
3286           }
3287         }
3288         else if (myInitOffsetEdge.IsImage(ROE)) {
3289           if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3290             const TopoDS_Face& FRoot = TopoDS::Face(Root1);
3291             const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
3292             GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
3293             if (Conti == GeomAbs_CN) {
3294               B.Continuity(OE,F1,F1,GeomAbs_CN);
3295             }
3296             else if ( Conti > GeomAbs_C0) {
3297               B.Continuity(OE,F1,F1,GeomAbs_G1);
3298             }
3299           }
3300         }
3301       }
3302       continue;
3303     }
3304
3305
3306     //  code regularities G1 between :
3307     //    - sphere and tube : one root is a vertex, the other is an edge 
3308     //                        and the vertex is included in the edge
3309     //    - face and tube   : one root is a face, the other an edge 
3310     //                        and the edge is included in the face
3311     //    - face and face    : if two root faces are tangent in 
3312     //                        the initial shape, they will be tangent in the offset shape
3313     //    - tube and tube  : if 2 edges generating tubes are
3314     //                        tangents, the 2 will be tangent either.
3315     if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3316       TopoDS_Vertex V1,V2;
3317       TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3318       if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3319         B.Continuity(OE,F1,F2,GeomAbs_G1);
3320       }
3321     }
3322     else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3323       TopoDS_Vertex V1,V2;
3324       TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3325       if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3326         B.Continuity(OE,F1,F2,GeomAbs_G1);
3327       }
3328     }
3329     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3330       TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3331       for ( ; exp2.More(); exp2.Next()) {
3332         if ( exp2.Current().IsSame(Root2)) {
3333           B.Continuity(OE,F1,F2,GeomAbs_G1);
3334           break;
3335         }
3336       }
3337     }
3338     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
3339       TopExp_Explorer exp2(Root2,TopAbs_EDGE);
3340       for ( ; exp2.More(); exp2.Next()) {
3341         if ( exp2.Current().IsSame(Root1)) {
3342           B.Continuity(OE,F1,F2,GeomAbs_G1);
3343           break;
3344         }
3345       }
3346     }
3347     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3348     //  if two root faces are tangent in 
3349     //  the initial shape, they will be tangent in the offset shape
3350       TopTools_ListOfShape LE,LV;
3351       BRepOffset_Tool::HasCommonShapes(TopoDS::Face(Root1),
3352                                        TopoDS::Face(Root2),
3353                                        LE,LV);
3354       if ( LE.Extent() == 1) { 
3355         const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
3356         if ( myAnalyse.HasAncestor(Ed)) {
3357           const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
3358           if (LI.Extent()       == 1   && 
3359               LI.First().Type() == BRepOffset_Tangent) {
3360             B.Continuity(OE,F1,F2,GeomAbs_G1);
3361           }
3362         }
3363       }
3364     }
3365     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
3366       TopTools_ListOfShape LV;
3367       TopExp_Explorer exp1,exp2;
3368       for (exp1.Init(Root1,TopAbs_VERTEX); exp1.More(); exp1.Next()) {
3369         TopExp_Explorer exp2(F2,TopAbs_EDGE);
3370         for (exp2.Init(Root2,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
3371           if (exp1.Current().IsSame(exp2.Current())) {
3372             LV.Append(exp1.Current());
3373           }
3374         }
3375       }
3376       if ( LV.Extent() == 1) {
3377         TopTools_ListOfShape LEdTg;
3378         myAnalyse.TangentEdges(TopoDS::Edge(Root1),
3379                                TopoDS::Vertex(LV.First()),
3380                                LEdTg);
3381         TopTools_ListIteratorOfListOfShape it(LEdTg);
3382         for (; it.More(); it.Next()) {
3383           if ( it.Value().IsSame(Root2)) {
3384             B.Continuity(OE,F1,F2,GeomAbs_G1);
3385             break;
3386           }
3387         }
3388       }
3389     }
3390   }
3391
3392 #ifdef DEB
3393   if ( ChronBuild) Clock.Show();
3394 #endif
3395 }
3396
3397
3398
3399 //=======================================================================
3400 //function : UpDateTolerance
3401 //purpose  : 
3402 //=======================================================================
3403
3404 static void UpdateTolerance (TopoDS_Shape& S,
3405                              const TopTools_MapOfShape& Faces)
3406 {
3407   BRep_Builder B;
3408   TopTools_MapOfShape View;
3409   TopoDS_Vertex V[2];
3410
3411   // The edges of caps are not modified.
3412   TopTools_MapIteratorOfMapOfShape it;
3413   for (it.Initialize(Faces); it.More(); it.Next()) {
3414     const TopoDS_Shape& F = it.Key();
3415     TopExp_Explorer Exp;
3416     for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3417       View.Add(Exp.Current());
3418     }
3419   }
3420   
3421   TopExp_Explorer Exp;
3422   for (Exp.Init(S,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3423     TopoDS_Edge E = TopoDS::Edge(Exp.Current());
3424     if (View.Add(E)) {
3425       Handle(BRepCheck_Edge) EdgeCorrector = new BRepCheck_Edge(E);
3426       Standard_Real    Tol = EdgeCorrector->Tolerance();
3427       B.UpdateEdge (E,Tol);
3428       
3429       // Update the vertices.
3430       TopExp::Vertices(E,V[0],V[1]);
3431      
3432       for (Standard_Integer i = 0 ; i <=1 ; i++) {
3433         if (View.Add(V[i])) {
3434           Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
3435           TV->Tolerance(0.);
3436           Handle(BRepCheck_Vertex) VertexCorrector = new BRepCheck_Vertex(V[i]);
3437           B.UpdateVertex (V[i],VertexCorrector->Tolerance());
3438           // use the occasion to clean the vertices.
3439           (TV->ChangePoints()).Clear();
3440         }
3441         B.UpdateVertex(V[i],Tol);
3442       }
3443     }
3444   }
3445 }
3446