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