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