1 // File: Bisector_BisecPC.cxx
2 // Created: Thu Mar 10 17:54:52 1994
3 // Author: Yves FRICAUD
6 #include <Bisector_BisecPC.ixx>
7 #include <Bisector.hxx>
8 #include <Geom2dAdaptor_Curve.hxx>
9 #include <Geom2d_Curve.hxx>
10 #include <Geom2d_Line.hxx>
11 #include <Geom2d_CartesianPoint.hxx>
12 #include <Geom2dInt_GInter.hxx>
13 #include <Geom2dGcc.hxx>
14 #include <GccEnt_Position.hxx>
15 #include <Geom2dGcc_Circ2d2TanRad.hxx>
16 #include <Geom2dGcc_QualifiedCurve.hxx>
17 #include <Geom2d_TrimmedCurve.hxx>
18 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
19 #include <Geom2dLProp_CLProps2d.hxx>
20 #include <gp_Pnt2d.hxx>
21 #include <gp_Vec2d.hxx>
22 #include <gp_Ax2d.hxx>
24 #include <Precision.hxx>
26 #include <IntRes2d_IntersectionPoint.hxx>
28 #include <Standard_DivideByZero.hxx>
29 #include <Standard_NotImplemented.hxx>
31 //=============================================================================
34 //=============================================================================
35 Bisector_BisecPC::Bisector_BisecPC()
39 //=============================================================================
42 //=============================================================================
43 Bisector_BisecPC::Bisector_BisecPC(const Handle(Geom2d_Curve)& Cu,
45 const Standard_Real Side,
46 const Standard_Real DistMax)
48 Perform (Cu,P,Side,DistMax);
51 //=============================================================================
54 //=============================================================================
55 Bisector_BisecPC::Bisector_BisecPC(const Handle(Geom2d_Curve)& Cu,
57 const Standard_Real Side,
58 const Standard_Real UMin,
59 const Standard_Real UMax)
62 curve = Handle (Geom2d_Curve)::DownCast(Cu->Copy());
65 startIntervals.Append(UMin);
66 endIntervals .Append(UMax);
68 extensionStart = Standard_False;
69 extensionEnd = Standard_False;
70 pointStartBis = Value(UMin);
71 pointEndBis = Value(UMax);
72 isConvex = Bisector::IsConvex(curve,sign);
75 //=============================================================================
78 //=============================================================================
79 void Bisector_BisecPC::Perform(const Handle(Geom2d_Curve)& Cu,
81 const Standard_Real Side,
82 const Standard_Real DistMax)
84 curve = Handle (Geom2d_Curve)::DownCast(Cu->Copy());
88 isConvex = Bisector::IsConvex(curve,sign);
89 //--------------------------------------------
90 // Calculate interval of definition.
91 //--------------------------------------------
95 //-------------------------
96 // Construction extensions.
97 //-------------------------
99 extensionStart = Standard_False;
100 extensionEnd = Standard_False;
101 pointStartBis = Value(startIntervals.First());
102 pointEndBis = Value(endIntervals .Last());
105 if (point.IsEqual(curve->Value(curve->FirstParameter()),
106 Precision::Confusion()) ) {
107 extensionStart = Standard_True;
108 Standard_Real UFirst = startIntervals.First() - P.Distance(pointStartBis);
109 startIntervals.InsertBefore(1,UFirst);
110 endIntervals .InsertBefore(1,startIntervals.Value(2));
113 else if (point.IsEqual(curve->Value(curve->LastParameter()),
114 Precision::Confusion()) ) {
115 extensionEnd = Standard_True;
116 Standard_Real ULast = endIntervals.Last() + P.Distance(pointEndBis);
117 startIntervals.Append(endIntervals.Last());
118 endIntervals .Append(ULast);
124 //=============================================================================
125 //function : IsExtendAtStart
127 //=============================================================================
128 Standard_Boolean Bisector_BisecPC::IsExtendAtStart() const
130 return extensionStart;
133 //=============================================================================
134 //function : IsExtendAtEnd
136 //=============================================================================
137 Standard_Boolean Bisector_BisecPC::IsExtendAtEnd() const
142 //=============================================================================
145 //=============================================================================
146 void Bisector_BisecPC::Reverse()
148 Standard_NotImplemented::Raise();
151 //=============================================================================
152 //function : ReversedParameter
154 //=============================================================================
155 Standard_Real Bisector_BisecPC::ReversedParameter(const Standard_Real U) const
157 return LastParameter() + FirstParameter() - U;
160 //=============================================================================
163 //=============================================================================
164 Handle(Geom2d_Geometry) Bisector_BisecPC::Copy() const
166 Handle(Geom2d_Curve) CopyC = Handle(Geom2d_Curve)::DownCast(curve->Copy());
167 Handle(Bisector_BisecPC) C = new Bisector_BisecPC();
169 C->Init (CopyC,point,sign,
170 startIntervals,endIntervals,bisInterval,currentInterval,
171 shiftParameter,distMax,isEmpty,isConvex,extensionStart,extensionEnd,
172 pointStartBis,pointEndBis);
176 //=============================================================================
177 //function : Transform
179 //=============================================================================
180 void Bisector_BisecPC::Transform(const gp_Trsf2d& T)
182 curve ->Transform(T);
183 point . Transform(T);
184 pointStartBis. Transform(T);
185 pointEndBis . Transform(T);
188 //=============================================================================
191 //=============================================================================
192 Standard_Boolean Bisector_BisecPC::IsCN(const Standard_Integer N) const
194 return curve->IsCN(N+1);
197 //=============================================================================
198 //function : FirstParameter
200 //=============================================================================
201 Standard_Real Bisector_BisecPC::FirstParameter() const
203 return startIntervals.First();
206 //=============================================================================
207 //function : LastParameter
209 //=============================================================================
210 Standard_Real Bisector_BisecPC::LastParameter() const
212 return endIntervals.Last();
215 //=============================================================================
216 //function : Continuity
218 //=============================================================================
219 GeomAbs_Shape Bisector_BisecPC::Continuity() const
221 GeomAbs_Shape Cont = curve->Continuity();
223 case GeomAbs_C1 : return GeomAbs_C0;
224 case GeomAbs_C2 : return GeomAbs_C1;
225 case GeomAbs_C3 : return GeomAbs_C2;
226 case GeomAbs_CN : return GeomAbs_CN;
234 //=============================================================================
235 //function : NbIntervals
237 //=============================================================================
238 Standard_Integer Bisector_BisecPC::NbIntervals() const
240 return startIntervals.Length();
243 //=============================================================================
244 //function : IntervalFirst
246 //=============================================================================
247 Standard_Real Bisector_BisecPC::IntervalFirst(const Standard_Integer I) const
249 return startIntervals.Value(I);
252 //=============================================================================
253 //function : IntervalLast
255 //=============================================================================
256 Standard_Real Bisector_BisecPC::IntervalLast(const Standard_Integer I) const
258 return endIntervals.Value(I);
261 //=============================================================================
262 //function : IntervalContinuity
264 //=============================================================================
265 GeomAbs_Shape Bisector_BisecPC::IntervalContinuity() const
267 GeomAbs_Shape Cont = curve->Continuity();
269 case GeomAbs_C1 : return GeomAbs_C0;
270 case GeomAbs_C2 : return GeomAbs_C1;
271 case GeomAbs_C3 : return GeomAbs_C2;
272 case GeomAbs_CN : return GeomAbs_CN;
280 //=============================================================================
281 //function : IsClosed
283 //=============================================================================
284 Standard_Boolean Bisector_BisecPC::IsClosed() const
286 if (curve->IsClosed()) {
287 //-----------------------------------------------------------------------
288 // The bisectrice is closed if the curve is closed and the bissectrice
289 // has only one domain of continuity equal to the one of the curve.
290 // -----------------------------------------------------------------------
291 if (startIntervals.First() == curve->FirstParameter() &&
292 endIntervals .First() == curve->LastParameter () )
293 return Standard_True;
295 return Standard_False;
298 //=============================================================================
299 //function : IsPeriodic
301 //=============================================================================
302 Standard_Boolean Bisector_BisecPC::IsPeriodic() const
304 return Standard_False;
307 //=============================================================================
308 //function : Extension
310 //=============================================================================
311 void Bisector_BisecPC::Extension(const Standard_Real U,
320 if ( U < startIntervals.Value(bisInterval)) {
321 dU = U - startIntervals.Value(bisInterval);
322 DirExt.SetCoord(pointStartBis.X() - point.X(),
323 pointStartBis.Y() - point.Y());
324 P.SetCoord(pointStartBis.X() + dU*DirExt.X(),
325 pointStartBis.Y() + dU*DirExt.Y());
327 else if ( U > endIntervals.Value(bisInterval)) {
328 dU = U - endIntervals.Value(bisInterval);
329 DirExt.SetCoord(point.X() - pointEndBis.X(),
330 point.Y() - pointEndBis.Y());
331 P.SetCoord(pointEndBis.X() + dU*DirExt.X(),
332 pointEndBis.Y() + dU*DirExt.Y());
334 V1.SetCoord(DirExt.X(),DirExt.Y());
335 V2.SetCoord(0. ,0. );
336 V3.SetCoord(0. ,0. );
340 //=============================================================================
342 // purpose : To each point of the curve is associated a point on the
343 // bissectrice. The equation of the bissectrice is:
345 // F(u) = P(u) - 1/2* -------------- * N(u)
348 // N(u) normal to the curve by u.
349 // ( | ) designation of the scalar product.
350 //=============================================================================
351 void Bisector_BisecPC::Values(const Standard_Real U,
352 const Standard_Integer N,
358 if ( U < startIntervals.Value(bisInterval)) {
359 Extension(U,P,V1,V2,V3);
362 else if ( U > endIntervals.Value(bisInterval)) {
363 Extension(U,P,V1,V2,V3);
366 Standard_Real UOnCurve = LinkBisCurve(U);
372 case 0 : {curve->D1(UOnCurve,PC,Tu) ;break;}
373 case 1 : {curve->D2(UOnCurve,PC,Tu,Tuu) ;break;}
374 case 2 : {curve->D3(UOnCurve,PC,Tu,Tuu,T3u);break;}
377 gp_Vec2d PPC(PC.X() - point.X(), PC.Y() - point.Y());
378 gp_Vec2d Nor( - Tu.Y(), Tu.X());
380 Standard_Real SquarePPC = PPC.SquareMagnitude();
381 Standard_Real NorPPC = Nor.Dot(PPC);
384 if (Abs(NorPPC) > gp::Resolution() && (NorPPC*sign) < 0.) {
385 A1 = 0.5*SquarePPC/NorPPC;
386 P.SetCoord(PC.X() - Nor.X()*A1, PC.Y() - Nor.Y()*A1);
390 if (N == 0) return; // End Calculation Point;
392 gp_Vec2d Nu ( - Tuu.Y() , Tuu.X()); // derivative of the normal by U.
393 Standard_Real NuPPC = Nu .Dot(PPC);
394 Standard_Real TuPPC = Tu .Dot(PPC);
395 Standard_Real NorPPCE2 = NorPPC*NorPPC;
396 Standard_Real A2 = TuPPC/NorPPC - 0.5*NuPPC*SquarePPC/NorPPCE2;
398 //--------------------------
399 V1 = Tu - A1*Nu - A2*Nor;
400 //--------------------------
401 if (N == 1) return; // End calculation D1.
403 gp_Vec2d Nuu ( - T3u.Y() , T3u.X());
405 Standard_Real NorPPCE4 = NorPPCE2*NorPPCE2;
406 Standard_Real NuuPPC = Nuu.Dot(PPC);
407 Standard_Real TuuPPC = Tuu.Dot(PPC);
409 Standard_Real A21 = TuuPPC/NorPPC - TuPPC*NuPPC/NorPPCE2;
410 Standard_Real A22 = (0.5*NuuPPC*SquarePPC + NuPPC*TuPPC)/NorPPCE2 -
411 NuPPC*SquarePPC*NorPPC*NuPPC/NorPPCE4;
412 Standard_Real A2u = A21 - A22;
413 //----------------------------------------
414 V2 = Tuu - 2*A2*Nu - A1*Nuu - A2u*Nor;
415 //----------------------------------------
418 //=============================================================================
419 //function : Curvature
421 //=============================================================================
424 static Standard_Real Curvature (const Handle(Geom2d_Curve)& C,
432 Standard_Real Norm2 = D1.SquareMagnitude();;
437 K1 = (D1^D2)/(Norm2*sqrt(Norm2));
443 //=============================================================================
444 //function : Distance
445 //purpose : distance at the square of the point of parameter U to the curve and at point:
448 // d = 1/4* ------------------- ||Nor||
451 // where Nor is the normal to the curve by U.
452 //=============================================================================
453 Standard_Real Bisector_BisecPC::Distance (const Standard_Real U) const
458 Standard_Real UOnCurve = LinkBisCurve(U);
460 curve->D1(UOnCurve,PC,Tan);
461 gp_Vec2d PPC(PC.X() - point.X(), PC.Y() - point.Y());
462 gp_Vec2d Nor( - Tan.Y(), Tan.X());
464 Standard_Real NorNor = Nor.SquareMagnitude();
465 Standard_Real SquareMagPPC = PPC.SquareMagnitude();
466 Standard_Real Prosca = Nor.Dot(PPC);
468 if (point.IsEqual(PC,Precision::Confusion())) {
469 if (isConvex) { return 0.;}
470 //----------------------------------------------------
471 // the point is on a concave curve.
472 // The required point is not the common point.
473 // This can avoid the discontinuity of the bisectrice.
474 //----------------------------------------------------
475 else { return Precision::Infinite();}
478 if (Abs(Prosca) < Precision::Confusion() || (Prosca*sign) > 0. ) {
479 return Precision::Infinite();
482 Standard_Real A = 0.5*SquareMagPPC/Prosca;
483 Standard_Real Dist = A*A*NorNor;
484 //----------------------------------------
485 // Test Curvature if the curve is concave.
486 //----------------------------------------
488 // Standard_Real K = Curvature(curve,UOnCurve,Precision::Confusion());
490 // if (Dist > 1/(K*K)) { Dist = Precision::Infinite();}
499 //=============================================================================
502 //=============================================================================
503 void Bisector_BisecPC::D0(const Standard_Real U,
508 Values(U,0,P,V1,V2,V3);
512 //=============================================================================
515 //=============================================================================
516 void Bisector_BisecPC::D1(const Standard_Real U,
523 Values(U,1,P,V,V2,V3);
527 //=============================================================================
530 //=============================================================================
531 void Bisector_BisecPC::D2(const Standard_Real U,
540 Values(U,2,P,V1,V2,V3);
543 //=============================================================================
546 //=============================================================================
547 void Bisector_BisecPC::D3(const Standard_Real U,
557 Values(U,3,P,V1,V2,V3);
561 //=============================================================================
564 //=============================================================================
565 gp_Vec2d Bisector_BisecPC::DN (const Standard_Real U,
566 const Standard_Integer N) const
572 Values (U,N,P,V1,V2,V3);
578 Standard_NotImplemented::Raise();
584 //=============================================================================
585 //function : SearchBound
587 //=============================================================================
588 Standard_Real Bisector_BisecPC::SearchBound (const Standard_Real U1,
589 const Standard_Real U2) const
591 Standard_Real Dist1,Dist2,DistMid,U11,U22;
593 Standard_Real UMid = 0.;
597 Standard_Real Tol = Precision::PConfusion();
598 Standard_Real DistMax2 = distMax*distMax;
600 Dist1 = Distance(U11);
601 Dist2 = Distance(U22);
603 while ((U22 - U11) > Tol) {
604 UMid = 0.5*( U22 + U11);
605 DistMid = Distance(UMid);
606 if ((Dist1 > DistMax2) == (DistMid > DistMax2)) {
618 //=============================================================================
619 //function : CuspFilter
621 //=============================================================================
622 void Bisector_BisecPC::CuspFilter()
624 Standard_NotImplemented::Raise();
627 //=============================================================================
628 //function : ComputeIntervals
630 //=============================================================================
631 void Bisector_BisecPC::ComputeIntervals ()
634 Standard_Real U1 =0.,U2 =0.,UProj =0.;
636 Standard_Real U1,U2,UProj;
638 Standard_Real UStart,UEnd;
639 Standard_Real Dist1,Dist2,DistProj;
640 isEmpty = Standard_False;
642 Standard_Boolean YaProj = Standard_False;
643 Standard_Real DistMax2 = distMax*distMax;
645 U1 = curve->FirstParameter();
646 U2 = curve->LastParameter();
647 Dist1 = Distance(U1);
648 Dist2 = Distance(U2);
649 DistProj = Precision::Infinite();
651 Geom2dAPI_ProjectPointOnCurve Proj(point,curve,U1,U2);
652 if (Proj.NbPoints() > 0) {
653 UProj = Proj.LowerDistanceParameter();
654 DistProj = Distance(UProj);
655 YaProj = Standard_True;
658 if (Dist1 < DistMax2 && Dist2 < DistMax2) {
659 if (DistProj > DistMax2 && YaProj) {
660 isEmpty = Standard_True;
663 startIntervals.Append(U1);
664 endIntervals .Append(U2);
668 else if (Dist1 > DistMax2 && Dist2 > DistMax2) {
669 if (DistProj < DistMax2) {
670 UStart = SearchBound(U1,UProj);
671 UEnd = SearchBound(UProj,U2);
674 isEmpty = Standard_True;
678 else if (Dist1 < DistMax2) {
680 UEnd = SearchBound(U1,U2);
682 else if (Dist2 < DistMax2) {
684 UStart = SearchBound(U1,U2);
686 startIntervals.Append(UStart);
687 endIntervals .Append(UEnd);
689 //------------------------------------------------------------------------
690 // Eventual offset of the parameter on the curve correspondingly to the one
691 // on the curve. The offset can be done if the curve is periodical and the
692 // point of initial parameter is less then the interval of continuity.
693 //------------------------------------------------------------------------
694 if (curve->IsPeriodic()) {
695 if (startIntervals.Length() > 1) { // Plusieurs intervals.
696 if (endIntervals .Last() == curve->LastParameter() &&
697 startIntervals.First() == curve->FirstParameter() ) {
698 //---------------------------------------------------------------
699 // the bissectrice is defined at the origin.
700 // => Fusion of the first and the last interval.
701 // => 0 on the bisectrice becomes the start of the first interval
702 // => offset of parameter on all limits of intervals.
703 //---------------------------------------------------------------
704 startIntervals.Remove(1);
705 endIntervals .Remove(endIntervals.Length());
707 shiftParameter = Period() - startIntervals.First() ;
708 for (Standard_Integer k = 1; k <= startIntervals.Length(); k++) {
709 endIntervals .ChangeValue(k) += shiftParameter;
710 startIntervals.ChangeValue(k) += shiftParameter;
712 startIntervals.ChangeValue(1) = 0.;
718 //=============================================================================
719 //function : LinkBisCurve
721 //=============================================================================
722 Standard_Real Bisector_BisecPC::LinkBisCurve(const Standard_Real U) const
724 return (U - shiftParameter);
727 //=============================================================================
728 //function : LinkCurveBis
730 //=============================================================================
731 Standard_Real Bisector_BisecPC::LinkCurveBis(const Standard_Real U) const
733 return (U + shiftParameter);
736 //=============================================================================
739 //=============================================================================
740 Standard_Boolean Bisector_BisecPC::IsEmpty() const
745 //==========================================================================
746 //function : Parameter
748 //==========================================================================
749 Standard_Real Bisector_BisecPC::Parameter(const gp_Pnt2d& P) const
751 Standard_Real Tol = Precision::Confusion();
753 if (P.IsEqual(pointStartBis,Tol)) {return startIntervals.Value(bisInterval);}
754 if (P.IsEqual(pointEndBis ,Tol)) {return endIntervals .Value(bisInterval);}
756 if (extensionStart) {
757 gp_Ax2d Axe(pointStartBis,gp_Dir2d(pointStartBis.X() - P.X(),
758 pointStartBis.Y() - P.Y()));
759 Standard_Real U = ElCLib::LineParameter(Axe,P);
760 gp_Pnt2d Proj = ElCLib::LineValue(U,Axe);
761 if (Proj.IsEqual(P,Tol) && U < 0.) {
762 return U + startIntervals.Value(bisInterval);
766 gp_Ax2d Axe(pointEndBis,gp_Dir2d(P.X() - pointEndBis.X(),
767 P.Y() - pointEndBis.Y()));
768 Standard_Real U = ElCLib::LineParameter(Axe,P);
769 gp_Pnt2d Proj = ElCLib::LineValue(U,Axe);
770 if (Proj.IsEqual(P,Tol) && U > 0.) {
771 return U + endIntervals.Value(bisInterval);
775 Standard_Real UOnCurve = 0.;
777 Standard_Real UOnCurve;
779 Geom2dAPI_ProjectPointOnCurve Proj(P,curve,
780 curve->FirstParameter(),curve->LastParameter());
781 if (Proj.NbPoints() > 0) {
782 UOnCurve = Proj.LowerDistanceParameter();
784 return LinkCurveBis(UOnCurve);
788 //=============================================================================
791 //=============================================================================
792 static void Indent(const Standard_Integer Offset) {
794 for (Standard_Integer i = 0; i < Offset; i++) {cout << " ";}
798 //=============================================================================
801 //=============================================================================
802 void Bisector_BisecPC::Init (const Handle_Geom2d_Curve& Curve,
803 const gp_Pnt2d& Point,
804 const Standard_Real Sign,
805 const TColStd_SequenceOfReal& StartIntervals,
806 const TColStd_SequenceOfReal& EndIntervals,
807 const Standard_Integer BisInterval,
808 const Standard_Integer CurrentInterval,
809 const Standard_Real ShiftParameter,
810 const Standard_Real DistMax,
811 const Standard_Boolean IsEmpty,
812 const Standard_Boolean IsConvex,
813 const Standard_Boolean ExtensionStart,
814 const Standard_Boolean ExtensionEnd,
815 const gp_Pnt2d& PointStartBis,
816 const gp_Pnt2d& PointEndBis)
821 startIntervals = StartIntervals;
822 endIntervals = EndIntervals;
823 bisInterval = BisInterval;
824 currentInterval = CurrentInterval;
825 shiftParameter = ShiftParameter;
829 extensionStart = ExtensionStart;
830 extensionEnd = ExtensionEnd;
831 pointStartBis = PointStartBis;
832 pointEndBis = PointEndBis;
835 //=============================================================================
838 //=============================================================================
839 //void Bisector_BisecPC::Dump(const Standard_Integer Deep,
840 void Bisector_BisecPC::Dump(const Standard_Integer ,
841 const Standard_Integer Offset) const
844 cout <<"Bisector_BisecPC :"<<endl;
846 cout <<"Point :"<<endl;
847 cout <<" X = "<<point.X()<<endl;
848 cout <<" Y = "<<point.Y()<<endl;
849 cout <<"Sign :"<<sign<<endl;
850 cout <<"Number Of Intervals :"<<startIntervals.Length()<<endl;
851 for (Standard_Integer i = 1; i <= startIntervals.Length(); i++) {
852 cout <<"Interval number :"<<i<<"Start :"<<startIntervals.Value(i)
853 <<" end :"<< endIntervals.Value(i)<<endl ;
855 cout <<"Index Current Interval :"<<currentInterval<<endl;