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