e924fb7eee832e1befc366ffdd32e06f571f50da
[occt.git] / src / ChFiDS / ChFiDS_Spine.cxx
1 // Created on: 1993-11-18
2 // Created by: Isabelle GRIGNON
3 // Copyright (c) 1993-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 // Modified by isg, Thu Mar 17 09:21:31 1994
18
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Curve.hxx>
21 #include <ChFiDS_ErrorStatus.hxx>
22 #include <ChFiDS_HElSpine.hxx>
23 #include <ChFiDS_ListIteratorOfListOfHElSpine.hxx>
24 #include <ChFiDS_Spine.hxx>
25 #include <ElCLib.hxx>
26 #include <GCPnts_AbscissaPoint.hxx>
27 #include <gp_Circ.hxx>
28 #include <gp_Lin.hxx>
29 #include <gp_Pnt.hxx>
30 #include <gp_Vec.hxx>
31 #include <Precision.hxx>
32 #include <Standard_Type.hxx>
33 #include <TopExp.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Vertex.hxx>
36
37 //=======================================================================
38 //function : ChFiDS_Spine
39 //purpose  : 
40 //=======================================================================
41 ChFiDS_Spine::ChFiDS_Spine():
42        splitdone(Standard_False),
43        tolesp(Precision::Confusion()),
44        firstprolon(Standard_False), 
45        lastprolon(Standard_False),
46        firstistgt(Standard_False), 
47        lastistgt(Standard_False),
48        hasfirsttgt(Standard_False), 
49        haslasttgt(Standard_False),
50        hasref(Standard_False)
51 {
52 }
53
54 ChFiDS_Spine::ChFiDS_Spine(const Standard_Real Tol):
55        splitdone(Standard_False),
56        tolesp(Tol),
57        firstprolon(Standard_False), 
58        lastprolon(Standard_False),
59        firstistgt(Standard_False), 
60        lastistgt(Standard_False),
61        hasfirsttgt(Standard_False), 
62        haslasttgt(Standard_False),
63        hasref(Standard_False)
64 {
65 }
66
67 //=======================================================================
68 //function : AppendElSpine
69 //purpose  : 
70 //=======================================================================
71
72 void ChFiDS_Spine::AppendElSpine(const Handle(ChFiDS_HElSpine)& Els)
73 {
74   elspines.Append(Els);
75 }
76
77 //=======================================================================
78 //function : ElSpine
79 //purpose  : 
80 //=======================================================================
81
82 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const TopoDS_Edge& E) const 
83 {
84   return ElSpine(Index(E));
85 }
86
87 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Integer IE) const 
88 {
89   Standard_Real wmil = 0.5 * (FirstParameter(IE) + LastParameter(IE));
90   if(IsPeriodic()) wmil = ElCLib::InPeriod(wmil,FirstParameter(),LastParameter());
91   return ElSpine(wmil);
92 }
93
94 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Real W) const 
95 {
96   ChFiDS_ListIteratorOfListOfHElSpine It(elspines);
97   for (; It.More(); It.Next()) {
98     Handle(ChFiDS_HElSpine) cur = It.Value();
99     Standard_Real uf = cur->FirstParameter();
100     Standard_Real ul = cur->LastParameter();
101     if(uf <= W && W <= ul) return cur;
102   }  
103   return Handle(ChFiDS_HElSpine)();
104 }
105
106 //=======================================================================
107 //function : ChangeElSpines
108 //purpose  : 
109 //=======================================================================
110
111 ChFiDS_ListOfHElSpine& ChFiDS_Spine::ChangeElSpines() 
112 {
113   return elspines;
114 }
115
116 //=======================================================================
117 //function : SplitDone
118 //purpose  : 
119 //=======================================================================
120
121 void ChFiDS_Spine::SplitDone(const Standard_Boolean B)
122 {
123   splitdone = B;
124 }
125
126 //=======================================================================
127 //function : SplitDone
128 //purpose  : 
129 //=======================================================================
130
131 Standard_Boolean ChFiDS_Spine::SplitDone() const 
132 {
133   return splitdone;
134 }
135
136 //=======================================================================
137 //function : Reset
138 //purpose  : 
139 //=======================================================================
140
141 void ChFiDS_Spine::Reset(const Standard_Boolean AllData)
142 {
143   splitdone = Standard_False;
144   //if(AllData && !isconstant.IsNull()) isconstant->ChangeArray1().Init(0);
145   elspines.Clear();
146   if(AllData){
147     firstparam = 0.;
148     lastparam = abscissa->Value(abscissa->Upper());
149     firstprolon = lastprolon = Standard_False;
150   }
151 }
152
153 //=======================================================================
154 //function : FirstParameter
155 //purpose  : 
156 //=======================================================================
157
158 Standard_Real  ChFiDS_Spine::FirstParameter() const
159 {
160   if(firstprolon) return firstparam;
161   return 0.;
162 }
163
164
165 //=======================================================================
166 //function : LastParameter
167 //purpose  : 
168 //=======================================================================
169
170 Standard_Real  ChFiDS_Spine::LastParameter() const
171 {
172   if(lastprolon) return lastparam;
173   return abscissa->Value(abscissa->Upper());
174 }
175
176 //=======================================================================
177 //function : SetFirstParameter
178 //purpose  : 
179 //=======================================================================
180
181 void ChFiDS_Spine::SetFirstParameter(const Standard_Real Par) 
182 {
183 #ifdef OCCT_DEBUG
184   if(Par >= Precision::Confusion()) 
185     cout<<"Interior extension at the start of guideline"<<endl;
186   if(IsPeriodic())
187     cout<<"WARNING!!! Extension on periodic guideline."<<endl;
188 #endif
189   firstprolon = Standard_True;
190   firstparam = Par;
191 }
192
193
194 //=======================================================================
195 //function : SetLastParameter
196 //purpose  : 
197 //=======================================================================
198
199 void ChFiDS_Spine::SetLastParameter(const Standard_Real Par) 
200 {
201 #ifdef OCCT_DEBUG
202   Standard_Real lll = abscissa->Value(abscissa->Upper());
203   if((Par - lll) <= -Precision::Confusion()) 
204     cout<<"Interior extension at the end of guideline"<<endl;
205   if(IsPeriodic())
206     cout<<"WARNING!!! Extension on periodic guideline."<<endl;
207 #endif
208   lastprolon = Standard_True;
209   lastparam = Par;
210 }
211
212 //=======================================================================
213 //function : FirstParameter
214 //purpose  : 
215 //=======================================================================
216
217 Standard_Real  ChFiDS_Spine::FirstParameter
218 (const Standard_Integer IndexSpine) const 
219 {
220   if (IndexSpine==1) return 0.;
221   return abscissa->Value(IndexSpine-1);
222 }
223
224 //=======================================================================
225 //function : LastParameter
226 //purpose  : 
227 //=======================================================================
228
229 Standard_Real  ChFiDS_Spine::LastParameter
230 (const Standard_Integer IndexSpine) const 
231 {
232   return abscissa->Value(IndexSpine);
233 }
234
235 //=======================================================================
236 //function : Length
237 //purpose  : 
238 //=======================================================================
239
240 Standard_Real  ChFiDS_Spine::Length
241 (const Standard_Integer IndexSpine) const 
242 {
243   if (IndexSpine==1) return abscissa->Value(IndexSpine);
244   return abscissa->Value(IndexSpine) - abscissa->Value(IndexSpine-1);
245 }
246
247 //=======================================================================
248 //function : IsPeriodic
249 //purpose  : 
250 //=======================================================================
251
252 Standard_Boolean ChFiDS_Spine::IsPeriodic() const
253 {
254   return (firstState == ChFiDS_Closed);
255 }
256
257
258 //=======================================================================
259 //function : IsClosed
260 //purpose  : 
261 //=======================================================================
262
263 Standard_Boolean ChFiDS_Spine::IsClosed() const
264 {
265   return (FirstVertex().IsSame(LastVertex()));
266 }
267
268
269 //=======================================================================
270 //function : FirstVertex
271 //purpose  : 
272 //=======================================================================
273
274 TopoDS_Vertex ChFiDS_Spine::FirstVertex() const
275 {
276   TopoDS_Edge E = TopoDS::Edge(spine.First());
277   if(E.Orientation() == TopAbs_FORWARD) return TopExp::FirstVertex(E); 
278   return TopExp::LastVertex(E); 
279 }
280
281
282 //=======================================================================
283 //function : LastVertex
284 //purpose  : 
285 //=======================================================================
286
287 TopoDS_Vertex ChFiDS_Spine::LastVertex() const
288 {
289   TopoDS_Edge E = TopoDS::Edge(spine.Last());
290   if(E.Orientation() == TopAbs_FORWARD) return TopExp::LastVertex(E); 
291   return TopExp::FirstVertex(E); 
292 }
293
294
295 //=======================================================================
296 //function : Absc
297 //purpose  : 
298 //=======================================================================
299
300 Standard_Real ChFiDS_Spine::Absc(const TopoDS_Vertex& V) const
301 {
302   TopoDS_Vertex d,f;
303   TopoDS_Edge E;
304   for(Standard_Integer i = 1; i<=spine.Length(); i++){
305     E = TopoDS::Edge(spine.Value(i));
306     TopExp::Vertices(E,d,f);
307     if(d.IsSame(V) && E.Orientation() == TopAbs_FORWARD){
308       return FirstParameter(i);
309     }
310     if(d.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
311       return LastParameter(i);
312     }
313     if(f.IsSame(V) && E.Orientation() == TopAbs_FORWARD){
314       return LastParameter(i);
315     }
316     if(f.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
317       return FirstParameter(i);
318     }
319   }
320   return -1.;
321 }
322
323
324 //=======================================================================
325 //function : Period
326 //purpose  : 
327 //=======================================================================
328
329 Standard_Real ChFiDS_Spine::Period() const
330 {
331   if(!IsPeriodic()) Standard_Failure::Raise("Non-periodic Spine");
332   return abscissa->Value(abscissa->Upper());
333 }
334
335
336 //=======================================================================
337 //function : Resolution
338 //purpose  : 
339 //=======================================================================
340
341 Standard_Real ChFiDS_Spine::Resolution(const Standard_Real R3d) const
342 {
343   return R3d;
344 }
345
346
347 //=======================================================================
348 //function : SetFirstTgt
349 //purpose  : 
350 //=======================================================================
351
352 void  ChFiDS_Spine::SetFirstTgt(const Standard_Real W)
353 {
354   if(IsPeriodic()) Standard_Failure::Raise
355     ("No extension by tangent on periodic contours"); 
356 #ifdef OCCT_DEBUG
357   if(W >= Precision::Confusion()) 
358     cout<<"Interior extension at start of the guideline"<<endl;
359 #endif
360   //The flag is suspended if is already positioned to avoid  
361   //stopping d1
362   hasfirsttgt = Standard_False;
363   D1(W,firstori,firsttgt);
364   //and it is reset.
365   hasfirsttgt = Standard_True;
366   firsttgtpar = W;
367 }
368
369
370 //=======================================================================
371 //function : SetLastTgt
372 //purpose  : 
373 //=======================================================================
374
375 void  ChFiDS_Spine::SetLastTgt(const Standard_Real W)
376 {
377   if(IsPeriodic()) Standard_Failure::Raise
378     ("No extension by tangent periodic contours"); 
379
380 #ifdef OCCT_DEBUG
381   Standard_Real L = W - abscissa->Value(abscissa->Upper());
382   if(L <= -Precision::Confusion()) 
383     cout<<"Interior extension at the end of guideline"<<endl;
384 #endif
385   //The flag is suspended if is already positioned to avoid  
386   //stopping d1 
387   haslasttgt = Standard_False;
388   D1(W,lastori,lasttgt);
389   //and it is reset.
390   haslasttgt = Standard_True;
391   lasttgtpar = W;
392 }
393
394
395 //=======================================================================
396 //function : HasFirstTgt
397 //purpose  : 
398 //=======================================================================
399
400 Standard_Boolean  ChFiDS_Spine::HasFirstTgt()const
401 {
402   return hasfirsttgt;
403 }
404
405 //=======================================================================
406 //function : HasLastTgt
407 //purpose  : 
408 //=======================================================================
409
410 Standard_Boolean  ChFiDS_Spine::HasLastTgt()const
411 {
412   return haslasttgt;
413 }
414
415 //=======================================================================
416 //function : SetReference
417 //purpose  : 
418 //=======================================================================
419
420 void  ChFiDS_Spine::SetReference(const Standard_Real W)
421 {
422   hasref = Standard_True;
423   Standard_Real lll = abscissa->Value(abscissa->Upper());
424   if(IsPeriodic()) valref = ElCLib::InPeriod(W,0.,lll);
425   else valref = W;
426 }
427
428
429 //=======================================================================
430 //function : SetReference
431 //purpose  : 
432 //=======================================================================
433
434 void  ChFiDS_Spine::SetReference(const Standard_Integer I)
435 {
436   hasref = Standard_True;
437   if(I == 1) valref = abscissa->Value(1)*0.5;
438   else valref = (abscissa->Value(I) + abscissa->Value(I-1))*0.5;
439 }
440
441
442 //=======================================================================
443 //function : Index
444 //purpose  : 
445 //=======================================================================
446
447 Standard_Integer ChFiDS_Spine::Index(const Standard_Real W,
448                                      const Standard_Boolean Forward) const
449 {
450   Standard_Integer ind, len = abscissa->Length();
451   Standard_Real par = W,last = abscissa->Value(abscissa->Upper());
452   Standard_Real f = 0., l = 0., t = Max(tolesp,Precision::Confusion());
453
454   if(IsPeriodic() && Abs(par) >= t && Abs(par-last) >= t) 
455     par = ElCLib::InPeriod(par,0.,last);
456   
457   for (ind=1; ind <= len; ind++) {
458     f = l;
459     l = abscissa->Value(ind);
460     if (par<l || ind==len) break;
461   }
462   if (Forward && ind<len && Abs(par-l) < t) ind++;
463   else if (!Forward && ind > 1 && Abs(par-f) < t) ind--;
464   else if (Forward && IsPeriodic() && ind == len && Abs(par-l) < t) ind = 1;
465   else if (!Forward && IsPeriodic() && ind == 1 && Abs(par-f) < t) ind = len;
466   return ind;
467 }
468
469 //=======================================================================
470 //function : Index
471 //purpose  : 
472 //=======================================================================
473
474 Standard_Integer ChFiDS_Spine::Index (const TopoDS_Edge& E) const
475 {
476   for(Standard_Integer IE = 1; IE <= spine.Length(); IE++){
477     if(E.IsSame(spine.Value(IE))) return IE;
478   }
479   return 0;
480 }
481
482 //=======================================================================
483 //function : UnsetReference
484 //purpose  : 
485 //=======================================================================
486
487 void  ChFiDS_Spine::UnsetReference()
488 {
489   hasref = Standard_False;
490 }
491
492 //=======================================================================
493 //function : Load
494 //purpose  : 
495 //=======================================================================
496
497 void  ChFiDS_Spine::Load()
498 {
499   if(!abscissa.IsNull()){
500 #ifdef OCCT_DEBUG
501     cout<<"new load of CE"<<endl;
502 #endif
503   }
504   Standard_Integer len = spine.Length();
505   abscissa = new TColStd_HArray1OfReal(1,len);
506   Standard_Real a1 = 0.;
507   for (Standard_Integer i = 1; i <= len; i++){
508     myCurve.Initialize(TopoDS::Edge(spine.Value(i)));
509     a1 += GCPnts_AbscissaPoint::Length(myCurve);
510     abscissa->SetValue(i,a1);
511   }
512   indexofcurve =1;
513   myCurve.Initialize(TopoDS::Edge(spine.Value(1)));
514 }
515
516
517 //=======================================================================
518 //function : Absc
519 //purpose  : 
520 //=======================================================================
521
522 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U) 
523 {
524   return Absc(U,indexofcurve);
525 }
526
527 //=======================================================================
528 //function : Absc
529 //purpose  : 
530 //=======================================================================
531
532 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U,
533                                  const Standard_Integer I) 
534 {
535
536   
537   if(indexofcurve != I){
538     void* p = (void*)this;
539     ((ChFiDS_Spine*)p)->indexofcurve = I;
540     ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(I)));
541   }
542   Standard_Real L = FirstParameter(I);
543   if (spine.Value(I).Orientation() == TopAbs_REVERSED) {
544     L += GCPnts_AbscissaPoint::Length(myCurve,U,myCurve.LastParameter());
545   }
546   else{
547     L += GCPnts_AbscissaPoint::Length(myCurve,myCurve.FirstParameter(),U);
548   }
549   return L;
550 }
551
552 //=======================================================================
553 //function : Parameter
554 //purpose  : 
555 //=======================================================================
556
557 void ChFiDS_Spine::Parameter(const Standard_Real AbsC,
558                              Standard_Real& U,
559                              const Standard_Boolean Oriented) 
560 {
561   Standard_Integer Index;
562   for (Index=1;Index<abscissa->Length();Index++) {
563     if (AbsC<abscissa->Value(Index)) break;
564   }
565   Parameter(Index,AbsC,U,Oriented);
566 }
567
568
569 //=======================================================================
570 //function : Parameter
571 //purpose  : 
572 //=======================================================================
573
574 void ChFiDS_Spine::Parameter(const Standard_Integer Index,
575                              const Standard_Real AbsC,
576                              Standard_Real& U,
577                              const Standard_Boolean Oriented) 
578 {
579
580   if (Index != indexofcurve) {
581     void* p = (void*)this;
582     ((ChFiDS_Spine*)p)->indexofcurve = Index;
583     ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
584   }
585   Standard_Real L;
586   TopAbs_Orientation Or = spine.Value(Index).Orientation();
587   if (Or == TopAbs_REVERSED) {
588     L = abscissa->Value(indexofcurve)-AbsC; 
589   }
590   else if (indexofcurve==1) {
591     L = AbsC;
592   }  
593   else {
594     L = AbsC - abscissa->Value(indexofcurve-1); 
595   }
596   Standard_Real t = L/Length(Index);
597   Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
598 //  GCPnts_AbscissaPoint GCP;
599 //  GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
600   GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
601   U = GCP.Parameter();
602   if (Or == TopAbs_REVERSED && Oriented) {
603     U = (myCurve.LastParameter()+myCurve.FirstParameter()) - U;
604   }
605 }
606
607
608 //=======================================================================
609 //function : Prepare
610 //purpose  : 
611 //=======================================================================
612
613 void  ChFiDS_Spine::Prepare(Standard_Real& L, 
614                             Standard_Integer& Ind) const
615 {
616   Standard_Real tol = Max(tolesp,Precision::Confusion());
617   Standard_Real last = abscissa->Value(abscissa->Upper());
618   Standard_Integer len = abscissa->Length();
619   if(IsPeriodic() && Abs(L) >= tol && Abs(L-last) >= tol) 
620     L = ElCLib::InPeriod(L,0.,last);
621
622   if(hasfirsttgt && (L <= firsttgtpar)){
623     if(hasref && valref >= L && Abs(L-firsttgtpar) <= tol){
624       Ind = Index(L);
625     }
626     else{Ind = -1; L -= firsttgtpar;} 
627   }
628   else if(L <= 0.){Ind = 1;}
629   else if(haslasttgt && (L >= lasttgtpar)){
630     if(hasref && valref <= L && Abs(L-lasttgtpar) <= tol){
631       Ind = Index(L); 
632     }
633     else{Ind = len + 1; L -= lasttgtpar;} 
634   }
635   else if(L >= last){Ind = len;}
636   else{
637     for (Ind=1;Ind < len;Ind++) {
638       if (L<abscissa->Value(Ind)) break;
639     }
640     if(hasref){
641       if (L >= valref && Ind != 1){
642         if(Abs(L-abscissa->Value(Ind-1)) <= Precision::Confusion()) Ind--;
643       }
644       else if (L <= valref && Ind != len){
645         if(Abs(L-abscissa->Value(Ind)) <= Precision::Confusion()) Ind++;
646       }
647     }
648   }
649   if(Ind >= 1 && Ind <= len){ 
650     if (spine.Value(Ind).Orientation() == TopAbs_REVERSED){
651       L = abscissa->Value(Ind) - L; 
652     }
653     else if (Ind!=1){
654       L -= abscissa->Value(Ind - 1); 
655     }
656   }
657 }
658
659 //=======================================================================
660 //function : Value
661 //purpose  : 
662 //=======================================================================
663
664 gp_Pnt  ChFiDS_Spine::Value(const Standard_Real AbsC) 
665 {
666
667   Standard_Integer Index;
668   Standard_Real L = AbsC;
669
670   Prepare(L,Index);
671
672   if (Index == -1) {
673     gp_Pnt Pp = firstori;
674     gp_Vec Vp = firsttgt;
675     Vp.Multiply(L);
676     Pp.Translate(Vp);
677     return Pp;
678   }
679   else if (Index == (abscissa->Length() + 1)) {
680     gp_Pnt Pp = lastori;
681     gp_Vec Vp = lasttgt;
682     Vp.Multiply(L);
683     Pp.Translate(Vp);
684     return Pp;
685   }
686   if (Index != indexofcurve) {
687     void* p = (void*)this;
688     ((ChFiDS_Spine*)p)->indexofcurve = Index;
689     ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
690   }
691   Standard_Real t = L/Length(Index);
692   Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
693 //  GCPnts_AbscissaPoint GCP;
694 //  GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
695   GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
696   return myCurve.Value(GCP.Parameter());
697 }
698
699 //=======================================================================
700 //function : D0
701 //purpose  : 
702 //=======================================================================
703
704 void  ChFiDS_Spine::D0(const Standard_Real AbsC, gp_Pnt& P) 
705 {
706   P = Value(AbsC);
707 }
708
709 //=======================================================================
710 //function : D1
711 //purpose  : 
712 //=======================================================================
713
714 void  ChFiDS_Spine::D1(const Standard_Real AbsC, 
715                                    gp_Pnt& P, 
716                                    gp_Vec& V1) 
717 {
718   Standard_Integer Index;
719   Standard_Real L = AbsC;
720
721   Prepare(L,Index);
722
723   if (Index == -1) {
724     P = firstori;
725     V1 = firsttgt;
726     gp_Vec Vp = firsttgt;
727     Vp.Multiply(L);
728     P.Translate(Vp);
729   }
730   else if (Index == (abscissa->Length() + 1)) {
731     P = lastori;
732     V1 = lasttgt;
733     gp_Vec Vp = lasttgt;
734     Vp.Multiply(L);
735     P.Translate(Vp);
736   }
737   else {
738     if (Index != indexofcurve) {
739       void* p = (void*)this;
740       ((ChFiDS_Spine*)p)->indexofcurve = Index;
741       ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
742     }
743     Standard_Real t = L/Length(Index);
744     Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
745 //    GCPnts_AbscissaPoint GCP;
746 //    GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
747     GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
748     myCurve.D1(GCP.Parameter(),P,V1);
749     Standard_Real D1 = 1./V1.Magnitude();
750     if (spine.Value(Index).Orientation() == TopAbs_REVERSED) D1 = -D1;
751     V1.Multiply(D1);
752   }
753 }
754
755
756 //=======================================================================
757 //function : D2
758 //purpose  : 
759 //=======================================================================
760
761 void  ChFiDS_Spine::D2(const Standard_Real AbsC, 
762                                    gp_Pnt& P, 
763                                    gp_Vec& V1, 
764                                    gp_Vec& V2) 
765 {
766
767   Standard_Integer Index;
768   Standard_Real L = AbsC;
769
770   Prepare(L,Index);
771
772   if (Index == -1) {
773     P = firstori;
774     V1 = firsttgt;
775     V2.SetCoord(0.,0.,0.);
776     gp_Vec Vp = firsttgt;
777     Vp.Multiply(L);
778     P.Translate(Vp);
779   }
780   else if (Index == (abscissa->Length() + 1)) {
781     P = lastori;
782     V1 = lasttgt;
783     V2.SetCoord(0.,0.,0.);
784     gp_Vec Vp = lasttgt;
785     Vp.Multiply(L);
786     P.Translate(Vp);
787   }
788   else {
789     if (Index != indexofcurve) {
790       void* p = (void*)this;
791       ((ChFiDS_Spine*)p)->indexofcurve = Index;
792       ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
793     }
794     Standard_Real t = L/Length(Index);
795     Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
796 //    GCPnts_AbscissaPoint GCP;
797 //    GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
798     GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
799     myCurve.D2(GCP.Parameter(),P,V1,V2);
800     Standard_Real N1 = V1.SquareMagnitude();
801     Standard_Real D2 = -(V1.Dot(V2))*(1./N1)*(1./N1);
802     V2.Multiply(1./N1);
803     N1 = Sqrt(N1);
804     gp_Vec Va = V1.Multiplied(D2);
805     V2.Add(Va);
806     Standard_Real D1 = 1./N1;
807     if (spine.Value(Index).Orientation() == TopAbs_REVERSED) D1 = -D1;
808     V1.Multiply(D1);
809   }
810 }
811
812 //=======================================================================
813 //function : SetCurrent
814 //purpose  : 
815 //=======================================================================
816
817 void ChFiDS_Spine::SetCurrent(const Standard_Integer Index)
818 {  
819   if (Index != indexofcurve)  {
820     indexofcurve = Index;
821     myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
822   }
823
824
825 //=======================================================================
826 //function : CurrentElementarySpine
827 //purpose  : 
828 //=======================================================================
829
830 const BRepAdaptor_Curve&  ChFiDS_Spine::CurrentElementarySpine
831 (const Standard_Integer Index) 
832 {
833   if (Index != indexofcurve)  {
834     indexofcurve = Index;
835     myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
836   }
837   return myCurve;
838 }
839
840 //=======================================================================
841 //function : GetType
842 //purpose  : 
843 //=======================================================================
844
845 GeomAbs_CurveType ChFiDS_Spine::GetType() const
846 {
847   return myCurve.GetType();
848 }
849
850 //=======================================================================
851 //function : Line
852 //purpose  : 
853 //=======================================================================
854
855 gp_Lin ChFiDS_Spine::Line() const
856 {
857   gp_Lin LL(myCurve.Line());
858   if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
859     LL.Reverse();
860     LL.SetLocation(myCurve.Value(myCurve.LastParameter()));
861   }
862   else {
863     LL.SetLocation(myCurve.Value(myCurve.FirstParameter()));
864   }
865   return LL;
866 }
867
868
869 //=======================================================================
870 //function : Circle
871 //purpose  : 
872 //=======================================================================
873
874 gp_Circ ChFiDS_Spine::Circle() const
875 {
876   gp_Ax2 Ac = myCurve.Circle().Position();
877   gp_Dir Dc(gp_Vec(Ac.Location(),myCurve.Value(myCurve.FirstParameter())));
878   gp_Dir ZZ(Ac.Direction());
879   
880   if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
881     Dc = gp_Dir(gp_Vec(Ac.Location(),myCurve.Value(myCurve.LastParameter())));
882     ZZ.Reverse();
883   }
884   gp_Ax2 A(Ac.Location(),ZZ,Dc);
885   return gp_Circ(A,myCurve.Circle().Radius());
886 }
887 //=======================================================================
888 //function : SetErrorStatus
889 //purpose  : met a jour le statut d'erreur 
890 //=======================================================================
891 void  ChFiDS_Spine::SetErrorStatus(const ChFiDS_ErrorStatus state)
892 {
893   errorstate=state;
894 }
895 //=======================================================================
896 //function : ErrorStatus
897 //purpose  : renvoie le statut d'erreur concernant la spine 
898 //=======================================================================
899
900 ChFiDS_ErrorStatus  ChFiDS_Spine::ErrorStatus()const 
901 {
902   return errorstate;
903 }