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