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