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