0026173: Wrong result of ChFi3d_ChBuilder algorithm: incorrect processing of G1 junct...
[occt.git] / src / ChFi3d / ChFi3d_Builder_1.cxx
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_HCurve2d.hxx>
19 #include <Adaptor3d_HSurface.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_HCurve2d.hxx>
32 #include <BRepAdaptor_HSurface.hxx>
33 #include <BRepAdaptor_Surface.hxx>
34 #include <BRepBlend_Line.hxx>
35 #include <BRepLProp_SLProps.hxx>
36 #include <BRepTopAdaptor_TopolTool.hxx>
37 #include <ChFi3d.hxx>
38 #include <ChFi3d_Builder.hxx>
39 #include <ChFi3d_Builder_0.hxx>
40 #include <ChFiDS_CommonPoint.hxx>
41 #include <ChFiDS_ErrorStatus.hxx>
42 #include <ChFiDS_FilSpine.hxx>
43 #include <ChFiDS_HData.hxx>
44 #include <ChFiDS_HElSpine.hxx>
45 #include <ChFiDS_ListIteratorOfListOfStripe.hxx>
46 #include <ChFiDS_ListIteratorOfRegularities.hxx>
47 #include <ChFiDS_Regul.hxx>
48 #include <ChFiDS_Spine.hxx>
49 #include <ChFiDS_State.hxx>
50 #include <ChFiDS_Stripe.hxx>
51 #include <ChFiDS_SurfData.hxx>
52 #include <Geom2d_Curve.hxx>
53 #include <Geom_Surface.hxx>
54 #include <gp_Pnt.hxx>
55 #include <gp_Pnt2d.hxx>
56 #include <gp_Vec.hxx>
57 #include <LocalAnalysis_SurfaceContinuity.hxx>
58 #include <Precision.hxx>
59 #include <Standard_ConstructionError.hxx>
60 #include <Standard_NoSuchObject.hxx>
61 #include <Standard_OutOfRange.hxx>
62 #include <TopAbs.hxx>
63 #include <TopAbs_Orientation.hxx>
64 #include <TopAbs_ShapeEnum.hxx>
65 #include <TopExp.hxx>
66 #include <TopoDS.hxx>
67 #include <TopoDS_Edge.hxx>
68 #include <TopoDS_Face.hxx>
69 #include <TopoDS_Shape.hxx>
70 #include <TopoDS_Vertex.hxx>
71 #include <TopOpeBRepBuild_HBuilder.hxx>
72 #include <TopOpeBRepDS_HDataStructure.hxx>
73 #include <TopOpeBRepDS_Surface.hxx>
74 #include <TopOpeBRepTool_TOOL.hxx>
75 #include <TopTools_ListIteratorOfListOfShape.hxx>
76
77 #ifdef OCCT_DEBUG
78 extern Standard_Boolean ChFi3d_GetcontextFORCEBLEND(); 
79 #endif
80
81 static TopOpeBRepDS_BuildTool mkbuildtool()
82 {
83   TopOpeBRepTool_GeomTool GT2(TopOpeBRepTool_BSPLINE1,
84                               Standard_True,
85                               Standard_False,
86                               Standard_False);
87   TopOpeBRepDS_BuildTool BT(GT2);
88   BT.OverWrite(Standard_False);
89   BT.Translate(Standard_False);
90   return BT;
91 }
92
93 //=======================================================================
94 //function : ChFi3d_Builder
95 //purpose  : 
96 //=======================================================================
97 ChFi3d_Builder::ChFi3d_Builder(const TopoDS_Shape& S,
98                                const Standard_Real Ta) :  
99    done(Standard_False), myShape(S)
100 {
101   myDS = new TopOpeBRepDS_HDataStructure();
102   myCoup = new TopOpeBRepBuild_HBuilder(mkbuildtool());
103   myEFMap.Fill(S,TopAbs_EDGE,TopAbs_FACE);
104   myESoMap.Fill(S,TopAbs_EDGE,TopAbs_SOLID);
105   myEShMap.Fill(S,TopAbs_EDGE,TopAbs_SHELL);
106   myVFMap.Fill(S,TopAbs_VERTEX,TopAbs_FACE);
107   myVEMap.Fill(S,TopAbs_VERTEX,TopAbs_EDGE);
108   SetParams(Ta,1.e-4,1.e-5,1.e-4,1.e-5,1.e-3);
109   SetContinuity(GeomAbs_C1, Ta);
110 }
111
112 //=======================================================================
113 //function : SetParams
114 //purpose  : 
115 //=======================================================================
116
117 void ChFi3d_Builder::SetParams(const Standard_Real Tang, 
118                                const Standard_Real Tesp, 
119                                const Standard_Real T2d, 
120                                const Standard_Real TApp3d, 
121                                const Standard_Real TolApp2d, 
122                                const Standard_Real Fleche)
123 {
124   angular = Tang;
125   tolesp = Tesp;
126   tol2d =  T2d;
127   tolapp3d = TApp3d;
128   tolapp2d = TolApp2d;
129   fleche = Fleche;
130 }
131
132 //=======================================================================
133 //function : SetContinuity
134 //purpose  : 
135 //=======================================================================
136
137 void ChFi3d_Builder::SetContinuity(const GeomAbs_Shape InternalContinuity,
138                                    const Standard_Real AngularTolerance)
139 {
140   myConti = InternalContinuity;
141   tolappangle = AngularTolerance;
142 }
143
144 //=======================================================================
145 //function : IsDone
146 //purpose  : 
147 //=======================================================================
148
149 Standard_Boolean ChFi3d_Builder::IsDone() const 
150 {
151   return done;
152 }
153
154 //=======================================================================
155 //function : Shape
156 //purpose  : 
157 //=======================================================================
158
159 TopoDS_Shape ChFi3d_Builder::Shape()const
160 {
161   Standard_NoSuchObject_Raise_if(!done,"");  
162   return myShapeResult;
163 }
164
165 //=======================================================================
166 //function : NbFaultyContours
167 //purpose  : 
168 //=======================================================================
169
170 Standard_Integer ChFi3d_Builder::NbFaultyContours() const
171 {
172   return badstripes.Extent();
173 }
174
175 //=======================================================================
176 //function : FaultyContour
177 //purpose  : 
178 //=======================================================================
179
180 Standard_Integer ChFi3d_Builder::FaultyContour(const Standard_Integer I) const
181 {
182   ChFiDS_ListIteratorOfListOfStripe itel;
183   Standard_Integer k = 0;
184   Handle(ChFiDS_Stripe) st;
185   for (itel.Initialize(badstripes);itel.More(); itel.Next()) {
186     k += 1;
187     if(k == I) {
188       st = itel.Value();
189       break;
190     }
191   }
192   if(st.IsNull()) return 0;
193   k = 0;
194   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
195     k += 1;
196     if(st == itel.Value()) return k;
197   }
198   return 0;
199 }
200
201 //=======================================================================
202 //function : NbComputedSurfaces
203 //purpose  : 
204 //=======================================================================
205
206 Standard_Integer ChFi3d_Builder::NbComputedSurfaces(const Standard_Integer IC) const
207 {
208   ChFiDS_ListIteratorOfListOfStripe itel;
209   Standard_Integer k = 0;
210   Handle(ChFiDS_Stripe) st;
211   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
212     k += 1;
213     if(k == IC) {
214       st = itel.Value();
215       break;
216     }
217   }
218   if(st.IsNull()) return 0;
219   if(st->Spine().IsNull()) return 0;
220   Handle(ChFiDS_HData) hd = st->SetOfSurfData();
221   if(hd.IsNull()) return 0;
222   return hd->Length();
223 }
224
225 //=======================================================================
226 //function : ComputedSurface
227 //purpose  : 
228 //=======================================================================
229
230 Handle(Geom_Surface) ChFi3d_Builder::ComputedSurface(const Standard_Integer IC,
231                                                      const Standard_Integer IS) const
232 {
233  ChFiDS_ListIteratorOfListOfStripe itel;
234   Standard_Integer k = 0;
235   Handle(ChFiDS_Stripe) st;
236   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
237     k += 1;
238     if(k == IC) {
239       st = itel.Value();
240       break;
241     }
242   }
243   Handle(ChFiDS_HData) hd = st->SetOfSurfData();
244   Standard_Integer isurf=hd->Value(IS)->Surf();
245   return  myDS->Surface(isurf).Surface();
246 }
247
248 //=======================================================================
249 //function : NbFaultyVertices
250 //purpose  : 
251 //=======================================================================
252
253 Standard_Integer ChFi3d_Builder::NbFaultyVertices() const
254 {
255   return badvertices.Extent();
256 }
257
258 //=======================================================================
259 //function : FaultyVertex
260 //purpose  : 
261 //=======================================================================
262
263 TopoDS_Vertex ChFi3d_Builder::FaultyVertex(const Standard_Integer IV) const
264 {
265   TopTools_ListIteratorOfListOfShape it;
266   TopoDS_Vertex V;
267   Standard_Integer k = 0;
268   for(it.Initialize(badvertices);it.More(); it.Next()) {
269     k += 1;
270     if(k == IV) {
271       V = TopoDS::Vertex(it.Value());
272       break;
273     }
274   }
275   return V;
276 }
277
278 //=======================================================================
279 //function : HasResult
280 //purpose  : 
281 //=======================================================================
282
283 Standard_Boolean ChFi3d_Builder::HasResult() const 
284 {
285   return hasresult;
286 }
287
288 //=======================================================================
289 //function : BadShape
290 //purpose  : 
291 //=======================================================================
292
293 TopoDS_Shape ChFi3d_Builder::BadShape()const
294 {
295   Standard_NoSuchObject_Raise_if(!hasresult,"");  
296   return badShape;
297 }
298
299 //=======================================================================
300 //function : StripeStatus
301 //purpose  : 
302 //=======================================================================
303
304 ChFiDS_ErrorStatus ChFi3d_Builder::StripeStatus(const Standard_Integer IC)const
305 {  
306   ChFiDS_ListIteratorOfListOfStripe itel;
307   Standard_Integer k =0;
308   Handle(ChFiDS_Stripe) st;
309   for (itel.Initialize(myListStripe);itel.More(); itel.Next()) {
310     k += 1;
311     if(k == IC) {
312       st = itel.Value();
313       break;
314     }
315   }
316   ChFiDS_ErrorStatus stat=st->Spine()->ErrorStatus();
317   return stat;
318 }
319
320 //=======================================================================
321 //function : Builder
322 //purpose  : 
323 //=======================================================================
324
325 Handle(TopOpeBRepBuild_HBuilder) ChFi3d_Builder::Builder()const
326 {
327   return myCoup;
328 }
329
330 //=======================================================================
331 //function : ChFi3d_FaceTangency
332 //purpose  : determine if the faces opposing to edges are tangent
333 //           to go from opposing faces on e0 to opposing faces 
334 //           on e1, consider all faces starting at a common top.
335 //=======================================================================
336
337 Standard_Boolean ChFi3d_Builder::FaceTangency(const TopoDS_Edge& E0,
338                                               const TopoDS_Edge& E1,
339                                               const TopoDS_Vertex& V) const
340 {
341   TopTools_ListIteratorOfListOfShape It,Jt;
342   TopoDS_Edge Ec;
343   Standard_Integer Nbf;
344   TopoDS_Face F[2];
345
346   //It is checked if the connection is not on a regular edge.
347   for (It.Initialize(myEFMap(E1)), Nbf= 0 ;It.More();It.Next(), Nbf++) {
348     if (Nbf>1) 
349       Standard_ConstructionError::Raise("ChFi3d_Builder:only 2 faces");
350     F[Nbf] = TopoDS::Face(It.Value());
351   }      
352   if(Nbf < 2) return Standard_False;
353 //  Modified by Sergey KHROMOV - Fri Dec 21 17:44:19 2001 Begin
354 //if (BRep_Tool::Continuity(E1,F[0],F[1]) != GeomAbs_C0) {
355   if (ChFi3d_isTangentFaces(E1,F[0],F[1])) {
356 //  Modified by Sergey KHROMOV - Fri Dec 21 17:44:21 2001 End
357     return Standard_False;
358   }
359
360   for (Jt.Initialize(myVEMap(V));Jt.More();Jt.Next()) {
361     Ec = TopoDS::Edge(Jt.Value());
362     if (!Ec.IsSame(E0) && !Ec.IsSame(E1) && 
363         Ec.Orientation() != TopAbs_INTERNAL && 
364         Ec.Orientation() != TopAbs_EXTERNAL &&
365         !BRep_Tool::Degenerated(Ec)) {
366       for (It.Initialize(myEFMap(Ec)), Nbf= 0 ;It.More();It.Next(), Nbf++) {
367         if (Nbf>1) 
368           Standard_ConstructionError::Raise("ChFi3d_Builder:only 2 faces");
369         F[Nbf] = TopoDS::Face(It.Value());
370       }      
371       if(Nbf < 2) return Standard_False;
372 //  Modified by Sergey KHROMOV - Tue Dec 18 18:10:40 2001 Begin
373 //    if (BRep_Tool::Continuity(Ec,F[0],F[1]) < GeomAbs_G1) {
374       if (!ChFi3d_isTangentFaces(Ec,F[0],F[1])) {
375 //  Modified by Sergey KHROMOV - Tue Dec 18 18:10:41 2001 End
376         return Standard_False;
377       }
378     }
379   }
380   return Standard_True;
381   
382 }
383
384
385 //=======================================================================
386 //function : TangentExtremity
387 //purpose  : Test if 2 faces are tangent at the end of an edge
388 //=======================================================================
389 static Standard_Boolean TangentExtremity(const TopoDS_Vertex&                V,
390                                          const TopoDS_Edge&                  E,
391                                          const Handle(BRepAdaptor_HSurface)& hs1,
392                                          const Handle(BRepAdaptor_HSurface)& hs2,
393 //                                       const Standard_Real                 t3d,
394                                          const Standard_Real                 tang)
395 {
396   TopoDS_Face f1 = hs1->ChangeSurface().Face();
397   TopAbs_Orientation O1 = f1.Orientation();
398   f1.Orientation(TopAbs_FORWARD);
399   TopoDS_Face f2 = hs2->ChangeSurface().Face();
400   TopAbs_Orientation O2 = f2.Orientation();
401   f2.Orientation(TopAbs_FORWARD);
402   TopoDS_Edge e1 = E, e2 = E;
403   e1.Orientation(TopAbs_FORWARD);
404   e2.Orientation(TopAbs_FORWARD);
405   if(f1.IsSame(f2) && BRep_Tool::IsClosed(e1,f1))
406     e2.Orientation(TopAbs_REVERSED);
407   Standard_Real p1 = BRep_Tool::Parameter(V,e1,f1);
408   Standard_Real p2 = BRep_Tool::Parameter(V,e2,f2);
409   Standard_Real u,v,f,l, Eps = 1.e-9;
410   gp_Vec n1, n2;//   gp_Pnt pt1,pt2;
411   Handle(Geom2d_Curve) pc1 = BRep_Tool::CurveOnSurface(e1,f1,f,l);
412   pc1->Value(p1).Coord(u,v);
413   BRepLProp_SLProps theProp1(hs1->ChangeSurface(), u, v, 1, Eps);
414   if  (theProp1.IsNormalDefined()) {
415     n1.SetXYZ(theProp1.Normal().XYZ());
416     if (O1 == TopAbs_REVERSED) n1.Reverse();
417   }
418   else return Standard_False; // It is not known...
419
420  
421   Handle(Geom2d_Curve) pc2 = BRep_Tool::CurveOnSurface(e2,f2,f,l);
422   pc2->Value(p2).Coord(u,v);
423   BRepLProp_SLProps theProp2(hs2->ChangeSurface(), u, v, 1, Eps);
424   if  (theProp2.IsNormalDefined()) {
425     n2.SetXYZ(theProp2.Normal().XYZ());
426     if(O2 == TopAbs_REVERSED) n2.Reverse();
427   }
428   else return Standard_False; //  It is not known...
429
430   return (n1.Angle(n2) < tang);
431 }
432
433 //=======================================================================
434 //function : TangentOnVertex
435 //purpose  : Test if support faces of an edge are tangent at end.
436 //=======================================================================
437 static Standard_Boolean TangentOnVertex(const TopoDS_Vertex&    V,
438                                         const TopoDS_Edge&      E,
439                                         const ChFiDS_Map&       EFMap,
440                                         const Standard_Real     tang)
441 {
442   TopoDS_Face ff1,ff2;
443   ChFi3d_conexfaces(E,ff1,ff2,EFMap);
444   if(ff1.IsNull() || ff2.IsNull()) return 0;
445   Handle(BRepAdaptor_HSurface) S1 = new (BRepAdaptor_HSurface)(ff1);
446   Handle(BRepAdaptor_HSurface) S2 = new (BRepAdaptor_HSurface)(ff2);
447   return TangentExtremity(V, E, S1, S2, tang);
448 }
449
450 //=======================================================================
451 //function : PerformExtremity
452 //purpose  : In case if PerformElement returned BreakPoint at one or  
453 //           another extremity, it is attempted to refine 
454 //           depending on concavities between neighbour faces of the top.
455 //=======================================================================
456
457 void ChFi3d_Builder::PerformExtremity (const Handle(ChFiDS_Spine)& Spine) 
458 {
459   Standard_Integer NbG1Connections = 0;
460   
461   for(Standard_Integer ii = 1; ii <= 2; ii++){
462     TopoDS_Edge E[3],Ec;
463     TopoDS_Vertex V;
464     ChFiDS_State sst;
465     Standard_Integer iedge;
466     Handle(BRepAdaptor_HSurface) hs1,hs2;
467     if(ii == 1){
468       sst = Spine->FirstStatus();
469       iedge = 1;
470       V = Spine->FirstVertex();
471     }
472     else{
473       sst = Spine->LastStatus(); 
474       iedge = Spine->NbEdges();
475       E[0] = Spine->Edges(iedge);
476       V = Spine->LastVertex();
477     }
478     //Before all it is checked if the tangency is not dead.
479     E[0] = Spine->Edges(iedge);
480     ConexFaces (Spine,iedge,0,hs1,hs2);
481     if(TangentExtremity(V,E[0],hs1,hs2,angular)){
482       Spine->SetTangencyExtremity(Standard_True, (ii == 1));
483     }
484
485     if(sst == ChFiDS_BreakPoint){
486       TopTools_ListIteratorOfListOfShape It;//,Jt;
487       Standard_Integer i = 0;
488       Standard_Boolean sommetpourri = Standard_False;
489       TopTools_IndexedMapOfShape EdgesOfV;
490       //to avoid repeating of edges
491       for (It.Initialize(myVEMap(V)); It.More(); It.Next())
492         EdgesOfV.Add(It.Value());
493       for (Standard_Integer ind = 1; ind <= EdgesOfV.Extent(); ind++) {
494         Ec = TopoDS::Edge(EdgesOfV(ind));
495         Standard_Boolean bonedge = !BRep_Tool::Degenerated(Ec);
496         if (bonedge)
497         {
498           TopoDS_Face F1, F2;
499           ChFi3d_conexfaces(Ec, F1, F2, myEFMap);
500           if (!F2.IsNull() && ChFi3d_isTangentFaces(Ec, F1, F2, GeomAbs_G2))
501           {
502             bonedge = Standard_False;
503             if (!F1.IsSame(F2))
504               NbG1Connections++;
505           }
506         }
507         if(bonedge){
508           if (!Ec.IsSame(E[0]))
509           {
510             if( i < 2 ){
511               i++;
512               E[i] = Ec;
513             }
514             else{
515 #ifdef OCCT_DEBUG
516             cout<<"top has more than 3 edges"<<endl;
517 #endif
518               sommetpourri = Standard_True;
519               break;
520             }
521           }
522         }
523       }
524       if(i != 2) sommetpourri = Standard_True;
525       if(!sommetpourri){
526         sst = ChFi3d_EdgeState(E,myEFMap);
527       }
528       if(ii==1)Spine->SetFirstStatus(sst);
529       else Spine->SetLastStatus(sst);
530     }
531   }
532   
533   if (!Spine->IsPeriodic()) {
534     TopTools_ListIteratorOfListOfShape It,Jt;
535     Standard_Integer nbf = 0, jf = 0;
536     for (It.Initialize(myVFMap(Spine->FirstVertex())); It.More(); It.Next()){
537       jf++;
538       Standard_Integer kf = 1;
539       const TopoDS_Shape& cur = It.Value();
540       for (Jt.Initialize(myVFMap(Spine->FirstVertex())); Jt.More() && (kf < jf); Jt.Next(), kf++){
541         if(cur.IsSame(Jt.Value())) break;
542       }
543       if(kf == jf) nbf++;
544     }
545     nbf -= NbG1Connections;
546     if(nbf>3) {
547       Spine->SetFirstStatus(ChFiDS_BreakPoint);
548 #ifdef OCCT_DEBUG
549       cout<<"top has : "<<nbf<<" faces."<<endl;
550 #endif
551     }
552     nbf = 0, jf = 0;
553     for (It.Initialize(myVFMap(Spine->LastVertex())); It.More(); It.Next()){
554       jf++;
555       Standard_Integer kf = 1;
556       const TopoDS_Shape& cur = It.Value();
557       for (Jt.Initialize(myVFMap(Spine->LastVertex())); Jt.More() && (kf < jf); Jt.Next(), kf++){
558         if(cur.IsSame(Jt.Value())) break;
559       }
560       if(kf == jf) nbf++;
561     }
562     nbf -= NbG1Connections;
563     if(nbf>3) {
564       Spine->SetLastStatus(ChFiDS_BreakPoint);
565 #ifdef OCCT_DEBUG
566       cout<<"top has : "<<nbf<<" faces."<<endl;
567 #endif
568     }
569   }
570 }
571
572 //=======================================================================
573 //function : PerformElement
574 //purpose  :  find all mutually tangent edges ;
575 // Each edge has 2 opposing faces. For 2 adjacent tangent edges it is required that 
576 // the opposing faces were tangent.
577 //=======================================================================
578
579 Standard_Boolean ChFi3d_Builder::PerformElement(const Handle(ChFiDS_Spine)& Spine) 
580 {
581   Standard_Real ta = angular;
582   TopTools_ListIteratorOfListOfShape It;
583   Standard_Integer Nbface;
584   TopTools_ListIteratorOfListOfShape Jt;
585   Standard_Real Wl,Wf;
586   Standard_Boolean degeneOnEc;
587   gp_Pnt P2;
588   gp_Vec V1,V2;
589   TopoDS_Vertex Ve1,VStart,FVEc,LVEc,FVEv,LVEv;
590   TopoDS_Edge Ev,Ec(Spine->Edges(1));
591   if(BRep_Tool::Degenerated(Ec)) return 0;
592   //it is checked if the edge is a cut edge
593   TopoDS_Face ff1,ff2;
594   ChFi3d_conexfaces(Ec,ff1,ff2,myEFMap);
595   if(ff1.IsNull() || ff2.IsNull()) return 0;
596 //  Modified by Sergey KHROMOV - Fri Dec 21 17:46:22 2001 End
597 //if(BRep_Tool::Continuity(Ec,ff1,ff2) != GeomAbs_C0) return 0;
598   if (ChFi3d_isTangentFaces(Ec,ff1,ff2)) return 0;
599 //  Modified by Sergey KHROMOV - Fri Dec 21 17:46:24 2001 Begin
600   
601   BRepAdaptor_Curve CEc,CEv;
602   TopAbs_Orientation curor = Ec.Orientation();
603   TopExp::Vertices(Ec,VStart,LVEc);
604
605
606   Standard_Boolean Fini = Standard_False;
607   Standard_Integer Nb;
608   ChFiDS_State CurSt = ChFiDS_Closed;
609   if (VStart.IsSame(LVEc)) {//case if only one edge is closed
610     CEc.Initialize(Ec);
611     Wl = BRep_Tool::Parameter(VStart,Ec);
612     CEc.D1(Wl,P2,V1);
613     Wl = BRep_Tool::Parameter(LVEc,Ec);
614     CEc.D1(Wl,P2,V2);
615     if (V1.IsParallel(V2,ta)) {
616       if (FaceTangency(Ec,Ec,VStart)) {
617         CurSt = ChFiDS_Closed; 
618       }
619       else {
620         CurSt = ChFiDS_BreakPoint; 
621       } 
622     }
623     else {
624       CurSt = ChFiDS_BreakPoint; 
625     }
626     Spine->SetLastStatus(CurSt);
627     Spine->SetFirstStatus(CurSt);
628   }
629   else { // Downstream progression
630     FVEc = VStart;
631     TopAbs_Orientation Or1;
632     while (!Fini) {
633       CurSt = ChFiDS_FreeBoundary;
634       Wl = BRep_Tool::Parameter(LVEc,Ec);
635       degeneOnEc = TangentOnVertex(LVEc, Ec, myEFMap, ta);
636       CEc.Initialize(Ec);
637       CEc.D1(Wl,P2,V1);
638       Nb = Spine->NbEdges();
639
640       for (It.Initialize(myVEMap(LVEc));It.More();It.Next()) {
641         Ev = TopoDS::Edge(It.Value());
642         if (!Ev.IsSame(Ec) && !BRep_Tool::Degenerated(Ev)){
643           TopExp::Vertices(Ev,FVEv,LVEv);
644           if (LVEc.IsSame(LVEv)) {
645             Ve1 = FVEv;
646             FVEv = LVEv;
647             LVEv = Ve1;
648             Or1 = TopAbs_REVERSED;
649           }
650           else Or1 = TopAbs_FORWARD;
651
652           Wf = BRep_Tool::Parameter(FVEv,Ev);
653           CEv.Initialize(Ev);
654           CEv.D1(Wf,P2,V2);   
655           Standard_Real av1v2 = V1.Angle(V2);
656           Standard_Boolean rev = (Or1 != curor);    
657           Standard_Boolean OnAjoute = Standard_False;
658           if (FaceTangency(Ec,Ev,FVEv)) {
659             // there is no need of tolerance
660             // to make a decision (PRO9486) the regularity is enough.
661             // However, the abcense of turn-back is checked (PRO9810)
662             OnAjoute = ((!rev && av1v2 < M_PI/2) 
663                         ||(rev && av1v2 > M_PI/2));
664             // mate attention to the single case (cf CTS21610_1)
665             if (OnAjoute && (degeneOnEc || 
666                 TangentOnVertex(LVEc, Ev,myEFMap, ta)) )
667               OnAjoute=((!rev && av1v2 < ta) || (rev && (M_PI - av1v2) < ta));
668           }
669           if (OnAjoute) {
670             Fini = Standard_False; // If this can be useful (Cf PRO14713)
671             Ec = Ev; 
672 //          Ec = TopoDS::Edge(Ev); 
673             Ec.Orientation(Or1);
674             Wl = Wf; LVEc = LVEv; 
675             Spine->SetEdges(Ec);
676             curor = Or1;
677             if (VStart.IsSame(LVEv)) {
678               if (FaceTangency(Ev,Spine->Edges(1),LVEv)) {
679                 CurSt = ChFiDS_Closed; Fini = Standard_True;
680               }
681               else {
682                 CurSt = ChFiDS_BreakPoint;Fini = Standard_True;
683               }
684             }
685             break;
686           }
687           else {
688             for (Jt.Initialize(myEFMap(Ev)), Nbface= 0 ;Jt.More();Jt.Next(), 
689                  Nbface++) {}
690             if (Nbface> 1) CurSt = ChFiDS_BreakPoint;
691             Fini = ((!rev && av1v2 < ta) || (rev && (M_PI - av1v2) < ta)); 
692           }
693         } 
694       } 
695       Fini = Fini || (Nb == Spine->NbEdges());
696     }
697     Spine->SetLastStatus(CurSt);
698     if (CurSt == ChFiDS_Closed) {
699       Spine->SetFirstStatus(CurSt);
700     }
701     else {// Upstream progression
702       Fini = Standard_False;
703       Ec = Spine->Edges(1);
704       curor = Ec.Orientation();
705       FVEc = VStart;
706       while (!Fini) {
707         CurSt = ChFiDS_FreeBoundary;
708         Wl = BRep_Tool::Parameter(FVEc,Ec);
709         degeneOnEc = TangentOnVertex(FVEc, Ec, myEFMap, ta);
710         CEc.Initialize(Ec);
711         CEc.D1(Wl,P2,V1);
712         Nb = Spine->NbEdges();
713
714         for (It.Initialize(myVEMap(FVEc));It.More();It.Next()) {
715           Ev = TopoDS::Edge(It.Value());
716           if (!Ev.IsSame(Ec) && !BRep_Tool::Degenerated(Ev)) {
717             TopExp::Vertices(Ev,FVEv,LVEv);
718             if (FVEc.IsSame(FVEv)) {
719               Ve1 = FVEv;
720               FVEv = LVEv;
721               LVEv = Ve1;
722               Or1 = TopAbs_REVERSED;
723             }
724             else {
725               Or1 = TopAbs_FORWARD;
726             }
727             Wf = BRep_Tool::Parameter(LVEv,Ev);
728             CEv.Initialize(Ev);
729             CEv.D1(Wf,P2,V2);
730             Standard_Real av1v2 = V1.Angle(V2);
731             Standard_Boolean rev = (Or1 != curor);
732             Standard_Boolean OnAjoute =  Standard_False;
733             if (FaceTangency(Ec,Ev,LVEv)) {
734               OnAjoute = ((!rev && av1v2 < M_PI/2) 
735                         ||(rev && av1v2 > M_PI/2));
736             if (OnAjoute && (degeneOnEc || 
737                 TangentOnVertex(FVEc, Ev,myEFMap, ta)) )
738               OnAjoute=((!rev && av1v2 < ta) || (rev && (M_PI-av1v2) < ta));
739             }
740             if  (OnAjoute) {
741               Ec = Ev; 
742 //            Ec = TopoDS::Edge(Ev); 
743               Ec.Orientation(Or1);
744               Wl = Wf; FVEc = FVEv; 
745               Spine->PutInFirst(Ec);
746               curor = Or1;
747               break;
748             }
749             else {
750               for(Jt.Initialize(myEFMap(Ev)),Nbface= 0 ;Jt.More();Jt.Next(), 
751                   Nbface++) {}
752               if (Nbface> 1) CurSt = ChFiDS_BreakPoint;
753               Fini = ((!rev && av1v2 < ta) || (rev && (M_PI - av1v2) < ta));
754             }
755           } 
756         } 
757         Fini = Fini || (Nb == Spine->NbEdges());
758       }
759       Spine->SetFirstStatus(CurSt);
760     }
761   }
762   return 1;
763 }
764
765 //=======================================================================
766 //function : Remove
767 //purpose  : 
768 //=======================================================================
769
770 void  ChFi3d_Builder::Remove(const TopoDS_Edge& E)
771 {
772   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
773
774   for ( ; itel.More(); itel.Next()) {
775     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
776     for (Standard_Integer j = 1; j <= sp->NbEdges(); j++){
777       if (E.IsSame(sp->Edges(j))){
778         myListStripe.Remove(itel);
779         return;
780       }
781     }
782   }
783 }
784
785
786 //=======================================================================
787 //function : Value
788 //purpose  : 
789 //=======================================================================
790
791 Handle(ChFiDS_Spine) ChFi3d_Builder::Value
792 (const Standard_Integer I)const 
793 {
794   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
795   for (Standard_Integer ic = 1; ic < I; ic++) {itel.Next();}
796   return itel.Value()->Spine();
797 }
798
799 //=======================================================================
800 //function : NbElements
801 //purpose  : 
802 //=======================================================================
803
804 Standard_Integer ChFi3d_Builder::NbElements()const 
805 {
806   Standard_Integer i = 0;
807   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
808   for ( ;itel.More(); itel.Next()){
809     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
810     if(sp.IsNull()) break;
811     i++;
812   }
813   return i;
814 }
815
816 //=======================================================================
817 //function : Contains
818 //purpose  : 
819 //=======================================================================
820
821 Standard_Integer ChFi3d_Builder::Contains(const TopoDS_Edge& E)const
822 {
823   Standard_Integer i = 1,j;
824   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
825   for ( ;itel.More(); itel.Next(), i++){
826     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
827     if(sp.IsNull()) break;
828     for (j = 1; j <= sp->NbEdges(); j++){
829       if(E.IsSame(sp->Edges(j))) return i;
830     }
831   }
832   return 0;
833 }
834
835 //=======================================================================
836 //function : Contains
837 //purpose  : 
838 //=======================================================================
839
840 Standard_Integer ChFi3d_Builder::Contains(const TopoDS_Edge& E,
841                                           Standard_Integer&  IndexInSpine)const
842 {
843   Standard_Integer i = 1,j;
844   IndexInSpine = 0;
845   ChFiDS_ListIteratorOfListOfStripe itel(myListStripe);
846   for ( ;itel.More(); itel.Next(), i++){
847     const Handle(ChFiDS_Spine)& sp = itel.Value()->Spine();
848     if(sp.IsNull()) break;
849     for (j = 1; j <= sp->NbEdges(); j++){
850       if(E.IsSame(sp->Edges(j)))
851         {
852           IndexInSpine = j;
853           return i;
854         }
855     }
856   }
857   return 0;
858 }
859
860 //=======================================================================
861 //function : Length
862 //purpose  : 
863 //=======================================================================
864
865 Standard_Real ChFi3d_Builder::Length(const Standard_Integer IC)const
866 {
867   if(IC <= NbElements()){
868     const Handle(ChFiDS_Spine)& sp = Value(IC);
869     return sp->LastParameter(sp->NbEdges());
870   }
871   return -1;
872 }
873
874
875 //=======================================================================
876 //function : FirstVertex
877 //purpose  : 
878 //=======================================================================
879
880 TopoDS_Vertex ChFi3d_Builder::FirstVertex(const Standard_Integer IC) const
881 {
882   if(IC <= NbElements()){
883     return Value(IC)->FirstVertex();
884   }
885   return TopoDS_Vertex();
886 }
887
888 //=======================================================================
889 //function : LastVertex
890 //purpose  : 
891 //=======================================================================
892
893 TopoDS_Vertex ChFi3d_Builder::LastVertex(const Standard_Integer IC) const
894 {
895   if(IC <= NbElements()){
896     return Value(IC)->LastVertex();
897   }
898   return TopoDS_Vertex();
899 }
900
901 //=======================================================================
902 //function : Abscissa
903 //purpose  : 
904 //=======================================================================
905
906 Standard_Real ChFi3d_Builder::Abscissa(const Standard_Integer IC,
907                                        const TopoDS_Vertex& V) const
908 {
909   if(IC <= NbElements()){
910     return Value(IC)->Absc(V);
911   }
912   return -1;
913 }
914
915 //=======================================================================
916 //function : RelativeAbscissa
917 //purpose  : 
918 //=======================================================================
919
920 Standard_Real ChFi3d_Builder::RelativeAbscissa(const Standard_Integer IC,
921                                                const TopoDS_Vertex& V) const
922 {
923   if(IC <= NbElements()){
924     return Abscissa(IC,V)/Length(IC);
925   }
926   return -1;
927 }
928
929 //=======================================================================
930 //function : Closed
931 //purpose  : 
932 //=======================================================================
933
934 Standard_Boolean ChFi3d_Builder::Closed(const Standard_Integer IC)const
935 {
936   if(IC <= NbElements()){
937     return Value(IC)->IsClosed();
938   }
939   return Standard_False;
940 }
941
942 //=======================================================================
943 //function : ClosedAndTangent
944 //purpose  : 
945 //=======================================================================
946
947 Standard_Boolean ChFi3d_Builder::ClosedAndTangent
948 (const Standard_Integer IC)const
949 {
950   if(IC <= NbElements()){
951     return Value(IC)->IsPeriodic();
952   }
953   return Standard_False;
954 }
955