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