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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified by isg, Thu Mar 17 09:21:31 1994
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>
26 #include <BRep_Tool.hxx>
28 #include <Precision.hxx>
30 //=======================================================================
31 //function : ChFiDS_Spine
33 //=======================================================================
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)
48 ChFiDS_Spine::ChFiDS_Spine(const Standard_Real Tol):
49 splitdone(Standard_False),
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)
61 //=======================================================================
62 //function : AppendElSpine
64 //=======================================================================
66 void ChFiDS_Spine::AppendElSpine(const Handle(ChFiDS_HElSpine)& Els)
71 //=======================================================================
74 //=======================================================================
76 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const TopoDS_Edge& E) const
78 return ElSpine(Index(E));
81 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Integer IE) const
83 Standard_Real wmil = 0.5 * (FirstParameter(IE) + LastParameter(IE));
84 if(IsPeriodic()) wmil = ElCLib::InPeriod(wmil,FirstParameter(),LastParameter());
88 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Real W) const
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;
97 return Handle(ChFiDS_HElSpine)();
100 //=======================================================================
101 //function : ChangeElSpines
103 //=======================================================================
105 ChFiDS_ListOfHElSpine& ChFiDS_Spine::ChangeElSpines()
110 //=======================================================================
111 //function : SplitDone
113 //=======================================================================
115 void ChFiDS_Spine::SplitDone(const Standard_Boolean B)
120 //=======================================================================
121 //function : SplitDone
123 //=======================================================================
125 Standard_Boolean ChFiDS_Spine::SplitDone() const
130 //=======================================================================
133 //=======================================================================
135 void ChFiDS_Spine::Reset(const Standard_Boolean AllData)
137 splitdone = Standard_False;
138 //if(AllData && !isconstant.IsNull()) isconstant->ChangeArray1().Init(0);
142 lastparam = abscissa->Value(abscissa->Upper());
143 firstprolon = lastprolon = Standard_False;
147 //=======================================================================
148 //function : FirstParameter
150 //=======================================================================
152 Standard_Real ChFiDS_Spine::FirstParameter() const
154 if(firstprolon) return firstparam;
159 //=======================================================================
160 //function : LastParameter
162 //=======================================================================
164 Standard_Real ChFiDS_Spine::LastParameter() const
166 if(lastprolon) return lastparam;
167 return abscissa->Value(abscissa->Upper());
170 //=======================================================================
171 //function : SetFirstParameter
173 //=======================================================================
175 void ChFiDS_Spine::SetFirstParameter(const Standard_Real Par)
178 if(Par >= Precision::Confusion())
179 cout<<"Interior extension at the start of guideline"<<endl;
181 cout<<"WARNING!!! Extension on periodic guideline."<<endl;
183 firstprolon = Standard_True;
188 //=======================================================================
189 //function : SetLastParameter
191 //=======================================================================
193 void ChFiDS_Spine::SetLastParameter(const Standard_Real Par)
196 Standard_Real lll = abscissa->Value(abscissa->Upper());
197 if((Par - lll) <= -Precision::Confusion())
198 cout<<"Interior extension at the end of guideline"<<endl;
200 cout<<"WARNING!!! Extension on periodic guideline."<<endl;
202 lastprolon = Standard_True;
206 //=======================================================================
207 //function : FirstParameter
209 //=======================================================================
211 Standard_Real ChFiDS_Spine::FirstParameter
212 (const Standard_Integer IndexSpine) const
214 if (IndexSpine==1) return 0.;
215 return abscissa->Value(IndexSpine-1);
218 //=======================================================================
219 //function : LastParameter
221 //=======================================================================
223 Standard_Real ChFiDS_Spine::LastParameter
224 (const Standard_Integer IndexSpine) const
226 return abscissa->Value(IndexSpine);
229 //=======================================================================
232 //=======================================================================
234 Standard_Real ChFiDS_Spine::Length
235 (const Standard_Integer IndexSpine) const
237 if (IndexSpine==1) return abscissa->Value(IndexSpine);
238 return abscissa->Value(IndexSpine) - abscissa->Value(IndexSpine-1);
241 //=======================================================================
242 //function : IsPeriodic
244 //=======================================================================
246 Standard_Boolean ChFiDS_Spine::IsPeriodic() const
248 return (firstState == ChFiDS_Closed);
252 //=======================================================================
253 //function : IsClosed
255 //=======================================================================
257 Standard_Boolean ChFiDS_Spine::IsClosed() const
259 return (FirstVertex().IsSame(LastVertex()));
263 //=======================================================================
264 //function : FirstVertex
266 //=======================================================================
268 TopoDS_Vertex ChFiDS_Spine::FirstVertex() const
270 TopoDS_Edge E = TopoDS::Edge(spine.First());
271 if(E.Orientation() == TopAbs_FORWARD) return TopExp::FirstVertex(E);
272 return TopExp::LastVertex(E);
276 //=======================================================================
277 //function : LastVertex
279 //=======================================================================
281 TopoDS_Vertex ChFiDS_Spine::LastVertex() const
283 TopoDS_Edge E = TopoDS::Edge(spine.Last());
284 if(E.Orientation() == TopAbs_FORWARD) return TopExp::LastVertex(E);
285 return TopExp::FirstVertex(E);
289 //=======================================================================
292 //=======================================================================
294 Standard_Real ChFiDS_Spine::Absc(const TopoDS_Vertex& V) const
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);
304 if(d.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
305 return LastParameter(i);
307 if(f.IsSame(V) && E.Orientation() == TopAbs_FORWARD){
308 return LastParameter(i);
310 if(f.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
311 return FirstParameter(i);
318 //=======================================================================
321 //=======================================================================
323 Standard_Real ChFiDS_Spine::Period() const
325 if(!IsPeriodic()) Standard_Failure::Raise("Non-periodic Spine");
326 return abscissa->Value(abscissa->Upper());
330 //=======================================================================
331 //function : Resolution
333 //=======================================================================
335 Standard_Real ChFiDS_Spine::Resolution(const Standard_Real R3d) const
341 //=======================================================================
342 //function : SetFirstTgt
344 //=======================================================================
346 void ChFiDS_Spine::SetFirstTgt(const Standard_Real W)
348 if(IsPeriodic()) Standard_Failure::Raise
349 ("No extension by tangent on periodic contours");
351 if(W >= Precision::Confusion())
352 cout<<"Interior extension at start of the guideline"<<endl;
354 //The flag is suspended if is already positioned to avoid
356 hasfirsttgt = Standard_False;
357 D1(W,firstori,firsttgt);
359 hasfirsttgt = Standard_True;
364 //=======================================================================
365 //function : SetLastTgt
367 //=======================================================================
369 void ChFiDS_Spine::SetLastTgt(const Standard_Real W)
371 if(IsPeriodic()) Standard_Failure::Raise
372 ("No extension by tangent periodic contours");
375 Standard_Real L = W - abscissa->Value(abscissa->Upper());
376 if(L <= -Precision::Confusion())
377 cout<<"Interior extension at the end of guideline"<<endl;
379 //The flag is suspended if is already positioned to avoid
381 haslasttgt = Standard_False;
382 D1(W,lastori,lasttgt);
384 haslasttgt = Standard_True;
389 //=======================================================================
390 //function : HasFirstTgt
392 //=======================================================================
394 Standard_Boolean ChFiDS_Spine::HasFirstTgt()const
399 //=======================================================================
400 //function : HasLastTgt
402 //=======================================================================
404 Standard_Boolean ChFiDS_Spine::HasLastTgt()const
409 //=======================================================================
410 //function : SetReference
412 //=======================================================================
414 void ChFiDS_Spine::SetReference(const Standard_Real W)
416 hasref = Standard_True;
417 Standard_Real lll = abscissa->Value(abscissa->Upper());
418 if(IsPeriodic()) valref = ElCLib::InPeriod(W,0.,lll);
423 //=======================================================================
424 //function : SetReference
426 //=======================================================================
428 void ChFiDS_Spine::SetReference(const Standard_Integer I)
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;
436 //=======================================================================
439 //=======================================================================
441 Standard_Integer ChFiDS_Spine::Index(const Standard_Real W,
442 const Standard_Boolean Forward) const
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());
448 if(IsPeriodic() && Abs(par) >= t && Abs(par-last) >= t)
449 par = ElCLib::InPeriod(par,0.,last);
451 for (ind=1; ind <= len; ind++) {
453 l = abscissa->Value(ind);
454 if (par<l || ind==len) break;
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;
463 //=======================================================================
466 //=======================================================================
468 Standard_Integer ChFiDS_Spine::Index (const TopoDS_Edge& E) const
470 for(Standard_Integer IE = 1; IE <= spine.Length(); IE++){
471 if(E.IsSame(spine.Value(IE))) return IE;
476 //=======================================================================
477 //function : UnsetReference
479 //=======================================================================
481 void ChFiDS_Spine::UnsetReference()
483 hasref = Standard_False;
486 //=======================================================================
489 //=======================================================================
491 void ChFiDS_Spine::Load()
493 if(!abscissa.IsNull()){
495 cout<<"new load of CE"<<endl;
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);
507 myCurve.Initialize(TopoDS::Edge(spine.Value(1)));
511 //=======================================================================
514 //=======================================================================
516 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U)
518 return Absc(U,indexofcurve);
521 //=======================================================================
524 //=======================================================================
526 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U,
527 const Standard_Integer I)
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)));
536 Standard_Real L = FirstParameter(I);
537 if (spine.Value(I).Orientation() == TopAbs_REVERSED) {
538 L += GCPnts_AbscissaPoint::Length(myCurve,U,myCurve.LastParameter());
541 L += GCPnts_AbscissaPoint::Length(myCurve,myCurve.FirstParameter(),U);
546 //=======================================================================
547 //function : Parameter
549 //=======================================================================
551 void ChFiDS_Spine::Parameter(const Standard_Real AbsC,
553 const Standard_Boolean Oriented)
555 Standard_Integer Index;
556 for (Index=1;Index<abscissa->Length();Index++) {
557 if (AbsC<abscissa->Value(Index)) break;
559 Parameter(Index,AbsC,U,Oriented);
563 //=======================================================================
564 //function : Parameter
566 //=======================================================================
568 void ChFiDS_Spine::Parameter(const Standard_Integer Index,
569 const Standard_Real AbsC,
571 const Standard_Boolean Oriented)
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)));
580 TopAbs_Orientation Or = spine.Value(Index).Orientation();
581 if (Or == TopAbs_REVERSED) {
582 L = abscissa->Value(indexofcurve)-AbsC;
584 else if (indexofcurve==1) {
588 L = AbsC - abscissa->Value(indexofcurve-1);
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);
596 if (Or == TopAbs_REVERSED && Oriented) {
597 U = (myCurve.LastParameter()+myCurve.FirstParameter()) - U;
602 //=======================================================================
605 //=======================================================================
607 void ChFiDS_Spine::Prepare(Standard_Real& L,
608 Standard_Integer& Ind) const
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);
616 if(hasfirsttgt && (L <= firsttgtpar)){
617 if(hasref && valref >= L && Abs(L-firsttgtpar) <= tol){
620 else{Ind = -1; L -= firsttgtpar;}
622 else if(L <= 0.){Ind = 1;}
623 else if(haslasttgt && (L >= lasttgtpar)){
624 if(hasref && valref <= L && Abs(L-lasttgtpar) <= tol){
627 else{Ind = len + 1; L -= lasttgtpar;}
629 else if(L >= last){Ind = len;}
631 for (Ind=1;Ind < len;Ind++) {
632 if (L<abscissa->Value(Ind)) break;
635 if (L >= valref && Ind != 1){
636 if(Abs(L-abscissa->Value(Ind-1)) <= Precision::Confusion()) Ind--;
638 else if (L <= valref && Ind != len){
639 if(Abs(L-abscissa->Value(Ind)) <= Precision::Confusion()) Ind++;
643 if(Ind >= 1 && Ind <= len){
644 if (spine.Value(Ind).Orientation() == TopAbs_REVERSED){
645 L = abscissa->Value(Ind) - L;
648 L -= abscissa->Value(Ind - 1);
653 //=======================================================================
656 //=======================================================================
658 gp_Pnt ChFiDS_Spine::Value(const Standard_Real AbsC)
661 Standard_Integer Index;
662 Standard_Real L = AbsC;
667 gp_Pnt Pp = firstori;
668 gp_Vec Vp = firsttgt;
673 else if (Index == (abscissa->Length() + 1)) {
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)));
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());
693 //=======================================================================
696 //=======================================================================
698 void ChFiDS_Spine::D0(const Standard_Real AbsC, gp_Pnt& P)
703 //=======================================================================
706 //=======================================================================
708 void ChFiDS_Spine::D1(const Standard_Real AbsC,
712 Standard_Integer Index;
713 Standard_Real L = AbsC;
720 gp_Vec Vp = firsttgt;
724 else if (Index == (abscissa->Length() + 1)) {
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)));
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;
750 //=======================================================================
753 //=======================================================================
755 void ChFiDS_Spine::D2(const Standard_Real AbsC,
761 Standard_Integer Index;
762 Standard_Real L = AbsC;
769 V2.SetCoord(0.,0.,0.);
770 gp_Vec Vp = firsttgt;
774 else if (Index == (abscissa->Length() + 1)) {
777 V2.SetCoord(0.,0.,0.);
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)));
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);
798 gp_Vec Va = V1.Multiplied(D2);
800 Standard_Real D1 = 1./N1;
801 if (spine.Value(Index).Orientation() == TopAbs_REVERSED) D1 = -D1;
806 //=======================================================================
807 //function : SetCurrent
809 //=======================================================================
811 void ChFiDS_Spine::SetCurrent(const Standard_Integer Index)
813 if (Index != indexofcurve) {
814 indexofcurve = Index;
815 myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
819 //=======================================================================
820 //function : CurrentElementarySpine
822 //=======================================================================
824 const BRepAdaptor_Curve& ChFiDS_Spine::CurrentElementarySpine
825 (const Standard_Integer Index)
827 if (Index != indexofcurve) {
828 indexofcurve = Index;
829 myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
834 //=======================================================================
837 //=======================================================================
839 GeomAbs_CurveType ChFiDS_Spine::GetType() const
841 return myCurve.GetType();
844 //=======================================================================
847 //=======================================================================
849 gp_Lin ChFiDS_Spine::Line() const
851 gp_Lin LL(myCurve.Line());
852 if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
854 LL.SetLocation(myCurve.Value(myCurve.LastParameter()));
857 LL.SetLocation(myCurve.Value(myCurve.FirstParameter()));
863 //=======================================================================
866 //=======================================================================
868 gp_Circ ChFiDS_Spine::Circle() const
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());
874 if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
875 Dc = gp_Dir(gp_Vec(Ac.Location(),myCurve.Value(myCurve.LastParameter())));
878 gp_Ax2 A(Ac.Location(),ZZ,Dc);
879 return gp_Circ(A,myCurve.Circle().Radius());
881 //=======================================================================
882 //function : SetErrorStatus
883 //purpose : met a jour le statut d'erreur
884 //=======================================================================
885 void ChFiDS_Spine::SetErrorStatus(const ChFiDS_ErrorStatus state)
889 //=======================================================================
890 //function : ErrorStatus
891 //purpose : renvoie le statut d'erreur concernant la spine
892 //=======================================================================
894 ChFiDS_ErrorStatus ChFiDS_Spine::ErrorStatus()const