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