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
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.
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.
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.
21 // Modified by isg, Thu Mar 17 09:21:31 1994
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>
30 #include <BRep_Tool.hxx>
32 #include <Precision.hxx>
34 //=======================================================================
35 //function : ChFiDS_Spine
37 //=======================================================================
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)
52 ChFiDS_Spine::ChFiDS_Spine(const Standard_Real Tol):
53 splitdone(Standard_False),
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)
65 //=======================================================================
66 //function : AppendElSpine
68 //=======================================================================
70 void ChFiDS_Spine::AppendElSpine(const Handle(ChFiDS_HElSpine)& Els)
75 //=======================================================================
78 //=======================================================================
80 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const TopoDS_Edge& E) const
82 return ElSpine(Index(E));
85 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Integer IE) const
87 Standard_Real wmil = 0.5 * (FirstParameter(IE) + LastParameter(IE));
88 if(IsPeriodic()) wmil = ElCLib::InPeriod(wmil,FirstParameter(),LastParameter());
92 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Real W) const
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;
101 return Handle(ChFiDS_HElSpine)();
104 //=======================================================================
105 //function : ChangeElSpines
107 //=======================================================================
109 ChFiDS_ListOfHElSpine& ChFiDS_Spine::ChangeElSpines()
114 //=======================================================================
115 //function : SplitDone
117 //=======================================================================
119 void ChFiDS_Spine::SplitDone(const Standard_Boolean B)
124 //=======================================================================
125 //function : SplitDone
127 //=======================================================================
129 Standard_Boolean ChFiDS_Spine::SplitDone() const
134 //=======================================================================
137 //=======================================================================
139 void ChFiDS_Spine::Reset(const Standard_Boolean AllData)
141 splitdone = Standard_False;
142 //if(AllData && !isconstant.IsNull()) isconstant->ChangeArray1().Init(0);
146 lastparam = abscissa->Value(abscissa->Upper());
147 firstprolon = lastprolon = Standard_False;
151 //=======================================================================
152 //function : FirstParameter
154 //=======================================================================
156 Standard_Real ChFiDS_Spine::FirstParameter() const
158 if(firstprolon) return firstparam;
163 //=======================================================================
164 //function : LastParameter
166 //=======================================================================
168 Standard_Real ChFiDS_Spine::LastParameter() const
170 if(lastprolon) return lastparam;
171 return abscissa->Value(abscissa->Upper());
174 //=======================================================================
175 //function : SetFirstParameter
177 //=======================================================================
179 void ChFiDS_Spine::SetFirstParameter(const Standard_Real Par)
182 if(Par >= Precision::Confusion())
183 cout<<"Interior extension at the start of guideline"<<endl;
185 cout<<"WARNING!!! Extension on periodic guideline."<<endl;
187 firstprolon = Standard_True;
192 //=======================================================================
193 //function : SetLastParameter
195 //=======================================================================
197 void ChFiDS_Spine::SetLastParameter(const Standard_Real Par)
200 Standard_Real lll = abscissa->Value(abscissa->Upper());
201 if((Par - lll) <= -Precision::Confusion())
202 cout<<"Interior extension at the end of guideline"<<endl;
204 cout<<"WARNING!!! Extension on periodic guideline."<<endl;
206 lastprolon = Standard_True;
210 //=======================================================================
211 //function : FirstParameter
213 //=======================================================================
215 Standard_Real ChFiDS_Spine::FirstParameter
216 (const Standard_Integer IndexSpine) const
218 if (IndexSpine==1) return 0.;
219 return abscissa->Value(IndexSpine-1);
222 //=======================================================================
223 //function : LastParameter
225 //=======================================================================
227 Standard_Real ChFiDS_Spine::LastParameter
228 (const Standard_Integer IndexSpine) const
230 return abscissa->Value(IndexSpine);
233 //=======================================================================
236 //=======================================================================
238 Standard_Real ChFiDS_Spine::Length
239 (const Standard_Integer IndexSpine) const
241 if (IndexSpine==1) return abscissa->Value(IndexSpine);
242 return abscissa->Value(IndexSpine) - abscissa->Value(IndexSpine-1);
245 //=======================================================================
246 //function : IsPeriodic
248 //=======================================================================
250 Standard_Boolean ChFiDS_Spine::IsPeriodic() const
252 return (firstState == ChFiDS_Closed);
256 //=======================================================================
257 //function : IsClosed
259 //=======================================================================
261 Standard_Boolean ChFiDS_Spine::IsClosed() const
263 return (FirstVertex().IsSame(LastVertex()));
267 //=======================================================================
268 //function : FirstVertex
270 //=======================================================================
272 TopoDS_Vertex ChFiDS_Spine::FirstVertex() const
274 TopoDS_Edge E = TopoDS::Edge(spine.First());
275 if(E.Orientation() == TopAbs_FORWARD) return TopExp::FirstVertex(E);
276 return TopExp::LastVertex(E);
280 //=======================================================================
281 //function : LastVertex
283 //=======================================================================
285 TopoDS_Vertex ChFiDS_Spine::LastVertex() const
287 TopoDS_Edge E = TopoDS::Edge(spine.Last());
288 if(E.Orientation() == TopAbs_FORWARD) return TopExp::LastVertex(E);
289 return TopExp::FirstVertex(E);
293 //=======================================================================
296 //=======================================================================
298 Standard_Real ChFiDS_Spine::Absc(const TopoDS_Vertex& V) const
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);
308 if(d.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
309 return LastParameter(i);
311 if(f.IsSame(V) && E.Orientation() == TopAbs_FORWARD){
312 return LastParameter(i);
314 if(f.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
315 return FirstParameter(i);
322 //=======================================================================
325 //=======================================================================
327 Standard_Real ChFiDS_Spine::Period() const
329 if(!IsPeriodic()) Standard_Failure::Raise("Non-periodic Spine");
330 return abscissa->Value(abscissa->Upper());
334 //=======================================================================
335 //function : Resolution
337 //=======================================================================
339 Standard_Real ChFiDS_Spine::Resolution(const Standard_Real R3d) const
345 //=======================================================================
346 //function : SetFirstTgt
348 //=======================================================================
350 void ChFiDS_Spine::SetFirstTgt(const Standard_Real W)
352 if(IsPeriodic()) Standard_Failure::Raise
353 ("No extension by tangent on periodic contours");
355 if(W >= Precision::Confusion())
356 cout<<"Interior extension at start of the guideline"<<endl;
358 //The flag is suspended if is already positioned to avoid
360 hasfirsttgt = Standard_False;
361 D1(W,firstori,firsttgt);
363 hasfirsttgt = Standard_True;
368 //=======================================================================
369 //function : SetLastTgt
371 //=======================================================================
373 void ChFiDS_Spine::SetLastTgt(const Standard_Real W)
375 if(IsPeriodic()) Standard_Failure::Raise
376 ("No extension by tangent periodic contours");
379 Standard_Real L = W - abscissa->Value(abscissa->Upper());
380 if(L <= -Precision::Confusion())
381 cout<<"Interior extension at the end of guideline"<<endl;
383 //The flag is suspended if is already positioned to avoid
385 haslasttgt = Standard_False;
386 D1(W,lastori,lasttgt);
388 haslasttgt = Standard_True;
393 //=======================================================================
394 //function : HasFirstTgt
396 //=======================================================================
398 Standard_Boolean ChFiDS_Spine::HasFirstTgt()const
403 //=======================================================================
404 //function : HasLastTgt
406 //=======================================================================
408 Standard_Boolean ChFiDS_Spine::HasLastTgt()const
413 //=======================================================================
414 //function : SetReference
416 //=======================================================================
418 void ChFiDS_Spine::SetReference(const Standard_Real W)
420 hasref = Standard_True;
421 Standard_Real lll = abscissa->Value(abscissa->Upper());
422 if(IsPeriodic()) valref = ElCLib::InPeriod(W,0.,lll);
427 //=======================================================================
428 //function : SetReference
430 //=======================================================================
432 void ChFiDS_Spine::SetReference(const Standard_Integer I)
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;
440 //=======================================================================
443 //=======================================================================
445 Standard_Integer ChFiDS_Spine::Index(const Standard_Real W,
446 const Standard_Boolean Forward) const
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());
452 if(IsPeriodic() && Abs(par) >= t && Abs(par-last) >= t)
453 par = ElCLib::InPeriod(par,0.,last);
455 for (ind=1; ind <= len; ind++) {
457 l = abscissa->Value(ind);
458 if (par<l || ind==len) break;
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;
467 //=======================================================================
470 //=======================================================================
472 Standard_Integer ChFiDS_Spine::Index (const TopoDS_Edge& E) const
474 for(Standard_Integer IE = 1; IE <= spine.Length(); IE++){
475 if(E.IsSame(spine.Value(IE))) return IE;
480 //=======================================================================
481 //function : UnsetReference
483 //=======================================================================
485 void ChFiDS_Spine::UnsetReference()
487 hasref = Standard_False;
490 //=======================================================================
493 //=======================================================================
495 void ChFiDS_Spine::Load()
497 if(!abscissa.IsNull()){
499 cout<<"new load of CE"<<endl;
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);
511 myCurve.Initialize(TopoDS::Edge(spine.Value(1)));
515 //=======================================================================
518 //=======================================================================
520 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U)
522 return Absc(U,indexofcurve);
525 //=======================================================================
528 //=======================================================================
530 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U,
531 const Standard_Integer I)
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)));
540 Standard_Real L = FirstParameter(I);
541 if (spine.Value(I).Orientation() == TopAbs_REVERSED) {
542 L += GCPnts_AbscissaPoint::Length(myCurve,U,myCurve.LastParameter());
545 L += GCPnts_AbscissaPoint::Length(myCurve,myCurve.FirstParameter(),U);
550 //=======================================================================
551 //function : Parameter
553 //=======================================================================
555 void ChFiDS_Spine::Parameter(const Standard_Real AbsC,
557 const Standard_Boolean Oriented)
559 Standard_Integer Index;
560 for (Index=1;Index<abscissa->Length();Index++) {
561 if (AbsC<abscissa->Value(Index)) break;
563 Parameter(Index,AbsC,U,Oriented);
567 //=======================================================================
568 //function : Parameter
570 //=======================================================================
572 void ChFiDS_Spine::Parameter(const Standard_Integer Index,
573 const Standard_Real AbsC,
575 const Standard_Boolean Oriented)
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)));
584 TopAbs_Orientation Or = spine.Value(Index).Orientation();
585 if (Or == TopAbs_REVERSED) {
586 L = abscissa->Value(indexofcurve)-AbsC;
588 else if (indexofcurve==1) {
592 L = AbsC - abscissa->Value(indexofcurve-1);
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);
600 if (Or == TopAbs_REVERSED && Oriented) {
601 U = (myCurve.LastParameter()+myCurve.FirstParameter()) - U;
606 //=======================================================================
609 //=======================================================================
611 void ChFiDS_Spine::Prepare(Standard_Real& L,
612 Standard_Integer& Ind) const
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);
620 if(hasfirsttgt && (L <= firsttgtpar)){
621 if(hasref && valref >= L && Abs(L-firsttgtpar) <= tol){
624 else{Ind = -1; L -= firsttgtpar;}
626 else if(L <= 0.){Ind = 1;}
627 else if(haslasttgt && (L >= lasttgtpar)){
628 if(hasref && valref <= L && Abs(L-lasttgtpar) <= tol){
631 else{Ind = len + 1; L -= lasttgtpar;}
633 else if(L >= last){Ind = len;}
635 for (Ind=1;Ind < len;Ind++) {
636 if (L<abscissa->Value(Ind)) break;
639 if (L >= valref && Ind != 1){
640 if(Abs(L-abscissa->Value(Ind-1)) <= Precision::Confusion()) Ind--;
642 else if (L <= valref && Ind != len){
643 if(Abs(L-abscissa->Value(Ind)) <= Precision::Confusion()) Ind++;
647 if(Ind >= 1 && Ind <= len){
648 if (spine.Value(Ind).Orientation() == TopAbs_REVERSED){
649 L = abscissa->Value(Ind) - L;
652 L -= abscissa->Value(Ind - 1);
657 //=======================================================================
660 //=======================================================================
662 gp_Pnt ChFiDS_Spine::Value(const Standard_Real AbsC)
665 Standard_Integer Index;
666 Standard_Real L = AbsC;
671 gp_Pnt Pp = firstori;
672 gp_Vec Vp = firsttgt;
677 else if (Index == (abscissa->Length() + 1)) {
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)));
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());
697 //=======================================================================
700 //=======================================================================
702 void ChFiDS_Spine::D0(const Standard_Real AbsC, gp_Pnt& P)
707 //=======================================================================
710 //=======================================================================
712 void ChFiDS_Spine::D1(const Standard_Real AbsC,
716 Standard_Integer Index;
717 Standard_Real L = AbsC;
724 gp_Vec Vp = firsttgt;
728 else if (Index == (abscissa->Length() + 1)) {
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)));
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;
754 //=======================================================================
757 //=======================================================================
759 void ChFiDS_Spine::D2(const Standard_Real AbsC,
765 Standard_Integer Index;
766 Standard_Real L = AbsC;
773 V2.SetCoord(0.,0.,0.);
774 gp_Vec Vp = firsttgt;
778 else if (Index == (abscissa->Length() + 1)) {
781 V2.SetCoord(0.,0.,0.);
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)));
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);
802 gp_Vec Va = V1.Multiplied(D2);
804 Standard_Real D1 = 1./N1;
805 if (spine.Value(Index).Orientation() == TopAbs_REVERSED) D1 = -D1;
810 //=======================================================================
811 //function : SetCurrent
813 //=======================================================================
815 void ChFiDS_Spine::SetCurrent(const Standard_Integer Index)
817 if (Index != indexofcurve) {
818 indexofcurve = Index;
819 myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
823 //=======================================================================
824 //function : CurrentElementarySpine
826 //=======================================================================
828 const BRepAdaptor_Curve& ChFiDS_Spine::CurrentElementarySpine
829 (const Standard_Integer Index)
831 if (Index != indexofcurve) {
832 indexofcurve = Index;
833 myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
838 //=======================================================================
841 //=======================================================================
843 GeomAbs_CurveType ChFiDS_Spine::GetType() const
845 return myCurve.GetType();
848 //=======================================================================
851 //=======================================================================
853 gp_Lin ChFiDS_Spine::Line() const
855 gp_Lin LL(myCurve.Line());
856 if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
858 LL.SetLocation(myCurve.Value(myCurve.LastParameter()));
861 LL.SetLocation(myCurve.Value(myCurve.FirstParameter()));
867 //=======================================================================
870 //=======================================================================
872 gp_Circ ChFiDS_Spine::Circle() const
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());
878 if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
879 Dc = gp_Dir(gp_Vec(Ac.Location(),myCurve.Value(myCurve.LastParameter())));
882 gp_Ax2 A(Ac.Location(),ZZ,Dc);
883 return gp_Circ(A,myCurve.Circle().Radius());
885 //=======================================================================
886 //function : SetErrorStatus
887 //purpose : met a jour le statut d'erreur
888 //=======================================================================
889 void ChFiDS_Spine::SetErrorStatus(const ChFiDS_ErrorStatus state)
893 //=======================================================================
894 //function : ErrorStatus
895 //purpose : renvoie le statut d'erreur concernant la spine
896 //=======================================================================
898 ChFiDS_ErrorStatus ChFiDS_Spine::ErrorStatus()const