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