1 // Created on: 1993-12-15
2 // Created by: Isabelle GRIGNON
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 
18 #include <Adaptor2d_Curve2d.hxx>
19 #include <Adaptor3d_Surface.hxx>
20 #include <Adaptor3d_TopolTool.hxx>
21 #include <AppBlend_Approx.hxx>
22 #include <Blend_CurvPointFuncInv.hxx>
23 #include <Blend_FuncInv.hxx>
24 #include <Blend_Function.hxx>
25 #include <Blend_RstRstFunction.hxx>
26 #include <Blend_SurfCurvFuncInv.hxx>
27 #include <Blend_SurfPointFuncInv.hxx>
28 #include <Blend_SurfRstFunction.hxx>
29 #include <BRep_Tool.hxx>
30 #include <BRepAdaptor_Curve.hxx>
31 #include <BRepAdaptor_Curve2d.hxx>
32 #include <BRepAdaptor_Surface.hxx>
33 #include <BRepBlend_Line.hxx>
34 #include <BRepLProp_SLProps.hxx>
35 #include <BRepTopAdaptor_TopolTool.hxx>
36 #include <ChFi3d.hxx>
37 #include <ChFi3d_Builder.hxx>
38 #include <ChFi3d_Builder_0.hxx>
39 #include <ChFiDS_CommonPoint.hxx>
40 #include <ChFiDS_ErrorStatus.hxx>
41 #include <ChFiDS_FilSpine.hxx>
42 #include <ChFiDS_HData.hxx>
43 #include <ChFiDS_ElSpine.hxx>
44 #include <ChFiDS_ListIteratorOfListOfStripe.hxx>
45 #include <ChFiDS_ListIteratorOfRegularities.hxx>
46 #include <ChFiDS_Regul.hxx>
47 #include <ChFiDS_Spine.hxx>
48 #include <ChFiDS_State.hxx>
49 #include <ChFiDS_Stripe.hxx>
50 #include <ChFiDS_SurfData.hxx>
51 #include <Geom2d_Curve.hxx>
52 #include <Geom_Surface.hxx>
53 #include <Geom_OffsetSurface.hxx>
54 #include <Geom_RectangularTrimmedSurface.hxx>
55 #include <GeomInt_IntSS.hxx>
56 #include <Extrema_ExtPC.hxx>
57 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
58 #include <Geom_BSplineCurve.hxx>
59 #include <gp_Pnt.hxx>
60 #include <gp_Pnt2d.hxx>
61 #include <gp_Vec.hxx>
62 #include <LocalAnalysis_SurfaceContinuity.hxx>
63 #include <Precision.hxx>
64 #include <Standard_ConstructionError.hxx>
65 #include <Standard_NoSuchObject.hxx>
66 #include <Standard_OutOfRange.hxx>
67 #include <TopAbs.hxx>
68 #include <TopAbs_Orientation.hxx>
69 #include <TopAbs_ShapeEnum.hxx>
70 #include <TopExp.hxx>
71 #include <TopoDS.hxx>
72 #include <TopoDS_Edge.hxx>
73 #include <TopoDS_Face.hxx>
74 #include <TopoDS_Shape.hxx>
75 #include <TopoDS_Vertex.hxx>
76 #include <TopOpeBRepBuild_HBuilder.hxx>
77 #include <TopOpeBRepDS_HDataStructure.hxx>
78 #include <TopOpeBRepDS_Surface.hxx>
79 #include <TopOpeBRepTool_TOOL.hxx>
80 #include <TopTools_ListIteratorOfListOfShape.hxx>
81 #include <BRepLib_MakeEdge.hxx>
82 
83 #ifdef OCCT_DEBUG
84 extern Standard_Boolean ChFi3d_GetcontextFORCEBLEND();
85 #endif
86 
ReorderFaces(TopoDS_Face & theF1,TopoDS_Face & theF2,const TopoDS_Face & theFirstFace,const TopoDS_Edge & thePrevEdge,const TopoDS_Vertex & theCommonVertex,const ChFiDS_Map & theEFmap)87 static void ReorderFaces(TopoDS_Face&         theF1,
88                          TopoDS_Face&         theF2,
89                          const TopoDS_Face&   theFirstFace,
90                          const TopoDS_Edge&   thePrevEdge,
91                          const TopoDS_Vertex& theCommonVertex,
92                          const ChFiDS_Map&    theEFmap)
93 {
94   if (theF1.IsSame(theFirstFace))
95     return;
96   else if (theF2.IsSame(theFirstFace))
97   {
98     TopoDS_Face TmpFace = theF1; theF1 = theF2; theF2 = TmpFace;
99     return;
100   }
101 
102   //Loop until find <theF1> or <theF2>
103   Standard_Boolean ToExchange = Standard_False;
104   TopoDS_Edge PrevEdge = thePrevEdge, CurEdge;
105   TopoDS_Face PrevFace = theFirstFace, CurFace;
106   for (;;)
107   {
108     TopTools_IndexedDataMapOfShapeListOfShape VEmap;
109     TopExp::MapShapesAndAncestors(PrevFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
110     const TopTools_ListOfShape& Elist = VEmap.FindFromKey(theCommonVertex);
111     if (PrevEdge.IsSame(Elist.First()))
112       CurEdge = TopoDS::Edge(Elist.Last());
113     else
114       CurEdge = TopoDS::Edge(Elist.First());
115 
116     const TopTools_ListOfShape& Flist = theEFmap.FindFromKey(CurEdge);
117     if (PrevFace.IsSame(Flist.First()))
118       CurFace = TopoDS::Face(Flist.Last());
119     else
120       CurFace = TopoDS::Face(Flist.First());
121 
122     if (CurFace.IsSame(theF1))
123       break;
124     else if (CurFace.IsSame(theF2))
125     {
126       ToExchange = Standard_True;
127       break;
128     }
129 
130     PrevEdge = CurEdge;
131     PrevFace = CurFace;
132   }
133 
134   if (ToExchange)
135   {
136     TopoDS_Face TmpFace = theF1; theF1 = theF2; theF2 = TmpFace;
137   }
138 }
139 
ConcatCurves(TColGeom_SequenceOfCurve & theCurves,TColGeom_SequenceOfCurve & theNewCurves)140 static void ConcatCurves(TColGeom_SequenceOfCurve& theCurves,
141                          TColGeom_SequenceOfCurve& theNewCurves)
142 {
143   while (!theCurves.IsEmpty())
144   {
145     GeomConvert_CompCurveToBSplineCurve Concat;
146     Standard_Boolean Success = Standard_False;
147     for (Standard_Integer i = 1; i <= theCurves.Length(); i++)
148     {
149       const Handle(Geom_Curve)& aCurve = theCurves(i);
150       Handle(Geom_BoundedCurve) aBoundedCurve = Handle(Geom_BoundedCurve)::DownCast(aCurve);
151       Success = Concat.Add(aBoundedCurve, 1.e-5, Standard_True);
152       if (!Success)
153         Success = Concat.Add(aBoundedCurve, 1.e-5, Standard_False);
154       if (Success)
155       {
156         theCurves.Remove(i);
157         i--;
158       }
159     }
160     Handle(Geom_Curve) aNewCurve = Concat.BSplineCurve();
161     theNewCurves.Append(aNewCurve);
162   }
163 }
164 
MakeOffsetEdge(const TopoDS_Edge & theEdge,const Standard_Real Distance,const BRepAdaptor_Surface & S1,const BRepAdaptor_Surface & S2)165 static TopoDS_Edge MakeOffsetEdge(const TopoDS_Edge&         theEdge,
166                                   const Standard_Real        Distance,
167                                   const BRepAdaptor_Surface& S1,
168                                   const BRepAdaptor_Surface& S2)
169 {
170   TopoDS_Edge OffsetEdge;
171 
172   TopoDS_Face F1 = S1.Face();
173   TopoDS_Face F2 = S2.Face();
174   Handle(Geom_Surface) GS1 = BRep_Tool::Surface(F1);
175   Handle(Geom_Surface) TrGS1 =
176     new Geom_RectangularTrimmedSurface(GS1,
177                                        S1.FirstUParameter(), S1.LastUParameter(),
178                                        S1.FirstVParameter(), S1.LastVParameter());
179   Standard_Real Offset = -Distance;
180   if (F1.Orientation() == TopAbs_REVERSED)
181     Offset = Distance;
182   Handle(Geom_OffsetSurface) MakeOffsetSurf = new Geom_OffsetSurface(TrGS1, Offset);
183   Handle(Geom_Surface) OffsetTrGS1 = MakeOffsetSurf->Surface();
184   if (OffsetTrGS1.IsNull())
185     OffsetTrGS1 = MakeOffsetSurf;
186   Handle(Geom_Surface) GS2 = BRep_Tool::Surface(F2);
187   Handle(Geom_Surface) TrGS2 =
188     new Geom_RectangularTrimmedSurface(GS2,
189                                        S2.FirstUParameter(), S2.LastUParameter(),
190                                        S2.FirstVParameter(), S2.LastVParameter());
191   GeomInt_IntSS Intersector(OffsetTrGS1, TrGS2, Precision::Confusion());
192   if (!Intersector.IsDone() || Intersector.NbLines() == 0)
193   {
194     return OffsetEdge;
195   }
196 
197   Handle(Geom_Curve) IntCurve = Intersector.Line(1);
198   gp_Pnt Ends [2];
199   BRepAdaptor_Curve aBAcurve(theEdge);
200   Ends[0] = aBAcurve.Value(aBAcurve.FirstParameter());
201   Ends[1] = aBAcurve.Value(aBAcurve.LastParameter());
202 
203   if (Intersector.NbLines() > 1)
204   {
205     TColGeom_SequenceOfCurve Curves, NewCurves;
206     for (Standard_Integer i = 1; i <= Intersector.NbLines(); i++)
207       Curves.Append(Intersector.Line(i));
208 
209     ConcatCurves(Curves, NewCurves);
210 
211     Standard_Real MinDist = RealLast();
212     Standard_Integer imin = 1;
213     for (Standard_Integer i = 1; i <= NewCurves.Length(); i++)
214     {
215       GeomAdaptor_Curve GAcurve(NewCurves(i));
216       Extrema_ExtPC Projector(Ends[0], GAcurve);
217       if (!Projector.IsDone() || Projector.NbExt() == 0)
218         continue;
219       for (Standard_Integer iext = 1; iext <= Projector.NbExt(); iext++)
220       {
221         Standard_Real aDist = Projector.SquareDistance(iext);
222         if (aDist < MinDist)
223         {
224           MinDist = aDist;
225           imin = i;
226         }
227       }
228     }
229     IntCurve = NewCurves(imin);
230   }
231   if (IntCurve.IsNull())
232   {
233     return OffsetEdge;
234   }
235   //Projection of extremities onto <IntCurve>
236   GeomAdaptor_Curve GAcurve(IntCurve);
237   Standard_Real Params [2];
238   for (Standard_Integer ind_end = 0; ind_end < 2; ind_end++)
239   {
240     if (ind_end == 1 && aBAcurve.IsClosed()/*HGuide->IsPeriodic()*//*HGuide->IsClosed()*/)
241       break;
242     Extrema_ExtPC Projector(Ends[ind_end], GAcurve);
243     Standard_Real param[4], dist[4];
244     gp_Pnt Pnt[4];
245     param[1] = GAcurve.FirstParameter();
246     param[2] = GAcurve.LastParameter();
247     Projector.TrimmedSquareDistances(dist[1], dist[2], Pnt[1], Pnt[2]);
248     dist[3] = RealLast();
249     if (Projector.IsDone() && Projector.NbExt() > 0)
250     {
251       Standard_Integer imin = 1;
252       for (Standard_Integer i = 2; i <= Projector.NbExt(); i++)
253         if (Projector.SquareDistance(i) < Projector.SquareDistance(imin))
254           imin = i;
255       param[3] = Projector.Point(imin).Parameter();
256       dist[3]  = Projector.SquareDistance(imin);
257       Pnt[3]   = Projector.Point(imin).Value();
258     }
259 
260     Standard_Integer imin = 1;
261     for (Standard_Integer i = 2; i <= 3; i++)
262       if (dist[i] < dist[imin])
263         imin = i;
264 
265     Params[ind_end] = param[imin]; //Projector.Point(imin).Parameter();
266   }
267   if (aBAcurve.IsClosed()/*HGuide->IsPeriodic()*//*HGuide->IsClosed()*/)
268     Params[1] = GAcurve.LastParameter(); //temporary
269   if (Params[0] > Params[1])
270   {
271     Standard_Boolean IsClosed = Standard_False;
272     gp_Pnt fpnt = IntCurve->Value(IntCurve->FirstParameter());
273     gp_Pnt lpnt = IntCurve->Value(IntCurve->LastParameter());
274     if (fpnt.SquareDistance(lpnt) <= Precision::SquareConfusion())
275       IsClosed = Standard_True;
276     if (IsClosed)
277       Params[1] = IntCurve->LastParameter();
278     else
279     {
280       Standard_Real NewFirstPar = IntCurve->ReversedParameter(Params[0]);
281       Standard_Real NewLastPar  = IntCurve->ReversedParameter(Params[1]);
282       IntCurve->Reverse();
283       Params[0] = NewFirstPar;
284       Params[1] = NewLastPar;
285     }
286   }
287   if (aBAcurve.IsClosed()/*HGuide->IsPeriodic()*//*HGuide->IsClosed()*/) //check the direction of closed curve
288   {
289     gp_Pnt aPnt, anOffsetPnt;
290     gp_Vec Tangent, OffsetTangent;
291     aBAcurve.D1(aBAcurve.FirstParameter(), aPnt, Tangent);
292     IntCurve->D1(Params[0], anOffsetPnt, OffsetTangent);
293     if (Tangent*OffsetTangent < 0)
294       IntCurve->Reverse();
295   }
296 
297   /*
298   Standard_Real ParTol = 1.e-5;
299   Standard_Real FirstDiff = aBAcurve.FirstParameter() - Params[0];
300   Standard_Real LastDiff  = aBAcurve.LastParameter()  - Params[1];
301   if (Abs(FirstDiff) > ParTol ||
302       Abs(LastDiff)  > ParTol)
303   {
304     Handle(Geom_BSplineCurve) BsplCurve = Handle(Geom_BSplineCurve)::DownCast(IntCurve);
305     TColStd_Array1OfReal aKnots(1, BsplCurve->NbKnots());
306     BsplCurve->Knots(aKnots);
307     BSplCLib::Reparametrize(aBAcurve.FirstParameter(), aBAcurve.LastParameter(), aKnots);
308     BsplCurve->SetKnots(aKnots);
309     if (aBAcurve.IsPeriodic() && !BsplCurve->IsPeriodic())
310       BsplCurve->SetPeriodic();
311     IntCurve = BsplCurve;
312   }
313   */
314 
315   OffsetEdge = BRepLib_MakeEdge(IntCurve, Params[0], Params[1]);
316   return OffsetEdge;
317 }
318 
mkbuildtool()319 static TopOpeBRepDS_BuildTool mkbuildtool()
320 {
321   TopOpeBRepTool_GeomTool GT2(TopOpeBRepTool_BSPLINE1,
322 			      Standard_True,
323 			      Standard_False,
324 			      Standard_False);
325   TopOpeBRepDS_BuildTool BT(GT2);
326   BT.OverWrite(Standard_False);
327   BT.Translate(Standard_False);
328   return BT;
329 }
330 
331 //=======================================================================
332 //function : ChFi3d_Builder
333 //purpose  :
334 //=======================================================================
ChFi3d_Builder(const TopoDS_Shape & S,const Standard_Real Ta)335 ChFi3d_Builder::ChFi3d_Builder(const TopoDS_Shape& S,
336 			       const Standard_Real Ta) :
337    done(Standard_False), myShape(S)
338 {
339   myDS = new TopOpeBRepDS_HDataStructure();
340   myCoup = new TopOpeBRepBuild_HBuilder(mkbuildtool());
341   myEFMap.Fill(S,TopAbs_EDGE,TopAbs_FACE);
342   myESoMap.Fill(S,TopAbs_EDGE,TopAbs_SOLID);
343   myEShMap.Fill(S,TopAbs_EDGE,TopAbs_SHELL);
344   myVFMap.Fill(S,TopAbs_VERTEX,TopAbs_FACE);
345   myVEMap.Fill(S,TopAbs_VERTEX,TopAbs_EDGE);
346   SetParams(Ta,1.e-4,1.e-5,1.e-4,1.e-5,1.e-3);
347   SetContinuity(GeomAbs_C1, Ta);
348 }
349 
350 //=======================================================================
351 //function : SetParams
352 //purpose  :
353 //=======================================================================
354 
SetParams(const Standard_Real Tang,const Standard_Real Tesp,const Standard_Real T2d,const Standard_Real TApp3d,const Standard_Real TolApp2d,const Standard_Real Fleche)355 void ChFi3d_Builder::SetParams(const Standard_Real Tang,
356 			       const Standard_Real Tesp,
357 			       const Standard_Real T2d,
358 			       const Standard_Real TApp3d,
359 			       const Standard_Real TolApp2d,
360 			       const Standard_Real Fleche)
361 {
362   angular = Tang;
363   tolesp = Tesp;
364   tol2d =  T2d;
365   tolapp3d = TApp3d;
366   tolapp2d = TolApp2d;
367   fleche = Fleche;
368 }
369 
370 //=======================================================================
371 //function : SetContinuity
372 //purpose  :
373 //=======================================================================
374 
SetContinuity(const GeomAbs_Shape InternalContinuity,const Standard_Real AngularTolerance)375 void ChFi3d_Builder::SetContinuity(const GeomAbs_Shape InternalContinuity,
376 				   const Standard_Real AngularTolerance)
377 {
378   myConti = InternalContinuity;
379   tolappangle = AngularTolerance;
380 }
381 
382 //=======================================================================
383 //function : IsDone
384 //purpose  :
385 //=======================================================================
386 
IsDone() const387 Standard_Boolean ChFi3d_Builder::IsDone() const
388 {
389   return done;
390 }
391 
392 //=======================================================================
393 //function : Shape
394 //purpose  :
395 //=======================================================================
396 
Shape() const397 TopoDS_Shape ChFi3d_Builder::Shape()const
398 {
399   Standard_NoSuchObject_Raise_if (!done, "ChFi3d_Builder::Shape() - no result");
400   return myShapeResult;
401 }
402 
403 //=======================================================================
404 //function : NbFaultyContours
405 //purpose  :
406 //=======================================================================
407 
NbFaultyContours() const408 Standard_Integer ChFi3d_Builder::NbFaultyContours() const
409 {
410   return badstripes.Extent();
411 }
412 
413 //=======================================================================
414 //function : FaultyContour
415 //purpose  :
416 //=======================================================================
417 
FaultyContour(const Standard_Integer I) const418 Standard_Integer ChFi3d_Builder::FaultyContour(const Standard_Integer I) const
419 {
420   ChFiDS_ListIteratorOfListOfStripe itel;
421   Standard_Integer k = 0;
422   Handle(ChFiDS_Stripe) st;
423   for (itel.Initialize(badstripes);itel.More(); itel.Next()) {
424     k += 1;
425     if(k == I) {
426       st = itel.Value();
427       break;
428     }
429   }
430   if(st.IsNull()) return 0;
431   k = 0;
432   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
433     k += 1;
434     if(st == itel.Value()) return k;
435   }
436   return 0;
437 }
438 
439 //=======================================================================
440 //function : NbComputedSurfaces
441 //purpose  :
442 //=======================================================================
443 
NbComputedSurfaces(const Standard_Integer IC) const444 Standard_Integer ChFi3d_Builder::NbComputedSurfaces(const Standard_Integer IC) const
445 {
446   ChFiDS_ListIteratorOfListOfStripe itel;
447   Standard_Integer k = 0;
448   Handle(ChFiDS_Stripe) st;
449   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
450     k += 1;
451     if(k == IC) {
452       st = itel.Value();
453       break;
454     }
455   }
456   if(st.IsNull()) return 0;
457   if(st->Spine().IsNull()) return 0;
458   Handle(ChFiDS_HData) hd = st->SetOfSurfData();
459   if(hd.IsNull()) return 0;
460   return hd->Length();
461 }
462 
463 //=======================================================================
464 //function : ComputedSurface
465 //purpose  :
466 //=======================================================================
467 
Handle(Geom_Surface)468 Handle(Geom_Surface) ChFi3d_Builder::ComputedSurface(const Standard_Integer IC,
469 						     const Standard_Integer IS) const
470 {
471  ChFiDS_ListIteratorOfListOfStripe itel;
472   Standard_Integer k = 0;
473   Handle(ChFiDS_Stripe) st;
474   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
475     k += 1;
476     if(k == IC) {
477       st = itel.Value();
478       break;
479     }
480   }
481   Handle(ChFiDS_HData) hd = st->SetOfSurfData();
482   Standard_Integer isurf=hd->Value(IS)->Surf();
483   return  myDS->Surface(isurf).Surface();
484 }
485 
486 //=======================================================================
487 //function : NbFaultyVertices
488 //purpose  :
489 //=======================================================================
490 
NbFaultyVertices() const491 Standard_Integer ChFi3d_Builder::NbFaultyVertices() const
492 {
493   return badvertices.Extent();
494 }
495 
496 //=======================================================================
497 //function : FaultyVertex
498 //purpose  :
499 //=======================================================================
500 
FaultyVertex(const Standard_Integer IV) const501 TopoDS_Vertex ChFi3d_Builder::FaultyVertex(const Standard_Integer IV) const
502 {
503   TopTools_ListIteratorOfListOfShape it;
504   TopoDS_Vertex V;
505   Standard_Integer k = 0;
506   for(it.Initialize(badvertices);it.More(); it.Next()) {
507     k += 1;
508     if(k == IV) {
509       V = TopoDS::Vertex(it.Value());
510       break;
511     }
512   }
513   return V;
514 }
515 
516 //=======================================================================
517 //function : HasResult
518 //purpose  :
519 //=======================================================================
520 
HasResult() const521 Standard_Boolean ChFi3d_Builder::HasResult() const
522 {
523   return hasresult;
524 }
525 
526 //=======================================================================
527 //function : BadShape
528 //purpose  :
529 //=======================================================================
530 
BadShape() const531 TopoDS_Shape ChFi3d_Builder::BadShape()const
532 {
533   Standard_NoSuchObject_Raise_if (!hasresult, "ChFi3d_Builder::BadShape() - no result");
534   return badShape;
535 }
536 
537 //=======================================================================
538 //function : StripeStatus
539 //purpose  :
540 //=======================================================================
541 
StripeStatus(const Standard_Integer IC) const542 ChFiDS_ErrorStatus ChFi3d_Builder::StripeStatus(const Standard_Integer IC)const
543 {
544   ChFiDS_ListIteratorOfListOfStripe itel;
545   Standard_Integer k =0;
546   Handle(ChFiDS_Stripe) st;
547   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
548     k += 1;
549     if(k == IC) {
550       st = itel.Value();
551       break;
552     }
553   }
554   ChFiDS_ErrorStatus stat=st->Spine()->ErrorStatus();
555   return stat;
556 }
557 
558 //=======================================================================
559 //function : Builder
560 //purpose  :
561 //=======================================================================
562 
Handle(TopOpeBRepBuild_HBuilder)563 Handle(TopOpeBRepBuild_HBuilder) ChFi3d_Builder::Builder()const
564 {
565   return myCoup;
566 }
567 
568 //=======================================================================
569 //function : ChFi3d_FaceTangency
570 //purpose  : determine if the faces opposing to edges are tangent
571 //           to go from opposing faces on e0 to opposing faces
572 //           on e1, consider all faces starting at a common top.
573 //=======================================================================
574 
FaceTangency(const TopoDS_Edge & E0,const TopoDS_Edge & E1,const TopoDS_Vertex & V) const575 Standard_Boolean ChFi3d_Builder::FaceTangency(const TopoDS_Edge& E0,
576 					      const TopoDS_Edge& E1,
577 					      const TopoDS_Vertex& V) const
578 {
579   TopTools_ListIteratorOfListOfShape It,Jt;
580   TopoDS_Edge Ec;
581   Standard_Integer Nbf;
582   TopoDS_Face F[2];
583 
584   //It is checked if the connection is not on a regular edge.
585   for (It.Initialize(myEFMap(E1)), Nbf= 0 ;It.More();It.Next(), Nbf++) {
586     if (Nbf>1)
587       throw Standard_ConstructionError("ChFi3d_Builder:only 2 faces");
588     F[Nbf] = TopoDS::Face(It.Value());
589   }
590   if(Nbf < 2) return Standard_False;
591 //  Modified by Sergey KHROMOV - Fri Dec 21 17:44:19 2001 Begin
592 //if (BRep_Tool::Continuity(E1,F[0],F[1]) != GeomAbs_C0) {
593   if (ChFi3d::IsTangentFaces(E1,F[0],F[1])) {
594 //  Modified by Sergey KHROMOV - Fri Dec 21 17:44:21 2001 End
595     return Standard_False;
596   }
597 
598   for (Jt.Initialize(myVEMap(V));Jt.More();Jt.Next()) {
599     Ec = TopoDS::Edge(Jt.Value());
600     if (!Ec.IsSame(E0) && !Ec.IsSame(E1) &&
601 	Ec.Orientation() != TopAbs_INTERNAL &&
602 	Ec.Orientation() != TopAbs_EXTERNAL &&
603 	!BRep_Tool::Degenerated(Ec)) {
604       for (It.Initialize(myEFMap(Ec)), Nbf= 0 ;It.More();It.Next(), Nbf++) {
605 	if (Nbf>1)
606 	  throw Standard_ConstructionError("ChFi3d_Builder:only 2 faces");
607 	F[Nbf] = TopoDS::Face(It.Value());
608       }
609       if(Nbf < 2) return Standard_False;
610 //  Modified by Sergey KHROMOV - Tue Dec 18 18:10:40 2001 Begin
611 //    if (BRep_Tool::Continuity(Ec,F[0],F[1]) < GeomAbs_G1) {
612       if (!ChFi3d::IsTangentFaces(Ec,F[0],F[1])) {
613 //  Modified by Sergey KHROMOV - Tue Dec 18 18:10:41 2001 End
614 	return Standard_False;
615       }
616     }
617   }
618   return Standard_True;
619 
620 }
621 
622 
623 //=======================================================================
624 //function : TangentExtremity
625 //purpose  : Test if 2 faces are tangent at the end of an edge
626 //=======================================================================
TangentExtremity(const TopoDS_Vertex & V,const TopoDS_Edge & E,const Handle (BRepAdaptor_Surface)& hs1,const Handle (BRepAdaptor_Surface)& hs2,const Standard_Real tang)627 static Standard_Boolean TangentExtremity(const TopoDS_Vertex&                V,
628 					 const TopoDS_Edge&                  E,
629 					 const Handle(BRepAdaptor_Surface)& hs1,
630 					 const Handle(BRepAdaptor_Surface)& hs2,
631 //					 const Standard_Real                 t3d,
632 					 const Standard_Real                 tang)
633 {
634   TopoDS_Face f1 = hs1->Face();
635   TopAbs_Orientation O1 = f1.Orientation();
636   f1.Orientation(TopAbs_FORWARD);
637   TopoDS_Face f2 = hs2->Face();
638   TopAbs_Orientation O2 = f2.Orientation();
639   f2.Orientation(TopAbs_FORWARD);
640   TopoDS_Edge e1 = E, e2 = E;
641   e1.Orientation(TopAbs_FORWARD);
642   e2.Orientation(TopAbs_FORWARD);
643   if(f1.IsSame(f2) && BRep_Tool::IsClosed(e1,f1))
644     e2.Orientation(TopAbs_REVERSED);
645   Standard_Real p1 = BRep_Tool::Parameter(V,e1,f1);
646   Standard_Real p2 = BRep_Tool::Parameter(V,e2,f2);
647   Standard_Real u,v,f,l, Eps = 1.e-9;
648   gp_Vec n1, n2;//   gp_Pnt pt1,pt2;
649   Handle(Geom2d_Curve) pc1 = BRep_Tool::CurveOnSurface(e1,f1,f,l);
650   pc1->Value(p1).Coord(u,v);
651   BRepLProp_SLProps theProp1 (*hs1, u, v, 1, Eps);
652   if  (theProp1.IsNormalDefined()) {
653     n1.SetXYZ(theProp1.Normal().XYZ());
654     if (O1 == TopAbs_REVERSED) n1.Reverse();
655   }
656   else return Standard_False; // It is not known...
657 
658 
659   Handle(Geom2d_Curve) pc2 = BRep_Tool::CurveOnSurface(e2,f2,f,l);
660   pc2->Value(p2).Coord(u,v);
661   BRepLProp_SLProps theProp2 (*hs2, u, v, 1, Eps);
662   if  (theProp2.IsNormalDefined()) {
663     n2.SetXYZ(theProp2.Normal().XYZ());
664     if(O2 == TopAbs_REVERSED) n2.Reverse();
665   }
666   else return Standard_False; //  It is not known...
667 
668   return (n1.Angle(n2) < tang);
669 }
670 
671 //=======================================================================
672 //function : TangentOnVertex
673 //purpose  : Test if support faces of an edge are tangent at end.
674 //=======================================================================
TangentOnVertex(const TopoDS_Vertex & V,const TopoDS_Edge & E,const ChFiDS_Map & EFMap,const Standard_Real tang)675 static Standard_Boolean TangentOnVertex(const TopoDS_Vertex&    V,
676 					const TopoDS_Edge&      E,
677 					const ChFiDS_Map&       EFMap,
678 					const Standard_Real     tang)
679 {
680   TopoDS_Face ff1,ff2;
681   ChFi3d_conexfaces(E,ff1,ff2,EFMap);
682   if(ff1.IsNull() || ff2.IsNull()) return 0;
683   Handle(BRepAdaptor_Surface) S1 = new (BRepAdaptor_Surface)(ff1);
684   Handle(BRepAdaptor_Surface) S2 = new (BRepAdaptor_Surface)(ff2);
685   return TangentExtremity(V, E, S1, S2, tang);
686 }
687 
688 //=======================================================================
689 //function : PerformExtremity
690 //purpose  : In case if PerformElement returned BreakPoint at one or
691 //           another extremity, it is attempted to refine
692 //           depending on concavities between neighbour faces of the top.
693 //=======================================================================
694 
PerformExtremity(const Handle (ChFiDS_Spine)& Spine)695 void ChFi3d_Builder::PerformExtremity (const Handle(ChFiDS_Spine)& Spine)
696 {
697   Standard_Integer NbG1Connections = 0;
698 
699   for(Standard_Integer ii = 1; ii <= 2; ii++){
700     TopoDS_Edge E[3];
701     TopoDS_Vertex V;
702     ChFiDS_State sst;
703     Standard_Integer iedge;
704     Handle(BRepAdaptor_Surface) hs1,hs2;
705     if(ii == 1){
706       sst = Spine->FirstStatus();
707       iedge = 1;
708       V = Spine->FirstVertex();
709     }
710     else{
711       sst = Spine->LastStatus();
712       iedge = Spine->NbEdges();
713       E[0] = Spine->Edges(iedge);
714       V = Spine->LastVertex();
715     }
716     //Before all it is checked if the tangency is not dead.
717     E[0] = Spine->Edges(iedge);
718     ConexFaces (Spine,iedge,hs1,hs2);
719     if(TangentExtremity(V,E[0],hs1,hs2,angular)){
720       Spine->SetTangencyExtremity(Standard_True, (ii == 1));
721     }
722 
723     if(sst == ChFiDS_BreakPoint){
724       TopTools_ListIteratorOfListOfShape It;//,Jt;
725       Standard_Boolean sommetpourri = Standard_False;
726       TopTools_IndexedMapOfOrientedShape EdgesOfV;
727       TopTools_MapOfShape Edges;
728       Edges.Add(E[0]);
729       EdgesOfV.Add(E[0]);
730       Standard_Integer IndOfE = 0;
731       for (It.Initialize(myVEMap(V)); It.More(); It.Next())
732       {
733         TopoDS_Edge anEdge = TopoDS::Edge(It.Value());
734         if (BRep_Tool::Degenerated(anEdge))
735           continue;
736         TopoDS_Face F1, F2;
737         ChFi3d_conexfaces(anEdge, F1, F2, myEFMap);
738         if (!F2.IsNull() && ChFi3d::IsTangentFaces(anEdge, F1, F2, GeomAbs_G2)) //smooth edge
739         {
740           if (!F1.IsSame(F2))
741             NbG1Connections++;
742           continue;
743         }
744 
745         if (Edges.Add(anEdge))
746         {
747           EdgesOfV.Add(anEdge);
748           if (IndOfE < 2)
749           {
750             IndOfE++;
751             E[IndOfE] = anEdge;
752           }
753         }
754         else
755         {
756           TopoDS_Vertex V1, V2;
757           TopExp::Vertices(anEdge, V1, V2);
758           if (V1.IsSame(V2)) //edge is closed - two ends of the edge in the vertex
759           {
760             Standard_Integer anInd = EdgesOfV.FindIndex(anEdge);
761             if (anInd == 0)
762               anInd = EdgesOfV.FindIndex(anEdge.Reversed());
763             anEdge = TopoDS::Edge(EdgesOfV(anInd));
764             anEdge.Reverse();
765             if (EdgesOfV.Add(anEdge))
766             {
767               if (IndOfE < 2)
768               {
769                 IndOfE++;
770                 E[IndOfE] = anEdge;
771               }
772             }
773           }
774         }
775       }
776 
777       if (EdgesOfV.Extent() != 3)
778         sommetpourri = Standard_True;
779 
780       if(!sommetpourri){
781 	sst = ChFi3d_EdgeState(E,myEFMap);
782       }
783       if(ii==1)Spine->SetFirstStatus(sst);
784       else Spine->SetLastStatus(sst);
785     }
786   }
787 
788   if (!Spine->IsPeriodic()) {
789     TopTools_ListIteratorOfListOfShape It,Jt;
790     Standard_Integer nbf = 0, jf = 0;
791     for (It.Initialize(myVFMap(Spine->FirstVertex())); It.More(); It.Next()){
792       jf++;
793       Standard_Integer kf = 1;
794       const TopoDS_Shape& cur = It.Value();
795       for (Jt.Initialize(myVFMap(Spine->FirstVertex())); Jt.More() && (kf < jf); Jt.Next(), kf++){
796 	if(cur.IsSame(Jt.Value())) break;
797       }
798       if(kf == jf) nbf++;
799     }
800     nbf -= NbG1Connections;
801     if(nbf>3) {
802       Spine->SetFirstStatus(ChFiDS_BreakPoint);
803 #ifdef OCCT_DEBUG
804       std::cout<<"top has : "<<nbf<<" faces."<<std::endl;
805 #endif
806     }
807     nbf = 0, jf = 0;
808     for (It.Initialize(myVFMap(Spine->LastVertex())); It.More(); It.Next()){
809       jf++;
810       Standard_Integer kf = 1;
811       const TopoDS_Shape& cur = It.Value();
812       for (Jt.Initialize(myVFMap(Spine->LastVertex())); Jt.More() && (kf < jf); Jt.Next(), kf++){
813 	if(cur.IsSame(Jt.Value())) break;
814       }
815       if(kf == jf) nbf++;
816     }
817     nbf -= NbG1Connections;
818     if(nbf>3) {
819       Spine->SetLastStatus(ChFiDS_BreakPoint);
820 #ifdef OCCT_DEBUG
821       std::cout<<"top has : "<<nbf<<" faces."<<std::endl;
822 #endif
823     }
824   }
825 }
826 
827 //=======================================================================
828 //function : PerformElement
829 //purpose  :  find all mutually tangent edges ;
830 // Each edge has 2 opposing faces. For 2 adjacent tangent edges it is required that
831 // the opposing faces were tangent.
832 //=======================================================================
833 
PerformElement(const Handle (ChFiDS_Spine)& Spine,const Standard_Real Offset,const TopoDS_Face & theFirstFace)834 Standard_Boolean ChFi3d_Builder::PerformElement(const Handle(ChFiDS_Spine)& Spine,
835                                                 const Standard_Real         Offset,
836                                                 const TopoDS_Face&          theFirstFace)
837 {
838   Standard_Real ta = angular;
839   TopTools_ListIteratorOfListOfShape It;
840   Standard_Integer Nbface;
841   TopTools_ListIteratorOfListOfShape Jt;
842   Standard_Real Wl,Wf;
843   Standard_Boolean degeneOnEc;
844   gp_Pnt P2;
845   gp_Vec V1,V2;
846   TopoDS_Vertex Ve1,VStart,FVEc,LVEc,FVEv,LVEv;
847   TopoDS_Edge Ev,Ec(Spine->Edges(1));
848   if(BRep_Tool::Degenerated(Ec)) return 0;
849   //it is checked if the edge is a cut edge
850   TopoDS_Face ff1,ff2;
851   ChFi3d_conexfaces(Ec,ff1,ff2,myEFMap);
852   if(ff1.IsNull() || ff2.IsNull()) return 0;
853 //  Modified by Sergey KHROMOV - Fri Dec 21 17:46:22 2001 End
854 //if(BRep_Tool::Continuity(Ec,ff1,ff2) != GeomAbs_C0) return 0;
855   if (ChFi3d::IsTangentFaces(Ec,ff1,ff2)) return 0;
856 //  Modified by Sergey KHROMOV - Fri Dec 21 17:46:24 2001 Begin
857 
858   TopoDS_Face FirstFace = ff1;
859   if (!theFirstFace.IsNull() && ff2.IsSame(theFirstFace))
860   {
861     FirstFace = ff2;
862     ff2 = ff1; ff1 = FirstFace;
863   }
864   myEdgeFirstFace.Bind(Ec, FirstFace);
865 
866   //Define concavity
867   ChFiDS_TypeOfConcavity TypeOfConcavity = ChFi3d::DefineConnectType(Ec, ff1, ff2,
868                                                                      1.e-5, Standard_True);
869   Spine->SetTypeOfConcavity(TypeOfConcavity);
870 
871   Standard_Boolean ToRestrict = (Offset > 0)? Standard_True : Standard_False;
872   BRepAdaptor_Surface Sb1(ff1, ToRestrict);
873   BRepAdaptor_Surface Sb2(ff2, ToRestrict);
874   if (Offset > 0)
875   {
876     TopoDS_Edge OffsetEdge = MakeOffsetEdge(Ec, Offset, Sb1, Sb2);
877     OffsetEdge.Orientation(Ec.Orientation());
878     Spine->SetOffsetEdges(OffsetEdge);
879   }
880 
881   BRepAdaptor_Curve CEc,CEv;
882   TopAbs_Orientation curor = Ec.Orientation();
883   TopExp::Vertices(Ec,VStart,LVEc);
884 
885 
886   Standard_Boolean Fini = Standard_False;
887   Standard_Integer Nb;
888   ChFiDS_State CurSt = ChFiDS_Closed;
889   if (VStart.IsSame(LVEc)) {//case if only one edge is closed
890     CEc.Initialize(Ec);
891     Wl = BRep_Tool::Parameter(VStart,Ec);
892     CEc.D1(Wl,P2,V1);
893     Wl = BRep_Tool::Parameter(LVEc,Ec);
894     CEc.D1(Wl,P2,V2);
895     Standard_Boolean IsFaceTangency = FaceTangency(Ec,Ec,VStart);
896     if (V1.IsParallel(V2,ta) ||
897         IsFaceTangency)
898     {
899       if (IsFaceTangency) {
900 	CurSt = ChFiDS_Closed;
901       }
902       else {
903 	CurSt = ChFiDS_BreakPoint;
904       }
905     }
906     else {
907       CurSt = ChFiDS_BreakPoint;
908     }
909     Spine->SetLastStatus(CurSt);
910     Spine->SetFirstStatus(CurSt);
911   }
912   else { // Downstream progression
913     FVEc = VStart;
914     TopAbs_Orientation Or1;
915     while (!Fini) {
916       CurSt = ChFiDS_FreeBoundary;
917       Wl = BRep_Tool::Parameter(LVEc,Ec);
918       degeneOnEc = TangentOnVertex(LVEc, Ec, myEFMap, ta);
919       CEc.Initialize(Ec);
920       CEc.D1(Wl,P2,V1);
921       Nb = Spine->NbEdges();
922 
923       for (It.Initialize(myVEMap(LVEc));It.More();It.Next()) {
924 	Ev = TopoDS::Edge(It.Value());
925 	if (!Ev.IsSame(Ec) && !BRep_Tool::Degenerated(Ev)){
926 	  TopExp::Vertices(Ev,FVEv,LVEv);
927 	  if (LVEc.IsSame(LVEv)) {
928 	    Ve1 = FVEv;
929 	    FVEv = LVEv;
930 	    LVEv = Ve1;
931 	    Or1 = TopAbs_REVERSED;
932 	  }
933 	  else Or1 = TopAbs_FORWARD;
934 
935 	  Wf = BRep_Tool::Parameter(FVEv,Ev);
936 	  CEv.Initialize(Ev);
937 	  CEv.D1(Wf,P2,V2);
938 	  Standard_Real av1v2 = V1.Angle(V2);
939 	  Standard_Boolean rev = (Or1 != curor);
940 	  Standard_Boolean OnAjoute = Standard_False;
941 	  if (FaceTangency(Ec,Ev,FVEv)) {
942 	    // there is no need of tolerance
943 	    // to make a decision (PRO9486) the regularity is enough.
944             // However, the abcense of turn-back is checked (PRO9810)
945 	    OnAjoute = ((!rev && av1v2 < M_PI/2)
946 			||(rev && av1v2 > M_PI/2));
947             // mate attention to the single case (cf CTS21610_1)
948             if (OnAjoute && (degeneOnEc ||
949                 TangentOnVertex(LVEc, Ev,myEFMap, ta)) )
950 	      OnAjoute=((!rev && av1v2 < ta) || (rev && (M_PI - av1v2) < ta));
951 	  }
952 	  if (OnAjoute) {
953 	    Fini = Standard_False; // If this can be useful (Cf PRO14713)
954             TopoDS_Vertex CommonVertex;
955             TopExp::CommonVertex(Ec, Ev, CommonVertex);
956             TopoDS_Edge PrevEdge = Ec;
957 	    Ec = Ev;
958 //	    Ec = TopoDS::Edge(Ev);
959 	    Ec.Orientation(Or1);
960 	    Wl = Wf; LVEc = LVEv;
961 	    Spine->SetEdges(Ec);
962             TopoDS_Face CurF1, CurF2;
963             ChFi3d_conexfaces(Ec,CurF1,CurF2,myEFMap);
964             ReorderFaces(CurF1, CurF2, FirstFace, PrevEdge, CommonVertex, myEFMap);
965             myEdgeFirstFace.Bind(Ec, CurF1);
966             if (Offset > 0)
967             {
968               BRepAdaptor_Surface CurSb1(CurF1), CurSb2(CurF2);
969               TopoDS_Edge anOffsetEdge = MakeOffsetEdge(Ec, Offset, CurSb1, CurSb2);
970               anOffsetEdge.Orientation(Or1);
971               Spine->SetOffsetEdges(anOffsetEdge);
972             }
973             FirstFace = CurF1;
974 	    curor = Or1;
975 	    if (VStart.IsSame(LVEv)) {
976 	      if (FaceTangency(Ev,Spine->Edges(1),LVEv)) {
977 		CurSt = ChFiDS_Closed; Fini = Standard_True;
978 	      }
979 	      else {
980 		CurSt = ChFiDS_BreakPoint;Fini = Standard_True;
981 	      }
982 	    }
983 	    break;
984 	  }
985 	  else {
986 	    for (Jt.Initialize(myEFMap(Ev)), Nbface= 0 ;Jt.More();Jt.Next(),
987 		 Nbface++) {}
988 	    if (Nbface> 1) CurSt = ChFiDS_BreakPoint;
989 	    Fini = ((!rev && av1v2 < ta) || (rev && (M_PI - av1v2) < ta));
990 	  }
991 	}
992       }
993       Fini = Fini || (Nb == Spine->NbEdges());
994     }
995     Spine->SetLastStatus(CurSt);
996     if (CurSt == ChFiDS_Closed) {
997       Spine->SetFirstStatus(CurSt);
998     }
999     else {// Upstream progression
1000       Fini = Standard_False;
1001       Ec = Spine->Edges(1);
1002       FirstFace = TopoDS::Face(myEdgeFirstFace(Ec));
1003       curor = Ec.Orientation();
1004       FVEc = VStart;
1005       while (!Fini) {
1006 	CurSt = ChFiDS_FreeBoundary;
1007 	Wl = BRep_Tool::Parameter(FVEc,Ec);
1008 	degeneOnEc = TangentOnVertex(FVEc, Ec, myEFMap, ta);
1009 	CEc.Initialize(Ec);
1010 	CEc.D1(Wl,P2,V1);
1011 	Nb = Spine->NbEdges();
1012 
1013 	for (It.Initialize(myVEMap(FVEc));It.More();It.Next()) {
1014 	  Ev = TopoDS::Edge(It.Value());
1015 	  if (!Ev.IsSame(Ec) && !BRep_Tool::Degenerated(Ev)) {
1016 	    TopExp::Vertices(Ev,FVEv,LVEv);
1017 	    if (FVEc.IsSame(FVEv)) {
1018 	      Ve1 = FVEv;
1019 	      FVEv = LVEv;
1020 	      LVEv = Ve1;
1021 	      Or1 = TopAbs_REVERSED;
1022 	    }
1023 	    else {
1024 	      Or1 = TopAbs_FORWARD;
1025 	    }
1026 	    Wf = BRep_Tool::Parameter(LVEv,Ev);
1027 	    CEv.Initialize(Ev);
1028 	    CEv.D1(Wf,P2,V2);
1029 	    Standard_Real av1v2 = V1.Angle(V2);
1030 	    Standard_Boolean rev = (Or1 != curor);
1031             Standard_Boolean OnAjoute =  Standard_False;
1032 	    if (FaceTangency(Ec,Ev,LVEv)) {
1033 	      OnAjoute = ((!rev && av1v2 < M_PI/2)
1034 			||(rev && av1v2 > M_PI/2));
1035             if (OnAjoute && (degeneOnEc ||
1036                 TangentOnVertex(FVEc, Ev,myEFMap, ta)) )
1037 	      OnAjoute=((!rev && av1v2 < ta) || (rev && (M_PI-av1v2) < ta));
1038 	    }
1039 	    if  (OnAjoute) {
1040               TopoDS_Vertex CommonVertex;
1041               TopExp::CommonVertex(Ec, Ev, CommonVertex);
1042               TopoDS_Edge PrevEdge = Ec;
1043 	      Ec = Ev;
1044 //	      Ec = TopoDS::Edge(Ev);
1045 	      Ec.Orientation(Or1);
1046 	      Wl = Wf; FVEc = FVEv;
1047 	      Spine->PutInFirst(Ec);
1048               TopoDS_Face CurF1, CurF2;
1049               ChFi3d_conexfaces(Ec,CurF1,CurF2,myEFMap);
1050               ReorderFaces(CurF1, CurF2, FirstFace, PrevEdge, CommonVertex, myEFMap);
1051               myEdgeFirstFace.Bind(Ec, CurF1);
1052               if (Offset > 0)
1053               {
1054                 BRepAdaptor_Surface CurSb1(CurF1), CurSb2(CurF2);
1055                 TopoDS_Edge anOffsetEdge = MakeOffsetEdge(Ec, Offset, CurSb1, CurSb2);
1056                 anOffsetEdge.Orientation(Or1);
1057                 Spine->PutInFirstOffset(anOffsetEdge);
1058               }
1059               FirstFace = CurF1;
1060 	      curor = Or1;
1061 	      break;
1062 	    }
1063 	    else {
1064 	      for(Jt.Initialize(myEFMap(Ev)),Nbface= 0 ;Jt.More();Jt.Next(),
1065 		  Nbface++) {}
1066 	      if (Nbface> 1) CurSt = ChFiDS_BreakPoint;
1067 	      Fini = ((!rev && av1v2 < ta) || (rev && (M_PI - av1v2) < ta));
1068 	    }
1069 	  }
1070 	}
1071 	Fini = Fini || (Nb == Spine->NbEdges());
1072       }
1073       Spine->SetFirstStatus(CurSt);
1074     }
1075   }
1076   return 1;
1077 }
1078 
1079 //=======================================================================
1080 //function : Remove
1081 //purpose  :
1082 //=======================================================================
1083 
Remove(const TopoDS_Edge & E)1084 void  ChFi3d_Builder::Remove(const TopoDS_Edge& E)
1085 {
1086   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
1087 
1088   for ( ; itel.More(); itel.Next()) {
1089     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
1090     for (Standard_Integer j = 1; j <= sp->NbEdges(); j++){
1091       if (E.IsSame(sp->Edges(j))){
1092 	myListStripe.Remove(itel);
1093 	return;
1094       }
1095     }
1096   }
1097 }
1098 
1099 
1100 //=======================================================================
1101 //function : Value
1102 //purpose  :
1103 //=======================================================================
1104 
Handle(ChFiDS_Spine)1105 Handle(ChFiDS_Spine) ChFi3d_Builder::Value
1106 (const Standard_Integer I)const
1107 {
1108   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
1109   for (Standard_Integer ic = 1; ic < I; ic++) {itel.Next();}
1110   return itel.Value()->Spine();
1111 }
1112 
1113 //=======================================================================
1114 //function : NbElements
1115 //purpose  :
1116 //=======================================================================
1117 
NbElements() const1118 Standard_Integer ChFi3d_Builder::NbElements()const
1119 {
1120   Standard_Integer i = 0;
1121   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
1122   for ( ;itel.More(); itel.Next()){
1123     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
1124     if(sp.IsNull()) break;
1125     i++;
1126   }
1127   return i;
1128 }
1129 
1130 //=======================================================================
1131 //function : Contains
1132 //purpose  :
1133 //=======================================================================
1134 
Contains(const TopoDS_Edge & E) const1135 Standard_Integer ChFi3d_Builder::Contains(const TopoDS_Edge& E)const
1136 {
1137   Standard_Integer i = 1,j;
1138   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
1139   for ( ;itel.More(); itel.Next(), i++){
1140     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
1141     if(sp.IsNull()) break;
1142     for (j = 1; j <= sp->NbEdges(); j++){
1143       if(E.IsSame(sp->Edges(j))) return i;
1144     }
1145   }
1146   return 0;
1147 }
1148 
1149 //=======================================================================
1150 //function : Contains
1151 //purpose  :
1152 //=======================================================================
1153 
Contains(const TopoDS_Edge & E,Standard_Integer & IndexInSpine) const1154 Standard_Integer ChFi3d_Builder::Contains(const TopoDS_Edge& E,
1155 					  Standard_Integer&  IndexInSpine)const
1156 {
1157   Standard_Integer i = 1,j;
1158   IndexInSpine = 0;
1159   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
1160   for ( ;itel.More(); itel.Next(), i++){
1161     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
1162     if(sp.IsNull()) break;
1163     for (j = 1; j <= sp->NbEdges(); j++){
1164       if(E.IsSame(sp->Edges(j)))
1165 	{
1166 	  IndexInSpine = j;
1167 	  return i;
1168 	}
1169     }
1170   }
1171   return 0;
1172 }
1173 
1174 //=======================================================================
1175 //function : Length
1176 //purpose  :
1177 //=======================================================================
1178 
Length(const Standard_Integer IC) const1179 Standard_Real ChFi3d_Builder::Length(const Standard_Integer IC)const
1180 {
1181   if(IC <= NbElements()){
1182     const Handle(ChFiDS_Spine)& sp = Value(IC);
1183     return sp->LastParameter(sp->NbEdges());
1184   }
1185   return -1;
1186 }
1187 
1188 
1189 //=======================================================================
1190 //function : FirstVertex
1191 //purpose  :
1192 //=======================================================================
1193 
FirstVertex(const Standard_Integer IC) const1194 TopoDS_Vertex ChFi3d_Builder::FirstVertex(const Standard_Integer IC) const
1195 {
1196   if(IC <= NbElements()){
1197     return Value(IC)->FirstVertex();
1198   }
1199   return TopoDS_Vertex();
1200 }
1201 
1202 //=======================================================================
1203 //function : LastVertex
1204 //purpose  :
1205 //=======================================================================
1206 
LastVertex(const Standard_Integer IC) const1207 TopoDS_Vertex ChFi3d_Builder::LastVertex(const Standard_Integer IC) const
1208 {
1209   if(IC <= NbElements()){
1210     return Value(IC)->LastVertex();
1211   }
1212   return TopoDS_Vertex();
1213 }
1214 
1215 //=======================================================================
1216 //function : Abscissa
1217 //purpose  :
1218 //=======================================================================
1219 
Abscissa(const Standard_Integer IC,const TopoDS_Vertex & V) const1220 Standard_Real ChFi3d_Builder::Abscissa(const Standard_Integer IC,
1221 				       const TopoDS_Vertex& V) const
1222 {
1223   if(IC <= NbElements()){
1224     return Value(IC)->Absc(V);
1225   }
1226   return -1;
1227 }
1228 
1229 //=======================================================================
1230 //function : RelativeAbscissa
1231 //purpose  :
1232 //=======================================================================
1233 
RelativeAbscissa(const Standard_Integer IC,const TopoDS_Vertex & V) const1234 Standard_Real ChFi3d_Builder::RelativeAbscissa(const Standard_Integer IC,
1235 					       const TopoDS_Vertex& V) const
1236 {
1237   if(IC <= NbElements()){
1238     return Abscissa(IC,V)/Length(IC);
1239   }
1240   return -1;
1241 }
1242 
1243 //=======================================================================
1244 //function : Closed
1245 //purpose  :
1246 //=======================================================================
1247 
Closed(const Standard_Integer IC) const1248 Standard_Boolean ChFi3d_Builder::Closed(const Standard_Integer IC)const
1249 {
1250   if(IC <= NbElements()){
1251     return Value(IC)->IsClosed();
1252   }
1253   return Standard_False;
1254 }
1255 
1256 //=======================================================================
1257 //function : ClosedAndTangent
1258 //purpose  :
1259 //=======================================================================
1260 
ClosedAndTangent(const Standard_Integer IC) const1261 Standard_Boolean ChFi3d_Builder::ClosedAndTangent
1262 (const Standard_Integer IC)const
1263 {
1264   if(IC <= NbElements()){
1265     return Value(IC)->IsPeriodic();
1266   }
1267   return Standard_False;
1268 }
1269 
1270