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