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