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