0028903: BRepOffset_MakeOffset produces invalid shape (thickshell) in Intersection...
[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 TopAbs_Orientation OrientationOfEdgeInFace(const TopoDS_Edge& theEdge,
325                                                   const TopoDS_Face& theFace)
326 {
327   TopAbs_Orientation anOr = TopAbs_EXTERNAL;
328   
329   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
330   for (; Explo.More(); Explo.Next())
331   {
332     const TopoDS_Shape& anEdge = Explo.Current();
333     if (anEdge.IsSame(theEdge))
334     {
335       anOr = anEdge.Orientation();
336       break;
337     }
338   }
339
340   return anOr;
341 }
342
343 //
344 static Standard_Boolean FindParameter(const TopoDS_Vertex& V, 
345                                       const TopoDS_Edge& E,
346                                       Standard_Real& U)
347 {
348   // Search the vertex in the edge
349
350   Standard_Boolean rev = Standard_False;
351   TopoDS_Shape VF;
352   TopAbs_Orientation orient = TopAbs_INTERNAL;
353
354   TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
355
356   // if the edge has no vertices
357   // and is degenerated use the vertex orientation
358   // RLE, june 94
359
360   if (!itv.More() && BRep_Tool::Degenerated(E)) {
361     orient = V.Orientation();
362   }
363
364   while (itv.More()) {
365     const TopoDS_Shape& Vcur = itv.Value();
366     if (V.IsSame(Vcur)) {
367       if (VF.IsNull()) {
368         VF = Vcur;
369       }
370       else {
371         rev = E.Orientation() == TopAbs_REVERSED;
372         if (Vcur.Orientation() == V.Orientation()) {
373           VF = Vcur;
374         }
375       }
376     }
377     itv.Next();
378   }
379   
380   if (!VF.IsNull()) orient = VF.Orientation();
381  
382   Standard_Real f,l;
383
384   if (orient ==  TopAbs_FORWARD) {
385     BRep_Tool::Range(E,f,l);
386     //return (rev) ? l : f;
387     U = (rev) ? l : f;
388     return Standard_True;
389   }
390  
391   else if (orient ==  TopAbs_REVERSED) {
392     BRep_Tool::Range(E,f,l);
393     //return (rev) ? f : l;
394     U = (rev) ? f : l;
395     return Standard_True;
396    }
397
398   else {
399     TopLoc_Location L;
400     const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
401     L = L.Predivided(V.Location());
402     if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
403       BRep_ListIteratorOfListOfPointRepresentation itpr
404         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
405
406       while (itpr.More()) {
407         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
408         if (pr->IsPointOnCurve(C,L)) {
409           Standard_Real p = pr->Parameter();
410           Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
411           if (!C.IsNull()) {
412             // Closed curves RLE 16 june 94
413             if (Precision::IsNegativeInfinite(f))
414               {
415                 //return pr->Parameter();//p;
416                 U = pr->Parameter();
417                 return Standard_True;
418               }
419             if (Precision::IsPositiveInfinite(l))
420               {
421                 //return pr->Parameter();//p;
422                 U = pr->Parameter();
423                 return Standard_True;
424               }
425             gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
426             gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
427             Standard_Real tol = BRep_Tool::Tolerance(V);
428             if (Pf.Distance(Pl) < tol) {
429               if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
430                 if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
431                 else                                   res = l;//p = l;
432               }
433             }
434           }
435           //return res;//p;
436           U = res;
437           return Standard_True;
438         }
439         itpr.Next();
440       }
441     }
442     else {
443       // no 3d curve !!
444       // let us try with the first pcurve
445       Handle(Geom2d_Curve) PC;
446       Handle(Geom_Surface) S;
447       BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
448       L = L.Predivided(V.Location()); 
449       BRep_ListIteratorOfListOfPointRepresentation itpr
450         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
451
452       while (itpr.More()) {
453         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
454         if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
455           Standard_Real p = pr->Parameter();
456           // Closed curves RLE 16 june 94
457           if (PC->IsClosed()) {
458             if ((p == PC->FirstParameter()) || 
459                 (p == PC->LastParameter())) {
460               if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
461               else                                   p = PC->LastParameter();
462             }
463           }
464           //return p;
465           U = p;
466           return Standard_True;
467         }
468         itpr.Next();
469       }
470     }
471   }
472   
473   //throw Standard_NoSuchObject("BRep_Tool:: no parameter on edge");
474   return Standard_False;
475 }
476
477 //=======================================================================
478 //function : GetEdgePoints
479 //purpose  : gets the first, last and middle points of the edge
480 //=======================================================================
481 static void GetEdgePoints(const TopoDS_Edge& anEdge,
482                                       const TopoDS_Face& aFace,
483                                       gp_Pnt& fPnt, gp_Pnt& mPnt,
484                                       gp_Pnt& lPnt)
485 {
486   Standard_Real f, l;
487   Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
488   gp_Pnt2d fPnt2d = theCurve->Value(f);
489   gp_Pnt2d lPnt2d = theCurve->Value(l);
490   gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
491   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
492   fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
493   lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
494   mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
495 }
496
497 //=======================================================================
498 //function : FillContours
499 //purpose  : fills free boundary contours and faces connected (MapEF)
500 //=======================================================================
501 static void FillContours(const TopoDS_Shape& aShape,
502                          const BRepOffset_Analyse& Analyser,
503                          TopTools_IndexedDataMapOfShapeListOfShape& Contours,
504                          TopTools_DataMapOfShapeShape& MapEF)
505 {
506   TopTools_ListOfShape Edges;
507
508   TopExp_Explorer Explo(aShape, TopAbs_FACE);
509   BRepTools_WireExplorer Wexp;
510
511   for (; Explo.More(); Explo.Next())
512     {
513       TopoDS_Face aFace = TopoDS::Face(Explo.Current());
514       TopoDS_Iterator itf(aFace);
515       for (; itf.More(); itf.Next())
516         {
517           TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
518           for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
519             {
520               TopoDS_Edge anEdge = Wexp.Current();
521               if (BRep_Tool::Degenerated(anEdge))
522                 continue;
523               const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
524               if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary)
525                 {
526                   MapEF.Bind(anEdge, aFace);
527                   Edges.Append(anEdge);
528                 }
529             }
530         }
531     }
532
533   TopTools_ListIteratorOfListOfShape itl;
534   while (!Edges.IsEmpty())
535     {
536       TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
537       Edges.RemoveFirst();
538       TopoDS_Vertex StartVertex, CurVertex;
539       TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
540       TopTools_ListOfShape aContour;
541       aContour.Append(StartEdge);
542       while (!CurVertex.IsSame(StartVertex))
543         for (itl.Initialize(Edges); itl.More(); itl.Next())
544           {
545             TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
546             TopoDS_Vertex V1, V2;
547             TopExp::Vertices(anEdge, V1, V2);
548             if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
549               {
550                 aContour.Append(anEdge);
551                 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
552                 Edges.Remove(itl);
553                 break;
554               }
555           }
556       Contours.Add(StartVertex, aContour);
557     }
558 }
559
560 //
561 //-----------------------------------------------------------------------
562 //
563 //=======================================================================
564 //function : BRepOffset_MakeOffset
565 //purpose  : 
566 //=======================================================================
567
568 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
569 {
570   myAsDes = new BRepAlgo_AsDes();
571 }
572
573
574 //=======================================================================
575 //function : BRepOffset_MakeOffset
576 //purpose  : 
577 //=======================================================================
578
579 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape&    S, 
580                                              const Standard_Real    Offset, 
581                                              const Standard_Real    Tol, 
582                                              const BRepOffset_Mode  Mode, 
583                                              const Standard_Boolean Inter, 
584                                              const Standard_Boolean SelfInter, 
585                                              const GeomAbs_JoinType Join,
586                                              const Standard_Boolean Thickening,
587                                              const Standard_Boolean RemoveIntEdges)
588
589 myOffset     (Offset),
590 myTol        (Tol),
591 myShape      (S),
592 myMode       (Mode),
593 myInter      (Inter),
594 mySelfInter  (SelfInter),
595 myJoin       (Join),
596 myThickening    (Thickening),
597 myRemoveIntEdges(RemoveIntEdges),
598 myDone     (Standard_False)
599 {
600   myAsDes = new BRepAlgo_AsDes();
601   MakeOffsetShape();
602 }
603
604
605 //=======================================================================
606 //function : Initialize
607 //purpose  : 
608 //=======================================================================
609
610 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S, 
611                                        const Standard_Real    Offset, 
612                                        const Standard_Real    Tol, 
613                                        const BRepOffset_Mode  Mode,
614                                        const Standard_Boolean Inter,
615                                        const Standard_Boolean SelfInter,
616                                        const GeomAbs_JoinType Join,
617                                        const Standard_Boolean Thickening,
618                                        const Standard_Boolean RemoveIntEdges)
619 {
620   myOffset     = Offset;
621   myShape      = S;
622   myTol        = Tol;
623   myMode       = Mode;
624   myInter      = Inter;
625   mySelfInter  = SelfInter;
626   myJoin       = Join;
627   myThickening     = Thickening;
628   myRemoveIntEdges = RemoveIntEdges;
629   myDone     = Standard_False;
630   myIsPerformSewing = Standard_False;
631   myIsPlanar = Standard_False;
632   Clear();
633 }
634
635
636 //=======================================================================
637 //function : Clear
638 //purpose  : 
639 //=======================================================================
640
641 void BRepOffset_MakeOffset::Clear()
642 {
643   myOffsetShape.Nullify();
644   myInitOffsetFace .Clear();
645   myInitOffsetEdge .Clear();
646   myImageOffset    .Clear();
647   myFaces          .Clear();  
648   myFaceOffset     .Clear();
649   myAsDes          ->Clear();
650   myDone     = Standard_False;
651 }
652
653 //=======================================================================
654 //function : AddFace
655 //purpose  : 
656 //=======================================================================
657
658 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
659   myFaces.Add(F);    
660   //-------------
661   // MAJ SD.
662   //-------------
663   myInitOffsetFace.SetRoot (F)  ;    
664   myInitOffsetFace.Bind    (F,F);
665   myImageOffset.SetRoot    (F)  ;  
666 }
667
668 //=======================================================================
669 //function : SetOffsetOnFace
670 //purpose  : 
671 //=======================================================================
672
673 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F, 
674                                             const Standard_Real Off)
675 {
676   if ( myFaceOffset.IsBound(F)) myFaceOffset.UnBind(F);
677   myFaceOffset.Bind(F,Off);
678 }
679
680 //=======================================================================
681 //function : RemoveCorks
682 //purpose  : 
683 //=======================================================================
684
685 static void RemoveCorks (TopoDS_Shape&               S,
686                          TopTools_IndexedMapOfShape& Faces)
687 {  
688   TopoDS_Compound SS;
689   BRep_Builder    B;
690   B.MakeCompound (SS);
691   //-----------------------------------------------------
692   // Construction of a shape without caps.
693   // and Orientation of caps as in shape S.
694   //-----------------------------------------------------
695   TopExp_Explorer exp(S,TopAbs_FACE);
696   for (; exp.More(); exp.Next()) {
697     const TopoDS_Shape& Cork = exp.Current(); 
698     if (!Faces.Contains(Cork)) {
699       B.Add(SS,Cork);
700     }
701     else {
702       Faces.RemoveKey(Cork);
703       Faces.Add(Cork); // to reset it with proper orientation.
704     }
705   }
706   S = SS;
707 #ifdef DRAW
708   if ( AffichOffC) 
709     DBRep::Set("myInit", SS);
710 #endif
711
712 }
713
714 //=======================================================================
715 //function : IsConnectedShell
716 //purpose  : 
717 //=======================================================================
718 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
719 {  
720   BRepTools_Quilt Glue;
721   Glue.Add( S );
722
723   TopoDS_Shape SS = Glue.Shells();
724   TopExp_Explorer Explo( SS, TopAbs_SHELL );
725   Explo.Next();
726   if (Explo.More())
727     return Standard_False;
728   
729   return Standard_True;
730 }
731
732
733 //=======================================================================
734 //function : MakeList
735 //purpose  : 
736 //=======================================================================
737
738 static void MakeList (TopTools_ListOfShape&             OffsetFaces,
739                       const BRepAlgo_Image&             myInitOffsetFace,
740                       const TopTools_IndexedMapOfShape& myFaces)
741 {
742   TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
743   for ( ; itLOF.More(); itLOF.Next()) {
744     const TopoDS_Shape& Root = itLOF.Value();
745     if (!myFaces.Contains(Root)) {
746       if (myInitOffsetFace.HasImage(Root)) {
747         TopTools_ListIteratorOfListOfShape aItLS(myInitOffsetFace.Image(Root));
748         for (; aItLS.More(); aItLS.Next()) {
749           OffsetFaces.Append(aItLS.Value());
750         }
751       }
752     }
753   }
754 }
755
756 //=======================================================================
757 //function : EvalMax
758 //purpose  : 
759 //=======================================================================
760
761 static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
762 {
763   TopExp_Explorer exp;
764   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
765     const TopoDS_Vertex& V    = TopoDS::Vertex(exp.Current());
766     Standard_Real        TolV = BRep_Tool::Tolerance(V); 
767     if (TolV > Tol) Tol = TolV;
768   }
769 }
770
771
772 //=======================================================================
773 //function : MakeOffsetShape
774 //purpose  : 
775 //=======================================================================
776
777 void BRepOffset_MakeOffset::MakeOffsetShape()
778 {  
779   myDone = Standard_False;
780   //
781   // check if shape consists of only planar faces
782   myIsPlanar = IsPlanar(myShape);
783   //------------------------------------------
784   // Construction of myShape without caps.
785   //------------------------------------------
786   if(!myFaces.IsEmpty())
787   {
788     RemoveCorks (myShape,myFaces);
789   }
790
791   if (!CheckInputData())
792   {
793     // There is error in input data.
794     // Check Error() method.
795     return;
796   }
797
798   TopAbs_State       Side = TopAbs_IN;
799   if (myOffset < 0.) Side = TopAbs_OUT;
800
801   // ------------
802   // Preanalyse.
803   // ------------
804   EvalMax(myShape,myTol);
805   // There are possible second variant: analytical continuation of arcsin.
806   Standard_Real TolAngleCoeff = Min(myTol / (Abs(myOffset * 0.5) + Precision::Confusion()), 1.0);
807   Standard_Real TolAngle = 4*ASin(TolAngleCoeff);
808   myAnalyse.Perform(myShape,TolAngle);
809   //---------------------------------------------------
810   // Construction of Offset from preanalysis.
811   //---------------------------------------------------  
812   //----------------------------
813   // MaJ of SD Face - Offset
814   //----------------------------
815   UpdateFaceOffset();
816
817   if (myJoin == GeomAbs_Arc)          
818     BuildOffsetByArc();
819   else if (myJoin == GeomAbs_Intersection) 
820     BuildOffsetByInter();
821   //-----------------
822   // Auto unwinding.
823   //-----------------
824   // if (mySelfInter)  SelfInter(Modif);
825   //-----------------
826   // Intersection 3d .
827   //-----------------
828   BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
829   Intersection3D (Inter);
830   //-----------------
831   // Intersection2D
832   //-----------------
833   TopTools_IndexedMapOfShape& Modif    = Inter.TouchedFaces(); 
834   TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
835
836   if (!Modif.IsEmpty()) Intersection2D (Modif,NewEdges);
837   //-------------------------------------------------------
838   // Unwinding 2D and reconstruction of modified faces
839   //----------------------------------------------------
840   MakeLoops (Modif);
841   //-----------------------------------------------------
842   // Reconstruction of non modified faces sharing 
843   // reconstructed edges
844   //------------------------------------------------------
845   if (!Modif.IsEmpty()) MakeFaces (Modif);
846
847   if (myThickening)
848     MakeMissingWalls();
849
850   //-------------------------
851   // Construction of shells.
852   //-------------------------
853   MakeShells ();
854   if (myOffsetShape.IsNull()) {
855     // not done
856     myDone = Standard_False;
857     return;
858   }
859   //--------------
860   // Unwinding 3D.
861   //--------------
862   SelectShells ();
863   //----------------------------------
864   // Remove INTERNAL edges if necessary
865   //----------------------------------
866   if (myRemoveIntEdges) {
867     RemoveInternalEdges();
868   }
869   //----------------------------------
870   // Coding of regularities.
871   //----------------------------------
872   EncodeRegularity();
873   //----------------------
874   // Creation of solids.
875   //----------------------
876   MakeSolid ();
877
878   //-----------------------------
879   // MAJ Tolerance edge and Vertex
880   // ----------------------------
881   if (!myOffsetShape.IsNull()) {
882     UpdateTolerance (myOffsetShape,myFaces);
883     BRepLib::UpdateTolerances( myOffsetShape );
884   }
885
886   CorrectConicalFaces();
887
888   // Result solid should be computed in MakeOffset scope.
889   if (myThickening &&
890       myIsPerformSewing)
891   {
892     BRepBuilderAPI_Sewing aSew(myTol);
893     aSew.Add(myOffsetShape);
894     aSew.Perform();
895     myOffsetShape = aSew.SewedShape();
896
897     // Rebuild solid.
898     // Offset shape expected to be really closed after sewing.
899     myOffsetShape.Closed(Standard_True);
900     MakeSolid();
901   }
902
903   myDone = Standard_True;
904 }
905
906
907
908 //=======================================================================
909 //function : MakeThickSolid
910 //purpose  : 
911 //=======================================================================
912
913 void BRepOffset_MakeOffset::MakeThickSolid() 
914 {
915   //--------------------------------------------------------------
916   // Construction of shell parallel to shell (initial without cap).
917   //--------------------------------------------------------------
918   MakeOffsetShape ();
919
920   if (!myDone)
921   {
922     // Save return code and myDone state.
923     return;
924   }
925
926   //--------------------------------------------------------------------
927   // Construction of a solid with the initial shell, parallel shell 
928   // limited by caps.
929   //--------------------------------------------------------------------
930   if (!myFaces.IsEmpty())
931   {
932     TopoDS_Solid    Res;
933     TopExp_Explorer exp;
934     BRep_Builder    B;
935     Standard_Integer NbF = myFaces.Extent();
936
937     B.MakeSolid(Res);
938
939     BRepTools_Quilt Glue;
940     for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next())
941     {
942       NbF++;
943       Glue.Add (exp.Current());
944     } 
945     Standard_Boolean YaResult = 0;
946     if (!myOffsetShape.IsNull())
947       {
948       for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
949         {
950         YaResult = 1;
951         Glue.Add (exp.Current().Reversed());
952         }
953 #ifdef OCCT_DEBUG
954       if(YaResult == 0)
955         {
956         cout << "OffsetShape does not contain a FACES." << endl;
957         }
958 #endif
959       }
960 #ifdef OCCT_DEBUG
961     else
962       {
963       cout << "OffsetShape is null!" << endl;
964       }
965 #endif
966
967     if (YaResult == 0)
968       {
969       myDone = Standard_False;
970       myError = BRepOffset_UnknownError;
971       return;
972       }
973
974     myOffsetShape = Glue.Shells();
975     for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next())
976     {
977       B.Add(Res,exp.Current());
978     }
979     Res.Closed(Standard_True);
980     myOffsetShape = Res;
981
982     // Test of Validity of the result of thick Solid 
983     // more face than the initial solid.
984     Standard_Integer NbOF = 0;
985     for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
986     {
987       NbOF++;
988     }
989     if (NbOF <= NbF)
990     {
991       myDone = Standard_False;
992       myError = BRepOffset_UnknownError;
993       return;
994     }
995   }
996
997   if (myOffset > 0 ) myOffsetShape.Reverse();
998
999   myDone = Standard_True;
1000 }
1001
1002 //=======================================================================
1003 //function : IsDone
1004 //purpose  : 
1005 //=======================================================================
1006
1007 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
1008 {
1009   return myDone;
1010 }
1011
1012 //=======================================================================
1013 //function : Error
1014 //purpose  : 
1015 //=======================================================================
1016
1017 BRepOffset_Error BRepOffset_MakeOffset::Error() const
1018 {
1019   return myError;
1020 }
1021
1022 //=======================================================================
1023 //function : Shape
1024 //purpose  : 
1025 //=======================================================================
1026
1027 const TopoDS_Shape&  BRepOffset_MakeOffset::Shape() const 
1028 {
1029   return myOffsetShape;
1030 }
1031
1032 //=======================================================================
1033 //function : MakeOffsetFaces
1034 //purpose  : 
1035 //=======================================================================
1036 void BRepOffset_MakeOffset::MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset& theMapSF)
1037 {
1038   Standard_Real aCurOffset;
1039   TopTools_ListOfShape aLF;
1040   TopTools_DataMapOfShapeShape ShapeTgt;
1041   TopTools_ListIteratorOfListOfShape aItLF;
1042   //
1043   Standard_Boolean OffsetOutside = (myOffset > 0.);
1044   //
1045   BRepLib::SortFaces(myShape, aLF);
1046   //
1047   aItLF.Initialize(aLF);
1048   for (; aItLF.More(); aItLF.Next()) {
1049     const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
1050     aCurOffset = myFaceOffset.IsBound(aF) ? myFaceOffset(aF) : myOffset;
1051     BRepOffset_Offset OF(aF, aCurOffset, ShapeTgt, OffsetOutside, myJoin);
1052     TopTools_ListOfShape Let;
1053     myAnalyse.Edges(aF,BRepOffset_Tangent,Let);
1054     TopTools_ListIteratorOfListOfShape itl(Let);    
1055     for (; itl.More(); itl.Next()) {
1056       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1057       if ( !ShapeTgt.IsBound(Cur)) {
1058         TopoDS_Shape aLocalShape = OF.Generated(Cur);
1059         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1060         ShapeTgt.Bind(Cur,OF.Generated(Cur));
1061         TopoDS_Vertex V1,V2,OV1,OV2;
1062         TopExp::Vertices (Cur,V1,V2);
1063         TopExp::Vertices (OTE,OV1,OV2);      
1064         TopTools_ListOfShape LE;
1065         if (!ShapeTgt.IsBound(V1)) {
1066           myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
1067           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
1068           if (LE.Extent() == LA.Extent())
1069             ShapeTgt.Bind(V1,OV1);
1070         }
1071         if (!ShapeTgt.IsBound(V2)) {
1072           LE.Clear();
1073           myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
1074           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
1075           if (LE.Extent() == LA.Extent())
1076             ShapeTgt.Bind(V2,OV2);
1077         }
1078       }
1079     }
1080     theMapSF.Bind(aF,OF);
1081   }
1082 }
1083
1084 //=======================================================================
1085 //function : BuildOffsetByInter
1086 //purpose  : 
1087 //=======================================================================
1088 void BRepOffset_MakeOffset::BuildOffsetByInter()
1089 {
1090 #ifdef OCCT_DEBUG
1091   if ( ChronBuild) {
1092     cout << " CONSTRUCTION OF OFFSETS :" << endl;
1093     Clock.Reset();
1094     Clock.Start();
1095   }
1096 #endif
1097
1098   TopExp_Explorer Exp, Exp2, ExpC;
1099   TopTools_ListIteratorOfListOfShape itLF;
1100   
1101   //--------------------------------------------------------
1102   // Construction of faces parallel to initial faces
1103   //--------------------------------------------------------
1104   BRepOffset_DataMapOfShapeOffset MapSF;
1105   MakeOffsetFaces(MapSF);
1106   //--------------------------------------------------------------------
1107   // MES   : Map of OffsetShape -> Extended Shapes.
1108   // Build : Map of Initial SS  -> OffsetShape build by Inter.
1109   //                               can be an edge or a compound of edges       
1110   //---------------------------------------------------------------------
1111   TopTools_DataMapOfShapeShape MES;  
1112   TopTools_DataMapOfShapeShape Build; 
1113   TopTools_ListOfShape         Failed;
1114   TopAbs_State                 Side = TopAbs_IN;  
1115   Handle(BRepAlgo_AsDes)       AsDes = new BRepAlgo_AsDes();
1116
1117   //-------------------------------------------------------------------
1118   // Extension of faces and calculation of new edges of intersection.
1119   //-------------------------------------------------------------------
1120   Standard_Boolean  ExtentContext = 0;
1121   if (myOffset > 0) ExtentContext = 1;
1122
1123   BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
1124   // Intersection between parallel faces
1125   Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
1126   // Intersection with caps.
1127   Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
1128
1129
1130   //---------------------------------------------------------------------------------
1131   // Extension of neighbor edges of new edges and intersection between neighbors.
1132   //--------------------------------------------------------------------------------
1133   Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
1134   IntersectEdges(myShape, MapSF, MES, Build, AsDes, AsDes2d);
1135   //-----------------------------------------------------------
1136   // Great restriction of new edges and update of AsDes.
1137   //------------------------------------------ ----------------
1138   TopTools_DataMapOfShapeListOfShape anEdgesOrigins; // offset edge - initial edges
1139   TopTools_IndexedMapOfShape NewEdges;
1140   TopTools_DataMapOfShapeShape aETrimEInf; // trimmed - not trimmed edges
1141   //
1142   //Map of edges obtained after FACE-FACE (offsetted) intersection.
1143   //Key1 is edge trimmed by intersection points with other edges;
1144   //Item is not-trimmed edge. 
1145   TrimEdges(myShape, myOffset, MapSF, MES, Build, AsDes, AsDes2d, NewEdges, aETrimEInf, anEdgesOrigins);
1146   //
1147   //--------------------------------- 
1148   // Intersection 2D on //
1149   //---------------------------------  
1150   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
1151   TopTools_DataMapOfShapeShape aFacesOrigins; // offset face - initial face
1152   TopTools_ListOfShape LFE; 
1153   BRepAlgo_Image     IMOE;
1154   GetEnlargedFaces(myShape, MapSF, MES, aFacesOrigins, IMOE, LFE);
1155   //
1156   TopTools_ListIteratorOfListOfShape itLFE(LFE);
1157   for (; itLFE.More(); itLFE.Next())
1158   {
1159     const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
1160     Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF);
1161     BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, aDMVV);
1162   }
1163   //----------------------------------------------
1164   // Intersections 2d on caps.
1165   //----------------------------------------------
1166   Standard_Integer i;
1167   for (i = 1; i <= myFaces.Extent(); i++)
1168   {
1169     const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
1170     Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork);
1171     BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, aDMVV);
1172   }
1173   //
1174   BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes);
1175   //-------------------------------
1176   // Unwinding of extended Faces.
1177   //-------------------------------
1178   //
1179   TopTools_MapOfShape aMFDone;
1180   //
1181   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
1182     BuildSplitsOfExtendedFaces(LFE, AsDes, anEdgesOrigins, aFacesOrigins, aETrimEInf, IMOE);
1183     //
1184     TopTools_ListIteratorOfListOfShape aItLF(LFE);
1185     for (; aItLF.More(); aItLF.Next()) {
1186       const TopoDS_Shape& aS = aItLF.Value();
1187       aMFDone.Add(aS);
1188     }
1189   }
1190   else {
1191     myMakeLoops.Build(LFE, AsDes, IMOE);
1192   }
1193   //
1194 #ifdef OCCT_DEBUG
1195   TopTools_IndexedMapOfShape COES;
1196 #endif
1197   //---------------------------
1198   // MAJ SD. for faces //
1199   //---------------------------
1200   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1201     const TopoDS_Shape& FI   = Exp.Current();
1202     myInitOffsetFace.SetRoot(FI);
1203     TopoDS_Face  OF  = MapSF(FI).Face();
1204     if (MES.IsBound(OF)) {
1205       OF = TopoDS::Face(MES(OF));
1206       if (IMOE.HasImage(OF)) {
1207         const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
1208         myInitOffsetFace.Bind(FI,LOFE);
1209         for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
1210           const TopoDS_Shape& OFE =  itLF.Value();
1211           myImageOffset.SetRoot(OFE);
1212 #ifdef DRAW
1213           if (AffichInt2d) {
1214             sprintf(name,"AF_%d",NbAF++);
1215             DBRep::Set(name,OFE);
1216           }
1217 #endif
1218           TopTools_MapOfShape View;
1219           for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1220                Exp2.More(); Exp2.Next()) {
1221             const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1222             
1223             myAsDes->Add (OFE,COE);
1224 #ifdef DRAW
1225             if (AffichInt2d) {
1226               sprintf(name,"AE_%d",NbAE++);
1227               DBRep::Set(name,COE);
1228               COES.Add(COE);
1229             }
1230 #endif
1231             if (View.Add(COE)){
1232               if (!myAsDes->HasDescendant(COE)) {
1233                 TopoDS_Vertex CV1,CV2;
1234                 TopExp::Vertices(COE,CV1,CV2);
1235                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1236                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
1237               }
1238             }
1239           }
1240         }
1241       }
1242       else {
1243         if (aMFDone.Contains(OF)) {
1244           continue;
1245         }
1246         //
1247         myInitOffsetFace.Bind(FI,OF);
1248         myImageOffset.SetRoot(OF);
1249 #ifdef DRAW 
1250         if (AffichInt2d) {
1251           sprintf(name,"AF_%d",NbAF++);
1252           DBRep::Set(name,OF);
1253         }
1254 #endif
1255         const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
1256         for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1257           const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1258           if (IMOE.HasImage(OE)) {
1259             const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1260             TopTools_ListIteratorOfListOfShape itLOE(LOE);
1261             for (; itLOE.More(); itLOE.Next()) {
1262               TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
1263               const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
1264 //              const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
1265               myAsDes->Add(OF,COE);
1266 #ifdef DRAW
1267               if (AffichInt2d) {
1268                 sprintf(name,"AE_%d",NbAE++);
1269                 DBRep::Set(name,COE);
1270                 COES.Add(COE);
1271               }
1272 #endif
1273               
1274               if (!myAsDes->HasDescendant(COE)) {
1275                 TopoDS_Vertex CV1,CV2;
1276                 TopExp::Vertices(COE,CV1,CV2);
1277                  if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1278                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
1279               }
1280             }
1281           }
1282           else {
1283             myAsDes->Add(OF,OE);
1284 #ifdef DRAW
1285             if (AffichInt2d) {
1286               sprintf(name,"AE_%d",NbAE++);
1287               DBRep::Set(name,OE);
1288               COES.Add(OE);
1289             }
1290 #endif
1291
1292             const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
1293             myAsDes->Add(OE,LV);
1294           }
1295         }
1296       }
1297     }
1298     else {
1299       myInitOffsetFace.Bind(FI,OF);
1300       myImageOffset.SetRoot(OF);
1301       TopTools_MapOfShape View;
1302       for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1303            Exp2.More(); Exp2.Next()) {
1304
1305         const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1306         myAsDes->Add (OF,COE);
1307 #ifdef DRAW
1308         if (AffichInt2d) {
1309           sprintf(name,"AE_%d",NbAE++);
1310           DBRep::Set(name,COE);
1311           COES.Add(COE);
1312         }
1313 #endif
1314         
1315         if (View.Add(Exp2.Current())) {
1316           if (!myAsDes->HasDescendant(COE)) {
1317             TopoDS_Vertex CV1,CV2;
1318             TopExp::Vertices(COE,CV1,CV2);
1319             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1320             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));        
1321           }
1322         }
1323       } 
1324     }
1325   }
1326   //  Modified by skv - Tue Mar 15 16:20:43 2005
1327   // Add methods for supporting history.
1328   TopTools_MapOfShape aMapEdges;
1329
1330   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1331     const TopoDS_Shape& aFaceRef = Exp.Current();
1332
1333     Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1334
1335     for (; Exp2.More(); Exp2.Next()) {
1336       const TopoDS_Shape& anEdgeRef = Exp2.Current();
1337
1338       if (aMapEdges.Add(anEdgeRef)) {
1339         myInitOffsetEdge.SetRoot(anEdgeRef);
1340         if (Build.IsBound(anEdgeRef)) {
1341           TopoDS_Shape aNewShape = Build(anEdgeRef);
1342           
1343           if (aNewShape.ShapeType() == TopAbs_EDGE) {
1344             if (IMOE.HasImage(aNewShape)) {
1345               const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
1346               
1347               myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1348             } else
1349               myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
1350           } else { // aNewShape != TopAbs_EDGE
1351             TopTools_ListOfShape aListNewEdge;
1352             
1353             for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1354               const TopoDS_Shape &aResEdge = ExpC.Current();
1355               
1356               if (IMOE.HasImage(aResEdge)) {
1357                 const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
1358                 TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
1359                 
1360                 for (; aNewEIter.More(); aNewEIter.Next())
1361                   aListNewEdge.Append(aNewEIter.Value());
1362               } else
1363                 aListNewEdge.Append(aResEdge);
1364             }
1365             
1366             myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
1367           }
1368         } 
1369         else { // Free boundary.
1370           TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
1371
1372           if (MES.IsBound(aNewEdge))
1373             aNewEdge = MES(aNewEdge);
1374
1375           if (IMOE.HasImage(aNewEdge)) {
1376             const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
1377
1378             myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1379           } else
1380             myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
1381         }
1382       }
1383     }
1384   }
1385 //  Modified by skv - Tue Mar 15 16:20:43 2005
1386
1387   //---------------------------
1388   // MAJ SD. for caps
1389   //---------------------------
1390   //TopTools_MapOfShape View; 
1391   for (i = 1; i <= myFaces.Extent(); i++) {
1392     const TopoDS_Shape& Cork = myFaces(i);
1393     const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
1394     for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1395       const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1396       if (IMOE.HasImage(OE)) {
1397         const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1398           TopTools_ListIteratorOfListOfShape itLOE(LOE);
1399         for (; itLOE.More(); itLOE.Next()) {
1400           const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
1401           myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
1402 #ifdef DRAW
1403           if (AffichInt2d) {
1404             sprintf(name,"AE_%d",NbAE++);
1405             DBRep::Set(name,COE);
1406             COES.Add(COE);
1407           }
1408 #endif
1409           
1410           if (!myAsDes->HasDescendant(COE)) {
1411             TopoDS_Vertex CV1,CV2;
1412             TopExp::Vertices(COE,CV1,CV2);
1413             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1414             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));          
1415           }
1416         }
1417       }
1418       else {
1419         myAsDes->Add(Cork,OE);
1420         if (AsDes->HasDescendant(OE)) {
1421           myAsDes->Add(OE,AsDes->Descendant(OE));
1422         }
1423 #ifdef DRAW
1424         if (AffichInt2d) {
1425           sprintf(name,"AE_%d",NbAE++);
1426           DBRep::Set(name,OE);
1427           COES.Add(OE);
1428         }
1429 #endif
1430       }
1431     }
1432   }
1433   
1434 #ifdef OCCT_DEBUG
1435   DEBVerticesControl (COES,myAsDes);
1436   if ( ChronBuild) Clock.Show();
1437 #endif
1438 }
1439
1440 //=======================================================================
1441 //function : BuildOffsetByArc
1442 //purpose  : 
1443 //=======================================================================
1444 void BRepOffset_MakeOffset::BuildOffsetByArc()
1445 {
1446 #ifdef OCCT_DEBUG
1447   if ( ChronBuild) {
1448     cout << " CONSTRUCTION OF OFFSETS :" << endl;
1449     Clock.Reset();
1450     Clock.Start();
1451   }
1452 #endif
1453
1454   TopExp_Explorer Exp;
1455   TopTools_ListIteratorOfListOfShape itLF;
1456   TopTools_MapOfShape Done;
1457   
1458   //--------------------------------------------------------
1459   // Construction of faces parallel to initial faces
1460   //--------------------------------------------------------
1461   BRepOffset_DataMapOfShapeOffset MapSF;
1462   MakeOffsetFaces(MapSF);
1463   //--------------------------------------------------------
1464   // Construction of tubes on edge.
1465   //--------------------------------------------------------
1466   BRepOffset_Type    OT = BRepOffset_Convex;
1467   if (myOffset < 0.) OT = BRepOffset_Concave; 
1468    
1469   for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) {
1470     const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1471     if (Done.Add(E)) {
1472       const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
1473       if (Anc.Extent() == 2) {
1474         const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1475         if (!L.IsEmpty() && L.First().Type() == OT) {
1476           Standard_Real CurOffset = myOffset;
1477           if ( myFaceOffset.IsBound(Anc.First()))
1478             CurOffset = myFaceOffset(Anc.First());
1479           TopoDS_Shape aLocalShapeGen = MapSF(Anc.First()).Generated(E);
1480           TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShapeGen);
1481           aLocalShapeGen = MapSF(Anc.Last()).Generated(E);
1482           TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShapeGen);
1483 //          TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1484 //          TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
1485           // find if exits tangent edges in the original shape
1486           TopoDS_Edge E1f, E1l;
1487           TopoDS_Vertex V1f, V1l;
1488           TopExp::Vertices(E,V1f,V1l);
1489           TopTools_ListOfShape TangE;
1490           myAnalyse.TangentEdges(E,V1f,TangE);
1491           // find if the pipe on the tangent edges are soon created.
1492           TopTools_ListIteratorOfListOfShape itl(TangE);
1493           Standard_Boolean Find = Standard_False;
1494           for ( ; itl.More() && !Find; itl.Next()) {
1495             if ( MapSF.IsBound(itl.Value())) {
1496               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
1497               E1f  = TopoDS::Edge(aLocalShape);
1498 //              E1f  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
1499               Find = Standard_True;
1500             }
1501           }
1502           TangE.Clear();
1503           myAnalyse.TangentEdges(E,V1l,TangE);
1504           // find if the pipe on the tangent edges are soon created.
1505           itl.Initialize(TangE);
1506           Find = Standard_False;
1507           for ( ; itl.More() && !Find; itl.Next()) {
1508             if ( MapSF.IsBound(itl.Value())) {
1509               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
1510               E1l  = TopoDS::Edge(aLocalShape);
1511 //              E1l  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
1512               Find = Standard_True;
1513             }
1514           }
1515           BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
1516           MapSF.Bind(E,OF);
1517         }
1518       }
1519       else {
1520         // ----------------------
1521         // free border.
1522         // ----------------------
1523         TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1524         TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1525 ///        TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1526         myInitOffsetEdge.SetRoot(E); // skv: supporting history.
1527         myInitOffsetEdge.Bind (E,EOn1);      
1528       }
1529     }
1530   }
1531
1532   //--------------------------------------------------------
1533   // Construction of spheres on vertex.
1534   //--------------------------------------------------------
1535   Done.Clear();
1536   TopTools_ListIteratorOfListOfShape it;
1537
1538   for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) {
1539     const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
1540     if (Done.Add(V)) {
1541       const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
1542       TopTools_ListOfShape LE;
1543       myAnalyse.Edges(V,OT,LE);
1544
1545       if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
1546         TopTools_ListOfShape LOE;
1547         //--------------------------------------------------------
1548         // Return connected edges on tubes.
1549         //--------------------------------------------------------
1550         for (it.Initialize(LE) ; it.More(); it.Next()) {
1551           LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
1552         }
1553         //----------------------
1554         // construction sphere.
1555         //-----------------------
1556         const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
1557         const TopoDS_Shape& FF = LLA.First();
1558         Standard_Real CurOffset = myOffset;
1559         if ( myFaceOffset.IsBound(FF))
1560           CurOffset = myFaceOffset(FF);
1561         
1562         BRepOffset_Offset OF(V,LOE,CurOffset);
1563         MapSF.Bind(V,OF);
1564       }
1565       //--------------------------------------------------------------
1566       // Particular processing if V is at least a free border.
1567       //-------------------------------------------------------------
1568       TopTools_ListOfShape LBF;
1569       myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF);
1570       if (!LBF.IsEmpty()) {        
1571         Standard_Boolean First = Standard_True;
1572         for (it.Initialize(LE) ; it.More(); it.Next()) {
1573           if (First) {
1574             myInitOffsetEdge.SetRoot(V); // skv: supporting history.
1575             myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
1576             First = Standard_False;
1577           }
1578           else {
1579             myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
1580           }
1581         } 
1582       }
1583     }
1584   }
1585
1586   //------------------------------------------------------------
1587   // Extension of parallel faces to the context.
1588   // Extended faces are ordered in DS and removed from MapSF.
1589   //------------------------------------------------------------
1590   if (!myFaces.IsEmpty()) ToContext (MapSF);
1591
1592   //------------------------------------------------------
1593   // MAJ SD.
1594   //------------------------------------------------------
1595   BRepOffset_Type    RT = BRepOffset_Concave;
1596   if (myOffset < 0.) RT = BRepOffset_Convex;
1597   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
1598   for ( ; It.More(); It.Next()) {
1599     const TopoDS_Shape& SI = It.Key(); 
1600     const BRepOffset_Offset& SF = It.Value();
1601     if (SF.Status() == BRepOffset_Reversed ||
1602         SF.Status() == BRepOffset_Degenerated ) {
1603       //------------------------------------------------
1604       // Degenerated or returned faces are not stored.
1605       //------------------------------------------------
1606       continue; 
1607     }        
1608
1609     const TopoDS_Face&  OF = It.Value().Face();
1610     myInitOffsetFace.Bind    (SI,OF);      
1611     myInitOffsetFace.SetRoot (SI);      // Initial<-> Offset
1612     myImageOffset.SetRoot    (OF);      // FaceOffset root of images
1613     
1614     if (SI.ShapeType() == TopAbs_FACE) {
1615       for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1616            Exp.More(); Exp.Next()) {
1617         //--------------------------------------------------------------------
1618         // To each face are associatedthe edges that restrict that 
1619         // The edges that do not generate tubes or are not tangent
1620         // to two faces are removed.
1621         //--------------------------------------------------------------------
1622         const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1623         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
1624         if (!L.IsEmpty() && L.First().Type() != RT) {
1625           TopAbs_Orientation OO  = E.Orientation();
1626           TopoDS_Shape aLocalShape = It.Value().Generated(E);
1627           TopoDS_Edge        OE  = TopoDS::Edge(aLocalShape);
1628 //          TopoDS_Edge        OE  = TopoDS::Edge(It.Value().Generated(E));
1629           myAsDes->Add (OF,OE.Oriented(OO));
1630         }
1631       }
1632     }
1633     else {
1634       for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1635            Exp.More(); Exp.Next()) {
1636         myAsDes->Add (OF,Exp.Current());
1637       }
1638     }
1639   }
1640
1641 #ifdef OCCT_DEBUG
1642   if ( ChronBuild) Clock.Show();
1643 #endif
1644 }
1645
1646
1647
1648 //=======================================================================
1649 //function : SelfInter
1650 //purpose  : 
1651 //=======================================================================
1652
1653 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
1654 {
1655 #ifdef OCCT_DEBUG
1656   if ( ChronBuild) {
1657     cout << " AUTODEBOUCLAGE:" << endl;
1658     Clock.Reset();
1659     Clock.Start();
1660   }    
1661 #endif  
1662
1663   throw Standard_NotImplemented();
1664 }
1665
1666
1667 //=======================================================================
1668 //function : ToContext
1669 //purpose  : 
1670 //=======================================================================
1671
1672 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
1673 {
1674   TopTools_DataMapOfShapeShape        Created;   
1675   TopTools_DataMapOfShapeShape        MEF;
1676   TopTools_IndexedMapOfShape          FacesToBuild;
1677   TopTools_ListIteratorOfListOfShape  itl;
1678   TopExp_Explorer                     exp;
1679
1680 //  TopAbs_State       Side = TopAbs_IN;  
1681 //  if (myOffset < 0.) Side = TopAbs_OUT;
1682
1683   TopAbs_State       Side = TopAbs_OUT; 
1684
1685   /*
1686   Standard_Integer i;
1687   for (i = 1; i <= myFaces.Extent(); i++) {
1688     const TopoDS_Face& CF = TopoDS::Face(myFaces(i));
1689     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1690          exp.More(); exp.Next()) {
1691       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1692       if (!myAnalyse.HasAncestor(E)) {
1693         //----------------------------------------------------------------
1694         // The edges of context faces that are not in the initial shape
1695         // can appear in the result.
1696         //----------------------------------------------------------------
1697         //myAsDes->Add(CF,E);
1698       }  
1699     }
1700   }
1701   */
1702   
1703   //--------------------------------------------------------
1704   // Determine the edges and faces reconstructed by  
1705   // intersection.
1706   //---------------------------------------------------------
1707   Standard_Integer j;
1708   for (j = 1; j <= myFaces.Extent(); j++) {
1709     const TopoDS_Face& CF = TopoDS::Face(myFaces(j));
1710     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1711          exp.More(); exp.Next()) {
1712       const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); 
1713       if (myAnalyse.HasAncestor(E)) {
1714         const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
1715         for (itl.Initialize(LEA); itl.More(); itl.Next()) {
1716           const BRepOffset_Offset& OF = MapSF(itl.Value());
1717           FacesToBuild.Add(itl.Value());
1718           MEF.Bind(OF.Generated(E),CF);
1719         }
1720          TopoDS_Vertex V[2];
1721         TopExp::Vertices(E,V[0],V[1]);
1722         for (Standard_Integer i = 0; i < 2; i++) {
1723           const TopTools_ListOfShape& LVA =  myAnalyse.Ancestors(V[i]);
1724           for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
1725             const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
1726             if (MapSF.IsBound(EV)) {
1727               const BRepOffset_Offset& OF = MapSF(EV);
1728               FacesToBuild.Add(EV);
1729               MEF.Bind(OF.Generated(V[i]),CF);
1730             }
1731           }
1732         }
1733       }
1734     }
1735   }
1736   //---------------------------
1737   // Reconstruction of faces.
1738   //---------------------------
1739   TopoDS_Face        F,NF;
1740   BRepOffset_Type    RT = BRepOffset_Concave;
1741   if (myOffset < 0.) RT = BRepOffset_Convex;
1742   TopoDS_Shape       OE,NE;
1743   TopAbs_Orientation Or;
1744
1745   for (j = 1; j <= FacesToBuild.Extent(); j++) {
1746     const TopoDS_Shape& S   = FacesToBuild(j);
1747     BRepOffset_Offset   BOF;
1748     BOF = MapSF(S);
1749     F = TopoDS::Face(BOF.Face());
1750     BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF);
1751     MapSF.UnBind(S);
1752     //--------------
1753     // MAJ SD.
1754     //--------------
1755     myInitOffsetFace.Bind    (S,NF);      
1756     myInitOffsetFace.SetRoot (S);      // Initial<-> Offset
1757     myImageOffset.SetRoot    (NF);
1758
1759     if (S.ShapeType() == TopAbs_FACE) {
1760       for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1761            exp.More(); exp.Next()) {
1762         
1763         const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1764         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
1765         OE = BOF.Generated(E);
1766         Or = E.Orientation();
1767         OE.Orientation(Or);
1768         if (!L.IsEmpty() && L.First().Type() != RT) {
1769           if (Created.IsBound(OE)) {
1770             NE = Created(OE); 
1771             if (NE.Orientation() == TopAbs_REVERSED) 
1772               NE.Orientation(TopAbs::Reverse(Or));
1773             else
1774               NE.Orientation(Or);
1775             myAsDes->Add(NF,NE);
1776           }
1777           else {
1778             myAsDes->Add(NF,OE);
1779           }
1780         }
1781       }
1782     }
1783     else {
1784       //------------------
1785       // Tube
1786       //---------------------
1787       for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
1788            exp.More(); exp.Next()) {
1789         myAsDes->Add (NF,exp.Current());
1790       }
1791     }    
1792     MapSF.UnBind(S);
1793   }
1794
1795   //------------------
1796   // MAJ free borders
1797   //------------------
1798   TopTools_DataMapIteratorOfDataMapOfShapeShape itc;
1799   for (itc.Initialize(Created); itc.More(); itc.Next()) {
1800     OE = itc.Key();
1801     NE = itc.Value();
1802     if (myInitOffsetEdge.IsImage(OE)) {
1803       TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
1804       Or = myInitOffsetEdge.Image(E).First().Orientation();
1805       if (NE.Orientation() == TopAbs_REVERSED) 
1806         NE.Orientation(TopAbs::Reverse(Or));
1807       else
1808         NE.Orientation(Or);
1809       myInitOffsetEdge.Remove(OE);
1810       myInitOffsetEdge.Bind(E,NE);
1811     }
1812   }
1813 }
1814
1815
1816 //=======================================================================
1817 //function : UpdateFaceOffset
1818 //purpose  : 
1819 //=======================================================================
1820
1821 void BRepOffset_MakeOffset::UpdateFaceOffset()
1822 {
1823   TopTools_MapOfShape M;
1824   TopTools_DataMapOfShapeReal CopiedMap;
1825   CopiedMap.Assign(myFaceOffset);
1826   TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
1827
1828   BRepOffset_Type    RT = BRepOffset_Convex;
1829   if (myOffset < 0.) RT = BRepOffset_Concave;
1830
1831   for ( ; it.More(); it.Next()) {
1832     const TopoDS_Face& F = TopoDS::Face(it.Key());
1833     Standard_Real CurOffset = CopiedMap(F);
1834     if ( !M.Add(F)) continue;
1835     TopoDS_Compound Co;
1836     BRep_Builder Build;
1837     Build.MakeCompound(Co);
1838     TopTools_MapOfShape Dummy;
1839     Build.Add(Co,F);
1840     if (myJoin == GeomAbs_Arc)
1841       myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent,RT);
1842     else   
1843       myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent);
1844
1845     TopExp_Explorer exp(Co,TopAbs_FACE);
1846     for (; exp.More(); exp.Next()) {
1847       const TopoDS_Face& FF = TopoDS::Face(exp.Current());
1848       if ( !M.Add(FF)) continue;
1849       if ( myFaceOffset.IsBound(FF))
1850         myFaceOffset.UnBind(FF);
1851       myFaceOffset.Bind(FF,CurOffset);
1852     }
1853   }
1854 }
1855
1856 //=======================================================================
1857 //function : CorrectConicalFaces
1858 //purpose  : 
1859 //=======================================================================
1860
1861 void BRepOffset_MakeOffset::CorrectConicalFaces()
1862 {
1863   if(myOffsetShape.IsNull())
1864   {
1865     return;
1866   }
1867   //
1868   TopTools_SequenceOfShape Cones;
1869   TopTools_SequenceOfShape Circs;
1870   TopTools_SequenceOfShape Seams;
1871   Standard_Real TolApex = 1.e-5;
1872
1873   Standard_Integer i;
1874
1875   TopTools_DataMapOfShapeListOfShape FacesOfCone;
1876   //TopTools_DataMapOfShapeShape DegEdges;
1877   TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE );
1878   if (myJoin == GeomAbs_Arc)
1879   {
1880     for (; Explo.More(); Explo.Next())
1881     {
1882       TopoDS_Face aFace = TopoDS::Face( Explo.Current() );
1883       Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace );
1884       //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
1885       //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //???
1886       
1887       TopTools_IndexedMapOfShape Emap;
1888       TopExp::MapShapes( aFace, TopAbs_EDGE, Emap );
1889       for (i = 1; i <= Emap.Extent(); i++)
1890       {
1891         TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) );
1892         //Standard_Real f, l;
1893         //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l );
1894         //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape());
1895         if (BRep_Tool::Degenerated(anEdge))
1896         {
1897           //Check if anEdge is a really degenerated edge or not
1898           BRepAdaptor_Curve BACurve(anEdge, aFace);
1899           gp_Pnt Pfirst, Plast, Pmid;
1900           Pfirst = BACurve.Value(BACurve.FirstParameter());
1901           Plast  = BACurve.Value(BACurve.LastParameter());
1902           Pmid   = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.);
1903           if (Pfirst.Distance(Plast) <= TolApex &&
1904               Pfirst.Distance(Pmid)  <= TolApex)
1905             continue;
1906           //Cones.Append( aFace );
1907           //Circs.Append( anEdge );
1908           //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge );
1909           TopoDS_Edge OrEdge = 
1910             TopoDS::Edge( myInitOffsetEdge.Root( anEdge) );
1911           TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1912           if ( FacesOfCone.IsBound(VF) )
1913           {
1914             //add a face to the existing list
1915             TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF);
1916             aFaces.Append (aFace);
1917             //DegEdges.Bind(aFace, anEdge);
1918           }
1919           else
1920           {
1921             //the vertex is not in the map => create a new key and items
1922             TopTools_ListOfShape aFaces;
1923             aFaces.Append (aFace);
1924             FacesOfCone.Bind(VF, aFaces);
1925             //DegEdges.Bind(aFace, anEdge);
1926           }
1927         }
1928       } //for (i = 1; i <= Emap.Extent(); i++)
1929     } //for (; fexp.More(); fexp.Next())
1930   } //if (myJoin == GeomAbs_Arc)
1931
1932   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone);
1933   BRep_Builder BB;
1934   TopLoc_Location L;
1935   Standard_Boolean IsModified = Standard_False;
1936   for (; Cone.More(); Cone.Next() ) {
1937     gp_Sphere theSphere;
1938     Handle(Geom_SphericalSurface) aSphSurf;
1939     TopoDS_Wire SphereWire;
1940     BB.MakeWire(SphereWire);
1941     TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key());
1942     const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex);
1943     TopTools_ListIteratorOfListOfShape itFaces(Faces);
1944     Standard_Boolean isFirstFace = Standard_True;
1945     gp_Pnt FirstPoint;
1946     TopoDS_Vertex theFirstVertex, CurFirstVertex;
1947     for (; itFaces.More(); itFaces.Next())
1948     {
1949       TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First());
1950       TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace));
1951       for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
1952       {
1953         DegEdge = TopoDS::Edge(Explo.Current());
1954         if (BRep_Tool::Degenerated(DegEdge))
1955         {
1956           TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) );
1957           TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1958           if (VF.IsSame(anApex))
1959             break;
1960         }
1961       }
1962       TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD);
1963       TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape);
1964       BB.Degenerated(CurEdge, Standard_False);
1965       BB.SameRange(CurEdge, Standard_False);
1966       BB.SameParameter(CurEdge, Standard_False);
1967       gp_Pnt fPnt, lPnt, mPnt;
1968       GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt);
1969       Standard_Real f, l;
1970       BRep_Tool::Range(CurEdge, f, l);
1971       if (isFirstFace)
1972       {
1973         gp_Vec aVec1(fPnt, mPnt);
1974         gp_Vec aVec2(fPnt, lPnt);
1975         gp_Vec aNorm = aVec1.Crossed(aVec2);
1976         gp_Pnt theApex = BRep_Tool::Pnt(anApex);
1977         gp_Vec ApexToFpnt(theApex, fPnt);
1978         gp_Vec Ydir = aNorm ^ ApexToFpnt;
1979         gp_Vec Xdir = Ydir ^ aNorm;
1980         //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f);
1981         gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir));
1982         theSphere.SetRadius(myOffset);
1983         theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/);
1984         aSphSurf = new Geom_SphericalSurface(theSphere);
1985         FirstPoint = fPnt;
1986         theFirstVertex = BRepLib_MakeVertex(fPnt);
1987         CurFirstVertex = theFirstVertex;
1988       }
1989       
1990       TopoDS_Vertex v1, v2, FirstVert, EndVert;
1991       TopExp::Vertices(CurEdge, v1, v2);
1992       FirstVert = CurFirstVertex;
1993       if (lPnt.Distance(FirstPoint) <= Precision::Confusion())
1994         EndVert = theFirstVertex;
1995       else
1996         EndVert = BRepLib_MakeVertex(lPnt);
1997       CurEdge.Free( Standard_True );
1998       BB.Remove(CurEdge, v1);
1999       BB.Remove(CurEdge, v2);
2000       BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD));
2001       BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED));
2002       //take the curve from sphere an put it to the edge
2003       Standard_Real Uf, Vf, Ul, Vl;
2004       ElSLib::Parameters( theSphere, fPnt, Uf, Vf );
2005       ElSLib::Parameters( theSphere, lPnt, Ul, Vl );
2006       if (Abs(Ul) <= Precision::Confusion())
2007         Ul = 2.*M_PI;
2008       Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
2009       /*
2010         if (!isFirstFace)
2011         {
2012         gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
2013         if (Abs(Uf - f) > Precision::Confusion())
2014         {
2015         aCircle.Rotate(aCircle.Axis(), f - Uf);
2016         aCurv = new Geom_Circle(aCircle);
2017         }
2018         }
2019       */
2020       Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul);
2021       BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion());
2022       BB.Range(CurEdge, Uf, Ul, Standard_True);
2023       Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() );
2024       Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul);
2025       BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion());
2026       BB.Range(CurEdge, aSphSurf, L, Uf, Ul);
2027       BRepLib::SameParameter(CurEdge);
2028       BB.Add(SphereWire, CurEdge);
2029       //Modifying correspondent edges in aFace: substitute vertices common with CurEdge
2030       BRepAdaptor_Curve2d BAc2d(CurEdge, aFace);
2031       gp_Pnt2d fPnt2d, lPnt2d;
2032       fPnt2d = BAc2d.Value(BAc2d.FirstParameter());
2033       lPnt2d = BAc2d.Value(BAc2d.LastParameter());
2034       TopTools_IndexedMapOfShape Emap;
2035       TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
2036       TopoDS_Edge EE [2];
2037       Standard_Integer j = 0, k;
2038       for (k = 1; k <= Emap.Extent(); k++)
2039       {
2040         const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k));
2041         if (!BRep_Tool::Degenerated(anEdge))
2042         {
2043           TopoDS_Vertex V1, V2;
2044           TopExp::Vertices(anEdge, V1, V2);
2045           if (V1.IsSame(v1) || V2.IsSame(v1))
2046             EE[j++] = anEdge;
2047         }
2048       }
2049       for (k = 0; k < j; k++)
2050       {
2051         TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD);
2052         TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
2053         Eforward.Free(Standard_True);
2054         TopoDS_Vertex V1, V2;
2055         TopExp::Vertices( Eforward, V1, V2 );
2056         BRepAdaptor_Curve2d EEc( Eforward, aFace );
2057         gp_Pnt2d p2d1, p2d2;
2058         p2d1 = EEc.Value(EEc.FirstParameter());
2059         p2d2 = EEc.Value(EEc.LastParameter());
2060         if (V1.IsSame(v1))
2061         {
2062           TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())?
2063             FirstVert : EndVert;
2064           BB.Remove( Eforward, V1 );
2065           BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) );
2066         }
2067         else
2068         {
2069           TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())?
2070             FirstVert : EndVert;
2071           BB.Remove( Eforward, V2 );
2072           BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) );
2073         }
2074       }
2075       
2076       isFirstFace = Standard_False;
2077       CurFirstVertex = EndVert;
2078     }
2079     //Building new spherical face
2080     Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
2081     gp_Pnt2d p2d1, p2d2;
2082     TopTools_ListOfShape EdgesOfWire;
2083     TopoDS_Iterator itw(SphereWire);
2084     for (; itw.More(); itw.Next())
2085     {
2086       const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2087       EdgesOfWire.Append(anEdge);
2088       Standard_Real f, l;
2089       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l);
2090       p2d1 = aC2d->Value(f);
2091       p2d2 = aC2d->Value(l);
2092       if (p2d1.X() < Ufirst)
2093         Ufirst = p2d1.X();
2094       if (p2d1.X() > Ulast)
2095         Ulast = p2d1.X();
2096       if (p2d2.X() < Ufirst)
2097         Ufirst = p2d2.X();
2098       if (p2d2.X() > Ulast)
2099         Ulast = p2d2.X();
2100     }
2101     TopTools_ListOfShape NewEdges;
2102     TopoDS_Edge FirstEdge;
2103     TopTools_ListIteratorOfListOfShape itl(EdgesOfWire);
2104     for (; itl.More(); itl.Next())
2105     {
2106       FirstEdge = TopoDS::Edge(itl.Value());
2107       Standard_Real f, l;
2108       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l);
2109       p2d1 = aC2d->Value(f);
2110       p2d2 = aC2d->Value(l);
2111       if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion())
2112       {
2113         EdgesOfWire.Remove(itl);
2114         break;
2115       }
2116     }
2117     NewEdges.Append(FirstEdge.Oriented(TopAbs_FORWARD));
2118     TopoDS_Vertex Vf1, CurVertex;
2119     TopExp::Vertices(FirstEdge, Vf1, CurVertex);
2120     itl.Initialize(EdgesOfWire);
2121     while (itl.More())
2122     {
2123       const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2124       TopoDS_Vertex V1, V2;
2125       TopExp::Vertices(anEdge, V1, V2);
2126       if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
2127       {
2128         NewEdges.Append(anEdge.Oriented(TopAbs_FORWARD));
2129         CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
2130         EdgesOfWire.Remove(itl);
2131       }
2132       else
2133         itl.Next();
2134     }
2135     
2136     Standard_Real Vfirst, Vlast;
2137     if (p2d1.Y() > 0.)
2138     {
2139       Vfirst = p2d1.Y(); Vlast = M_PI/2.;
2140     }
2141     else
2142     {
2143       Vfirst = -M_PI/2.; Vlast = p2d1.Y();
2144     }
2145     TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
2146     TopoDS_Edge OldEdge, DegEdge;
2147     for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2148     {
2149       DegEdge = TopoDS::Edge(Explo.Current());
2150       if (BRep_Tool::Degenerated(DegEdge))
2151         break;
2152     }
2153     TopoDS_Vertex DegVertex = TopExp::FirstVertex(DegEdge);
2154     for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2155     {
2156       OldEdge = TopoDS::Edge(Explo.Current());
2157       TopoDS_Vertex V1, V2;
2158       TopExp::Vertices(OldEdge, V1, V2);
2159       if (!V1.IsSame(DegVertex) && !V2.IsSame(DegVertex))
2160         break;
2161     }
2162     TopoDS_Vertex V1, V2;
2163     TopExp::Vertices(OldEdge, V1, V2);
2164     TopTools_ListOfShape LV1, LV2;
2165     LV1.Append(Vf1.Oriented(TopAbs_FORWARD));
2166     LV2.Append(CurVertex.Oriented(TopAbs_FORWARD));
2167     BRepTools_Substitution theSubstitutor;
2168     theSubstitutor.Substitute(V1.Oriented(TopAbs_FORWARD), LV1);
2169     if (!V1.IsSame(V2))
2170       theSubstitutor.Substitute(V2.Oriented(TopAbs_FORWARD), LV2);
2171     theSubstitutor.Substitute(OldEdge.Oriented(TopAbs_FORWARD), NewEdges);
2172     theSubstitutor.Build(NewSphericalFace);
2173     if (theSubstitutor.IsCopied(NewSphericalFace))
2174     {
2175       const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace);
2176       NewSphericalFace = TopoDS::Face(listSh.First());
2177     }
2178     
2179     //Adding NewSphericalFace to the shell
2180     Explo.Init( myOffsetShape, TopAbs_SHELL );
2181     TopoDS_Shape theShell = Explo.Current();
2182     theShell.Free( Standard_True );
2183     BB.Add( theShell, NewSphericalFace );
2184     IsModified = Standard_True;
2185     if(!theShell.Closed())
2186     {
2187       if(BRep_Tool::IsClosed(theShell))
2188       {
2189         theShell.Closed(Standard_True);
2190       }
2191     }
2192   }
2193   //
2194   if(!IsModified)
2195   {
2196     return;
2197   }
2198   //
2199   if (myShape.ShapeType() == TopAbs_SOLID || myThickening)
2200   {
2201     //Explo.Init( myOffsetShape, TopAbs_SHELL );
2202
2203     //if (Explo.More()) {
2204     //  TopoDS_Shape theShell = Explo.Current();
2205     //  theShell.Closed( Standard_True );
2206     //}
2207
2208     Standard_Integer            NbShell = 0;
2209     TopoDS_Compound             NC;
2210     TopoDS_Shape                S1;
2211     BB.MakeCompound (NC);
2212
2213     TopoDS_Solid Sol;
2214     BB.MakeSolid(Sol);
2215     Sol.Closed(Standard_True);
2216     for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) {
2217       TopoDS_Shell Sh = TopoDS::Shell(Explo.Current());
2218       //if (myThickening && myOffset > 0.)
2219       //  Sh.Reverse();
2220       NbShell++;
2221       if (Sh.Closed()) {
2222         BB.Add(Sol,Sh);
2223       }
2224       else {
2225         BB.Add (NC,Sh);
2226         if(NbShell == 1)
2227         {
2228           S1 = Sh;
2229         }
2230       }
2231     }
2232     TopoDS_Iterator anIt(Sol);
2233     Standard_Boolean SolIsNull = !anIt.More();
2234     //Checking solid
2235     if(!SolIsNull)
2236     {
2237       Standard_Integer nbs = 0;
2238       while(anIt.More()) {anIt.Next(); ++nbs;}
2239       if(nbs > 1)
2240       {
2241         BRepCheck_Analyzer aCheck(Sol, Standard_False);
2242         if(!aCheck.IsValid())
2243         {
2244           TopTools_ListOfShape aSolList;
2245           CorrectSolid(Sol, aSolList);
2246           if(!aSolList.IsEmpty())
2247           {
2248             BB.Add(NC, Sol);
2249             TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
2250             for(; aSLIt.More(); aSLIt.Next())
2251             {
2252               BB.Add(NC, aSLIt.Value());
2253             }
2254             SolIsNull = Standard_True;
2255           }
2256         }
2257       }
2258     }
2259     //
2260     anIt.Initialize(NC);
2261     Standard_Boolean NCIsNull = !anIt.More();
2262     if((!SolIsNull) && (!NCIsNull))
2263     {
2264       BB.Add(NC, Sol);
2265       myOffsetShape = NC;
2266     }
2267     else if(SolIsNull && (!NCIsNull))
2268     {
2269       if (NbShell == 1) 
2270       {
2271         myOffsetShape = S1;
2272       }
2273       else
2274       {
2275         myOffsetShape = NC;
2276       }
2277     }
2278     else if((!SolIsNull) && NCIsNull)
2279     {
2280       myOffsetShape = Sol;
2281     }
2282     else
2283     {
2284       myOffsetShape = NC;
2285     }
2286   }
2287 }
2288
2289
2290 //=======================================================================
2291 //function : Intersection3D
2292 //purpose  : 
2293 //=======================================================================
2294
2295 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
2296 {
2297 #ifdef OCCT_DEBUG
2298   if (ChronBuild) {
2299     cout << " INTERSECTION 3D:" << endl;
2300     Clock.Reset();
2301     Clock.Start();  
2302   }
2303 #endif
2304
2305   // In the Complete Intersection mode, implemented currently for planar
2306   // solids only, there is no need to intersect the faces here.
2307   // This intersection will be performed in the method BuildShellsCompleteInter
2308   // where the special treatment is applied to produced faces.
2309   //
2310   // Make sure to match the parameters in which the method
2311   // BuildShellsCompleteInter is called.
2312   if (myInter && (myJoin == GeomAbs_Intersection) && myIsPlanar &&
2313       !myThickening && myFaces.IsEmpty() && IsSolid(myShape))
2314     return;
2315
2316
2317   TopTools_ListOfShape OffsetFaces;  // list of faces // created.
2318   MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2319
2320   if (!myFaces.IsEmpty()) {     
2321     Standard_Boolean InSide = (myOffset < 0.); // Temporary
2322     // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2323     // between the cap and the part.
2324
2325     if (myJoin == GeomAbs_Arc) 
2326       Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge);
2327   }
2328   if (myInter) {
2329     //-------------
2330     //Complete.
2331     //-------------
2332     Inter.CompletInt (OffsetFaces,myInitOffsetFace);
2333     TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
2334     if (myJoin == GeomAbs_Intersection) {
2335       BRepOffset_Tool::CorrectOrientation (myShape,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2336     }
2337   }
2338   else {
2339     //--------------------------------
2340     // Only between neighbor faces.
2341     //--------------------------------
2342     Inter.ConnexIntByArc(OffsetFaces,myShape,myAnalyse,myInitOffsetFace);
2343   }
2344 #ifdef OCCT_DEBUG
2345   if ( ChronBuild) Clock.Show();
2346 #endif
2347 }
2348
2349 //=======================================================================
2350 //function : Intersection2D
2351 //purpose  : 
2352 //=======================================================================
2353
2354 void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Modif,
2355                                            const TopTools_IndexedMapOfShape& NewEdges)
2356 {
2357 #ifdef OCCT_DEBUG
2358   if (ChronBuild) {
2359     cout << " INTERSECTION 2D:" << endl;
2360     Clock.Reset();
2361     Clock.Start();  
2362   }
2363 #endif
2364   //--------------------------------------------------------
2365   // calculate intersections2d on faces concerned by 
2366   // intersection3d
2367   //---------------------------------------------------------
2368   //TopTools_MapIteratorOfMapOfShape it(Modif);
2369   //-----------------------------------------------
2370   // Intersection of edges 2 by 2.
2371   //-----------------------------------------------
2372   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
2373   Standard_Integer i;
2374   for (i = 1; i <= Modif.Extent(); i++) {
2375     const TopoDS_Face& F  = TopoDS::Face(Modif(i));
2376     BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol, aDMVV);
2377   }
2378   //
2379   BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes);
2380   //
2381 #ifdef OCCT_DEBUG
2382   if (AffichInt2d) {
2383     DEBVerticesControl (NewEdges,myAsDes);
2384   }
2385   if ( ChronBuild) Clock.Show();
2386 #endif
2387 }
2388
2389
2390 //=======================================================================
2391 //function : MakeLoops
2392 //purpose  : 
2393 //=======================================================================
2394
2395 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
2396 {
2397 #ifdef OCCT_DEBUG
2398   if (ChronBuild) {
2399      cout << " DEBOUCLAGE 2D:" << endl;
2400      Clock.Reset();
2401      Clock.Start(); 
2402   }
2403 #endif
2404   //TopTools_MapIteratorOfMapOfShape    it(Modif);
2405   TopTools_ListOfShape                LF,LC;
2406   //-----------------------------------------
2407   // unwinding of faces // modified.
2408   //-----------------------------------------
2409   Standard_Integer i;
2410   for (i = 1; i <= Modif.Extent(); i++) { 
2411     if (!myFaces.Contains(Modif(i)))
2412       LF.Append(Modif(i));
2413   }
2414   //
2415   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2416     BuildSplitsOfTrimmedFaces(LF, myAsDes, myImageOffset);
2417   }
2418   else {
2419     myMakeLoops.Build(LF,myAsDes,myImageOffset);
2420   }
2421
2422   //-----------------------------------------
2423   // unwinding of caps.
2424   //-----------------------------------------
2425   for (i = 1; i <= myFaces.Extent(); i++)
2426     LC.Append(myFaces(i));
2427
2428   Standard_Boolean   InSide = 1;
2429   if (myOffset > 0 ) InSide = 0;
2430   myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide);
2431
2432 #ifdef OCCT_DEBUG
2433   if ( ChronBuild) Clock.Show();
2434 #endif
2435 }
2436
2437 //=======================================================================
2438 //function : MakeFaces
2439 //purpose  : Reconstruction of topologically unchanged faces that
2440 //           share edges that were reconstructed.
2441 //=======================================================================
2442
2443 void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
2444 {
2445 #ifdef OCCT_DEBUG
2446   if (ChronBuild) {  
2447     cout << " RECONSTRUCTION OF FACES:" << endl;
2448     Clock.Reset();
2449     Clock.Start();
2450   }
2451 #endif
2452   TopTools_ListIteratorOfListOfShape itr;
2453   const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
2454   TopTools_ListOfShape        LOF;
2455   //----------------------------------
2456   // Loop on all faces //.
2457   //----------------------------------
2458   for (itr.Initialize(Roots); itr.More(); itr.Next()) {
2459     TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
2460     if (!myImageOffset.HasImage(F)) {
2461       LOF.Append(F);
2462     }
2463   }
2464   //
2465   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2466     BuildSplitsOfTrimmedFaces(LOF, myAsDes, myImageOffset);
2467   }
2468   else {
2469     myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
2470   }
2471   
2472 #ifdef OCCT_DEBUG
2473   if ( ChronBuild) Clock.Show();
2474 #endif
2475 }
2476
2477 //=======================================================================
2478 //function : UpdateInitOffset
2479 //purpose  : Update and cleaning of myInitOffset 
2480 //=======================================================================
2481 static void UpdateInitOffset (BRepAlgo_Image&         myInitOffset,
2482                               BRepAlgo_Image&         myImageOffset,
2483                               const TopoDS_Shape&     myOffsetShape,
2484                               const TopAbs_ShapeEnum &theShapeType) // skv
2485 {
2486   BRepAlgo_Image NIOF;
2487   const TopTools_ListOfShape& Roots = myInitOffset.Roots();
2488   TopTools_ListIteratorOfListOfShape it(Roots);
2489   for (; it.More(); it.Next()) {
2490     NIOF.SetRoot (it.Value());    
2491   }
2492   for (it.Initialize(Roots); it.More(); it.Next()) {
2493     const TopoDS_Shape& SI = it.Value();
2494     TopTools_ListOfShape LI;
2495     TopTools_ListOfShape L1;
2496     myInitOffset.LastImage(SI,L1);
2497     TopTools_ListIteratorOfListOfShape itL1(L1);
2498     for (; itL1.More(); itL1.Next()) {
2499       const TopoDS_Shape& O1 = itL1.Value();
2500       TopTools_ListOfShape L2;
2501       myImageOffset.LastImage(O1,L2);
2502       LI.Append(L2);
2503     }
2504     NIOF.Bind(SI,LI);
2505   }
2506 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
2507 //  Supporting history.
2508 //   NIOF.Filter(myOffsetShape,TopAbs_FACE);
2509   NIOF.Filter(myOffsetShape, theShapeType);
2510 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
2511   myInitOffset = NIOF;
2512 }
2513
2514 //=======================================================================
2515 //function : MakeMissingWalls
2516 //purpose  : 
2517 //=======================================================================
2518 void BRepOffset_MakeOffset::MakeMissingWalls ()
2519 {
2520   TopTools_IndexedDataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
2521   TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
2522   Standard_Real OffsetVal = Abs(myOffset);
2523
2524   FillContours(myShape, myAnalyse, Contours, MapEF);
2525
2526   for (Standard_Integer ic = 1; ic <= Contours.Extent(); ic++)
2527   {
2528     TopoDS_Vertex StartVertex = TopoDS::Vertex(Contours.FindKey(ic));
2529     TopoDS_Edge StartEdge;
2530     const TopTools_ListOfShape& aContour = Contours(ic);
2531     TopTools_ListIteratorOfListOfShape itl(aContour);
2532     Standard_Boolean FirstStep = Standard_True;
2533     TopoDS_Edge PrevEdge;
2534     TopoDS_Vertex PrevVertex = StartVertex;
2535     Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
2536     for (; itl.More(); itl.Next())
2537     {
2538       TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2539       TopoDS_Face aFaceOfEdge = TopoDS::Face(MapEF(anEdge));
2540
2541       // Check for offset existence.
2542       if (!myInitOffsetEdge.HasImage(anEdge))
2543         continue;
2544
2545       // Check for existence of two different vertices.
2546       TopTools_ListOfShape LOE, LOE2;
2547       myInitOffsetEdge.LastImage( anEdge, LOE );
2548       myImageOffset.LastImage( LOE.Last(), LOE2 );
2549       TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
2550       TopoDS_Vertex V1, V2, V3, V4;
2551       TopExp::Vertices(OE,     V4, V3);
2552       TopExp::Vertices(anEdge, V1, V2);
2553       Standard_Real aF, aL;
2554       const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
2555       if (!aC.IsNull() &&
2556          (!aC->IsClosed() && !aC->IsPeriodic()))
2557       {
2558         gp_Pnt aPntF = BRep_Tool::Pnt(V1);
2559         gp_Pnt aPntL = BRep_Tool::Pnt(V2);
2560         Standard_Real aDistE = aPntF.SquareDistance(aPntL);
2561         if ( aDistE < Precision::SquareConfusion())
2562         {
2563           // Bad case: non closed, but vertexes mapped to same 3d point.
2564           continue;
2565         }
2566
2567         Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
2568         if (aDistE < anEdgeTol)
2569         {
2570           // Potential problems not detected via checkshape.
2571           gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
2572           gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
2573           if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
2574           {
2575             // To avoid computation of complex analytical continuation of Sin / ArcSin.
2576             Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
2577             Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
2578             Standard_Real aCurrentAngle =  gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
2579             if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
2580                 Abs (aCurrentAngle) > aMaxAngle)
2581             {
2582               // anEdge not collinear to offset edge.
2583               isBuildFromScratch = Standard_True;
2584               myIsPerformSewing = Standard_True;
2585               continue;
2586             }
2587           }
2588         }
2589       }
2590
2591       Standard_Boolean ToReverse = Standard_False;
2592       if (!V1.IsSame(PrevVertex))
2593       {
2594         TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
2595         aVtx = V3; V3 = V4; V4 = aVtx;
2596         ToReverse = Standard_True;
2597       }
2598
2599       OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
2600       TopoDS_Edge E3, E4;
2601       Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
2602       if (FirstStep || isBuildFromScratch)
2603       {
2604         E4 = BRepLib_MakeEdge( V1, V4 );
2605         if (FirstStep)
2606           StartEdge = E4;
2607       }
2608       else
2609         E4 = PrevEdge;
2610       if (V2.IsSame(StartVertex) && !ArcOnV2)
2611         E3 = StartEdge;
2612       else
2613         E3 = BRepLib_MakeEdge( V2, V3 );
2614       E4.Reverse();
2615
2616       if (isBuildFromScratch)
2617       {
2618         E3.Reverse();
2619         E4.Reverse();
2620       }
2621
2622       TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
2623       const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
2624       Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
2625       Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
2626       BRep_Builder BB;
2627       TopoDS_Wire theWire;
2628       BB.MakeWire(theWire);
2629       if (ToReverse)
2630       {
2631         BB.Add(theWire, anEdge.Reversed());
2632         BB.Add(theWire, E3.Reversed());
2633         BB.Add(theWire, OE.Reversed());
2634         BB.Add(theWire, E4.Reversed());
2635       }
2636       else
2637       {
2638         BB.Add(theWire, anEdge);
2639         BB.Add(theWire, E3);
2640         BB.Add(theWire, OE);
2641         BB.Add(theWire, E4);
2642       }
2643
2644       BRepLib::BuildCurves3d( theWire, myTol );
2645       theWire.Closed(Standard_True);
2646       TopoDS_Face NewFace;
2647       Handle(Geom_Surface) theSurf;
2648       BRepAdaptor_Curve BAcurve(anEdge);
2649       BRepAdaptor_Curve BAcurveOE(OE);
2650       Standard_Real fpar = BAcurve.FirstParameter();
2651       Standard_Real lpar = BAcurve.LastParameter();
2652       gp_Pnt PonE  = BAcurve.Value(fpar);
2653       gp_Pnt PonOE = BAcurveOE.Value(fpar);
2654       gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
2655       Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
2656       Standard_Boolean IsPlanar = Standard_False;
2657       if (BAcurve.GetType() == GeomAbs_Circle &&
2658         BAcurveOE.GetType() == GeomAbs_Circle)
2659       {
2660         gp_Circ aCirc = BAcurve.Circle();
2661         gp_Circ aCircOE = BAcurveOE.Circle();
2662         gp_Lin anAxisLine(aCirc.Axis());
2663         gp_Dir CircAxisDir = aCirc.Axis().Direction();
2664         if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
2665           anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
2666         { //cylinder, plane or cone
2667           if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
2668             theSurf = GC_MakeCylindricalSurface(aCirc).Value();
2669           else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
2670             IsPlanar = Standard_True;
2671             //
2672             gp_Pnt PonEL = BAcurve.Value(lpar);
2673             if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
2674               Standard_Boolean bIsHole;
2675               TopoDS_Edge aE1, aE2;
2676               TopoDS_Wire aW1, aW2;
2677               Handle(Geom_Plane) aPL;
2678               IntTools_FClass2d aClsf;
2679               //
2680               if (aCirc.Radius()>aCircOE.Radius()) {
2681                 aE1 = anEdge;
2682                 aE2 = OE;
2683               } else {
2684                 aE1 = OE;
2685                 aE2 = anEdge;
2686               }
2687               //
2688               BB.MakeWire(aW1);
2689               BB.Add(aW1, aE1);
2690               BB.MakeWire(aW2);
2691               BB.Add(aW2, aE2);
2692               //
2693               aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
2694               for (Standard_Integer i = 0; i < 2; ++i) {
2695                 TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
2696                 TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
2697                 //
2698                 TopoDS_Face aFace;
2699                 BB.MakeFace(aFace, aPL, Precision::Confusion());
2700                 BB.Add (aFace, aW);
2701                 aClsf.Init(aFace, Precision::Confusion());
2702                 bIsHole=aClsf.IsHole();
2703                 if ((bIsHole && !i) || (!bIsHole && i)) {
2704                   aW.Nullify();
2705                   BB.MakeWire(aW);
2706                   BB.Add(aW, aE.Reversed());
2707                 }
2708               }
2709               //
2710               BB.MakeFace(NewFace, aPL, Precision::Confusion());
2711               BB.Add(NewFace, aW1);
2712               BB.Add(NewFace, aW2);
2713             }
2714           }
2715           else //case of cone
2716           {
2717             gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
2718               aCirc.Radius(), aCircOE.Radius());
2719             gp_Ax3 theAx3(aCirc.Position());
2720             if (CircAxisDir * theCone.Axis().Direction() < 0.)
2721             {
2722               theAx3.ZReverse();
2723               CircAxisDir.Reverse();
2724             }
2725             theCone.SetPosition(theAx3);
2726             theSurf = new Geom_ConicalSurface(theCone);
2727           }
2728           if (!IsPlanar) {
2729             TopLoc_Location Loc;
2730             EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
2731             BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2732             Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
2733             OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
2734             BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2735             aLine2d  = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
2736             aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
2737             if (E3.IsSame(E4))
2738             {
2739               if (Coeff > 0.)
2740                 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2741               else
2742               {
2743                 BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
2744                 theWire.Nullify();
2745                 BB.MakeWire(theWire);
2746                 BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
2747                 BB.Add(theWire, E4);
2748                 BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
2749                 BB.Add(theWire, E3);
2750                 theWire.Closed(Standard_True);
2751               }
2752             }
2753             else
2754             {
2755               BB.SameParameter(E3, Standard_False);
2756               BB.SameRange(E3, Standard_False);
2757               BB.SameParameter(E4, Standard_False);
2758               BB.SameRange(E4, Standard_False);
2759               BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2760               BB.Range(E3, theSurf, Loc, 0., OffsetVal);
2761               BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2762               BB.Range(E4, theSurf, Loc, 0., OffsetVal);
2763             }
2764             NewFace = BRepLib_MakeFace(theSurf, theWire);
2765           }
2766         } //cylinder or cone
2767       } //if both edges are arcs of circles
2768       if (NewFace.IsNull())
2769       {
2770         BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
2771         if (MF.Error() == BRepLib_FaceDone)
2772         {
2773           NewFace = MF.Face();
2774           IsPlanar = Standard_True;
2775         }
2776         else //Extrusion (by thrusections)
2777         {
2778           Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
2779           Handle(Geom_TrimmedCurve) TrEdgeCurve =
2780             new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
2781           Standard_Real fparOE, lparOE;
2782           Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
2783           Handle(Geom_TrimmedCurve) TrOffsetCurve =
2784             new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
2785           GeomFill_Generator ThrusecGenerator;
2786           ThrusecGenerator.AddCurve( TrEdgeCurve );
2787           ThrusecGenerator.AddCurve( TrOffsetCurve );
2788           ThrusecGenerator.Perform( Precision::PConfusion() );
2789           theSurf = ThrusecGenerator.Surface();
2790           //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
2791           Standard_Real Uf, Ul, Vf, Vl;
2792           theSurf->Bounds(Uf, Ul, Vf, Vl);
2793           TopLoc_Location Loc;
2794           EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
2795           BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2796           OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
2797           BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2798           Standard_Real UonV1 = (ToReverse)? Ul : Uf;
2799           Standard_Real UonV2 = (ToReverse)? Uf : Ul;
2800           aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
2801           aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
2802           if (E3.IsSame(E4))
2803           {
2804             BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2805             Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
2806             BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
2807             BB.Range(E3, Vf, Vl);
2808           }
2809           else
2810           {
2811             BB.SameParameter(E3, Standard_False);
2812             BB.SameRange(E3, Standard_False);
2813             BB.SameParameter(E4, Standard_False);
2814             BB.SameRange(E4, Standard_False);
2815             BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2816             BB.Range(E3, theSurf, Loc, Vf, Vl);
2817             BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2818             BB.Range(E4, theSurf, Loc, Vf, Vl);
2819             Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
2820             BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
2821             BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
2822             Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
2823             BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
2824             BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
2825           }
2826           NewFace = BRepLib_MakeFace(theSurf, theWire);
2827         }
2828       }
2829       if (!IsPlanar)
2830       {
2831         Standard_Real fparOE = BAcurveOE.FirstParameter();
2832         Standard_Real lparOE = BAcurveOE.LastParameter();
2833         TopLoc_Location Loc;
2834         if (Abs(fpar - fparOE) > Precision::Confusion())
2835         {
2836           const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
2837           gp_Pnt2d fp2d   = EdgeLine2d->Value(fpar);
2838           gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
2839           aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
2840           Handle(Geom_Curve) aCurve;
2841           Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
2842           Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
2843           GeomAdaptor_Surface GAsurf( theSurf );
2844           Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2845           Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2846           Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2847           Standard_Real max_deviation = 0., average_deviation;
2848           GeomLib::BuildCurve3d(Precision::Confusion(),
2849             ConS, FirstPar, LastPar,
2850             aCurve, max_deviation, average_deviation);
2851           BB.UpdateEdge( anE4, aCurve, max_deviation );
2852           BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
2853           BB.Range( anE4, FirstPar, LastPar );
2854         }
2855         if (Abs(lpar - lparOE) > Precision::Confusion())
2856         {
2857           const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
2858           gp_Pnt2d lp2d   = EdgeLine2d->Value(lpar);
2859           gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
2860           aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
2861           Handle(Geom_Curve) aCurve;
2862           Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
2863           Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
2864           GeomAdaptor_Surface GAsurf( theSurf );
2865           Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2866           Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2867           Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2868           Standard_Real max_deviation = 0., average_deviation;
2869           GeomLib::BuildCurve3d(Precision::Confusion(),
2870             ConS, FirstPar, LastPar,
2871             aCurve, max_deviation, average_deviation);
2872           BB.UpdateEdge( anE3, aCurve, max_deviation );
2873           BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
2874           BB.Range( anE3, FirstPar, LastPar );
2875         }
2876       }
2877       BRepLib::SameParameter(NewFace);
2878       BRepTools::Update(NewFace);
2879       //Check orientation
2880       TopAbs_Orientation anOr = OrientationOfEdgeInFace(anEdge, aFaceOfEdge);
2881       TopAbs_Orientation OrInNewFace = OrientationOfEdgeInFace(anEdge, NewFace);
2882       if (OrInNewFace != TopAbs::Reverse(anOr))
2883         NewFace.Reverse();
2884       ///////////////////
2885       myWalls.Append(NewFace);
2886       if (ArcOnV2)
2887       {
2888         TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
2889         TopoDS_Vertex arcV1, arcV2;
2890         TopExp::Vertices(anArc, arcV1, arcV2);
2891         Standard_Boolean ArcReverse = Standard_False;
2892         if (!arcV1.IsSame(V3))
2893         {
2894           TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
2895           ArcReverse = Standard_True;
2896         }
2897         TopoDS_Edge EA1, EA2;
2898         //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
2899         EA1 = E3;
2900         EA1.Reverse();
2901         if (ToReverse)
2902           EA1.Reverse();
2903         //////////////////////////////////////////////////////
2904         if (V2.IsSame(StartVertex))
2905           EA2 = StartEdge;
2906         else
2907           EA2 = BRepLib_MakeEdge( V2, arcV2 );
2908         anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
2909         if (EA1.Orientation() == TopAbs_REVERSED)
2910           anArc.Reverse();
2911         EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
2912         TopoDS_Wire arcWire;
2913         BB.MakeWire(arcWire);
2914         BB.Add(arcWire, EA1);
2915         BB.Add(arcWire, anArc);
2916         BB.Add(arcWire, EA2);
2917         BRepLib::BuildCurves3d( arcWire, myTol );
2918         arcWire.Closed(Standard_True);
2919         TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
2920         BRepTools::Update(arcFace);
2921         myWalls.Append(arcFace);
2922         TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
2923         const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
2924         PrevEdge = CEA2;
2925         PrevVertex = V2;
2926       }
2927       else
2928       {
2929         if (isBuildFromScratch)
2930         {
2931           PrevEdge = TopoDS::Edge(E4);
2932           PrevVertex = V1;
2933           isBuildFromScratch = Standard_False;
2934         }
2935         else
2936         {
2937           PrevEdge = E3;
2938           PrevVertex = V2;
2939         }
2940       }
2941       FirstStep = Standard_False;
2942     }
2943   }
2944 }
2945
2946 //=======================================================================
2947 //function : MakeShells
2948 //purpose  : 
2949 //=======================================================================
2950
2951 void BRepOffset_MakeOffset::MakeShells ()
2952 {
2953 #ifdef OCCT_DEBUG
2954   if (ChronBuild) {  
2955     cout << " RECONSTRUCTION OF SHELLS:" << endl;
2956     Clock.Reset();
2957     Clock.Start();
2958   }
2959 #endif
2960   //
2961   // Prepare list of splits of the offset faces to make the shells
2962   TopTools_ListOfShape aLSF;
2963   const TopTools_ListOfShape& R = myImageOffset.Roots();
2964   TopTools_ListIteratorOfListOfShape it(R);
2965   //
2966   for (; it.More(); it.Next()) {
2967     TopoDS_Shape aF = it.Value();
2968     if (myThickening) //offsetted faces must change their orientations
2969       aF.Reverse();
2970     //
2971     TopTools_ListOfShape Image;
2972     myImageOffset.LastImage(aF,Image);
2973     TopTools_ListIteratorOfListOfShape it2(Image);
2974     for (; it2.More(); it2.Next()) {
2975       const TopoDS_Shape& aFIm = it2.Value();
2976       aLSF.Append(aFIm);
2977     }
2978   }
2979   //
2980   if (myThickening) {
2981     TopExp_Explorer Explo(myShape, TopAbs_FACE);
2982     for (; Explo.More(); Explo.Next()) {
2983       const TopoDS_Shape& aF = Explo.Current();
2984       aLSF.Append(aF);
2985     }
2986     //
2987     it.Initialize(myWalls);
2988     for (; it.More(); it.Next()) {
2989       const TopoDS_Shape& aF = it.Value();
2990       aLSF.Append(aF);
2991     }
2992   }
2993   //
2994   if (aLSF.IsEmpty()) {
2995     return;
2996   }
2997   //
2998   Standard_Boolean bDone = Standard_False;
2999   if ((myJoin == GeomAbs_Intersection) && myInter &&
3000       !myThickening && myFaces.IsEmpty() &&
3001       IsSolid(myShape) && myIsPlanar) {
3002     //
3003     TopoDS_Shape aShells;
3004     bDone = BuildShellsCompleteInter(aLSF, myImageOffset, aShells);
3005     if (bDone) {
3006       myOffsetShape = aShells;
3007     }
3008   }
3009   //
3010   if (!bDone) {
3011     BRepTools_Quilt Glue;
3012     TopTools_ListIteratorOfListOfShape aItLS(aLSF);
3013     for (; aItLS.More(); aItLS.Next()) {
3014       Glue.Add(aItLS.Value());
3015     }
3016     myOffsetShape = Glue.Shells();
3017   }
3018   //
3019   //Set correct value for closed flag
3020   TopExp_Explorer Explo(myOffsetShape, TopAbs_SHELL);
3021   for(; Explo.More(); Explo.Next())
3022   {
3023     TopoDS_Shape aS = Explo.Current(); 
3024     if(!aS.Closed())
3025     {
3026       if(BRep_Tool::IsClosed(aS))
3027       {
3028         aS.Closed(Standard_True);
3029       }
3030     }
3031   }
3032 }
3033
3034 //=======================================================================
3035 //function : MakeSolid
3036 //purpose  : 
3037 //=======================================================================
3038
3039 void BRepOffset_MakeOffset::MakeSolid ()
3040 {
3041  if (myOffsetShape.IsNull()) return;
3042
3043 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
3044 //  Supporting history.
3045   UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
3046   UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
3047 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
3048   TopExp_Explorer             exp;
3049   BRep_Builder                B;
3050   Standard_Integer            NbShell = 0;
3051   TopoDS_Compound             NC;
3052   TopoDS_Shape                S1;
3053   B.MakeCompound (NC);
3054
3055   TopoDS_Solid Sol;
3056   B.MakeSolid(Sol);
3057   Sol.Closed(Standard_True);
3058   Standard_Boolean aMakeSolid = (myShape.ShapeType() == TopAbs_SOLID) || myThickening;
3059   for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
3060     TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
3061     if (myThickening && myOffset > 0.)
3062       Sh.Reverse();
3063     NbShell++;
3064     if (Sh.Closed() && aMakeSolid) {
3065       B.Add(Sol,Sh);
3066     }
3067     else {
3068       B.Add (NC,Sh);
3069       if(NbShell == 1)
3070       {
3071         S1 = Sh;
3072       }
3073     }
3074   }
3075   TopoDS_Iterator anIt(Sol);
3076   Standard_Boolean SolIsNull = !anIt.More();
3077   //Checking solid
3078   if(!SolIsNull)
3079   {
3080     Standard_Integer nbs = 0;
3081     while(anIt.More()) {anIt.Next(); ++nbs;}
3082     if(nbs > 1)
3083     {
3084       BRepCheck_Analyzer aCheck(Sol, Standard_False);
3085       if(!aCheck.IsValid())
3086       {
3087         TopTools_ListOfShape aSolList;
3088         CorrectSolid(Sol, aSolList);
3089         if(!aSolList.IsEmpty())
3090         {
3091           B.Add(NC, Sol);
3092           TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
3093           for(; aSLIt.More(); aSLIt.Next())
3094           {
3095             B.Add(NC, aSLIt.Value());
3096           }
3097           SolIsNull = Standard_True;
3098         }
3099       }
3100     }
3101   }
3102   anIt.Initialize(NC);
3103   Standard_Boolean NCIsNull = !anIt.More();
3104   if((!SolIsNull) && (!NCIsNull))
3105   {
3106     B.Add(NC, Sol);
3107     myOffsetShape = NC;
3108   }
3109   else if(SolIsNull && (!NCIsNull))
3110   {
3111     if (NbShell == 1) 
3112     {
3113       myOffsetShape = S1;
3114     }
3115     else
3116     {
3117       myOffsetShape = NC;
3118     }
3119   }
3120   else if((!SolIsNull) && NCIsNull)
3121   {
3122     myOffsetShape = Sol;
3123   }
3124   else
3125   {
3126     myOffsetShape = NC;
3127   }
3128 }
3129
3130 //=======================================================================
3131 //function : SelectShells
3132 //purpose  : 
3133 //=======================================================================
3134
3135 void BRepOffset_MakeOffset::SelectShells ()
3136 {
3137   TopTools_MapOfShape FreeEdges;
3138   TopExp_Explorer exp(myShape,TopAbs_EDGE);
3139   //-------------------------------------------------------------
3140   // FreeEdges all edges that can have free border in the  
3141   // parallel shell
3142   // 1 - free borders of myShape .
3143   //-------------------------------------------------------------
3144   for ( ; exp.More(); exp.Next()) {
3145     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3146     const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
3147     if (LA.Extent() < 2) {
3148       if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
3149               FreeEdges.Add(E);                       
3150       }
3151     }  
3152   }
3153   // myShape has free borders and there are no caps
3154   // no unwinding 3d.
3155   if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
3156
3157   myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
3158 }
3159
3160 //=======================================================================
3161 //function : OffsetFacesFromShapes
3162 //purpose  : 
3163 //=======================================================================
3164
3165 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
3166 {
3167   return myInitOffsetFace;
3168 }
3169
3170 //  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
3171
3172 //=======================================================================
3173 //function : GetJoinType
3174 //purpose  : Query offset join type.
3175 //=======================================================================
3176
3177 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
3178 {
3179   return myJoin;
3180 }
3181
3182 //=======================================================================
3183 //function : OffsetEdgesFromShapes
3184 //purpose  : 
3185 //=======================================================================
3186
3187 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
3188 {
3189   return myInitOffsetEdge;
3190 }
3191
3192 //  Modified by skv - Tue Mar 15 16:20:43 2005 End
3193
3194 //=======================================================================
3195 //function : ClosingFaces
3196 //purpose  : 
3197 //=======================================================================
3198
3199 const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
3200 {
3201   return myFaces;
3202 }
3203
3204
3205
3206 //=======================================================================
3207 //function : EncodeRegularity
3208 //purpose  : 
3209 //=======================================================================
3210
3211 void BRepOffset_MakeOffset::EncodeRegularity ()
3212 {
3213 #ifdef OCCT_DEBUG
3214   if (ChronBuild) {  
3215     cout << " CODING OF REGULARITIES:" << endl;
3216     Clock.Reset();
3217     Clock.Start();
3218   }
3219 #endif
3220
3221   if (myOffsetShape.IsNull()) return;
3222   // find edges G1 in the result
3223   TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
3224
3225   BRep_Builder B;
3226   TopTools_MapOfShape MS;
3227
3228   for ( ; exp.More(); exp.Next()) {
3229     TopoDS_Edge OE  = TopoDS::Edge(exp.Current());
3230     BRepLib::BuildCurve3d(OE,myTol);
3231     TopoDS_Edge ROE = OE;
3232     
3233     if ( !MS.Add(OE)) continue;
3234       
3235     if ( myImageOffset.IsImage(OE)) 
3236       ROE = TopoDS::Edge(myImageOffset.Root(OE));
3237
3238     const TopTools_ListOfShape& LofOF    = myAsDes->Ascendant(ROE);
3239     
3240     if (LofOF.Extent() != 2) {
3241 #ifdef OCCT_DEBUG_VERB
3242     cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
3243 #endif
3244       continue;
3245     }
3246
3247     const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
3248     const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
3249     
3250     if ( F1.IsNull() || F2.IsNull()) 
3251       continue;
3252    
3253     const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
3254     const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
3255
3256     TopAbs_ShapeEnum Type1 = Root1.ShapeType();
3257     TopAbs_ShapeEnum Type2 = Root2.ShapeType();
3258  
3259     if (F1.IsSame(F2)) {      
3260       if (BRep_Tool::IsClosed(OE,F1)) {
3261         // Temporary Debug for the Bench.
3262         // Check with YFR.
3263         // In mode intersection, the edges are not coded in myInitOffsetEdge
3264         // so, manage case by case
3265         // Note DUB; for Hidden parts, it is NECESSARY to code CN 
3266         // Analytic Surfaces.
3267         if (myJoin == GeomAbs_Intersection) {
3268           BRepAdaptor_Surface BS(F1,Standard_False);
3269           GeomAbs_SurfaceType SType = BS.GetType();
3270           if (SType == GeomAbs_Cylinder ||
3271               SType == GeomAbs_Cone     ||
3272               SType == GeomAbs_Sphere   ||
3273               SType == GeomAbs_Torus      ) {
3274             B.Continuity(OE,F1,F1,GeomAbs_CN);
3275           }
3276           else {
3277             // See YFR : MaJ of myInitOffsetFace
3278           }
3279         }
3280         else if (myInitOffsetEdge.IsImage(ROE)) {
3281           if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3282             const TopoDS_Face& FRoot = TopoDS::Face(Root1);
3283             const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
3284             GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
3285             if (Conti == GeomAbs_CN) {
3286               B.Continuity(OE,F1,F1,GeomAbs_CN);
3287             }
3288             else if ( Conti > GeomAbs_C0) {
3289               B.Continuity(OE,F1,F1,GeomAbs_G1);
3290             }
3291           }
3292         }
3293       }
3294       continue;
3295     }
3296
3297
3298     //  code regularities G1 between :
3299     //    - sphere and tube : one root is a vertex, the other is an edge 
3300     //                        and the vertex is included in the edge
3301     //    - face and tube   : one root is a face, the other an edge 
3302     //                        and the edge is included in the face
3303     //    - face and face    : if two root faces are tangent in 
3304     //                        the initial shape, they will be tangent in the offset shape
3305     //    - tube and tube  : if 2 edges generating tubes are
3306     //                        tangents, the 2 will be tangent either.
3307     if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3308       TopoDS_Vertex V1,V2;
3309       TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3310       if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3311         B.Continuity(OE,F1,F2,GeomAbs_G1);
3312       }
3313     }
3314     else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3315       TopoDS_Vertex V1,V2;
3316       TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3317       if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3318         B.Continuity(OE,F1,F2,GeomAbs_G1);
3319       }
3320     }
3321     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3322       TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3323       for ( ; exp2.More(); exp2.Next()) {
3324         if ( exp2.Current().IsSame(Root2)) {
3325           B.Continuity(OE,F1,F2,GeomAbs_G1);
3326           break;
3327         }
3328       }
3329     }
3330     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
3331       TopExp_Explorer exp2(Root2,TopAbs_EDGE);
3332       for ( ; exp2.More(); exp2.Next()) {
3333         if ( exp2.Current().IsSame(Root1)) {
3334           B.Continuity(OE,F1,F2,GeomAbs_G1);
3335           break;
3336         }
3337       }
3338     }
3339     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3340     //  if two root faces are tangent in 
3341     //  the initial shape, they will be tangent in the offset shape
3342       TopTools_ListOfShape LE;
3343       BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_EDGE, LE);
3344       if ( LE.Extent() == 1) {
3345         const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
3346         if ( myAnalyse.HasAncestor(Ed)) {
3347           const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
3348           if (LI.Extent()       == 1   && 
3349               LI.First().Type() == BRepOffset_Tangent) {
3350             B.Continuity(OE,F1,F2,GeomAbs_G1);
3351           }
3352         }
3353       }
3354     }
3355     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
3356       TopTools_ListOfShape LV;
3357       BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_VERTEX, LV);
3358       if ( LV.Extent() == 1) {
3359         TopTools_ListOfShape LEdTg;
3360         myAnalyse.TangentEdges(TopoDS::Edge(Root1),
3361                                TopoDS::Vertex(LV.First()),
3362                                LEdTg);
3363         TopTools_ListIteratorOfListOfShape it(LEdTg);
3364         for (; it.More(); it.Next()) {
3365           if ( it.Value().IsSame(Root2)) {
3366             B.Continuity(OE,F1,F2,GeomAbs_G1);
3367             break;
3368           }
3369         }
3370       }
3371     }
3372   }
3373
3374 #ifdef OCCT_DEBUG
3375   if ( ChronBuild) Clock.Show();
3376 #endif
3377 }
3378
3379 //=======================================================================
3380 //function : ComputeMaxDist
3381 //purpose  : 
3382 //=======================================================================
3383 Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
3384                              const Handle(Geom_Curve)& theCrv,
3385                              const Standard_Real theFirst,
3386                              const Standard_Real theLast)
3387 {
3388   Standard_Real aMaxDist = 0.;
3389   Standard_Integer i, NCONTROL = 23;
3390   Standard_Real aPrm, aDist2;
3391   gp_Pnt aP;
3392   for (i = 0; i< NCONTROL; i++) {
3393     aPrm = ((NCONTROL - 1 - i)*theFirst + i*theLast) / (NCONTROL - 1);
3394     aP = theCrv->Value(aPrm);
3395     if (Precision::IsInfinite(aP.X()) || Precision::IsInfinite(aP.Y())
3396       || Precision::IsInfinite(aP.Z()))
3397     {
3398       return Precision::Infinite();
3399     }
3400     aDist2 = thePlane.SquareDistance(aP);
3401     if (aDist2 > aMaxDist) aMaxDist = aDist2;  
3402   }
3403   return sqrt(aMaxDist)*1.05;
3404 }
3405 //=======================================================================
3406 //function : UpDateTolerance
3407 //purpose  : 
3408 //=======================================================================
3409
3410 void UpdateTolerance (TopoDS_Shape& S,
3411                       const TopTools_IndexedMapOfShape& Faces)
3412 {
3413   BRep_Builder B;
3414   TopTools_MapOfShape View;
3415   TopoDS_Vertex V[2];
3416
3417   // The edges of caps are not modified.
3418   Standard_Integer j;
3419   for (j = 1; j <= Faces.Extent(); j++) {
3420     const TopoDS_Shape& F = Faces(j);
3421     TopExp_Explorer Exp;
3422     for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3423       View.Add(Exp.Current());
3424     }
3425   }
3426   
3427   Standard_Real Tol;
3428   TopExp_Explorer ExpF;
3429   for (ExpF.Init(S, TopAbs_FACE); ExpF.More(); ExpF.Next())
3430   {
3431     const TopoDS_Shape& F = ExpF.Current();
3432     if (Faces.Contains(F))
3433     {
3434       continue;
3435     }
3436     BRepAdaptor_Surface aBAS(TopoDS::Face(F), Standard_False);
3437     TopExp_Explorer Exp;
3438     for (Exp.Init(F, TopAbs_EDGE); Exp.More(); Exp.Next()) {
3439       TopoDS_Edge E = TopoDS::Edge(Exp.Current());
3440       Standard_Boolean isUpdated = Standard_False;
3441       if (aBAS.GetType() == GeomAbs_Plane)
3442       {
3443         //Edge does not seem to have pcurve on plane,
3444         //so EdgeCorrector does not include it in tolerance calculation
3445         Standard_Real aFirst, aLast;
3446         Handle(Geom_Curve) aCrv = BRep_Tool::Curve(E, aFirst, aLast);
3447         Standard_Real aMaxDist = ComputeMaxDist(aBAS.Plane(), aCrv, aFirst, aLast);
3448         B.UpdateEdge(E, aMaxDist);
3449         isUpdated = Standard_True;
3450       }
3451       if (View.Add(E))
3452       {
3453
3454         BRepCheck_Edge EdgeCorrector(E);
3455         Tol = EdgeCorrector.Tolerance();
3456         B.UpdateEdge(E, Tol);
3457         isUpdated = Standard_True;
3458       }
3459       if (isUpdated)
3460       {
3461         Tol = BRep_Tool::Tolerance(E);
3462         // Update the vertices.
3463         TopExp::Vertices(E, V[0], V[1]);
3464
3465         for (Standard_Integer i = 0; i <= 1; i++) {
3466           if (View.Add(V[i])) {
3467             Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
3468             TV->Tolerance(0.);
3469             BRepCheck_Vertex VertexCorrector(V[i]);
3470             B.UpdateVertex(V[i], VertexCorrector.Tolerance());
3471             // use the occasion to clean the vertices.
3472             (TV->ChangePoints()).Clear();
3473           }
3474           B.UpdateVertex(V[i], Tol);
3475         }
3476       }
3477     }
3478   }
3479 }
3480
3481 //=======================================================================
3482 //function : CorrectSolid
3483 //purpose  : 
3484 //=======================================================================
3485 void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
3486 {
3487   BRep_Builder aBB;
3488   TopoDS_Shape anOuterShell;
3489   NCollection_List<Standard_Real> aVols;
3490   Standard_Real aVolMax = 0., anOuterVol = 0.;
3491
3492   TopoDS_Iterator anIt(theSol);
3493   for(; anIt.More(); anIt.Next())
3494   {
3495     const TopoDS_Shape& aSh = anIt.Value();
3496     GProp_GProps aVProps;
3497     BRepGProp::VolumeProperties(aSh, aVProps, Standard_True);
3498     if(Abs(aVProps.Mass()) > aVolMax)
3499     {
3500       anOuterVol = aVProps.Mass();
3501       aVolMax = Abs(anOuterVol);
3502       anOuterShell = aSh; 
3503     }
3504     aVols.Append(aVProps.Mass());
3505   }
3506   //
3507   if (Abs(anOuterVol) < Precision::Confusion()) {
3508     return;
3509   }
3510   if(anOuterVol < 0.)
3511   {
3512     anOuterShell.Reverse();
3513   }
3514   TopoDS_Solid aNewSol;
3515   aBB.MakeSolid(aNewSol);
3516   aNewSol.Closed(Standard_True);
3517   aBB.Add(aNewSol, anOuterShell);
3518   BRepClass3d_SolidClassifier aSolClass(aNewSol);
3519   //
3520   anIt.Initialize(theSol);
3521   NCollection_List<Standard_Real>::Iterator aVIt(aVols);
3522   for(; anIt.More(); anIt.Next(), aVIt.Next())
3523   {
3524     TopoDS_Shell aSh = TopoDS::Shell(anIt.Value());
3525     if(aSh.IsSame(anOuterShell))
3526     {
3527       continue;
3528     }
3529     else
3530     {
3531       TopExp_Explorer aVExp(aSh, TopAbs_VERTEX);
3532       const TopoDS_Vertex& aV = TopoDS::Vertex(aVExp.Current());
3533       gp_Pnt aP = BRep_Tool::Pnt(aV);
3534       aSolClass.Perform(aP, BRep_Tool::Tolerance(aV));
3535       if(aSolClass.State() == TopAbs_IN)
3536       {
3537         if(aVIt.Value() > 0.)
3538         {
3539           aSh.Reverse();
3540         }
3541         aBB.Add(aNewSol, aSh);
3542       }
3543       else
3544       {
3545         if(aVIt.Value() < 0.)
3546         {
3547           aSh.Reverse();
3548         }
3549         TopoDS_Solid aSol;
3550         aBB.MakeSolid(aSol);
3551         aSol.Closed(Standard_True);
3552         aBB.Add(aSol, aSh);
3553         theSolList.Append(aSol);
3554       }
3555     }
3556   }
3557   theSol = aNewSol;
3558 }
3559
3560 //=======================================================================
3561 //function : CheckInputData
3562 //purpose  : Check input data for possiblity of offset perform.
3563 //=======================================================================
3564 Standard_Boolean BRepOffset_MakeOffset::CheckInputData()
3565 {
3566   // Set initial error state.
3567   myError = BRepOffset_NoError;
3568   TopoDS_Shape aTmpShape;
3569   myBadShape = aTmpShape;
3570
3571   // Non-null offset.
3572   if (Abs(myOffset) <= myTol)
3573   {
3574     Standard_Boolean isFound = Standard_False;
3575     TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset);
3576     for( ; anIter.More(); anIter.Next())
3577     {
3578       if (Abs(anIter.Value()) > myTol)
3579       {
3580         isFound = Standard_True;
3581         break;
3582       }
3583     }
3584
3585     if (!isFound)
3586     {
3587       // No face with non-null offset found.
3588       myError = BRepOffset_NullOffset;
3589       return Standard_False;
3590     }
3591   }
3592
3593   // Connectivity of input shape.
3594   if (!IsConnectedShell(myShape))
3595   {
3596     myError = BRepOffset_NotConnectedShell;
3597     return Standard_False;
3598   }
3599
3600   // Normals check and continuity check.
3601   const Standard_Integer aPntPerDim = 20; // 21 points on each dimension.
3602   Standard_Real aUmin, aUmax, aVmin, aVmax;
3603   TopExp_Explorer anExpSF(myShape, TopAbs_FACE);
3604   NCollection_Map<Handle(TopoDS_TShape)> aPresenceMap;
3605   TopLoc_Location L;
3606   gp_Pnt2d aPnt2d;
3607   for( ; anExpSF.More(); anExpSF.Next())
3608   {
3609     const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current());
3610
3611     if (aPresenceMap.Contains(aF.TShape()))
3612     {
3613       // Not perform computations with partner shapes,
3614       // since they are contain same geometry.
3615       continue;
3616     }
3617     aPresenceMap.Add(aF.TShape());
3618
3619     const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L);
3620     BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax);
3621
3622     // Continuity check.
3623     if (aSurf->Continuity() == GeomAbs_C0)
3624     {
3625       myError = BRepOffset_C0Geometry;
3626       return Standard_False;
3627     }
3628
3629     // Get degenerated points, to avoid check them.
3630     NCollection_Vector<gp_Pnt> aBad3dPnts;
3631     TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
3632     for( ; anExpFE.More(); anExpFE.Next())
3633     {
3634       const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current());
3635       if (BRep_Tool::Degenerated(aE))
3636       {
3637         aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE))));
3638       }
3639     }
3640
3641     // Geometry grid check.
3642     for(Standard_Integer i = 0; i <= aPntPerDim; i++)
3643     {
3644       Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim;
3645       for(Standard_Integer j = 0; j <= aPntPerDim; j++)
3646       {
3647         Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim;
3648
3649         myError = checkSinglePoint(aUParam, aVParam, aSurf, aBad3dPnts);
3650         if (myError != BRepOffset_NoError)
3651           return Standard_False;
3652       }
3653     }
3654
3655     // Vertex list check.
3656     TopExp_Explorer anExpFV(aF, TopAbs_VERTEX);
3657     for( ; anExpFV.More(); anExpFV.Next())
3658     {
3659       const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current());
3660       aPnt2d = BRep_Tool::Parameters(aV, aF);
3661
3662       myError = checkSinglePoint(aPnt2d.X(), aPnt2d.Y(), aSurf, aBad3dPnts);
3663       if (myError != BRepOffset_NoError)
3664         return Standard_False;
3665     }
3666   }
3667
3668   return Standard_True;
3669 }
3670
3671
3672 //=======================================================================
3673 //function : GetBadShape
3674 //purpose  : Get shape where problems detected.
3675 //=======================================================================
3676 const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const
3677 {
3678   return myBadShape;
3679 }
3680
3681 //=======================================================================
3682 //function : RemoveInternalEdges
3683 //purpose  : 
3684 //=======================================================================
3685 void BRepOffset_MakeOffset::RemoveInternalEdges()
3686 {
3687   Standard_Boolean bRemoveWire, bRemoveEdge;
3688   TopExp_Explorer aExpF, aExpW, aExpE;
3689   TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
3690   //
3691   TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF);
3692   //
3693   aExpF.Init(myOffsetShape, TopAbs_FACE);
3694   for (; aExpF.More(); aExpF.Next()) {
3695     TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
3696     //
3697     TopTools_ListOfShape aLIW;
3698     //
3699     aExpW.Init(aF, TopAbs_WIRE);
3700     for (; aExpW.More(); aExpW.Next()) {
3701       TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current();
3702       //
3703       bRemoveWire = Standard_True;
3704       TopTools_ListOfShape aLIE;
3705       //
3706       aExpE.Init(aW, TopAbs_EDGE);
3707       for (; aExpE.More(); aExpE.Next()) {
3708         const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
3709         if (aE.Orientation() != TopAbs_INTERNAL) {
3710           bRemoveWire = Standard_False;
3711           continue;
3712         }
3713         //
3714         const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE);
3715         bRemoveEdge = (aLF.Extent() == 1);
3716         if (bRemoveEdge) {
3717           aLIE.Append(aE);
3718         }
3719         else {
3720           bRemoveWire = Standard_False;
3721         }
3722       }
3723       //
3724       if (bRemoveWire) {
3725         aLIW.Append(aW);
3726       }
3727       else if (aLIE.Extent()) {
3728         RemoveShapes(aW, aLIE);
3729       }
3730     }
3731     //
3732     if (aLIW.Extent()) {
3733       RemoveShapes(aF, aLIW);
3734     }
3735   }
3736 }
3737
3738 //=======================================================================
3739 // static methods implementation
3740 //=======================================================================
3741
3742 //=======================================================================
3743 //function : checkSinglePoint
3744 //purpose  : Check single point on surface for bad normals
3745 //=======================================================================
3746 BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
3747                                   const Standard_Real theVParam,
3748                                   const Handle(Geom_Surface)& theSurf,
3749                                   const NCollection_Vector<gp_Pnt>& theBadPoints)
3750 {
3751   gp_Pnt aPnt;
3752   gp_Vec aD1U, aD1V;
3753   theSurf->D1(theUParam, theVParam, aPnt, aD1U, aD1V);
3754
3755   if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
3756       aD1V.SquareMagnitude() < Precision::SquareConfusion() )
3757   {
3758     Standard_Boolean isKnownBadPnt = Standard_False;
3759     for(Standard_Integer anIdx  = theBadPoints.Lower();
3760                          anIdx <= theBadPoints.Upper();
3761                        ++anIdx)
3762     {
3763       if (aPnt.SquareDistance(theBadPoints(anIdx)) < Precision::SquareConfusion())
3764       {
3765         isKnownBadPnt = Standard_True;
3766         break;
3767       }
3768     } // for(Standard_Integer anIdx  = theBadPoints.Lower();
3769
3770     if (!isKnownBadPnt)
3771     {
3772       return BRepOffset_BadNormalsOnGeometry;
3773     }
3774     else
3775     {
3776       return BRepOffset_NoError;
3777     }
3778   } //  if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
3779
3780   if (aD1U.IsParallel(aD1V, Precision::Confusion()))
3781   {
3782     // Isolines are collinear.
3783     return BRepOffset_BadNormalsOnGeometry;
3784   }
3785
3786   return BRepOffset_NoError;
3787 }
3788
3789 //=======================================================================
3790 //function : RemoveShapes
3791 //purpose  : Removes the shapes <theLS> from the shape <theS>
3792 //=======================================================================
3793 void RemoveShapes(TopoDS_Shape& theS,
3794                   const TopTools_ListOfShape& theLS)
3795 {
3796   BRep_Builder aBB;
3797   //
3798   Standard_Boolean bFree = theS.Free();
3799   theS.Free(Standard_True);
3800   //
3801   TopTools_ListIteratorOfListOfShape aIt(theLS);
3802   for (; aIt.More(); aIt.Next()) {
3803     const TopoDS_Shape& aSI = aIt.Value();
3804     aBB.Remove(theS, aSI);
3805   }
3806   //
3807   theS.Free(bFree);
3808 }
3809
3810 //=======================================================================
3811 //function : UpdateHistory
3812 //purpose  : Updates the history information
3813 //=======================================================================
3814 void UpdateHistory(const TopTools_ListOfShape& theLF,
3815                    BOPAlgo_Builder& theGF,
3816                    BRepAlgo_Image& theImage)
3817 {
3818   TopTools_ListIteratorOfListOfShape aIt(theLF);
3819   for (; aIt.More(); aIt.Next()) {
3820     const TopoDS_Shape& aF = aIt.Value();
3821     const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
3822     if (aLFIm.Extent()) {
3823       if (theImage.HasImage(aF)) {
3824         theImage.Add(aF, aLFIm);
3825       }
3826       else {
3827         theImage.Bind(aF, aLFIm);
3828       }
3829     }
3830   }
3831 }
3832
3833 //=======================================================================
3834 //function : IntersectEdges
3835 //purpose  : 
3836 //=======================================================================
3837 void BRepOffset_MakeOffset::IntersectEdges(const TopoDS_Shape& theShape,
3838                                            BRepOffset_DataMapOfShapeOffset& theMapSF,
3839                                            TopTools_DataMapOfShapeShape& theMES,
3840                                            TopTools_DataMapOfShapeShape& theBuild,
3841                                            Handle(BRepAlgo_AsDes)& theAsDes,
3842                                            Handle(BRepAlgo_AsDes)& theAsDes2d)
3843 {
3844   Standard_Real aTolF;
3845   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
3846   TopExp_Explorer aExp(theShape, TopAbs_FACE);
3847   // intersect edges created from edges
3848   TopTools_IndexedMapOfShape aMFV;
3849   for (; aExp.More(); aExp.Next()) {
3850     const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
3851     aTolF = BRep_Tool::Tolerance(aF);
3852     BRepOffset_Inter2d::ConnexIntByInt
3853       (aF, theMapSF(aF), theMES, theBuild, theAsDes2d, myOffset, aTolF, aMFV, aDMVV);
3854   }
3855   // intersect edges created from vertices
3856   Standard_Integer i, aNbF = aMFV.Extent();
3857   for (i = 1; i <= aNbF; ++i) {
3858     const TopoDS_Face& aF = TopoDS::Face(aMFV(i));
3859     aTolF = BRep_Tool::Tolerance(aF);
3860     BRepOffset_Inter2d::ConnexIntByIntInVert
3861       (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, aTolF, aDMVV);
3862   }
3863   //
3864   // fuse vertices on edges
3865   BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d);
3866 }
3867
3868 //=======================================================================
3869 //function : TrimEdges
3870 //purpose  : 
3871 //=======================================================================
3872 void TrimEdges(const TopoDS_Shape& theShape,
3873                const Standard_Real theOffset,
3874                BRepOffset_DataMapOfShapeOffset& theMapSF,
3875                TopTools_DataMapOfShapeShape& theMES,
3876                TopTools_DataMapOfShapeShape& theBuild,
3877                Handle(BRepAlgo_AsDes)& theAsDes,
3878                Handle(BRepAlgo_AsDes)& theAsDes2d,
3879                TopTools_IndexedMapOfShape& theNewEdges,
3880                TopTools_DataMapOfShapeShape& theETrimEInf,
3881                TopTools_DataMapOfShapeListOfShape& theEdgesOrigins)
3882 {
3883   TopExp_Explorer Exp,Exp2,ExpC;
3884   TopoDS_Shape    NE;
3885   TopoDS_Edge     TNE;
3886   TopoDS_Face     NF;
3887   //
3888   for (Exp.Init(theShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
3889     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
3890     NF = theMapSF(FI).Face();
3891     if (theMES.IsBound(NF)) {
3892       NF = TopoDS::Face(theMES(NF));
3893     }
3894     //
3895     TopTools_MapOfShape View;
3896     TopTools_IndexedMapOfShape VEmap;
3897     Standard_Integer i, aNb;
3898     //
3899     TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
3900     TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
3901     //
3902     aNb = VEmap.Extent();
3903     for (i = 1; i <= aNb; ++i) {
3904       const TopoDS_Shape& aS = VEmap(i);
3905       if (!View.Add(aS)) {
3906         continue;
3907       }
3908       //
3909       if (theBuild.IsBound(aS)) {
3910         NE = theBuild(aS);
3911         // keep connection to original edges
3912         ExpC.Init(NE, TopAbs_EDGE);
3913         for (; ExpC.More(); ExpC.Next()) {
3914           const TopoDS_Edge& NEC = TopoDS::Edge(ExpC.Current());
3915           TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NEC);
3916           if (!pLEOr) {
3917             pLEOr = theEdgesOrigins.Bound(NEC, TopTools_ListOfShape());
3918           }
3919           AppendToList(*pLEOr, aS);
3920         }
3921         // trim edges
3922         if (NE.ShapeType() == TopAbs_EDGE) {
3923           if (theNewEdges.Add(NE)) {
3924             TrimEdge (TopoDS::Edge(NE),theAsDes2d,theAsDes, theETrimEInf);
3925           }
3926         }
3927         else {
3928           //------------------------------------------------------------
3929           // The Intersections are on several edges.
3930           // The pieces without intersections with neighbors  
3931           // are removed from AsDes.
3932           //------------------------------------------------------------
3933           for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
3934             TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
3935             if (theNewEdges.Add(NEC)) {
3936               if (!theAsDes2d->Descendant(NEC).IsEmpty()) {
3937                 TrimEdge (NEC,theAsDes2d, theAsDes, theETrimEInf);
3938               }
3939               else {
3940                 if (theAsDes->HasAscendant(NEC)) {
3941                   theAsDes->Remove(NEC);
3942                 }
3943               }
3944             }
3945           }
3946         }
3947       }
3948       else {
3949         if (aS.ShapeType() != TopAbs_EDGE) {
3950           continue;
3951         }
3952         //
3953         NE = theMapSF(FI).Generated(aS);
3954         //// modified by jgv, 19.12.03 for OCC4455 ////
3955         NE.Orientation(aS.Orientation());
3956         //
3957         TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NE);
3958         if (!pLEOr) {
3959           pLEOr = theEdgesOrigins.Bound(NE, TopTools_ListOfShape());
3960         }
3961         AppendToList(*pLEOr, aS);
3962         //
3963         if (theMES.IsBound(NE)) {
3964           NE = theMES(NE);
3965           NE.Orientation(aS.Orientation());
3966           if (theNewEdges.Add(NE)) {
3967             TrimEdge (TopoDS::Edge(NE), theAsDes2d, theAsDes, theETrimEInf);
3968           } 
3969         }
3970         else {
3971           TopoDS_Edge& anEdge = TopoDS::Edge(NE);
3972           BRepAdaptor_Curve aBAC(anEdge);
3973           if (aBAC.GetType() == GeomAbs_Line) {
3974             TopoDS_Edge aNewEdge;
3975             BRepOffset_Inter2d::ExtentEdge(anEdge, aNewEdge, theOffset);
3976             theETrimEInf.Bind(anEdge, aNewEdge);
3977           }
3978         }
3979         theAsDes->Add(NF,NE);
3980       } 
3981     }
3982   }
3983 }
3984
3985 //=======================================================================
3986 //function : TrimEdge
3987 //purpose  : Trim the edge of the largest of descendants in AsDes2d.
3988 //           Order in AsDes two vertices that have trimmed the edge.
3989 //=======================================================================
3990 void TrimEdge(TopoDS_Edge&                  NE,
3991               const Handle(BRepAlgo_AsDes)& AsDes2d,
3992               Handle(BRepAlgo_AsDes)& AsDes,
3993               TopTools_DataMapOfShapeShape& theETrimEInf)
3994 {
3995   TopoDS_Edge aSourceEdge;
3996   TopoDS_Vertex V1,V2;
3997   Standard_Real aT1, aT2;
3998   //
3999   TopExp::Vertices(NE, V1, V2);
4000   BRep_Tool::Range(NE, aT1, aT2);
4001   //
4002   BOPTools_AlgoTools::MakeSplitEdge(NE, V1, aT1, V2, aT2, aSourceEdge);
4003   //
4004   //
4005   Standard_Real aSameParTol = Precision::Confusion();
4006   
4007   Standard_Real U = 0.;
4008   Standard_Real UMin =  Precision::Infinite();
4009   Standard_Real UMax = -UMin;
4010
4011   const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
4012   //
4013   Standard_Boolean bTrim = Standard_False;
4014   //
4015   if (LE.Extent() > 1) {
4016     TopTools_ListIteratorOfListOfShape it (LE);
4017     for (; it.More(); it.Next()) {
4018       TopoDS_Vertex V = TopoDS::Vertex(it.Value());
4019       if (NE.Orientation() == TopAbs_REVERSED)
4020         V.Reverse();
4021       //V.Orientation(TopAbs_INTERNAL);
4022       if (!FindParameter(V, NE, U)) {
4023         Standard_Real f, l;
4024         Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
4025         gp_Pnt thePoint = BRep_Tool::Pnt(V);
4026         GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
4027         if (Projector.NbPoints() == 0)
4028           throw Standard_ConstructionError("BRepOffset_MakeOffset::TrimEdge no projection");
4029         U = Projector.LowerDistanceParameter();
4030       }
4031       if (U < UMin) {
4032         UMin = U; V1   = V;
4033       }
4034       if (U > UMax) {
4035         UMax = U; V2   = V;
4036       }
4037     }
4038     //
4039     if (V1.IsNull() || V2.IsNull()) {
4040       throw Standard_ConstructionError("BRepOffset_MakeOffset::TrimEdge");
4041     }
4042     if (!V1.IsSame(V2)) {
4043       NE.Free( Standard_True );
4044       BRep_Builder B;
4045       TopAbs_Orientation Or = NE.Orientation();
4046       NE.Orientation(TopAbs_FORWARD);
4047       TopoDS_Vertex VF,VL;
4048       TopExp::Vertices (NE,VF,VL);
4049       B.Remove(NE,VF);
4050       B.Remove(NE,VL);
4051       B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
4052       B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
4053       B.Range(NE,UMin,UMax);
4054       NE.Orientation(Or);
4055       AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
4056       AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
4057       BRepLib::SameParameter(NE, aSameParTol, Standard_True);
4058       //
4059       bTrim = Standard_True;
4060     }
4061   }
4062   //
4063   if (!bTrim) {
4064     BRepAdaptor_Curve aBAC(NE);
4065     if (aBAC.GetType() == GeomAbs_Line) {
4066       if (AsDes->HasAscendant(NE)) {
4067         AsDes->Remove(NE);
4068       }
4069     }
4070   }
4071   else
4072   {
4073     if (!theETrimEInf.IsBound(NE)) {
4074       theETrimEInf.Bind(NE, aSourceEdge);
4075     }
4076   }
4077 }
4078
4079 //=======================================================================
4080 //function : GetEnlargedFaces
4081 //purpose  : 
4082 //=======================================================================
4083 void GetEnlargedFaces(const TopoDS_Shape& theShape,
4084                       const BRepOffset_DataMapOfShapeOffset& theMapSF,
4085                       const TopTools_DataMapOfShapeShape& theMES,
4086                       TopTools_DataMapOfShapeShape& theFacesOrigins,
4087                       BRepAlgo_Image& theImage,
4088                       TopTools_ListOfShape& theLSF)
4089 {
4090   TopExp_Explorer aExp(theShape, TopAbs_FACE);
4091   for (; aExp.More(); aExp.Next()) {
4092     const TopoDS_Shape& FI  = aExp.Current();
4093     const TopoDS_Shape& OFI = theMapSF(FI).Face();
4094     if (theMES.IsBound(OFI)) {
4095       const TopoDS_Face& aLocalFace = TopoDS::Face(theMES(OFI));
4096       theLSF.Append(aLocalFace);
4097       theImage.SetRoot(aLocalFace);
4098       //
4099       theFacesOrigins.Bind(aLocalFace, FI);
4100     }
4101   }
4102 }
4103
4104 //=======================================================================
4105 //function : BuildShellsCompleteInter
4106 //purpose  : Make the shells from list of faces using MakerVolume algorithm.
4107 //           In case there will be more than just one solid, it will be
4108 //           rebuilt using only outer faces.
4109 //=======================================================================
4110 Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
4111                                           BRepAlgo_Image& theImage,
4112                                           TopoDS_Shape& theShells)
4113 {
4114   // make solids
4115   BOPAlgo_MakerVolume aMV1;
4116   aMV1.SetArguments(theLF);
4117   // we need to intersect the faces to process the tangential faces
4118   aMV1.SetIntersect(Standard_True);
4119   aMV1.SetAvoidInternalShapes(Standard_True);
4120   aMV1.Perform();
4121   //
4122   Standard_Boolean bDone = ! aMV1.HasErrors();
4123   if (!bDone) {
4124     return bDone;
4125   }
4126   //
4127   UpdateHistory(theLF, aMV1, theImage);
4128   //
4129   const TopoDS_Shape& aResult1 = aMV1.Shape();
4130   if (aResult1.ShapeType() == TopAbs_SOLID) {
4131     // result is the alone solid, nothing to do
4132     return GetSubShapes(aResult1, TopAbs_SHELL, theShells);
4133   }
4134
4135   // Allocators for effective memory allocations
4136   // Global allocator for the long-living containers
4137   Handle(NCollection_IncAllocator) anAllocGlob = new NCollection_IncAllocator;
4138   // Local allocator for the local containers
4139   Handle(NCollection_IncAllocator) anAllocLoc = new NCollection_IncAllocator;
4140
4141   // Since the <theImage> object does not support multiple ancestors,
4142   // prepare local copy of the origins, which will be used to resolve
4143   // non-manifold solids produced by Maker Volume algorithm by comparison
4144   // of the normal directions of the split faces with their origins.
4145   TopTools_DataMapOfShapeListOfShape anOrigins(1, anAllocGlob);
4146   TopTools_ListIteratorOfListOfShape aItLR(theImage.Roots());
4147   for (; aItLR.More(); aItLR.Next())
4148   {
4149     const TopoDS_Shape& aFR = aItLR.Value();
4150
4151     // Reset the local allocator
4152     anAllocLoc->Reset();
4153     // Find the last splits of the root face, including the ones
4154     // created during MakeVolume operation
4155     TopTools_ListOfShape aLFIm(anAllocLoc);
4156     theImage.LastImage(aFR, aLFIm);
4157
4158     TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4159     for (; aItLFIm.More(); aItLFIm.Next())
4160     {
4161       const TopoDS_Shape& aFIm = aItLFIm.Value();
4162       TopTools_ListOfShape *pLFOr = anOrigins.ChangeSeek(aFIm);
4163       if (!pLFOr) {
4164         pLFOr = anOrigins.Bound(aFIm, TopTools_ListOfShape(anAllocGlob));
4165       }
4166       pLFOr->Append(aFR);
4167     }
4168   }
4169
4170   // Reset the local allocator
4171   anAllocLoc->Reset();
4172   // It is necessary to rebuild the solids, avoiding internal faces
4173   // Map faces to solids
4174   TopTools_IndexedDataMapOfShapeListOfShape aDMFS(1, anAllocLoc);
4175   TopExp::MapShapesAndAncestors(aResult1, TopAbs_FACE, TopAbs_SOLID, aDMFS);
4176   //
4177   Standard_Integer i, aNb = aDMFS.Extent();
4178   bDone = (aNb > 0);
4179   if (!bDone) {
4180     // unable to build any solid
4181     return bDone;
4182   }
4183   //
4184   // get faces attached to only one solid
4185   TopTools_ListOfShape aLF(anAllocLoc);
4186   for (i = 1; i <= aNb; ++i) {
4187     const TopTools_ListOfShape& aLS = aDMFS(i);
4188     if (aLS.Extent() == 1) {
4189       const TopoDS_Shape& aF = aDMFS.FindKey(i);
4190       aLF.Append(aF);
4191     }
4192   }
4193   //
4194   // make solids from the new list
4195   BOPAlgo_MakerVolume aMV2;
4196   aMV2.SetArguments(aLF);
4197   // no need to intersect this time
4198   aMV2.SetIntersect(Standard_False);
4199   aMV2.SetAvoidInternalShapes(Standard_True);
4200   aMV2.Perform();
4201   bDone = ! aMV2.HasErrors();
4202   if (!bDone) {
4203     return bDone;
4204   }
4205   //
4206   const TopoDS_Shape& aResult2 = aMV2.Shape();
4207   if (aResult2.ShapeType() == TopAbs_SOLID) {
4208     return GetSubShapes(aResult2, TopAbs_SHELL, theShells);
4209   }
4210   //
4211   TopExp_Explorer aExp(aResult2, TopAbs_FACE);
4212   bDone = aExp.More();
4213   if (!bDone) {
4214     return bDone;
4215   }
4216   //
4217   aLF.Clear();
4218   aDMFS.Clear();
4219   anAllocLoc->Reset();
4220
4221   // the result is non-manifold - resolve it comparing normal
4222   // directions of the offset faces and original faces
4223   for (; aExp.More(); aExp.Next())
4224   {
4225     const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
4226     const TopTools_ListOfShape* pLFOr = anOrigins.Seek(aF);
4227     if (!pLFOr)
4228     {
4229       Standard_ASSERT_INVOKE("BRepOffset_MakeOffset::BuildShellsCompleteInterSplit(): "
4230                              "Origins map does not contain the split face");
4231       continue;
4232     }
4233     // Check orientation
4234     TopTools_ListIteratorOfListOfShape aItLOr(*pLFOr);
4235     for (; aItLOr.More(); aItLOr.Next())
4236     {
4237       const TopoDS_Face& aFOr = TopoDS::Face(aItLOr.Value());
4238       if (BRepOffset_Tool::CheckPlanesNormals(aF, aFOr))
4239       {
4240         aLF.Append(aF);
4241         break;
4242       }
4243     }
4244   }
4245   //
4246   // make solid from most outer faces with correct normal direction
4247   BOPAlgo_MakerVolume aMV3;
4248   aMV3.SetArguments(aLF);
4249   aMV3.SetIntersect(Standard_False);
4250   aMV3.SetAvoidInternalShapes(Standard_True);
4251   aMV3.Perform();
4252   bDone = ! aMV3.HasErrors();
4253   if (!bDone) {
4254     return bDone;
4255   }
4256   //
4257   const TopoDS_Shape& aResult3 = aMV3.Shape();
4258   return GetSubShapes(aResult3, TopAbs_SHELL, theShells);
4259 }
4260
4261 //=======================================================================
4262 //function : GetSubShapes
4263 //purpose  : 
4264 //=======================================================================
4265 Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
4266                               const TopAbs_ShapeEnum theSSType,
4267                               TopoDS_Shape& theResult)
4268 {
4269   TopExp_Explorer aExp(theShape, theSSType);
4270   if (!aExp.More()) {
4271     return Standard_False;
4272   }
4273   //
4274   TopoDS_Compound aResult;
4275   BRep_Builder().MakeCompound(aResult);
4276   //
4277   for (; aExp.More(); aExp.Next()) {
4278     const TopoDS_Shape& aSS = aExp.Current();
4279     BRep_Builder().Add(aResult, aSS);
4280   }
4281   theResult = aResult;
4282   return Standard_True;
4283 }
4284
4285 //=======================================================================
4286 //function : IsPlanar
4287 //purpose  : Checks if all the faces of the shape are planes
4288 //=======================================================================
4289 Standard_Boolean IsPlanar(const TopoDS_Shape& theS)
4290 {
4291   TopExp_Explorer aExp(theS, TopAbs_FACE);
4292   for (; aExp.More(); aExp.Next()) {
4293     const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
4294     BRepAdaptor_Surface aBAS(aF, Standard_False);
4295     if (aBAS.GetType() != GeomAbs_Plane) {
4296       break;
4297     }
4298   }
4299   return !aExp.More();
4300 }
4301
4302 //=======================================================================
4303 //function : IsSolid
4304 //purpose  : Checks if the shape is solid
4305 //=======================================================================
4306 Standard_Boolean IsSolid(const TopoDS_Shape& theS)
4307 {
4308   TopExp_Explorer aExp(theS, TopAbs_SOLID);
4309   return aExp.More();
4310 }
4311
4312 //=======================================================================
4313 //function : AppendToList
4314 //purpose  : Add to a list only unique elements
4315 //=======================================================================
4316 void AppendToList(TopTools_ListOfShape& theList,
4317                   const TopoDS_Shape& theShape)
4318 {
4319   TopTools_ListIteratorOfListOfShape aIt(theList);
4320   for (; aIt.More(); aIt.Next()) {
4321     const TopoDS_Shape& aS = aIt.Value();
4322     if (aS.IsSame(theShape)) {
4323       return;
4324     }
4325   }
4326   theList.Append(theShape);
4327 }