1 // Created on: 1995-10-23
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 #include <BRepOffset_Tool.hxx>
18 
19 #include <Bnd_Box2d.hxx>
20 #include <BndLib_Add3dCurve.hxx>
21 #include <BOPAlgo_PaveFiller.hxx>
22 #include <BOPDS_DS.hxx>
23 #include <BOPTools_AlgoTools.hxx>
24 #include <BOPTools_AlgoTools2D.hxx>
25 #include <BRep_CurveRepresentation.hxx>
26 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
27 #include <BRep_TEdge.hxx>
28 #include <BRep_Tool.hxx>
29 #include <BRep_Builder.hxx>
30 #include <BRepAdaptor_Curve.hxx>
31 #include <BRepAdaptor_Curve2d.hxx>
32 #include <BRepAdaptor_Surface.hxx>
33 #include <BRepAlgo_AsDes.hxx>
34 #include <BRepAlgo_Image.hxx>
35 #include <BRepBndLib.hxx>
36 #include <BRepLib.hxx>
37 #include <BRepLib_MakeEdge.hxx>
38 #include <BRepLib_MakeFace.hxx>
39 #include <BRepLib_MakePolygon.hxx>
40 #include <BRepLib_MakeVertex.hxx>
41 #include <BRepOffset_Analyse.hxx>
42 #include <BRepOffset_Interval.hxx>
43 #include <BRepOffset_ListOfInterval.hxx>
44 #include <BRepTools.hxx>
45 #include <BRepTools_Modifier.hxx>
46 #include <BRepTools_TrsfModification.hxx>
47 #include <BRepTools_WireExplorer.hxx>
48 #include <BRepTopAdaptor_FClass2d.hxx>
49 #include <ElCLib.hxx>
50 #include <ElSLib.hxx>
51 #include <Extrema_ExtPC.hxx>
52 #include <Extrema_ExtPC2d.hxx>
53 #include <BRepExtrema_DistShapeShape.hxx>
54 #include <GCPnts_AbscissaPoint.hxx>
55 #include <GCPnts_QuasiUniformDeflection.hxx>
56 #include <GCPnts_UniformAbscissa.hxx>
57 #include <Geom2d_BezierCurve.hxx>
58 #include <Geom2d_BSplineCurve.hxx>
59 #include <Geom2d_Circle.hxx>
60 #include <Geom2d_Curve.hxx>
61 #include <Geom2d_Ellipse.hxx>
62 #include <Geom2d_Hyperbola.hxx>
63 #include <Geom2d_Line.hxx>
64 #include <Geom2d_Parabola.hxx>
65 #include <Geom2d_TrimmedCurve.hxx>
66 #include <Geom2dAdaptor_Curve.hxx>
67 #include <Geom2dConvert_ApproxCurve.hxx>
68 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
69 #include <Geom2dInt_GInter.hxx>
70 #include <Geom_BezierSurface.hxx>
71 #include <Geom_BSplineCurve.hxx>
72 #include <Geom_BSplineSurface.hxx>
73 #include <Geom_Conic.hxx>
74 #include <Geom_ConicalSurface.hxx>
75 #include <Geom_Curve.hxx>
76 #include <Geom_Line.hxx>
77 #include <Geom_OffsetSurface.hxx>
78 #include <Geom_Plane.hxx>
79 #include <Geom_RectangularTrimmedSurface.hxx>
80 #include <Geom_Surface.hxx>
81 #include <Geom_SurfaceOfLinearExtrusion.hxx>
82 #include <Geom_SurfaceOfRevolution.hxx>
83 #include <Geom_TrimmedCurve.hxx>
84 #include <GeomAdaptor_Surface.hxx>
85 #include <GeomAPI.hxx>
86 #include <GeomAPI_ExtremaCurveCurve.hxx>
87 #include <GeomAPI_ProjectPointOnCurve.hxx>
88 #include <GeomConvert_ApproxCurve.hxx>
89 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
90 #include <GeomInt_IntSS.hxx>
91 #include <GeomLib.hxx>
92 #include <GeomProjLib.hxx>
93 #include <gp.hxx>
94 #include <gp_Pnt.hxx>
95 #include <gp_Vec.hxx>
96 #include <IntRes2d_IntersectionPoint.hxx>
97 #include <IntRes2d_IntersectionSegment.hxx>
98 #include <IntTools_FaceFace.hxx>
99 #include <Precision.hxx>
100 #include <ProjLib_HProjectedCurve.hxx>
101 #include <ProjLib_ProjectedCurve.hxx>
102 #include <ShapeCustom_Curve2d.hxx>
103 #include <Standard_ConstructionError.hxx>
104 #include <TColgp_Array1OfPnt2d.hxx>
105 #include <TopAbs.hxx>
106 #include <TopExp.hxx>
107 #include <TopExp_Explorer.hxx>
108 #include <TopoDS.hxx>
109 #include <TopoDS_Compound.hxx>
110 #include <TopoDS_Edge.hxx>
111 #include <TopoDS_Face.hxx>
112 #include <TopoDS_Iterator.hxx>
113 #include <TopoDS_Shape.hxx>
114 #include <TopoDS_Vertex.hxx>
115 #include <TopoDS_Wire.hxx>
116 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
117 #include <TopTools_ListIteratorOfListOfShape.hxx>
118 #include <TopTools_SequenceOfShape.hxx>
119 
120 #include <stdio.h>
121 
122 // The constant defines the maximal value to enlarge surfaces.
123 // It is limited to 1.e+7. This limitation is justified by the
124 // floating point format. As we can have only 15
125 // valuable decimal numbers, then during intersection of surfaces with
126 // bounds of 1.e+8 the possible inaccuracy might appear already in seventh
127 // decimal place which will be more than Precision::Confusion value -
128 // 1.e-7, default tolerance value for the section curves.
129 // By decreasing the max enlarge value to 1.e+7 the inaccuracy will be
130 // shifted to eighth decimal place, i.e. the inaccuracy will be
131 // decreased to values less than 1.e-7.
132 const Standard_Real TheInfini = 1.e+7;
133 
134 //tma: for new boolean operation
135 #ifdef DRAW
136 #include <DBRep.hxx>
137 #include <Geom2d_Conic.hxx>
138 #include <Geom_BoundedCurve.hxx>
139 Standard_Boolean AffichInter  = Standard_False;
140 static Standard_Integer NbNewEdges  = 1;
141 static Standard_Integer NbFaces     = 1;
142 static Standard_Integer NbFOB       = 1;
143 static Standard_Integer NbFTE       = 1;
144 static Standard_Integer NbExtE      = 1;
145 #endif
146 
147 #ifdef OCCT_DEBUG
148 static Standard_Boolean AffichExtent = Standard_False;
149 #endif
150 
151 static
152   void PerformPlanes(const TopoDS_Face& theFace1,
153                      const TopoDS_Face& theFace2,
154                      const TopAbs_State theState,
155                      TopTools_ListOfShape& theL1,
156                      TopTools_ListOfShape& theL2);
157 
158 static void UpdateVertexTolerances(const TopoDS_Face& theFace);
159 
160 inline
161   Standard_Boolean IsInf(const Standard_Real theVal);
162 
163 //=======================================================================
164 //function : EdgeVertices
165 //purpose  :
166 //=======================================================================
167 
EdgeVertices(const TopoDS_Edge & E,TopoDS_Vertex & V1,TopoDS_Vertex & V2)168 void BRepOffset_Tool::EdgeVertices (const TopoDS_Edge&   E,
169 				    TopoDS_Vertex& V1,
170 				    TopoDS_Vertex& V2)
171 {
172   if (E.Orientation() == TopAbs_REVERSED) {
173     TopExp::Vertices(E,V2,V1);
174   }
175   else {
176     TopExp::Vertices(E,V1,V2);
177   }
178 }
179 
180 //=======================================================================
181 //function : FindPeriod
182 //purpose  :
183 //=======================================================================
184 
FindPeriod(const TopoDS_Face & F,Standard_Real & umin,Standard_Real & umax,Standard_Real & vmin,Standard_Real & vmax)185 static void FindPeriod (const TopoDS_Face& F,
186 			Standard_Real&     umin,
187 			Standard_Real&     umax,
188 			Standard_Real&     vmin,
189 			Standard_Real&     vmax)
190 {
191 
192   Bnd_Box2d B;
193   TopExp_Explorer exp;
194   for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
195     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
196 
197     Standard_Real pf,pl;
198     const Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,pf,pl);
199     if (C.IsNull()) return;
200     Geom2dAdaptor_Curve PC(C,pf,pl);
201     Standard_Real i, nbp = 20;
202     if (PC.GetType() == GeomAbs_Line) nbp = 2;
203     Standard_Real step = (pl - pf) / nbp;
204     gp_Pnt2d P;
205     PC.D0(pf,P);
206     B.Add(P);
207     for (i = 2; i < nbp; i++) {
208       pf += step;
209       PC.D0(pf,P);
210       B.Add(P);
211     }
212     PC.D0(pl,P);
213     B.Add(P);
214     B.Get(umin,vmin,umax,vmax);
215   }
216 }
217 
218 //=======================================================================
219 //function : PutInBounds
220 //purpose  : Recadre la courbe 2d dans les bounds de la face
221 //=======================================================================
222 
PutInBounds(const TopoDS_Face & F,const TopoDS_Edge & E,Handle (Geom2d_Curve)& C2d)223 static void PutInBounds (const TopoDS_Face&          F,
224 			 const TopoDS_Edge&          E,
225 			 Handle(Geom2d_Curve)&       C2d)
226 {
227   Standard_Real   umin,umax,vmin,vmax;
228   Standard_Real   f,l;
229   BRep_Tool::Range(E,f,l);
230 
231   TopLoc_Location L; // Recup S avec la location pour eviter la copie.
232   Handle (Geom_Surface) S   = BRep_Tool::Surface(F,L);
233 
234   if (S->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
235     S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
236   }
237   //---------------
238   // Recadre en U.
239   //---------------
240   if (!S->IsUPeriodic() && !S->IsVPeriodic()) return;
241 
242   FindPeriod (F,umin,umax,vmin,vmax);
243 
244   if (S->IsUPeriodic()) {
245     Standard_Real period  = S->UPeriod();
246     Standard_Real eps     = period*1.e-6;
247     gp_Pnt2d      Pf      = C2d->Value(f);
248     gp_Pnt2d      Pl      = C2d->Value(l);
249     gp_Pnt2d      Pm      = C2d->Value(0.34*f + 0.66*l);
250     Standard_Real minC    = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X());
251     Standard_Real maxC    = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X());
252     Standard_Real du = 0.;
253     if (minC< umin - eps) {
254       du = (int((umin - minC)/period) + 1)*period;
255     }
256     if (minC > umax + eps) {
257       du = -(int((minC - umax)/period) + 1)*period;
258     }
259     if (du != 0) {
260       gp_Vec2d T1(du,0.);
261       C2d->Translate(T1);
262       minC += du; maxC += du;
263     }
264     // Ajuste au mieux la courbe dans le domaine.
265     if (maxC > umax +100*eps) {
266       Standard_Real d1 = maxC - umax;
267       Standard_Real d2 = umin - minC + period;
268       if (d2 < d1) du =-period;
269       if ( du != 0.) {
270 	gp_Vec2d T2(du,0.);
271 	C2d->Translate(T2);
272       }
273     }
274   }
275   //------------------
276   // Recadre en V.
277   //------------------
278   if (S->IsVPeriodic()) {
279     Standard_Real period  = S->VPeriod();
280     Standard_Real eps     = period*1.e-6;
281     gp_Pnt2d      Pf      = C2d->Value(f);
282     gp_Pnt2d      Pl      = C2d->Value(l);
283     gp_Pnt2d      Pm      = C2d->Value(0.34*f + 0.66*l);
284     Standard_Real minC    = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y());
285     Standard_Real maxC    = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y());
286     Standard_Real dv = 0.;
287     if (minC< vmin - eps) {
288       dv = (int((vmin - minC)/period) + 1)*period;
289     }
290     if (minC > vmax + eps) {
291       dv = -(int((minC - vmax)/period) + 1)*period;
292     }
293     if (dv != 0) {
294       gp_Vec2d T1(0.,dv);
295       C2d->Translate(T1);
296       minC += dv; maxC += dv;
297     }
298     // Ajuste au mieux la courbe dans le domaine.
299     if (maxC > vmax +100*eps) {
300       Standard_Real d1 = maxC - vmax;
301       Standard_Real d2 = vmin - minC + period;
302       if (d2 < d1) dv =-period;
303       if ( dv != 0.) {
304 	gp_Vec2d T2(0.,dv);
305 	C2d->Translate(T2);
306       }
307     }
308   }
309 }
310 
311 //=======================================================================
312 //function : Gabarit
313 //purpose  :
314 //=======================================================================
315 
Gabarit(const Handle (Geom_Curve)& aCurve)316 Standard_Real BRepOffset_Tool::Gabarit(const Handle(Geom_Curve)& aCurve)
317 {
318   GeomAdaptor_Curve GC( aCurve );
319   Bnd_Box aBox;
320   BndLib_Add3dCurve::Add( GC, Precision::Confusion(), aBox );
321   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dist;
322   aBox.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
323   dist = Max( (aXmax-aXmin), (aYmax-aYmin) );
324   dist = Max( dist, (aZmax-aZmin) );
325   return dist;
326 }
327 
328 //=======================================================================
329 //function : BuildPCurves
330 //purpose  :
331 //=======================================================================
332 
BuildPCurves(const TopoDS_Edge & E,const TopoDS_Face & F)333 static void BuildPCurves (const TopoDS_Edge&  E,
334 			  const TopoDS_Face&  F)
335 {
336   Standard_Real   ff,ll;
337   Handle (Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E,F,ff,ll);
338   if (!C2d.IsNull()) return;
339 
340   //Standard_Real Tolerance = Max(Precision::Confusion(),BRep_Tool::Tolerance(E));
341   Standard_Real Tolerance = Precision::Confusion();
342 
343   BRepAdaptor_Surface AS(F,0);
344   BRepAdaptor_Curve   AC(E);
345 
346   //Try to find pcurve on a bound of BSpline or Bezier surface
347   Handle( Geom_Surface ) theSurf = BRep_Tool::Surface( F );
348   Handle( Standard_Type ) typS = theSurf->DynamicType();
349   if (typS == STANDARD_TYPE(Geom_OffsetSurface))
350     typS = Handle(Geom_OffsetSurface)::DownCast (theSurf)->BasisSurface()->DynamicType();
351   if (typS == STANDARD_TYPE(Geom_BezierSurface) || typS == STANDARD_TYPE(Geom_BSplineSurface))
352     {
353       gp_Pnt fpoint = AC.Value( AC.FirstParameter() );
354       gp_Pnt lpoint = AC.Value( AC.LastParameter() );
355       TopoDS_Face theFace = BRepLib_MakeFace( theSurf, Precision::Confusion() );
356       Standard_Real U1 = 0., U2 = 0., TolProj = 1.e-4; //1.e-5;
357       TopoDS_Edge theEdge;
358       TopExp_Explorer Explo;
359       Explo.Init( theFace, TopAbs_EDGE );
360       for (; Explo.More(); Explo.Next())
361 	{
362 	  TopoDS_Edge anEdge = TopoDS::Edge( Explo.Current() );
363 	  BRepAdaptor_Curve aCurve( anEdge );
364 	  Extrema_ExtPC fextr( fpoint, aCurve );
365 	  if (!fextr.IsDone() || fextr.NbExt() < 1)
366 	    continue;
367 	  Standard_Real dist2, dist2min = RealLast();
368           Standard_Integer i;
369 	  for (i = 1; i <= fextr.NbExt(); i++)
370 	    {
371 	      dist2 = fextr.SquareDistance(i);
372 	      if (dist2 < dist2min)
373 		{
374 		  dist2min = dist2;
375 		  U1 = fextr.Point(i).Parameter();
376 		}
377 	    }
378 	  if (dist2min > TolProj * TolProj)
379 	    continue;
380 	  Extrema_ExtPC lextr( lpoint, aCurve );
381 	  if (!lextr.IsDone() || lextr.NbExt() <1)
382 	    continue;
383 	  dist2min = RealLast();
384 	  for (i = 1; i <= lextr.NbExt(); i++)
385 	    {
386 	      dist2 = lextr.SquareDistance(i);
387 	      if (dist2 < dist2min)
388 		{
389 		  dist2min = dist2;
390 		  U2 = lextr.Point(i).Parameter();
391 		}
392 	    }
393 	  if (dist2min <= TolProj * TolProj)
394 	    {
395 	      theEdge = anEdge;
396 	      break;
397 	    }
398 	} // for (; Explo.More(); Explo.Current())
399 
400       if (! theEdge.IsNull())
401 	{
402 	  //Construction of pcurve
403 	  if (U2 < U1)
404 	    {
405 	      Standard_Real temp = U1;
406 	      U1 = U2;
407 	      U2 = temp;
408 	    }
409 	  Standard_Real f, l;
410 	  C2d = BRep_Tool::CurveOnSurface( theEdge, theFace, f, l );
411 	  C2d = new Geom2d_TrimmedCurve( C2d, U1, U2 );
412 
413 	  if (theSurf->IsUPeriodic() || theSurf->IsVPeriodic())
414 	    PutInBounds( F, E, C2d );
415 
416 	  BRep_Builder B;
417 	  B.UpdateEdge( E, C2d, F, BRep_Tool::Tolerance(E) );
418 	  BRepLib::SameRange( E );
419 
420 	  return;
421 	}
422     } // if (typS == ...
423 
424   Handle(BRepAdaptor_Surface) HS = new BRepAdaptor_Surface(AS);
425   Handle(BRepAdaptor_Curve)   HC = new BRepAdaptor_Curve(AC);
426 
427   ProjLib_ProjectedCurve Proj(HS,HC,Tolerance);
428 
429   switch ( Proj.GetType()) {
430 
431   case GeomAbs_Line:
432     C2d = new Geom2d_Line(Proj.Line());
433     break;
434 
435   case GeomAbs_Circle:
436     C2d = new Geom2d_Circle(Proj.Circle());
437     break;
438 
439   case GeomAbs_Ellipse:
440     C2d = new Geom2d_Ellipse(Proj.Ellipse());
441     break;
442 
443   case GeomAbs_Parabola:
444     C2d = new Geom2d_Parabola(Proj.Parabola());
445     break;
446 
447   case GeomAbs_Hyperbola:
448     C2d = new Geom2d_Hyperbola(Proj.Hyperbola());
449     break;
450 
451   case GeomAbs_BezierCurve:
452     C2d = Proj.Bezier();
453     break;
454 
455   case GeomAbs_BSplineCurve:
456     C2d = Proj.BSpline();
457     break;
458   default:
459     break;
460   }
461 
462   if (AS.IsUPeriodic() || AS.IsVPeriodic()) {
463     PutInBounds(F,E,C2d);
464   }
465   if (!C2d.IsNull()) {
466     BRep_Builder    B;
467     B.UpdateEdge (E,C2d,F,BRep_Tool::Tolerance(E));
468   }
469   else {
470     throw Standard_ConstructionError("BRepOffset_Tool::BuildPCurves");
471   }
472 }
473 
474 //=======================================================================
475 //function : OriSect
476 //purpose  :
477 //=======================================================================
478 
OrientSection(const TopoDS_Edge & E,const TopoDS_Face & F1,const TopoDS_Face & F2,TopAbs_Orientation & O1,TopAbs_Orientation & O2)479 void BRepOffset_Tool::OrientSection (const TopoDS_Edge&  E,
480 				     const TopoDS_Face&  F1,
481 				     const TopoDS_Face&  F2,
482 				     TopAbs_Orientation& O1,
483 				     TopAbs_Orientation& O2)
484 {
485   TopLoc_Location L;
486   Standard_Real   f,l;
487 
488 
489   Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
490   Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);
491   Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l);
492   Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,F2,f,l);
493   Handle (Geom_Curve)   C  = BRep_Tool::Curve(E,L,f,l);
494 
495   BRepAdaptor_Curve BAcurve( E );
496 
497   GCPnts_AbscissaPoint AP(BAcurve,GCPnts_AbscissaPoint::Length(BAcurve)/2.0,f);
498   Standard_Real ParOnC;
499 
500   if(AP.IsDone())
501     ParOnC = AP.Parameter();
502   else
503     ParOnC = BOPTools_AlgoTools2D::IntermediatePoint(f, l);
504 
505   gp_Vec T1 = C->DN(ParOnC,1).Transformed(L.Transformation());
506   if (T1.SquareMagnitude() > gp::Resolution()) {
507     T1.Normalize();
508   }
509 
510   gp_Pnt2d P  = C1->Value(ParOnC);
511   gp_Pnt   P3;
512   gp_Vec   D1U,D1V;
513 
514   S1->D1(P.X(),P.Y(),P3,D1U,D1V);
515   gp_Vec DN1(D1U^D1V);
516   if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse();
517 
518   P = C2->Value(ParOnC);
519   S2->D1(P.X(),P.Y(),P3,D1U,D1V);
520   gp_Vec DN2(D1U^D1V);
521   if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse();
522 
523   gp_Vec        ProVec = DN2^T1;
524   Standard_Real Prod  =  DN1.Dot(ProVec);
525   if (Prod < 0.0) {
526     O1 = TopAbs_FORWARD;
527   }
528   else {
529     O1 = TopAbs_REVERSED;
530   }
531   ProVec = DN1^T1;
532   Prod  =  DN2.Dot(ProVec);
533   if (Prod < 0.0) {
534     O2 = TopAbs_FORWARD;
535   }
536   else {
537     O2 = TopAbs_REVERSED;
538   }
539   if (F1.Orientation() == TopAbs_REVERSED) O1 = TopAbs::Reverse(O1);
540   if (F2.Orientation() == TopAbs_REVERSED) O2 = TopAbs::Reverse(O2);
541 }
542 
543 //=======================================================================
544 //function : FindCommonShapes
545 //purpose  :
546 //=======================================================================
FindCommonShapes(const TopoDS_Face & theF1,const TopoDS_Face & theF2,TopTools_ListOfShape & theLE,TopTools_ListOfShape & theLV)547 Standard_Boolean BRepOffset_Tool::FindCommonShapes(const TopoDS_Face& theF1,
548                                                    const TopoDS_Face& theF2,
549                                                    TopTools_ListOfShape& theLE,
550                                                    TopTools_ListOfShape& theLV)
551 {
552   Standard_Boolean bFoundEdges =
553     FindCommonShapes(theF1, theF2, TopAbs_EDGE,   theLE);
554   Standard_Boolean bFoundVerts =
555     FindCommonShapes(theF1, theF2, TopAbs_VERTEX, theLV);
556   return bFoundEdges || bFoundVerts;
557 }
558 
559 //=======================================================================
560 //function : FindCommonShapes
561 //purpose  :
562 //=======================================================================
FindCommonShapes(const TopoDS_Shape & theS1,const TopoDS_Shape & theS2,const TopAbs_ShapeEnum theType,TopTools_ListOfShape & theLSC)563 Standard_Boolean BRepOffset_Tool::FindCommonShapes(const TopoDS_Shape& theS1,
564                                                    const TopoDS_Shape& theS2,
565                                                    const TopAbs_ShapeEnum theType,
566                                                    TopTools_ListOfShape& theLSC)
567 {
568   theLSC.Clear();
569   //
570   TopTools_MapOfShape aMS;
571   TopExp_Explorer aExp(theS1, theType);
572   for (; aExp.More(); aExp.Next()) {
573     aMS.Add(aExp.Current());
574   }
575   //
576   if (aMS.IsEmpty()) {
577     return Standard_False;
578   }
579   //
580   TopTools_MapOfShape aMFence;
581   aExp.Init(theS2, theType);
582   for (; aExp.More(); aExp.Next()) {
583     const TopoDS_Shape& aS2 = aExp.Current();
584     if (aMS.Contains(aS2)) {
585       if (aMFence.Add(aS2)) {
586         theLSC.Append(aS2);
587       }
588     }
589   }
590   //
591   return !theLSC.IsEmpty();
592 }
593 
594 //=======================================================================
595 //function : ToSmall
596 //purpose  :
597 //=======================================================================
598 
ToSmall(const Handle (Geom_Curve)& C)599 static Standard_Boolean ToSmall (const Handle(Geom_Curve)& C)
600 {
601   Standard_Real Tol = 10*Precision::Confusion();
602   Standard_Real m   = (C->FirstParameter()*0.668 + C->LastParameter()*0.332);
603   gp_Pnt P1 = C->Value(C->FirstParameter());
604   gp_Pnt P2 = C->Value(C->LastParameter());
605   gp_Pnt P3 = C->Value(m);
606   if (P1.Distance(P2) > Tol) return Standard_False;
607   if (P2.Distance(P3) > Tol) return Standard_False;
608   return Standard_True;
609 }
610 
611 
612 //=======================================================================
613 //function : IsOnSurface
614 //purpose  :
615 //=======================================================================
616 
IsOnSurface(const Handle (Geom_Curve)& C,const Handle (Geom_Surface)& S,Standard_Real TolConf,Standard_Real & TolReached)617 static Standard_Boolean IsOnSurface(const Handle(Geom_Curve)&   C,
618 				    const Handle(Geom_Surface)& S,
619 				    Standard_Real               TolConf,
620 				    Standard_Real&              TolReached)
621 {
622   Standard_Real    f = C->FirstParameter();
623   Standard_Real    l = C->LastParameter();
624   Standard_Integer n = 5;
625   Standard_Real du = (f-l)/(n-1);
626   TolReached = 0.;
627 
628   gp_Pnt P;
629   Standard_Real U,V;
630 
631   GeomAdaptor_Surface AS(S);
632 
633   switch ( AS.GetType()) {
634   case GeomAbs_Plane:
635     {
636       gp_Ax3 Ax = AS.Plane().Position();
637       for ( Standard_Integer i = 0; i < n; i++) {
638 	P = C->Value(f+i*du);
639 	ElSLib::PlaneParameters(Ax,P,U,V);
640 	TolReached = P.Distance(ElSLib::PlaneValue(U,V,Ax));
641 	if ( TolReached  > TolConf)
642 	  return Standard_False;
643       }
644       break;
645     }
646   case GeomAbs_Cylinder:
647     {
648       gp_Ax3        Ax  = AS.Cylinder().Position();
649       Standard_Real Rad = AS.Cylinder().Radius();
650       for ( Standard_Integer i = 0; i < n; i++) {
651 	P = C->Value(f+i*du);
652 	ElSLib::CylinderParameters(Ax,Rad,P,U,V);
653 	TolReached = P.Distance(ElSLib::CylinderValue(U,V,Ax,Rad));
654 	if ( TolReached > TolConf)
655 	  return Standard_False;
656       }
657       break;
658     }
659   case GeomAbs_Cone:
660     {
661       gp_Ax3        Ax  = AS.Cone().Position();
662       Standard_Real Rad = AS.Cone().RefRadius();
663       Standard_Real Alp = AS.Cone().SemiAngle();
664       for ( Standard_Integer i = 0; i < n; i++) {
665 	P = C->Value(f+i*du);
666 	ElSLib::ConeParameters(Ax,Rad,Alp,P,U,V);
667 	TolReached = P.Distance(ElSLib::ConeValue(U,V,Ax,Rad,Alp));
668 	if ( TolReached > TolConf)
669 	  return Standard_False;
670       }
671       break;
672     }
673   case GeomAbs_Sphere:
674     {
675       gp_Ax3        Ax  = AS.Sphere().Position();
676       Standard_Real Rad = AS.Sphere().Radius();
677       for ( Standard_Integer i = 0; i < n; i++) {
678 	P = C->Value(f+i*du);
679 	ElSLib::SphereParameters(Ax,Rad,P,U,V);
680 	TolReached = P.Distance(ElSLib::SphereValue(U,V,Ax,Rad));
681 	if ( TolReached > TolConf)
682 	  return Standard_False;
683       }
684       break;
685     }
686   case GeomAbs_Torus:
687     {
688       gp_Ax3        Ax  = AS.Torus().Position();
689       Standard_Real R1  = AS.Torus().MajorRadius();
690       Standard_Real R2  = AS.Torus().MinorRadius();
691       for ( Standard_Integer i = 0; i < n; i++) {
692 	P = C->Value(f+i*du);
693 	ElSLib::TorusParameters(Ax,R1,R2,P,U,V);
694 	TolReached =  P.Distance(ElSLib::TorusValue(U,V,Ax,R1,R2));
695 	if ( TolReached > TolConf)
696 	  return Standard_False;
697       }
698       break;
699     }
700 
701   default:
702     {
703       return Standard_False;
704     }
705   }
706 
707   return Standard_True;
708 }
709 
710 
711 //=======================================================================
712 //function : PipeInter
713 //purpose  :
714 //=======================================================================
715 
PipeInter(const TopoDS_Face & F1,const TopoDS_Face & F2,TopTools_ListOfShape & L1,TopTools_ListOfShape & L2,const TopAbs_State Side)716 void BRepOffset_Tool::PipeInter(const TopoDS_Face& F1,
717 				const TopoDS_Face& F2,
718 				TopTools_ListOfShape& L1,
719 				TopTools_ListOfShape& L2,
720 				const TopAbs_State    Side)
721 {
722 #ifdef DRAW
723   if (AffichInter) {
724     char name[256];
725     sprintf(name,"FF_%d",NbFaces++);
726     DBRep::Set(name,F1);
727     sprintf(name,"FF_%d",NbFaces++);
728     DBRep::Set(name,F2);
729   }
730 #endif
731 
732   Handle (Geom_Curve) CI;
733   TopAbs_Orientation O1,O2;
734   L1.Clear(); L2.Clear();
735   BRep_Builder B;
736   Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
737   Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);
738 
739   GeomInt_IntSS Inter (S1,S2, Precision::Confusion(),1,1,1);
740 
741   if (Inter.IsDone()) {
742     for (Standard_Integer i = 1; i <= Inter.NbLines(); i++) {
743       CI = Inter.Line(i);
744       if (ToSmall(CI)) continue;
745       TopoDS_Edge E = BRepLib_MakeEdge(CI);
746       if (Inter.HasLineOnS1(i)) {
747 	Handle(Geom2d_Curve) C2 = Inter.LineOnS1(i);
748 	PutInBounds  (F1,E,C2);
749 	B.UpdateEdge (E,C2,F1,BRep_Tool::Tolerance(E));
750       }
751       else {
752 	BuildPCurves (E,F1);
753       }
754       if (Inter.HasLineOnS2(i)) {
755 	Handle(Geom2d_Curve) C2 = Inter.LineOnS2(i);
756 	PutInBounds  (F2,E,C2);
757 	B.UpdateEdge (E,C2,F2,BRep_Tool::Tolerance(E));
758       }
759       else {
760 	BuildPCurves (E,F2);
761       }
762       OrientSection (E,F1,F2,O1,O2);
763       if (Side == TopAbs_OUT) {
764 	O1 = TopAbs::Reverse(O1);
765 	O2 = TopAbs::Reverse(O2);
766       }
767       L1.Append (E.Oriented(O1));
768       L2.Append (E.Oriented(O2));
769 #ifdef DRAW
770       if (AffichInter) {
771         char name[256];
772 	sprintf(name,"EI_%d",NbNewEdges++);
773 	DBRep::Set(name,E.Oriented(O1));
774       }
775 #endif
776     }
777   }
778 }
779 
780 //=======================================================================
781 //function : IsAutonomVertex
782 //purpose  : Checks whether a vertex is "autonom" or not
783 //=======================================================================
784 
IsAutonomVertex(const TopoDS_Shape & theVertex,const BOPDS_PDS & thePDS,const TopoDS_Face & theFace1,const TopoDS_Face & theFace2)785 static Standard_Boolean IsAutonomVertex(const TopoDS_Shape& theVertex,
786 					const BOPDS_PDS&    thePDS,
787                                         const TopoDS_Face&  theFace1,
788                                         const TopoDS_Face&  theFace2)
789 {
790   Standard_Integer nV = thePDS->Index(theVertex);
791   Standard_Integer nF [2];
792   nF[0] = thePDS->Index(theFace1);
793   nF[1] = thePDS->Index(theFace2);
794 
795   for (Standard_Integer i = 0; i < 2; i++)
796   {
797     const BOPDS_FaceInfo& aFaceInfo = thePDS->FaceInfo(nF[i]);
798     const TColStd_MapOfInteger& IndMap = aFaceInfo.VerticesOn();
799     if (IndMap.Contains(nV))
800       return Standard_False;
801   }
802 
803   return Standard_True;
804 }
805 
806 //=======================================================================
807 //function : IsAutonomVertex
808 //purpose  : Checks whether a vertex is "autonom" or not
809 //=======================================================================
810 
IsAutonomVertex(const TopoDS_Shape & aVertex,const BOPDS_PDS & pDS)811 static Standard_Boolean IsAutonomVertex(const TopoDS_Shape& aVertex,
812 					const BOPDS_PDS& pDS)
813 {
814   Standard_Integer index;
815   Standard_Integer aNbVVs, aNbEEs, aNbEFs, aInt;
816   //
817   index = pDS->Index(aVertex);
818   if (index == -1) {
819     Standard_Integer i, i1, i2;
820     i1=pDS->NbSourceShapes();
821     i2=pDS->NbShapes();
822     for (i=i1; i<i2; ++i) {
823       const TopoDS_Shape& aSx=pDS->Shape(i);
824       if(aSx.IsSame(aVertex)) {
825 		  index = i;
826 		  break;
827 		}
828 	    }
829 	}
830   //
831   if (!pDS->IsNewShape(index)) {
832     return Standard_False;
833     }
834   //check if vertex with index "index" is not created in VV or EE or EF interference
835   //VV
836   BOPDS_VectorOfInterfVV& aVVs=pDS->InterfVV();
837   aNbVVs = aVVs.Length();
838   for(aInt = 0; aInt < aNbVVs; aInt++) {
839     const BOPDS_InterfVV& aVV = aVVs(aInt);
840     if (aVV.HasIndexNew()) {
841       if (aVV.IndexNew() == index) {
842 		return Standard_False;
843 	    }
844 	}
845     }
846   //EE
847   BOPDS_VectorOfInterfEE& aEEs=pDS->InterfEE();
848   aNbEEs = aEEs.Length();
849   for(aInt = 0; aInt < aNbEEs; aInt++) {
850     const BOPDS_InterfEE& aEE = aEEs(aInt);
851     IntTools_CommonPrt aCP = aEE.CommonPart();
852     if(aCP.Type() == TopAbs_VERTEX) {
853       if (aEE.IndexNew() == index) {
854 		    return Standard_False;
855 		}
856 	    }
857 	}
858   //EF
859   BOPDS_VectorOfInterfEF& aEFs=pDS->InterfEF();
860   aNbEFs = aEFs.Length();
861   for(aInt = 0; aInt < aNbEFs; aInt++) {
862     const BOPDS_InterfEF& aEF = aEFs(aInt);
863     IntTools_CommonPrt aCP = aEF.CommonPart();
864     if(aCP.Type() == TopAbs_VERTEX) {
865       if (aEF.IndexNew() == index) {
866         return Standard_False;
867     }
868     }
869   }
870   return Standard_True;
871 }
872 
873 
874 //=======================================================================
875 //function : AreConnex
876 //purpose  : define if two shapes are connex by a vertex (vertices)
877 //=======================================================================
878 
AreConnex(const TopoDS_Wire & W1,const TopoDS_Wire & W2)879 static Standard_Boolean AreConnex(const TopoDS_Wire& W1,
880 				  const TopoDS_Wire& W2)
881 {
882   TopoDS_Vertex V11, V12, V21, V22;
883   TopExp::Vertices( W1, V11, V12 );
884   TopExp::Vertices( W2, V21, V22 );
885 
886   if (V11.IsSame(V21) || V11.IsSame(V22) ||
887       V12.IsSame(V21) || V12.IsSame(V22))
888     return Standard_True;
889 
890   return Standard_False;
891 }
892 
893 //=======================================================================
894 //function : AreClosed
895 //purpose  : define if two edges are connex by two vertices
896 //=======================================================================
897 
AreClosed(const TopoDS_Edge & E1,const TopoDS_Edge & E2)898 static Standard_Boolean AreClosed(const TopoDS_Edge& E1,
899 				  const TopoDS_Edge& E2)
900 {
901   TopoDS_Vertex V11, V12, V21, V22;
902   TopExp::Vertices( E1, V11, V12 );
903   TopExp::Vertices( E2, V21, V22 );
904 
905   if ((V11.IsSame(V21) && V12.IsSame(V22)) ||
906       (V11.IsSame(V22) && V12.IsSame(V21)))
907     return Standard_True;
908 
909   return Standard_False;
910 }
911 
912 //=======================================================================
913 //function : BSplineEdges
914 //purpose  :
915 //=======================================================================
916 
BSplineEdges(const TopoDS_Edge & E1,const TopoDS_Edge & E2,const Standard_Integer par1,const Standard_Integer par2,Standard_Real & angle)917 static Standard_Boolean BSplineEdges(const TopoDS_Edge& E1,
918 				     const TopoDS_Edge& E2,
919 				     const Standard_Integer par1,
920 				     const Standard_Integer par2,
921 				     Standard_Real& angle)
922 {
923   Standard_Real first1, last1, first2, last2, Param1, Param2;
924 
925   Handle(Geom_Curve) C1 = BRep_Tool::Curve( E1, first1, last1 );
926   if (C1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
927     C1 = Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
928 
929   Handle(Geom_Curve) C2 = BRep_Tool::Curve( E2, first2, last2 );
930   if (C2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
931     C2 = Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
932 
933   if (!C1->IsInstance(STANDARD_TYPE(Geom_BSplineCurve)) ||
934       !C2->IsInstance(STANDARD_TYPE(Geom_BSplineCurve)))
935     return Standard_False;
936 
937   Param1 = (par1 == 0)? first1 : last1;
938   Param2 = (par2 == 0)? first2 : last2;
939 
940   gp_Pnt Pnt1, Pnt2;
941   gp_Vec Der1, Der2;
942   C1->D1( Param1, Pnt1, Der1 );
943   C2->D1( Param2, Pnt2, Der2 );
944 
945   if (Der1.Magnitude() <= gp::Resolution() ||
946       Der2.Magnitude() <= gp::Resolution())
947     angle = M_PI/2.;
948   else
949     angle = Der1.Angle(Der2);
950 
951   return Standard_True;
952 }
953 
954 //=======================================================================
955 //function : AngleWireEdge
956 //purpose  :
957 //=======================================================================
958 
AngleWireEdge(const TopoDS_Wire & aWire,const TopoDS_Edge & anEdge)959 static Standard_Real AngleWireEdge(const TopoDS_Wire& aWire,
960 				   const TopoDS_Edge& anEdge)
961 {
962   TopoDS_Vertex V11, V12, V21, V22, CV;
963   TopExp::Vertices( aWire,  V11, V12 );
964   TopExp::Vertices( anEdge, V21, V22 );
965   CV = (V11.IsSame(V21) || V11.IsSame(V22))? V11 : V12;
966   TopoDS_Edge FirstEdge;
967   TopoDS_Iterator itw(aWire);
968   for (; itw.More(); itw.Next())
969     {
970       FirstEdge = TopoDS::Edge(itw.Value());
971       TopoDS_Vertex v1, v2;
972       TopExp::Vertices( FirstEdge, v1, v2 );
973       if (v1.IsSame(CV) || v2.IsSame(CV))
974 	{
975 	  V11 = v1;
976 	  V12 = v2;
977 	  break;
978 	}
979     }
980   Standard_Real Angle;
981   if (V11.IsSame(CV) && V21.IsSame(CV))
982     {
983       BSplineEdges( FirstEdge, anEdge, 0, 0, Angle );
984       Angle = M_PI - Angle;
985     }
986   else if (V11.IsSame(CV) && V22.IsSame(CV))
987     BSplineEdges( FirstEdge, anEdge, 0, 1, Angle );
988   else if (V12.IsSame(CV) && V21.IsSame(CV))
989     BSplineEdges( FirstEdge, anEdge, 1, 0, Angle );
990   else
991     {
992       BSplineEdges( FirstEdge, anEdge, 1, 1, Angle );
993       Angle = M_PI - Angle;
994     }
995   return Angle;
996 }
997 
998 
999 //=======================================================================
1000 //function : ReconstructPCurves
1001 //purpose  :
1002 //=======================================================================
1003 
ReconstructPCurves(const TopoDS_Edge & anEdge)1004 static void ReconstructPCurves(const TopoDS_Edge& anEdge)
1005 {
1006   Standard_Real f, l;
1007   Handle(Geom_Curve) C3d = BRep_Tool::Curve(anEdge, f, l);
1008 
1009   BRep_ListIteratorOfListOfCurveRepresentation
1010     itcr( (Handle(BRep_TEdge)::DownCast(anEdge.TShape()))->ChangeCurves() );
1011   for (; itcr.More(); itcr.Next())
1012     {
1013       Handle( BRep_CurveRepresentation ) CurveRep = itcr.Value();
1014       if (CurveRep->IsCurveOnSurface())
1015 	{
1016 	  Handle(Geom_Surface) theSurf  = CurveRep->Surface();
1017 	  TopLoc_Location      theLoc   = CurveRep->Location();
1018 	  theLoc = anEdge.Location() * theLoc;
1019 	  theSurf = Handle(Geom_Surface)::DownCast
1020 	    (theSurf->Transformed(theLoc.Transformation()));
1021 	  Handle(Geom2d_Curve) ProjPCurve =
1022 	    GeomProjLib::Curve2d( C3d, f, l, theSurf );
1023           if(!ProjPCurve.IsNull())
1024           {
1025 	    CurveRep->PCurve( ProjPCurve );
1026           }
1027 	}
1028     }
1029 }
1030 
1031 //=======================================================================
1032 //function : ConcatPCurves
1033 //purpose  :
1034 //=======================================================================
1035 
ConcatPCurves(const TopoDS_Edge & E1,const TopoDS_Edge & E2,const TopoDS_Face & F,const Standard_Boolean After,Standard_Real & newFirst,Standard_Real & newLast)1036 static Handle(Geom2d_Curve) ConcatPCurves(const TopoDS_Edge& E1,
1037 					  const TopoDS_Edge& E2,
1038 					  const TopoDS_Face& F,
1039 					  const Standard_Boolean After,
1040 					  Standard_Real& newFirst,
1041 					  Standard_Real& newLast)
1042 {
1043   Standard_Real Tol = 1.e-7;
1044   GeomAbs_Shape Continuity = GeomAbs_C1;
1045   Standard_Integer MaxDeg = 14;
1046   Standard_Integer MaxSeg = 16;
1047 
1048   Standard_Real first1, last1, first2, last2;
1049   Handle(Geom2d_Curve) PCurve1, PCurve2, newPCurve;
1050 
1051   PCurve1 = BRep_Tool::CurveOnSurface( E1, F, first1, last1 );
1052   if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1053     PCurve1 = Handle(Geom2d_TrimmedCurve)::DownCast (PCurve1)->BasisCurve();
1054 
1055   PCurve2 = BRep_Tool::CurveOnSurface( E2, F, first2, last2 );
1056   if (PCurve2->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1057     PCurve2 = Handle(Geom2d_TrimmedCurve)::DownCast (PCurve2)->BasisCurve();
1058 
1059   if (PCurve1 == PCurve2)
1060     {
1061       newPCurve = PCurve1;
1062       newFirst  = Min( first1, first2 );
1063       newLast   = Max( last1, last2 );
1064     }
1065   else if (PCurve1->DynamicType() == PCurve2->DynamicType() &&
1066 	   (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Line)) ||
1067 	    PCurve1->IsKind(STANDARD_TYPE(Geom2d_Conic))))
1068     {
1069       newPCurve = PCurve1;
1070       gp_Pnt2d P1, P2;
1071       P1 = PCurve2->Value( first2 );
1072       P2 = PCurve2->Value( last2 );
1073       if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Line)))
1074 	{
1075 	  Handle(Geom2d_Line) Lin1 = Handle(Geom2d_Line)::DownCast (PCurve1);
1076 	  gp_Lin2d theLin = Lin1->Lin2d();
1077 	  first2 = ElCLib::Parameter( theLin, P1 );
1078 	  last2  = ElCLib::Parameter( theLin, P2 );
1079 	}
1080       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Circle)))
1081 	{
1082 	  Handle(Geom2d_Circle) Circ1 = Handle(Geom2d_Circle)::DownCast (PCurve1);
1083 	  gp_Circ2d theCirc = Circ1->Circ2d();
1084 	  first2 = ElCLib::Parameter( theCirc, P1 );
1085 	  last2  = ElCLib::Parameter( theCirc, P2 );
1086 	}
1087       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Ellipse)))
1088 	{
1089 	  Handle(Geom2d_Ellipse) Ell1 = Handle(Geom2d_Ellipse)::DownCast (PCurve1);
1090 	  gp_Elips2d theElips = Ell1->Elips2d();
1091 	  first2 = ElCLib::Parameter( theElips, P1 );
1092 	  last2  = ElCLib::Parameter( theElips, P2 );
1093 	}
1094       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Parabola)))
1095 	{
1096 	  Handle(Geom2d_Parabola) Parab1 = Handle(Geom2d_Parabola)::DownCast (PCurve1);
1097 	  gp_Parab2d theParab = Parab1->Parab2d();
1098 	  first2 = ElCLib::Parameter( theParab, P1 );
1099 	  last2  = ElCLib::Parameter( theParab, P2 );
1100 	}
1101       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Hyperbola)))
1102 	{
1103 	  Handle(Geom2d_Hyperbola) Hypr1 = Handle(Geom2d_Hyperbola)::DownCast (PCurve1);
1104 	  gp_Hypr2d theHypr = Hypr1->Hypr2d();
1105 	  first2 = ElCLib::Parameter( theHypr, P1 );
1106 	  last2  = ElCLib::Parameter( theHypr, P2 );
1107 	}
1108       newFirst  = Min( first1, first2 );
1109       newLast   = Max( last1, last2 );
1110     }
1111   else
1112     {
1113       Handle(Geom2d_TrimmedCurve) TC1 = new Geom2d_TrimmedCurve( PCurve1, first1, last1 );
1114       Handle(Geom2d_TrimmedCurve) TC2 = new Geom2d_TrimmedCurve( PCurve2, first2, last2 );
1115       Geom2dConvert_CompCurveToBSplineCurve Concat2d( TC1 );
1116       Concat2d.Add( TC2, Precision::Confusion(), After );
1117       newPCurve = Concat2d.BSplineCurve();
1118       if (newPCurve->Continuity() < GeomAbs_C1)
1119 	{
1120 	  Geom2dConvert_ApproxCurve Approx2d( newPCurve, Tol, Continuity, MaxSeg, MaxDeg );
1121 	  if (Approx2d.HasResult())
1122 	    newPCurve = Approx2d.Curve();
1123 	}
1124       newFirst = newPCurve->FirstParameter();
1125       newLast  = newPCurve->LastParameter();
1126     }
1127 
1128   return newPCurve;
1129 }
1130 
1131 //=======================================================================
1132 //function : Glue
1133 //purpose  : glue two edges.
1134 //=======================================================================
1135 
Glue(const TopoDS_Edge & E1,const TopoDS_Edge & E2,const TopoDS_Vertex & Vfirst,const TopoDS_Vertex & Vlast,const Standard_Boolean After,const TopoDS_Face & F1,const Standard_Boolean addPCurve1,const TopoDS_Face & F2,const Standard_Boolean addPCurve2,const Standard_Real theGlueTol)1136 static TopoDS_Edge Glue(const TopoDS_Edge& E1,
1137                         const TopoDS_Edge& E2,
1138                         const TopoDS_Vertex& Vfirst,
1139                         const TopoDS_Vertex& Vlast,
1140                         const Standard_Boolean After,
1141                         const TopoDS_Face& F1,
1142                         const Standard_Boolean addPCurve1,
1143                         const TopoDS_Face& F2,
1144                         const Standard_Boolean addPCurve2,
1145                         const Standard_Real theGlueTol)
1146 {
1147   TopoDS_Edge newEdge;
1148 
1149   Standard_Real Tol = 1.e-7;
1150   GeomAbs_Shape Continuity = GeomAbs_C1;
1151   Standard_Integer MaxDeg = 14;
1152   Standard_Integer MaxSeg = 16;
1153 
1154   Handle(Geom_Curve) C1, C2, newCurve;
1155   Handle(Geom2d_Curve) PCurve1, PCurve2, newPCurve;
1156   Standard_Real first1, last1, first2, last2, fparam=0., lparam=0.;
1157   Standard_Boolean IsCanonic = Standard_False;
1158 
1159   C1 = BRep_Tool::Curve( E1, first1, last1 );
1160   if (C1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1161     C1 = Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
1162 
1163   C2 = BRep_Tool::Curve( E2, first2, last2 );
1164   if (C2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1165     C2 = Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
1166 
1167   if (C1 == C2)
1168     {
1169       newCurve = C1;
1170       fparam = Min( first1, first2 );
1171       lparam = Max( last1, last2 );
1172     }
1173   else if (C1->DynamicType() == C2->DynamicType() &&
1174 	   (C1->IsInstance(STANDARD_TYPE(Geom_Line)) ||
1175 	    C1->IsKind(STANDARD_TYPE(Geom_Conic))))
1176     {
1177       IsCanonic = Standard_True;
1178       newCurve  = C1;
1179     }
1180   else
1181     {
1182       Handle(Geom_TrimmedCurve) TC1 = new Geom_TrimmedCurve( C1, first1, last1 );
1183       Handle(Geom_TrimmedCurve) TC2 = new Geom_TrimmedCurve( C2, first2, last2 );
1184       GeomConvert_CompCurveToBSplineCurve Concat( TC1 );
1185       if (!Concat.Add( TC2, theGlueTol, After ))
1186         return newEdge;
1187       newCurve = Concat.BSplineCurve();
1188       if (newCurve->Continuity() < GeomAbs_C1)
1189 	{
1190 	  GeomConvert_ApproxCurve Approx3d( newCurve, Tol, Continuity, MaxSeg, MaxDeg );
1191 	  if (Approx3d.HasResult())
1192 	    newCurve = Approx3d.Curve();
1193 	}
1194       fparam = newCurve->FirstParameter();
1195       lparam = newCurve->LastParameter();
1196     }
1197 
1198   BRep_Builder BB;
1199 
1200   if (IsCanonic)
1201     newEdge = BRepLib_MakeEdge( newCurve, Vfirst, Vlast );
1202   else
1203     newEdge = BRepLib_MakeEdge( newCurve, Vfirst, Vlast, fparam, lparam );
1204 
1205   Standard_Real newFirst, newLast;
1206   if (addPCurve1)
1207     {
1208       newPCurve = ConcatPCurves( E1, E2, F1, After, newFirst, newLast );
1209       BB.UpdateEdge( newEdge, newPCurve, F1, 0. );
1210       BB.Range( newEdge, F1, newFirst, newLast );
1211     }
1212   if (addPCurve2)
1213     {
1214       newPCurve = ConcatPCurves( E1, E2, F2, After, newFirst, newLast );
1215       BB.UpdateEdge( newEdge, newPCurve, F2, 0. );
1216       BB.Range( newEdge, F2, newFirst, newLast );
1217     }
1218 
1219   return newEdge;
1220 }
1221 
1222 //=======================================================================
1223 //function : CheckIntersFF
1224 //purpose  :
1225 //=======================================================================
1226 
CheckIntersFF(const BOPDS_PDS & pDS,const TopoDS_Edge & RefEdge,TopTools_IndexedMapOfShape & TrueEdges)1227 static void CheckIntersFF(const BOPDS_PDS& pDS,
1228                           const TopoDS_Edge& RefEdge,
1229                           TopTools_IndexedMapOfShape& TrueEdges)
1230 {
1231   BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
1232   Standard_Integer aNb = aFFs.Length();
1233   Standard_Integer i, j, nbe = 0;
1234 
1235   TopoDS_Compound Edges;
1236   BRep_Builder BB;
1237   BB.MakeCompound(Edges);
1238 
1239   for (i = 0; i < aNb; ++i)
1240   {
1241     BOPDS_InterfFF& aFFi=aFFs(i);
1242     const BOPDS_VectorOfCurve& aBCurves=aFFi.Curves();
1243       Standard_Integer aNbCurves = aBCurves.Length();
1244 
1245     for (j = 0; j < aNbCurves; ++j)
1246     {
1247       const BOPDS_Curve& aBC=aBCurves(j);
1248       const BOPDS_ListOfPaveBlock& aSectEdges = aBC.PaveBlocks();
1249 
1250       BOPDS_ListIteratorOfListOfPaveBlock aPBIt;
1251       aPBIt.Initialize(aSectEdges);
1252 
1253       for (; aPBIt.More(); aPBIt.Next())
1254       {
1255         const Handle(BOPDS_PaveBlock)& aPB = aPBIt.Value();
1256         Standard_Integer nSect = aPB->Edge();
1257         const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&pDS->Shape(nSect);
1258         BB.Add(Edges, anEdge);
1259         nbe++;
1260       }
1261     }
1262   }
1263 
1264   if (nbe == 0)
1265     return;
1266 
1267   TopTools_ListOfShape CompList;
1268   BOPTools_AlgoTools::MakeConnexityBlocks(Edges, TopAbs_VERTEX, TopAbs_EDGE, CompList);
1269 
1270   TopoDS_Shape NearestCompound;
1271   if (CompList.Extent() == 1)
1272     NearestCompound = CompList.First();
1273   else
1274   {
1275     BRepAdaptor_Curve BAcurve(RefEdge);
1276     gp_Pnt Pref = BAcurve.Value((BAcurve.FirstParameter()+BAcurve.LastParameter())/2);
1277     TopoDS_Vertex Vref = BRepLib_MakeVertex(Pref);
1278     Standard_Real MinDist = RealLast();
1279     TopTools_ListIteratorOfListOfShape itl(CompList);
1280     for (; itl.More(); itl.Next())
1281     {
1282       const TopoDS_Shape& aCompound = itl.Value();
1283 
1284       BRepExtrema_DistShapeShape Projector(Vref, aCompound);
1285       if (!Projector.IsDone() || Projector.NbSolution() == 0)
1286         continue;
1287 
1288       Standard_Real aDist = Projector.Value();
1289       if (aDist < MinDist)
1290       {
1291         MinDist = aDist;
1292         NearestCompound = aCompound;
1293       }
1294     }
1295   }
1296 
1297   TopExp::MapShapes(NearestCompound, TopAbs_EDGE, TrueEdges);
1298 }
1299 
1300 //=======================================================================
1301 //function : AssembleEdge
1302 //purpose  :
1303 //=======================================================================
1304 
AssembleEdge(const BOPDS_PDS & pDS,const TopoDS_Face & F1,const TopoDS_Face & F2,const Standard_Boolean addPCurve1,const Standard_Boolean addPCurve2,const TopTools_SequenceOfShape & EdgesForConcat)1305 static TopoDS_Edge AssembleEdge(const BOPDS_PDS& pDS,
1306                                 const TopoDS_Face& F1,
1307                                 const TopoDS_Face& F2,
1308                                 const Standard_Boolean addPCurve1,
1309                                 const Standard_Boolean addPCurve2,
1310                                 const TopTools_SequenceOfShape& EdgesForConcat)
1311 {
1312   TopoDS_Edge NullEdge;
1313   TopoDS_Edge CurEdge = TopoDS::Edge( EdgesForConcat(1) );
1314   Standard_Real aGlueTol = Precision::Confusion();
1315 
1316   for (Standard_Integer j = 2; j <= EdgesForConcat.Length(); j++)
1317   {
1318     TopoDS_Edge anEdge = TopoDS::Edge( EdgesForConcat(j) );
1319     Standard_Boolean After = Standard_False;
1320     TopoDS_Vertex Vfirst, Vlast;
1321     Standard_Boolean AreClosedWire = AreClosed( CurEdge, anEdge );
1322     if (AreClosedWire)
1323     {
1324       TopoDS_Vertex V1, V2;
1325       TopExp::Vertices( CurEdge, V1, V2 );
1326       Standard_Boolean IsAutonomV1 = IsAutonomVertex( V1, pDS, F1, F2 );
1327       Standard_Boolean IsAutonomV2 = IsAutonomVertex( V2, pDS, F1, F2 );
1328       if (IsAutonomV1)
1329       {
1330         After = Standard_False;
1331         Vfirst = Vlast = V2;
1332       }
1333       else if (IsAutonomV2)
1334       {
1335         After = Standard_True;
1336         Vfirst = Vlast = V1;
1337       }
1338       else
1339         return NullEdge;
1340     }
1341     else
1342     {
1343       TopoDS_Vertex CV, V11, V12, V21, V22;
1344       TopExp::CommonVertex( CurEdge, anEdge, CV );
1345       Standard_Boolean IsAutonomCV = Standard_False;
1346       if (!CV.IsNull())
1347       {
1348         IsAutonomCV = IsAutonomVertex(CV, pDS, F1, F2);
1349       }
1350       if (IsAutonomCV)
1351       {
1352         aGlueTol = BRep_Tool::Tolerance(CV);
1353         TopExp::Vertices( CurEdge, V11, V12 );
1354         TopExp::Vertices( anEdge,  V21, V22 );
1355         if (V11.IsSame(CV) && V21.IsSame(CV))
1356         {
1357           Vfirst = V22;
1358           Vlast  = V12;
1359         }
1360         else if (V11.IsSame(CV) && V22.IsSame(CV))
1361         {
1362           Vfirst = V21;
1363           Vlast  = V12;
1364         }
1365         else if (V12.IsSame(CV) && V21.IsSame(CV))
1366         {
1367           Vfirst = V11;
1368           Vlast  = V22;
1369         }
1370         else
1371         {
1372           Vfirst = V11;
1373           Vlast  = V21;
1374         }
1375       }
1376       else
1377         return NullEdge;
1378     } //end of else (open wire)
1379 
1380     TopoDS_Edge NewEdge = Glue(CurEdge, anEdge, Vfirst, Vlast, After,
1381                                F1, addPCurve1, F2, addPCurve2, aGlueTol);
1382     if (NewEdge.IsNull())
1383       return NullEdge;
1384     else
1385       CurEdge = NewEdge;
1386   } //end of for (Standard_Integer j = 2; j <= EdgesForConcat.Length(); j++)
1387 
1388   return CurEdge;
1389 }
1390 
1391 //=======================================================================
1392 //function : Inter3D
1393 //purpose  :
1394 //=======================================================================
1395 
Inter3D(const TopoDS_Face & F1,const TopoDS_Face & F2,TopTools_ListOfShape & L1,TopTools_ListOfShape & L2,const TopAbs_State Side,const TopoDS_Edge & RefEdge,const TopoDS_Face & theRefFace1,const TopoDS_Face & theRefFace2)1396 void BRepOffset_Tool::Inter3D(const TopoDS_Face& F1,
1397 			      const TopoDS_Face& F2,
1398 			      TopTools_ListOfShape& L1,
1399 			      TopTools_ListOfShape& L2,
1400 			      const TopAbs_State    Side,
1401 			      const TopoDS_Edge&    RefEdge,
1402                               const TopoDS_Face&    theRefFace1,
1403                               const TopoDS_Face&    theRefFace2)
1404 {
1405 #ifdef DRAW
1406   if (AffichInter) {
1407     char name[256];
1408     sprintf(name,"FF_%d",NbFaces++);
1409     DBRep::Set(name,F1);
1410     sprintf(name,"FF_%d",NbFaces++);
1411     DBRep::Set(name,F2);
1412   }
1413 #endif
1414 
1415   // Check if the faces are planar and not trimmed - in this case
1416   // the IntTools_FaceFace intersection algorithm will be used directly.
1417   BRepAdaptor_Surface aBAS1(F1, Standard_False), aBAS2(F2, Standard_False);
1418   if (aBAS1.GetType() == GeomAbs_Plane &&
1419       aBAS2.GetType() == GeomAbs_Plane) {
1420     aBAS1.Initialize(F1, Standard_True);
1421     if (IsInf(aBAS1.LastUParameter()) && IsInf(aBAS1.LastVParameter())) {
1422       aBAS2.Initialize(F2, Standard_True);
1423       if (IsInf(aBAS2.LastUParameter()) && IsInf(aBAS2.LastVParameter())) {
1424         // Intersect the planes without pave filler
1425         PerformPlanes(F1, F2, Side, L1, L2);
1426         return;
1427       }
1428     }
1429   }
1430 
1431   // create 3D curves on faces
1432   BRepLib::BuildCurves3d(F1);
1433   BRepLib::BuildCurves3d(F2);
1434   UpdateVertexTolerances(F1);
1435   UpdateVertexTolerances(F2);
1436 
1437   BOPAlgo_PaveFiller aPF;
1438   TopTools_ListOfShape aLS;
1439   aLS.Append(F1);
1440   aLS.Append(F2);
1441   aPF.SetArguments(aLS);
1442   //
1443   aPF.Perform();
1444 
1445   TopTools_IndexedMapOfShape TrueEdges;
1446   if (!RefEdge.IsNull())
1447     CheckIntersFF( aPF.PDS(), RefEdge, TrueEdges );
1448 
1449   Standard_Boolean addPCurve1 = 1;
1450   Standard_Boolean addPCurve2 = 1;
1451 
1452   const BOPDS_PDS& pDS = aPF.PDS();
1453   BOPDS_VectorOfInterfFF& aFFs=pDS->InterfFF();
1454   Standard_Integer aNb = aFFs.Length();
1455   Standard_Integer i = 0, j = 0, k;
1456   // Store Result
1457   L1.Clear(); L2.Clear();
1458   TopAbs_Orientation O1,O2;
1459   BRep_Builder BB;
1460   //
1461   const Handle(IntTools_Context)& aContext = aPF.Context();
1462   //
1463   for (i = 0; i < aNb; i++) {
1464     BOPDS_InterfFF& aFFi=aFFs(i);
1465     const BOPDS_VectorOfCurve& aBCurves=aFFi.Curves();
1466 
1467     Standard_Integer aNbCurves = aBCurves.Length();
1468 
1469     for (j = 0; j < aNbCurves; j++) {
1470       const BOPDS_Curve& aBC=aBCurves(j);
1471       const BOPDS_ListOfPaveBlock& aSectEdges = aBC.PaveBlocks();
1472 
1473       BOPDS_ListIteratorOfListOfPaveBlock aPBIt;
1474       aPBIt.Initialize(aSectEdges);
1475 
1476       for (; aPBIt.More(); aPBIt.Next()) {
1477         const Handle(BOPDS_PaveBlock)& aPB = aPBIt.Value();
1478         Standard_Integer nSect = aPB->Edge();
1479         const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&pDS->Shape(nSect);
1480 	if (!TrueEdges.IsEmpty() && !TrueEdges.Contains(anEdge))
1481 	  continue;
1482 
1483         Standard_Real f, l;
1484 	const Handle(Geom_Curve)& aC3DE = BRep_Tool::Curve(anEdge, f, l);
1485 	Handle(Geom_TrimmedCurve) aC3DETrim;
1486 
1487 	if(!aC3DE.IsNull())
1488             aC3DETrim = new Geom_TrimmedCurve(aC3DE, f, l);
1489 
1490 	Standard_Real aTolEdge = BRep_Tool::Tolerance(anEdge);
1491 
1492         if (!BOPTools_AlgoTools2D::HasCurveOnSurface(anEdge, F1)) {
1493           Handle(Geom2d_Curve) aC2d = aBC.Curve().FirstCurve2d();
1494           if(!aC3DETrim.IsNull()) {
1495             Handle(Geom2d_Curve) aC2dNew;
1496 
1497             if(aC3DE->IsPeriodic()) {
1498               BOPTools_AlgoTools2D::AdjustPCurveOnFace(F1, f, l,  aC2d, aC2dNew, aContext);
1499             }
1500             else {
1501               BOPTools_AlgoTools2D::AdjustPCurveOnFace(F1, aC3DETrim, aC2d, aC2dNew, aContext);
1502             }
1503             aC2d = aC2dNew;
1504           }
1505           BB.UpdateEdge(anEdge, aC2d, F1, aTolEdge);
1506         }
1507 
1508         if (!BOPTools_AlgoTools2D::HasCurveOnSurface(anEdge, F2)) {
1509           Handle(Geom2d_Curve) aC2d = aBC.Curve().SecondCurve2d();
1510           if(!aC3DETrim.IsNull()) {
1511             Handle(Geom2d_Curve) aC2dNew;
1512 
1513             if(aC3DE->IsPeriodic()) {
1514               BOPTools_AlgoTools2D::AdjustPCurveOnFace(F2, f, l,  aC2d, aC2dNew, aContext);
1515             }
1516             else {
1517               BOPTools_AlgoTools2D::AdjustPCurveOnFace(F2, aC3DETrim, aC2d, aC2dNew, aContext);
1518             }
1519             aC2d = aC2dNew;
1520           }
1521           BB.UpdateEdge(anEdge, aC2d, F2, aTolEdge);
1522         }
1523 
1524         OrientSection (anEdge, F1, F2, O1, O2);
1525         if (Side == TopAbs_OUT) {
1526           O1 = TopAbs::Reverse(O1);
1527           O2 = TopAbs::Reverse(O2);
1528         }
1529 
1530         L1.Append (anEdge.Oriented(O1));
1531         L2.Append (anEdge.Oriented(O2));
1532 
1533 #ifdef DRAW
1534         if (AffichInter) {
1535 	  char name[256];
1536           sprintf(name,"EI_%d",NbNewEdges++);
1537           DBRep::Set(name,anEdge.Oriented(O1));
1538 
1539         }
1540 #endif
1541       }
1542     }
1543   }
1544 
1545   Standard_Real aSameParTol = Precision::Confusion();
1546   Standard_Boolean isEl1 = Standard_False, isEl2 = Standard_False;
1547 
1548   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F1);
1549   if (aSurf->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
1550     aSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (aSurf)->BasisSurface();
1551   if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1552     addPCurve1 = Standard_False;
1553   else if (aSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
1554     isEl1 = Standard_True;
1555 
1556   aSurf = BRep_Tool::Surface(F2);
1557   if (aSurf->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
1558     aSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (aSurf)->BasisSurface();
1559   if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1560     addPCurve2 = Standard_False;
1561   else if (aSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
1562     isEl2 = Standard_True;
1563 
1564   if (L1.Extent() > 1 && (!isEl1 || !isEl2) && !theRefFace1.IsNull())
1565   {
1566     //remove excess edges that are out of range
1567     TopoDS_Vertex aV1, aV2;
1568     TopExp::Vertices (RefEdge, aV1, aV2);
1569     if (!aV1.IsSame(aV2)) //only if RefEdge is open
1570     {
1571       Handle(Geom_Surface) aRefSurf1 = BRep_Tool::Surface (theRefFace1);
1572       Handle(Geom_Surface) aRefSurf2 = BRep_Tool::Surface (theRefFace2);
1573       if (aRefSurf1->IsUClosed() || aRefSurf1->IsVClosed() ||
1574           aRefSurf2->IsUClosed() || aRefSurf2->IsVClosed())
1575       {
1576         TopoDS_Edge MinAngleEdge;
1577         Standard_Real MinAngle = Precision::Infinite();
1578         BRepAdaptor_Curve aRefBAcurve (RefEdge);
1579         gp_Pnt aRefPnt = aRefBAcurve.Value ((aRefBAcurve.FirstParameter() + aRefBAcurve.LastParameter())/2);
1580 
1581         TopTools_ListIteratorOfListOfShape itl (L1);
1582         for (; itl.More(); itl.Next())
1583         {
1584           const TopoDS_Edge& anEdge = TopoDS::Edge (itl.Value());
1585 
1586           BRepAdaptor_Curve aBAcurve (anEdge);
1587           gp_Pnt aMidPntOnEdge = aBAcurve.Value ((aBAcurve.FirstParameter() + aBAcurve.LastParameter())/2);
1588           gp_Vec RefToMid (aRefPnt, aMidPntOnEdge);
1589 
1590           Extrema_ExtPC aProjector (aRefPnt, aBAcurve);
1591           if (aProjector.IsDone())
1592           {
1593             Standard_Integer imin = 0;
1594             Standard_Real MinSqDist = Precision::Infinite();
1595             for (Standard_Integer ind = 1; ind <= aProjector.NbExt(); ind++)
1596             {
1597               Standard_Real aSqDist = aProjector.SquareDistance(ind);
1598               if (aSqDist < MinSqDist)
1599               {
1600                 MinSqDist = aSqDist;
1601                 imin = ind;
1602               }
1603             }
1604             if (imin != 0)
1605             {
1606               gp_Pnt aProjectionOnEdge = aProjector.Point(imin).Value();
1607               gp_Vec RefToProj (aRefPnt, aProjectionOnEdge);
1608               Standard_Real anAngle = RefToProj.Angle(RefToMid);
1609               if (anAngle < MinAngle)
1610               {
1611                 MinAngle = anAngle;
1612                 MinAngleEdge = anEdge;
1613               }
1614             }
1615           }
1616         }
1617 
1618         if (!MinAngleEdge.IsNull())
1619         {
1620           TopTools_ListIteratorOfListOfShape itlist1 (L1);
1621           TopTools_ListIteratorOfListOfShape itlist2 (L2);
1622 
1623           while (itlist1.More())
1624           {
1625             const TopoDS_Shape& anEdge = itlist1.Value();
1626             if (anEdge.IsSame(MinAngleEdge))
1627             {
1628               itlist1.Next();
1629               itlist2.Next();
1630             }
1631             else
1632             {
1633               L1.Remove(itlist1);
1634               L2.Remove(itlist2);
1635             }
1636           }
1637         }
1638       } //if closed
1639     } //if (!aV1.IsSame(aV2))
1640   } //if (L1.Extent() > 1 && (!isEl1 || !isEl2) && !theRefFace1.IsNull())
1641 
1642   if (L1.Extent() > 1 && (!isEl1 || !isEl2)) {
1643     TopTools_SequenceOfShape eseq;
1644     TopTools_SequenceOfShape EdgesForConcat;
1645 
1646     if (!TrueEdges.IsEmpty())
1647     {
1648       for (i = TrueEdges.Extent(); i >= 1; i--)
1649         EdgesForConcat.Append( TrueEdges(i) );
1650       TopoDS_Edge AssembledEdge =
1651         AssembleEdge( pDS, F1, F2, addPCurve1, addPCurve2, EdgesForConcat );
1652       if (AssembledEdge.IsNull())
1653         for (i = TrueEdges.Extent(); i >= 1; i--)
1654           eseq.Append( TrueEdges(i) );
1655       else
1656         eseq.Append(AssembledEdge);
1657     }
1658     else
1659     {
1660       TopTools_SequenceOfShape wseq;
1661       TopTools_SequenceOfShape edges;
1662       TopTools_ListIteratorOfListOfShape itl(L1);
1663       for (; itl.More(); itl.Next())
1664         edges.Append( itl.Value() );
1665       while (!edges.IsEmpty())
1666       {
1667         TopoDS_Edge anEdge = TopoDS::Edge( edges.First() );
1668         TopoDS_Wire aWire, resWire;
1669         BB.MakeWire(aWire);
1670         BB.Add( aWire, anEdge );
1671         TColStd_SequenceOfInteger Candidates;
1672         for (k = 1; k <= wseq.Length(); k++)
1673         {
1674           resWire = TopoDS::Wire(wseq(k));
1675           if (AreConnex( resWire, aWire ))
1676           {
1677             Candidates.Append( 1 );
1678             break;
1679           }
1680         }
1681         if (Candidates.IsEmpty())
1682         {
1683           wseq.Append( aWire );
1684           edges.Remove(1);
1685         }
1686         else
1687         {
1688           for (j = 2; j <= edges.Length(); j++)
1689           {
1690             anEdge = TopoDS::Edge( edges(j) );
1691             aWire.Nullify();
1692             BB.MakeWire(aWire);
1693             BB.Add( aWire, anEdge );
1694             if (AreConnex( resWire, aWire ))
1695               Candidates.Append( j );
1696           }
1697           Standard_Integer minind = 1;
1698           if (Candidates.Length() > 1)
1699           {
1700             Standard_Real MinAngle = RealLast();
1701             for (j = 1; j <= Candidates.Length(); j++)
1702             {
1703               anEdge = TopoDS::Edge( edges(Candidates(j)) );
1704               Standard_Real anAngle = AngleWireEdge( resWire, anEdge );
1705               if (anAngle < MinAngle)
1706               {
1707                 MinAngle = anAngle;
1708                 minind = j;
1709               }
1710             }
1711           }
1712           BB.Add( resWire, TopoDS::Edge(edges(Candidates(minind))) );
1713           wseq(k) = resWire;
1714           edges.Remove(Candidates(minind));
1715         }
1716       } //end of while (!edges.IsEmpty())
1717 
1718       for (i = 1; i <= wseq.Length(); i++)
1719       {
1720         TopoDS_Wire aWire = TopoDS::Wire(wseq(i));
1721         TopTools_SequenceOfShape aLocalEdgesForConcat;
1722         if (aWire.Closed())
1723         {
1724           TopoDS_Vertex StartVertex;
1725           TopoDS_Edge StartEdge;
1726           Standard_Boolean StartFound = Standard_False;
1727           TopTools_ListOfShape Elist;
1728 
1729           TopoDS_Iterator itw(aWire);
1730           for (; itw.More(); itw.Next())
1731           {
1732             TopoDS_Edge anEdge = TopoDS::Edge(itw.Value());
1733             if (StartFound)
1734               Elist.Append(anEdge);
1735             else
1736             {
1737               TopoDS_Vertex V1, V2;
1738               TopExp::Vertices( anEdge, V1, V2 );
1739               if (!IsAutonomVertex( V1, pDS ))
1740               {
1741                 StartVertex = V2;
1742                 StartEdge = anEdge;
1743                 StartFound = Standard_True;
1744               }
1745               else if (!IsAutonomVertex( V2, pDS ))
1746               {
1747                 StartVertex = V1;
1748                 StartEdge = anEdge;
1749                 StartFound = Standard_True;
1750               }
1751               else
1752                 Elist.Append(anEdge);
1753             }
1754           } //end of for (; itw.More(); itw.Next())
1755           if (!StartFound)
1756           {
1757             itl.Initialize(Elist);
1758             StartEdge = TopoDS::Edge(itl.Value());
1759             Elist.Remove(itl);
1760             TopoDS_Vertex V1, V2;
1761             TopExp::Vertices( StartEdge, V1, V2 );
1762             StartVertex = V1;
1763           }
1764           aLocalEdgesForConcat.Append( StartEdge );
1765           while (!Elist.IsEmpty())
1766           {
1767             for (itl.Initialize(Elist); itl.More(); itl.Next())
1768             {
1769               TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
1770               TopoDS_Vertex V1, V2;
1771               TopExp::Vertices( anEdge, V1, V2 );
1772               if (V1.IsSame(StartVertex))
1773               {
1774                 StartVertex = V2;
1775                 aLocalEdgesForConcat.Append( anEdge );
1776                 Elist.Remove(itl);
1777                 break;
1778               }
1779               else if (V2.IsSame(StartVertex))
1780               {
1781                 StartVertex = V1;
1782                 aLocalEdgesForConcat.Append( anEdge );
1783                 Elist.Remove(itl);
1784                 break;
1785               }
1786             }
1787           } //end of while (!Elist.IsEmpty())
1788         } //end of if (aWire.Closed())
1789         else
1790         {
1791           BRepTools_WireExplorer Wexp( aWire );
1792           for (; Wexp.More(); Wexp.Next())
1793             aLocalEdgesForConcat.Append( Wexp.Current() );
1794         }
1795 
1796         TopoDS_Edge AssembledEdge =
1797           AssembleEdge( pDS, F1, F2, addPCurve1, addPCurve2, aLocalEdgesForConcat );
1798         if (AssembledEdge.IsNull())
1799           for (j = aLocalEdgesForConcat.Length(); j >= 1; j--)
1800             eseq.Append( aLocalEdgesForConcat(j) );
1801         else
1802           eseq.Append( AssembledEdge );
1803       } //for (i = 1; i <= wseq.Length(); i++)
1804     } //end of else (when TrueEdges is empty)
1805 
1806     if (eseq.Length() < L1.Extent())
1807     {
1808       L1.Clear();
1809       L2.Clear();
1810       for (i = 1; i <= eseq.Length(); i++)
1811       {
1812         TopoDS_Shape aShape = eseq(i);
1813         TopoDS_Edge anEdge = TopoDS::Edge(eseq(i));
1814         BRepLib::SameParameter(anEdge, aSameParTol, Standard_True);
1815         Standard_Real EdgeTol = BRep_Tool::Tolerance(anEdge);
1816 #ifdef OCCT_DEBUG
1817         std::cout<<"Tolerance of glued E =      "<<EdgeTol<<std::endl;
1818 #endif
1819         if (EdgeTol > 1.e-2)
1820           continue;
1821 
1822         if (EdgeTol >= 1.e-4)
1823         {
1824           ReconstructPCurves(anEdge);
1825           BRepLib::SameParameter(anEdge, aSameParTol, Standard_True);
1826 #ifdef OCCT_DEBUG
1827           std::cout<<"After projection tol of E = "<<BRep_Tool::Tolerance(anEdge)<<std::endl;
1828 #endif
1829         }
1830 
1831         OrientSection( anEdge, F1, F2, O1, O2 );
1832         if (Side == TopAbs_OUT)
1833         {
1834           O1 = TopAbs::Reverse(O1);
1835           O2 = TopAbs::Reverse(O2);
1836         }
1837 
1838         L1.Append( anEdge.Oriented(O1) );
1839         L2.Append( anEdge.Oriented(O2) );
1840       }
1841     }
1842   } //end of if (L1.Extent() > 1)
1843 
1844   else
1845   {
1846     TopTools_ListIteratorOfListOfShape itl(L1);
1847     for (; itl.More(); itl.Next())
1848     {
1849       const TopoDS_Edge& anEdge = TopoDS::Edge( itl.Value() );
1850       BRepLib::SameParameter(anEdge, aSameParTol, Standard_True);
1851     }
1852   }
1853 }
1854 
1855 //=======================================================================
1856 //function : TryProject
1857 //purpose  :
1858 //=======================================================================
1859 
TryProject(const TopoDS_Face & F1,const TopoDS_Face & F2,const TopTools_ListOfShape & Edges,TopTools_ListOfShape & LInt1,TopTools_ListOfShape & LInt2,const TopAbs_State Side,const Standard_Real TolConf)1860 Standard_Boolean BRepOffset_Tool::TryProject
1861 (const TopoDS_Face&          F1,
1862  const TopoDS_Face&          F2,
1863  const TopTools_ListOfShape& Edges,
1864        TopTools_ListOfShape& LInt1,
1865        TopTools_ListOfShape& LInt2,
1866  const TopAbs_State          Side,
1867  const Standard_Real         TolConf)
1868 {
1869 #ifdef DRAW
1870   if (AffichInter) {
1871     char name[256];
1872     sprintf(name,"FF_%d",NbFaces++);
1873     DBRep::Set(name,F1);
1874     sprintf(name,"FF_%d",NbFaces++);
1875     DBRep::Set(name,F2);
1876   }
1877 #endif
1878 
1879   // try to find if the edges <Edges> are laying on the face F1.
1880   LInt1.Clear(); LInt2.Clear();
1881   TopTools_ListIteratorOfListOfShape it(Edges);
1882   Standard_Boolean     isOk = Standard_True;
1883   Standard_Boolean     Ok   = Standard_True;
1884   TopAbs_Orientation   O1,O2;
1885   Handle(Geom_Surface) Bouchon = BRep_Tool::Surface(F1);
1886   BRep_Builder B;
1887 
1888   for ( ; it.More(); it.Next()) {
1889     TopLoc_Location L;
1890     Standard_Real f,l;
1891     TopoDS_Edge CurE     = TopoDS::Edge(it.Value());
1892     Handle(Geom_Curve) C = BRep_Tool::Curve(CurE,L,f,l);
1893     if (C.IsNull()) {
1894       BRepLib::BuildCurve3d(CurE,BRep_Tool::Tolerance(CurE));
1895       C  = BRep_Tool::Curve(CurE,L,f,l);
1896     }
1897     C = new Geom_TrimmedCurve(C,f,l);
1898     if ( !L.IsIdentity()) C->Transform(L);
1899     Standard_Real TolReached;
1900     isOk = IsOnSurface(C,Bouchon,TolConf,TolReached);
1901 
1902     if ( isOk) {
1903       B.UpdateEdge(CurE,TolReached);
1904       BuildPCurves(CurE,F1);
1905       OrientSection (CurE,F1,F2,O1,O2);
1906       if (Side == TopAbs_OUT) {
1907 	O1 = TopAbs::Reverse(O1);
1908 	O2 = TopAbs::Reverse(O2);
1909       }
1910       LInt1.Append (CurE.Oriented(O1));
1911       LInt2.Append (CurE.Oriented(O2));
1912 #ifdef DRAW
1913       if (AffichInter) {
1914         char name[256];
1915         sprintf(name,"EI_%d",NbNewEdges++);
1916 	DBRep::Set(name,CurE.Oriented(O1));
1917       }
1918 #endif
1919     }
1920     else
1921       Ok = Standard_False;
1922   }
1923   return Ok;
1924 }
1925 
1926 
1927 //=======================================================================
1928 //function : InterOrExtent
1929 //purpose  :
1930 //=======================================================================
1931 
InterOrExtent(const TopoDS_Face & F1,const TopoDS_Face & F2,TopTools_ListOfShape & L1,TopTools_ListOfShape & L2,const TopAbs_State Side)1932 void BRepOffset_Tool::InterOrExtent(const TopoDS_Face& F1,
1933 				    const TopoDS_Face& F2,
1934 				    TopTools_ListOfShape& L1,
1935 				    TopTools_ListOfShape& L2,
1936 				    const TopAbs_State    Side)
1937 {
1938 #ifdef DRAW
1939   if (AffichInter) {
1940     char name[256];
1941     sprintf(name,"FF_%d",NbFaces++);
1942     DBRep::Set(name,F1);
1943     sprintf(name,"FF_%d",NbFaces++);
1944     DBRep::Set(name,F2);
1945   }
1946 #endif
1947 
1948   Handle (Geom_Curve) CI;
1949   TopAbs_Orientation O1,O2;
1950   L1.Clear(); L2.Clear();
1951   Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
1952   Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);
1953 
1954   if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1955     Handle(Geom_RectangularTrimmedSurface) RTS ;
1956     RTS = Handle(Geom_RectangularTrimmedSurface)::DownCast (S1);
1957     if (RTS->BasisSurface()->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
1958       S1 = RTS->BasisSurface();
1959     }
1960   }
1961   if (S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1962     Handle(Geom_RectangularTrimmedSurface) RTS ;
1963     RTS = Handle(Geom_RectangularTrimmedSurface)::DownCast (S2);
1964     if (RTS->BasisSurface()->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
1965       S2 = RTS->BasisSurface();
1966     }
1967   }
1968 
1969   GeomInt_IntSS Inter  (S1,S2, Precision::Confusion());
1970 
1971   if (Inter.IsDone()) {
1972     for (Standard_Integer i = 1; i <= Inter.NbLines(); i++) {
1973       CI = Inter.Line(i);
1974 
1975       if (ToSmall(CI)) continue;
1976       TopoDS_Edge E = BRepLib_MakeEdge(CI);
1977       BuildPCurves (E,F1);
1978       BuildPCurves (E,F2);
1979       OrientSection (E,F1,F2,O1,O2);
1980       if (Side == TopAbs_OUT) {
1981 	O1 = TopAbs::Reverse(O1);
1982 	O2 = TopAbs::Reverse(O2);
1983       }
1984       L1.Append (E.Oriented(O1));
1985       L2.Append (E.Oriented(O2));
1986 #ifdef DRAW
1987       if (AffichInter) {
1988         char name[256];
1989 	sprintf(name,"EI_%d",NbNewEdges++);
1990 	DBRep::Set(name,E.Oriented(O1));
1991       }
1992 #endif
1993     }
1994   }
1995 }
1996 
1997 //=======================================================================
1998 //function : ExtentEdge
1999 //purpose  :
2000 //=======================================================================
2001 
ExtentEdge(const TopoDS_Face & F,const TopoDS_Face & EF,const TopoDS_Edge & E,TopoDS_Edge & NE)2002 static void ExtentEdge(const TopoDS_Face& F,
2003 		       const TopoDS_Face& EF,
2004 		       const TopoDS_Edge& E,
2005 		       TopoDS_Edge&       NE)
2006 {
2007   BRepAdaptor_Curve CE(E);
2008   GeomAbs_CurveType Type = CE.GetType();
2009   TopoDS_Shape aLocalEdge = E.EmptyCopied();
2010   NE = TopoDS::Edge(aLocalEdge);
2011 //  NE = TopoDS::Edge(E.EmptyCopied());
2012 
2013   if (Type == GeomAbs_Line || Type == GeomAbs_Circle || Type == GeomAbs_Ellipse ||
2014       Type == GeomAbs_Hyperbola || Type == GeomAbs_Parabola) {
2015     return;
2016   }
2017   // Extension en tangence jusqu'au bord de la surface.
2018   Standard_Real   PMax = 1.e2;
2019   TopLoc_Location L;
2020   Handle(Geom_Surface) S = BRep_Tool::Surface(F,L);
2021   Standard_Real umin,umax,vmin,vmax;
2022 
2023   S->Bounds(umin,umax,vmin,vmax);
2024   umin = Max(umin,-PMax);vmin = Max(vmin,-PMax);
2025   umax = Min(umax, PMax);vmax = Min(vmax, PMax);
2026 
2027 
2028   Standard_Real f,l;
2029   Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E,F,f,l);
2030 
2031   //calcul point cible . ie point d'intersection du prolongement tangent et des bords.
2032   gp_Pnt2d P;
2033   gp_Vec2d Tang;
2034   C2d->D1(CE.FirstParameter(),P,Tang);
2035   Standard_Real tx,ty,tmin;
2036   tx = ty = Precision::Infinite();
2037   if (Abs(Tang.X()) > Precision::Confusion())
2038     tx = Min (Abs((umax - P.X())/Tang.X()), Abs((umin - P.X())/Tang.X()));
2039   if (Abs(Tang.Y()) > Precision::Confusion())
2040     ty = Min (Abs((vmax - P.Y())/Tang.Y()), Abs((vmin - P.Y())/Tang.Y()));
2041   tmin = Min (tx,ty);
2042   Tang = tmin*Tang;
2043   gp_Pnt2d  PF2d (P.X() - Tang.X(),P.Y() - Tang.Y());
2044 
2045   C2d->D1(CE.LastParameter(),P,Tang);
2046   tx = ty = Precision::Infinite();
2047   if (Abs(Tang.X()) > Precision::Confusion())
2048     tx = Min (Abs((umax - P.X())/Tang.X()), Abs((umin - P.X())/Tang.X()));
2049   if (Abs(Tang.Y()) > Precision::Confusion())
2050     ty = Min (Abs((vmax - P.Y())/Tang.Y()), Abs((vmin - P.Y())/Tang.Y()));
2051   tmin = Min (tx,ty);
2052   Tang = tmin*Tang;
2053   gp_Pnt2d  PL2d (P.X() + Tang.X(),P.Y() + Tang.Y());
2054 
2055   Handle(Geom_Curve) CC = GeomAPI::To3d(C2d,gp_Pln(gp::XOY()));
2056   gp_Pnt PF(PF2d.X(),PF2d.Y(),0.);
2057   gp_Pnt PL(PL2d.X(),PL2d.Y(),0.);
2058 
2059   Handle(Geom_BoundedCurve) ExtC = Handle(Geom_BoundedCurve)::DownCast(CC);
2060   if (ExtC.IsNull()) return;
2061 
2062   GeomLib::ExtendCurveToPoint(ExtC,PF,1,0);
2063   GeomLib::ExtendCurveToPoint(ExtC,PL,1,1);
2064 
2065   Handle(Geom2d_Curve) CNE2d = GeomAPI::To2d(ExtC,gp_Pln(gp::XOY()));
2066 
2067   //Construction de la nouvelle arrete;
2068   BRep_Builder B;
2069   B.MakeEdge(NE);
2070 //  B.UpdateEdge (NE,CNE2d,F,BRep_Tool::Tolerance(E));
2071   B.UpdateEdge (NE,CNE2d,EF,BRep_Tool::Tolerance(E));
2072   B.Range (NE,CNE2d->FirstParameter(), CNE2d->LastParameter());
2073   NE.Orientation(E.Orientation());
2074 #ifdef DRAW
2075   if (AffichExtent) {
2076     char name[256];
2077     sprintf (name,"F_%d",NbExtE);
2078     DBRep::Set(name,EF);
2079     sprintf (name,"OE_%d",NbExtE);
2080     DBRep::Set (name,E);
2081     sprintf (name,"ExtE_%d",NbExtE++);
2082     DBRep::Set(name,NE);
2083   }
2084 #endif
2085 }
2086 
2087 //=======================================================================
2088 //function : ProjectVertexOnEdge
2089 //purpose  :
2090 //=======================================================================
2091 
ProjectVertexOnEdge(TopoDS_Vertex & V,const TopoDS_Edge & E,Standard_Real TolConf)2092 static Standard_Boolean  ProjectVertexOnEdge(TopoDS_Vertex&     V,
2093 					     const TopoDS_Edge& E,
2094 					     Standard_Real      TolConf)
2095 {
2096 #ifdef DRAW
2097   if (AffichExtent) {
2098     DBRep::Set("V",V);
2099     DBRep::Set("E",E);
2100   }
2101 #endif
2102   BRep_Builder    B;
2103   Standard_Real   f,l;
2104   Standard_Real U = 0.;
2105   TopLoc_Location L;
2106   Standard_Boolean found = Standard_False;
2107 
2108   gp_Pnt            P = BRep_Tool::Pnt  (V);
2109   BRepAdaptor_Curve C = BRepAdaptor_Curve(E);
2110   f = C.FirstParameter(); l = C.LastParameter();
2111 
2112   if (V.Orientation() == TopAbs_FORWARD) {
2113     if (Abs(f) < Precision::Infinite()) {
2114       gp_Pnt PF = C.Value (f);
2115       if (PF.IsEqual(P,TolConf)) {
2116 	U = f;
2117 	found = Standard_True;
2118       }
2119     }
2120   }
2121   if (V.Orientation() == TopAbs_REVERSED) {
2122     if (!found && Abs(l) < Precision::Infinite()) {
2123       gp_Pnt PL = C.Value (l);
2124       if (PL.IsEqual(P,TolConf)) {
2125 	U = l;
2126 	found = Standard_True;
2127       }
2128     }
2129   }
2130   if (!found) {
2131     Extrema_ExtPC Proj(P,C);
2132     if (Proj.IsDone() && Proj.NbExt() > 0) {
2133       Standard_Real Dist2,Dist2Min = Proj.SquareDistance(1);
2134       U = Proj.Point(1).Parameter();
2135       for (Standard_Integer i = 2; i <= Proj.NbExt(); i++) {
2136 	Dist2 = Proj.SquareDistance(i);
2137 	if (Dist2 < Dist2Min) {
2138 	  Dist2Min = Dist2;
2139 	  U = Proj.Point(i).Parameter();
2140 	}
2141       }
2142       found = Standard_True;
2143     }
2144   }
2145 
2146 #ifdef OCCT_DEBUG
2147   if (AffichExtent) {
2148     Standard_Real Dist = P.Distance(C.Value(U));
2149     if (Dist > TolConf) {
2150       std::cout << " ProjectVertexOnEdge :distance vertex edge :"<<Dist<<std::endl;
2151     }
2152     if (U < f - Precision::Confusion() ||
2153 	U > l + Precision::Confusion()) {
2154       std::cout << " ProjectVertexOnEdge : hors borne :"<<std::endl;
2155       std::cout << " f = "<<f<<" l ="<<l<< " U ="<<U<<std::endl;
2156     }
2157   }
2158   if (!found) {
2159     std::cout <<"BRepOffset_Tool::ProjectVertexOnEdge Parameter no found"<<std::endl;
2160     if (Abs(f) < Precision::Infinite() &&
2161 	Abs(l) < Precision::Infinite()) {
2162 #ifdef DRAW
2163       DBRep::Set("E",E);
2164 #endif
2165     }
2166   }
2167 #endif
2168   if (found) {
2169     TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
2170     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
2171     aLocalShape = V.Oriented(TopAbs_INTERNAL);
2172 //    TopoDS_Edge EE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
2173     B.UpdateVertex(TopoDS::Vertex(aLocalShape),
2174 		   U,EE,BRep_Tool::Tolerance(E));
2175 
2176   }
2177   return found;
2178 }
2179 
2180 //=======================================================================
2181 //function : Inter2d
2182 //purpose  :
2183 //=======================================================================
2184 
Inter2d(const TopoDS_Face & F,const TopoDS_Edge & E1,const TopoDS_Edge & E2,TopTools_ListOfShape & LV,const Standard_Real TolConf)2185 void BRepOffset_Tool::Inter2d (const TopoDS_Face&    F,
2186 			       const TopoDS_Edge&    E1,
2187 			       const TopoDS_Edge&    E2,
2188 			       TopTools_ListOfShape& LV,
2189 			       const Standard_Real   TolConf)
2190 {
2191 #ifdef DRAW
2192   if (AffichExtent) {
2193     DBRep::Set("E1",E1);
2194     DBRep::Set("E2",E2);
2195     DBRep::Set("F",F);
2196   }
2197 #endif
2198   BRep_Builder  B;
2199   Standard_Real fl1[2],fl2[2];
2200   LV.Clear();
2201 
2202   // Si l edge a ete etendu les pcurves ne sont pas forcement
2203   // a jour.
2204   BuildPCurves(E1,F);
2205   BuildPCurves(E2,F);
2206 
2207 
2208   // Construction des curves 3d si elles n existent pas
2209   // utile pour coder correctement les parametres des vertex
2210   // d intersection sur les edges.
2211   //TopLoc_Location L;
2212   //Standard_Real   f,l;
2213   //Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(E1,L,f,l);
2214   //if (C3d1.IsNull()) {
2215   //  BRepLib::BuildCurve3d(E1,BRep_Tool::Tolerance(E1));
2216   //}
2217   //Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(E2,L,f,l);
2218   //if (C3d2.IsNull()) {
2219   //  BRepLib::BuildCurve3d(E2,BRep_Tool::Tolerance(E2));
2220   //}
2221 
2222   Standard_Integer NbPC1 = 1, NbPC2 = 1;
2223   if (BRep_Tool::IsClosed(E1,F)) NbPC1++;
2224   if (BRep_Tool::IsClosed(E2,F)) NbPC2++;
2225 
2226   Handle(Geom_Surface) S  = BRep_Tool::Surface(F);
2227   Handle(Geom2d_Curve) C1, C2;
2228   Standard_Boolean YaSol = Standard_False;
2229   Standard_Integer itry  = 0;
2230 
2231   while (!YaSol && itry < 2) {
2232     for ( Standard_Integer i = 1; i <= NbPC1 ; i++) {
2233 	TopoDS_Shape aLocalEdgeReversedE1 = E1.Reversed();
2234       if (i == 1)  C1 = BRep_Tool::CurveOnSurface(E1,F,fl1[0],fl1[1]);
2235       else         C1 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalEdgeReversedE1),
2236 						  F,fl1[0],fl1[1]);
2237 //      if (i == 1)  C1 = BRep_Tool::CurveOnSurface(E1,F,fl1[0],fl1[1]);
2238 //     else         C1 = BRep_Tool::CurveOnSurface(TopoDS::Edge(E1.Reversed()),
2239 //						  F,fl1[0],fl1[1]);
2240       for ( Standard_Integer j = 1; j <= NbPC2; j++ ) {
2241 	TopoDS_Shape aLocalEdge = E2.Reversed();
2242 	if (j == 1)  C2 = BRep_Tool::CurveOnSurface(E2,F,fl2[0],fl2[1]);
2243 	else         C2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalEdge),
2244 						    F,fl2[0],fl2[1]);
2245 //	if (j == 1)  C2 = BRep_Tool::CurveOnSurface(E2,F,fl2[0],fl2[1]);
2246 //	else         C2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(E2.Reversed()),
2247 //						    F,fl2[0],fl2[1]);
2248 #ifdef OCCT_DEBUG
2249 	if (C1.IsNull() || C2.IsNull()) {
2250 	  std::cout <<"Inter2d : Pas de pcurve"<<std::endl;
2251 #ifdef DRAW
2252 	  DBRep::Set("E1",E1);
2253 	  DBRep::Set("E2",E2);
2254 	  DBRep::Set("F",F);
2255 #endif
2256 	  return;
2257 	}
2258 #endif
2259 	Standard_Real    U1 = 0.,U2 = 0.;
2260 	gp_Pnt2d         P2d;
2261         Standard_Boolean aCurrentFind = Standard_False;
2262 	if (itry == 1) {
2263 	  fl1[0] = C1->FirstParameter(); fl1[1] = C1->LastParameter();
2264 	  fl2[0] = C2->FirstParameter(); fl2[1] = C2->LastParameter();
2265 	}
2266 	Geom2dAdaptor_Curve   AC1(C1,fl1[0],fl1[1]);
2267 	Geom2dAdaptor_Curve   AC2(C2,fl2[0],fl2[1]);
2268 
2269 	if (itry == 0) {
2270 	  gp_Pnt2d P1[2],P2[2];
2271 	  P1[0] = C1->Value(fl1[0]); P1[1] = C1->Value(fl1[1]);
2272 	  P2[0] = C2->Value(fl2[0]); P2[1] = C2->Value(fl2[1]);
2273 
2274 	  Standard_Integer i1 ;
2275 	  for ( i1 = 0; i1 < 2; i1++) {
2276 	    for (Standard_Integer i2 = 0; i2 < 2; i2++) {
2277 	      if (Abs(fl1[i1]) < Precision::Infinite() &&
2278 		  Abs(fl2[i2]) < Precision::Infinite()   ) {
2279 		if (P1[i1].IsEqual(P2[i2],TolConf)) {
2280 		  YaSol = Standard_True;
2281                   aCurrentFind = Standard_True;
2282 		  U1  = fl1[i1]; U2 = fl2[i2];
2283 		  P2d = C1->Value(U1);
2284 		}
2285 	      }
2286 	    }
2287 	  }
2288 	  if (!YaSol)
2289 	    for (i1 = 0; i1 < 2; i1++)
2290 	      {
2291 		Extrema_ExtPC2d extr( P1[i1], AC2 );
2292 		if (extr.IsDone() && extr.NbExt() > 0)
2293 		  {
2294 		    Standard_Real Dist2, Dist2Min = extr.SquareDistance(1);
2295 		    Standard_Integer IndexMin = 1;
2296 		    for (Standard_Integer ind = 2; ind <= extr.NbExt(); ind++)
2297 		      {
2298 			Dist2 = extr.SquareDistance(ind);
2299 			if (Dist2 < Dist2Min)
2300 			  {
2301 			    Dist2Min = Dist2;
2302 			    IndexMin = ind;
2303 			  }
2304 		      }
2305             if (Dist2Min <= Precision::SquareConfusion())
2306 		      {
2307                         YaSol = Standard_True;
2308                         aCurrentFind = Standard_True;
2309 			P2d = P1[i1];
2310 			U1 = fl1[i1];
2311 			U2 = (extr.Point(IndexMin)).Parameter();
2312 			break;
2313 		      }
2314 		  }
2315 	      }
2316 	  if (!YaSol)
2317 	    for (Standard_Integer i2 = 0; i2 < 2; i2++)
2318 	      {
2319 		Extrema_ExtPC2d extr( P2[i2], AC1 );
2320 		if (extr.IsDone() && extr.NbExt() > 0)
2321 		  {
2322 		    Standard_Real Dist2, Dist2Min = extr.SquareDistance(1);
2323 		    Standard_Integer IndexMin = 1;
2324 		    for (Standard_Integer ind = 2; ind <= extr.NbExt(); ind++)
2325 		      {
2326 			Dist2 = extr.SquareDistance(ind);
2327 			if (Dist2 < Dist2Min)
2328 			  {
2329 			    Dist2Min = Dist2;
2330 			    IndexMin = ind;
2331 			  }
2332 		      }
2333             if (Dist2Min <= Precision::SquareConfusion())
2334 		      {
2335 			YaSol = Standard_True;
2336                         aCurrentFind = Standard_True;
2337 			P2d = P2[i2];
2338 			U2 = fl2[i2];
2339 			U1 = (extr.Point(IndexMin)).Parameter();
2340 			break;
2341 		      }
2342 		  }
2343 	      }
2344 	}
2345 
2346 	if (!YaSol) {
2347 	  Geom2dInt_GInter Inter (AC1,AC2,TolConf,TolConf);
2348 
2349 	  if (!Inter.IsEmpty() && Inter.NbPoints() > 0) {
2350 		  YaSol = Standard_True;
2351                   aCurrentFind = Standard_True;
2352 	    U1  = Inter.Point(1).ParamOnFirst();
2353 	    U2  = Inter.Point(1).ParamOnSecond();
2354 	    P2d = Inter.Point(1).Value();
2355 	  }
2356 	  else if (!Inter.IsEmpty() && Inter.NbSegments() > 0) {
2357 	    		  YaSol = Standard_True;
2358                   aCurrentFind = Standard_True;
2359 	    IntRes2d_IntersectionSegment Seg = Inter.Segment(1);
2360 	    IntRes2d_IntersectionPoint IntP1 = Seg.FirstPoint();
2361 	    IntRes2d_IntersectionPoint IntP2 = Seg.LastPoint();
2362 	    Standard_Real U1on1 = IntP1.ParamOnFirst();
2363 	    Standard_Real U1on2 = IntP2.ParamOnFirst();
2364 	    Standard_Real U2on1 = IntP1.ParamOnSecond();
2365 	    Standard_Real U2on2 = IntP2.ParamOnSecond();
2366 #ifdef OCCT_DEBUG
2367 	    std::cout << " BRepOffset_Tool::Inter2d SEGMENT d intersection" << std::endl;
2368 	    std::cout << "     ===> Parametres sur Curve1 : ";
2369 	    std::cout << U1on1 << " " << U1on2 << std::endl;
2370 	    std::cout << "     ===> Parametres sur Curve2 : ";
2371 	    std::cout << U2on1 << " " << U2on2 << std::endl;
2372 #endif
2373 	    U1 = (U1on1 + U1on2)/2.;
2374 	    U2 = (U2on1 + U2on2)/2.;
2375 	    gp_Pnt2d P2d1 = C1->Value(U1);
2376 	    gp_Pnt2d P2d2 = C2->Value(U2);
2377 	    P2d.SetX( (P2d1.X() + P2d2.X()) / 2.);
2378 	    P2d.SetY( (P2d1.Y() + P2d2.Y()) / 2.);
2379 	  }
2380 	}
2381 	if (aCurrentFind) {
2382 	  gp_Pnt        P   = S->Value(P2d.X(),P2d.Y());
2383 	  TopoDS_Vertex V = BRepLib_MakeVertex(P);
2384 	  V.Orientation(TopAbs_INTERNAL);
2385 	  TopoDS_Shape aLocalEdgeOrientedE1 = E1.Oriented(TopAbs_FORWARD);
2386 	  B.UpdateVertex(V,U1,TopoDS::Edge(aLocalEdgeOrientedE1),TolConf);
2387           aLocalEdgeOrientedE1 = E2.Oriented(TopAbs_FORWARD);
2388 	  B.UpdateVertex(V,U2,TopoDS::Edge(aLocalEdgeOrientedE1),TolConf);
2389 //	  B.UpdateVertex(V,U1,TopoDS::Edge(E1.Oriented(TopAbs_FORWARD)),TolConf);
2390 //	  B.UpdateVertex(V,U2,TopoDS::Edge(E2.Oriented(TopAbs_FORWARD)),TolConf);
2391 	  LV.Append(V);
2392 	}
2393       }
2394     }
2395     itry++;
2396   }
2397 
2398   if (LV.Extent() > 1) {
2399     //------------------------------------------------
2400     // garde seulement les vertex les plus proches du
2401     //debut et de la fin.
2402     //------------------------------------------------
2403     TopTools_ListIteratorOfListOfShape it(LV);
2404     TopoDS_Vertex         VF,VL;
2405     Standard_Real         UMin =  Precision::Infinite();
2406     Standard_Real         UMax = -Precision::Infinite();
2407     Standard_Real         U;
2408 
2409     for ( ; it.More(); it.Next()) {
2410       TopoDS_Vertex CV = TopoDS::Vertex(it.Value());
2411       TopoDS_Shape aLocalEdge = E1.Oriented(TopAbs_FORWARD);
2412       U = BRep_Tool::Parameter(CV,TopoDS::Edge(aLocalEdge));
2413 //      U = BRep_Tool::Parameter(CV,TopoDS::Edge(E1.Oriented(TopAbs_FORWARD)));
2414       if ( U < UMin) {
2415 	VF = CV; UMin = U;
2416       }
2417       if ( U > UMax) {
2418 	VL = CV; UMax = U;
2419       }
2420     }
2421     LV.Clear();LV.Append(VF); LV.Append(VL);
2422   }
2423 
2424 #ifdef OCCT_DEBUG
2425   if (!YaSol) {
2426     std::cout <<"Inter2d : Pas de solution"<<std::endl;
2427 #ifdef DRAW
2428     DBRep::Set("E1",E1);
2429     DBRep::Set("E2",E2);
2430     DBRep::Set("F",F);
2431 #endif
2432   }
2433 #endif
2434 }
2435 
2436 //=======================================================================
2437 //function : SelectEdge
2438 //purpose  :
2439 //=======================================================================
2440 
SelectEdge(const TopoDS_Face &,const TopoDS_Face &,const TopoDS_Edge & E,TopTools_ListOfShape & LInt)2441 static void SelectEdge (const TopoDS_Face& /*F*/,
2442 			const TopoDS_Face& /*EF*/,
2443 			const TopoDS_Edge& E,
2444 			TopTools_ListOfShape& LInt)
2445 {
2446  //------------------------------------------------------------
2447   // detrompeur sur les intersections sur les faces periodiques
2448   //------------------------------------------------------------
2449    TopTools_ListIteratorOfListOfShape it(LInt);
2450   Standard_Real dU = 1.0e100;
2451   TopoDS_Edge   GE;
2452 
2453   Standard_Real Fst, Lst, tmp;
2454   BRep_Tool::Range(E, Fst, Lst);
2455   BRepAdaptor_Curve  Ad1(E);
2456 
2457   gp_Pnt PFirst = Ad1.Value( Fst );
2458   gp_Pnt PLast  = Ad1.Value( Lst );
2459 
2460   //----------------------------------------------------------------------
2461   // Selection de l edge qui couvre le plus le domaine de l edge initiale.
2462   //----------------------------------------------------------------------
2463   for (; it.More(); it.Next()) {
2464     const TopoDS_Edge& EI = TopoDS::Edge(it.Value());
2465 
2466     BRep_Tool::Range(EI, Fst, Lst);
2467     BRepAdaptor_Curve  Ad2(EI);
2468     gp_Pnt P1 = Ad2.Value(Fst);
2469     gp_Pnt P2 = Ad2.Value(Lst);
2470 
2471     tmp = P1.Distance(PFirst) + P2.Distance(PLast);
2472     if( tmp <= dU ) {
2473       dU = tmp;
2474       GE = EI;
2475     }
2476 
2477   }
2478   LInt.Clear();
2479   LInt.Append(GE);
2480 }
2481 
2482 
2483 //=======================================================================
2484 //function : Init
2485 //purpose  :
2486 //=======================================================================
2487 
MakeFace(const Handle (Geom_Surface)& S,const Standard_Real Um,const Standard_Real UM,const Standard_Real Vm,const Standard_Real VM,const Standard_Boolean uclosed,const Standard_Boolean vclosed,const Standard_Boolean isVminDegen,const Standard_Boolean isVmaxDegen,TopoDS_Face & F)2488 static void MakeFace(const Handle(Geom_Surface)& S,
2489 		     const Standard_Real Um,
2490 		     const Standard_Real UM,
2491 		     const Standard_Real Vm,
2492 		     const Standard_Real VM,
2493 		     const Standard_Boolean uclosed,
2494 		     const Standard_Boolean vclosed,
2495 		     const Standard_Boolean isVminDegen,
2496 		     const Standard_Boolean isVmaxDegen,
2497 		     TopoDS_Face&        F)
2498 {
2499   Standard_Real UMin = Um;
2500   Standard_Real UMax = UM;
2501   Standard_Real VMin = Vm;
2502   Standard_Real VMax = VM;
2503 
2504   // compute infinite flags
2505   Standard_Boolean umininf = Precision::IsNegativeInfinite(UMin);
2506   Standard_Boolean umaxinf = Precision::IsPositiveInfinite(UMax);
2507   Standard_Boolean vmininf = Precision::IsNegativeInfinite(VMin);
2508   Standard_Boolean vmaxinf = Precision::IsPositiveInfinite(VMax);
2509 
2510   // degenerated flags (for cones)
2511   Standard_Boolean vmindegen = isVminDegen, vmaxdegen = isVmaxDegen;
2512   Handle(Geom_Surface) theSurf = S;
2513   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
2514     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2515   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
2516     {
2517       Handle(Geom_ConicalSurface) ConicalS = Handle(Geom_ConicalSurface)::DownCast (theSurf);
2518       gp_Cone theCone = ConicalS->Cone();
2519       gp_Pnt theApex = theCone.Apex();
2520       Standard_Real Uapex, Vapex;
2521       ElSLib::Parameters( theCone, theApex, Uapex, Vapex );
2522       if (Abs(VMin - Vapex) <= Precision::Confusion())
2523 	vmindegen = Standard_True;
2524       if (Abs(VMax - Vapex) <= Precision::Confusion())
2525 	vmaxdegen = Standard_True;
2526     }
2527 
2528   // compute vertices
2529   BRep_Builder B;
2530   Standard_Real tol = Precision::Confusion();
2531 
2532   TopoDS_Vertex V00,V10,V11,V01;
2533 
2534   if (!umininf) {
2535     if (!vmininf) B.MakeVertex(V00,S->Value(UMin,VMin),tol);
2536     if (!vmaxinf) B.MakeVertex(V01,S->Value(UMin,VMax),tol);
2537   }
2538   if (!umaxinf) {
2539     if (!vmininf) B.MakeVertex(V10,S->Value(UMax,VMin),tol);
2540     if (!vmaxinf) B.MakeVertex(V11,S->Value(UMax,VMax),tol);
2541   }
2542 
2543   if (uclosed) {
2544     V10 = V00;
2545     V11 = V01;
2546   }
2547 
2548   if (vclosed) {
2549     V01 = V00;
2550     V11 = V10;
2551   }
2552 
2553   if (vmindegen)
2554     V10 = V00;
2555   if (vmaxdegen)
2556     V11 = V01;
2557 
2558   // make the lines
2559   Handle(Geom2d_Line) Lumin,Lumax,Lvmin,Lvmax;
2560   if (!umininf)
2561     Lumin = new Geom2d_Line(gp_Pnt2d(UMin,0),gp_Dir2d(0,1));
2562   if (!umaxinf)
2563     Lumax = new Geom2d_Line(gp_Pnt2d(UMax,0),gp_Dir2d(0,1));
2564   if (!vmininf)
2565     Lvmin = new Geom2d_Line(gp_Pnt2d(0,VMin),gp_Dir2d(1,0));
2566   if (!vmaxinf)
2567     Lvmax = new Geom2d_Line(gp_Pnt2d(0,VMax),gp_Dir2d(1,0));
2568 
2569   Handle(Geom_Curve) Cumin,Cumax,Cvmin,Cvmax;
2570   Standard_Real TolApex = 1.e-5;
2571   //Standard_Boolean hasiso = ! S->IsKind(STANDARD_TYPE(Geom_OffsetSurface));
2572   Standard_Boolean hasiso = S->IsKind(STANDARD_TYPE(Geom_ElementarySurface));
2573   if (hasiso) {
2574     if (!umininf)
2575       Cumin = S->UIso(UMin);
2576     if (!umaxinf)
2577       Cumax = S->UIso(UMax);
2578     if (!vmininf)
2579       {
2580 	Cvmin = S->VIso(VMin);
2581 	if (BRepOffset_Tool::Gabarit( Cvmin ) <= TolApex)
2582 	  vmindegen = Standard_True;
2583       }
2584     if (!vmaxinf)
2585       {
2586 	Cvmax = S->VIso(VMax);
2587 	if (BRepOffset_Tool::Gabarit( Cvmax ) <= TolApex)
2588 	  vmaxdegen = Standard_True;
2589       }
2590   }
2591 
2592   // make the face
2593   B.MakeFace(F,S,tol);
2594 
2595   // make the edges
2596   TopoDS_Edge eumin,eumax,evmin,evmax;
2597 
2598   if (!umininf) {
2599     if (hasiso)
2600       B.MakeEdge(eumin,Cumin,tol);
2601     else
2602       B.MakeEdge(eumin);
2603     if (uclosed)
2604       B.UpdateEdge(eumin,Lumax,Lumin,F,tol);
2605     else
2606       B.UpdateEdge(eumin,Lumin,F,tol);
2607     if (!vmininf) {
2608       V00.Orientation(TopAbs_FORWARD);
2609       B.Add(eumin,V00);
2610     }
2611     if (!vmaxinf) {
2612       V01.Orientation(TopAbs_REVERSED);
2613       B.Add(eumin,V01);
2614     }
2615     B.Range(eumin,VMin,VMax);
2616   }
2617 
2618   if (!umaxinf) {
2619     if (uclosed)
2620       eumax = eumin;
2621     else {
2622       if (hasiso)
2623 	B.MakeEdge(eumax,Cumax,tol);
2624       else
2625 	B.MakeEdge(eumax);
2626       B.UpdateEdge(eumax,Lumax,F,tol);
2627       if (!vmininf) {
2628 	V10.Orientation(TopAbs_FORWARD);
2629 	B.Add(eumax,V10);
2630       }
2631       if (!vmaxinf) {
2632 	V11.Orientation(TopAbs_REVERSED);
2633 	B.Add(eumax,V11);
2634       }
2635       B.Range(eumax,VMin,VMax);
2636     }
2637   }
2638 
2639   if (!vmininf) {
2640     if (hasiso && !vmindegen)
2641       B.MakeEdge(evmin,Cvmin,tol);
2642     else
2643       B.MakeEdge(evmin);
2644     if (vclosed)
2645       B.UpdateEdge(evmin,Lvmin,Lvmax,F,tol);
2646     else
2647       B.UpdateEdge(evmin,Lvmin,F,tol);
2648     if (!umininf) {
2649       V00.Orientation(TopAbs_FORWARD);
2650       B.Add(evmin,V00);
2651     }
2652     if (!umaxinf) {
2653       V10.Orientation(TopAbs_REVERSED);
2654       B.Add(evmin,V10);
2655     }
2656     B.Range(evmin,UMin,UMax);
2657     if (vmindegen)
2658       B.Degenerated(evmin, Standard_True);
2659   }
2660 
2661   if (!vmaxinf) {
2662     if (vclosed)
2663       evmax = evmin;
2664     else {
2665       if (hasiso && !vmaxdegen)
2666 	B.MakeEdge(evmax,Cvmax,tol);
2667       else
2668 	B.MakeEdge(evmax);
2669       B.UpdateEdge(evmax,Lvmax,F,tol);
2670       if (!umininf) {
2671 	V01.Orientation(TopAbs_FORWARD);
2672 	B.Add(evmax,V01);
2673       }
2674       if (!umaxinf) {
2675 	V11.Orientation(TopAbs_REVERSED);
2676 	B.Add(evmax,V11);
2677       }
2678       B.Range(evmax,UMin,UMax);
2679       if (vmaxdegen)
2680 	B.Degenerated(evmax, Standard_True);
2681     }
2682   }
2683 
2684   // make the wires and add them to the face
2685   eumin.Orientation(TopAbs_REVERSED);
2686   evmax.Orientation(TopAbs_REVERSED);
2687 
2688   TopoDS_Wire W;
2689 
2690   if (!umininf && !umaxinf && vmininf && vmaxinf) {
2691     // two wires in u
2692     B.MakeWire(W);
2693     B.Add(W,eumin);
2694     B.Add(F,W);
2695     B.MakeWire(W);
2696     B.Add(W,eumax);
2697     B.Add(F,W);
2698     F.Closed(uclosed);
2699   }
2700 
2701   else if (umininf && umaxinf && !vmininf && !vmaxinf) {
2702     // two wires in v
2703     B.MakeWire(W);
2704     B.Add(W,evmin);
2705     B.Add(F,W);
2706     B.MakeWire(W);
2707     B.Add(W,evmax);
2708     B.Add(F,W);
2709     F.Closed(vclosed);
2710   }
2711 
2712   else if (!umininf || !umaxinf || !vmininf || !vmaxinf) {
2713     // one wire
2714     B.MakeWire(W);
2715     if (!umininf) B.Add(W,eumin);
2716     if (!vmininf) B.Add(W,evmin);
2717     if (!umaxinf) B.Add(W,eumax);
2718     if (!vmaxinf) B.Add(W,evmax);
2719     B.Add(F,W);
2720     W.Closed(!umininf && !umaxinf && !vmininf && !vmaxinf);
2721     F.Closed(uclosed && vclosed);
2722   }
2723 }
2724 
2725 //=======================================================================
2726 //function : EnLargeGeometry
2727 //purpose  :
2728 //=======================================================================
2729 
EnlargeGeometry(Handle (Geom_Surface)& S,Standard_Real & U1,Standard_Real & U2,Standard_Real & V1,Standard_Real & V2,Standard_Boolean & IsV1degen,Standard_Boolean & IsV2degen,const Standard_Real uf1,const Standard_Real uf2,const Standard_Real vf1,const Standard_Real vf2,const Standard_Real coeff,const Standard_Boolean theGlobalEnlargeU,const Standard_Boolean theGlobalEnlargeVfirst,const Standard_Boolean theGlobalEnlargeVlast,const Standard_Real theLenBeforeUfirst,const Standard_Real theLenAfterUlast,const Standard_Real theLenBeforeVfirst,const Standard_Real theLenAfterVlast)2730 static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)&  S,
2731 					Standard_Real&         U1,
2732 					Standard_Real&         U2,
2733 					Standard_Real&         V1,
2734 					Standard_Real&         V2,
2735 					Standard_Boolean&      IsV1degen,
2736 					Standard_Boolean&      IsV2degen,
2737 					const Standard_Real    uf1,
2738 					const Standard_Real    uf2,
2739 					const Standard_Real    vf1,
2740 					const Standard_Real    vf2,
2741                                         const Standard_Real    coeff,
2742 					const Standard_Boolean theGlobalEnlargeU,
2743 					const Standard_Boolean theGlobalEnlargeVfirst,
2744 					const Standard_Boolean theGlobalEnlargeVlast,
2745                                         const Standard_Real    theLenBeforeUfirst,
2746                                         const Standard_Real    theLenAfterUlast,
2747                                         const Standard_Real    theLenBeforeVfirst,
2748                                         const Standard_Real    theLenAfterVlast)
2749 {
2750   const Standard_Real TolApex = 1.e-5;
2751 
2752   Standard_Boolean SurfaceChange = Standard_False;
2753   if ( S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
2754     Handle(Geom_Surface) BS = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2755     EnlargeGeometry(BS,U1,U2,V1,V2,IsV1degen,IsV2degen,
2756 		    uf1,uf2,vf1,vf2,coeff,
2757                     theGlobalEnlargeU, theGlobalEnlargeVfirst, theGlobalEnlargeVlast,
2758                     theLenBeforeUfirst, theLenAfterUlast, theLenBeforeVfirst, theLenAfterVlast);
2759     if (!theGlobalEnlargeVfirst)
2760       V1 = vf1;
2761     if (!theGlobalEnlargeVlast)
2762       V2 = vf2;
2763     if (!theGlobalEnlargeVfirst || !theGlobalEnlargeVlast)
2764       //Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->SetTrim( U1, U2, V1, V2 );
2765       S = new Geom_RectangularTrimmedSurface( BS, U1, U2, V1, V2 );
2766     else
2767       S = BS;
2768     SurfaceChange = Standard_True;
2769   }
2770   else if (S->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface)) {
2771     Handle(Geom_Surface) Surf = Handle(Geom_OffsetSurface)::DownCast (S)->BasisSurface();
2772     SurfaceChange = EnlargeGeometry(Surf,U1,U2,V1,V2,IsV1degen,IsV2degen,
2773 				    uf1,uf2,vf1,vf2,coeff,
2774                                     theGlobalEnlargeU, theGlobalEnlargeVfirst, theGlobalEnlargeVlast,
2775                                     theLenBeforeUfirst, theLenAfterUlast, theLenBeforeVfirst, theLenAfterVlast);
2776     Handle(Geom_OffsetSurface)::DownCast(S)->SetBasisSurface(Surf);
2777   }
2778   else if (S->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) ||
2779 	   S->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfRevolution))
2780   {
2781     Standard_Real du_first = 0., du_last = 0.,
2782       dv_first = 0., dv_last = 0.;
2783     Handle( Geom_Curve ) uiso, viso, uiso1, uiso2, viso1, viso2;
2784     Standard_Real u1, u2, v1, v2;
2785     Standard_Boolean enlargeU = theGlobalEnlargeU, enlargeV = Standard_True;
2786     Standard_Boolean enlargeUfirst = enlargeU, enlargeUlast = enlargeU;
2787     Standard_Boolean enlargeVfirst = theGlobalEnlargeVfirst, enlargeVlast = theGlobalEnlargeVlast;
2788     S->Bounds( u1, u2, v1, v2 );
2789     if (Precision::IsInfinite(u1) || Precision::IsInfinite(u2))
2790     {
2791       du_first = du_last = uf2-uf1;
2792       u1 = uf1 - du_first;
2793       u2 = uf2 + du_last;
2794       enlargeU = Standard_False;
2795     }
2796     else if (S->IsUClosed())
2797       enlargeU = Standard_False;
2798     else
2799     {
2800       viso = S->VIso( vf1 );
2801       GeomAdaptor_Curve gac( viso );
2802       Standard_Real du_default = GCPnts_AbscissaPoint::Length( gac ) * coeff;
2803       du_first = (theLenBeforeUfirst == -1)? du_default : theLenBeforeUfirst;
2804       du_last  = (theLenAfterUlast == -1)? du_default : theLenAfterUlast;
2805       uiso1 = S->UIso( uf1 );
2806       uiso2 = S->UIso( uf2 );
2807       if (BRepOffset_Tool::Gabarit( uiso1 ) <= TolApex)
2808         enlargeUfirst = Standard_False;
2809       if (BRepOffset_Tool::Gabarit( uiso2 ) <= TolApex)
2810         enlargeUlast = Standard_False;
2811     }
2812     if (Precision::IsInfinite(v1) || Precision::IsInfinite(v2))
2813     {
2814       dv_first = dv_last = vf2-vf1;
2815       v1 = vf1 - dv_first;
2816       v2 = vf2 + dv_last;
2817       enlargeV = Standard_False;
2818     }
2819     else if (S->IsVClosed())
2820       enlargeV = Standard_False;
2821     else
2822     {
2823       uiso = S->UIso( uf1 );
2824       GeomAdaptor_Curve gac( uiso );
2825       Standard_Real dv_default = GCPnts_AbscissaPoint::Length( gac ) * coeff;
2826       dv_first = (theLenBeforeVfirst == -1)? dv_default : theLenBeforeVfirst;
2827       dv_last  = (theLenAfterVlast == -1)? dv_default : theLenAfterVlast;
2828       viso1 = S->VIso( vf1 );
2829       viso2 = S->VIso( vf2 );
2830       if (BRepOffset_Tool::Gabarit( viso1 ) <= TolApex)
2831       {
2832         enlargeVfirst = Standard_False;
2833         IsV1degen = Standard_True;
2834       }
2835       if (BRepOffset_Tool::Gabarit( viso2 ) <= TolApex)
2836       {
2837         enlargeVlast = Standard_False;
2838         IsV2degen = Standard_True;
2839       }
2840     }
2841     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface( S, u1, u2, v1, v2 );
2842     if (enlargeU)
2843     {
2844       if (enlargeUfirst && du_first != 0.)
2845         GeomLib::ExtendSurfByLength (aSurf, du_first, 1, Standard_True, Standard_False);
2846       if (enlargeUlast && du_last != 0.)
2847         GeomLib::ExtendSurfByLength (aSurf, du_last, 1, Standard_True, Standard_True);
2848     }
2849     if (enlargeV)
2850     {
2851       if (enlargeVfirst && dv_first != 0.)
2852         GeomLib::ExtendSurfByLength (aSurf, dv_first, 1, Standard_False, Standard_False);
2853       if (enlargeVlast && dv_last != 0.)
2854         GeomLib::ExtendSurfByLength (aSurf, dv_last, 1, Standard_False, Standard_True);
2855     }
2856     S = aSurf;
2857     S->Bounds( U1, U2, V1, V2 );
2858     SurfaceChange = Standard_True;
2859   }
2860   else if (S->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
2861 	   S->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface))
2862   {
2863     Standard_Boolean enlargeU = theGlobalEnlargeU, enlargeV = Standard_True;
2864     Standard_Boolean enlargeUfirst = enlargeU, enlargeUlast = enlargeU;
2865     Standard_Boolean enlargeVfirst = theGlobalEnlargeVfirst, enlargeVlast = theGlobalEnlargeVlast;
2866     if (S->IsUClosed())
2867       enlargeU = Standard_False;
2868     if (S->IsVClosed())
2869       enlargeV = Standard_False;
2870 
2871     Standard_Real duf = uf2-uf1, dvf = vf2-vf1;
2872     Standard_Real u1, u2, v1, v2;
2873     S->Bounds( u1, u2, v1, v2 );
2874 
2875     Standard_Real du_first = 0., du_last = 0.,
2876       dv_first = 0., dv_last = 0.;
2877     Handle( Geom_Curve ) uiso1, uiso2, viso1, viso2;
2878     Standard_Real gabarit_uiso1, gabarit_uiso2, gabarit_viso1, gabarit_viso2;
2879 
2880     uiso1 = S->UIso( u1 );
2881     uiso2 = S->UIso( u2 );
2882     viso1 = S->VIso( v1 );
2883     viso2 = S->VIso( v2 );
2884     gabarit_uiso1 = BRepOffset_Tool::Gabarit( uiso1 );
2885     gabarit_uiso2 = BRepOffset_Tool::Gabarit( uiso2 );
2886     gabarit_viso1 = BRepOffset_Tool::Gabarit( viso1 );
2887     gabarit_viso2 = BRepOffset_Tool::Gabarit( viso2 );
2888     if (gabarit_viso1 <= TolApex ||
2889         gabarit_viso2 <= TolApex)
2890       enlargeU = Standard_False;
2891     if (gabarit_uiso1 <= TolApex ||
2892         gabarit_uiso2 <= TolApex)
2893       enlargeV = Standard_False;
2894 
2895     GeomAdaptor_Curve gac;
2896     if (enlargeU)
2897     {
2898       gac.Load( viso1 );
2899       Standard_Real du_default = GCPnts_AbscissaPoint::Length( gac ) * coeff;
2900       du_first = (theLenBeforeUfirst == -1)? du_default : theLenBeforeUfirst;
2901       du_last  = (theLenAfterUlast == -1)? du_default : theLenAfterUlast;
2902       if (gabarit_uiso1 <= TolApex)
2903         enlargeUfirst = Standard_False;
2904       if (gabarit_uiso2 <= TolApex)
2905         enlargeUlast = Standard_False;
2906     }
2907     if (enlargeV)
2908     {
2909       gac.Load( uiso1 );
2910       Standard_Real dv_default = GCPnts_AbscissaPoint::Length( gac ) * coeff;
2911       dv_first = (theLenBeforeVfirst == -1)? dv_default : theLenBeforeVfirst;
2912       dv_last  = (theLenAfterVlast == -1)? dv_default : theLenAfterVlast;
2913       if (gabarit_viso1 <= TolApex)
2914       {
2915         enlargeVfirst = Standard_False;
2916         IsV1degen = Standard_True;
2917       }
2918       if (gabarit_viso2 <= TolApex)
2919       {
2920         enlargeVlast = Standard_False;
2921         IsV2degen = Standard_True;
2922       }
2923     }
2924 
2925     Handle(Geom_BoundedSurface) aSurf = Handle(Geom_BoundedSurface)::DownCast (S);
2926     if (enlargeU)
2927     {
2928       if (enlargeUfirst && uf1-u1 < duf && du_first != 0.)
2929         GeomLib::ExtendSurfByLength (aSurf, du_first, 1, Standard_True, Standard_False);
2930       if (enlargeUlast && u2-uf2 < duf && du_last != 0.)
2931         GeomLib::ExtendSurfByLength (aSurf, du_last, 1, Standard_True, Standard_True);
2932     }
2933     if (enlargeV)
2934     {
2935       if (enlargeVfirst && vf1-v1 < dvf && dv_first != 0.)
2936         GeomLib::ExtendSurfByLength (aSurf, dv_first, 1, Standard_False, Standard_False);
2937       if (enlargeVlast && v2-vf2 < dvf && dv_last != 0.)
2938         GeomLib::ExtendSurfByLength (aSurf, dv_last, 1, Standard_False, Standard_True);
2939     }
2940     S = aSurf;
2941 
2942     S->Bounds( U1, U2, V1, V2 );
2943     SurfaceChange = Standard_True;
2944   }
2945   else {
2946     Standard_Real UU1,UU2,VV1,VV2;
2947     S->Bounds(UU1,UU2,VV1,VV2);
2948     // Pas d extension au dela des bornes de la surface.
2949     U1 = Max(UU1,U1);
2950     V1 = Max(VV1,V1);
2951     U2 = Min(UU2,U2);
2952     V2 = Min(VV2,V2);
2953   }
2954   return SurfaceChange;
2955 }
2956 
2957 //=======================================================================
2958 //function : UpDatePCurve
2959 //purpose  :  Mise a jour des pcurves de F sur la surface de de BF.
2960 //            F and BF has to be FORWARD,
2961 //=======================================================================
2962 
UpdatePCurves(const TopoDS_Face & F,TopoDS_Face & BF)2963 static void UpdatePCurves (const TopoDS_Face& F,
2964 			         TopoDS_Face& BF)
2965 {
2966   Standard_Real   f,l;
2967   Standard_Integer i;
2968   BRep_Builder    B;
2969   TopTools_IndexedMapOfShape Emap;
2970   Handle(Geom2d_Curve) NullPCurve;
2971 
2972   TopExp::MapShapes( F, TopAbs_EDGE, Emap );
2973 
2974   for (i = 1; i <= Emap.Extent(); i++)
2975     {
2976       TopoDS_Edge CE = TopoDS::Edge( Emap(i) );
2977       CE.Orientation( TopAbs_FORWARD );
2978       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface( CE, F, f, l );
2979       if (!C2.IsNull())
2980 	{
2981 	  if (BRep_Tool::IsClosed( CE, F ))
2982 	    {
2983 	      CE.Reverse();
2984 	      Handle(Geom2d_Curve) C2R = BRep_Tool::CurveOnSurface( CE, F, f, l );
2985 	      B.UpdateEdge( CE, NullPCurve, NullPCurve, F, BRep_Tool::Tolerance(CE) );
2986 	      B.UpdateEdge( CE, C2, C2R, BF, BRep_Tool::Tolerance(CE) );
2987 	    }
2988 	  else
2989 	    {
2990 	      B.UpdateEdge( CE, NullPCurve, F, BRep_Tool::Tolerance(CE) );
2991 	      B.UpdateEdge( CE, C2, BF, BRep_Tool::Tolerance(CE) );
2992 	    }
2993 
2994 	  B.Range(CE,f,l);
2995 	}
2996     }
2997 }
2998 
2999 //=======================================================================
3000 //function :CompactUVBounds
3001 //purpose  :
3002 //=======================================================================
3003 
CompactUVBounds(const TopoDS_Face & F,Standard_Real & UMin,Standard_Real & UMax,Standard_Real & VMin,Standard_Real & VMax)3004 static void CompactUVBounds (const TopoDS_Face& F,
3005 				 Standard_Real& UMin,
3006 				 Standard_Real& UMax,
3007 				 Standard_Real& VMin,
3008 				 Standard_Real& VMax)
3009 {
3010   // Calcul serre pour que les bornes ne couvrent pas plus d une periode
3011   Standard_Real U1,U2;
3012   Standard_Real N = 33;
3013   Bnd_Box2d B;
3014 
3015   TopExp_Explorer exp;
3016   for (exp.Init(F, TopAbs_EDGE); exp.More(); exp.Next()) {
3017     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3018     BRepAdaptor_Curve2d C(E,F);
3019     BRep_Tool::Range(E,U1,U2);
3020     gp_Pnt2d P;
3021     Standard_Real U  = U1;
3022     Standard_Real DU = (U2-U1)/(N-1);
3023     for (Standard_Integer j=1;j<N;j++) {
3024       C.D0(U,P);
3025       U+=DU;
3026       B.Add(P);
3027     }
3028     C.D0(U2,P);
3029     B.Add(P);
3030   }
3031 
3032   if (!B.IsVoid())
3033     B.Get(UMin,VMin,UMax,VMax);
3034   else
3035     BRep_Tool::Surface(F)->Bounds (UMin, UMax, VMin, VMax);
3036 }
3037 
3038 //=======================================================================
3039 //function : CheckBounds
3040 //purpose  :
3041 //=======================================================================
3042 
CheckBounds(const TopoDS_Face & F,const BRepOffset_Analyse & Analyse,Standard_Boolean & enlargeU,Standard_Boolean & enlargeVfirst,Standard_Boolean & enlargeVlast)3043 void BRepOffset_Tool::CheckBounds(const TopoDS_Face& F,
3044 				  const BRepOffset_Analyse& Analyse,
3045 				  Standard_Boolean& enlargeU,
3046 				  Standard_Boolean& enlargeVfirst,
3047 				  Standard_Boolean& enlargeVlast)
3048 {
3049   enlargeU = Standard_True;
3050   enlargeVfirst = Standard_True; enlargeVlast = Standard_True;
3051 
3052   Standard_Integer Ubound = 0, Vbound = 0;
3053   Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
3054   Standard_Real Vfirst = RealLast(), Vlast = RealFirst();
3055 
3056   Standard_Real UF1,UF2,VF1,VF2;
3057   CompactUVBounds(F,UF1,UF2,VF1,VF2);
3058 
3059   Handle(Geom_Surface) theSurf = BRep_Tool::Surface(F);
3060   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
3061     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (theSurf)->BasisSurface();
3062 
3063   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) ||
3064       theSurf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfRevolution) ||
3065       theSurf->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
3066       theSurf->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface))
3067     {
3068       TopExp_Explorer Explo(F, TopAbs_EDGE);
3069       for (; Explo.More(); Explo.Next())
3070 	{
3071 	  const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
3072 	  const BRepOffset_ListOfInterval& L = Analyse.Type(anEdge);
3073 	  if (!L.IsEmpty() || BRep_Tool::Degenerated(anEdge))
3074 	    {
3075 	      ChFiDS_TypeOfConcavity OT = L.First().Type();
3076 	      if (OT == ChFiDS_Tangential || BRep_Tool::Degenerated(anEdge))
3077 		{
3078 		  Standard_Real fpar, lpar;
3079 		  Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, F, fpar, lpar);
3080 		  if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
3081 		    aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (aCurve)->BasisCurve();
3082 
3083 		  Handle(Geom2d_Line) theLine;
3084 		  if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_Line))
3085 		    theLine = Handle(Geom2d_Line)::DownCast (aCurve);
3086 		  else if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_BezierCurve) ||
3087 			   aCurve->DynamicType() == STANDARD_TYPE(Geom2d_BSplineCurve))
3088 		    {
3089 		      Standard_Real newFpar, newLpar, deviation;
3090 		      theLine = ShapeCustom_Curve2d::ConvertToLine2d(aCurve, fpar, lpar, Precision::Confusion(),
3091 								     newFpar, newLpar, deviation);
3092 		    }
3093 
3094 		  if (!theLine.IsNull())
3095 		    {
3096 		      gp_Dir2d theDir = theLine->Direction();
3097 		      if (theDir.IsParallel( gp::DX2d(), Precision::Angular() ))
3098 			{
3099 			  Vbound++;
3100 			  if (BRep_Tool::Degenerated(anEdge))
3101 			    {
3102 			      if (Abs(theLine->Location().Y() - VF1) <= Precision::Confusion())
3103 				enlargeVfirst = Standard_False;
3104 			      else //theLine->Location().Y() is near VF2
3105 				enlargeVlast  = Standard_False;
3106 			    }
3107 			  else
3108 			    {
3109 			      if (theLine->Location().Y() < Vfirst)
3110 				Vfirst = theLine->Location().Y();
3111 			      if (theLine->Location().Y() > Vlast)
3112 				Vlast  = theLine->Location().Y();
3113 			    }
3114 			}
3115 		      else if (theDir.IsParallel( gp::DY2d(), Precision::Angular() ))
3116 			{
3117 			  Ubound++;
3118 			  if (theLine->Location().X() < Ufirst)
3119 			    Ufirst = theLine->Location().X();
3120 			  if (theLine->Location().X() > Ulast)
3121 			    Ulast  = theLine->Location().X();
3122 			}
3123 		    }
3124 		}
3125 	    }
3126 	}
3127     }
3128 
3129   if (Ubound >= 2 || Vbound >= 2)
3130     {
3131       if (Ubound >= 2 &&
3132 	  Abs(UF1-Ufirst) <= Precision::Confusion() &&
3133 	  Abs(UF2-Ulast)  <= Precision::Confusion())
3134 	enlargeU = Standard_False;
3135       if (Vbound >= 2 &&
3136 	  Abs(VF1-Vfirst) <= Precision::Confusion() &&
3137 	  Abs(VF2-Vlast)  <= Precision::Confusion())
3138 	{
3139 	  enlargeVfirst = Standard_False;
3140 	  enlargeVlast  = Standard_False;
3141 	}
3142     }
3143 }
3144 
3145 //=======================================================================
3146 //function : EnLargeFace
3147 //purpose  :
3148 //=======================================================================
3149 
EnLargeFace(const TopoDS_Face & F,TopoDS_Face & BF,const Standard_Boolean CanExtentSurface,const Standard_Boolean UpdatePCurve,const Standard_Boolean theEnlargeU,const Standard_Boolean theEnlargeVfirst,const Standard_Boolean theEnlargeVlast,const Standard_Integer theExtensionMode,const Standard_Real theLenBeforeUfirst,const Standard_Real theLenAfterUlast,const Standard_Real theLenBeforeVfirst,const Standard_Real theLenAfterVlast)3150 Standard_Boolean BRepOffset_Tool::EnLargeFace
3151 (const TopoDS_Face&       F,
3152  TopoDS_Face&             BF,
3153  const Standard_Boolean   CanExtentSurface,
3154  const Standard_Boolean   UpdatePCurve,
3155  const Standard_Boolean   theEnlargeU,
3156  const Standard_Boolean   theEnlargeVfirst,
3157  const Standard_Boolean   theEnlargeVlast,
3158  const Standard_Integer   theExtensionMode,
3159  const Standard_Real      theLenBeforeUfirst,
3160  const Standard_Real      theLenAfterUlast,
3161  const Standard_Real      theLenBeforeVfirst,
3162  const Standard_Real      theLenAfterVlast)
3163 {
3164   //---------------------------
3165   // extension de la geometrie.
3166   //---------------------------
3167   TopLoc_Location       L;
3168   Handle (Geom_Surface) S = BRep_Tool::Surface(F,L);
3169   Standard_Real         UU1,VV1,UU2,VV2;
3170   Standard_Boolean      uperiodic = Standard_False, vperiodic = Standard_False;
3171   Standard_Boolean      isVV1degen = Standard_False, isVV2degen = Standard_False;
3172   Standard_Real         US1,VS1,US2,VS2;
3173   Standard_Real         UF1,VF1,UF2,VF2;
3174   Standard_Boolean      SurfaceChange = Standard_False;
3175 
3176   if (S->IsUPeriodic() || S->IsVPeriodic()) {
3177     // Calcul serre pour que les bornes ne couvre pas plus d une periode
3178     CompactUVBounds(F,UF1,UF2,VF1,VF2);
3179   }
3180   else {
3181     BRepTools::UVBounds(F,UF1,UF2,VF1,VF2);
3182   }
3183 
3184   S->Bounds            (US1,US2,VS1,VS2);
3185   Standard_Real coeff;
3186   if (theExtensionMode == 1)
3187   {
3188     UU1 = VV1 = - TheInfini;
3189     UU2 = VV2 =   TheInfini;
3190     coeff = 0.25;
3191   }
3192   else
3193   {
3194     Standard_Real FaceDU = UF2 - UF1;
3195     Standard_Real FaceDV = VF2 - VF1;
3196     UU1 = UF1 - 10*FaceDU;
3197     UU2 = UF2 + 10*FaceDU;
3198     VV1 = VF1 - 10*FaceDV;
3199     VV2 = VF2 + 10*FaceDV;
3200     coeff = 1.;
3201   }
3202 
3203   if (CanExtentSurface) {
3204     SurfaceChange = EnlargeGeometry(S, UU1, UU2, VV1, VV2, isVV1degen, isVV2degen, UF1, UF2, VF1, VF2, coeff,
3205                                     theEnlargeU, theEnlargeVfirst, theEnlargeVlast,
3206                                     theLenBeforeUfirst, theLenAfterUlast, theLenBeforeVfirst, theLenAfterVlast);
3207   }
3208   else {
3209     UU1 = Max(US1,UU1); UU2 = Min(UU2,US2);
3210     VV1 = Max(VS1,VV1); VV2 = Min(VS2,VV2);
3211   }
3212 
3213   if (S->IsUPeriodic()) {
3214     uperiodic = Standard_True;
3215     Standard_Real    Period = S->UPeriod();
3216     Standard_Real    Delta  = Period - (UF2 - UF1);
3217     Standard_Real    alpha  = 0.1;
3218     UU1 = UF1 - alpha*Delta; UU2 = UF2 + alpha*Delta;
3219     if ((UU2 - UU1) > Period) {
3220       UU2 = UU1 + Period;
3221     }
3222   }
3223   if (S->IsVPeriodic()) {
3224     vperiodic = Standard_True;
3225     Standard_Real    Period = S->VPeriod();
3226     Standard_Real    Delta  = Period - (VF2 - VF1);
3227     Standard_Real    alpha  = 0.1;
3228     VV1 = VF1 - alpha*Delta; VV2 = VF2 + alpha*Delta;
3229     if ((VV2 - VV1) > Period) {
3230       VV2 = VV1 + Period;
3231     }
3232   }
3233 
3234   //Special treatment for conical surfaces
3235   Handle(Geom_Surface) theSurf = S;
3236   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
3237     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
3238   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
3239     {
3240       Handle(Geom_ConicalSurface) ConicalS = Handle(Geom_ConicalSurface)::DownCast (theSurf);
3241       gp_Cone theCone = ConicalS->Cone();
3242       gp_Pnt theApex = theCone.Apex();
3243       Standard_Real Uapex, Vapex;
3244       ElSLib::Parameters( theCone, theApex, Uapex, Vapex );
3245       if (VV1 < Vapex && Vapex < VV2)
3246 	{
3247 	  //consider that VF1 and VF2 are on the same side from apex
3248 	  Standard_Real TolApex = 1.e-5;
3249 	  if (Vapex - VF1 >= TolApex ||
3250 	      Vapex - VF2 >= TolApex)   //if (VF1 < Vapex || VF2 < Vapex)
3251 	    VV2 = Vapex;
3252 	  else
3253 	    VV1 = Vapex;
3254 	}
3255     }
3256 
3257   if (!theEnlargeU)
3258     {
3259       UU1 = UF1; UU2 = UF2;
3260     }
3261   if (!theEnlargeVfirst)
3262     VV1 = VF1;
3263   if (!theEnlargeVlast)
3264     VV2 = VF2;
3265 
3266   //Detect closedness in U and V directions
3267   Standard_Boolean uclosed = Standard_False, vclosed = Standard_False;
3268   BRepTools::DetectClosedness(F, uclosed, vclosed);
3269   if (uclosed && !uperiodic &&
3270       (theLenBeforeUfirst != 0. || theLenAfterUlast != 0.))
3271     uclosed = Standard_False;
3272   if (vclosed && !vperiodic &&
3273       (theLenBeforeVfirst != 0. && theLenAfterVlast != 0.))
3274     vclosed = Standard_False;
3275 
3276   MakeFace(S,UU1,UU2,VV1,VV2,uclosed,vclosed,isVV1degen,isVV2degen,BF);
3277   BF.Location(L);
3278 /*
3279   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
3280     BRep_Builder B;
3281     //----------------------------------------------------------------
3282     // utile pour les bouchons on ne doit pas changer leur geometrie.
3283     // (Ce que fait BRepLib_MakeFace si S est restreinte).
3284     // On remet S et on update les pcurves.
3285     //----------------------------------------------------------------
3286     TopExp_Explorer exp;
3287     exp.Init(BF,TopAbs_EDGE);
3288     Standard_Real f=0.,l=0.;
3289     for (; exp.More(); exp.Next()) {
3290       TopoDS_Edge   CE  = TopoDS::Edge(exp.Current());
3291       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(CE,BF,f,l);
3292       B.UpdateEdge (CE,C2,S,L,BRep_Tool::Tolerance(CE));
3293     }
3294     B.UpdateFace(BF,S,L,BRep_Tool::Tolerance(F));
3295   }
3296 */
3297   if (SurfaceChange && UpdatePCurve) {
3298     TopoDS_Shape aLocalFace = F.Oriented(TopAbs_FORWARD);
3299     UpdatePCurves(TopoDS::Face(aLocalFace),BF);
3300     //UpdatePCurves(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),BF);
3301     BRep_Builder BB;
3302     BB.UpdateFace( F, S, L, BRep_Tool::Tolerance(F) );
3303   }
3304 
3305   BF.Orientation(F.Orientation());
3306   return SurfaceChange;
3307 }
3308 
3309 //=======================================================================
3310 //function : TryParameter
3311 //purpose  :
3312 //=======================================================================
3313 
TryParameter(const TopoDS_Edge & OE,TopoDS_Vertex & V,const TopoDS_Edge & NE,Standard_Real TolConf)3314 static Standard_Boolean TryParameter (const TopoDS_Edge& OE,
3315 				      TopoDS_Vertex&     V,
3316 				      const TopoDS_Edge& NE,
3317 				      Standard_Real      TolConf)
3318 {
3319   BRepAdaptor_Curve OC(OE);
3320   BRepAdaptor_Curve NC(NE);
3321   Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter();
3322   Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter();
3323   Standard_Real U = 0.;
3324   gp_Pnt           P  = BRep_Tool::Pnt(V);
3325   Standard_Boolean OK = Standard_False;
3326 
3327   if (P.Distance(OC.Value(Of)) < TolConf) {
3328     if (Of > Nf && Of < Nl  && P.Distance(NC.Value(Of)) < TolConf) {
3329       OK = Standard_True;
3330       U    = Of;
3331     }
3332   }
3333   if (P.Distance(OC.Value(Ol)) < TolConf) {
3334     if (Ol > Nf && Ol < Nl  && P.Distance(NC.Value(Ol)) < TolConf) {
3335       OK = Standard_True;
3336       U    = Ol;
3337     }
3338   }
3339   if (OK) {
3340     BRep_Builder B;
3341     TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD);
3342     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
3343 //    TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD));
3344     aLocalShape = V.Oriented(TopAbs_INTERNAL);
3345     B.UpdateVertex(TopoDS::Vertex(aLocalShape),
3346 		   U,NE,BRep_Tool::Tolerance(NE));
3347 //    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
3348 //		   U,NE,BRep_Tool::Tolerance(NE));
3349   }
3350   return OK;
3351 }
3352 
3353 //=======================================================================
3354 //function :
3355 //purpose  :
3356 //=======================================================================
3357 
MapVertexEdges(const TopoDS_Shape & S,TopTools_DataMapOfShapeListOfShape & MEV)3358 void BRepOffset_Tool::MapVertexEdges (const TopoDS_Shape& S,
3359 				      TopTools_DataMapOfShapeListOfShape& MEV)
3360 {
3361   TopExp_Explorer      exp;
3362   exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
3363   TopTools_MapOfShape  DejaVu;
3364   for ( ; exp.More(); exp.Next()) {
3365     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3366     if (DejaVu.Add(E)) {
3367       TopoDS_Vertex     V1,V2;
3368       TopExp::Vertices (E,V1,V2);
3369       if (!MEV.IsBound(V1)) {
3370 	TopTools_ListOfShape empty;
3371 	MEV.Bind(V1,empty);
3372       }
3373       MEV(V1).Append(E);
3374       if (!V1.IsSame(V2)) {
3375 	if (!MEV.IsBound(V2)) {
3376 	  TopTools_ListOfShape empty;
3377 	  MEV.Bind(V2,empty);
3378 	}
3379 	MEV(V2).Append(E);
3380       }
3381     }
3382   }
3383 }
3384 
3385 //=======================================================================
3386 //function :
3387 //purpose  :
3388 //=======================================================================
3389 
BuildNeighbour(const TopoDS_Wire & W,const TopoDS_Face & F,TopTools_DataMapOfShapeShape & NOnV1,TopTools_DataMapOfShapeShape & NOnV2)3390 void BRepOffset_Tool::BuildNeighbour (const TopoDS_Wire& W,
3391 				      const TopoDS_Face& F,
3392 				      TopTools_DataMapOfShapeShape& NOnV1,
3393 				      TopTools_DataMapOfShapeShape& NOnV2)
3394 {
3395   TopoDS_Vertex V1,V2,VP1,VP2,FV1,FV2;
3396   TopoDS_Edge   CurE,FirstE,PrecE;
3397   BRepTools_WireExplorer         wexp;
3398 
3399   TopoDS_Shape aLocalFace = F.Oriented(TopAbs_FORWARD);
3400   TopoDS_Shape aLocalWire = W.Oriented(TopAbs_FORWARD);
3401   wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
3402 //  wexp.Init(TopoDS::Wire(W.Oriented(TopAbs_FORWARD)),
3403 //	    TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
3404   CurE = FirstE = PrecE = wexp.Current();
3405   TopExp::Vertices(CurE,V1,V2);
3406   FV1 = VP1 = V1; FV2 = VP2 = V2;
3407   wexp.Next();
3408   while (wexp.More()) {
3409     CurE = wexp.Current();
3410     TopExp::Vertices(CurE,V1,V2);
3411     if (V1.IsSame(VP1)) { NOnV1.Bind(PrecE,CurE); NOnV1.Bind(CurE,PrecE);}
3412     if (V1.IsSame(VP2)) { NOnV2.Bind(PrecE,CurE); NOnV1.Bind(CurE,PrecE);}
3413     if (V2.IsSame(VP1)) { NOnV1.Bind(PrecE,CurE); NOnV2.Bind(CurE,PrecE);}
3414     if (V2.IsSame(VP2)) { NOnV2.Bind(PrecE,CurE); NOnV2.Bind(CurE,PrecE);}
3415     PrecE = CurE;
3416     VP1 = V1; VP2 = V2;
3417     wexp.Next();
3418   }
3419   if (V1.IsSame(FV1)) { NOnV1.Bind(FirstE,CurE); NOnV1.Bind(CurE,FirstE);}
3420   if (V1.IsSame(FV2)) { NOnV2.Bind(FirstE,CurE); NOnV1.Bind(CurE,FirstE);}
3421   if (V2.IsSame(FV1)) { NOnV1.Bind(FirstE,CurE); NOnV2.Bind(CurE,FirstE);}
3422   if (V2.IsSame(FV2)) { NOnV2.Bind(FirstE,CurE); NOnV2.Bind(CurE,FirstE);}
3423 }
3424 
3425 //=======================================================================
3426 //function : ExtentFace
3427 //purpose  :
3428 //=======================================================================
3429 
ExtentFace(const TopoDS_Face & F,TopTools_DataMapOfShapeShape & ConstShapes,TopTools_DataMapOfShapeShape & ToBuild,const TopAbs_State Side,const Standard_Real TolConf,TopoDS_Face & NF)3430 void BRepOffset_Tool::ExtentFace (const TopoDS_Face&            F,
3431 				  TopTools_DataMapOfShapeShape& ConstShapes,
3432 				  TopTools_DataMapOfShapeShape& ToBuild,
3433 				  const TopAbs_State            Side,
3434 				  const Standard_Real           TolConf,
3435 				  TopoDS_Face&                  NF)
3436 {
3437 #ifdef DRAW
3438   if (AffichInter) {
3439     char name[256];
3440     sprintf(name,"FTE_%d",NbFTE++);
3441     DBRep::Set(name,F);
3442   }
3443 #endif
3444 
3445   TopExp_Explorer                    exp,exp2;
3446   TopTools_DataMapOfShapeShape       Build;
3447   TopTools_DataMapOfShapeShape       Extent;
3448   TopoDS_Edge                        FirstE,PrecE,CurE,NE;
3449   BRep_Builder B;
3450   TopoDS_Face  EF;
3451 
3452   // Construction de la boite englobante de la face a etendre et des bouchons pour
3453   // limiter les extensions.
3454   //Bnd_Box ContextBox;
3455   //BRepBndLib::Add(F,B);
3456   //TopTools_DataMapIteratorOfDataMapOfShape itTB(ToBuild);
3457   //for (; itTB.More(); itTB.Next()) {
3458   //BRepBndLib::Add(TopBuild.Value(), ContextBox);
3459   //}
3460 
3461 
3462   Standard_Boolean SurfaceChange;
3463   SurfaceChange = EnLargeFace (F,EF,Standard_True);
3464 
3465   TopoDS_Shape aLocalShape = EF.EmptyCopied();
3466   NF = TopoDS::Face(aLocalShape);
3467 //  NF = TopoDS::Face(EF.EmptyCopied());
3468   NF.Orientation(TopAbs_FORWARD);
3469 
3470   if (SurfaceChange) {
3471     //------------------------------------------------
3472     // Mise a jour des pcurves sur la surface de base.
3473     //------------------------------------------------
3474     TopoDS_Face Fforward = F;
3475     Fforward.Orientation(TopAbs_FORWARD);
3476     TopTools_IndexedMapOfShape Emap;
3477     TopExp::MapShapes( Fforward, TopAbs_EDGE, Emap );
3478     Standard_Real f,l;
3479     for (Standard_Integer i = 1; i <= Emap.Extent(); i++) {
3480       TopoDS_Edge   CE  = TopoDS::Edge( Emap(i) );
3481       CE.Orientation(TopAbs_FORWARD);
3482       TopoDS_Edge   Ecs; //patch
3483       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(CE,Fforward,f,l);
3484       if (!C2.IsNull()) {
3485 	if (ConstShapes.IsBound(CE)) {
3486 	  Ecs = TopoDS::Edge(ConstShapes(CE));
3487 	  BRep_Tool::Range(Ecs,f,l);
3488 	}
3489 	if (BRep_Tool::IsClosed(CE,Fforward))  {
3490 	  TopoDS_Shape aLocalShapeReversedCE = CE.Reversed();
3491 	  Handle(Geom2d_Curve) C2R =
3492 	    BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShapeReversedCE),Fforward,f,l);
3493 //	  Handle(Geom2d_Curve) C2R =
3494 //	    BRep_Tool::CurveOnSurface(TopoDS::Edge(CE.Reversed()),F,f,l);
3495 	  B.UpdateEdge (CE,C2,C2R,EF,BRep_Tool::Tolerance(CE));
3496 	  if (! Ecs.IsNull())
3497 	    B.UpdateEdge (Ecs,C2,C2R,EF,BRep_Tool::Tolerance(CE));
3498 	}
3499 	else {
3500 	  B.UpdateEdge (CE,C2,EF,BRep_Tool::Tolerance(CE));
3501 	  if (! Ecs.IsNull())
3502 	    B.UpdateEdge (Ecs,C2,EF,BRep_Tool::Tolerance(CE));
3503 	}
3504 	B.Range(CE,f,l);
3505 	if (! Ecs.IsNull())
3506 	  B.Range(Ecs,f,l);
3507       }
3508     }
3509   }
3510 
3511   for (exp.Init(F.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
3512        exp.More();
3513        exp.Next()) {
3514     const TopoDS_Wire& W = TopoDS::Wire(exp.Current());
3515     TopTools_DataMapOfShapeListOfShape MVE; // Vertex -> Edges incidentes.
3516     TopTools_DataMapOfShapeShape       NOnV1;
3517     TopTools_DataMapOfShapeShape       NOnV2;
3518 
3519     MapVertexEdges (W,MVE);
3520     BuildNeighbour (W,F,NOnV1,NOnV2);
3521 
3522     TopTools_ListOfShape LInt1,LInt2;
3523     TopoDS_Face          StopFace;
3524     //------------------------------------------------
3525     // Construction edges
3526     //------------------------------------------------
3527     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
3528 	 exp2.More(); exp2.Next()) {
3529       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3530       if (ConstShapes.IsBound(E)) ToBuild.UnBind(E);
3531       if (ToBuild.IsBound(E)) {
3532 	TopTools_ListOfShape LOE;
3533 	LOE.Append(E);
3534 	BRepOffset_Tool::TryProject (TopoDS::Face(ToBuild(E)),
3535 				     EF,LOE,LInt2,LInt1,Side,TolConf);
3536 	if (!LInt1.IsEmpty())
3537 	  ToBuild.UnBind(E);
3538       }
3539     }
3540 
3541     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
3542 	 exp2.More(); exp2.Next()) {
3543       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3544       if (ConstShapes.IsBound(E)) ToBuild.UnBind(E);
3545       if (ToBuild.IsBound(E)) {
3546         EnLargeFace(TopoDS::Face(ToBuild(E)),StopFace,Standard_False);
3547         TopoDS_Face NullFace;
3548         BRepOffset_Tool::Inter3D (EF,StopFace,LInt1,LInt2,Side,E,NullFace,NullFace);
3549         // No intersection, it may happen for example for a chosen (non-offsetted) planar face and
3550         // its neighbour offseted cylindrical face, if the offset is directed so that
3551         // the radius of the cylinder becomes smaller.
3552         if (LInt1.IsEmpty())
3553           continue;
3554 	if (LInt1.Extent() > 1) {
3555 	  // l intersection est en plusieurs edges (franchissement de couture)
3556 	  SelectEdge (F,EF,E,LInt1);
3557 	}
3558 	NE = TopoDS::Edge(LInt1.First());
3559 	Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &NE.TShape());
3560 	TE->Tolerance( TE->Tolerance()*10. ); //????
3561 	if (NE.Orientation() == E.Orientation()) {
3562 	  Build.Bind(E,NE.Oriented(TopAbs_FORWARD));
3563 	}
3564 	else {
3565 	  Build.Bind(E,NE.Oriented(TopAbs_REVERSED));
3566 	}
3567 	const TopoDS_Edge& EOnV1 = TopoDS::Edge(NOnV1(E));
3568 	if (!ToBuild    .IsBound(EOnV1) &&
3569 	    !ConstShapes.IsBound(EOnV1) &&
3570 	    !Build      .IsBound(EOnV1)) {
3571 	  ExtentEdge (F,EF,EOnV1,NE);
3572 	  Build.Bind (EOnV1,NE.Oriented(TopAbs_FORWARD));
3573 	}
3574 	const TopoDS_Edge& EOnV2 = TopoDS::Edge(NOnV2(E));
3575 	if (!ToBuild    .IsBound(EOnV2) &&
3576 	    !ConstShapes.IsBound(EOnV2) &&
3577 	    !Build      .IsBound(EOnV2)) {
3578 	  ExtentEdge (F,EF,EOnV2,NE);
3579 	  Build.Bind (EOnV2,NE.Oriented (TopAbs_FORWARD));
3580 	}
3581       }
3582     }
3583 
3584     //------------------------------------------------
3585     // Construction Vertex.
3586     //------------------------------------------------
3587     TopTools_ListOfShape LV;
3588     Standard_Real        f,l;
3589     TopoDS_Edge          ERef;
3590     TopoDS_Vertex        V1,V2;
3591 
3592     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); exp2.More(); exp2.Next())
3593     {
3594       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3595       TopExp::Vertices (E,V1,V2);
3596       BRep_Tool::Range (E,f,l);
3597       TopoDS_Vertex V;
3598       if (Build.IsBound(E))
3599       {
3600         const TopoDS_Edge& NEOnV1 = TopoDS::Edge(NOnV1(E));
3601         if (Build.IsBound(NEOnV1) && (ToBuild.IsBound(E) || ToBuild.IsBound(NEOnV1)))
3602         {
3603           if (E.IsSame(NEOnV1))
3604             V = TopExp::FirstVertex(TopoDS::Edge(Build(E)));
3605           else
3606           {
3607             //---------------
3608             // intersection.
3609             //---------------
3610             if (!Build.IsBound(V1))
3611             {
3612               Inter2d (EF,TopoDS::Edge(Build(E)), TopoDS::Edge(Build(NEOnV1)),LV,/*TolConf*/Precision::Confusion());
3613 
3614               if(!LV.IsEmpty())
3615               {
3616                 if (Build(E).Orientation() == TopAbs_FORWARD)
3617                 {
3618                   V = TopoDS::Vertex(LV.First());
3619                 }
3620                 else
3621                 {
3622                   V = TopoDS::Vertex(LV.Last());
3623                 }
3624               }
3625               else
3626               {
3627                 return;
3628               }
3629             }
3630             else
3631             {
3632               V = TopoDS::Vertex(Build(V1));
3633               if (MVE (V1).Extent() > 2)
3634               {
3635                 V.Orientation(TopAbs_FORWARD);
3636                 if (Build(E).Orientation() == TopAbs_REVERSED)
3637                   V.Orientation(TopAbs_REVERSED);
3638 
3639                 ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3640               }
3641             }
3642           }
3643         }
3644         else
3645         {
3646           //------------
3647           //projection
3648           //------------
3649           V = V1;
3650           if (ConstShapes.IsBound(V1)) V = TopoDS::Vertex(ConstShapes(V1));
3651           V.Orientation(TopAbs_FORWARD);
3652           if (Build(E).Orientation() == TopAbs_REVERSED)
3653             V.Orientation(TopAbs_REVERSED);
3654           if (!TryParameter    (E,V,TopoDS::Edge(Build(E)),TolConf))
3655             ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3656         }
3657 
3658         ConstShapes.Bind(V1,V);
3659         Build.Bind      (V1,V);
3660         const TopoDS_Edge& NEOnV2 = TopoDS::Edge(NOnV2(E));
3661         if (Build.IsBound(NEOnV2) && (ToBuild.IsBound(E) || ToBuild.IsBound(NEOnV2)))
3662         {
3663           if (E.IsSame(NEOnV2))
3664             V = TopExp::LastVertex(TopoDS::Edge(Build(E)));
3665           else
3666           {
3667             //--------------
3668             // intersection.
3669             //---------------
3670 
3671             if (!Build.IsBound(V2))
3672             {
3673               Inter2d (EF,TopoDS::Edge(Build(E)), TopoDS::Edge(Build(NEOnV2)),LV,/*TolConf*/Precision::Confusion());
3674 
3675               if(!LV.IsEmpty())
3676               {
3677                 if (Build(E).Orientation() == TopAbs_FORWARD)
3678                 {
3679                   V = TopoDS::Vertex(LV.Last());
3680                 }
3681                 else
3682                 {
3683                   V = TopoDS::Vertex(LV.First());
3684                 }
3685               }
3686               else
3687               {
3688                 return;
3689               }
3690             }
3691             else
3692             {
3693               V = TopoDS::Vertex(Build(V2));
3694               if (MVE (V2).Extent() > 2)
3695               {
3696                 V.Orientation(TopAbs_REVERSED);
3697                 if (Build(E).Orientation() == TopAbs_REVERSED)
3698                   V.Orientation(TopAbs_FORWARD);
3699 
3700                 ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3701               }
3702             }
3703           }
3704         }
3705         else
3706         {
3707           //------------
3708           //projection
3709           //------------
3710           V = V2;
3711           if (ConstShapes.IsBound(V2))
3712             V = TopoDS::Vertex(ConstShapes(V2));
3713           V.Orientation(TopAbs_REVERSED);
3714           if (Build(E).Orientation() == TopAbs_REVERSED)
3715             V.Orientation(TopAbs_FORWARD);
3716           if (!TryParameter (E,V,TopoDS::Edge(Build(E)),TolConf))
3717             ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3718         }
3719         ConstShapes.Bind(V2,V);
3720         Build.Bind(V2,V);
3721       }
3722     }
3723 
3724     TopoDS_Wire        NW;
3725     TopoDS_Vertex      NV1,NV2;
3726     TopAbs_Orientation Or;
3727     Standard_Real      U1,U2;
3728     Standard_Real      eps = Precision::Confusion();
3729 
3730 #ifdef OCCT_DEBUG
3731     TopLoc_Location    L;
3732 #endif
3733     B.MakeWire(NW);
3734 
3735     //-----------------
3736     // Reconstruction.
3737     //-----------------
3738     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
3739 	 exp2.More(); exp2.Next()) {
3740       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3741       TopExp::Vertices (E,V1,V2);
3742       if (Build.IsBound(E)) {
3743 	NE = TopoDS::Edge(Build(E));
3744 	BRep_Tool::Range(NE,f,l);
3745 	Or = NE.Orientation();
3746 	//-----------------------------------------------------
3747 	// Copy pour virer les vertex deja sur la nouvelle edge.
3748 	//-----------------------------------------------------
3749 	NV1 = TopoDS::Vertex(ConstShapes(V1));
3750 	NV2 = TopoDS::Vertex(ConstShapes(V2));
3751 
3752 	TopoDS_Shape aLocalVertexOrientedNV1 = NV1.Oriented(TopAbs_INTERNAL);
3753 	TopoDS_Shape aLocalEdge   = NE.Oriented(TopAbs_INTERNAL);
3754 
3755 	U1 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalVertexOrientedNV1),
3756 				  TopoDS::Edge  (aLocalEdge));
3757         aLocalVertexOrientedNV1 = NV2.Oriented(TopAbs_INTERNAL);
3758 	aLocalEdge   = NE.Oriented(TopAbs_FORWARD);
3759 	U2 = BRep_Tool::Parameter (TopoDS::Vertex(aLocalVertexOrientedNV1),TopoDS::Edge  (aLocalEdge));
3760 //	U1 = BRep_Tool::Parameter
3761 //	  (TopoDS::Vertex(NV1.Oriented(TopAbs_INTERNAL)),
3762 //	   TopoDS::Edge  (NE .Oriented(TopAbs_FORWARD)));
3763 //	U2 = BRep_Tool::Parameter
3764 //	  (TopoDS::Vertex(NV2.Oriented(TopAbs_INTERNAL)),
3765 //	   TopoDS::Edge  (NE.Oriented(TopAbs_FORWARD)));
3766 	aLocalEdge = NE.EmptyCopied();
3767 	NE = TopoDS::Edge(aLocalEdge);
3768 	NE.Orientation(TopAbs_FORWARD);
3769 	if (NV1.IsSame(NV2))
3770 	  {
3771 	    //--------------
3772 	    // edge ferme.
3773 	    //--------------
3774 	    if (Or == TopAbs_FORWARD) {U1 = f; U2 = l;}
3775 	    else                      {U1 = l; U2 = f;}
3776 	    if (Or == TopAbs_FORWARD)
3777 	      {
3778 		if (U1 > U2)
3779 		  {
3780 		    if (Abs(U1-l) < eps) U1 = f;
3781 		    if (Abs(U2-f) < eps) U2 = l;
3782 		  }
3783 		TopoDS_Shape aLocalVertex = NV1.Oriented(TopAbs_FORWARD );
3784 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3785 		aLocalVertex = NV2.Oriented(TopAbs_REVERSED);
3786 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3787 //		B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_FORWARD )));
3788 //		B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_REVERSED)));
3789 		B.Range(NE,U1,U2);
3790 		ConstShapes.Bind(E,NE);
3791 		NE.Orientation(E.Orientation());
3792 	      }
3793 	    else
3794 	      {
3795 		if (U2 > U1)
3796 		  {
3797 		    if (Abs(U2-l) < eps) U2 = f;
3798 		    if (Abs(U1-f) < eps) U1 = l;
3799 		  }
3800 		TopoDS_Shape aLocalVertex = NV2.Oriented(TopAbs_FORWARD );
3801 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3802 		aLocalVertex = NV1.Oriented(TopAbs_REVERSED);
3803 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3804 //		B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_FORWARD )));
3805 //		B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_REVERSED)));
3806 		B.Range(NE,U2,U1);
3807 		ConstShapes.Bind(E,NE.Oriented(TopAbs_REVERSED));
3808 		NE.Orientation(TopAbs::Reverse(E.Orientation()));
3809 	      }
3810 	  }
3811 	else
3812 	  {
3813 	    //-------------------
3814 	    // edge is not ferme.
3815 	    //-------------------
3816 	    if (Or == TopAbs_FORWARD) {
3817 	      if (U1 > U2) {
3818 		TopoDS_Shape aLocalVertex = NV2.Oriented(TopAbs_FORWARD );
3819 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3820 		aLocalVertex = NV1.Oriented(TopAbs_REVERSED);
3821 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3822 //		B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_FORWARD )));
3823 //		B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_REVERSED)));
3824 		B.Range(NE,U2,U1);
3825 	      }
3826 	      else
3827 		{
3828 		  TopoDS_Shape aLocalVertex = NV1.Oriented(TopAbs_FORWARD );
3829 		  B.Add (NE,TopoDS::Vertex(aLocalVertex));
3830 		  aLocalVertex = NV2.Oriented(TopAbs_REVERSED);
3831 		  B.Add (NE,TopoDS::Vertex(aLocalVertex));
3832 //		  B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_FORWARD )));
3833 //		  B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_REVERSED)));
3834 		  B.Range(NE,U1,U2);
3835 		}
3836 	      ConstShapes.Bind(E,NE);
3837 	      NE.Orientation(E.Orientation());
3838 	    }
3839 	    else {
3840 	      if (U2 > U1) {
3841 		TopoDS_Shape aLocalVertex = NV1.Oriented(TopAbs_FORWARD );
3842 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3843 		aLocalVertex = NV2.Oriented(TopAbs_REVERSED);
3844 		B.Add (NE,TopoDS::Vertex(aLocalVertex));
3845 //		B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_FORWARD )));
3846 //		B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_REVERSED)));
3847 		B.Range(NE,U1,U2);
3848 		ConstShapes.Bind(E,NE);
3849 		NE.Orientation(E.Orientation());
3850 	      }
3851 	      else
3852 		{
3853 		  TopoDS_Shape aLocalVertex = NV2.Oriented(TopAbs_FORWARD );
3854 		  B.Add (NE,TopoDS::Vertex(aLocalVertex));
3855 		  aLocalVertex = NV1.Oriented(TopAbs_REVERSED);
3856 		  B.Add (NE,TopoDS::Vertex(aLocalVertex));
3857 //		  B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_FORWARD )));
3858 //		  B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_REVERSED)));
3859 		  B.Range(NE,U2,U1);
3860 		  ConstShapes.Bind(E,NE.Oriented(TopAbs_REVERSED));
3861 		  NE.Orientation(TopAbs::Reverse(E.Orientation()));
3862 		}
3863 	    }
3864 	  }
3865 	Build.UnBind(E);
3866       } // Build.IsBound(E)
3867       else if (ConstShapes.IsBound(E)) { // !Build.IsBound(E)
3868 	NE = TopoDS::Edge(ConstShapes(E));
3869 	BuildPCurves(NE,NF);
3870 	Or = NE.Orientation();
3871 	if (Or == TopAbs_REVERSED) {
3872 	  NE.Orientation(TopAbs::Reverse(E.Orientation()));
3873 	}
3874 	else {
3875 	  NE.Orientation(E.Orientation());
3876 	}
3877       }
3878       else {
3879 	NE = E;
3880 	ConstShapes.Bind(E,NE.Oriented(TopAbs_FORWARD));
3881       }
3882       B.Add(NW,NE);
3883     }
3884     B.Add(NF,NW.Oriented(W.Orientation()));
3885   }
3886   NF.Orientation(F.Orientation());
3887   BRepTools::Update(NF); // Maj des UVPoints
3888 
3889 #ifdef DRAW
3890   if (AffichInter) {
3891     char name[256];
3892     sprintf(name,"FOB_%d",NbFOB++);
3893     DBRep::Set(name,NF);
3894   }
3895 #endif
3896 }
3897 
3898 
3899 //=======================================================================
3900 //function : Deboucle3D
3901 //purpose  :
3902 //=======================================================================
Deboucle3D(const TopoDS_Shape & S,const TopTools_MapOfShape & Boundary)3903 TopoDS_Shape BRepOffset_Tool::Deboucle3D(const TopoDS_Shape& S,
3904                                          const TopTools_MapOfShape& Boundary)
3905 {
3906   TopoDS_Shape SS;
3907   switch (S.ShapeType())
3908   {
3909     case TopAbs_SHELL:
3910     {
3911       // if the shell contains free borders that do not belong to the
3912       // free borders of caps ( Boundary) it is removed.
3913       TopTools_IndexedDataMapOfShapeListOfShape Map;
3914       TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, Map);
3915 
3916       Standard_Boolean JeGarde = Standard_True;
3917       for (Standard_Integer i = 1; i <= Map.Extent() && JeGarde; i++) {
3918         const TopTools_ListOfShape& aLF = Map(i);
3919         if (aLF.Extent() < 2) {
3920           const TopoDS_Edge& anEdge = TopoDS::Edge(Map.FindKey(i));
3921           if (anEdge.Orientation() == TopAbs_INTERNAL) {
3922             const TopoDS_Face& aFace = TopoDS::Face(aLF.First());
3923             if (aFace.Orientation() != TopAbs_INTERNAL) {
3924               continue;
3925             }
3926           }
3927           if (!Boundary.Contains(anEdge) &&
3928               !BRep_Tool::Degenerated(anEdge))
3929             JeGarde = Standard_False;
3930         }
3931       }
3932       if (JeGarde) SS = S;
3933     }
3934     break;
3935 
3936     case TopAbs_COMPOUND:
3937     case TopAbs_SOLID:
3938     {
3939       // iterate on sub-shapes and add non-empty.
3940       TopoDS_Iterator it(S);
3941       TopoDS_Shape SubShape;
3942       Standard_Integer NbSub = 0;
3943       BRep_Builder B;
3944       if (S.ShapeType() == TopAbs_COMPOUND) {
3945         B.MakeCompound(TopoDS::Compound(SS));
3946       }
3947       else {
3948         B.MakeSolid(TopoDS::Solid(SS));
3949       }
3950       for (; it.More(); it.Next()) {
3951         const TopoDS_Shape& CurS = it.Value();
3952         SubShape = Deboucle3D(CurS, Boundary);
3953         if (!SubShape.IsNull()) {
3954           B.Add(SS, SubShape);
3955           NbSub++;
3956         }
3957       }
3958       if (NbSub == 0)
3959       {
3960         SS = TopoDS_Shape();
3961       }
3962     }
3963     break;
3964 
3965     default:
3966       break;
3967   }
3968 
3969   return SS;
3970 }
3971 
3972 //=======================================================================
3973 //function : IsInOut
3974 //purpose  :
3975 //=======================================================================
3976 
IsInOut(BRepTopAdaptor_FClass2d & FC,Geom2dAdaptor_Curve AC,const TopAbs_State & S)3977 static Standard_Boolean IsInOut (BRepTopAdaptor_FClass2d& FC,
3978 				 Geom2dAdaptor_Curve      AC,
3979 				 const TopAbs_State&      S )
3980 {
3981  Standard_Real Def = 100*Precision::Confusion();
3982  GCPnts_QuasiUniformDeflection QU(AC,Def);
3983 
3984  for (Standard_Integer i = 1; i <= QU.NbPoints(); i++) {
3985    gp_Pnt2d P = AC.Value(QU.Parameter(i));
3986    if (FC.Perform(P) != S) {
3987      return Standard_False;
3988    }
3989  }
3990  return Standard_True;
3991 }
3992 
3993 //=======================================================================
3994 //function : CorrectOrientation
3995 //purpose  :
3996 //=======================================================================
3997 
CorrectOrientation(const TopoDS_Shape & SI,const TopTools_IndexedMapOfShape & NewEdges,Handle (BRepAlgo_AsDes)& AsDes,BRepAlgo_Image & InitOffset,const Standard_Real Offset)3998 void BRepOffset_Tool::CorrectOrientation(const TopoDS_Shape&        SI,
3999 					 const TopTools_IndexedMapOfShape& NewEdges,
4000 					 Handle(BRepAlgo_AsDes)&    AsDes,
4001 					 BRepAlgo_Image&            InitOffset,
4002 					 const Standard_Real        Offset)
4003 {
4004 
4005   TopExp_Explorer exp;
4006   exp.Init(SI,TopAbs_FACE);
4007   Standard_Real   f=0.,l=0.;
4008 
4009   for (; exp.More(); exp.Next()) {
4010 
4011     const TopoDS_Face&          FI  = TopoDS::Face(exp.Current());
4012     const TopTools_ListOfShape& LOF = InitOffset.Image(FI);
4013     TopTools_ListIteratorOfListOfShape it(LOF);
4014     for (; it.More(); it.Next()) {
4015       const TopoDS_Face&    OF   = TopoDS::Face(it.Value());
4016       TopTools_ListOfShape& LOE = AsDes->ChangeDescendant(OF);
4017       TopTools_ListIteratorOfListOfShape itE(LOE);
4018 
4019       Standard_Boolean YaInt = Standard_False;
4020       for (; itE.More(); itE.Next()) {
4021 	const TopoDS_Edge& OE = TopoDS::Edge(itE.Value());
4022 	if (NewEdges.Contains(OE)) {YaInt = Standard_True; break;}
4023       }
4024       if (YaInt) {
4025 	TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD);
4026 	BRepTopAdaptor_FClass2d FC (TopoDS::Face(aLocalFace),
4027 				    Precision::Confusion());
4028 //	BRepTopAdaptor_FClass2d FC (TopoDS::Face(FI.Oriented(TopAbs_FORWARD)),
4029 //				    Precision::Confusion());
4030 	for (itE.Initialize(LOE); itE.More(); itE.Next()) {
4031 	  TopoDS_Shape&   OE   = itE.Value();
4032 	  if (NewEdges.Contains(OE)) {
4033 	    Handle(Geom2d_Curve) CO2d =
4034 	      BRep_Tool::CurveOnSurface(TopoDS::Edge(OE),OF,f,l);
4035 	    Geom2dAdaptor_Curve  AC(CO2d,f,l);
4036 
4037 	    if (Offset > 0) {
4038 	      if (IsInOut(FC,AC,TopAbs_OUT)) OE.Reverse();
4039 	    }
4040 //	    else {
4041 //	      if (IsInOut(FC,AC,TopAbs_IN)) OE.Reverse();
4042 //	    }
4043 	  }
4044 	}
4045       }
4046     }
4047   }
4048 
4049 }
4050 
4051 //=======================================================================
4052 //function : CheckNormals
4053 //purpose  :
4054 //=======================================================================
CheckPlanesNormals(const TopoDS_Face & theFace1,const TopoDS_Face & theFace2,const Standard_Real theTolAng)4055 Standard_Boolean BRepOffset_Tool::CheckPlanesNormals(const TopoDS_Face& theFace1,
4056                                                      const TopoDS_Face& theFace2,
4057                                                      const Standard_Real theTolAng)
4058 {
4059   BRepAdaptor_Surface aBAS1(theFace1, Standard_False), aBAS2(theFace2, Standard_False);
4060   if (aBAS1.GetType() != GeomAbs_Plane ||
4061       aBAS2.GetType() != GeomAbs_Plane) {
4062     return Standard_False;
4063   }
4064   //
4065   gp_Dir aDN1 = aBAS1.Plane().Position().Direction();
4066   if (theFace1.Orientation() == TopAbs_REVERSED) {
4067     aDN1.Reverse();
4068   }
4069   //
4070   gp_Dir aDN2 = aBAS2.Plane().Position().Direction();
4071   if (theFace2.Orientation() == TopAbs_REVERSED) {
4072     aDN2.Reverse();
4073   }
4074   //
4075   Standard_Real anAngle = aDN1.Angle(aDN2);
4076   return (anAngle < theTolAng);
4077 }
4078 
4079 //=======================================================================
4080 //function : PerformPlanes
4081 //purpose  :
4082 //=======================================================================
PerformPlanes(const TopoDS_Face & theFace1,const TopoDS_Face & theFace2,const TopAbs_State theSide,TopTools_ListOfShape & theL1,TopTools_ListOfShape & theL2)4083 void PerformPlanes(const TopoDS_Face& theFace1,
4084                    const TopoDS_Face& theFace2,
4085                    const TopAbs_State theSide,
4086                    TopTools_ListOfShape& theL1,
4087                    TopTools_ListOfShape& theL2)
4088 {
4089   theL1.Clear();
4090   theL2.Clear();
4091   // Intersect the planes using IntTools_FaceFace directly
4092   IntTools_FaceFace aFF;
4093   aFF.SetParameters(Standard_True, Standard_True, Standard_True, Precision::Confusion());
4094   aFF.Perform(theFace1, theFace2);
4095   //
4096   if (!aFF.IsDone()) {
4097     return;
4098   }
4099   //
4100   const IntTools_SequenceOfCurves& aSC = aFF.Lines();
4101   if (aSC.IsEmpty()) {
4102     return;
4103   }
4104   //
4105   // In Plane/Plane intersection only one curve is always produced.
4106   // Make the edge from this section curve.
4107   TopoDS_Edge aE;
4108   {
4109     BRep_Builder aBB;
4110     const IntTools_Curve& aIC = aSC(1);
4111     const Handle(Geom_Curve)& aC3D = aIC.Curve();
4112     aBB.MakeEdge(aE, aC3D, aIC.Tolerance());
4113     // Get bounds of the curve
4114     Standard_Real aTF, aTL;
4115     gp_Pnt aPF, aPL;
4116     aIC.Bounds(aTF, aTL, aPF, aPL);
4117     // Make the bounding vertices
4118     TopoDS_Vertex aVF, aVL;
4119     aBB.MakeVertex(aVF, aPF, aIC.Tolerance());
4120     aBB.MakeVertex(aVL, aPL, aIC.Tolerance());
4121     aVL.Orientation(TopAbs_REVERSED);
4122     // Add vertices to the edge
4123     aBB.Add(aE, aVF);
4124     aBB.Add(aE, aVL);
4125     // Add 2D curves to the edge
4126     aBB.UpdateEdge(aE, aIC.FirstCurve2d(), theFace1, aIC.Tolerance());
4127     aBB.UpdateEdge(aE, aIC.SecondCurve2d(), theFace2, aIC.Tolerance());
4128     // Update range of the new edge
4129     aBB.Range(aE, aTF, aTL);
4130   }
4131   //
4132   // Orient section
4133   TopAbs_Orientation O1, O2;
4134   BRepOffset_Tool::OrientSection(aE, theFace1, theFace2, O1, O2);
4135   if (theSide == TopAbs_OUT) {
4136     O1 = TopAbs::Reverse(O1);
4137     O2 = TopAbs::Reverse(O2);
4138   }
4139   //
4140   BRepLib::SameParameter(aE, Precision::Confusion(), Standard_True);
4141   //
4142   // Add edge to result
4143   theL1.Append(aE.Oriented(O1));
4144   theL2.Append(aE.Oriented(O2));
4145 }
4146 
4147 //=======================================================================
4148 //function : IsInf
4149 //purpose  : Checks if the given value is close to infinite (TheInfini)
4150 //=======================================================================
IsInf(const Standard_Real theVal)4151 Standard_Boolean IsInf(const Standard_Real theVal)
4152 {
4153   return (theVal > TheInfini*0.9);
4154 }
4155 
UpdateVertexTolerances(const TopoDS_Face & theFace)4156 static void UpdateVertexTolerances(const TopoDS_Face& theFace)
4157 {
4158   BRep_Builder BB;
4159   TopTools_IndexedDataMapOfShapeListOfShape VEmap;
4160   TopExp::MapShapesAndAncestors(theFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
4161 
4162   for (Standard_Integer i = 1; i <= VEmap.Extent(); i++)
4163   {
4164     const TopoDS_Vertex& aVertex = TopoDS::Vertex(VEmap.FindKey(i));
4165     const TopTools_ListOfShape& Elist = VEmap(i);
4166     gp_Pnt PntVtx = BRep_Tool::Pnt(aVertex);
4167     TopTools_ListIteratorOfListOfShape itl(Elist);
4168     for (; itl.More(); itl.Next())
4169     {
4170       const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
4171       TopoDS_Vertex V1, V2;
4172       TopExp::Vertices(anEdge, V1, V2);
4173       Standard_Real fpar, lpar;
4174       BRep_Tool::Range(anEdge, fpar, lpar);
4175       Standard_Real aParam = (V1.IsSame(aVertex))? fpar : lpar;
4176       if (!BRep_Tool::Degenerated(anEdge))
4177       {
4178         BRepAdaptor_Curve BAcurve(anEdge);
4179         gp_Pnt aPnt = BAcurve.Value(aParam);
4180         Standard_Real aDist = PntVtx.Distance(aPnt);
4181         BB.UpdateVertex(aVertex, aDist);
4182         if (V1.IsSame(V2))
4183         {
4184           aPnt = BAcurve.Value(lpar);
4185           aDist = PntVtx.Distance(aPnt);
4186           BB.UpdateVertex(aVertex, aDist);
4187         }
4188       }
4189       BRepAdaptor_Curve BAcurveonsurf(anEdge, theFace);
4190       gp_Pnt aPnt = BAcurveonsurf.Value(aParam);
4191       Standard_Real aDist = PntVtx.Distance(aPnt);
4192       BB.UpdateVertex(aVertex, aDist);
4193       if (V1.IsSame(V2))
4194       {
4195         aPnt = BAcurveonsurf.Value(lpar);
4196         aDist = PntVtx.Distance(aPnt);
4197         BB.UpdateVertex(aVertex, aDist);
4198       }
4199     }
4200   }
4201 }
4202