0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[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           std::cout <<"Vertex on at least 3 edges."<<std::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           std::cout <<"Vertex on more than 3 edges."<<std::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     std::cout <<" distmin between VP : "<<distmin<<std::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         std::cout << "OffsetShape does not contain a FACES." << std::endl;
957         }
958 #endif
959       }
960 #ifdef OCCT_DEBUG
961     else
962       {
963       std::cout << "OffsetShape is null!" << std::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     std::cout << " CONSTRUCTION OF OFFSETS :" << std::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     std::cout << " CONSTRUCTION OF OFFSETS :" << std::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     std::cout << " AUTODEBOUCLAGE:" << std::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     Standard_Integer nbs = Sol.NbChildren();
2233     Standard_Boolean SolIsNull = (nbs == 0);
2234     //Checking solid
2235     if (nbs > 1)
2236     {
2237       BRepCheck_Analyzer aCheck (Sol, Standard_False);
2238       if (!aCheck.IsValid ())
2239       {
2240         TopTools_ListOfShape aSolList;
2241         CorrectSolid (Sol, aSolList);
2242         if (!aSolList.IsEmpty ())
2243         {
2244           BB.Add (NC, Sol);
2245           TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
2246           for (; aSLIt.More (); aSLIt.Next ())
2247           {
2248             BB.Add (NC, aSLIt.Value ());
2249           }
2250           SolIsNull = Standard_True;
2251         }
2252       }
2253     }
2254     //
2255     Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
2256     if((!SolIsNull) && (!NCIsNull))
2257     {
2258       BB.Add(NC, Sol);
2259       myOffsetShape = NC;
2260     }
2261     else if(SolIsNull && (!NCIsNull))
2262     {
2263       if (NbShell == 1) 
2264       {
2265         myOffsetShape = S1;
2266       }
2267       else
2268       {
2269         myOffsetShape = NC;
2270       }
2271     }
2272     else if((!SolIsNull) && NCIsNull)
2273     {
2274       myOffsetShape = Sol;
2275     }
2276     else
2277     {
2278       myOffsetShape = NC;
2279     }
2280   }
2281 }
2282
2283
2284 //=======================================================================
2285 //function : Intersection3D
2286 //purpose  : 
2287 //=======================================================================
2288
2289 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
2290 {
2291 #ifdef OCCT_DEBUG
2292   if (ChronBuild) {
2293     std::cout << " INTERSECTION 3D:" << std::endl;
2294     Clock.Reset();
2295     Clock.Start();  
2296   }
2297 #endif
2298
2299   // In the Complete Intersection mode, implemented currently for planar
2300   // solids only, there is no need to intersect the faces here.
2301   // This intersection will be performed in the method BuildShellsCompleteInter
2302   // where the special treatment is applied to produced faces.
2303   //
2304   // Make sure to match the parameters in which the method
2305   // BuildShellsCompleteInter is called.
2306   if (myInter && (myJoin == GeomAbs_Intersection) && myIsPlanar &&
2307       !myThickening && myFaces.IsEmpty() && IsSolid(myShape))
2308     return;
2309
2310
2311   TopTools_ListOfShape OffsetFaces;  // list of faces // created.
2312   MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2313
2314   if (!myFaces.IsEmpty()) {     
2315     Standard_Boolean InSide = (myOffset < 0.); // Temporary
2316     // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2317     // between the cap and the part.
2318
2319     if (myJoin == GeomAbs_Arc) 
2320       Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge);
2321   }
2322   if (myInter) {
2323     //-------------
2324     //Complete.
2325     //-------------
2326     Inter.CompletInt (OffsetFaces,myInitOffsetFace);
2327     TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
2328     if (myJoin == GeomAbs_Intersection) {
2329       BRepOffset_Tool::CorrectOrientation (myShape,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2330     }
2331   }
2332   else {
2333     //--------------------------------
2334     // Only between neighbor faces.
2335     //--------------------------------
2336     Inter.ConnexIntByArc(OffsetFaces,myShape,myAnalyse,myInitOffsetFace);
2337   }
2338 #ifdef OCCT_DEBUG
2339   if ( ChronBuild) Clock.Show();
2340 #endif
2341 }
2342
2343 //=======================================================================
2344 //function : Intersection2D
2345 //purpose  : 
2346 //=======================================================================
2347
2348 void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Modif,
2349                                            const TopTools_IndexedMapOfShape& NewEdges)
2350 {
2351 #ifdef OCCT_DEBUG
2352   if (ChronBuild) {
2353     std::cout << " INTERSECTION 2D:" << std::endl;
2354     Clock.Reset();
2355     Clock.Start();  
2356   }
2357 #endif
2358   //--------------------------------------------------------
2359   // calculate intersections2d on faces concerned by 
2360   // intersection3d
2361   //---------------------------------------------------------
2362   //TopTools_MapIteratorOfMapOfShape it(Modif);
2363   //-----------------------------------------------
2364   // Intersection of edges 2 by 2.
2365   //-----------------------------------------------
2366   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
2367   Standard_Integer i;
2368   for (i = 1; i <= Modif.Extent(); i++) {
2369     const TopoDS_Face& F  = TopoDS::Face(Modif(i));
2370     BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol, aDMVV);
2371   }
2372   //
2373   BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes);
2374   //
2375 #ifdef OCCT_DEBUG
2376   if (AffichInt2d) {
2377     DEBVerticesControl (NewEdges,myAsDes);
2378   }
2379   if ( ChronBuild) Clock.Show();
2380 #endif
2381 }
2382
2383
2384 //=======================================================================
2385 //function : MakeLoops
2386 //purpose  : 
2387 //=======================================================================
2388
2389 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
2390 {
2391 #ifdef OCCT_DEBUG
2392   if (ChronBuild) {
2393      std::cout << " DEBOUCLAGE 2D:" << std::endl;
2394      Clock.Reset();
2395      Clock.Start(); 
2396   }
2397 #endif
2398   //TopTools_MapIteratorOfMapOfShape    it(Modif);
2399   TopTools_ListOfShape                LF,LC;
2400   //-----------------------------------------
2401   // unwinding of faces // modified.
2402   //-----------------------------------------
2403   Standard_Integer i;
2404   for (i = 1; i <= Modif.Extent(); i++) { 
2405     if (!myFaces.Contains(Modif(i)))
2406       LF.Append(Modif(i));
2407   }
2408   //
2409   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2410     BuildSplitsOfTrimmedFaces(LF, myAsDes, myImageOffset);
2411   }
2412   else {
2413     myMakeLoops.Build(LF,myAsDes,myImageOffset);
2414   }
2415
2416   //-----------------------------------------
2417   // unwinding of caps.
2418   //-----------------------------------------
2419   for (i = 1; i <= myFaces.Extent(); i++)
2420     LC.Append(myFaces(i));
2421
2422   Standard_Boolean   InSide = 1;
2423   if (myOffset > 0 ) InSide = 0;
2424   myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide);
2425
2426 #ifdef OCCT_DEBUG
2427   if ( ChronBuild) Clock.Show();
2428 #endif
2429 }
2430
2431 //=======================================================================
2432 //function : MakeFaces
2433 //purpose  : Reconstruction of topologically unchanged faces that
2434 //           share edges that were reconstructed.
2435 //=======================================================================
2436
2437 void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
2438 {
2439 #ifdef OCCT_DEBUG
2440   if (ChronBuild) {  
2441     std::cout << " RECONSTRUCTION OF FACES:" << std::endl;
2442     Clock.Reset();
2443     Clock.Start();
2444   }
2445 #endif
2446   TopTools_ListIteratorOfListOfShape itr;
2447   const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
2448   TopTools_ListOfShape        LOF;
2449   //----------------------------------
2450   // Loop on all faces //.
2451   //----------------------------------
2452   for (itr.Initialize(Roots); itr.More(); itr.Next()) {
2453     TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
2454     if (!myImageOffset.HasImage(F)) {
2455       LOF.Append(F);
2456     }
2457   }
2458   //
2459   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2460     BuildSplitsOfTrimmedFaces(LOF, myAsDes, myImageOffset);
2461   }
2462   else {
2463     myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
2464   }
2465   
2466 #ifdef OCCT_DEBUG
2467   if ( ChronBuild) Clock.Show();
2468 #endif
2469 }
2470
2471 //=======================================================================
2472 //function : UpdateInitOffset
2473 //purpose  : Update and cleaning of myInitOffset 
2474 //=======================================================================
2475 static void UpdateInitOffset (BRepAlgo_Image&         myInitOffset,
2476                               BRepAlgo_Image&         myImageOffset,
2477                               const TopoDS_Shape&     myOffsetShape,
2478                               const TopAbs_ShapeEnum &theShapeType) // skv
2479 {
2480   BRepAlgo_Image NIOF;
2481   const TopTools_ListOfShape& Roots = myInitOffset.Roots();
2482   TopTools_ListIteratorOfListOfShape it(Roots);
2483   for (; it.More(); it.Next()) {
2484     NIOF.SetRoot (it.Value());    
2485   }
2486   for (it.Initialize(Roots); it.More(); it.Next()) {
2487     const TopoDS_Shape& SI = it.Value();
2488     TopTools_ListOfShape LI;
2489     TopTools_ListOfShape L1;
2490     myInitOffset.LastImage(SI,L1);
2491     TopTools_ListIteratorOfListOfShape itL1(L1);
2492     for (; itL1.More(); itL1.Next()) {
2493       const TopoDS_Shape& O1 = itL1.Value();
2494       TopTools_ListOfShape L2;
2495       myImageOffset.LastImage(O1,L2);
2496       LI.Append(L2);
2497     }
2498     NIOF.Bind(SI,LI);
2499   }
2500 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
2501 //  Supporting history.
2502 //   NIOF.Filter(myOffsetShape,TopAbs_FACE);
2503   NIOF.Filter(myOffsetShape, theShapeType);
2504 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
2505   myInitOffset = NIOF;
2506 }
2507
2508 //=======================================================================
2509 //function : MakeMissingWalls
2510 //purpose  : 
2511 //=======================================================================
2512 void BRepOffset_MakeOffset::MakeMissingWalls ()
2513 {
2514   TopTools_IndexedDataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
2515   TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
2516   Standard_Real OffsetVal = Abs(myOffset);
2517
2518   FillContours(myShape, myAnalyse, Contours, MapEF);
2519
2520   for (Standard_Integer ic = 1; ic <= Contours.Extent(); ic++)
2521   {
2522     TopoDS_Vertex StartVertex = TopoDS::Vertex(Contours.FindKey(ic));
2523     TopoDS_Edge StartEdge;
2524     const TopTools_ListOfShape& aContour = Contours(ic);
2525     TopTools_ListIteratorOfListOfShape itl(aContour);
2526     Standard_Boolean FirstStep = Standard_True;
2527     TopoDS_Edge PrevEdge;
2528     TopoDS_Vertex PrevVertex = StartVertex;
2529     Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
2530     for (; itl.More(); itl.Next())
2531     {
2532       TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2533       TopoDS_Face aFaceOfEdge = TopoDS::Face(MapEF(anEdge));
2534
2535       // Check for offset existence.
2536       if (!myInitOffsetEdge.HasImage(anEdge))
2537         continue;
2538
2539       // Check for existence of two different vertices.
2540       TopTools_ListOfShape LOE, LOE2;
2541       myInitOffsetEdge.LastImage( anEdge, LOE );
2542       myImageOffset.LastImage( LOE.Last(), LOE2 );
2543       TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
2544       TopoDS_Vertex V1, V2, V3, V4;
2545       TopExp::Vertices(OE,     V4, V3);
2546       TopExp::Vertices(anEdge, V1, V2);
2547       Standard_Real aF, aL;
2548       const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
2549       if (!aC.IsNull() &&
2550          (!aC->IsClosed() && !aC->IsPeriodic()))
2551       {
2552         gp_Pnt aPntF = BRep_Tool::Pnt(V1);
2553         gp_Pnt aPntL = BRep_Tool::Pnt(V2);
2554         Standard_Real aDistE = aPntF.SquareDistance(aPntL);
2555         if ( aDistE < Precision::SquareConfusion())
2556         {
2557           // Bad case: non closed, but vertexes mapped to same 3d point.
2558           continue;
2559         }
2560
2561         Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
2562         if (aDistE < anEdgeTol)
2563         {
2564           // Potential problems not detected via checkshape.
2565           gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
2566           gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
2567           if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
2568           {
2569             // To avoid computation of complex analytical continuation of Sin / ArcSin.
2570             Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
2571             Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
2572             Standard_Real aCurrentAngle =  gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
2573             if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
2574                 Abs (aCurrentAngle) > aMaxAngle)
2575             {
2576               // anEdge not collinear to offset edge.
2577               isBuildFromScratch = Standard_True;
2578               myIsPerformSewing = Standard_True;
2579               continue;
2580             }
2581           }
2582         }
2583       }
2584
2585       Standard_Boolean ToReverse = Standard_False;
2586       if (!V1.IsSame(PrevVertex))
2587       {
2588         TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
2589         aVtx = V3; V3 = V4; V4 = aVtx;
2590         ToReverse = Standard_True;
2591       }
2592
2593       OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
2594       TopoDS_Edge E3, E4;
2595       Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
2596       if (FirstStep || isBuildFromScratch)
2597       {
2598         E4 = BRepLib_MakeEdge( V1, V4 );
2599         if (FirstStep)
2600           StartEdge = E4;
2601       }
2602       else
2603         E4 = PrevEdge;
2604       if (V2.IsSame(StartVertex) && !ArcOnV2)
2605         E3 = StartEdge;
2606       else
2607         E3 = BRepLib_MakeEdge( V2, V3 );
2608       E4.Reverse();
2609
2610       if (isBuildFromScratch)
2611       {
2612         E3.Reverse();
2613         E4.Reverse();
2614       }
2615
2616       TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
2617       const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
2618       Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
2619       Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
2620       BRep_Builder BB;
2621       TopoDS_Wire theWire;
2622       BB.MakeWire(theWire);
2623       if (ToReverse)
2624       {
2625         BB.Add(theWire, anEdge.Reversed());
2626         BB.Add(theWire, E3.Reversed());
2627         BB.Add(theWire, OE.Reversed());
2628         BB.Add(theWire, E4.Reversed());
2629       }
2630       else
2631       {
2632         BB.Add(theWire, anEdge);
2633         BB.Add(theWire, E3);
2634         BB.Add(theWire, OE);
2635         BB.Add(theWire, E4);
2636       }
2637
2638       BRepLib::BuildCurves3d( theWire, myTol );
2639       theWire.Closed(Standard_True);
2640       TopoDS_Face NewFace;
2641       Handle(Geom_Surface) theSurf;
2642       BRepAdaptor_Curve BAcurve(anEdge);
2643       BRepAdaptor_Curve BAcurveOE(OE);
2644       Standard_Real fpar = BAcurve.FirstParameter();
2645       Standard_Real lpar = BAcurve.LastParameter();
2646       gp_Pnt PonE  = BAcurve.Value(fpar);
2647       gp_Pnt PonOE = BAcurveOE.Value(fpar);
2648       gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
2649       Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
2650       Standard_Boolean IsPlanar = Standard_False;
2651       if (BAcurve.GetType() == GeomAbs_Circle &&
2652         BAcurveOE.GetType() == GeomAbs_Circle)
2653       {
2654         gp_Circ aCirc = BAcurve.Circle();
2655         gp_Circ aCircOE = BAcurveOE.Circle();
2656         gp_Lin anAxisLine(aCirc.Axis());
2657         gp_Dir CircAxisDir = aCirc.Axis().Direction();
2658         if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
2659           anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
2660         { //cylinder, plane or cone
2661           if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
2662             theSurf = GC_MakeCylindricalSurface(aCirc).Value();
2663           else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
2664             IsPlanar = Standard_True;
2665             //
2666             gp_Pnt PonEL = BAcurve.Value(lpar);
2667             if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
2668               Standard_Boolean bIsHole;
2669               TopoDS_Edge aE1, aE2;
2670               TopoDS_Wire aW1, aW2;
2671               Handle(Geom_Plane) aPL;
2672               IntTools_FClass2d aClsf;
2673               //
2674               if (aCirc.Radius()>aCircOE.Radius()) {
2675                 aE1 = anEdge;
2676                 aE2 = OE;
2677               } else {
2678                 aE1 = OE;
2679                 aE2 = anEdge;
2680               }
2681               //
2682               BB.MakeWire(aW1);
2683               BB.Add(aW1, aE1);
2684               BB.MakeWire(aW2);
2685               BB.Add(aW2, aE2);
2686               //
2687               aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
2688               for (Standard_Integer i = 0; i < 2; ++i) {
2689                 TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
2690                 TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
2691                 //
2692                 TopoDS_Face aFace;
2693                 BB.MakeFace(aFace, aPL, Precision::Confusion());
2694                 BB.Add (aFace, aW);
2695                 aClsf.Init(aFace, Precision::Confusion());
2696                 bIsHole=aClsf.IsHole();
2697                 if ((bIsHole && !i) || (!bIsHole && i)) {
2698                   aW.Nullify();
2699                   BB.MakeWire(aW);
2700                   BB.Add(aW, aE.Reversed());
2701                 }
2702               }
2703               //
2704               BB.MakeFace(NewFace, aPL, Precision::Confusion());
2705               BB.Add(NewFace, aW1);
2706               BB.Add(NewFace, aW2);
2707             }
2708           }
2709           else //case of cone
2710           {
2711             gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
2712               aCirc.Radius(), aCircOE.Radius());
2713             gp_Ax3 theAx3(aCirc.Position());
2714             if (CircAxisDir * theCone.Axis().Direction() < 0.)
2715             {
2716               theAx3.ZReverse();
2717               CircAxisDir.Reverse();
2718             }
2719             theCone.SetPosition(theAx3);
2720             theSurf = new Geom_ConicalSurface(theCone);
2721           }
2722           if (!IsPlanar) {
2723             TopLoc_Location Loc;
2724             EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
2725             BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2726             Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
2727             OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
2728             BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2729             aLine2d  = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
2730             aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
2731             if (E3.IsSame(E4))
2732             {
2733               if (Coeff > 0.)
2734                 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2735               else
2736               {
2737                 BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
2738                 theWire.Nullify();
2739                 BB.MakeWire(theWire);
2740                 BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
2741                 BB.Add(theWire, E4);
2742                 BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
2743                 BB.Add(theWire, E3);
2744                 theWire.Closed(Standard_True);
2745               }
2746             }
2747             else
2748             {
2749               BB.SameParameter(E3, Standard_False);
2750               BB.SameRange(E3, Standard_False);
2751               BB.SameParameter(E4, Standard_False);
2752               BB.SameRange(E4, Standard_False);
2753               BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2754               BB.Range(E3, theSurf, Loc, 0., OffsetVal);
2755               BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2756               BB.Range(E4, theSurf, Loc, 0., OffsetVal);
2757             }
2758             NewFace = BRepLib_MakeFace(theSurf, theWire);
2759           }
2760         } //cylinder or cone
2761       } //if both edges are arcs of circles
2762       if (NewFace.IsNull())
2763       {
2764         BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
2765         if (MF.Error() == BRepLib_FaceDone)
2766         {
2767           NewFace = MF.Face();
2768           IsPlanar = Standard_True;
2769         }
2770         else //Extrusion (by thrusections)
2771         {
2772           Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
2773           Handle(Geom_TrimmedCurve) TrEdgeCurve =
2774             new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
2775           Standard_Real fparOE, lparOE;
2776           Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
2777           Handle(Geom_TrimmedCurve) TrOffsetCurve =
2778             new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
2779           GeomFill_Generator ThrusecGenerator;
2780           ThrusecGenerator.AddCurve( TrEdgeCurve );
2781           ThrusecGenerator.AddCurve( TrOffsetCurve );
2782           ThrusecGenerator.Perform( Precision::PConfusion() );
2783           theSurf = ThrusecGenerator.Surface();
2784           //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
2785           Standard_Real Uf, Ul, Vf, Vl;
2786           theSurf->Bounds(Uf, Ul, Vf, Vl);
2787           TopLoc_Location Loc;
2788           EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
2789           BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2790           OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
2791           BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2792           Standard_Real UonV1 = (ToReverse)? Ul : Uf;
2793           Standard_Real UonV2 = (ToReverse)? Uf : Ul;
2794           aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
2795           aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
2796           if (E3.IsSame(E4))
2797           {
2798             BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2799             Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
2800             BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
2801             BB.Range(E3, Vf, Vl);
2802           }
2803           else
2804           {
2805             BB.SameParameter(E3, Standard_False);
2806             BB.SameRange(E3, Standard_False);
2807             BB.SameParameter(E4, Standard_False);
2808             BB.SameRange(E4, Standard_False);
2809             BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
2810             BB.Range(E3, theSurf, Loc, Vf, Vl);
2811             BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2812             BB.Range(E4, theSurf, Loc, Vf, Vl);
2813             Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
2814             BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
2815             BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
2816             Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
2817             BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
2818             BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
2819           }
2820           NewFace = BRepLib_MakeFace(theSurf, theWire);
2821         }
2822       }
2823       if (!IsPlanar)
2824       {
2825         Standard_Real fparOE = BAcurveOE.FirstParameter();
2826         Standard_Real lparOE = BAcurveOE.LastParameter();
2827         TopLoc_Location Loc;
2828         if (Abs(fpar - fparOE) > Precision::Confusion())
2829         {
2830           const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
2831           gp_Pnt2d fp2d   = EdgeLine2d->Value(fpar);
2832           gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
2833           aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
2834           Handle(Geom_Curve) aCurve;
2835           Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
2836           Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
2837           GeomAdaptor_Surface GAsurf( theSurf );
2838           Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2839           Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2840           Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2841           Standard_Real max_deviation = 0., average_deviation;
2842           GeomLib::BuildCurve3d(Precision::Confusion(),
2843             ConS, FirstPar, LastPar,
2844             aCurve, max_deviation, average_deviation);
2845           BB.UpdateEdge( anE4, aCurve, max_deviation );
2846           BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
2847           BB.Range( anE4, FirstPar, LastPar );
2848         }
2849         if (Abs(lpar - lparOE) > Precision::Confusion())
2850         {
2851           const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
2852           gp_Pnt2d lp2d   = EdgeLine2d->Value(lpar);
2853           gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
2854           aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
2855           Handle(Geom_Curve) aCurve;
2856           Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
2857           Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
2858           GeomAdaptor_Surface GAsurf( theSurf );
2859           Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
2860           Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2861           Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2862           Standard_Real max_deviation = 0., average_deviation;
2863           GeomLib::BuildCurve3d(Precision::Confusion(),
2864             ConS, FirstPar, LastPar,
2865             aCurve, max_deviation, average_deviation);
2866           BB.UpdateEdge( anE3, aCurve, max_deviation );
2867           BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
2868           BB.Range( anE3, FirstPar, LastPar );
2869         }
2870       }
2871       BRepLib::SameParameter(NewFace);
2872       BRepTools::Update(NewFace);
2873       //Check orientation
2874       TopAbs_Orientation anOr = OrientationOfEdgeInFace(anEdge, aFaceOfEdge);
2875       TopAbs_Orientation OrInNewFace = OrientationOfEdgeInFace(anEdge, NewFace);
2876       if (OrInNewFace != TopAbs::Reverse(anOr))
2877         NewFace.Reverse();
2878       ///////////////////
2879       myWalls.Append(NewFace);
2880       if (ArcOnV2)
2881       {
2882         TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
2883         TopoDS_Vertex arcV1, arcV2;
2884         TopExp::Vertices(anArc, arcV1, arcV2);
2885         Standard_Boolean ArcReverse = Standard_False;
2886         if (!arcV1.IsSame(V3))
2887         {
2888           TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
2889           ArcReverse = Standard_True;
2890         }
2891         TopoDS_Edge EA1, EA2;
2892         //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
2893         EA1 = E3;
2894         EA1.Reverse();
2895         if (ToReverse)
2896           EA1.Reverse();
2897         //////////////////////////////////////////////////////
2898         if (V2.IsSame(StartVertex))
2899           EA2 = StartEdge;
2900         else
2901           EA2 = BRepLib_MakeEdge( V2, arcV2 );
2902         anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
2903         if (EA1.Orientation() == TopAbs_REVERSED)
2904           anArc.Reverse();
2905         EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
2906         TopoDS_Wire arcWire;
2907         BB.MakeWire(arcWire);
2908         BB.Add(arcWire, EA1);
2909         BB.Add(arcWire, anArc);
2910         BB.Add(arcWire, EA2);
2911         BRepLib::BuildCurves3d( arcWire, myTol );
2912         arcWire.Closed(Standard_True);
2913         TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
2914         BRepTools::Update(arcFace);
2915         myWalls.Append(arcFace);
2916         TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
2917         const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
2918         PrevEdge = CEA2;
2919         PrevVertex = V2;
2920       }
2921       else
2922       {
2923         if (isBuildFromScratch)
2924         {
2925           PrevEdge = TopoDS::Edge(E4);
2926           PrevVertex = V1;
2927           isBuildFromScratch = Standard_False;
2928         }
2929         else
2930         {
2931           PrevEdge = E3;
2932           PrevVertex = V2;
2933         }
2934       }
2935       FirstStep = Standard_False;
2936     }
2937   }
2938 }
2939
2940 //=======================================================================
2941 //function : MakeShells
2942 //purpose  : 
2943 //=======================================================================
2944
2945 void BRepOffset_MakeOffset::MakeShells ()
2946 {
2947 #ifdef OCCT_DEBUG
2948   if (ChronBuild) {  
2949     std::cout << " RECONSTRUCTION OF SHELLS:" << std::endl;
2950     Clock.Reset();
2951     Clock.Start();
2952   }
2953 #endif
2954   //
2955   // Prepare list of splits of the offset faces to make the shells
2956   TopTools_ListOfShape aLSF;
2957   const TopTools_ListOfShape& R = myImageOffset.Roots();
2958   TopTools_ListIteratorOfListOfShape it(R);
2959   //
2960   for (; it.More(); it.Next()) {
2961     TopoDS_Shape aF = it.Value();
2962     if (myThickening) //offsetted faces must change their orientations
2963       aF.Reverse();
2964     //
2965     TopTools_ListOfShape Image;
2966     myImageOffset.LastImage(aF,Image);
2967     TopTools_ListIteratorOfListOfShape it2(Image);
2968     for (; it2.More(); it2.Next()) {
2969       const TopoDS_Shape& aFIm = it2.Value();
2970       aLSF.Append(aFIm);
2971     }
2972   }
2973   //
2974   if (myThickening) {
2975     TopExp_Explorer Explo(myShape, TopAbs_FACE);
2976     for (; Explo.More(); Explo.Next()) {
2977       const TopoDS_Shape& aF = Explo.Current();
2978       aLSF.Append(aF);
2979     }
2980     //
2981     it.Initialize(myWalls);
2982     for (; it.More(); it.Next()) {
2983       const TopoDS_Shape& aF = it.Value();
2984       aLSF.Append(aF);
2985     }
2986   }
2987   //
2988   if (aLSF.IsEmpty()) {
2989     return;
2990   }
2991   //
2992   Standard_Boolean bDone = Standard_False;
2993   if ((myJoin == GeomAbs_Intersection) && myInter &&
2994       !myThickening && myFaces.IsEmpty() &&
2995       IsSolid(myShape) && myIsPlanar) {
2996     //
2997     TopoDS_Shape aShells;
2998     bDone = BuildShellsCompleteInter(aLSF, myImageOffset, aShells);
2999     if (bDone) {
3000       myOffsetShape = aShells;
3001     }
3002   }
3003   //
3004   if (!bDone) {
3005     BRepTools_Quilt Glue;
3006     TopTools_ListIteratorOfListOfShape aItLS(aLSF);
3007     for (; aItLS.More(); aItLS.Next()) {
3008       Glue.Add(aItLS.Value());
3009     }
3010     myOffsetShape = Glue.Shells();
3011   }
3012   //
3013   //Set correct value for closed flag
3014   TopExp_Explorer Explo(myOffsetShape, TopAbs_SHELL);
3015   for(; Explo.More(); Explo.Next())
3016   {
3017     TopoDS_Shape aS = Explo.Current(); 
3018     if(!aS.Closed())
3019     {
3020       if(BRep_Tool::IsClosed(aS))
3021       {
3022         aS.Closed(Standard_True);
3023       }
3024     }
3025   }
3026 }
3027
3028 //=======================================================================
3029 //function : MakeSolid
3030 //purpose  : 
3031 //=======================================================================
3032
3033 void BRepOffset_MakeOffset::MakeSolid ()
3034 {
3035  if (myOffsetShape.IsNull()) return;
3036
3037 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
3038 //  Supporting history.
3039   UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
3040   UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
3041 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
3042   TopExp_Explorer             exp;
3043   BRep_Builder                B;
3044   Standard_Integer            NbShell = 0;
3045   TopoDS_Compound             NC;
3046   TopoDS_Shape                S1;
3047   B.MakeCompound (NC);
3048
3049   TopoDS_Solid Sol;
3050   B.MakeSolid(Sol);
3051   Sol.Closed(Standard_True);
3052   Standard_Boolean aMakeSolid = (myShape.ShapeType() == TopAbs_SOLID) || myThickening;
3053   for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
3054     TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
3055     if (myThickening && myOffset > 0.)
3056       Sh.Reverse();
3057     NbShell++;
3058     if (Sh.Closed() && aMakeSolid) {
3059       B.Add(Sol,Sh);
3060     }
3061     else {
3062       B.Add (NC,Sh);
3063       if(NbShell == 1)
3064       {
3065         S1 = Sh;
3066       }
3067     }
3068   }
3069   Standard_Integer nbs = Sol.NbChildren();
3070   Standard_Boolean SolIsNull = (nbs == 0);
3071   //Checking solid
3072   if (nbs > 1)
3073   {
3074     BRepCheck_Analyzer aCheck (Sol, Standard_False);
3075     if (!aCheck.IsValid ())
3076     {
3077       TopTools_ListOfShape aSolList;
3078       CorrectSolid (Sol, aSolList);
3079       if (!aSolList.IsEmpty ())
3080       {
3081         B.Add (NC, Sol);
3082         TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
3083         for (; aSLIt.More (); aSLIt.Next ())
3084         {
3085           B.Add (NC, aSLIt.Value ());
3086         }
3087         SolIsNull = Standard_True;
3088       }
3089     }
3090   }
3091   Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
3092   if((!SolIsNull) && (!NCIsNull))
3093   {
3094     B.Add(NC, Sol);
3095     myOffsetShape = NC;
3096   }
3097   else if(SolIsNull && (!NCIsNull))
3098   {
3099     if (NbShell == 1) 
3100     {
3101       myOffsetShape = S1;
3102     }
3103     else
3104     {
3105       myOffsetShape = NC;
3106     }
3107   }
3108   else if((!SolIsNull) && NCIsNull)
3109   {
3110     myOffsetShape = Sol;
3111   }
3112   else
3113   {
3114     myOffsetShape = NC;
3115   }
3116 }
3117
3118 //=======================================================================
3119 //function : SelectShells
3120 //purpose  : 
3121 //=======================================================================
3122
3123 void BRepOffset_MakeOffset::SelectShells ()
3124 {
3125   TopTools_MapOfShape FreeEdges;
3126   TopExp_Explorer exp(myShape,TopAbs_EDGE);
3127   //-------------------------------------------------------------
3128   // FreeEdges all edges that can have free border in the  
3129   // parallel shell
3130   // 1 - free borders of myShape .
3131   //-------------------------------------------------------------
3132   for ( ; exp.More(); exp.Next()) {
3133     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3134     const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
3135     if (LA.Extent() < 2) {
3136       if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
3137               FreeEdges.Add(E);                       
3138       }
3139     }  
3140   }
3141   // myShape has free borders and there are no caps
3142   // no unwinding 3d.
3143   if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
3144
3145   myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
3146 }
3147
3148 //=======================================================================
3149 //function : OffsetFacesFromShapes
3150 //purpose  : 
3151 //=======================================================================
3152
3153 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
3154 {
3155   return myInitOffsetFace;
3156 }
3157
3158 //  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
3159
3160 //=======================================================================
3161 //function : GetJoinType
3162 //purpose  : Query offset join type.
3163 //=======================================================================
3164
3165 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
3166 {
3167   return myJoin;
3168 }
3169
3170 //=======================================================================
3171 //function : OffsetEdgesFromShapes
3172 //purpose  : 
3173 //=======================================================================
3174
3175 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
3176 {
3177   return myInitOffsetEdge;
3178 }
3179
3180 //  Modified by skv - Tue Mar 15 16:20:43 2005 End
3181
3182 //=======================================================================
3183 //function : ClosingFaces
3184 //purpose  : 
3185 //=======================================================================
3186
3187 const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
3188 {
3189   return myFaces;
3190 }
3191
3192
3193
3194 //=======================================================================
3195 //function : EncodeRegularity
3196 //purpose  : 
3197 //=======================================================================
3198
3199 void BRepOffset_MakeOffset::EncodeRegularity ()
3200 {
3201 #ifdef OCCT_DEBUG
3202   if (ChronBuild) {  
3203     std::cout << " CODING OF REGULARITIES:" << std::endl;
3204     Clock.Reset();
3205     Clock.Start();
3206   }
3207 #endif
3208
3209   if (myOffsetShape.IsNull()) return;
3210   // find edges G1 in the result
3211   TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
3212
3213   BRep_Builder B;
3214   TopTools_MapOfShape MS;
3215
3216   for ( ; exp.More(); exp.Next()) {
3217     TopoDS_Edge OE  = TopoDS::Edge(exp.Current());
3218     BRepLib::BuildCurve3d(OE,myTol);
3219     TopoDS_Edge ROE = OE;
3220     
3221     if ( !MS.Add(OE)) continue;
3222       
3223     if ( myImageOffset.IsImage(OE)) 
3224       ROE = TopoDS::Edge(myImageOffset.Root(OE));
3225
3226     const TopTools_ListOfShape& LofOF    = myAsDes->Ascendant(ROE);
3227     
3228     if (LofOF.Extent() != 2) {
3229 #ifdef OCCT_DEBUG_VERB
3230     std::cout << " Edge shared by " << LofOF.Extent() << " Faces" << std::endl;
3231 #endif
3232       continue;
3233     }
3234
3235     const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
3236     const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
3237     
3238     if ( F1.IsNull() || F2.IsNull()) 
3239       continue;
3240    
3241     const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
3242     const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
3243
3244     TopAbs_ShapeEnum Type1 = Root1.ShapeType();
3245     TopAbs_ShapeEnum Type2 = Root2.ShapeType();
3246  
3247     if (F1.IsSame(F2)) {      
3248       if (BRep_Tool::IsClosed(OE,F1)) {
3249         // Temporary Debug for the Bench.
3250         // Check with YFR.
3251         // In mode intersection, the edges are not coded in myInitOffsetEdge
3252         // so, manage case by case
3253         // Note DUB; for Hidden parts, it is NECESSARY to code CN 
3254         // Analytic Surfaces.
3255         if (myJoin == GeomAbs_Intersection) {
3256           BRepAdaptor_Surface BS(F1,Standard_False);
3257           GeomAbs_SurfaceType SType = BS.GetType();
3258           if (SType == GeomAbs_Cylinder ||
3259               SType == GeomAbs_Cone     ||
3260               SType == GeomAbs_Sphere   ||
3261               SType == GeomAbs_Torus      ) {
3262             B.Continuity(OE,F1,F1,GeomAbs_CN);
3263           }
3264           else {
3265             // See YFR : MaJ of myInitOffsetFace
3266           }
3267         }
3268         else if (myInitOffsetEdge.IsImage(ROE)) {
3269           if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3270             const TopoDS_Face& FRoot = TopoDS::Face(Root1);
3271             const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
3272             GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
3273             if (Conti == GeomAbs_CN) {
3274               B.Continuity(OE,F1,F1,GeomAbs_CN);
3275             }
3276             else if ( Conti > GeomAbs_C0) {
3277               B.Continuity(OE,F1,F1,GeomAbs_G1);
3278             }
3279           }
3280         }
3281       }
3282       continue;
3283     }
3284
3285
3286     //  code regularities G1 between :
3287     //    - sphere and tube : one root is a vertex, the other is an edge 
3288     //                        and the vertex is included in the edge
3289     //    - face and tube   : one root is a face, the other an edge 
3290     //                        and the edge is included in the face
3291     //    - face and face    : if two root faces are tangent in 
3292     //                        the initial shape, they will be tangent in the offset shape
3293     //    - tube and tube  : if 2 edges generating tubes are
3294     //                        tangents, the 2 will be tangent either.
3295     if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3296       TopoDS_Vertex V1,V2;
3297       TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3298       if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3299         B.Continuity(OE,F1,F2,GeomAbs_G1);
3300       }
3301     }
3302     else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3303       TopoDS_Vertex V1,V2;
3304       TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3305       if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3306         B.Continuity(OE,F1,F2,GeomAbs_G1);
3307       }
3308     }
3309     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3310       TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3311       for ( ; exp2.More(); exp2.Next()) {
3312         if ( exp2.Current().IsSame(Root2)) {
3313           B.Continuity(OE,F1,F2,GeomAbs_G1);
3314           break;
3315         }
3316       }
3317     }
3318     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
3319       TopExp_Explorer exp2(Root2,TopAbs_EDGE);
3320       for ( ; exp2.More(); exp2.Next()) {
3321         if ( exp2.Current().IsSame(Root1)) {
3322           B.Continuity(OE,F1,F2,GeomAbs_G1);
3323           break;
3324         }
3325       }
3326     }
3327     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3328     //  if two root faces are tangent in 
3329     //  the initial shape, they will be tangent in the offset shape
3330       TopTools_ListOfShape LE;
3331       BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_EDGE, LE);
3332       if ( LE.Extent() == 1) {
3333         const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
3334         if ( myAnalyse.HasAncestor(Ed)) {
3335           const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
3336           if (LI.Extent()       == 1   && 
3337               LI.First().Type() == BRepOffset_Tangent) {
3338             B.Continuity(OE,F1,F2,GeomAbs_G1);
3339           }
3340         }
3341       }
3342     }
3343     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
3344       TopTools_ListOfShape LV;
3345       BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_VERTEX, LV);
3346       if ( LV.Extent() == 1) {
3347         TopTools_ListOfShape LEdTg;
3348         myAnalyse.TangentEdges(TopoDS::Edge(Root1),
3349                                TopoDS::Vertex(LV.First()),
3350                                LEdTg);
3351         TopTools_ListIteratorOfListOfShape it(LEdTg);
3352         for (; it.More(); it.Next()) {
3353           if ( it.Value().IsSame(Root2)) {
3354             B.Continuity(OE,F1,F2,GeomAbs_G1);
3355             break;
3356           }
3357         }
3358       }
3359     }
3360   }
3361
3362 #ifdef OCCT_DEBUG
3363   if ( ChronBuild) Clock.Show();
3364 #endif
3365 }
3366
3367 //=======================================================================
3368 //function : ComputeMaxDist
3369 //purpose  : 
3370 //=======================================================================
3371 Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
3372                              const Handle(Geom_Curve)& theCrv,
3373                              const Standard_Real theFirst,
3374                              const Standard_Real theLast)
3375 {
3376   Standard_Real aMaxDist = 0.;
3377   Standard_Integer i, NCONTROL = 23;
3378   Standard_Real aPrm, aDist2;
3379   gp_Pnt aP;
3380   for (i = 0; i< NCONTROL; i++) {
3381     aPrm = ((NCONTROL - 1 - i)*theFirst + i*theLast) / (NCONTROL - 1);
3382     aP = theCrv->Value(aPrm);
3383     if (Precision::IsInfinite(aP.X()) || Precision::IsInfinite(aP.Y())
3384       || Precision::IsInfinite(aP.Z()))
3385     {
3386       return Precision::Infinite();
3387     }
3388     aDist2 = thePlane.SquareDistance(aP);
3389     if (aDist2 > aMaxDist) aMaxDist = aDist2;  
3390   }
3391   return sqrt(aMaxDist)*1.05;
3392 }
3393 //=======================================================================
3394 //function : UpDateTolerance
3395 //purpose  : 
3396 //=======================================================================
3397
3398 void UpdateTolerance (TopoDS_Shape& S,
3399                       const TopTools_IndexedMapOfShape& Faces)
3400 {
3401   BRep_Builder B;
3402   TopTools_MapOfShape View;
3403   TopoDS_Vertex V[2];
3404
3405   // The edges of caps are not modified.
3406   Standard_Integer j;
3407   for (j = 1; j <= Faces.Extent(); j++) {
3408     const TopoDS_Shape& F = Faces(j);
3409     TopExp_Explorer Exp;
3410     for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3411       View.Add(Exp.Current());
3412     }
3413   }
3414   
3415   Standard_Real Tol;
3416   TopExp_Explorer ExpF;
3417   for (ExpF.Init(S, TopAbs_FACE); ExpF.More(); ExpF.Next())
3418   {
3419     const TopoDS_Shape& F = ExpF.Current();
3420     if (Faces.Contains(F))
3421     {
3422       continue;
3423     }
3424     BRepAdaptor_Surface aBAS(TopoDS::Face(F), Standard_False);
3425     TopExp_Explorer Exp;
3426     for (Exp.Init(F, TopAbs_EDGE); Exp.More(); Exp.Next()) {
3427       TopoDS_Edge E = TopoDS::Edge(Exp.Current());
3428       Standard_Boolean isUpdated = Standard_False;
3429       if (aBAS.GetType() == GeomAbs_Plane)
3430       {
3431         //Edge does not seem to have pcurve on plane,
3432         //so EdgeCorrector does not include it in tolerance calculation
3433         Standard_Real aFirst, aLast;
3434         Handle(Geom_Curve) aCrv = BRep_Tool::Curve(E, aFirst, aLast);
3435         Standard_Real aMaxDist = ComputeMaxDist(aBAS.Plane(), aCrv, aFirst, aLast);
3436         B.UpdateEdge(E, aMaxDist);
3437         isUpdated = Standard_True;
3438       }
3439       if (View.Add(E))
3440       {
3441
3442         BRepCheck_Edge EdgeCorrector(E);
3443         Tol = EdgeCorrector.Tolerance();
3444         B.UpdateEdge(E, Tol);
3445         isUpdated = Standard_True;
3446       }
3447       if (isUpdated)
3448       {
3449         Tol = BRep_Tool::Tolerance(E);
3450         // Update the vertices.
3451         TopExp::Vertices(E, V[0], V[1]);
3452
3453         for (Standard_Integer i = 0; i <= 1; i++) {
3454           if (View.Add(V[i])) {
3455             Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
3456             TV->Tolerance(0.);
3457             BRepCheck_Vertex VertexCorrector(V[i]);
3458             B.UpdateVertex(V[i], VertexCorrector.Tolerance());
3459             // use the occasion to clean the vertices.
3460             (TV->ChangePoints()).Clear();
3461           }
3462           B.UpdateVertex(V[i], Tol);
3463         }
3464       }
3465     }
3466   }
3467 }
3468
3469 //=======================================================================
3470 //function : CorrectSolid
3471 //purpose  : 
3472 //=======================================================================
3473 void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
3474 {
3475   BRep_Builder aBB;
3476   TopoDS_Shape anOuterShell;
3477   NCollection_List<Standard_Real> aVols;
3478   Standard_Real aVolMax = 0., anOuterVol = 0.;
3479
3480   TopoDS_Iterator anIt(theSol);
3481   for(; anIt.More(); anIt.Next())
3482   {
3483     const TopoDS_Shape& aSh = anIt.Value();
3484     GProp_GProps aVProps;
3485     BRepGProp::VolumeProperties(aSh, aVProps, Standard_True);
3486     if(Abs(aVProps.Mass()) > aVolMax)
3487     {
3488       anOuterVol = aVProps.Mass();
3489       aVolMax = Abs(anOuterVol);
3490       anOuterShell = aSh; 
3491     }
3492     aVols.Append(aVProps.Mass());
3493   }
3494   //
3495   if (Abs(anOuterVol) < Precision::Confusion()) {
3496     return;
3497   }
3498   if(anOuterVol < 0.)
3499   {
3500     anOuterShell.Reverse();
3501   }
3502   TopoDS_Solid aNewSol;
3503   aBB.MakeSolid(aNewSol);
3504   aNewSol.Closed(Standard_True);
3505   aBB.Add(aNewSol, anOuterShell);
3506   BRepClass3d_SolidClassifier aSolClass(aNewSol);
3507   //
3508   anIt.Initialize(theSol);
3509   NCollection_List<Standard_Real>::Iterator aVIt(aVols);
3510   for(; anIt.More(); anIt.Next(), aVIt.Next())
3511   {
3512     TopoDS_Shell aSh = TopoDS::Shell(anIt.Value());
3513     if(aSh.IsSame(anOuterShell))
3514     {
3515       continue;
3516     }
3517     else
3518     {
3519       TopExp_Explorer aVExp(aSh, TopAbs_VERTEX);
3520       const TopoDS_Vertex& aV = TopoDS::Vertex(aVExp.Current());
3521       gp_Pnt aP = BRep_Tool::Pnt(aV);
3522       aSolClass.Perform(aP, BRep_Tool::Tolerance(aV));
3523       if(aSolClass.State() == TopAbs_IN)
3524       {
3525         if(aVIt.Value() > 0.)
3526         {
3527           aSh.Reverse();
3528         }
3529         aBB.Add(aNewSol, aSh);
3530       }
3531       else
3532       {
3533         if(aVIt.Value() < 0.)
3534         {
3535           aSh.Reverse();
3536         }
3537         TopoDS_Solid aSol;
3538         aBB.MakeSolid(aSol);
3539         aSol.Closed(Standard_True);
3540         aBB.Add(aSol, aSh);
3541         theSolList.Append(aSol);
3542       }
3543     }
3544   }
3545   theSol = aNewSol;
3546 }
3547
3548 //=======================================================================
3549 //function : CheckInputData
3550 //purpose  : Check input data for possiblity of offset perform.
3551 //=======================================================================
3552 Standard_Boolean BRepOffset_MakeOffset::CheckInputData()
3553 {
3554   // Set initial error state.
3555   myError = BRepOffset_NoError;
3556   TopoDS_Shape aTmpShape;
3557   myBadShape = aTmpShape;
3558
3559   // Non-null offset.
3560   if (Abs(myOffset) <= myTol)
3561   {
3562     Standard_Boolean isFound = Standard_False;
3563     TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset);
3564     for( ; anIter.More(); anIter.Next())
3565     {
3566       if (Abs(anIter.Value()) > myTol)
3567       {
3568         isFound = Standard_True;
3569         break;
3570       }
3571     }
3572
3573     if (!isFound)
3574     {
3575       // No face with non-null offset found.
3576       myError = BRepOffset_NullOffset;
3577       return Standard_False;
3578     }
3579   }
3580
3581   // Connectivity of input shape.
3582   if (!IsConnectedShell(myShape))
3583   {
3584     myError = BRepOffset_NotConnectedShell;
3585     return Standard_False;
3586   }
3587
3588   // Normals check and continuity check.
3589   const Standard_Integer aPntPerDim = 20; // 21 points on each dimension.
3590   Standard_Real aUmin, aUmax, aVmin, aVmax;
3591   TopExp_Explorer anExpSF(myShape, TopAbs_FACE);
3592   NCollection_Map<Handle(TopoDS_TShape)> aPresenceMap;
3593   TopLoc_Location L;
3594   gp_Pnt2d aPnt2d;
3595   for( ; anExpSF.More(); anExpSF.Next())
3596   {
3597     const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current());
3598
3599     if (aPresenceMap.Contains(aF.TShape()))
3600     {
3601       // Not perform computations with partner shapes,
3602       // since they are contain same geometry.
3603       continue;
3604     }
3605     aPresenceMap.Add(aF.TShape());
3606
3607     const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L);
3608     BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax);
3609
3610     // Continuity check.
3611     if (aSurf->Continuity() == GeomAbs_C0)
3612     {
3613       myError = BRepOffset_C0Geometry;
3614       return Standard_False;
3615     }
3616
3617     // Get degenerated points, to avoid check them.
3618     NCollection_Vector<gp_Pnt> aBad3dPnts;
3619     TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
3620     for( ; anExpFE.More(); anExpFE.Next())
3621     {
3622       const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current());
3623       if (BRep_Tool::Degenerated(aE))
3624       {
3625         aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE))));
3626       }
3627     }
3628
3629     // Geometry grid check.
3630     for(Standard_Integer i = 0; i <= aPntPerDim; i++)
3631     {
3632       Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim;
3633       for(Standard_Integer j = 0; j <= aPntPerDim; j++)
3634       {
3635         Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim;
3636
3637         myError = checkSinglePoint(aUParam, aVParam, aSurf, aBad3dPnts);
3638         if (myError != BRepOffset_NoError)
3639           return Standard_False;
3640       }
3641     }
3642
3643     // Vertex list check.
3644     TopExp_Explorer anExpFV(aF, TopAbs_VERTEX);
3645     for( ; anExpFV.More(); anExpFV.Next())
3646     {
3647       const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current());
3648       aPnt2d = BRep_Tool::Parameters(aV, aF);
3649
3650       myError = checkSinglePoint(aPnt2d.X(), aPnt2d.Y(), aSurf, aBad3dPnts);
3651       if (myError != BRepOffset_NoError)
3652         return Standard_False;
3653     }
3654   }
3655
3656   return Standard_True;
3657 }
3658
3659
3660 //=======================================================================
3661 //function : GetBadShape
3662 //purpose  : Get shape where problems detected.
3663 //=======================================================================
3664 const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const
3665 {
3666   return myBadShape;
3667 }
3668
3669 //=======================================================================
3670 //function : RemoveInternalEdges
3671 //purpose  : 
3672 //=======================================================================
3673 void BRepOffset_MakeOffset::RemoveInternalEdges()
3674 {
3675   Standard_Boolean bRemoveWire, bRemoveEdge;
3676   TopExp_Explorer aExpF, aExpW, aExpE;
3677   TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
3678   //
3679   TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF);
3680   //
3681   aExpF.Init(myOffsetShape, TopAbs_FACE);
3682   for (; aExpF.More(); aExpF.Next()) {
3683     TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
3684     //
3685     TopTools_ListOfShape aLIW;
3686     //
3687     aExpW.Init(aF, TopAbs_WIRE);
3688     for (; aExpW.More(); aExpW.Next()) {
3689       TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current();
3690       //
3691       bRemoveWire = Standard_True;
3692       TopTools_ListOfShape aLIE;
3693       //
3694       aExpE.Init(aW, TopAbs_EDGE);
3695       for (; aExpE.More(); aExpE.Next()) {
3696         const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
3697         if (aE.Orientation() != TopAbs_INTERNAL) {
3698           bRemoveWire = Standard_False;
3699           continue;
3700         }
3701         //
3702         const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE);
3703         bRemoveEdge = (aLF.Extent() == 1);
3704         if (bRemoveEdge) {
3705           aLIE.Append(aE);
3706         }
3707         else {
3708           bRemoveWire = Standard_False;
3709         }
3710       }
3711       //
3712       if (bRemoveWire) {
3713         aLIW.Append(aW);
3714       }
3715       else if (aLIE.Extent()) {
3716         RemoveShapes(aW, aLIE);
3717       }
3718     }
3719     //
3720     if (aLIW.Extent()) {
3721       RemoveShapes(aF, aLIW);
3722     }
3723   }
3724 }
3725
3726 //=======================================================================
3727 // static methods implementation
3728 //=======================================================================
3729
3730 //=======================================================================
3731 //function : checkSinglePoint
3732 //purpose  : Check single point on surface for bad normals
3733 //=======================================================================
3734 BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
3735                                   const Standard_Real theVParam,
3736                                   const Handle(Geom_Surface)& theSurf,
3737                                   const NCollection_Vector<gp_Pnt>& theBadPoints)
3738 {
3739   gp_Pnt aPnt;
3740   gp_Vec aD1U, aD1V;
3741   theSurf->D1(theUParam, theVParam, aPnt, aD1U, aD1V);
3742
3743   if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
3744       aD1V.SquareMagnitude() < Precision::SquareConfusion() )
3745   {
3746     Standard_Boolean isKnownBadPnt = Standard_False;
3747     for(Standard_Integer anIdx  = theBadPoints.Lower();
3748                          anIdx <= theBadPoints.Upper();
3749                        ++anIdx)
3750     {
3751       if (aPnt.SquareDistance(theBadPoints(anIdx)) < Precision::SquareConfusion())
3752       {
3753         isKnownBadPnt = Standard_True;
3754         break;
3755       }
3756     } // for(Standard_Integer anIdx  = theBadPoints.Lower();
3757
3758     if (!isKnownBadPnt)
3759     {
3760       return BRepOffset_BadNormalsOnGeometry;
3761     }
3762     else
3763     {
3764       return BRepOffset_NoError;
3765     }
3766   } //  if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
3767
3768   if (aD1U.IsParallel(aD1V, Precision::Confusion()))
3769   {
3770     // Isolines are collinear.
3771     return BRepOffset_BadNormalsOnGeometry;
3772   }
3773
3774   return BRepOffset_NoError;
3775 }
3776
3777 //=======================================================================
3778 //function : RemoveShapes
3779 //purpose  : Removes the shapes <theLS> from the shape <theS>
3780 //=======================================================================
3781 void RemoveShapes(TopoDS_Shape& theS,
3782                   const TopTools_ListOfShape& theLS)
3783 {
3784   BRep_Builder aBB;
3785   //
3786   Standard_Boolean bFree = theS.Free();
3787   theS.Free(Standard_True);
3788   //
3789   TopTools_ListIteratorOfListOfShape aIt(theLS);
3790   for (; aIt.More(); aIt.Next()) {
3791     const TopoDS_Shape& aSI = aIt.Value();
3792     aBB.Remove(theS, aSI);
3793   }
3794   //
3795   theS.Free(bFree);
3796 }
3797
3798 //=======================================================================
3799 //function : UpdateHistory
3800 //purpose  : Updates the history information
3801 //=======================================================================
3802 void UpdateHistory(const TopTools_ListOfShape& theLF,
3803                    BOPAlgo_Builder& theGF,
3804                    BRepAlgo_Image& theImage)
3805 {
3806   TopTools_ListIteratorOfListOfShape aIt(theLF);
3807   for (; aIt.More(); aIt.Next()) {
3808     const TopoDS_Shape& aF = aIt.Value();
3809     const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
3810     if (aLFIm.Extent()) {
3811       if (theImage.HasImage(aF)) {
3812         theImage.Add(aF, aLFIm);
3813       }
3814       else {
3815         theImage.Bind(aF, aLFIm);
3816       }
3817     }
3818   }
3819 }
3820
3821 //=======================================================================
3822 //function : IntersectEdges
3823 //purpose  : 
3824 //=======================================================================
3825 void BRepOffset_MakeOffset::IntersectEdges(const TopoDS_Shape& theShape,
3826                                            BRepOffset_DataMapOfShapeOffset& theMapSF,
3827                                            TopTools_DataMapOfShapeShape& theMES,
3828                                            TopTools_DataMapOfShapeShape& theBuild,
3829                                            Handle(BRepAlgo_AsDes)& theAsDes,
3830                                            Handle(BRepAlgo_AsDes)& theAsDes2d)
3831 {
3832   Standard_Real aTolF;
3833   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
3834   TopExp_Explorer aExp(theShape, TopAbs_FACE);
3835   // intersect edges created from edges
3836   TopTools_IndexedMapOfShape aMFV;
3837   for (; aExp.More(); aExp.Next()) {
3838     const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
3839     aTolF = BRep_Tool::Tolerance(aF);
3840     BRepOffset_Inter2d::ConnexIntByInt
3841       (aF, theMapSF(aF), theMES, theBuild, theAsDes2d, myOffset, aTolF, aMFV, aDMVV);
3842   }
3843   // intersect edges created from vertices
3844   Standard_Integer i, aNbF = aMFV.Extent();
3845   for (i = 1; i <= aNbF; ++i) {
3846     const TopoDS_Face& aF = TopoDS::Face(aMFV(i));
3847     aTolF = BRep_Tool::Tolerance(aF);
3848     BRepOffset_Inter2d::ConnexIntByIntInVert
3849       (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, aTolF, aDMVV);
3850   }
3851   //
3852   // fuse vertices on edges
3853   BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d);
3854 }
3855
3856 //=======================================================================
3857 //function : TrimEdges
3858 //purpose  : 
3859 //=======================================================================
3860 void TrimEdges(const TopoDS_Shape& theShape,
3861                const Standard_Real theOffset,
3862                BRepOffset_DataMapOfShapeOffset& theMapSF,
3863                TopTools_DataMapOfShapeShape& theMES,
3864                TopTools_DataMapOfShapeShape& theBuild,
3865                Handle(BRepAlgo_AsDes)& theAsDes,
3866                Handle(BRepAlgo_AsDes)& theAsDes2d,
3867                TopTools_IndexedMapOfShape& theNewEdges,
3868                TopTools_DataMapOfShapeShape& theETrimEInf,
3869                TopTools_DataMapOfShapeListOfShape& theEdgesOrigins)
3870 {
3871   TopExp_Explorer Exp,Exp2,ExpC;
3872   TopoDS_Shape    NE;
3873   TopoDS_Edge     TNE;
3874   TopoDS_Face     NF;
3875   //
3876   for (Exp.Init(theShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
3877     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
3878     NF = theMapSF(FI).Face();
3879     if (theMES.IsBound(NF)) {
3880       NF = TopoDS::Face(theMES(NF));
3881     }
3882     //
3883     TopTools_MapOfShape View;
3884     TopTools_IndexedMapOfShape VEmap;
3885     Standard_Integer i, aNb;
3886     //
3887     TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
3888     TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
3889     //
3890     aNb = VEmap.Extent();
3891     for (i = 1; i <= aNb; ++i) {
3892       const TopoDS_Shape& aS = VEmap(i);
3893       if (!View.Add(aS)) {
3894         continue;
3895       }
3896       //
3897       if (theBuild.IsBound(aS)) {
3898         NE = theBuild(aS);
3899         // keep connection to original edges
3900         ExpC.Init(NE, TopAbs_EDGE);
3901         for (; ExpC.More(); ExpC.Next()) {
3902           const TopoDS_Edge& NEC = TopoDS::Edge(ExpC.Current());
3903           TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NEC);
3904           if (!pLEOr) {
3905             pLEOr = theEdgesOrigins.Bound(NEC, TopTools_ListOfShape());
3906           }
3907           AppendToList(*pLEOr, aS);
3908         }
3909         // trim edges
3910         if (NE.ShapeType() == TopAbs_EDGE) {
3911           if (theNewEdges.Add(NE)) {
3912             TrimEdge (TopoDS::Edge(NE),theAsDes2d,theAsDes, theETrimEInf);
3913           }
3914         }
3915         else {
3916           //------------------------------------------------------------
3917           // The Intersections are on several edges.
3918           // The pieces without intersections with neighbors  
3919           // are removed from AsDes.
3920           //------------------------------------------------------------
3921           for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
3922             TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
3923             if (theNewEdges.Add(NEC)) {
3924               if (!theAsDes2d->Descendant(NEC).IsEmpty()) {
3925                 TrimEdge (NEC,theAsDes2d, theAsDes, theETrimEInf);
3926               }
3927               else {
3928                 if (theAsDes->HasAscendant(NEC)) {
3929                   theAsDes->Remove(NEC);
3930                 }
3931               }
3932             }
3933           }
3934         }
3935       }
3936       else {
3937         if (aS.ShapeType() != TopAbs_EDGE) {
3938           continue;
3939         }
3940         //
3941         NE = theMapSF(FI).Generated(aS);
3942         //// modified by jgv, 19.12.03 for OCC4455 ////
3943         NE.Orientation(aS.Orientation());
3944         //
3945         TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NE);
3946         if (!pLEOr) {
3947           pLEOr = theEdgesOrigins.Bound(NE, TopTools_ListOfShape());
3948         }
3949         AppendToList(*pLEOr, aS);
3950         //
3951         if (theMES.IsBound(NE)) {
3952           NE = theMES(NE);
3953           NE.Orientation(aS.Orientation());
3954           if (theNewEdges.Add(NE)) {
3955             TrimEdge (TopoDS::Edge(NE), theAsDes2d, theAsDes, theETrimEInf);
3956           } 
3957         }
3958         else {
3959           TopoDS_Edge& anEdge = TopoDS::Edge(NE);
3960           BRepAdaptor_Curve aBAC(anEdge);
3961           if (aBAC.GetType() == GeomAbs_Line) {
3962             TopoDS_Edge aNewEdge;
3963             BRepOffset_Inter2d::ExtentEdge(anEdge, aNewEdge, theOffset);
3964             theETrimEInf.Bind(anEdge, aNewEdge);
3965           }
3966         }
3967         theAsDes->Add(NF,NE);
3968       } 
3969     }
3970   }
3971 }
3972
3973 //=======================================================================
3974 //function : TrimEdge
3975 //purpose  : Trim the edge of the largest of descendants in AsDes2d.
3976 //           Order in AsDes two vertices that have trimmed the edge.
3977 //=======================================================================
3978 void TrimEdge(TopoDS_Edge&                  NE,
3979               const Handle(BRepAlgo_AsDes)& AsDes2d,
3980               Handle(BRepAlgo_AsDes)& AsDes,
3981               TopTools_DataMapOfShapeShape& theETrimEInf)
3982 {
3983   TopoDS_Edge aSourceEdge;
3984   TopoDS_Vertex V1,V2;
3985   Standard_Real aT1, aT2;
3986   //
3987   TopExp::Vertices(NE, V1, V2);
3988   BRep_Tool::Range(NE, aT1, aT2);
3989   //
3990   BOPTools_AlgoTools::MakeSplitEdge(NE, V1, aT1, V2, aT2, aSourceEdge);
3991   //
3992   //
3993   Standard_Real aSameParTol = Precision::Confusion();
3994   
3995   Standard_Real U = 0.;
3996   Standard_Real UMin =  Precision::Infinite();
3997   Standard_Real UMax = -UMin;
3998
3999   const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
4000   //
4001   Standard_Boolean bTrim = Standard_False;
4002   //
4003   if (LE.Extent() > 1) {
4004     TopTools_ListIteratorOfListOfShape it (LE);
4005     for (; it.More(); it.Next()) {
4006       TopoDS_Vertex V = TopoDS::Vertex(it.Value());
4007       if (NE.Orientation() == TopAbs_REVERSED)
4008         V.Reverse();
4009       //V.Orientation(TopAbs_INTERNAL);
4010       if (!FindParameter(V, NE, U)) {
4011         Standard_Real f, l;
4012         Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
4013         gp_Pnt thePoint = BRep_Tool::Pnt(V);
4014         GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
4015         if (Projector.NbPoints() == 0)
4016           throw Standard_ConstructionError("BRepOffset_MakeOffset::TrimEdge no projection");
4017         U = Projector.LowerDistanceParameter();
4018       }
4019       if (U < UMin) {
4020         UMin = U; V1   = V;
4021       }
4022       if (U > UMax) {
4023         UMax = U; V2   = V;
4024       }
4025     }
4026     //
4027     if (V1.IsNull() || V2.IsNull()) {
4028       throw Standard_ConstructionError("BRepOffset_MakeOffset::TrimEdge");
4029     }
4030     if (!V1.IsSame(V2)) {
4031       NE.Free( Standard_True );
4032       BRep_Builder B;
4033       TopAbs_Orientation Or = NE.Orientation();
4034       NE.Orientation(TopAbs_FORWARD);
4035       TopoDS_Vertex VF,VL;
4036       TopExp::Vertices (NE,VF,VL);
4037       B.Remove(NE,VF);
4038       B.Remove(NE,VL);
4039       B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
4040       B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
4041       B.Range(NE,UMin,UMax);
4042       NE.Orientation(Or);
4043       AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
4044       AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
4045       BRepLib::SameParameter(NE, aSameParTol, Standard_True);
4046       //
4047       bTrim = Standard_True;
4048     }
4049   }
4050   //
4051   if (!bTrim) {
4052     BRepAdaptor_Curve aBAC(NE);
4053     if (aBAC.GetType() == GeomAbs_Line) {
4054       if (AsDes->HasAscendant(NE)) {
4055         AsDes->Remove(NE);
4056       }
4057     }
4058   }
4059   else
4060   {
4061     if (!theETrimEInf.IsBound(NE)) {
4062       theETrimEInf.Bind(NE, aSourceEdge);
4063     }
4064   }
4065 }
4066
4067 //=======================================================================
4068 //function : GetEnlargedFaces
4069 //purpose  : 
4070 //=======================================================================
4071 void GetEnlargedFaces(const TopoDS_Shape& theShape,
4072                       const BRepOffset_DataMapOfShapeOffset& theMapSF,
4073                       const TopTools_DataMapOfShapeShape& theMES,
4074                       TopTools_DataMapOfShapeShape& theFacesOrigins,
4075                       BRepAlgo_Image& theImage,
4076                       TopTools_ListOfShape& theLSF)
4077 {
4078   TopExp_Explorer aExp(theShape, TopAbs_FACE);
4079   for (; aExp.More(); aExp.Next()) {
4080     const TopoDS_Shape& FI  = aExp.Current();
4081     const TopoDS_Shape& OFI = theMapSF(FI).Face();
4082     if (theMES.IsBound(OFI)) {
4083       const TopoDS_Face& aLocalFace = TopoDS::Face(theMES(OFI));
4084       theLSF.Append(aLocalFace);
4085       theImage.SetRoot(aLocalFace);
4086       //
4087       theFacesOrigins.Bind(aLocalFace, FI);
4088     }
4089   }
4090 }
4091
4092 //=======================================================================
4093 //function : BuildShellsCompleteInter
4094 //purpose  : Make the shells from list of faces using MakerVolume algorithm.
4095 //           In case there will be more than just one solid, it will be
4096 //           rebuilt using only outer faces.
4097 //=======================================================================
4098 Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
4099                                           BRepAlgo_Image& theImage,
4100                                           TopoDS_Shape& theShells)
4101 {
4102   // make solids
4103   BOPAlgo_MakerVolume aMV1;
4104   aMV1.SetArguments(theLF);
4105   // we need to intersect the faces to process the tangential faces
4106   aMV1.SetIntersect(Standard_True);
4107   aMV1.SetAvoidInternalShapes(Standard_True);
4108   aMV1.Perform();
4109   //
4110   Standard_Boolean bDone = ! aMV1.HasErrors();
4111   if (!bDone) {
4112     return bDone;
4113   }
4114   //
4115   UpdateHistory(theLF, aMV1, theImage);
4116   //
4117   const TopoDS_Shape& aResult1 = aMV1.Shape();
4118   if (aResult1.ShapeType() == TopAbs_SOLID) {
4119     // result is the alone solid, nothing to do
4120     return GetSubShapes(aResult1, TopAbs_SHELL, theShells);
4121   }
4122
4123   // Allocators for effective memory allocations
4124   // Global allocator for the long-living containers
4125   Handle(NCollection_IncAllocator) anAllocGlob = new NCollection_IncAllocator;
4126   // Local allocator for the local containers
4127   Handle(NCollection_IncAllocator) anAllocLoc = new NCollection_IncAllocator;
4128
4129   // Since the <theImage> object does not support multiple ancestors,
4130   // prepare local copy of the origins, which will be used to resolve
4131   // non-manifold solids produced by Maker Volume algorithm by comparison
4132   // of the normal directions of the split faces with their origins.
4133   TopTools_DataMapOfShapeListOfShape anOrigins(1, anAllocGlob);
4134   TopTools_ListIteratorOfListOfShape aItLR(theImage.Roots());
4135   for (; aItLR.More(); aItLR.Next())
4136   {
4137     const TopoDS_Shape& aFR = aItLR.Value();
4138
4139     // Reset the local allocator
4140     anAllocLoc->Reset();
4141     // Find the last splits of the root face, including the ones
4142     // created during MakeVolume operation
4143     TopTools_ListOfShape aLFIm(anAllocLoc);
4144     theImage.LastImage(aFR, aLFIm);
4145
4146     TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4147     for (; aItLFIm.More(); aItLFIm.Next())
4148     {
4149       const TopoDS_Shape& aFIm = aItLFIm.Value();
4150       TopTools_ListOfShape *pLFOr = anOrigins.ChangeSeek(aFIm);
4151       if (!pLFOr) {
4152         pLFOr = anOrigins.Bound(aFIm, TopTools_ListOfShape(anAllocGlob));
4153       }
4154       pLFOr->Append(aFR);
4155     }
4156   }
4157
4158   // Reset the local allocator
4159   anAllocLoc->Reset();
4160   // It is necessary to rebuild the solids, avoiding internal faces
4161   // Map faces to solids
4162   TopTools_IndexedDataMapOfShapeListOfShape aDMFS(1, anAllocLoc);
4163   TopExp::MapShapesAndAncestors(aResult1, TopAbs_FACE, TopAbs_SOLID, aDMFS);
4164   //
4165   Standard_Integer i, aNb = aDMFS.Extent();
4166   bDone = (aNb > 0);
4167   if (!bDone) {
4168     // unable to build any solid
4169     return bDone;
4170   }
4171   //
4172   // get faces attached to only one solid
4173   TopTools_ListOfShape aLF(anAllocLoc);
4174   for (i = 1; i <= aNb; ++i) {
4175     const TopTools_ListOfShape& aLS = aDMFS(i);
4176     if (aLS.Extent() == 1) {
4177       const TopoDS_Shape& aF = aDMFS.FindKey(i);
4178       aLF.Append(aF);
4179     }
4180   }
4181   //
4182   // make solids from the new list
4183   BOPAlgo_MakerVolume aMV2;
4184   aMV2.SetArguments(aLF);
4185   // no need to intersect this time
4186   aMV2.SetIntersect(Standard_False);
4187   aMV2.SetAvoidInternalShapes(Standard_True);
4188   aMV2.Perform();
4189   bDone = ! aMV2.HasErrors();
4190   if (!bDone) {
4191     return bDone;
4192   }
4193   //
4194   const TopoDS_Shape& aResult2 = aMV2.Shape();
4195   if (aResult2.ShapeType() == TopAbs_SOLID) {
4196     return GetSubShapes(aResult2, TopAbs_SHELL, theShells);
4197   }
4198   //
4199   TopExp_Explorer aExp(aResult2, TopAbs_FACE);
4200   bDone = aExp.More();
4201   if (!bDone) {
4202     return bDone;
4203   }
4204   //
4205   aLF.Clear();
4206   aDMFS.Clear();
4207   anAllocLoc->Reset();
4208
4209   // the result is non-manifold - resolve it comparing normal
4210   // directions of the offset faces and original faces
4211   for (; aExp.More(); aExp.Next())
4212   {
4213     const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
4214     const TopTools_ListOfShape* pLFOr = anOrigins.Seek(aF);
4215     if (!pLFOr)
4216     {
4217       Standard_ASSERT_INVOKE("BRepOffset_MakeOffset::BuildShellsCompleteInterSplit(): "
4218                              "Origins map does not contain the split face");
4219       continue;
4220     }
4221     // Check orientation
4222     TopTools_ListIteratorOfListOfShape aItLOr(*pLFOr);
4223     for (; aItLOr.More(); aItLOr.Next())
4224     {
4225       const TopoDS_Face& aFOr = TopoDS::Face(aItLOr.Value());
4226       if (BRepOffset_Tool::CheckPlanesNormals(aF, aFOr))
4227       {
4228         aLF.Append(aF);
4229         break;
4230       }
4231     }
4232   }
4233   //
4234   // make solid from most outer faces with correct normal direction
4235   BOPAlgo_MakerVolume aMV3;
4236   aMV3.SetArguments(aLF);
4237   aMV3.SetIntersect(Standard_False);
4238   aMV3.SetAvoidInternalShapes(Standard_True);
4239   aMV3.Perform();
4240   bDone = ! aMV3.HasErrors();
4241   if (!bDone) {
4242     return bDone;
4243   }
4244   //
4245   const TopoDS_Shape& aResult3 = aMV3.Shape();
4246   return GetSubShapes(aResult3, TopAbs_SHELL, theShells);
4247 }
4248
4249 //=======================================================================
4250 //function : GetSubShapes
4251 //purpose  : 
4252 //=======================================================================
4253 Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
4254                               const TopAbs_ShapeEnum theSSType,
4255                               TopoDS_Shape& theResult)
4256 {
4257   TopExp_Explorer aExp(theShape, theSSType);
4258   if (!aExp.More()) {
4259     return Standard_False;
4260   }
4261   //
4262   TopoDS_Compound aResult;
4263   BRep_Builder().MakeCompound(aResult);
4264   //
4265   for (; aExp.More(); aExp.Next()) {
4266     const TopoDS_Shape& aSS = aExp.Current();
4267     BRep_Builder().Add(aResult, aSS);
4268   }
4269   theResult = aResult;
4270   return Standard_True;
4271 }
4272
4273 //=======================================================================
4274 //function : IsPlanar
4275 //purpose  : Checks if all the faces of the shape are planes
4276 //=======================================================================
4277 Standard_Boolean IsPlanar(const TopoDS_Shape& theS)
4278 {
4279   TopExp_Explorer aExp(theS, TopAbs_FACE);
4280   for (; aExp.More(); aExp.Next()) {
4281     const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
4282     BRepAdaptor_Surface aBAS(aF, Standard_False);
4283     if (aBAS.GetType() != GeomAbs_Plane) {
4284       break;
4285     }
4286   }
4287   return !aExp.More();
4288 }
4289
4290 //=======================================================================
4291 //function : IsSolid
4292 //purpose  : Checks if the shape is solid
4293 //=======================================================================
4294 Standard_Boolean IsSolid(const TopoDS_Shape& theS)
4295 {
4296   TopExp_Explorer aExp(theS, TopAbs_SOLID);
4297   return aExp.More();
4298 }
4299
4300 //=======================================================================
4301 //function : AppendToList
4302 //purpose  : Add to a list only unique elements
4303 //=======================================================================
4304 void AppendToList(TopTools_ListOfShape& theList,
4305                   const TopoDS_Shape& theShape)
4306 {
4307   TopTools_ListIteratorOfListOfShape aIt(theList);
4308   for (; aIt.More(); aIt.Next()) {
4309     const TopoDS_Shape& aS = aIt.Value();
4310     if (aS.IsSame(theShape)) {
4311       return;
4312     }
4313   }
4314   theList.Append(theShape);
4315 }