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