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