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