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