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