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
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Curve.hxx>
21 #include <ChFiDS_ErrorStatus.hxx>
22 #include <ChFiDS_HElSpine.hxx>
23 #include <ChFiDS_ListIteratorOfListOfHElSpine.hxx>
24 #include <ChFiDS_Spine.hxx>
26 #include <GCPnts_AbscissaPoint.hxx>
27 #include <gp_Circ.hxx>
31 #include <Precision.hxx>
32 #include <Standard_Type.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Vertex.hxx>
37 IMPLEMENT_STANDARD_RTTIEXT(ChFiDS_Spine,Standard_Transient)
39 //=======================================================================
40 //function : ChFiDS_Spine
42 //=======================================================================
43 ChFiDS_Spine::ChFiDS_Spine()
44 : splitdone(Standard_False),
45 myMode(ChFiDS_ClassicChamfer),
46 tolesp(Precision::Confusion()),
47 firstprolon(Standard_False),
48 lastprolon(Standard_False),
49 firstistgt(Standard_False),
50 lastistgt(Standard_False),
51 hasfirsttgt(Standard_False),
52 haslasttgt(Standard_False),
53 hasref(Standard_False)
57 //=======================================================================
58 //function : ChFiDS_Spine
60 //=======================================================================
61 ChFiDS_Spine::ChFiDS_Spine(const Standard_Real Tol)
62 : splitdone(Standard_False),
63 myMode(ChFiDS_ClassicChamfer),
65 firstprolon(Standard_False),
66 lastprolon(Standard_False),
67 firstistgt(Standard_False),
68 lastistgt(Standard_False),
69 hasfirsttgt(Standard_False),
70 haslasttgt(Standard_False),
71 hasref(Standard_False)
75 //=======================================================================
76 //function : AppendElSpine
78 //=======================================================================
80 void ChFiDS_Spine::AppendElSpine(const Handle(ChFiDS_HElSpine)& Els)
85 //=======================================================================
86 //function : AppendOffsetElSpine
88 //=======================================================================
90 void ChFiDS_Spine::AppendOffsetElSpine(const Handle(ChFiDS_HElSpine)& Els)
92 offset_elspines.Append(Els);
95 //=======================================================================
98 //=======================================================================
100 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const TopoDS_Edge& E) const
102 return ElSpine(Index(E));
105 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Integer IE) const
107 Standard_Real wmil = 0.5 * (FirstParameter(IE) + LastParameter(IE));
108 if(IsPeriodic()) wmil = ElCLib::InPeriod(wmil,FirstParameter(),LastParameter());
109 return ElSpine(wmil);
112 Handle(ChFiDS_HElSpine) ChFiDS_Spine::ElSpine(const Standard_Real W) const
114 if (elspines.Extent() == 1)
115 return elspines.First();
118 ChFiDS_ListIteratorOfListOfHElSpine It(elspines);
119 for (; It.More(); It.Next()) {
120 Handle(ChFiDS_HElSpine) cur = It.Value();
121 Standard_Real uf = cur->FirstParameter();
122 Standard_Real ul = cur->LastParameter();
123 if(uf <= W && W <= ul) return cur;
125 return Handle(ChFiDS_HElSpine)();
129 //=======================================================================
130 //function : ChangeElSpines
132 //=======================================================================
134 ChFiDS_ListOfHElSpine& ChFiDS_Spine::ChangeElSpines()
139 //=======================================================================
140 //function : ChangeOffsetElSpines
142 //=======================================================================
144 ChFiDS_ListOfHElSpine& ChFiDS_Spine::ChangeOffsetElSpines()
146 return offset_elspines;
149 //=======================================================================
150 //function : SplitDone
152 //=======================================================================
154 void ChFiDS_Spine::SplitDone(const Standard_Boolean B)
159 //=======================================================================
160 //function : SplitDone
162 //=======================================================================
164 Standard_Boolean ChFiDS_Spine::SplitDone() const
169 //=======================================================================
172 //=======================================================================
174 void ChFiDS_Spine::Reset(const Standard_Boolean AllData)
176 splitdone = Standard_False;
177 //if(AllData && !isconstant.IsNull()) isconstant->ChangeArray1().Init(0);
181 lastparam = abscissa->Value(abscissa->Upper());
182 firstprolon = lastprolon = Standard_False;
186 //=======================================================================
187 //function : FirstParameter
189 //=======================================================================
191 Standard_Real ChFiDS_Spine::FirstParameter() const
193 if(firstprolon) return firstparam;
198 //=======================================================================
199 //function : LastParameter
201 //=======================================================================
203 Standard_Real ChFiDS_Spine::LastParameter() const
205 if(lastprolon) return lastparam;
206 return abscissa->Value(abscissa->Upper());
209 //=======================================================================
210 //function : SetFirstParameter
212 //=======================================================================
214 void ChFiDS_Spine::SetFirstParameter(const Standard_Real Par)
217 if(Par >= Precision::Confusion())
218 std::cout<<"Interior extension at the start of guideline"<<std::endl;
220 std::cout<<"WARNING!!! Extension on periodic guideline."<<std::endl;
222 firstprolon = Standard_True;
227 //=======================================================================
228 //function : SetLastParameter
230 //=======================================================================
232 void ChFiDS_Spine::SetLastParameter(const Standard_Real Par)
235 Standard_Real lll = abscissa->Value(abscissa->Upper());
236 if((Par - lll) <= -Precision::Confusion())
237 std::cout<<"Interior extension at the end of guideline"<<std::endl;
239 std::cout<<"WARNING!!! Extension on periodic guideline."<<std::endl;
241 lastprolon = Standard_True;
245 //=======================================================================
246 //function : FirstParameter
248 //=======================================================================
250 Standard_Real ChFiDS_Spine::FirstParameter
251 (const Standard_Integer IndexSpine) const
253 if (IndexSpine==1) return 0.;
254 return abscissa->Value(IndexSpine-1);
257 //=======================================================================
258 //function : LastParameter
260 //=======================================================================
262 Standard_Real ChFiDS_Spine::LastParameter
263 (const Standard_Integer IndexSpine) const
265 return abscissa->Value(IndexSpine);
268 //=======================================================================
271 //=======================================================================
273 Standard_Real ChFiDS_Spine::Length
274 (const Standard_Integer IndexSpine) const
276 if (IndexSpine==1) return abscissa->Value(IndexSpine);
277 return abscissa->Value(IndexSpine) - abscissa->Value(IndexSpine-1);
280 //=======================================================================
281 //function : IsPeriodic
283 //=======================================================================
285 Standard_Boolean ChFiDS_Spine::IsPeriodic() const
287 return (firstState == ChFiDS_Closed);
291 //=======================================================================
292 //function : IsClosed
294 //=======================================================================
296 Standard_Boolean ChFiDS_Spine::IsClosed() const
298 return (FirstVertex().IsSame(LastVertex()));
302 //=======================================================================
303 //function : FirstVertex
305 //=======================================================================
307 TopoDS_Vertex ChFiDS_Spine::FirstVertex() const
309 TopoDS_Edge E = TopoDS::Edge(spine.First());
310 if(E.Orientation() == TopAbs_FORWARD) return TopExp::FirstVertex(E);
311 return TopExp::LastVertex(E);
315 //=======================================================================
316 //function : LastVertex
318 //=======================================================================
320 TopoDS_Vertex ChFiDS_Spine::LastVertex() const
322 TopoDS_Edge E = TopoDS::Edge(spine.Last());
323 if(E.Orientation() == TopAbs_FORWARD) return TopExp::LastVertex(E);
324 return TopExp::FirstVertex(E);
328 //=======================================================================
331 //=======================================================================
333 Standard_Real ChFiDS_Spine::Absc(const TopoDS_Vertex& V) const
337 for(Standard_Integer i = 1; i<=spine.Length(); i++){
338 E = TopoDS::Edge(spine.Value(i));
339 TopExp::Vertices(E,d,f);
340 if(d.IsSame(V) && E.Orientation() == TopAbs_FORWARD){
341 return FirstParameter(i);
343 if(d.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
344 return LastParameter(i);
346 if(f.IsSame(V) && E.Orientation() == TopAbs_FORWARD){
347 return LastParameter(i);
349 if(f.IsSame(V) && E.Orientation() == TopAbs_REVERSED){
350 return FirstParameter(i);
357 //=======================================================================
360 //=======================================================================
362 Standard_Real ChFiDS_Spine::Period() const
364 if(!IsPeriodic()) throw Standard_Failure("Non-periodic Spine");
365 return abscissa->Value(abscissa->Upper());
369 //=======================================================================
370 //function : Resolution
372 //=======================================================================
374 Standard_Real ChFiDS_Spine::Resolution(const Standard_Real R3d) const
380 //=======================================================================
381 //function : SetFirstTgt
383 //=======================================================================
385 void ChFiDS_Spine::SetFirstTgt(const Standard_Real W)
387 if(IsPeriodic()) throw Standard_Failure("No extension by tangent on periodic contours");
389 if(W >= Precision::Confusion())
390 std::cout<<"Interior extension at start of the guideline"<<std::endl;
392 //The flag is suspended if is already positioned to avoid
394 hasfirsttgt = Standard_False;
395 D1(W,firstori,firsttgt);
397 hasfirsttgt = Standard_True;
402 //=======================================================================
403 //function : SetLastTgt
405 //=======================================================================
407 void ChFiDS_Spine::SetLastTgt(const Standard_Real W)
409 if(IsPeriodic()) throw Standard_Failure("No extension by tangent periodic contours");
412 Standard_Real L = W - abscissa->Value(abscissa->Upper());
413 if(L <= -Precision::Confusion())
414 std::cout<<"Interior extension at the end of guideline"<<std::endl;
416 //The flag is suspended if is already positioned to avoid
418 haslasttgt = Standard_False;
419 D1(W,lastori,lasttgt);
421 haslasttgt = Standard_True;
426 //=======================================================================
427 //function : HasFirstTgt
429 //=======================================================================
431 Standard_Boolean ChFiDS_Spine::HasFirstTgt()const
436 //=======================================================================
437 //function : HasLastTgt
439 //=======================================================================
441 Standard_Boolean ChFiDS_Spine::HasLastTgt()const
446 //=======================================================================
447 //function : SetReference
449 //=======================================================================
451 void ChFiDS_Spine::SetReference(const Standard_Real W)
453 hasref = Standard_True;
454 Standard_Real lll = abscissa->Value(abscissa->Upper());
455 if(IsPeriodic()) valref = ElCLib::InPeriod(W,0.,lll);
460 //=======================================================================
461 //function : SetReference
463 //=======================================================================
465 void ChFiDS_Spine::SetReference(const Standard_Integer I)
467 hasref = Standard_True;
468 if(I == 1) valref = abscissa->Value(1)*0.5;
469 else valref = (abscissa->Value(I) + abscissa->Value(I-1))*0.5;
473 //=======================================================================
476 //=======================================================================
478 Standard_Integer ChFiDS_Spine::Index(const Standard_Real W,
479 const Standard_Boolean Forward) const
481 Standard_Integer ind, len = abscissa->Length();
482 Standard_Real par = W,last = abscissa->Value(abscissa->Upper());
483 Standard_Real f = 0., l = 0., t = Max(tolesp,Precision::Confusion());
485 if(IsPeriodic() && Abs(par) >= t && Abs(par-last) >= t)
486 par = ElCLib::InPeriod(par,0.,last);
488 for (ind=1; ind <= len; ind++) {
490 l = abscissa->Value(ind);
491 if (par<l || ind==len) break;
493 if (Forward && ind<len && Abs(par-l) < t) ind++;
494 else if (!Forward && ind > 1 && Abs(par-f) < t) ind--;
495 else if (Forward && IsPeriodic() && ind == len && Abs(par-l) < t) ind = 1;
496 else if (!Forward && IsPeriodic() && ind == 1 && Abs(par-f) < t) ind = len;
500 //=======================================================================
503 //=======================================================================
505 Standard_Integer ChFiDS_Spine::Index (const TopoDS_Edge& E) const
507 for(Standard_Integer IE = 1; IE <= spine.Length(); IE++){
508 if(E.IsSame(spine.Value(IE))) return IE;
513 //=======================================================================
514 //function : UnsetReference
516 //=======================================================================
518 void ChFiDS_Spine::UnsetReference()
520 hasref = Standard_False;
523 //=======================================================================
526 //=======================================================================
528 void ChFiDS_Spine::Load()
530 if(!abscissa.IsNull()){
532 std::cout<<"new load of CE"<<std::endl;
535 Standard_Integer len = spine.Length();
536 abscissa = new TColStd_HArray1OfReal(1,len);
537 Standard_Real a1 = 0.;
538 for (Standard_Integer i = 1; i <= len; i++){
539 myCurve.Initialize(TopoDS::Edge(spine.Value(i)));
540 a1 += GCPnts_AbscissaPoint::Length(myCurve);
541 abscissa->SetValue(i,a1);
544 myCurve.Initialize(TopoDS::Edge(spine.Value(1)));
548 //=======================================================================
551 //=======================================================================
553 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U)
555 return Absc(U,indexofcurve);
558 //=======================================================================
561 //=======================================================================
563 Standard_Real ChFiDS_Spine::Absc(const Standard_Real U,
564 const Standard_Integer I)
568 if(indexofcurve != I){
569 void* p = (void*)this;
570 ((ChFiDS_Spine*)p)->indexofcurve = I;
571 ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(I)));
573 Standard_Real L = FirstParameter(I);
574 if (spine.Value(I).Orientation() == TopAbs_REVERSED) {
575 L += GCPnts_AbscissaPoint::Length(myCurve,U,myCurve.LastParameter());
578 L += GCPnts_AbscissaPoint::Length(myCurve,myCurve.FirstParameter(),U);
583 //=======================================================================
584 //function : Parameter
586 //=======================================================================
588 void ChFiDS_Spine::Parameter(const Standard_Real AbsC,
590 const Standard_Boolean Oriented)
592 Standard_Integer Index;
593 for (Index=1;Index<abscissa->Length();Index++) {
594 if (AbsC<abscissa->Value(Index)) break;
596 Parameter(Index,AbsC,U,Oriented);
600 //=======================================================================
601 //function : Parameter
603 //=======================================================================
605 void ChFiDS_Spine::Parameter(const Standard_Integer Index,
606 const Standard_Real AbsC,
608 const Standard_Boolean Oriented)
611 if (Index != indexofcurve) {
612 void* p = (void*)this;
613 ((ChFiDS_Spine*)p)->indexofcurve = Index;
614 ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
617 TopAbs_Orientation Or = spine.Value(Index).Orientation();
618 if (Or == TopAbs_REVERSED) {
619 L = abscissa->Value(indexofcurve)-AbsC;
621 else if (indexofcurve==1) {
625 L = AbsC - abscissa->Value(indexofcurve-1);
627 Standard_Real t = L/Length(Index);
628 Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
629 // GCPnts_AbscissaPoint GCP;
630 // GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
631 GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
633 if (Or == TopAbs_REVERSED && Oriented) {
634 U = (myCurve.LastParameter()+myCurve.FirstParameter()) - U;
639 //=======================================================================
642 //=======================================================================
644 void ChFiDS_Spine::Prepare(Standard_Real& L,
645 Standard_Integer& Ind) const
647 Standard_Real tol = Max(tolesp,Precision::Confusion());
648 Standard_Real last = abscissa->Value(abscissa->Upper());
649 Standard_Integer len = abscissa->Length();
650 if(IsPeriodic() && Abs(L) >= tol && Abs(L-last) >= tol)
651 L = ElCLib::InPeriod(L,0.,last);
653 if(hasfirsttgt && (L <= firsttgtpar)){
654 if(hasref && valref >= L && Abs(L-firsttgtpar) <= tol){
657 else{Ind = -1; L -= firsttgtpar;}
659 else if(L <= 0.){Ind = 1;}
660 else if(haslasttgt && (L >= lasttgtpar)){
661 if(hasref && valref <= L && Abs(L-lasttgtpar) <= tol){
664 else{Ind = len + 1; L -= lasttgtpar;}
666 else if(L >= last){Ind = len;}
668 for (Ind=1;Ind < len;Ind++) {
669 if (L<abscissa->Value(Ind)) break;
672 if (L >= valref && Ind != 1){
673 if(Abs(L-abscissa->Value(Ind-1)) <= Precision::Confusion()) Ind--;
675 else if (L <= valref && Ind != len){
676 if(Abs(L-abscissa->Value(Ind)) <= Precision::Confusion()) Ind++;
680 if(Ind >= 1 && Ind <= len){
681 if (spine.Value(Ind).Orientation() == TopAbs_REVERSED){
682 L = abscissa->Value(Ind) - L;
685 L -= abscissa->Value(Ind - 1);
690 //=======================================================================
693 //=======================================================================
695 gp_Pnt ChFiDS_Spine::Value(const Standard_Real AbsC)
698 Standard_Integer Index;
699 Standard_Real L = AbsC;
704 gp_Pnt Pp = firstori;
705 gp_Vec Vp = firsttgt;
710 else if (Index == (abscissa->Length() + 1)) {
717 if (Index != indexofcurve) {
718 void* p = (void*)this;
719 ((ChFiDS_Spine*)p)->indexofcurve = Index;
720 ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
722 Standard_Real t = L/Length(Index);
723 Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
724 // GCPnts_AbscissaPoint GCP;
725 // GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
726 GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
727 return myCurve.Value(GCP.Parameter());
730 //=======================================================================
733 //=======================================================================
735 void ChFiDS_Spine::D0(const Standard_Real AbsC, gp_Pnt& P)
740 //=======================================================================
743 //=======================================================================
745 void ChFiDS_Spine::D1(const Standard_Real AbsC,
749 Standard_Integer Index;
750 Standard_Real L = AbsC;
757 gp_Vec Vp = firsttgt;
761 else if (Index == (abscissa->Length() + 1)) {
769 if (Index != indexofcurve) {
770 void* p = (void*)this;
771 ((ChFiDS_Spine*)p)->indexofcurve = Index;
772 ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
774 Standard_Real t = L/Length(Index);
775 Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
776 // GCPnts_AbscissaPoint GCP;
777 // GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
778 GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
779 myCurve.D1(GCP.Parameter(),P,V1);
780 Standard_Real D1 = 1./V1.Magnitude();
781 if (spine.Value(Index).Orientation() == TopAbs_REVERSED) D1 = -D1;
787 //=======================================================================
790 //=======================================================================
792 void ChFiDS_Spine::D2(const Standard_Real AbsC,
798 Standard_Integer Index;
799 Standard_Real L = AbsC;
806 V2.SetCoord(0.,0.,0.);
807 gp_Vec Vp = firsttgt;
811 else if (Index == (abscissa->Length() + 1)) {
814 V2.SetCoord(0.,0.,0.);
820 if (Index != indexofcurve) {
821 void* p = (void*)this;
822 ((ChFiDS_Spine*)p)->indexofcurve = Index;
823 ((ChFiDS_Spine*)p)->myCurve.Initialize(TopoDS::Edge(spine.Value(Index)));
825 Standard_Real t = L/Length(Index);
826 Standard_Real uapp = (1. - t) * myCurve.FirstParameter() + t * myCurve.LastParameter();
827 // GCPnts_AbscissaPoint GCP;
828 // GCP.Perform(myCurve,L,myCurve.FirstParameter(),uapp,BRep_Tool::Tolerance(myCurve.Edge()));
829 GCPnts_AbscissaPoint GCP(myCurve,L,myCurve.FirstParameter(),uapp);
830 myCurve.D2(GCP.Parameter(),P,V1,V2);
831 Standard_Real N1 = V1.SquareMagnitude();
832 Standard_Real D2 = -(V1.Dot(V2))*(1./N1)*(1./N1);
835 gp_Vec Va = V1.Multiplied(D2);
837 Standard_Real D1 = 1./N1;
838 if (spine.Value(Index).Orientation() == TopAbs_REVERSED) D1 = -D1;
843 //=======================================================================
844 //function : SetCurrent
846 //=======================================================================
848 void ChFiDS_Spine::SetCurrent(const Standard_Integer Index)
850 if (Index != indexofcurve) {
851 indexofcurve = Index;
852 myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
856 //=======================================================================
857 //function : CurrentElementarySpine
859 //=======================================================================
861 const BRepAdaptor_Curve& ChFiDS_Spine::CurrentElementarySpine
862 (const Standard_Integer Index)
864 if (Index != indexofcurve) {
865 indexofcurve = Index;
866 myCurve.Initialize(TopoDS::Edge(spine.Value(indexofcurve)));
871 //=======================================================================
874 //=======================================================================
876 GeomAbs_CurveType ChFiDS_Spine::GetType() const
878 return myCurve.GetType();
881 //=======================================================================
884 //=======================================================================
886 gp_Lin ChFiDS_Spine::Line() const
888 gp_Lin LL(myCurve.Line());
889 if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
891 LL.SetLocation(myCurve.Value(myCurve.LastParameter()));
894 LL.SetLocation(myCurve.Value(myCurve.FirstParameter()));
900 //=======================================================================
903 //=======================================================================
905 gp_Circ ChFiDS_Spine::Circle() const
907 gp_Ax2 Ac = myCurve.Circle().Position();
908 gp_Dir Dc(gp_Vec(Ac.Location(),myCurve.Value(myCurve.FirstParameter())));
909 gp_Dir ZZ(Ac.Direction());
911 if (spine.Value(indexofcurve).Orientation() == TopAbs_REVERSED) {
912 Dc = gp_Dir(gp_Vec(Ac.Location(),myCurve.Value(myCurve.LastParameter())));
915 gp_Ax2 A(Ac.Location(),ZZ,Dc);
916 return gp_Circ(A,myCurve.Circle().Radius());
918 //=======================================================================
919 //function : SetErrorStatus
920 //purpose : met a jour le statut d'erreur
921 //=======================================================================
922 void ChFiDS_Spine::SetErrorStatus(const ChFiDS_ErrorStatus state)
926 //=======================================================================
927 //function : ErrorStatus
928 //purpose : renvoie le statut d'erreur concernant la spine
929 //=======================================================================
931 ChFiDS_ErrorStatus ChFiDS_Spine::ErrorStatus()const