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