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