0025266: Debug statements in the source are getting flushed on to the console
[occt.git] / src / BiTgte / BiTgte_Blend.cxx
1 // Created on: 1996-12-16
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1996-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 #include <stdio.h>
18
19 #include <BiTgte_Blend.ixx>
20
21 // include - all hxx,
22 //         - all small static functions.
23
24 //======================== START STATIC FUNCTIONS ============
25 #include <BiTgte_DataMapOfShapeBox.hxx>
26 #include <BiTgte_CurveOnEdge.hxx>
27
28 #include <Bnd_Box.hxx>
29 #include <BRepBndLib.hxx>
30 #include <BRepTools.hxx>
31 #include <BRepTools_Quilt.hxx>
32 #include <BRepBuilderAPI_Sewing.hxx>
33 #include <BRep_Tool.hxx>
34 #include <BRep_Builder.hxx>
35 #include <BRepLib_MakeEdge.hxx>
36 #include <BRepOffset_DataMapOfShapeOffset.hxx>
37 #include <BRepOffset_DataMapIteratorOfDataMapOfShapeOffset.hxx>
38 #include <BRepOffset_Offset.hxx>
39 #include <BRepOffset_MakeLoops.hxx>
40 #include <BRepOffset_Inter3d.hxx>
41 #include <BRepOffset_Inter2d.hxx>
42 #include <BRepOffset_Interval.hxx>
43 #include <BRepOffset_ListOfInterval.hxx>
44 #include <BRepOffset_Tool.hxx>
45 #include <BRepAlgo_Loop.hxx>
46 #include <ChFi3d.hxx>
47 #include <GeomAbs_SurfaceType.hxx>
48 #include <GeomAPI_ProjectPointOnCurve.hxx>
49 #include <Geom_BSplineCurve.hxx>
50 #include <Geom_TrimmedCurve.hxx>
51 #include <Geom_Circle.hxx>
52 #include <Geom_Line.hxx>
53 #include <Geom2d_Curve.hxx>
54 #include <GeomAdaptor_Surface.hxx>
55 #include <Geom2dAdaptor_Curve.hxx>
56 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
57 #include <TopExp_Explorer.hxx>
58 #include <TopoDS_Wire.hxx>
59 #include <TopoDS_Vertex.hxx>
60 #include <TopoDS_Edge.hxx>
61 #include <TopoDS_Compound.hxx>
62 #include <TopTools_ListOfShape.hxx>
63 #include <TopTools_SequenceOfShape.hxx>
64 #include <TopTools_DataMapOfShapeShape.hxx>
65 #include <TopTools_MapIteratorOfMapOfShape.hxx>
66 #include <TopTools_ListIteratorOfListOfShape.hxx>
67 #include <gp.hxx>
68 #include <gp_Pnt2d.hxx>
69 #include <gp_Lin2d.hxx>
70 #include <gp_Lin.hxx>
71 #include <gp_Dir2d.hxx>
72 #include <gp_Pnt.hxx>
73 #include <gp_Dir.hxx>
74 #include <gp_Ax1.hxx>
75 #include <gp_Ax3.hxx>
76 #include <gp_Circ.hxx>
77 #include <gp_Sphere.hxx>
78
79 #include <AppCont_Function.hxx>
80 #include <Approx_FitAndDivide.hxx>
81 #include <AppParCurves_MultiCurve.hxx>
82 #include <BSplCLib.hxx>
83 #include <Convert_CompBezierCurvesToBSplineCurve.hxx>
84 #include <Precision.hxx>
85 #include <TColgp_Array1OfPnt.hxx>
86 #include <TColStd_Array1OfReal.hxx>
87 #include <TColStd_Array1OfInteger.hxx>
88
89 #include <Standard_NotImplemented.hxx>
90
91 #include <BRepLib.hxx>
92 #include <ElSLib.hxx>
93 #include <GeomAPI.hxx>
94 #include <TopoDS.hxx>
95 #include <TopExp.hxx>
96
97 #include <OSD_Chronometer.hxx>
98 // variables for performance 
99 Standard_Real t_mkcurve;
100 extern void ChFi3d_InitChron(OSD_Chronometer& ch);
101 extern void ChFi3d_ResultChron(OSD_Chronometer & ch, Standard_Real&    time);
102 #ifdef DRAW
103 static Standard_Boolean Affich = Standard_False;
104 static char name[100];
105 #include <DBRep.hxx>
106 #endif
107
108 //=======================================================================
109 //function : IsOnRestriction
110 //purpose  : 
111 //=======================================================================
112
113 static Standard_Boolean IsOnRestriction(const TopoDS_Vertex& V,
114                                         const TopoDS_Edge&   CurE,
115                                         const TopoDS_Face&   F,
116                                               TopoDS_Edge&   E) 
117 {
118   // find if Vertex V of CurE is on a restriction of F.
119   // if yes, store this restriction in E.
120
121   // dub - 03 01 97
122   // Method somewhat brutal : possible to really optimize by a
123   // direct call the SD of intersections -> See LBR
124
125   Standard_Real f,l;
126   Handle(Geom2d_Curve) CurC = BRep_Tool::CurveOnSurface(CurE,F,f,l);
127   Standard_Real U = BRep_Tool::Parameter(V,CurE,F);
128   gp_Pnt2d P = CurC->Value(U);
129
130   Geom2dAPI_ProjectPointOnCurve Proj;
131   
132   // The tolerance is exaggerated : it is better to construct too many
133   // tubes than to miss intersections.
134   // Standard_Real Tol = 100 * BRep_Tool::Tolerance(V);
135   Standard_Real Tol = BRep_Tool::Tolerance(V);
136   TopExp_Explorer exp(F,TopAbs_EDGE);
137   for ( ; exp.More(); exp.Next()) {
138     E = TopoDS::Edge(exp.Current());
139     Handle(Geom2d_Curve) PC = BRep_Tool::CurveOnSurface(E,F,f,l);
140     Proj.Init(P,PC,f,l);
141     if ( Proj.NbPoints() > 0) {
142       if (Proj.LowerDistance() < Tol) {
143         return Standard_True; 
144       }
145     }
146   }
147   return Standard_False;
148 }
149
150 //=======================================================================
151 //function : Add
152 //purpose  : 
153 //=======================================================================
154
155 static void Add(const TopoDS_Edge&         E,
156                       TopTools_IndexedMapOfShape& Map,
157                 const TopoDS_Shape&        S,
158                 const BRepOffset_Offset&   OF,
159                 const BRepOffset_Analyse&  Analyse,
160                 const Standard_Boolean     WarningSurBordLibre)
161 // If WarningSurBordLibre = TRUE, no propagation if the edge is open.
162 {
163   TopAbs_ShapeEnum Type = S.ShapeType();
164
165   if ( Type == TopAbs_FACE) {
166     TopExp_Explorer exp(S,TopAbs_EDGE);
167     for ( ; exp.More(); exp.Next()) {
168       const TopoDS_Edge& OriE = TopoDS::Edge(exp.Current());
169       TopoDS_Shape aLocalShape = OF.Generated(OriE);
170       const TopoDS_Edge& IE   = TopoDS::Edge(aLocalShape);
171 //      const TopoDS_Edge& IE   = TopoDS::Edge(OF.Generated(OriE));
172       if ( E.IsEqual(IE)) {
173         if (WarningSurBordLibre) {
174           // It is checked that the border is not free.
175           const TopTools_ListOfShape& L = Analyse.Ancestors(OriE);
176           if (L.Extent() == 1) break; // Nothing is done.
177         }
178         Map.Add(exp.Current());
179         break;
180       }
181     }
182   }
183   else if ( Type == TopAbs_EDGE) {
184     TopExp_Explorer exp(S,TopAbs_VERTEX);
185     for ( ; exp.More(); exp.Next()) {
186       TopoDS_Shape aLocalShape = OF.Generated(exp.Current());
187       const TopoDS_Edge& IE = TopoDS::Edge(aLocalShape);
188 //      const TopoDS_Edge& IE = TopoDS::Edge(OF.Generated(exp.Current()));
189       if ( E.IsEqual(IE)) {
190         const TopTools_ListOfShape& L = Analyse.Ancestors(exp.Current());
191         TopTools_ListIteratorOfListOfShape it(L);
192         for ( ; it.More(); it.Next()) {
193           Map.Add(it.Value());
194         }
195         break;
196       }
197     }
198   }
199 }
200
201
202 //=======================================================================
203 //function : IsInFace
204 //purpose  : 
205 //=======================================================================
206
207 static Standard_Boolean IsInFace(const TopoDS_Edge& E,
208                                  const TopoDS_Face& F)
209 {
210   TopExp_Explorer exp(F,TopAbs_EDGE);
211   for ( ;exp.More(); exp.Next()) 
212     if ( E.IsSame(exp.Current())) return Standard_True;
213   return Standard_False;
214 }
215
216
217 //=======================================================================
218 //function : KPartCurve3d
219 //purpose  : 
220 //=======================================================================
221
222 static void KPartCurve3d(TopoDS_Edge           Edge,
223                          Handle(Geom2d_Curve)  Curve,
224                          Handle(Geom_Surface)  Surf)
225 {
226   // try to find the particular case
227   // if not found call BRepLib::BuildCurve3d
228
229   TopLoc_Location Loc;
230   Standard_Real Tol = Precision::Confusion();
231
232   // Seach only isos on analytical surfaces.
233   Geom2dAdaptor_Curve C(Curve);
234   GeomAdaptor_Surface S(Surf);
235   GeomAbs_CurveType   CTy = C.GetType();
236   GeomAbs_SurfaceType STy = S.GetType();
237   BRep_Builder TheBuilder;
238
239   if ( STy != GeomAbs_Plane) { // if plane buildcurve3d manage KPart
240     if ( CTy == GeomAbs_Line) {
241       gp_Dir2d D = C.Line().Direction();
242       if ( D.IsParallel(gp::DX2d(),Precision::Angular())) { // Iso V.
243         if ( STy == GeomAbs_Sphere) {
244           gp_Pnt2d  P    = C.Line().Location();
245           if ( Abs( Abs(P.Y()) -M_PI/2. ) < Precision::PConfusion()) {
246             TheBuilder.Degenerated(Edge, Standard_True);
247           }
248           else {
249             gp_Sphere Sph  = S.Sphere();
250             gp_Ax3    Axis = Sph.Position();
251             gp_Circ   Ci   = ElSLib::SphereVIso(Axis,
252                                                 Sph.Radius(),
253                                                 P.Y());
254             gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
255             gp_Ax1 AxeRev(Axis.Location(), DRev);
256             Ci.Rotate(AxeRev, P.X());
257             Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
258             if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
259               Circle->Reverse();
260             TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
261           }
262         }
263         else if ( STy == GeomAbs_Cylinder) {
264           gp_Cylinder Cyl  = S.Cylinder();
265           gp_Pnt2d    P    = C.Line().Location();
266           gp_Ax3      Axis = Cyl.Position();
267           gp_Circ     Ci   = ElSLib::CylinderVIso(Axis,
268                                                   Cyl.Radius(),
269                                                   P.Y());
270           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
271           gp_Ax1 AxeRev(Axis.Location(), DRev);
272           Ci.Rotate(AxeRev, P.X());
273           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
274           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
275             Circle->Reverse();
276           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
277         }
278         else if ( STy == GeomAbs_Cone) {
279           gp_Cone  Cone = S.Cone();
280           gp_Pnt2d P    = C.Line().Location();
281           gp_Ax3   Axis = Cone.Position();
282           gp_Circ  Ci   = ElSLib::ConeVIso(Axis,
283                                            Cone.RefRadius(),
284                                            Cone.SemiAngle(),
285                                            P.Y());
286           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
287           gp_Ax1 AxeRev(Axis.Location(), DRev);
288           Ci.Rotate(AxeRev, P.X());
289           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
290           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
291             Circle->Reverse();
292           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
293         }
294         else if ( STy == GeomAbs_Torus) {
295           gp_Torus Tore = S.Torus();
296           gp_Pnt2d P    = C.Line().Location();
297           gp_Ax3   Axis = Tore.Position();
298           gp_Circ  Ci   = ElSLib::TorusVIso(Axis,
299                                             Tore.MajorRadius(),
300                                             Tore.MinorRadius(),
301                                             P.Y());
302           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
303           gp_Ax1 AxeRev(Axis.Location(), DRev);
304           Ci.Rotate(AxeRev, P.X());
305           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
306           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
307             Circle->Reverse();
308           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
309         }
310       }
311       else if ( D.IsParallel(gp::DY2d(),Precision::Angular())) { // Iso U.
312         if ( STy == GeomAbs_Sphere) {
313           gp_Sphere Sph  = S.Sphere();
314           gp_Pnt2d  P    = C.Line().Location();
315           gp_Ax3    Axis = Sph.Position();
316           // calculate iso 0.
317           gp_Circ   Ci   = ElSLib::SphereUIso(Axis, Sph.Radius(),0.);
318
319           // set to sameparameter (rotation of the circle - offset from Y)
320           gp_Dir DRev = Axis.XDirection().Crossed(Axis. Direction());
321           gp_Ax1 AxeRev(Axis.Location(),DRev);
322           Ci.Rotate(AxeRev, P.Y());
323
324           // transformation by iso U ( = P.X())
325           DRev = Axis.XDirection().Crossed(Axis.YDirection());
326           AxeRev = gp_Ax1(Axis.Location(), DRev);
327           Ci.Rotate(AxeRev, P.X());
328           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
329           
330           if ( D.IsOpposite(gp::DY2d(),Precision::Angular())) 
331             Circle->Reverse();
332           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
333         }
334         else if ( STy == GeomAbs_Cylinder) {
335           gp_Cylinder Cyl = S.Cylinder();
336           gp_Pnt2d    P   = C.Line().Location();
337           gp_Lin      L   = ElSLib::CylinderUIso(Cyl.Position(),
338                                                  Cyl.Radius(),
339                                                  P.X());
340           gp_Vec Tr(L.Direction());
341           Tr.Multiply(P.Y());
342           L.Translate(Tr);
343           Handle(Geom_Line) Line = new Geom_Line(L);
344           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
345             Line->Reverse();
346           TheBuilder.UpdateEdge(Edge, Line, Loc, Tol);
347         }
348         else if ( STy == GeomAbs_Cone) {
349           gp_Cone  Cone = S.Cone();
350           gp_Pnt2d P    = C.Line().Location();
351           gp_Lin   L    = ElSLib::ConeUIso(Cone.Position(),
352                                            Cone.RefRadius(),
353                                            Cone.SemiAngle(),
354                                            P.X());
355           gp_Vec Tr(L.Direction());
356           Tr.Multiply(P.Y());
357           L.Translate(Tr);        Handle(Geom_Line) Line = new Geom_Line(L);
358           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
359             Line->Reverse();
360           TheBuilder.UpdateEdge(Edge, Line, Loc, Tol);
361         }
362         else if ( STy == GeomAbs_Torus) {
363         }
364       }
365     }
366   }
367   else { // Case Plane
368     Handle(Geom_Curve) C3d = GeomAPI::To3d(Curve,S.Plane());
369     TheBuilder.UpdateEdge(Edge, C3d, Loc, Tol);
370   }
371 }
372
373
374 //=======================================================================
375 //function : MakeCurve
376 //purpose  : 
377 //=======================================================================
378
379 class MakeCurve_Function : public AppCont_Function
380 {
381   BiTgte_CurveOnEdge myCurve;
382   
383   public :
384   
385   MakeCurve_Function(const BiTgte_CurveOnEdge& C) : myCurve(C) {};
386
387   Standard_Real FirstParameter() const
388     {return myCurve.FirstParameter();}
389   
390   Standard_Real LastParameter() const
391     {return myCurve.LastParameter();}
392   
393   gp_Pnt Value(const Standard_Real t) const
394     {return myCurve.Value(t);}
395   
396   Standard_Boolean D1(const Standard_Real /*t*/, gp_Pnt& /*P*/, gp_Vec& /*V*/) const
397     {return Standard_False;}
398
399 };
400
401 Handle(Geom_Curve) MakeCurve (const BiTgte_CurveOnEdge& HC)
402 {
403   Handle(Geom_Curve) C;
404
405 #if BITGTE_DEB
406    OSD_Chronometer ch;
407    ChFi3d_InitChron(ch);
408 #endif
409
410   if ( HC.GetType() == GeomAbs_Circle) {
411     C = new Geom_Circle(HC.Circle());
412     C = new Geom_TrimmedCurve(C,HC.FirstParameter(),HC.LastParameter());
413   }
414   else { // the approximation is done
415     MakeCurve_Function F(HC);
416     Standard_Integer Deg1, Deg2;
417     Deg1 = Deg2 = 8;
418     Standard_Real Tol = Precision::Approximation();
419     Approx_FitAndDivide Fit(F,Deg1,Deg2,Tol,Tol,Standard_True);
420     Standard_Integer i;
421     Standard_Integer NbCurves = Fit.NbMultiCurves();
422     // it is attempted to make the curve at least C1
423     Convert_CompBezierCurvesToBSplineCurve Conv;
424     
425     for (i = 1; i <= NbCurves; i++) {
426       AppParCurves_MultiCurve MC = Fit.Value( i);    //Load the Ith Curve
427       TColgp_Array1OfPnt Poles( 1, MC.Degree() + 1); //Return poles
428       MC.Curve(1, Poles);
429       
430       Conv.AddCurve(Poles);
431     }
432     
433     Conv.Perform();
434     
435     Standard_Integer NbPoles    = Conv.NbPoles();
436     Standard_Integer NbKnots    = Conv.NbKnots();
437     TColgp_Array1OfPnt      NewPoles(1,NbPoles);
438     TColStd_Array1OfReal    NewKnots(1,NbKnots);
439     TColStd_Array1OfInteger NewMults(1,NbKnots);
440     
441     Conv.KnotsAndMults(NewKnots,NewMults);
442     Conv.Poles(NewPoles);
443     
444     BSplCLib::Reparametrize(HC.FirstParameter(),
445                             HC.LastParameter(),
446                             NewKnots);
447     
448     C = new Geom_BSplineCurve (NewPoles,
449                                NewKnots,
450                                NewMults,
451                                Conv.Degree());
452   }
453
454 #if BITGTE_DEB
455   ChFi3d_ResultChron(ch, t_mkcurve);
456 #endif
457
458   return C;
459 }
460
461
462 //=======================================================================
463 //function : Touched
464 //purpose  : Only the faces connected with caps are given
465 //=======================================================================
466
467 static void Touched(const BRepOffset_Analyse&, 
468                     const TopTools_MapOfShape&, 
469                     const TopoDS_Shape&,
470                     TopTools_MapOfShape&)
471 {
472   // currently nothing is done !!
473   /*if ( Standard_True) {
474     return;
475   }
476   else {
477     TopExp_Explorer exp(Shape, TopAbs_EDGE);
478     for ( ; exp.More(); exp.Next()) {
479       const TopTools_ListOfShape& L = Analyse.Ancestors(exp.Current());
480       if (StopFaces.Contains(L.First())) 
481         TouchedByCork.Add(L.Last());
482       else if (StopFaces.Contains(L.Last())) 
483         TouchedByCork.Add(L.First());
484     }
485   }*/
486   return;
487 }
488
489 //=======================================================================
490 //function : FindVertex
491 //purpose  : 
492 //=======================================================================
493
494 static TopoDS_Vertex FindVertex(const gp_Pnt&              P,
495                                 const TopTools_MapOfShape& Map,
496                                 const Standard_Real        Tol)
497 {
498   BRep_Builder B;
499   // Find in <Map> a vertex which represent the point <P>.
500   Standard_Real Tol2,Dist;
501   TopoDS_Vertex V,VV[2];
502   Standard_Real TolCarre = Tol*Tol;
503   TopTools_MapIteratorOfMapOfShape it(Map);
504   for ( ; it.More(); it.Next()) {
505     const TopoDS_Edge& E = TopoDS::Edge(it.Key());
506     if ( !E.IsNull()) {
507       TopExp::Vertices(E,VV[0],VV[1]);
508
509       for (Standard_Integer i = 0; i < 2 ; i++) {
510         // if OK la Tolerance du Vertex
511         Tol2 = BRep_Tool::Tolerance(VV[i]);
512         Tol2 *= Tol2;
513         gp_Pnt P1 = BRep_Tool::Pnt(VV[i]);
514         Dist = P.SquareDistance(P1);
515         if ( Dist <= Tol2) return VV[i];
516         // otherwise with the required tolerance.
517         if (TolCarre > Tol2) {
518           if ( Dist <= TolCarre) {
519             // so it is necessary to update the tolerance of Vertex.
520             B.UpdateVertex(VV[i],Tol);
521             return VV[i];
522           }
523         }
524       }
525     }
526   }
527
528   return V;
529 }
530
531
532 //=======================================================================
533 //function : MakeDegeneratedEdge
534 //purpose  : 
535 //=======================================================================
536
537 static TopoDS_Edge MakeDegeneratedEdge(const Handle(Geom_Curve)& CC,
538                                        const TopoDS_Vertex&    VfOnE)
539 {
540   BRep_Builder B;
541   Standard_Real Tol = Precision::Confusion();
542   // kill trimmed curves
543   Handle(Geom_Curve) C = CC;
544   Handle(Geom_TrimmedCurve) CT = Handle(Geom_TrimmedCurve)::DownCast(C);
545   while (!CT.IsNull()) {
546     C = CT->BasisCurve();
547     CT = Handle(Geom_TrimmedCurve)::DownCast(C);
548   }
549
550   TopoDS_Vertex V1,V2;
551   if ( VfOnE.IsNull()) {
552     gp_Pnt P = C->Value(C->FirstParameter());
553     B.MakeVertex(V1,P,Tol);
554     V2 = V1;
555   }
556   else {
557     V1 = V2 = VfOnE;
558   }
559   V1.Orientation(TopAbs_FORWARD);
560   V2.Orientation(TopAbs_REVERSED);
561
562   TopoDS_Edge E;
563   B.MakeEdge(E,C,Tol);
564   B.Add(E,V1); B.Add(E,V2);
565 //  B.UpdateVertex(V1,C->FirstParameter(),E,Tol);
566 //  B.UpdateVertex(V2,C->LastParameter(),E,Tol);
567   B.Range(E,CC->FirstParameter(),CC->LastParameter());
568   return E;
569 }
570
571
572 //=======================================================================
573 //function : Orientation
574 //purpose  : 
575 //=======================================================================
576
577 static TopAbs_Orientation Orientation(const TopoDS_Edge& E,
578                                       const TopoDS_Face& F,
579                                       const TopTools_ListOfShape& L)
580 {
581   TopAbs_Orientation Orien = TopAbs_FORWARD;
582   TopTools_ListIteratorOfListOfShape itld;
583   for ( itld.Initialize(L); itld.More(); itld.Next()) {
584     if ( itld.Value().IsSame(E)) {
585       Orien = itld.Value().Orientation();
586       break;
587     }
588   }
589   if ( F.Orientation() == TopAbs_REVERSED) 
590     Orien = TopAbs::Reverse(Orien);
591   
592   return Orien;
593 }
594
595 //=======================================================================
596 //function : FindCreatedEdge
597 //purpose  : 
598 //=======================================================================
599
600 static TopoDS_Edge FindCreatedEdge
601 (const TopoDS_Vertex&                   V1,
602  const TopoDS_Edge&                     E,
603  const BRepOffset_DataMapOfShapeOffset& MapSF,
604        TopTools_MapOfShape&             MapOnV,
605  const BRepOffset_Analyse&              CenterAnalyse,
606        Standard_Real                    Radius,
607        Standard_Real                    Tol)
608 {
609   TopoDS_Edge E1;
610   if (!CenterAnalyse.HasAncestor(V1)) return E1; // return a Null Shape.
611
612   TopTools_ListOfShape TangE;
613   CenterAnalyse.TangentEdges(E,V1,TangE);
614
615   TopTools_ListIteratorOfListOfShape itl(TangE);
616   Standard_Boolean Find = Standard_False;
617   for ( ; itl.More() && !Find; itl.Next()) {
618     const TopoDS_Edge& ET = TopoDS::Edge(itl.Value());
619     if ( MapSF.IsBound(ET)) {
620       TopoDS_Shape aLocalShape = MapSF(ET).Generated(V1);
621       E1 = TopoDS::Edge(aLocalShape);
622 //      E1 = TopoDS::Edge(MapSF(ET).Generated(V1));
623       MapOnV.Add(E1);
624       Find = Standard_True;
625     }
626     else {
627       // Find the sharing of vertices in case of tangent consecutive 3 edges 
628       // the second of which is the edge that degenerates the tube.
629       TopLoc_Location CLoc;
630       Standard_Real ff,ll;
631       Handle(Geom_Curve) CET = 
632         BRep_Tool::Curve(ET,CLoc,ff,ll);
633       if ( CET->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
634         CET = Handle(Geom_TrimmedCurve)::DownCast(CET)->BasisCurve();
635       }
636       Handle(Geom_Circle) Circ = Handle(Geom_Circle)::DownCast(CET);
637       if ( Circ.IsNull()) continue;
638       if ( Abs(Circ->Radius() - Abs(Radius)) > Tol) continue;
639       
640       TopoDS_Vertex U1,U2;
641       TopExp::Vertices(ET,U1,U2);
642       if ( U1.IsSame(V1)) U1 = U2;
643       TopTools_ListOfShape Tang2;
644       CenterAnalyse.TangentEdges(ET,U1,Tang2);
645       TopTools_ListIteratorOfListOfShape it2(Tang2);
646       for ( ; it2.More() ; it2.Next()) {
647         const TopoDS_Edge& ET2 = TopoDS::Edge(it2.Value());
648         if ( MapSF.IsBound(ET2)) {
649           TopoDS_Shape aLocalShape = MapSF(ET2).Generated(U1);
650           MapOnV.Add(TopoDS::Edge(aLocalShape));
651 //        MapOnV.Add(TopoDS::Edge(MapSF(ET2).Generated(U1)));
652         }
653       }
654     }
655   }
656   if (!Find) {
657     TangE.Clear();
658     //  CenterAnalyse.Edges(V1f, OT, TangE);
659     if (CenterAnalyse.HasAncestor(V1)) {
660       TangE = CenterAnalyse.Ancestors(V1);
661       itl.Initialize(TangE);
662       for ( ; itl.More() && !Find; itl.Next()) {
663         if ( MapSF.IsBound(itl.Value())) {
664           MapOnV.Add(MapSF(itl.Value()).Generated(V1));
665         }
666       }
667     }
668   }
669   
670   return E1;
671 }
672
673 //=======================================================================
674 //function : Bubble
675 //purpose  : Sets in increasing order the sequence of vertices. 
676 //=======================================================================
677
678 static void Bubble(const TopoDS_Edge&        E,
679                    TopTools_SequenceOfShape& Seq) 
680 {
681   Standard_Boolean Invert   = Standard_True;
682   Standard_Integer NbPoints = Seq.Length();
683   Standard_Real    U1,U2;
684   TopoDS_Vertex    V1,V2;
685
686   while (Invert) {
687     Invert = Standard_False;
688     for ( Standard_Integer i = 1; i < NbPoints; i++) {
689       TopoDS_Shape aLocalShape = Seq.Value(i)  .Oriented(TopAbs_INTERNAL);
690       V1 = TopoDS::Vertex(aLocalShape);
691       aLocalShape = Seq.Value(i+1).Oriented(TopAbs_INTERNAL);
692       V2 = TopoDS::Vertex(aLocalShape);
693 //      V1 = TopoDS::Vertex(Seq.Value(i)  .Oriented(TopAbs_INTERNAL));
694 //      V2 = TopoDS::Vertex(Seq.Value(i+1).Oriented(TopAbs_INTERNAL));
695
696       U1 = BRep_Tool::Parameter(V1,E);
697       U2 = BRep_Tool::Parameter(V2,E);
698       if (U2 < U1) {
699         Seq.Exchange(i,i+1);
700         Invert = Standard_True;
701       }
702     }
703   }
704 }
705
706 //=======================================================================
707 //function : CutEdge
708 //purpose  : 
709 //=======================================================================
710
711 static void CutEdge (const TopoDS_Edge&          E,
712                      const TopTools_ListOfShape& VOnE,
713                            TopTools_ListOfShape& NE   )
714 {
715   TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
716   TopoDS_Edge WE = TopoDS::Edge(aLocalShape);
717 //  TopoDS_Edge WE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
718
719   Standard_Real                      U1,U2;
720   TopoDS_Vertex                      V1,V2;
721   TopTools_SequenceOfShape           SV;
722   TopTools_ListIteratorOfListOfShape it(VOnE);
723   BRep_Builder                       B;
724
725   for ( ; it.More(); it.Next()) {
726     SV.Append(it.Value());
727   }
728   //--------------------------------
729   // Parse vertices on the edge.
730   //--------------------------------
731   Bubble (WE,SV);
732
733   Standard_Integer NbVer = SV.Length();
734   //----------------------------------------------------------------
735   // Construction of new edges.
736   // The vertices at the extremities of edges are not 
737   // necessarily in the list of vertices
738   //----------------------------------------------------------------
739   if (SV.IsEmpty()) {
740     NE.Append(E);
741     return;
742   }
743   TopoDS_Vertex    VF,VL;
744   Standard_Real    f,l;
745   BRep_Tool::Range(WE,f,l);
746   TopExp::Vertices(WE,VF,VL);
747
748   if (NbVer == 2) {
749     if (SV(1).IsEqual(VF) && SV(2).IsEqual(VL)) {
750       NE.Append(E);
751       return;
752     }
753   }
754   //----------------------------------------------------
755   // Processing of closed edges 
756   // If a vertex of intersection is on the common vertex,
757   // it should appear at the beginning and the end of SV.
758   //----------------------------------------------------
759   TopoDS_Vertex VCEI;
760
761   if (!VF.IsNull() && !VF.IsSame(SV.First())) SV.Prepend(VF);
762   if (!VL.IsNull() && !VL.IsSame(SV.Last ())) SV.Append (VL);
763
764   V1  = TopoDS::Vertex(SV.First());
765   SV.Remove(1);
766
767   while (!SV.IsEmpty()) {
768     
769     V2  = TopoDS::Vertex(SV.First());
770     SV.Remove(1);
771     
772     if ( V1.IsSame(V2)) {
773       cout << "Vertex Confondus dans CutEdges" << endl;
774       continue;
775     }
776     //-------------------------------------------
777     // Copy the edge and restriction by V1 V2.
778     //-------------------------------------------
779     TopoDS_Shape aLocalShape =WE.EmptyCopied();
780     TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
781 //    TopoDS_Edge NewEdge = TopoDS::Edge(WE.EmptyCopied());
782     B.Add  (NewEdge,V1.Oriented(TopAbs_FORWARD));
783     B.Add  (NewEdge,V2.Oriented(TopAbs_REVERSED));
784     if (V1.IsSame(VF)) 
785       U1 = f;
786     else {
787       aLocalShape = V1.Oriented(TopAbs_INTERNAL);
788       U1 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),WE);
789 //      U1 = BRep_Tool::Parameter
790 //      (TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),WE);
791     }
792     if (V2.IsSame(VL))
793       U2 = l;
794     else {
795       aLocalShape = V2.Oriented(TopAbs_INTERNAL);
796       U2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),WE);
797 //      U2 = BRep_Tool::Parameter
798 //      (TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),WE);
799     }
800     B.Range (NewEdge,U1,U2);
801     NE.Append(NewEdge.Oriented(E.Orientation()));
802
803     V1 = V2;
804   }
805 }
806 //======================== END OF STATIC FUNCTIONS ============
807
808
809
810
811 //=======================================================================
812 //function : BiTgte_Blend
813 //purpose  : 
814 //=======================================================================
815
816 BiTgte_Blend::BiTgte_Blend()
817 {
818   myAsDes = new BRepAlgo_AsDes();
819   myNbBranches = -1;
820 }
821
822
823 //=======================================================================
824 //function : BiTgte_Blend
825 //purpose  : 
826 //=======================================================================
827
828 BiTgte_Blend::BiTgte_Blend(const TopoDS_Shape&    S,
829                            const Standard_Real    Radius,
830                            const Standard_Real    Tol,
831                            const Standard_Boolean NUBS)
832 {
833   myAsDes = new BRepAlgo_AsDes();
834   Init(S,Radius,Tol,NUBS);
835 }
836
837
838 //=======================================================================
839 //function : Init
840 //purpose  : 
841 //=======================================================================
842
843 void BiTgte_Blend::Init(const TopoDS_Shape&    S,
844                         const Standard_Real    Radius,
845                         const Standard_Real    Tol,
846                         const Standard_Boolean NUBS) 
847 {
848   Clear();
849   myShape      = S;
850   myTol        = Tol;
851   myNubs       = NUBS;
852   myRadius     = Radius;
853   myNbBranches = -1;
854 //  TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,myAncestors);
855 }
856
857
858 //=======================================================================
859 //function : Clear
860 //purpose  : 
861 //=======================================================================
862
863 void BiTgte_Blend::Clear() 
864 {
865   myInitOffsetFace.Clear();
866   myImage         .Clear();
867   myImageOffset   .Clear();
868   myStopFaces     .Clear();  
869   myAnalyse       .Clear();
870   myAsDes        ->Clear();
871   myNbBranches   = -1;
872   myDone         = Standard_False;
873 }
874
875
876 //=======================================================================
877 //function : SetStoppingFace
878 //purpose  : 
879 //=======================================================================
880
881 void BiTgte_Blend::SetStoppingFace(const TopoDS_Face& Face) 
882 {
883   myStopFaces.Add(Face);    
884   //-------------
885   // MAJ SD. -> To end loop, set faces of edges
886   //-------------
887 //  myInitOffsetFace.SetRoot(Face);    
888 //  myInitOffsetFace.Bind   (Face,Face);
889 //  myImageOffset.SetRoot   (Face);  
890 }
891
892
893 //=======================================================================
894 //function : SetFaces
895 //purpose  : 
896 //=======================================================================
897
898 void BiTgte_Blend::SetFaces(const TopoDS_Face& F1,const TopoDS_Face& F2) 
899 {
900   myFaces.Add(F1);
901   myFaces.Add(F2);
902 }
903
904
905 //=======================================================================
906 //function : SetEdge
907 //purpose  : 
908 //=======================================================================
909
910 void BiTgte_Blend::SetEdge(const TopoDS_Edge& Edge) 
911 {
912   myEdges.Add(Edge);
913 }
914
915
916 //=======================================================================
917 //function : Perform
918 //purpose  : 
919 //=======================================================================
920
921 void BiTgte_Blend::Perform(const Standard_Boolean BuildShape) 
922 {
923   myBuildShape = BuildShape;
924
925   // Try cutting to avoid tubes on free borders
926   // that are not actually free.
927   Handle(BRepBuilderAPI_Sewing) Sew = new BRepBuilderAPI_Sewing(myTol);
928   BRepLib::BuildCurves3d(myShape);
929   TopExp_Explorer expf(myShape,TopAbs_FACE);
930   for ( ;expf.More(); expf.Next()) Sew->Add(expf.Current());
931   Sew->Perform();
932   TopoDS_Shape SewedShape = Sew->SewedShape();
933   if ( SewedShape.IsNull()) Standard_Failure::Raise("Sewing aux fraises");
934
935   // Check if the sewing modified the orientation.
936   expf.Init(myShape,TopAbs_FACE);
937   TopoDS_Face FaceRef = TopoDS::Face(expf.Current());
938   TopAbs_Orientation OriRef  = FaceRef.Orientation();
939   if (Sew->IsModified(FaceRef)) FaceRef = TopoDS::Face(Sew->Modified(FaceRef));
940   expf.Init(SewedShape, TopAbs_FACE);
941   for (; expf.More(); expf.Next()) {
942     const TopoDS_Face& FF = TopoDS::Face(expf.Current());
943     if (FaceRef.IsSame(FF) && (FF.Orientation() != OriRef)) {
944       SewedShape.Reverse();
945       break;
946     }
947   } 
948   
949   // Make SameParameter if Sew does not do it (Detect that edges
950   // are not sameparameter but it does nothing.)
951   expf.Init(SewedShape, TopAbs_EDGE);
952   for (; expf.More(); expf.Next()) {
953     const TopoDS_Edge& sec = TopoDS::Edge(expf.Current());
954     BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
955   }
956   
957   TopExp::MapShapesAndAncestors
958     (SewedShape,TopAbs_EDGE,TopAbs_FACE,myAncestors);
959   
960   // Extend myFaces with the faces of the sewed shape.
961   expf.Init(myShape,TopAbs_FACE);
962   for ( ; expf.More(); expf.Next()) {
963     const TopoDS_Shape& F = expf.Current();
964     if ( myFaces.Contains(F) && Sew->IsModified(F)) {
965       //myFaces.Remove(F);
966       TopoDS_Shape LastFace = myFaces(myFaces.Extent());
967       myFaces.RemoveLast();
968       if (myFaces.FindIndex(F) != 0)
969         myFaces.Substitute(myFaces.FindIndex(F), LastFace);
970       ////////////////////
971       myFaces.Add(Sew->Modified(F));
972     }
973   }
974   
975   myShape = SewedShape;
976 // end Sewing for false free borders.
977
978 #if BITGTE_DEB
979   OSD_Chronometer cl_total, ch;
980   Standard_Real   t_total, t_center, t_surface, t_shape;
981
982   t_total=0; t_center=0; t_surface=0; t_mkcurve=0; t_shape=0;
983   ChFi3d_InitChron(cl_total); 
984 #endif  
985
986   // ----------------------------------------------------------------
987   // place faces with the proper orientation in the initial shape
988   // ----------------------------------------------------------------
989   TopExp_Explorer exp(myShape,TopAbs_FACE);
990   for ( ; exp.More(); exp.Next()) {
991     const TopoDS_Shape& F = exp.Current();
992     if ( myFaces.Contains(F)) {
993       //myFaces.Remove(F);
994       TopoDS_Shape LastFace = myFaces(myFaces.Extent());
995       myFaces.RemoveLast();
996       if (myFaces.FindIndex(F) != 0)
997         myFaces.Substitute(myFaces.FindIndex(F), LastFace);
998       ////////////////////
999       myFaces.Add(F);
1000     }
1001     else if ( myStopFaces.Contains(F)) {
1002       myStopFaces.Remove(F);
1003       myStopFaces.Add(F);
1004     }
1005   }
1006
1007   // ----------------------------------------------
1008   // Calculate lines of centers and of surfaces
1009   // ----------------------------------------------
1010 #if BITGTE_DEB
1011   ChFi3d_InitChron(ch);
1012 #endif  
1013
1014   ComputeCenters();
1015   
1016 #if BITGTE_DEB
1017   ChFi3d_ResultChron(ch, t_center);
1018 #endif 
1019
1020   // -----------------------------
1021   // Calculate connection Surfaces
1022   // -----------------------------
1023 #if BITGTE_DEB
1024   ChFi3d_InitChron(ch);
1025 #endif
1026
1027   ComputeSurfaces();
1028
1029 #if BITGTE_DEB
1030   ChFi3d_ResultChron(ch, t_surface);
1031 #endif 
1032
1033   // ----------------------------------
1034   // Calculate the generated shape if required
1035   // ----------------------------------
1036 #if BITGTE_DEB
1037   ChFi3d_InitChron(ch);
1038 #endif  
1039
1040   if ( myBuildShape) ComputeShape();
1041
1042 #if BITGTE_DEB
1043   ChFi3d_ResultChron(ch, t_shape);
1044 #endif 
1045
1046   // Finally construct curves 3d from edges to be transfered
1047   // since the partition is provided ( A Priori);
1048   BRepLib::BuildCurves3d(myResult, Precision::Confusion());
1049
1050 #ifdef BITGTE_DEB
1051   ChFi3d_ResultChron(cl_total, t_total);
1052   cout<<endl; 
1053   cout<<"Blend_PERFORM: temps total "<<t_total<<" s  dont :"<<endl;
1054   cout<<"- ComputeCenters  "<<t_center<<" s"<<endl;  
1055   cout<<"- ComputeSurfaces "<<t_surface<<" s"<<endl;
1056   cout<<"----> MakeCurve   "<<t_mkcurve<<" s"<<endl;
1057   if ( myBuildShape)  cout<<"- ComputeShape "<<t_shape<<" s"<<endl;
1058 #endif
1059
1060   myDone = Standard_True;
1061 }
1062
1063
1064 //=======================================================================
1065 //function : IsDone
1066 //purpose  : 
1067 //=======================================================================
1068
1069 Standard_Boolean BiTgte_Blend::IsDone() const
1070 {
1071   return myDone;
1072 }
1073
1074 //=======================================================================
1075 //function : Shape
1076 //purpose  : 
1077 //=======================================================================
1078
1079 const TopoDS_Shape& BiTgte_Blend::Shape() const
1080 {
1081   return myResult;
1082 }
1083
1084
1085 //=======================================================================
1086 //function : NbSurfaces
1087 //purpose  : 
1088 //=======================================================================
1089
1090 Standard_Integer BiTgte_Blend::NbSurfaces() const
1091 {
1092   return myCenters.Extent();
1093 }
1094
1095
1096 //=======================================================================
1097 //function : Surface
1098 //purpose  : 
1099 //=======================================================================
1100
1101 Handle(Geom_Surface) BiTgte_Blend::Surface(const Standard_Integer Index) const
1102 {
1103   return Surface(myCenters(Index));
1104 }
1105
1106 //=======================================================================
1107 //function : TopoDS_Face&
1108 //purpose  : 
1109 //=======================================================================
1110
1111 const TopoDS_Face& BiTgte_Blend::Face(const Standard_Integer Index) const
1112 {
1113   return Face(myCenters(Index));
1114 }
1115
1116
1117
1118 //=======================================================================
1119 //function : CenterLines
1120 //purpose  : 
1121 //=======================================================================
1122
1123 void BiTgte_Blend::CenterLines(TopTools_ListOfShape& LC) const
1124 {
1125   LC.Clear();
1126   Standard_Integer Nb = NbSurfaces();
1127   for ( Standard_Integer i = 1; i <= Nb; i++) 
1128     LC.Append(myCenters(i));
1129 }
1130
1131
1132 //=======================================================================
1133 //function : Surface
1134 //purpose  : 
1135 //=======================================================================
1136
1137 Handle(Geom_Surface) BiTgte_Blend::Surface(const TopoDS_Shape& CenterLine) 
1138 const
1139
1140   const TopoDS_Face& F = myMapSF(CenterLine).Face();
1141   return BRep_Tool::Surface(F);
1142 }
1143
1144 //=======================================================================
1145 //function : TopoDS_Face&
1146 //purpose  : 
1147 //=======================================================================
1148
1149 const TopoDS_Face& BiTgte_Blend::Face(const TopoDS_Shape& CenterLine) const
1150 {
1151   if ( !myMapSF.IsBound(CenterLine)) {
1152     Standard_DomainError::Raise("BiTgte_Blend::Face");
1153   }
1154
1155   return myMapSF(CenterLine).Face();
1156 }
1157
1158 //=======================================================================
1159 //function : ContactType
1160 //purpose  : 
1161 //=======================================================================
1162
1163 BiTgte_ContactType BiTgte_Blend::ContactType(const Standard_Integer Index)
1164      const
1165 {
1166   const TopoDS_Shape& S1 = SupportShape1(Index);
1167   const TopoDS_Shape& S2 = SupportShape2(Index);
1168
1169   TopAbs_ShapeEnum Type1 = S1.ShapeType();
1170   TopAbs_ShapeEnum Type2 = S2.ShapeType();
1171   
1172   if (Type2 < Type1) {
1173     TopAbs_ShapeEnum Dummy = Type1;
1174     Type1 = Type2;
1175     Type2 = Dummy;
1176   }
1177   BiTgte_ContactType Type = BiTgte_VertexVertex;
1178
1179   switch (Type1) {
1180     
1181   case TopAbs_VERTEX:
1182     switch (Type2) {
1183     case TopAbs_VERTEX: Type = BiTgte_VertexVertex; break;
1184     case TopAbs_EDGE:   Type = BiTgte_EdgeVertex;   break;
1185     case TopAbs_FACE:   Type = BiTgte_FaceVertex;   break;
1186     default:
1187       break;
1188     }
1189     
1190   case TopAbs_EDGE:
1191     switch (Type2) {
1192     case TopAbs_EDGE:   Type = BiTgte_EdgeEdge; break;
1193     case TopAbs_FACE:   Type = BiTgte_FaceEdge; break;
1194     default:
1195       break;
1196    }
1197     
1198   case TopAbs_FACE:
1199     switch (Type2) {
1200     case TopAbs_FACE:   Type = BiTgte_FaceEdge; break;
1201     default:
1202       break;
1203     }
1204   default:
1205     break;
1206   }
1207   
1208   return Type;
1209 }
1210
1211
1212
1213 //=======================================================================
1214 //function : SupportShape1
1215 //purpose  : 
1216 //=======================================================================
1217
1218 const TopoDS_Shape& BiTgte_Blend::SupportShape1(const Standard_Integer Index)
1219      const
1220 {
1221   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1222   
1223   const TopTools_ListOfShape& L = myAsDes->Ascendant(CurE);
1224     
1225   // --------------------------------------------------------------
1226   // F1 and F2 = 2 parallel faces intersecting at CurE.
1227   // --------------------------------------------------------------
1228   const TopoDS_Face& F1 = TopoDS::Face(L.First()); 
1229   const TopoDS_Shape& Or1 = myInitOffsetFace.ImageFrom(F1);
1230   return Or1;
1231 }
1232
1233
1234 //=======================================================================
1235 //function : SupportShape2
1236 //purpose  : 
1237 //=======================================================================
1238
1239 const TopoDS_Shape& BiTgte_Blend::SupportShape2(const Standard_Integer Index)
1240      const
1241 {
1242   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1243   
1244   const TopTools_ListOfShape& L = myAsDes->Ascendant(CurE);
1245     
1246   // --------------------------------------------------------------
1247   // F1 and F2 = 2 parallel faces intersecting at CurE.
1248   // --------------------------------------------------------------
1249   const TopoDS_Face& F2 = TopoDS::Face(L.Last()); 
1250   const TopoDS_Shape& Or2 = myInitOffsetFace.ImageFrom(F2);
1251   return Or2;
1252 }
1253
1254
1255 //=======================================================================
1256 //function : CurveOnShape1
1257 //purpose  : 
1258 //=======================================================================
1259
1260 Handle(Geom_Curve) BiTgte_Blend::CurveOnShape1
1261 (const Standard_Integer Index) const
1262 {
1263   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1264   const TopoDS_Shape& F = myMapSF(CurE).Face();
1265
1266   // somewhat brutal method based ONLY on the construction of the fillet:
1267   // the first edge of the tube is exactly the edge on Shape1.
1268
1269   TopExp_Explorer exp(F,TopAbs_EDGE);
1270   const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1271   Handle(Geom_Curve) C;
1272   if ( !BRep_Tool::Degenerated(E)) { 
1273     Standard_Real f,l;
1274     C = BRep_Tool::Curve(E,f,l);
1275     C = new Geom_TrimmedCurve(C,f,l);
1276   }
1277   return C;
1278 }
1279
1280
1281 //=======================================================================
1282 //function : CurveOnShape2
1283 //purpose  : 
1284 //=======================================================================
1285
1286 Handle(Geom_Curve) BiTgte_Blend::CurveOnShape2
1287 (const Standard_Integer Index) const
1288 {
1289   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1290   const TopoDS_Shape& F = myMapSF(CurE).Face();
1291
1292   // somewhat brutal method based ONLY on the construction of the fillet:
1293   // the first edge of the tube is exactly the edge on Shape2.
1294
1295   TopExp_Explorer exp(F,TopAbs_EDGE);
1296   exp.Next();
1297   const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1298   Handle(Geom_Curve) C;
1299   if ( !BRep_Tool::Degenerated(E)) { 
1300     Standard_Real f,l;
1301     C = BRep_Tool::Curve(E,f,l);
1302     C = new Geom_TrimmedCurve(C,f,l);
1303   }
1304   return C;
1305 }
1306
1307
1308 //=======================================================================
1309 //function : PCurveOnFace1
1310 //purpose  : 
1311 //=======================================================================
1312
1313 Handle(Geom2d_Curve) BiTgte_Blend::PCurveOnFace1
1314 (const Standard_Integer /*Index*/) const
1315 {
1316   Handle(Geom2d_Curve) C;
1317   return C;
1318 }
1319
1320
1321 //=======================================================================
1322 //function : PCurve1OnFillet
1323 //purpose  : 
1324 //=======================================================================
1325
1326 Handle(Geom2d_Curve) BiTgte_Blend::PCurve1OnFillet
1327 (const Standard_Integer /*Index*/) const
1328 {
1329   Handle(Geom2d_Curve) C;
1330   return C;
1331 }
1332
1333
1334 //=======================================================================
1335 //function : PCurveOnFace2
1336 //purpose  : 
1337 //=======================================================================
1338
1339 Handle(Geom2d_Curve) BiTgte_Blend::PCurveOnFace2
1340 (const Standard_Integer /*Index*/) const
1341 {
1342   Handle(Geom2d_Curve) C;
1343   return C;
1344 }
1345
1346
1347 //=======================================================================
1348 //function : Curve2OnFillet
1349 //purpose  : 
1350 //=======================================================================
1351
1352 Handle(Geom2d_Curve) BiTgte_Blend::PCurve2OnFillet
1353 (const Standard_Integer /*Index*/) const
1354 {
1355   Handle(Geom2d_Curve) C;
1356   return C;
1357 }
1358
1359
1360
1361 //=======================================================================
1362 //function : NbBranches
1363 //purpose  : 
1364 //=======================================================================
1365
1366 Standard_Integer BiTgte_Blend::NbBranches() 
1367 {
1368   if (myNbBranches != -1) return myNbBranches;
1369
1370   // else, compute the Branches.
1371   BRepTools_Quilt Glue;
1372   
1373   Standard_Integer NbFaces = myCenters.Extent();
1374
1375
1376   if (NbFaces == 0) return 0;
1377
1378
1379   Standard_Integer i;
1380   for ( i = 1; i <= NbFaces; i++) {
1381     const TopoDS_Shape& CenterLine = myCenters(i);
1382     Glue.Add(myMapSF(CenterLine).Face()); 
1383   }
1384
1385   const TopoDS_Shape Shells = Glue.Shells();
1386
1387
1388   // Reorder Map myCenters.
1389   // The method is brutal and unpolished, 
1390   // it is possible to refine it.
1391   myNbBranches = 0;
1392   TopTools_IndexedMapOfShape tmpMap;
1393
1394   TopExp_Explorer exp(Shells,TopAbs_SHELL);
1395   for (; exp.More(); exp.Next()) {
1396     myNbBranches++;
1397   }
1398
1399   myIndices = new TColStd_HArray1OfInteger(1,myNbBranches+1);
1400
1401   myIndices->SetValue(1,0);
1402   Standard_Integer Count = 0;
1403   Standard_Integer Index = 2;
1404   
1405
1406   exp.Init(Shells,TopAbs_SHELL);
1407   for (; exp.More(); exp.Next()) {
1408     // CurS = the current Shell.
1409     const TopoDS_Shape CurS = exp.Current();
1410
1411     TopExp_Explorer exp2(CurS, TopAbs_FACE);
1412     for (; exp2.More(); exp2.Next()) {
1413       // CurF = the current face of the current Shell.
1414       const TopoDS_Shape CurF = exp2.Current();
1415
1416       for ( i = 1; i <= NbFaces; i++) {
1417         const TopoDS_Shape& Center = myCenters(i);
1418         const TopoDS_Shape& Rakk   = myMapSF(Center).Face();
1419         // Rakk = the ith generated connection face
1420         if (CurF.IsEqual(Rakk)) {
1421           tmpMap.Add(Center);
1422           Count++;
1423           break;
1424         }
1425       }
1426     }
1427     myIndices->SetValue(Index, Count);
1428     Index++;
1429   }
1430   
1431   myCenters = tmpMap;
1432   return myNbBranches;
1433 }
1434
1435
1436 //=======================================================================
1437 //function : IndicesOfBranche
1438 //purpose  : 
1439 //=======================================================================
1440
1441 void BiTgte_Blend::IndicesOfBranche
1442 (const Standard_Integer  Index,
1443        Standard_Integer& From,
1444        Standard_Integer& To   ) const 
1445 {
1446   // Attention to the ranking in myIndices:
1447   // If the branches are  1-4 5-9 10-12, it is ranked in myIndices:
1448   //                      0 4   9    12
1449   From = myIndices->Value(Index) + 1;
1450   To   = myIndices->Value(Index + 1);
1451 }
1452
1453
1454 //=======================================================================
1455 //function : ComputeCenters
1456 //purpose  : 
1457 //=======================================================================
1458
1459 void BiTgte_Blend::ComputeCenters() 
1460 {
1461   // ------------
1462   // Preanalyze.
1463   // ------------
1464   Standard_Real TolAngle = 2*ASin(myTol/Abs(myRadius*0.5));
1465   myAnalyse.Perform(myShape,TolAngle);
1466
1467   // ------------------------------------------
1468   // calculate faces touched by caps
1469   // ------------------------------------------
1470   TopTools_MapOfShape TouchedByCork;
1471   Touched(myAnalyse, myStopFaces, myShape, TouchedByCork);
1472
1473   // -----------------------
1474   // init of the intersector
1475   // -----------------------
1476   TopAbs_State       Side = TopAbs_IN;
1477   if (myRadius < 0.) Side = TopAbs_OUT;
1478   BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
1479
1480   BiTgte_DataMapOfShapeBox         MapSBox;
1481   TopTools_MapOfShape              Done;
1482   //TopTools_MapIteratorOfMapOfShape it;
1483
1484   BRep_Builder B;
1485   TopoDS_Compound Co; // to only know on which edges the tubes are made
1486   B.MakeCompound(Co);
1487
1488   // ----------------------------------------
1489   // Calculate Sections Face/Face + Propagation
1490   // ----------------------------------------
1491   Standard_Boolean JenRajoute = Standard_True;
1492   Standard_Integer i;
1493   
1494   while ( JenRajoute) {
1495     JenRajoute = Standard_False;
1496
1497     Standard_Boolean Fini = Standard_False;
1498
1499     TopTools_DataMapOfShapeShape EdgeTgt;
1500     
1501     while ( !Fini) {
1502
1503       // -------------------------------------------------
1504       // locate in myFaces the Faces connected to myEdges.
1505       // -------------------------------------------------
1506       Fini = Standard_True;
1507       //for (it.Initialize(myEdges); it.More(); it.Next()) {
1508       for (i = 1; i <= myEdges.Extent(); i++) {
1509         const TopoDS_Edge& E = TopoDS::Edge(myEdges(i));
1510         if (BRep_Tool::Degenerated(E)) continue;
1511
1512         const TopTools_ListOfShape& L = myAncestors.FindFromKey(E);
1513         if ( L.Extent() == 1) {
1514           // So this is a free border onwhich the ball should roll.
1515           myFaces.Add(E);
1516           
1517           // set in myStopFaces to not propagate the tube on free border.
1518           myStopFaces.Add(E);
1519         }
1520         else {
1521           TopTools_ListIteratorOfListOfShape itl;
1522           for (itl.Initialize(L); itl.More(); itl.Next()) {
1523             const TopoDS_Shape& Sh = itl.Value();
1524             if ( !myStopFaces.Contains(Sh)) myFaces.Add(itl.Value());
1525           }
1526         }
1527       }
1528       myEdges.Clear();
1529       
1530       // --------------------------------------------
1531       // Construction of Offsets of all faces.
1532       // --------------------------------------------
1533       //for (it.Initialize(myFaces); it.More(); it.Next()) {
1534       for (i = 1; i <= myFaces.Extent(); i++) {
1535         const TopoDS_Shape& AS = myFaces(i);
1536         if ( myMapSF.IsBound(AS)) continue;
1537
1538         BRepOffset_Offset OF1;
1539         TopoDS_Face BigF;
1540
1541         if (AS.ShapeType() == TopAbs_FACE) {
1542           const TopoDS_Face& F = TopoDS::Face(myFaces(i));
1543           if ( TouchedByCork.Contains(F)) {
1544             BRepOffset_Tool::EnLargeFace(F,BigF,Standard_True);
1545             OF1.Init(BigF,myRadius,EdgeTgt);
1546           }
1547           else {
1548             OF1.Init(F,myRadius,EdgeTgt);
1549           }
1550         }
1551         else { // So this is a Free Border edge on which the ball rolls.
1552           OF1.Init(TopoDS::Edge(AS),myRadius);
1553         }
1554
1555         // ------------------------------------
1556         // Increment the map of created tangents
1557         // ------------------------------------
1558         TopTools_ListOfShape Let;
1559         if ( AS.ShapeType() == TopAbs_FACE) { 
1560           myAnalyse.Edges(TopoDS::Face(AS),BRepOffset_Tangent,Let);
1561         }
1562         TopTools_ListIteratorOfListOfShape itlet(Let);
1563     
1564         for ( ; itlet.More(); itlet.Next()) {
1565           const TopoDS_Edge& Cur = TopoDS::Edge(itlet.Value());
1566           if ( !EdgeTgt.IsBound(Cur)) {
1567             TopoDS_Shape aLocalShape = OF1.Generated(Cur);
1568             const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1569 //          const TopoDS_Edge& OTE = TopoDS::Edge(OF1.Generated(Cur));
1570             EdgeTgt.Bind(Cur,OF1.Generated(Cur));
1571             TopoDS_Vertex V1,V2,OV1,OV2;
1572             TopExp::Vertices (Cur,V1,V2);
1573             TopExp::Vertices (OTE,OV1,OV2);      
1574             TopTools_ListOfShape LE;
1575             if (!EdgeTgt.IsBound(V1)) {
1576               myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
1577               const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V1);
1578               if (LE.Extent() == LA.Extent())
1579                 EdgeTgt.Bind(V1,OV1);
1580             }
1581             if (!EdgeTgt.IsBound(V2)) {
1582               LE.Clear();
1583               myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
1584               const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V2);
1585               if (LE.Extent() == LA.Extent())
1586                 EdgeTgt.Bind(V2,OV2);
1587             }
1588           }
1589         }
1590         // end of map created tangent
1591
1592         if (OF1.Status() == BRepOffset_Reversed ||
1593             OF1.Status() == BRepOffset_Degenerated ) continue;
1594
1595         const TopoDS_Face& F1 = OF1.Face();
1596
1597         // increment S D
1598         myInitOffsetFace.SetRoot(AS);
1599         myInitOffsetFace.Bind(AS,F1);
1600
1601         Bnd_Box Box1;
1602         BRepBndLib::Add(F1,Box1);
1603         MapSBox.Bind(F1,Box1);
1604
1605         // ---------------------------------------------
1606         // intersection with all already created faces.
1607         // ---------------------------------------------
1608         Fini = !Intersect(AS,F1,MapSBox,OF1,Inter);
1609
1610         if (AS.ShapeType() == TopAbs_FACE) B.Add(Co,AS);
1611
1612         myMapSF.Bind(AS, OF1);
1613
1614       }
1615     } // end of : while ( !Fini)
1616
1617
1618     //--------------------------------------------------------
1619     // so the offsets were created and intersected.
1620     // now the tubes are constructed.
1621     //--------------------------------------------------------
1622     // Construction of tubes on edge.
1623     //--------------------------------------------------------
1624     BRepOffset_Type    OT = BRepOffset_Convex;
1625     if (myRadius < 0.) OT = BRepOffset_Concave; 
1626     
1627     TopTools_IndexedDataMapOfShapeListOfShape Map;
1628     TopExp::MapShapesAndAncestors(Co,TopAbs_EDGE,TopAbs_FACE,Map);
1629     TopExp::MapShapesAndAncestors(Co,TopAbs_VERTEX,TopAbs_EDGE,Map);
1630     
1631     TopExp_Explorer exp(Co,TopAbs_EDGE);
1632     for ( ; exp.More(); exp.Next()) {
1633       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1634       if ( myMapSF.IsBound(E)) continue;
1635       
1636       const TopTools_ListOfShape& Anc = Map.FindFromKey(E);
1637       if (Anc.Extent() == 2) {
1638         const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1639         if (!L.IsEmpty() && L.First().Type() == OT) {
1640           TopoDS_Shape aLocalShape = myMapSF(Anc.First()).Generated(E);
1641           TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1642           aLocalShape = myMapSF(Anc.Last()) .Generated(E);
1643           TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShape);
1644 //        TopoDS_Edge EOn1 = TopoDS::Edge(myMapSF(Anc.First()).Generated(E));
1645 //        TopoDS_Edge EOn2 = TopoDS::Edge(myMapSF(Anc.Last()) .Generated(E));
1646           // find if exits tangent edges in the original shape
1647           TopoDS_Edge E1f, E1l;
1648           TopoDS_Vertex V1f, V1l;
1649           TopExp::Vertices(E,V1f,V1l);
1650           TopTools_ListOfShape TangE;
1651           myAnalyse.TangentEdges(E,V1f,TangE);
1652           // find if the pipe on the tangent edges are soon created.
1653           TopTools_ListIteratorOfListOfShape itl(TangE);
1654           Standard_Boolean Find = Standard_False;
1655           for ( ; itl.More() && !Find; itl.Next()) {
1656             if ( myMapSF.IsBound(itl.Value())) {
1657               TopoDS_Shape aLocalShape = myMapSF(itl.Value()).Generated(V1f);
1658               E1f  = TopoDS::Edge(aLocalShape);
1659 //            E1f  = TopoDS::Edge(myMapSF(itl.Value()).Generated(V1f));
1660               Find = Standard_True;
1661             }
1662           }
1663           TangE.Clear();
1664           myAnalyse.TangentEdges(E,V1l,TangE);
1665           // find if the pipe on the tangent edges are soon created.
1666           itl.Initialize(TangE);
1667           Find = Standard_False;
1668           for ( ; itl.More() && !Find; itl.Next()) {
1669             if ( myMapSF.IsBound(itl.Value())) {
1670               TopoDS_Shape aLocalShape = myMapSF(itl.Value()).Generated(V1l);
1671               E1l  = TopoDS::Edge(aLocalShape);
1672 //            E1l  = TopoDS::Edge(myMapSF(itl.Value()).Generated(V1l));
1673               Find = Standard_True;
1674             }
1675           }
1676           BRepOffset_Offset OF1 (E,EOn1,EOn2,myRadius,E1f, E1l);
1677           const TopoDS_Face& F1 = OF1.Face();
1678
1679           // maj S D
1680           myInitOffsetFace.SetRoot(E);
1681           myInitOffsetFace.Bind(E,F1);
1682
1683           Bnd_Box Box1;
1684           BRepBndLib::Add(F1,Box1);
1685           MapSBox.Bind(F1,Box1);
1686
1687           // ---------------------------------------------
1688           // intersection with all already created faces.
1689           // ---------------------------------------------
1690           Standard_Boolean IsOnRest = Intersect(E,F1,MapSBox,OF1,Inter);
1691           JenRajoute = JenRajoute || IsOnRest;
1692
1693           myMapSF.Bind(E,OF1);
1694         }
1695       }
1696     }
1697     
1698   } // end while JenRajoute
1699   
1700
1701   myEdges.Clear();
1702   myEdges = Inter.NewEdges();
1703
1704   // -------------------------------------------------------------------
1705   // now it is necessary to limit edges on the neighbors (otherwise one 
1706   // will go too far and will not be able to construct faces).
1707   // -------------------------------------------------------------------
1708
1709   // Proceed with MakeLoops 
1710
1711   BRepOffset_Type    OT = BRepOffset_Concave;
1712   if (myRadius < 0.) OT = BRepOffset_Convex; 
1713    
1714   TopTools_ListOfShape LOF;
1715   //it.Initialize(myFaces);
1716   for (i = 1; i <= myFaces.Extent(); i++) {
1717     const TopoDS_Shape& CurS  = myFaces(i);
1718
1719     // tube on free border, it is undesirable.
1720     if ( myStopFaces.Contains(CurS)) continue;
1721
1722     if ( !myMapSF.IsBound(CurS)) continue; // inverted or degenerated
1723
1724     const TopoDS_Face& CurOF = myMapSF(CurS).Face();
1725     LOF.Append(CurOF);
1726
1727     if (CurS.ShapeType() == TopAbs_FACE) {
1728       const TopoDS_Face& CurF = TopoDS::Face(CurS);
1729       TopExp_Explorer expe(CurF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1730       for (; expe.More(); expe.Next()) {
1731         // --------------------------------------------------------------
1732         // set in myAsDes the edges generated by limitations of the 
1733         // initial square if the type is correct (The edges that will 
1734         // disappear are not set)
1735         // --------------------------------------------------------------
1736         const TopoDS_Edge& CurE = TopoDS::Edge(expe.Current());
1737         const BRepOffset_ListOfInterval& L = myAnalyse.Type(CurE);
1738         if (!L.IsEmpty() && L.First().Type() != OT) {
1739           // a priori doe s not disappear, so it is set
1740           TopoDS_Shape aLocalShape = myMapSF(CurF).Generated(CurE);
1741           const TopoDS_Edge& CurOE = TopoDS::Edge(aLocalShape);
1742 //        const TopoDS_Edge& CurOE = 
1743 //          TopoDS::Edge(myMapSF(CurF).Generated(CurE));
1744           myAsDes->Add(CurOF,CurOE.Oriented(CurE.Orientation()));
1745         }
1746         else {
1747           const TopTools_ListOfShape& Lanc = myAnalyse.Ancestors(CurE);
1748           if (   !myFaces    .Contains(Lanc.First()) 
1749               || !myFaces    .Contains(Lanc.Last ())
1750               ||  myStopFaces.Contains(Lanc.First()) 
1751               ||  myStopFaces.Contains(Lanc.Last ())) {
1752             TopoDS_Shape aLocalShape = myMapSF(CurF).Generated(CurE);
1753             const TopoDS_Edge& CurOE = TopoDS::Edge(aLocalShape);
1754 //          const TopoDS_Edge& CurOE = 
1755 //            TopoDS::Edge(myMapSF(CurF).Generated(CurE));
1756             myAsDes->Add(CurOF,CurOE.Oriented(CurE.Orientation()));
1757           }
1758         }
1759       }
1760       BRepOffset_Inter2d::Compute(myAsDes,
1761                                   CurOF,
1762                                   myEdges,
1763                                   myTol);
1764     }
1765   }
1766
1767   // ----------------------------------------------------------------
1768   // It is also required to make 2D intersections with generated tubes
1769   // (Useful for unwinding)
1770   // ----------------------------------------------------------------
1771   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(myMapSF);
1772   for ( ; It.More(); It.Next()) {
1773     const TopoDS_Shape& CurS = It.Key();
1774     if ( CurS.ShapeType() == TopAbs_FACE) continue;
1775
1776     const TopoDS_Face& CurOF = It.Value().Face();
1777
1778     // no unwinding by tubes on free border.
1779     if ( myStopFaces.Contains(CurS)) continue;
1780
1781     LOF.Append(CurOF);
1782
1783     // --------------------------------------------------------------
1784     // set in myAsDes the edge restrictions of the square
1785     // --------------------------------------------------------------
1786     TopExp_Explorer expe(CurOF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1787     for (; expe.More(); expe.Next()) {
1788       const TopoDS_Edge& CurOE = TopoDS::Edge(expe.Current());
1789       myAsDes->Add(CurOF,CurOE);
1790     }
1791
1792     BRepOffset_Inter2d::Compute(myAsDes,
1793                                 CurOF,
1794                                 myEdges,
1795                                 myTol);
1796   }
1797   // ------------
1798   // unwinding 
1799   // ------------
1800   BRepOffset_MakeLoops MakeLoops;
1801   MakeLoops.Build( LOF, myAsDes, myImageOffset );
1802
1803   // ------------------------------------------------------------
1804   // It is possible to unwind edges at least one ancestor which of 
1805   // is a face of the initial shape, so:
1806   // the edges generated by intersection tube-tube are missing
1807   // ------------------------------------------------------------
1808
1809   // --------------------------------------------------------------
1810   // Currently set the unwinded surfaces in <myResult>
1811   // --------------------------------------------------------------
1812   B.MakeCompound(TopoDS::Compound(myResult));
1813   TopTools_ListIteratorOfListOfShape itLOF(LOF);
1814   for ( ; itLOF.More(); itLOF.Next()) {
1815     const TopoDS_Shape& CurLOF = itLOF.Value();
1816
1817     if ( !myImageOffset.HasImage(CurLOF)) 
1818       continue;
1819     
1820     TopTools_ListOfShape Lim;
1821     myImageOffset.LastImage(CurLOF,Lim);
1822     TopTools_ListIteratorOfListOfShape itLim(Lim);
1823     for ( ;itLim.More(); itLim.Next()) {
1824       // If a face is its own image, it is not set
1825       const TopoDS_Shape& CurLIM = itLim.Value();
1826       if (CurLIM.IsSame(CurLOF)) break;
1827
1828       B.Add(myResult,CurLIM);
1829     }
1830   }
1831
1832 #ifdef BITGTE_DEB
1833   if ( myResult.IsNull()) {
1834     cout << " No Lines of Generated Centers" << endl;
1835   }
1836 #ifdef DRAW
1837   else {
1838     if (Affich) DBRep::Set("Unwind",myResult);
1839   }
1840 #endif
1841 #endif
1842 }
1843
1844
1845 //=======================================================================
1846 //function : ComputeSurfaces
1847 //purpose  : 
1848 //=======================================================================
1849
1850 void BiTgte_Blend::ComputeSurfaces()
1851 {
1852   // set in myFaces, the faces actually implied in the connection
1853   myFaces.Clear();
1854
1855   // construct
1856   // 1 - Tubes (True Fillets)
1857   // 2 - Spheres.
1858
1859 #ifdef DRAW
1860   Standard_Integer nbc = 1;
1861 #endif
1862
1863   TopTools_ListOfShape Empty;
1864   TopTools_DataMapOfShapeListOfShape EmptyMap;
1865
1866   Handle(Geom_Surface) GS1, GS2;
1867   Handle(Geom_Curve)   GC1, GC2;
1868
1869   Standard_Real TolAngle = 2*ASin(myTol/Abs(myRadius*0.5));
1870   BRepOffset_Analyse CenterAnalyse(myResult,TolAngle);
1871
1872   // -----------------------------------------------------
1873   // Construction of tubes in myResult
1874   // -----------------------------------------------------
1875   BRep_Builder B;
1876   B.MakeCompound(TopoDS::Compound(myResult));
1877
1878   // --------------------------------------------------------------------
1879   // Dummy: for construction of spheres:
1880   // Set in Co the center line, then it there are at least 3
1881   // center lines sharing the same vertex, Sphere on this vertex.
1882   // --------------------------------------------------------------------
1883   TopoDS_Compound Co; 
1884   B.MakeCompound(Co);
1885
1886   // --------------------------------------------------------------------
1887   // Iteration on the edges lines of center
1888   // and their valid valid part is taken after cut and tube construction.
1889   // --------------------------------------------------------------------
1890
1891   //TopTools_MapIteratorOfMapOfShape ic(myEdges);
1892   Standard_Integer i;
1893   for (i = 1; i <= myEdges.Extent(); i++) {
1894     const TopoDS_Edge& CurE = TopoDS::Edge(myEdges(i));
1895
1896     const TopTools_ListOfShape& L = myAsDes->Ascendant(CurE);
1897     if ( L.Extent() != 2) continue;
1898     
1899     // --------------------------------------------------------------
1900     // F1 and F2 = 2 parallel faces intersecting in CurE.
1901     // --------------------------------------------------------------
1902     const TopoDS_Face& F1 = TopoDS::Face(L.First()); 
1903     const TopoDS_Face& F2 = TopoDS::Face(L.Last());
1904
1905     // -----------------------------------------------------
1906     // find the orientation of edges of intersection
1907     // in the initial faces.
1908     // -----------------------------------------------------
1909     const TopTools_ListOfShape& LD1 = myAsDes->Descendant(F1);
1910     const TopTools_ListOfShape& LD2 = myAsDes->Descendant(F2);
1911
1912     TopAbs_Orientation Orien1 = Orientation(CurE, F1, LD1);
1913     TopAbs_Orientation Orien2 = Orientation(CurE, F2, LD2);
1914     
1915     // ---------------------------------------------------------
1916     // Or1 and Or2 : the shapes generators of parallel faces 
1917     // ---------------------------------------------------------
1918     const TopoDS_Shape& Or1 = myInitOffsetFace.ImageFrom(F1);
1919     const TopoDS_Shape& Or2 = myInitOffsetFace.ImageFrom(F2);
1920
1921     myFaces.Add(Or1);
1922     myFaces.Add(Or2);
1923
1924     TopoDS_Edge     OE1, OE2;
1925     TopoDS_Face     OF1, OF2;
1926     TopLoc_Location Loc;
1927     Standard_Real   f1,l1,f2,l2;
1928     
1929     Standard_Boolean OF1isEdge = Standard_False;
1930     
1931     if ( Or1.ShapeType() == TopAbs_EDGE) {
1932       OF1isEdge = Standard_True;
1933       OE1 = TopoDS::Edge(Or1);
1934       GC1 = BRep_Tool::Curve(OE1,Loc,f1,l1);
1935       GC1 = 
1936         Handle(Geom_Curve)::DownCast(GC1->Transformed(Loc.Transformation()));
1937     }
1938     else if ( Or1.ShapeType() == TopAbs_FACE) {
1939       OF1 = TopoDS::Face(Or1);
1940       GS1 = BRep_Tool::Surface(OF1);
1941     }
1942
1943     // ----------------------------------------------------------------
1944     // If a vertex is used in contact, currently nothing is done  
1945     // and the vertexes are not managed (Intersections with sphere);
1946     // ----------------------------------------------------------------
1947     if ( OF1.IsNull() && OE1.IsNull()) continue;
1948     
1949     Standard_Boolean OF2isEdge = Standard_False;
1950     
1951     if ( Or2.ShapeType() == TopAbs_EDGE) {
1952       OF2isEdge = Standard_True;
1953       OE2 = TopoDS::Edge(Or2);
1954       GC2 = BRep_Tool::Curve(OE2,Loc,f2,l2);
1955       GC2 = 
1956         Handle(Geom_Curve)::
1957           DownCast(GC2->Transformed(Loc.Transformation()));
1958     }
1959     else if ( Or2.ShapeType() == TopAbs_FACE) {
1960       OF2 = TopoDS::Face(Or2);
1961       GS2 = BRep_Tool::Surface(OF2);
1962     }
1963     // ----------------------------------------------------------------
1964     // If a vertex is used in contact, currently nothing is done  
1965     // and the vertexes are not managed (Intersections with sphere);
1966     // ----------------------------------------------------------------
1967     if ( OF2.IsNull() && OE2.IsNull()) continue;
1968
1969
1970     TopTools_ListOfShape CurL;
1971
1972     if ( !myImageOffset.HasImage(CurE)) {// the tubes are not unwinded
1973       if ( OF1isEdge && OF2isEdge) {     // if I don't have the image, possibly
1974         CurL.Append(CurE);               // I'm on intersection tube-tube
1975       }                                  // See comment on the call to 
1976       else                               // MakeLoops
1977         continue;
1978     }
1979     else {
1980       myImageOffset.LastImage(CurE,CurL);
1981     }
1982
1983     // ---------------------------------------------------------------
1984     // CurL = List of edges descending from CurE ( = Cuts of CurE)
1985     // ---------------------------------------------------------------
1986     TopTools_ListIteratorOfListOfShape itl(CurL);
1987     for ( ; itl.More(); itl.Next()) {
1988       const TopoDS_Edge& CurCutE = TopoDS::Edge(itl.Value());
1989       
1990       Handle(Geom2d_Curve) PC1 = 
1991         BRep_Tool::CurveOnSurface(CurCutE,F1,f1,l1);
1992       Handle(Geom2d_Curve) PC2 = 
1993         BRep_Tool::CurveOnSurface(CurCutE,F2,f2,l2);
1994       if ( PC1.IsNull() || PC2.IsNull()) {
1995 #ifdef BITGTE_DEB
1996         cout << "No PCurves on Intersections : No tubes constructed";
1997         cout << endl;
1998 #endif  
1999         continue;
2000       }
2001
2002       TopoDS_Edge   E1f, E1l;
2003       TopoDS_Vertex V1f, V1l;
2004       TopoDS_Vertex VfOnE1,VlOnE1,VfOnE2,VlOnE2;
2005       TopTools_ListOfShape TangE;
2006       TopTools_MapOfShape MapOnV1f, MapOnV1l;
2007
2008       TopExp::Vertices(CurCutE,V1f,V1l);
2009
2010       // find if the pipe on the tangent edges are soon created.
2011       // edges generated by V1f and V1l + Maj MapOnV1f/l
2012       E1f = FindCreatedEdge(V1f,CurCutE,myMapSF,MapOnV1f,
2013                             CenterAnalyse,myRadius,myTol);
2014
2015       E1l = FindCreatedEdge(V1l,CurCutE,myMapSF,MapOnV1l,
2016                             CenterAnalyse,myRadius,myTol);
2017       
2018       TopoDS_Edge E1, E2;
2019       if ( OF1isEdge) {
2020         BiTgte_CurveOnEdge ConE(CurCutE, OE1);
2021         Handle(Geom_Curve) C = MakeCurve(ConE);
2022         gp_Pnt P1 = C->Value(C->FirstParameter());
2023         gp_Pnt P2 = C->Value(C->LastParameter());
2024         VfOnE1 = FindVertex(P1,MapOnV1f,myTol);
2025         if ( VfOnE1.IsNull())
2026           VfOnE1 = FindVertex(P1,MapOnV1l,myTol);
2027         VlOnE1 = FindVertex(P2,MapOnV1l,myTol);
2028         if ( VlOnE1.IsNull()) 
2029           VlOnE1 = FindVertex(P2,MapOnV1f,myTol);
2030         if ( P1.SquareDistance(P2) < myTol*myTol) {
2031           //BRepOffset_Offset manages degenerated KPart 
2032           //It is REQUIRED that C should be a circle with ZERO radius
2033           E1 = MakeDegeneratedEdge(C,VfOnE1);
2034         }
2035         else {
2036           E1 = BRepLib_MakeEdge(C,VfOnE1,VlOnE1);
2037         }
2038       }
2039       else {
2040         gp_Pnt2d P2d;
2041         P2d = PC1->Value(f1);
2042         gp_Pnt P1 = GS1->Value(P2d.X(),P2d.Y());
2043         P2d = PC1->Value(l1);
2044         gp_Pnt P2 = GS1->Value(P2d.X(),P2d.Y());
2045         VfOnE1 = FindVertex(P1,MapOnV1f,myTol);
2046         VlOnE1 = FindVertex(P2,MapOnV1l,myTol);
2047         BRepLib_MakeEdge MKE(PC1,GS1,VfOnE1,VlOnE1,f1,l1);
2048         if (MKE.IsDone()) 
2049           E1 = MKE.Edge();
2050         else  {
2051           cout << "Edge Not Done" << endl;
2052           E1 = MKE.Edge();
2053         }
2054           
2055         KPartCurve3d(E1,PC1,GS1);
2056       }
2057
2058       if ( OF2isEdge) {
2059         BiTgte_CurveOnEdge ConE(CurCutE, OE2);
2060         Handle(Geom_Curve) C = MakeCurve(ConE);
2061         gp_Pnt P1 = C->Value(C->FirstParameter());
2062         gp_Pnt P2 = C->Value(C->LastParameter());
2063         VfOnE2 = FindVertex(P1,MapOnV1f,myTol);
2064         if ( VfOnE2.IsNull()) 
2065           VfOnE2 = FindVertex(P1,MapOnV1l,myTol);
2066         VlOnE2 = FindVertex(P2,MapOnV1l,myTol);
2067         if ( VlOnE2.IsNull())
2068           VlOnE2 = FindVertex(P2,MapOnV1f,myTol);
2069         if ( P1.SquareDistance(P2) < myTol*myTol) {
2070           //BRepOffset_Offset manages degenerated KParts
2071           //It is REQUIRED that C should be a circle with ZERO radius
2072           E2 = MakeDegeneratedEdge(C,VfOnE2);
2073         }
2074         else {
2075           E2 = BRepLib_MakeEdge(C,VfOnE2,VlOnE2);
2076         }
2077       }
2078       else {
2079         gp_Pnt2d P2d;
2080         P2d = PC2->Value(f2);
2081         gp_Pnt P1 = GS2->Value(P2d.X(),P2d.Y());
2082         P2d = PC2->Value(l2);
2083         gp_Pnt P2 = GS2->Value(P2d.X(),P2d.Y());
2084         VfOnE2 = FindVertex(P1,MapOnV1f,myTol);
2085         VlOnE2 = FindVertex(P2,MapOnV1l,myTol);
2086         BRepLib_MakeEdge MKE(PC2,GS2,VfOnE2,VlOnE2,f2,l2);
2087         if (MKE.IsDone()) 
2088           E2 = MKE.Edge();
2089         else {
2090           cout << "edge not Done" << endl;
2091           E2 = MKE.Edge();
2092         }
2093         KPartCurve3d(E2,PC2,GS2);
2094       }
2095       // Increment of the Map of Created if reconstruction of the Shape is required
2096       if ( myBuildShape) {
2097         myCreated.Bind(CurCutE,EmptyMap);
2098
2099         myCreated(CurCutE).Bind(Or1,Empty);
2100         myCreated(CurCutE)(Or1).Append(E1);
2101
2102         myCreated(CurCutE).Bind(Or2,Empty);
2103         myCreated(CurCutE)(Or2).Append(E2);
2104       }
2105
2106       // ----------------------------------------------------------
2107       // try to init E1f, E1l, if not found with Analysis.
2108       // Should happen only if the THEORETICALLY tangent edges 
2109       // are not actually tangent ( Cf: Approximation of lines 
2110       // of intersection that add noise.)
2111       // ----------------------------------------------------------
2112       TopoDS_Vertex V1,V2;
2113       if ( E1f.IsNull() && !VfOnE1.IsNull() && !VfOnE2.IsNull()) {
2114         TopTools_MapIteratorOfMapOfShape it(MapOnV1f);
2115         for ( ; it.More(); it.Next()) {
2116           const TopoDS_Edge& E = TopoDS::Edge(it.Key());
2117           if ( !E.IsNull()) {
2118             TopExp::Vertices(E,V1,V2);
2119             if ((V1.IsSame(VfOnE1) && V2.IsSame(VfOnE2)) ||
2120                 (V2.IsSame(VfOnE1) && V1.IsSame(VfOnE2))   ) {
2121               E1f = E;
2122               break;
2123             }
2124           }
2125         }
2126       }
2127       if ( E1l.IsNull() && !VlOnE1.IsNull() && !VlOnE2.IsNull()) {
2128         TopTools_MapIteratorOfMapOfShape it(MapOnV1l);
2129         for ( ; it.More(); it.Next()) {
2130           const TopoDS_Edge& E = TopoDS::Edge(it.Key());
2131           if ( !E.IsNull()) {
2132             TopExp::Vertices(E,V1,V2);
2133             if ((V1.IsSame(VlOnE1) && V2.IsSame(VlOnE2)) ||
2134                 (V2.IsSame(VlOnE1) && V1.IsSame(VlOnE2))   ) {
2135               E1l = E;
2136               break;
2137             }
2138           }
2139         }
2140       }
2141       
2142       E1.Orientation(Orien1);
2143       E2.Orientation(Orien2);
2144
2145       BRepOffset_Offset AnOffset(CurCutE,E1,E2,-myRadius,E1f,E1l,
2146                                  myNubs, myTol, GeomAbs_C2);
2147       myMapSF.Bind(CurCutE,AnOffset);
2148       myCenters.Add(CurCutE);
2149       B.Add(Co, CurCutE);
2150
2151       const TopoDS_Face& Tuyo = AnOffset.Face();
2152       B.Add(myResult,Tuyo);
2153
2154       if ( myBuildShape) {
2155         // method based ONLY on the construction of fillet:
2156         // the first edge of the tube is exactly on Shape1.
2157         GeomAPI_ProjectPointOnCurve Projector;
2158         TopExp_Explorer exp(Tuyo,TopAbs_EDGE);
2159         TopoDS_Vertex V1,V2;
2160         if (OF1isEdge) { // Update CutEdges.
2161           const TopoDS_Edge& EOnF1 = TopoDS::Edge(exp.Current());
2162           TopExp::Vertices(EOnF1,V1,V2);
2163
2164           gp_Pnt P1 = BRep_Tool::Pnt(V1);
2165           Projector.Init(P1,GC1);
2166           Standard_Real U1 = Projector.LowerDistanceParameter();
2167
2168           gp_Pnt P2 = BRep_Tool::Pnt(V2);
2169           Projector.Init(P2,GC1);
2170           Standard_Real U2 = Projector.LowerDistanceParameter();
2171
2172           TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
2173           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,TopoDS::Edge(Or1),myTol);
2174           aLocalShape = V2.Oriented(TopAbs_INTERNAL);
2175           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,TopoDS::Edge(Or1),myTol);
2176 //        B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),U1,
2177 //                       TopoDS::Edge(Or1),myTol);
2178 //        B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),U2,
2179 //                       TopoDS::Edge(Or1),myTol);
2180
2181           if (!myCutEdges.IsBound(Or1)) {
2182             TopTools_ListOfShape Dummy;
2183             myCutEdges.Bind(Or1,Dummy);
2184           }
2185           TopTools_ListOfShape& L1 = myCutEdges(Or1);
2186           L1.Append(V1); L1.Append(V2);
2187         }
2188         if (OF2isEdge) { // Update CutEdges.
2189           exp.Next();
2190           const TopoDS_Edge& EOnF2 = TopoDS::Edge(exp.Current());
2191           TopExp::Vertices(EOnF2,V1,V2);;
2192
2193           gp_Pnt P1 = BRep_Tool::Pnt(V1);
2194           Projector.Init(P1,GC2);
2195           Standard_Real U1 = Projector.LowerDistanceParameter();
2196
2197           gp_Pnt P2 = BRep_Tool::Pnt(V2);
2198           Projector.Init(P2,GC2);
2199           Standard_Real U2 = Projector.LowerDistanceParameter();
2200
2201           TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
2202           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,TopoDS::Edge(Or2),myTol);
2203           aLocalShape = V2.Oriented(TopAbs_INTERNAL);
2204           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,TopoDS::Edge(Or2),myTol);
2205 //        B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),U1,
2206 //                       TopoDS::Edge(Or2),myTol);
2207 //        B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),U2,
2208 //                       TopoDS::Edge(Or2),myTol);
2209
2210           if (!myCutEdges.IsBound(Or2)) {
2211             TopTools_ListOfShape Dummy;
2212             myCutEdges.Bind(Or2,Dummy);
2213           }
2214           TopTools_ListOfShape& L2 = myCutEdges(Or2);
2215           L2.Append(V1); L2.Append(V2);
2216         }
2217       }
2218
2219 #ifdef DRAW
2220       if ( Affich) {
2221         sprintf(name,"%s_%d","SURF",nbc);
2222         DBRep::Set(name,AnOffset.Face());
2223         nbc++;
2224       }
2225 #endif
2226     }
2227   }
2228
2229   // ---------------------------------------------------
2230   // Construction of spheres, 
2231   // if enough tubes arrive at the vertex
2232   // ---------------------------------------------------
2233   TopTools_IndexedDataMapOfShapeListOfShape Map;
2234   TopExp::MapShapesAndAncestors(Co,TopAbs_VERTEX,TopAbs_EDGE,Map);
2235
2236   for ( Standard_Integer i = 1; i <= Map.Extent(); i++) {
2237     const TopoDS_Vertex& V = TopoDS::Vertex(Map.FindKey(i));
2238     if ( Map(i).Extent() != 3) continue;
2239
2240     TopTools_ListOfShape LOE;
2241     TopTools_ListIteratorOfListOfShape it;
2242     
2243     for (it.Initialize(Map(i)) ; it.More(); it.Next()) {
2244       Standard_Boolean Reverse = Standard_True;
2245       if ( Reverse) 
2246         LOE.Append(myMapSF(it.Value()).Generated(V).Reversed());
2247       else 
2248         LOE.Append(myMapSF(it.Value()).Generated(V));
2249     }
2250     
2251     BRepOffset_Offset OFT(V,LOE,-myRadius,myNubs, myTol, GeomAbs_C2);
2252     myMapSF.Bind(V,OFT);
2253     myCenters.Add(V);
2254
2255     B.Add(myResult,OFT.Face());
2256
2257 #ifdef DRAW
2258     if (Affich) {
2259       sprintf(name,"%s_%d","SURF",nbc);
2260       DBRep::Set(name,OFT.Face());
2261       nbc++;
2262     }
2263 #endif
2264   }
2265 }
2266
2267
2268 //=======================================================================
2269 //function : ComputeShape
2270 //purpose  : 
2271 //=======================================================================
2272 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
2273
2274 void BiTgte_Blend::ComputeShape() 
2275 {
2276   // Find in the initial Shapel:
2277   //  - untouched Faces
2278   //  - generated tubes
2279   //  - the faces neighbors of tubes that sould be reconstucted preserving sharing.
2280
2281   // For Debug : Visualize edges of the initial shape that should be reconstructed.
2282 #ifdef DRAW
2283   if (Affich) {
2284     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myCutEdges);
2285     Standard_Integer NbEdges = 0;
2286     for ( ; itm.More(); itm.Next()) {
2287       const TopoDS_Edge&          E    = TopoDS::Edge(itm.Key());
2288       const TopTools_ListOfShape& VonE = itm.Value();
2289       TopTools_ListOfShape NewE;
2290       
2291       CutEdge(E,VonE,NewE);
2292       for (TopTools_ListIteratorOfListOfShape it(NewE); it.More(); it.Next()) {
2293         sprintf(name,"%s_%d","CUTE",++NbEdges);
2294         DBRep::Set(name,it.Value());
2295       }
2296     }
2297   }
2298 #endif
2299   // end debug
2300
2301   //
2302   // modify the tubes on edge for partition of edges.
2303   //
2304   Standard_Integer NbS = NbSurfaces();
2305   for (Standard_Integer i = 1; i <= NbS; i++) {
2306     const TopoDS_Shape& S1 = SupportShape1(i);
2307
2308     if ( S1.ShapeType() == TopAbs_EDGE) {
2309       const TopoDS_Edge& E1   = TopoDS::Edge(S1);
2310       // it is required to replace in F the cut edges of E1, that
2311       // represent CutE
2312       const TopTools_ListOfShape& VonE = myCutEdges(E1);
2313       TopTools_ListOfShape NewE;
2314       CutEdge(E1,VonE,NewE);
2315       
2316     }
2317   }
2318
2319
2320   TopTools_DataMapOfShapeShape Created;
2321
2322   TopTools_ListOfShape Empty;
2323   TopTools_DataMapOfShapeListOfShape EmptyMap;
2324   
2325   BRep_Builder B;
2326
2327 #ifdef DRAW
2328   Standard_Integer NbNT = 1;
2329 #endif
2330
2331   // Maj of the Map of created.
2332   // Update edges that do not change in the resulting shape 
2333   // i.e. invariant edges in the unwinding.
2334   TopExp_Explorer exp(myShape,TopAbs_FACE);
2335   // Standard_Integer nbe = 1;
2336   for ( ;exp.More(); exp.Next()) {
2337
2338     const TopoDS_Face& CurF = TopoDS::Face(exp.Current());
2339
2340     if ( !myFaces.Contains(CurF)) continue; // so the face is not touched
2341
2342     // so the faces are unwinded
2343     if ( !myMapSF.IsBound(CurF)) continue; // inverted or degenerated
2344     
2345     const BRepOffset_Offset& Offset = myMapSF(CurF);
2346     const TopoDS_Face& CurOF = myMapSF(CurF).Face();
2347     
2348     if ( !myImageOffset.HasImage(CurOF)) // face disappears in unwinding
2349       continue;
2350     
2351     TopExp_Explorer exp2(CurF,TopAbs_EDGE);
2352     for ( ;exp2.More(); exp2.Next()) {
2353       const TopoDS_Edge& CurE  = TopoDS::Edge(exp2.Current());
2354       TopoDS_Shape aLocalShape = Offset.Generated(CurE);
2355       const TopoDS_Edge& CurOE = TopoDS::Edge(aLocalShape);
2356 //      const TopoDS_Edge& CurOE = TopoDS::Edge(Offset.Generated(CurE));
2357
2358       if (!myImageOffset.HasImage(CurOE)) continue; 
2359       // CurOE disappears
2360
2361       const TopoDS_Edge& ImE = 
2362         TopoDS::Edge(myImageOffset.Image(CurOE).First());
2363       if (ImE.IsSame(CurOE)) {
2364         myCreated.Bind(CurOE,EmptyMap);      
2365         myCreated(CurOE).Bind(CurF,Empty);
2366         myCreated(CurOE)(CurF).Append(CurE);
2367       }
2368     }
2369   }
2370
2371   // The connected faces are already in myResult.
2372   // So it is necessary to add faces:
2373   //    - non-touched (so not in myFaces)
2374   //    - issuing from the unwinding (non degenerated, non inverted, non disappeared)
2375   exp.Init(myShape,TopAbs_FACE);
2376   for ( ;exp.More(); exp.Next()) {
2377
2378     const TopoDS_Face& CurF = TopoDS::Face(exp.Current());
2379
2380     if ( !myFaces.Contains(CurF)) { 
2381       // so the face is not touched
2382       B.Add(myResult,CurF);
2383     }
2384     else { // so the faces are unwindeds
2385
2386       if ( !myMapSF.IsBound(CurF)) continue; // inverted or degenerated
2387
2388       const TopoDS_Face& CurOF = myMapSF(CurF).Face();
2389       
2390       if ( !myImageOffset.HasImage(CurOF)) // face disappears in unwinding
2391         continue;
2392       
2393       // List of faces generated by a face in the unwinding
2394       TopTools_ListOfShape Lim;
2395       myImageOffset.LastImage(CurOF,Lim);
2396       TopTools_ListIteratorOfListOfShape itLim(Lim);
2397       for ( ;itLim.More(); itLim.Next()) {
2398         // DeboucFace = offset Face unwinded in "Debouc".
2399         const TopoDS_Face& DeboucFace = TopoDS::Face(itLim.Value());
2400
2401         TopLoc_Location L;
2402         Handle(Geom_Surface) S = BRep_Tool::Surface(CurF,L);
2403         
2404         TopoDS_Face NewF; B.MakeFace(NewF);
2405         B.UpdateFace(NewF,S,L,BRep_Tool::Tolerance(CurF));
2406         
2407         TopTools_DataMapOfShapeShape MapSS;
2408                  
2409         TopoDS_Shape aLocalShape = DeboucFace.Oriented(TopAbs_FORWARD);
2410         const TopoDS_Face& Face = TopoDS::Face(aLocalShape);
2411 //      const TopoDS_Face& Face = 
2412 //        TopoDS::Face(DeboucFace.Oriented(TopAbs_FORWARD));
2413         TopExp_Explorer exp2(Face, TopAbs_EDGE);
2414         for ( ; exp2.More(); exp2.Next()) {
2415           const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
2416           TopoDS_Vertex V1,V2,OV1,OV2;
2417           TopExp::Vertices(E ,V1 ,V2 );
2418           if (myCreated.IsBound(E)) {
2419             if (myCreated(E).IsBound(CurF)) {
2420               const TopoDS_Edge& OE = TopoDS::Edge(myCreated(E)(CurF).First());
2421               TopExp::Vertices(OE,OV1,OV2);
2422               if ( !myCreated.IsBound(V1)) myCreated.Bind(V1,EmptyMap);
2423               if ( !myCreated.IsBound(V2)) myCreated.Bind(V2,EmptyMap);
2424               if ( !myCreated(V1).IsBound(CurF))  {
2425                 myCreated(V1).Bind(CurF,Empty);
2426                 myCreated(V1)(CurF).Append(OV1);
2427               }
2428               if ( !myCreated(V2).IsBound(CurF))  {
2429                 myCreated(V2).Bind(CurF,Empty);
2430                 myCreated(V2)(CurF).Append(OV2);
2431               }
2432             }
2433           }
2434         }
2435
2436         TopExp_Explorer expw(Face, TopAbs_WIRE);
2437         for ( ; expw.More(); expw.Next()) {
2438           const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
2439           TopExp_Explorer expe(W.Oriented(TopAbs_FORWARD),
2440                                TopAbs_EDGE);
2441           TopoDS_Wire OW;
2442           B.MakeWire(OW);
2443           
2444           for ( ; expe.More(); expe.Next()) {
2445             const TopoDS_Edge& E = TopoDS::Edge(expe.Current());
2446             Standard_Real f,l;
2447             Handle(Geom2d_Curve) C2d = 
2448               BRep_Tool::CurveOnSurface(E,Face,f,l);
2449             TopoDS_Edge OE;
2450             if ( MapSS.IsBound(E)) { // this is an edge of cutting 
2451               OE = TopoDS::Edge(MapSS(E));
2452               TopoDS_Shape aLocalShape = E.Reversed();
2453               Handle(Geom2d_Curve) C2d_1 = 
2454                 BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShape),Face,f,l);
2455 //            Handle(Geom2d_Curve) C2d_1 = 
2456 //              BRep_Tool::CurveOnSurface(TopoDS::Edge(E.Reversed()),
2457 //                                        Face,f,l);
2458               if ( E.Orientation() == TopAbs_FORWARD)
2459                 B.UpdateEdge(OE,C2d,C2d_1,NewF,BRep_Tool::Tolerance(E));
2460               else
2461                 B.UpdateEdge(OE,C2d_1,C2d,NewF,BRep_Tool::Tolerance(E));
2462               B.Range(OE,f,l);
2463             }
2464             else {
2465               // Is there an image in the Map of Created ?
2466               if ( myCreated.IsBound(E)) {
2467                 if ( myCreated(E).IsBound(CurF)) {
2468                   OE = TopoDS::Edge(myCreated(E)(CurF).First());
2469                 }
2470               }
2471               else {
2472                 B.MakeEdge(OE);
2473                 TopoDS_Vertex V1,V2,OV1,OV2;
2474                 TopExp::Vertices(E,V1,V2);
2475                 if ( myCreated.IsBound(V1) && myCreated(V1).IsBound(CurF)) {
2476                   OV1 = TopoDS::Vertex(myCreated(V1)(CurF).First());
2477                 }
2478                 else {
2479                   B.MakeVertex(OV1);
2480                   gp_Pnt2d P2d = 
2481                     C2d->Value(BRep_Tool::Parameter(V1,E,Face));
2482                   gp_Pnt P;
2483                   S->D0(P2d.X(),P2d.Y(),P);
2484                   P.Transform(L.Transformation());
2485                   B.UpdateVertex(OV1,P,BRep_Tool::Tolerance(V1));
2486                   myCreated.Bind(V1,EmptyMap);
2487                   myCreated(V1).Bind(CurF,Empty);
2488                   myCreated(V1)(CurF).Append(OV1);
2489                 }
2490                 if ( myCreated.IsBound(V2) && myCreated(V2).IsBound(CurF)) {
2491                   OV2 = TopoDS::Vertex(myCreated(V2)(CurF).First());
2492                 }
2493                 else {
2494                   B.MakeVertex(OV2);
2495                   gp_Pnt2d P2d = 
2496                     C2d->Value(BRep_Tool::Parameter(V2,E,Face));
2497                   gp_Pnt P;
2498                   S->D0(P2d.X(),P2d.Y(),P);
2499                   P.Transform(L.Transformation());
2500                   B.UpdateVertex(OV2,P,BRep_Tool::Tolerance(V2));
2501                   myCreated.Bind(V2,EmptyMap);
2502                   myCreated(V2).Bind(CurF,Empty);
2503                   myCreated(V2)(CurF).Append(OV2);
2504                 }
2505                 B.Add(OE,OV1.Oriented(V1.Orientation()));
2506                 B.Add(OE,OV2.Oriented(V2.Orientation()));
2507               }
2508               B.UpdateEdge(OE,C2d,NewF,BRep_Tool::Tolerance(E));
2509               B.Range(OE,f,l);
2510 //            ComputeCurve3d(OE,C2d,TheSurf,L,BRep_Tool::Tolerance(E));
2511               MapSS.Bind(E,OE);
2512             }
2513             B.Add(OW, OE.Oriented(E.Orientation()));
2514           }
2515           B.Add(NewF, OW.Oriented(W.Orientation()));
2516         }
2517
2518         NewF.Orientation(DeboucFace.Orientation());
2519   
2520         BRepTools::Update(NewF);
2521         B.Add(myResult,NewF);
2522       }
2523     }
2524   }
2525
2526   // non-regarding the cause, there always remain greeb borders on this Shape, so it is sewn.
2527   Handle(BRepBuilderAPI_Sewing) Sew = new BRepBuilderAPI_Sewing(myTol);
2528   
2529   BRepLib::BuildCurves3d(myResult);
2530   
2531   exp.Init(myResult,TopAbs_FACE);
2532   for ( ;exp.More(); exp.Next())
2533     Sew->Add(exp.Current());
2534   
2535   Sew->Perform();
2536
2537   // SameParameter is done in case Sew does not do it (Detect that the edges
2538   // are not sameparameter but does nothing.)
2539   
2540   const TopoDS_Shape& SewedShape = Sew->SewedShape();
2541   if ( !SewedShape.IsNull()) {
2542     exp.Init(Sew->SewedShape(), TopAbs_EDGE);
2543     for (; exp.More(); exp.Next()) {
2544       const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
2545       BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
2546     }
2547     myResult = SewedShape;
2548   }
2549 }
2550
2551
2552 //=======================================================================
2553 //function : Intersect
2554 //purpose  : 
2555 //=======================================================================
2556
2557 Standard_Boolean BiTgte_Blend::Intersect
2558 (const TopoDS_Shape&             Init,
2559  const TopoDS_Face&              Face,
2560  const BiTgte_DataMapOfShapeBox& MapSBox,
2561  const BRepOffset_Offset&        OF1,
2562        BRepOffset_Inter3d&       Inter) 
2563 {
2564   Standard_Boolean JenRajoute = Standard_False;
2565
2566   const Bnd_Box& Box1 = MapSBox(Face);
2567
2568   // -----------------------------------------------
2569   // intersection with all already created faces.
2570   // -----------------------------------------------
2571   const TopoDS_Shape& InitShape1 = OF1.InitialShape();
2572   Standard_Boolean F1surBordLibre = 
2573     InitShape1.ShapeType() == TopAbs_EDGE &&
2574       myStopFaces.Contains(InitShape1);
2575
2576   TopTools_MapOfShape Done;
2577   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(myMapSF);
2578   for ( ; It.More(); It.Next()) {
2579     const BRepOffset_Offset& OF2 = It.Value();
2580     const TopoDS_Face&       F2  = OF2.Face();
2581     
2582     if (Box1.IsOut(MapSBox(F2))) continue;
2583     
2584     if ( Inter.IsDone(Face,F2)) continue;
2585     
2586     // 2 tubes created on free border are not intersected.
2587     const TopoDS_Shape& InitShape2 = OF2.InitialShape();
2588     Standard_Boolean F2surBordLibre = 
2589       InitShape2.ShapeType() == TopAbs_EDGE &&
2590         myStopFaces.Contains(InitShape2);
2591
2592 #ifdef BITGTE_DEB
2593     if ( F1surBordLibre && F2surBordLibre) {
2594       cout << "Rejection : 2 tubes on free border are not intersected";
2595       cout << endl;
2596     }
2597 #endif
2598
2599     if ( F1surBordLibre && F2surBordLibre) continue;
2600
2601     // -------------------------------------------------------
2602     // Tubes are not intersected with neighbor faces.
2603     // -------------------------------------------------------
2604     const TopoDS_Shape& ItKey = It.Key();
2605
2606     if ( Init.ShapeType() == TopAbs_EDGE) {
2607       if (ItKey.ShapeType() == TopAbs_FACE &&
2608           IsInFace(TopoDS::Edge(Init), TopoDS::Face(ItKey)))  continue;
2609     }
2610     
2611     Inter.FaceInter(Face,F2,myInitOffsetFace);
2612     
2613     // ------------------------------------------
2614     // an edge of F1 or F2 has been touched ?
2615     // if yes, add faces in myFaces
2616     //   ==> JenRajoute = True
2617     // ------------------------------------------
2618     TopTools_ListOfShape LInt;
2619     Done.Clear();
2620     if (myAsDes->HasCommonDescendant(Face,F2,LInt)) {
2621       TopTools_ListIteratorOfListOfShape  itl2;
2622       for (itl2.Initialize(LInt); itl2.More(); itl2.Next()) {
2623         const TopoDS_Edge& CurE = TopoDS::Edge(itl2.Value());
2624         TopoDS_Vertex V1,V2;
2625         TopoDS_Edge   E1,E2;
2626         TopExp::Vertices(CurE,V1,V2);
2627         
2628         if ( Done.Add(V1)) {
2629           Standard_Boolean IsOnR1 = IsOnRestriction(V1,CurE,Face,E1);
2630           Standard_Boolean IsOnR2 = IsOnRestriction(V1,CurE,F2,E2);
2631 #ifdef BITGTE_DEB
2632           if (IsOnR1 && IsOnR2) {
2633             cout << "Leave in the same tps on 2 faces, ";
2634             cout << "propagation only on free border";
2635             cout << endl;
2636           }
2637 #endif
2638           if ( IsOnR1 ) {
2639             if ( !myStopFaces.Contains(Init)) {
2640               Add(E1,myEdges,Init,OF1,myAnalyse,IsOnR1 && IsOnR2);
2641               JenRajoute = Standard_True;
2642             }
2643           }
2644           if ( IsOnR2) {
2645             if ( !myStopFaces.Contains(ItKey)) {
2646               Add(E2,myEdges, ItKey,OF2,myAnalyse,IsOnR1 && IsOnR2);
2647               JenRajoute = Standard_True;
2648             }
2649           }
2650         }
2651
2652         if ( Done.Add(V2)) {
2653           Standard_Boolean IsOnR1 = IsOnRestriction(V2,CurE,Face,E1);
2654           Standard_Boolean IsOnR2 = IsOnRestriction(V2,CurE,F2,E2);
2655
2656           // If IsOnR1 && IsOnR2,
2657           // Leave in the same tps on 2 faces, propagate only on 
2658           // free borders.
2659           // A priori, only facet is closed.
2660 #ifdef BITGTE_DEB
2661           if (IsOnR1 && IsOnR2) {
2662             cout << "Leave with the same tps on 2 faces, ";
2663             cout << "propagate only if the border is free";
2664             cout << endl;
2665           }
2666 #endif
2667           if ( IsOnR1) {
2668             if ( !myStopFaces.Contains(Init)) {
2669               Add(E1,myEdges,Init,OF1,myAnalyse,IsOnR1 && IsOnR2);
2670               JenRajoute = Standard_True;
2671             }
2672           }
2673           if ( IsOnR2) {
2674             if ( !myStopFaces.Contains(ItKey)) {
2675               Add(E2,myEdges,ItKey,OF2,myAnalyse,IsOnR1 && IsOnR2);
2676               JenRajoute = Standard_True;
2677             }
2678           }
2679         }
2680       }
2681     }
2682   }
2683
2684   return JenRajoute;
2685 }
2686
2687