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