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