2d5f3bfb77b314ee1e109b6d486e743d387e971f
[occt.git] / src / ChFiDS / ChFiDS_FilSpine.cxx
1 // Created on: 1995-04-24
2 // Created by: Modelistation
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <ChFiDS_FilSpine.hxx>
19 #include <ChFiDS_HElSpine.hxx>
20 #include <ChFiDS_ListIteratorOfListOfHElSpine.hxx>
21 #include <ElCLib.hxx>
22 #include <gp_XY.hxx>
23 #include <Law_Composite.hxx>
24 #include <Law_Constant.hxx>
25 #include <Law_Function.hxx>
26 #include <Law_Interpol.hxx>
27 #include <Law_ListIteratorOfLaws.hxx>
28 #include <Law_S.hxx>
29 #include <Precision.hxx>
30 #include <Standard_DomainError.hxx>
31 #include <Standard_Type.hxx>
32 #include <TColgp_Array1OfPnt2d.hxx>
33 #include <TColStd_Array1OfInteger.hxx>
34 #include <TColStd_HArray1OfBoolean.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Vertex.hxx>
37
38 //=======================================================================
39 //function : ChFiDS_FilSpine
40 //purpose  : 
41 //=======================================================================
42 ChFiDS_FilSpine::ChFiDS_FilSpine() {}
43
44 ChFiDS_FilSpine::ChFiDS_FilSpine(const Standard_Real Tol) :
45 ChFiDS_Spine(Tol)
46 {}
47
48 //=======================================================================
49 //function : Reset
50 //purpose  : 
51 //=======================================================================
52
53 void ChFiDS_FilSpine::Reset(const Standard_Boolean AllData)
54 {
55   ChFiDS_Spine::Reset(AllData);
56   laws.Clear();
57   if(AllData)
58     parandrad.Clear();
59   else //Complete parandrad
60     {
61       Standard_Real spinedeb = FirstParameter();
62       Standard_Real spinefin = LastParameter();
63
64       gp_XY FirstUandR = parandrad.First();
65       gp_XY LastUandR  = parandrad.Last();
66       if (Abs( spinedeb - FirstUandR.X() ) > gp::Resolution())
67         {
68           FirstUandR.SetX( spinedeb );
69           parandrad.Prepend( FirstUandR );
70         }
71       if (Abs( spinefin - LastUandR.X() ) > gp::Resolution())
72         {
73           LastUandR.SetX( spinefin );
74           parandrad.Append( LastUandR );
75         }
76
77       if (IsPeriodic())
78         parandrad(parandrad.Length()).SetY( parandrad(1).Y() );
79     }
80 }
81
82 //=======================================================================
83 //function : SetRadius
84 //purpose  : 
85 //=======================================================================
86
87 void  ChFiDS_FilSpine::SetRadius(const Standard_Real Radius,
88                                  const TopoDS_Edge&  E)
89 {
90   splitdone = Standard_False;
91   Standard_Integer IE = Index(E);
92   gp_XY FirstUandR( 0., Radius ), LastUandR( 1., Radius );
93   SetRadius( FirstUandR, IE );
94   SetRadius( LastUandR, IE );
95 }
96
97 //=======================================================================
98 //function : UnSetRadius
99 //purpose  : 
100 //=======================================================================
101
102 void  ChFiDS_FilSpine::UnSetRadius(const TopoDS_Edge&  E)
103 {
104   splitdone = Standard_False;
105   Standard_Integer IE = Index(E);
106
107   Standard_Real Uf = FirstParameter(IE);
108   Standard_Real Ul = LastParameter(IE);
109   Standard_Integer ifirst = 0, ilast = 0;
110   for (Standard_Integer i = 1; i <= parandrad.Length(); i++)
111     {
112       if (Abs(parandrad(i).X()-Uf) <= gp::Resolution())
113         ifirst = i;
114       if (Abs(parandrad(i).X()-Ul) <= gp::Resolution())
115         ilast = i;
116     }
117   if (ifirst != 0 && ilast != 0)
118     parandrad.Remove( ifirst, ilast );
119 }
120
121 //=======================================================================
122 //function : SetRadius
123 //purpose  : 
124 //=======================================================================
125
126 void  ChFiDS_FilSpine::SetRadius(const Standard_Real  Radius,
127                                  const TopoDS_Vertex& V)
128 {
129   Standard_Real npar = Absc(V);
130   gp_XY UandR( npar, Radius );
131   SetRadius( UandR, 0 );
132 }
133
134 //=======================================================================
135 //function : SetRadius
136 //purpose  : 
137 //=======================================================================
138
139 void  ChFiDS_FilSpine::SetRadius(const Standard_Real  Radius)
140 {
141   parandrad.Clear();
142   gp_XY FirstUandR( FirstParameter(), Radius );
143   gp_XY LastUandR( LastParameter(), Radius );
144   SetRadius( FirstUandR, 0 );
145   SetRadius( LastUandR, 0 );
146 }
147
148 //=======================================================================
149 //function : SetRadius
150 //purpose  : 
151 //=======================================================================
152
153 void  ChFiDS_FilSpine::SetRadius(const gp_XY&           UandR,
154                                  const Standard_Integer IinC)
155 {
156   Standard_Real W;
157   if (IinC == 0)
158     W = UandR.X();
159   else
160     {
161       Standard_Real Uf = FirstParameter(IinC);
162       Standard_Real Ul = LastParameter(IinC);
163       W = Uf + UandR.X()*( Ul - Uf );
164     }
165
166   gp_XY pr( W, UandR.Y() );
167   Standard_Integer i;
168   for(i = 1; i <= parandrad.Length(); i++){
169     if(parandrad.Value(i).X() == W) {
170       parandrad.ChangeValue(i).SetY( UandR.Y() );
171       if (!splitdone) return;
172       else break;
173     }
174     else if(parandrad.Value(i).X() > W) {
175       parandrad.InsertBefore(i,pr);
176       if (!splitdone) return;
177       else break;
178     }
179   }
180   if (i == parandrad.Length()+1) parandrad.Append(pr);
181
182   //si le split est done il faut rejouer la law 
183   //correspondant au parametre W 
184   if (splitdone) {
185     ChFiDS_ListIteratorOfListOfHElSpine It(elspines);
186     Law_ListIteratorOfLaws Itl(laws);
187     Handle(ChFiDS_HElSpine) Els = It.Value();
188     if (Els->IsPeriodic()) Itl.Value() = ComputeLaw(Els);
189     else{
190       for (; It.More(); It.Next(), Itl.Next()) {
191         Els = It.Value();
192         Standard_Real uf = Els->FirstParameter();
193         Standard_Real ul = Els->LastParameter();
194         if(uf <= W && W <= ul) {
195           Itl.Value() = ComputeLaw(Els);
196         }
197       }  
198     }
199   }
200 }
201
202 //=======================================================================
203 //function : UnSetRadius
204 //purpose  : 
205 //=======================================================================
206
207 void  ChFiDS_FilSpine::UnSetRadius(const TopoDS_Vertex& V)
208 {
209   Standard_Real npar = Absc(V);
210   for(Standard_Integer i = 1; i <= parandrad.Length(); i++){
211     if(parandrad.Value(i).X() == npar) {
212       parandrad.Remove(i);
213       break;
214     }
215   }
216 }
217
218 //=======================================================================
219 //function : SetRadius
220 //purpose  : 
221 //=======================================================================
222
223 void  ChFiDS_FilSpine::SetRadius(const Handle(Law_Function)& C,
224                                  const Standard_Integer      /*IinC*/)
225 {
226   splitdone = Standard_False;
227   Handle(Law_Composite) prout = new Law_Composite();
228   Law_Laws& lst = prout->ChangeLaws();
229   lst.Append(C);
230   parandrad.Clear();
231 }
232
233
234 //=======================================================================
235 //function : IsConstant
236 //purpose  : 
237 //=======================================================================
238
239 Standard_Boolean  ChFiDS_FilSpine::IsConstant()const 
240 {
241   if (parandrad.IsEmpty())
242     return Standard_False;
243
244   Standard_Boolean isconst = Standard_True;
245   Standard_Real Radius = parandrad(1).Y();
246   for (Standard_Integer i = 2; i <= parandrad.Length(); i++)
247     if (Abs( Radius - parandrad(i).Y() ) > Precision::Confusion())
248       {
249         isconst = Standard_False;
250         break;
251       }
252   return isconst;
253 }
254
255 //=======================================================================
256 //function : IsConstant
257 //purpose  : 
258 //=======================================================================
259
260 Standard_Boolean  ChFiDS_FilSpine::IsConstant(const Standard_Integer IE)const 
261 {
262   Standard_Real Uf = FirstParameter(IE);
263   Standard_Real Ul = LastParameter(IE);
264
265   Standard_Real StartRad = 0.0, par, rad;
266   Standard_Integer i;
267   for (i = 1; i < parandrad.Length(); i++)
268     {
269       par = parandrad(i).X();
270       rad = parandrad(i).Y();
271       Standard_Real nextpar = parandrad(i+1).X();
272       if (Abs( Uf-par ) <= gp::Resolution() ||
273          (par < Uf && Uf < nextpar && nextpar-Uf > gp::Resolution()))
274         {
275           StartRad = rad;
276           break;
277         }
278     }
279   for (i++; i <= parandrad.Length(); i++)
280     {
281       par = parandrad(i).X();
282       rad = parandrad(i).Y();
283       if (Abs( rad-StartRad ) > Precision::Confusion())
284         return Standard_False;
285       if (Abs( Ul-par ) <= gp::Resolution())
286         return Standard_True;
287       if (par > Ul)
288         return Standard_True;
289     }
290   return Standard_True;
291 }
292
293 //=======================================================================
294 //function : Radius
295 //purpose  : 
296 //=======================================================================
297
298 Standard_Real  ChFiDS_FilSpine::Radius(const TopoDS_Edge& E)const 
299 {
300   Standard_Integer IE = Index(E);
301   return Radius(IE);
302 }
303
304 //=======================================================================
305 //function : Radius
306 //purpose  : 
307 //=======================================================================
308
309 Standard_Real  ChFiDS_FilSpine::Radius(const Standard_Integer IE)const 
310 {
311   Standard_Real Uf = FirstParameter(IE);
312   Standard_Real Ul = LastParameter(IE);
313
314   Standard_Real StartRad = 0., par, rad;
315   Standard_Integer i;
316   for (i = 1; i < parandrad.Length(); i++)
317     {
318       par = parandrad(i).X();
319       rad = parandrad(i).Y();
320       Standard_Real nextpar = parandrad(i+1).X();
321       if (Abs( Uf-par ) <= gp::Resolution() ||
322           (par < Uf && Uf < nextpar && nextpar-Uf > gp::Resolution()))
323         {
324           StartRad = rad;
325           break;
326         }
327     }
328   for (i++; i <= parandrad.Length(); i++)
329     {
330       par = parandrad(i).X();
331       rad = parandrad(i).Y();
332       if (Abs( rad-StartRad ) > Precision::Confusion())
333         Standard_DomainError::Raise("Edge is not constant");
334       if (Abs( Ul-par ) <= gp::Resolution())
335         return StartRad;
336       if (par > Ul)
337         return StartRad;
338     }
339   return StartRad;
340 }
341
342 //=======================================================================
343 //function : Radius
344 //purpose  : 
345 //=======================================================================
346
347 Standard_Real  ChFiDS_FilSpine::Radius()const 
348 {
349   if (!IsConstant()) Standard_DomainError::Raise("Spine is not constant");
350   return parandrad(1).Y();
351 }
352
353 //=======================================================================
354 //function : AppendElSpine
355 //purpose  : 
356 //=======================================================================
357
358 void ChFiDS_FilSpine::AppendElSpine(const Handle(ChFiDS_HElSpine)& Els)
359 {
360   ChFiDS_Spine::AppendElSpine(Els);
361   AppendLaw(Els);
362 }
363
364 //=======================================================================
365 //function : AppendLaw
366 //purpose  : 
367 //=======================================================================
368
369 void ChFiDS_FilSpine::AppendLaw(const Handle(ChFiDS_HElSpine)& Els)
370 {
371   Handle(Law_Composite) l = ComputeLaw(Els);
372   laws.Append(l);
373 }
374
375 static void mklaw(Law_Laws&                  res, 
376                   const TColgp_SequenceOfXY& pr,
377                   const Standard_Real        curdeb,
378                   const Standard_Real        curfin,
379                   const Standard_Real        Rdeb,
380                   const Standard_Real        Rfin,
381                   const Standard_Boolean     recadre,
382                   const Standard_Real        deb,
383                   const Standard_Real        fin,
384                   const Standard_Real        tol3d)
385 {
386   TColgp_SequenceOfXY npr;
387   Standard_Real rad = Rdeb, raf = Rfin;
388   Standard_Boolean yaunpointsurledeb = Standard_False;
389   Standard_Boolean yaunpointsurlefin = Standard_False;
390   if(!pr.IsEmpty()){
391     for (Standard_Integer i = 1; i <= pr.Length(); i++){
392       const gp_XY& cur = pr.Value(i);
393       Standard_Real wcur = cur.X();
394       if(recadre) wcur = ElCLib::InPeriod(wcur,deb,fin);
395       if( curdeb - tol3d <= wcur && wcur <= curfin + tol3d) {
396         if(wcur - curdeb < tol3d) {
397           yaunpointsurledeb = Standard_True;
398           gp_XY ncur = cur;
399           if(Rdeb < 0.) rad = cur.Y();
400           ncur.SetCoord(curdeb,rad);
401           npr.Append(ncur);
402         }  
403         else if(curfin - wcur < tol3d) {
404           yaunpointsurlefin = Standard_True;
405           gp_XY ncur = cur;
406           if(Rfin < 0.) raf = cur.Y();
407           ncur.SetCoord(curfin,raf);
408           npr.Append(ncur);
409         }  
410         else npr.Append(gp_XY(wcur,cur.Y()));
411       }
412     }
413   }
414
415   if(npr.IsEmpty()){
416     if( Rdeb < 0. && Rfin <0. ) 
417       Standard_DomainError::Raise("Impossible to create the law");
418     else if(Rdeb < 0. || Rfin <0.){
419       Standard_Real r = (Rfin<0.)? Rdeb  : Rfin;
420       Handle(Law_Constant) loi = new Law_Constant();
421       loi->Set(r,curdeb,curfin);
422       res.Append(loi);
423     }
424     else{
425       Handle(Law_S) loi = new Law_S();
426       loi->Set(curdeb,Rdeb,curfin,Rfin);
427       res.Append(loi);
428     }
429   }
430   else{
431     if(!yaunpointsurledeb && Rdeb >= 0.) npr.Append(gp_XY(curdeb,Rdeb));
432     if(!yaunpointsurlefin && Rfin >= 0.) npr.Append(gp_XY(curfin,Rfin));
433     Standard_Integer nbp = npr.Length();
434 //    for(Standard_Integer i = 1; i < nbp; i++){
435     Standard_Integer i;
436     for(i = 1; i < nbp; i++){
437       for(Standard_Integer j = i + 1; j <= nbp; j++){
438         if(npr.Value(i).X() > npr.Value(j).X()){
439           gp_XY temp = npr.Value(i);
440           npr.ChangeValue(i) = npr.Value(j);
441           npr.ChangeValue(j) = temp;
442         }
443       }      
444     }
445     //Duplicates are removed.
446     Standard_Boolean fini = (nbp <= 1);
447     i = 1;
448     while (!fini) {
449       if(fabs(npr.Value(i).X() - npr.Value(i+1).X()) < tol3d) {
450         npr.Remove(i);
451         nbp--;
452       }
453       else i++;
454       fini = (i >= nbp);
455     }
456
457     if(rad < 0.) {
458       Handle(Law_Constant) loi = new Law_Constant();
459       loi->Set(npr.First().Y(),curdeb,npr.First().X());
460       res.Append(loi);
461     }
462     if(nbp > 1){
463       TColgp_Array1OfPnt2d tpr(1,nbp);
464       for (Standard_Integer l = 1; l <= nbp; l++) {
465         tpr(l).SetXY(npr.Value(l));
466       }
467       Handle(Law_Interpol) curloi = new Law_Interpol();
468       curloi->Set(tpr,0.,0.,Standard_False);
469       res.Append(curloi);
470     }
471     if(raf < 0.) {
472       Handle(Law_Constant) loi = new Law_Constant();
473       loi->Set(npr.Last().Y(),npr.Last().X(),curfin);
474       res.Append(loi);
475     }
476   }
477 }
478                                   
479 //=======================================================================
480 //function : ComputeLaw
481 //purpose  : 
482 //=======================================================================
483
484 Handle(Law_Composite) ChFiDS_FilSpine::ComputeLaw
485 (const Handle(ChFiDS_HElSpine)& Els)
486 {
487   Standard_Real tol3d = Precision::Confusion();
488   Standard_Real deb,fin,curdeb,curfin;
489   curdeb = deb = Els->FirstParameter();
490   curfin = fin = Els->LastParameter();
491   Standard_Integer ideb = Index(deb,Standard_True);
492   Standard_Integer ifin = Index(fin,Standard_False);
493   Standard_Integer len = NbEdges();
494   // if the spine is periodic, attention to the index and parameters
495   Standard_Real spinedeb = FirstParameter();
496   Standard_Real spinefin = LastParameter();
497
498   Standard_Integer nbed = ifin - ideb + 1;
499   Standard_Integer biddeb = ideb, bidfin = ifin;
500
501   Handle(Law_Composite) loi = new Law_Composite();
502   Law_Laws& list = loi->ChangeLaws();
503   Standard_Real Rdeb = 0., Rfin = 0., Rcur;
504   Standard_Integer icur = 1;
505   Handle(Law_S) sl;
506   Handle(Law_Constant) lastloi;
507   Standard_Boolean lawencours = Standard_False;
508
509
510   if(IsPeriodic()){
511     if(deb < 0 && ideb > ifin)  bidfin += len;
512     else if(fin > LastParameter(len) && ideb > ifin)  bidfin += len;
513     nbed = bidfin - biddeb + 1;
514   }
515   TColStd_Array1OfInteger ind(1,nbed);
516   Standard_Integer j = 1;
517   for(Standard_Integer i = biddeb; i <= bidfin; i++){
518     ind(j++) = ((i - 1)%len) + 1; 
519   }
520
521   if(Els->IsPeriodic()){
522     // A pereodic composite is created at range, which is eventually  
523     // offset relatively to the elspine, to avoid a single point at 
524     // origin.
525     loi->SetPeriodic();
526     //Is there a constant edge?
527 //    for(Standard_Integer k = 1; k <= len; k++){
528     Standard_Integer k;
529     for( k = 1; k <= len; k++){
530       if (IsConstant(k)){ // yes  !
531         spinedeb = deb = curdeb = FirstParameter(k);
532         spinefin = fin = deb + Period();
533         for(Standard_Integer l = 1; l <= len; l++){
534           ind(l) = ((k + l -2)%len) + 1; 
535         }
536         Rdeb = Rfin = Radius(k);
537         icur++;
538         if(len == 1) curfin = LastParameter(k);//because InPeriod will make 0.!!!
539         else curfin = ElCLib::InPeriod(LastParameter(k),spinedeb,spinefin);
540         Handle(Law_Constant) curloi = new Law_Constant();
541         curloi->Set(Rdeb,curdeb,curfin);
542         list.Append(curloi);
543         curdeb = curfin;
544         break;
545       }
546     }
547     if(k > len){ // no !
548       if(parandrad.IsEmpty()) 
549         Standard_DomainError::Raise("Radius not defined");
550       Standard_Integer nbp = parandrad.Length();
551       if(nbp > 1){
552         deb = parandrad.First().X();
553         fin = deb + Period();
554         if(parandrad.Last().X() - fin <  - tol3d) nbp++;
555       }
556       else nbp++;
557       TColgp_Array1OfPnt2d pr(1,nbp);
558       for (Standard_Integer l = 1; l < nbp; l++) {
559         pr(l).SetXY(parandrad(l));
560       }
561       pr(nbp).SetCoord(fin,pr(1).Y());
562       Handle(Law_Interpol) curloi = new Law_Interpol();
563       curloi->Set(pr,Standard_True);
564       list.Append(curloi);
565       return loi;
566     }
567   }
568   else if(IsPeriodic()){
569     // start radius.
570     if (IsConstant(ind(1))) {
571       Rdeb = Radius(ind(1));
572       curfin = LastParameter(ind(1));
573       curfin = ElCLib::InPeriod(curfin,spinedeb + tol3d, spinefin + tol3d);
574       curfin = Min(fin,curfin);
575       Handle(Law_Constant) curloi = new Law_Constant();
576       curloi->Set(Rdeb,curdeb,curfin);
577       list.Append(curloi);
578       curdeb = curfin;
579       icur++;
580     } 
581     else{
582       // There is inevitably kpart right before!
583       Standard_Integer iprec = (ind(1) - 1);
584       if(iprec == 0) iprec = len;
585       if (IsConstant(iprec)){
586         Rdeb = Radius(iprec);
587       }
588       else Standard_DomainError::Raise("AppendLaw : previous constant is missing!");
589       lawencours = Standard_True;
590     }
591     // the raduis at end.
592     if (IsConstant(ind(nbed))) Rfin = Radius(ind(nbed));
593     else{
594       // There is inevitably kpart right after!
595       Standard_Integer isuiv = (ind(nbed) + 1);
596       if(isuiv == len + 1) isuiv = 1;
597       if (IsConstant(isuiv)) {
598         Rfin = Radius(isuiv);
599       }
600       else Standard_DomainError::Raise("AppendLaw : next constant is missing!");
601     }
602   }
603   else{
604     // the radius at start.
605     if (IsConstant(ind(1))) {
606       Rdeb = Radius(ind(1));
607       curfin = Min(fin,LastParameter(ind(1)));
608       Handle(Law_Constant) curloi = new Law_Constant();
609       curloi->Set(Rdeb,curdeb,curfin);
610       list.Append(curloi);
611       curdeb = curfin;
612       icur++;
613     } 
614     else{
615       if(ind(1) > 1){
616         if (IsConstant(ind(1) - 1)){
617           Rdeb = Radius(ind(1) - 1);
618         }
619         else Standard_DomainError::Raise("AppendLaw : previous constant is missing");
620       }
621       else if(parandrad.IsEmpty()){
622         Standard_DomainError::Raise("AppendLaw : no radius on vertex");
623       }
624       else Rdeb = -1.;
625       lawencours = Standard_True;
626     }
627     // the radius at end.
628     if (IsConstant(ind(nbed))) Rfin = Radius(ind(nbed));
629     else{
630       if(ind(nbed) < len){
631         if (IsConstant(ind(nbed) + 1)) Rfin = Radius(ind(nbed) + 1);
632         else Standard_DomainError::Raise("AppendLaw : next constant is missing");
633       }
634       else if(parandrad.IsEmpty()){
635         Standard_DomainError::Raise("AppendLaw : no radius on vertex");
636       }
637       else Rfin = -1.;
638     }
639   }
640
641   // There are infos on the extremities of the elspine, 
642   // all edges are parsed 
643   for(; icur <= nbed; icur++){
644     if (IsConstant(ind(icur))) {
645       Rcur = Radius(ind(icur));
646       if(lawencours){
647         Law_Laws temp;
648         mklaw(temp,parandrad,curdeb,curfin,Rdeb,Rcur,
649               IsPeriodic(),spinedeb,spinefin,tol3d);
650         list.Append(temp);
651         lawencours = Standard_False;
652         curdeb = curfin;
653       }
654       curfin = LastParameter(ind(icur));
655       if(IsPeriodic()){ 
656         curfin = ElCLib::InPeriod(curfin,spinedeb + tol3d, spinefin + tol3d);
657         if(ind(icur) == ind(nbed)){
658           // Attention the curfin can be wrong if the last edge passes 
659           // above the  origin periodic spline.
660           Standard_Real biddeb = FirstParameter(ind(icur));
661           biddeb = ElCLib::InPeriod(biddeb,spinedeb + tol3d, spinefin + tol3d);
662           if(biddeb >= curfin) curfin = fin;
663           else curfin = Min(fin,curfin);
664         }
665         else curfin = Min(fin,curfin);
666       }
667       if((curfin - curdeb) > tol3d){
668         Rdeb = Rcur;
669         Handle(Law_Constant) curloi = new Law_Constant();
670         curloi->Set(Rdeb,curdeb,curfin);
671         list.Append(curloi);
672         curdeb = curfin;
673       }
674     }
675     else {
676       curfin = LastParameter(ind(icur));
677       if(IsPeriodic()) 
678         curfin = ElCLib::InPeriod(curfin,spinedeb + tol3d, spinefin + tol3d);
679       curfin = Min(fin,curfin);
680       lawencours = Standard_True;
681       if(ind(icur) == ind(nbed)){
682         // Attention the curfin can be wrong if the last edge passes 
683           // above the  origin periodic spline.
684         if(IsPeriodic()) {
685           Standard_Real biddeb = FirstParameter(ind(icur));
686           curfin = LastParameter(ind(icur));
687           biddeb = ElCLib::InPeriod(biddeb,spinedeb + tol3d, spinefin + tol3d);
688           curfin = ElCLib::InPeriod(curfin,spinedeb + tol3d, spinefin + tol3d);
689           if(biddeb >= curfin) curfin = fin;
690           else curfin = Min(fin,curfin);
691         }
692         // or if it is the end of spine with extension.
693         else if(ind(icur) == len) curfin = fin;
694         Law_Laws temp;
695         mklaw(temp,parandrad,curdeb,curfin,Rdeb,Rfin,
696               IsPeriodic(),spinedeb,spinefin,tol3d);
697         list.Append(temp);
698       }
699     }
700   }
701   if(!lastloi.IsNull()) list.Append(lastloi);
702   return loi;
703 }
704
705 //=======================================================================
706 //function : Law
707 //purpose  : 
708 //=======================================================================
709
710 Handle(Law_Composite) ChFiDS_FilSpine::Law(const Handle(ChFiDS_HElSpine)& Els) const 
711 {
712   ChFiDS_ListIteratorOfListOfHElSpine Itsp(elspines);
713   Law_ListIteratorOfLaws Itl(laws);
714   for(; Itsp.More(); Itsp.Next(), Itl.Next()){
715     if(Els == Itsp.Value()){
716       return Handle(Law_Composite)::DownCast(Itl.Value());
717     }
718   }
719   return Handle(Law_Composite)();
720 }
721
722 //=======================================================================
723 //function : Law
724 //purpose  : 
725 //=======================================================================
726
727 Handle(Law_Function)& ChFiDS_FilSpine::ChangeLaw(const TopoDS_Edge& E)
728 {
729   if(!SplitDone()) {
730     Standard_DomainError::Raise("ChFiDS_FilSpine::ChangeLaw : the limits are not up-to-date");
731   }
732   Standard_Integer IE = Index(E);
733   if (IsConstant(IE)) {
734     Standard_DomainError::Raise("ChFiDS_FilSpine::ChangeLaw : no law on constant edges");
735   }
736   Handle(ChFiDS_HElSpine) hsp = ElSpine(IE);
737   Standard_Real w = 0.5*(FirstParameter(IE) + LastParameter(IE));
738   Handle(Law_Composite) lc = Law(hsp);
739   return lc->ChangeElementaryLaw(w);
740 }
741
742
743 //=======================================================================
744 //function : Radius
745 //purpose  : 
746 //=======================================================================
747
748 Standard_Real  ChFiDS_FilSpine::MaxRadFromSeqAndLaws()const 
749 {
750   Standard_Real MaxRad = 0.;
751
752   for (Standard_Integer i = 1; i <= parandrad.Length(); i++)
753     if (parandrad(i).Y() > MaxRad)
754       MaxRad = parandrad(i).Y();
755
756   Law_ListIteratorOfLaws itl( laws );
757   for (; itl.More(); itl.Next())
758     {
759       Handle(Law_Function) law = itl.Value();
760       Standard_Real fpar, lpar, par, delta, rad;
761       law->Bounds( fpar, lpar );
762       delta = (lpar - fpar)*0.2;
763       for (Standard_Integer i = 0; i <= 4; i++)
764         {
765           par = fpar + i*delta;
766           rad = law->Value(par);
767           if (rad > MaxRad)
768             MaxRad = rad;
769         }
770       rad = law->Value(lpar);
771       if (rad > MaxRad)
772         MaxRad = rad;
773     }
774   
775   return MaxRad;
776 }