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