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