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