1 // Created on: 1994-03-10
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1994-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 #include <Bisector_BisecPC.ixx>
18 #include <Bisector.hxx>
19 #include <Geom2dAdaptor_Curve.hxx>
20 #include <Geom2d_Curve.hxx>
21 #include <Geom2d_Line.hxx>
22 #include <Geom2d_CartesianPoint.hxx>
23 #include <Geom2dInt_GInter.hxx>
24 #include <Geom2dGcc.hxx>
25 #include <GccEnt_Position.hxx>
26 #include <Geom2dGcc_Circ2d2TanRad.hxx>
27 #include <Geom2dGcc_QualifiedCurve.hxx>
28 #include <Geom2d_TrimmedCurve.hxx>
29 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
30 #include <Geom2dLProp_CLProps2d.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <gp_Vec2d.hxx>
33 #include <gp_Ax2d.hxx>
35 #include <Precision.hxx>
37 #include <IntRes2d_IntersectionPoint.hxx>
39 #include <Standard_DivideByZero.hxx>
40 #include <Standard_NotImplemented.hxx>
42 //=============================================================================
45 //=============================================================================
46 Bisector_BisecPC::Bisector_BisecPC()
50 //=============================================================================
53 //=============================================================================
54 Bisector_BisecPC::Bisector_BisecPC(const Handle(Geom2d_Curve)& Cu,
56 const Standard_Real Side,
57 const Standard_Real DistMax)
59 Perform (Cu,P,Side,DistMax);
62 //=============================================================================
65 //=============================================================================
66 Bisector_BisecPC::Bisector_BisecPC(const Handle(Geom2d_Curve)& Cu,
68 const Standard_Real Side,
69 const Standard_Real UMin,
70 const Standard_Real UMax)
73 curve = Handle (Geom2d_Curve)::DownCast(Cu->Copy());
76 startIntervals.Append(UMin);
77 endIntervals .Append(UMax);
79 extensionStart = Standard_False;
80 extensionEnd = Standard_False;
81 pointStartBis = Value(UMin);
82 pointEndBis = Value(UMax);
83 isConvex = Bisector::IsConvex(curve,sign);
86 //=============================================================================
89 //=============================================================================
90 void Bisector_BisecPC::Perform(const Handle(Geom2d_Curve)& Cu,
92 const Standard_Real Side,
93 const Standard_Real DistMax)
95 curve = Handle (Geom2d_Curve)::DownCast(Cu->Copy());
99 isConvex = Bisector::IsConvex(curve,sign);
100 //--------------------------------------------
101 // Calculate interval of definition.
102 //--------------------------------------------
106 //-------------------------
107 // Construction extensions.
108 //-------------------------
110 extensionStart = Standard_False;
111 extensionEnd = Standard_False;
112 pointStartBis = Value(startIntervals.First());
113 pointEndBis = Value(endIntervals .Last());
116 if (point.IsEqual(curve->Value(curve->FirstParameter()),
117 Precision::Confusion()) ) {
118 extensionStart = Standard_True;
119 Standard_Real UFirst = startIntervals.First() - P.Distance(pointStartBis);
120 startIntervals.InsertBefore(1,UFirst);
121 endIntervals .InsertBefore(1,startIntervals.Value(2));
124 else if (point.IsEqual(curve->Value(curve->LastParameter()),
125 Precision::Confusion()) ) {
126 extensionEnd = Standard_True;
127 Standard_Real ULast = endIntervals.Last() + P.Distance(pointEndBis);
128 startIntervals.Append(endIntervals.Last());
129 endIntervals .Append(ULast);
135 //=============================================================================
136 //function : IsExtendAtStart
138 //=============================================================================
139 Standard_Boolean Bisector_BisecPC::IsExtendAtStart() const
141 return extensionStart;
144 //=============================================================================
145 //function : IsExtendAtEnd
147 //=============================================================================
148 Standard_Boolean Bisector_BisecPC::IsExtendAtEnd() const
153 //=============================================================================
156 //=============================================================================
157 void Bisector_BisecPC::Reverse()
159 Standard_NotImplemented::Raise();
162 //=============================================================================
163 //function : ReversedParameter
165 //=============================================================================
166 Standard_Real Bisector_BisecPC::ReversedParameter(const Standard_Real U) const
168 return LastParameter() + FirstParameter() - U;
171 //=============================================================================
174 //=============================================================================
175 Handle(Geom2d_Geometry) Bisector_BisecPC::Copy() const
177 Handle(Geom2d_Curve) CopyC = Handle(Geom2d_Curve)::DownCast(curve->Copy());
178 Handle(Bisector_BisecPC) C = new Bisector_BisecPC();
180 C->Init (CopyC,point,sign,
181 startIntervals,endIntervals,bisInterval,currentInterval,
182 shiftParameter,distMax,isEmpty,isConvex,extensionStart,extensionEnd,
183 pointStartBis,pointEndBis);
187 //=============================================================================
188 //function : Transform
190 //=============================================================================
191 void Bisector_BisecPC::Transform(const gp_Trsf2d& T)
193 curve ->Transform(T);
194 point . Transform(T);
195 pointStartBis. Transform(T);
196 pointEndBis . Transform(T);
199 //=============================================================================
202 //=============================================================================
203 Standard_Boolean Bisector_BisecPC::IsCN(const Standard_Integer N) const
205 return curve->IsCN(N+1);
208 //=============================================================================
209 //function : FirstParameter
211 //=============================================================================
212 Standard_Real Bisector_BisecPC::FirstParameter() const
214 return startIntervals.First();
217 //=============================================================================
218 //function : LastParameter
220 //=============================================================================
221 Standard_Real Bisector_BisecPC::LastParameter() const
223 return endIntervals.Last();
226 //=============================================================================
227 //function : Continuity
229 //=============================================================================
230 GeomAbs_Shape Bisector_BisecPC::Continuity() const
232 GeomAbs_Shape Cont = curve->Continuity();
234 case GeomAbs_C1 : return GeomAbs_C0;
235 case GeomAbs_C2 : return GeomAbs_C1;
236 case GeomAbs_C3 : return GeomAbs_C2;
237 case GeomAbs_CN : return GeomAbs_CN;
243 //=============================================================================
244 //function : NbIntervals
246 //=============================================================================
247 Standard_Integer Bisector_BisecPC::NbIntervals() const
249 return startIntervals.Length();
252 //=============================================================================
253 //function : IntervalFirst
255 //=============================================================================
256 Standard_Real Bisector_BisecPC::IntervalFirst(const Standard_Integer I) const
258 return startIntervals.Value(I);
261 //=============================================================================
262 //function : IntervalLast
264 //=============================================================================
265 Standard_Real Bisector_BisecPC::IntervalLast(const Standard_Integer I) const
267 return endIntervals.Value(I);
270 //=============================================================================
271 //function : IntervalContinuity
273 //=============================================================================
274 GeomAbs_Shape Bisector_BisecPC::IntervalContinuity() const
276 GeomAbs_Shape Cont = curve->Continuity();
278 case GeomAbs_C1 : return GeomAbs_C0;
279 case GeomAbs_C2 : return GeomAbs_C1;
280 case GeomAbs_C3 : return GeomAbs_C2;
281 case GeomAbs_CN : return GeomAbs_CN;
287 //=============================================================================
288 //function : IsClosed
290 //=============================================================================
291 Standard_Boolean Bisector_BisecPC::IsClosed() const
293 if (curve->IsClosed()) {
294 //-----------------------------------------------------------------------
295 // The bisectrice is closed if the curve is closed and the bissectrice
296 // has only one domain of continuity equal to the one of the curve.
297 // -----------------------------------------------------------------------
298 if (startIntervals.First() == curve->FirstParameter() &&
299 endIntervals .First() == curve->LastParameter () )
300 return Standard_True;
302 return Standard_False;
305 //=============================================================================
306 //function : IsPeriodic
308 //=============================================================================
309 Standard_Boolean Bisector_BisecPC::IsPeriodic() const
311 return Standard_False;
314 //=============================================================================
315 //function : Extension
317 //=============================================================================
318 void Bisector_BisecPC::Extension(const Standard_Real U,
327 if ( U < startIntervals.Value(bisInterval)) {
328 dU = U - startIntervals.Value(bisInterval);
329 DirExt.SetCoord(pointStartBis.X() - point.X(),
330 pointStartBis.Y() - point.Y());
331 P.SetCoord(pointStartBis.X() + dU*DirExt.X(),
332 pointStartBis.Y() + dU*DirExt.Y());
334 else if ( U > endIntervals.Value(bisInterval)) {
335 dU = U - endIntervals.Value(bisInterval);
336 DirExt.SetCoord(point.X() - pointEndBis.X(),
337 point.Y() - pointEndBis.Y());
338 P.SetCoord(pointEndBis.X() + dU*DirExt.X(),
339 pointEndBis.Y() + dU*DirExt.Y());
341 V1.SetCoord(DirExt.X(),DirExt.Y());
342 V2.SetCoord(0. ,0. );
343 V3.SetCoord(0. ,0. );
347 //=============================================================================
349 // purpose : To each point of the curve is associated a point on the
350 // bissectrice. The equation of the bissectrice is:
352 // F(u) = P(u) - 1/2* -------------- * N(u)
355 // N(u) normal to the curve by u.
356 // ( | ) designation of the scalar product.
357 //=============================================================================
358 void Bisector_BisecPC::Values(const Standard_Real U,
359 const Standard_Integer N,
365 if ( U < startIntervals.Value(bisInterval)) {
366 Extension(U,P,V1,V2,V3);
369 else if ( U > endIntervals.Value(bisInterval)) {
370 Extension(U,P,V1,V2,V3);
373 Standard_Real UOnCurve = LinkBisCurve(U);
379 case 0 : {curve->D1(UOnCurve,PC,Tu) ;break;}
380 case 1 : {curve->D2(UOnCurve,PC,Tu,Tuu) ;break;}
381 case 2 : {curve->D3(UOnCurve,PC,Tu,Tuu,T3u);break;}
384 gp_Vec2d PPC(PC.X() - point.X(), PC.Y() - point.Y());
385 gp_Vec2d Nor( - Tu.Y(), Tu.X());
387 Standard_Real SquarePPC = PPC.SquareMagnitude();
388 Standard_Real NorPPC = Nor.Dot(PPC);
391 if (Abs(NorPPC) > gp::Resolution() && (NorPPC*sign) < 0.) {
392 A1 = 0.5*SquarePPC/NorPPC;
393 P.SetCoord(PC.X() - Nor.X()*A1, PC.Y() - Nor.Y()*A1);
397 if (N == 0) return; // End Calculation Point;
399 gp_Vec2d Nu ( - Tuu.Y() , Tuu.X()); // derivative of the normal by U.
400 Standard_Real NuPPC = Nu .Dot(PPC);
401 Standard_Real TuPPC = Tu .Dot(PPC);
402 Standard_Real NorPPCE2 = NorPPC*NorPPC;
403 Standard_Real A2 = TuPPC/NorPPC - 0.5*NuPPC*SquarePPC/NorPPCE2;
405 //--------------------------
406 V1 = Tu - A1*Nu - A2*Nor;
407 //--------------------------
408 if (N == 1) return; // End calculation D1.
410 gp_Vec2d Nuu ( - T3u.Y() , T3u.X());
412 Standard_Real NorPPCE4 = NorPPCE2*NorPPCE2;
413 Standard_Real NuuPPC = Nuu.Dot(PPC);
414 Standard_Real TuuPPC = Tuu.Dot(PPC);
416 Standard_Real A21 = TuuPPC/NorPPC - TuPPC*NuPPC/NorPPCE2;
417 Standard_Real A22 = (0.5*NuuPPC*SquarePPC + NuPPC*TuPPC)/NorPPCE2 -
418 NuPPC*SquarePPC*NorPPC*NuPPC/NorPPCE4;
419 Standard_Real A2u = A21 - A22;
420 //----------------------------------------
421 V2 = Tuu - 2*A2*Nu - A1*Nuu - A2u*Nor;
422 //----------------------------------------
425 //=============================================================================
426 //function : Curvature
428 //=============================================================================
430 #ifdef OCCT_DEBUG_CUR
431 static Standard_Real Curvature (const Handle(Geom2d_Curve)& C,
439 Standard_Real Norm2 = D1.SquareMagnitude();;
444 K1 = (D1^D2)/(Norm2*sqrt(Norm2));
450 //=============================================================================
451 //function : Distance
452 //purpose : distance at the square of the point of parameter U to the curve and at point:
455 // d = 1/4* ------------------- ||Nor||
458 // where Nor is the normal to the curve by U.
459 //=============================================================================
460 Standard_Real Bisector_BisecPC::Distance (const Standard_Real U) const
465 Standard_Real UOnCurve = LinkBisCurve(U);
467 curve->D1(UOnCurve,PC,Tan);
468 gp_Vec2d PPC(PC.X() - point.X(), PC.Y() - point.Y());
469 gp_Vec2d Nor( - Tan.Y(), Tan.X());
471 Standard_Real NorNor = Nor.SquareMagnitude();
472 Standard_Real SquareMagPPC = PPC.SquareMagnitude();
473 Standard_Real Prosca = Nor.Dot(PPC);
475 if (point.IsEqual(PC,Precision::Confusion())) {
476 if (isConvex) { return 0.;}
477 //----------------------------------------------------
478 // the point is on a concave curve.
479 // The required point is not the common point.
480 // This can avoid the discontinuity of the bisectrice.
481 //----------------------------------------------------
482 else { return Precision::Infinite();}
485 if (Abs(Prosca) < Precision::Confusion() || (Prosca*sign) > 0. ) {
486 return Precision::Infinite();
489 Standard_Real A = 0.5*SquareMagPPC/Prosca;
490 Standard_Real Dist = A*A*NorNor;
491 #ifdef OCCT_DEBUG_CUR
492 //----------------------------------------
493 // Test Curvature if the curve is concave.
494 //----------------------------------------
496 Standard_Real K = Curvature(curve,UOnCurve,Precision::Confusion());
498 if (Dist > 1/(K*K)) { Dist = Precision::Infinite();}
508 //=============================================================================
511 //=============================================================================
512 void Bisector_BisecPC::D0(const Standard_Real U,
517 Values(U,0,P,V1,V2,V3);
521 //=============================================================================
524 //=============================================================================
525 void Bisector_BisecPC::D1(const Standard_Real U,
532 Values(U,1,P,V,V2,V3);
536 //=============================================================================
539 //=============================================================================
540 void Bisector_BisecPC::D2(const Standard_Real U,
549 Values(U,2,P,V1,V2,V3);
552 //=============================================================================
555 //=============================================================================
556 void Bisector_BisecPC::D3(const Standard_Real U,
566 Values(U,3,P,V1,V2,V3);
570 //=============================================================================
573 //=============================================================================
574 gp_Vec2d Bisector_BisecPC::DN (const Standard_Real U,
575 const Standard_Integer N) const
581 Values (U,N,P,V1,V2,V3);
587 Standard_NotImplemented::Raise();
593 //=============================================================================
594 //function : SearchBound
596 //=============================================================================
597 Standard_Real Bisector_BisecPC::SearchBound (const Standard_Real U1,
598 const Standard_Real U2) const
600 Standard_Real Dist1,DistMid,U11,U22;
601 Standard_Real UMid = 0.;
602 Standard_Real Tol = Precision::PConfusion();
603 Standard_Real DistMax2 = distMax*distMax;
605 Dist1 = Distance(U11);
607 while ((U22 - U11) > Tol) {
608 UMid = 0.5*( U22 + U11);
609 DistMid = Distance(UMid);
610 if ((Dist1 > DistMax2) == (DistMid > DistMax2)) {
621 //=============================================================================
622 //function : CuspFilter
624 //=============================================================================
625 void Bisector_BisecPC::CuspFilter()
627 Standard_NotImplemented::Raise();
630 //=============================================================================
631 //function : ComputeIntervals
633 //=============================================================================
634 void Bisector_BisecPC::ComputeIntervals ()
636 Standard_Real U1 =0.,U2 =0.,UProj =0.;
637 Standard_Real UStart,UEnd;
638 Standard_Real Dist1,Dist2,DistProj;
639 isEmpty = Standard_False;
641 Standard_Boolean YaProj = Standard_False;
642 Standard_Real DistMax2 = distMax*distMax;
644 U1 = curve->FirstParameter();
645 U2 = curve->LastParameter();
646 Dist1 = Distance(U1);
647 Dist2 = Distance(U2);
648 DistProj = Precision::Infinite();
650 Geom2dAPI_ProjectPointOnCurve Proj(point,curve,U1,U2);
651 if (Proj.NbPoints() > 0) {
652 UProj = Proj.LowerDistanceParameter();
653 DistProj = Distance(UProj);
654 YaProj = Standard_True;
657 if (Dist1 < DistMax2 && Dist2 < DistMax2) {
658 if (DistProj > DistMax2 && YaProj) {
659 isEmpty = Standard_True;
662 startIntervals.Append(U1);
663 endIntervals .Append(U2);
667 else if (Dist1 > DistMax2 && Dist2 > DistMax2) {
668 if (DistProj < DistMax2) {
669 UStart = SearchBound(U1,UProj);
670 UEnd = SearchBound(UProj,U2);
673 isEmpty = Standard_True;
677 else if (Dist1 < DistMax2) {
679 UEnd = SearchBound(U1,U2);
681 else if (Dist2 < DistMax2) {
683 UStart = SearchBound(U1,U2);
685 startIntervals.Append(UStart);
686 endIntervals .Append(UEnd);
688 //------------------------------------------------------------------------
689 // Eventual offset of the parameter on the curve correspondingly to the one
690 // on the curve. The offset can be done if the curve is periodical and the
691 // point of initial parameter is less then the interval of continuity.
692 //------------------------------------------------------------------------
693 if (curve->IsPeriodic()) {
694 if (startIntervals.Length() > 1) { // Plusieurs intervals.
695 if (endIntervals .Last() == curve->LastParameter() &&
696 startIntervals.First() == curve->FirstParameter() ) {
697 //---------------------------------------------------------------
698 // the bissectrice is defined at the origin.
699 // => Fusion of the first and the last interval.
700 // => 0 on the bisectrice becomes the start of the first interval
701 // => offset of parameter on all limits of intervals.
702 //---------------------------------------------------------------
703 startIntervals.Remove(1);
704 endIntervals .Remove(endIntervals.Length());
706 shiftParameter = Period() - startIntervals.First() ;
707 for (Standard_Integer k = 1; k <= startIntervals.Length(); k++) {
708 endIntervals .ChangeValue(k) += shiftParameter;
709 startIntervals.ChangeValue(k) += shiftParameter;
711 startIntervals.ChangeValue(1) = 0.;
717 //=============================================================================
718 //function : LinkBisCurve
720 //=============================================================================
721 Standard_Real Bisector_BisecPC::LinkBisCurve(const Standard_Real U) const
723 return (U - shiftParameter);
726 //=============================================================================
727 //function : LinkCurveBis
729 //=============================================================================
730 Standard_Real Bisector_BisecPC::LinkCurveBis(const Standard_Real U) const
732 return (U + shiftParameter);
735 //=============================================================================
738 //=============================================================================
739 Standard_Boolean Bisector_BisecPC::IsEmpty() const
744 //==========================================================================
745 //function : Parameter
747 //==========================================================================
748 Standard_Real Bisector_BisecPC::Parameter(const gp_Pnt2d& P) const
750 Standard_Real Tol = Precision::Confusion();
752 if (P.IsEqual(pointStartBis,Tol)) {return startIntervals.Value(bisInterval);}
753 if (P.IsEqual(pointEndBis ,Tol)) {return endIntervals .Value(bisInterval);}
755 if (extensionStart) {
756 gp_Ax2d Axe(pointStartBis,gp_Dir2d(pointStartBis.X() - P.X(),
757 pointStartBis.Y() - P.Y()));
758 Standard_Real U = ElCLib::LineParameter(Axe,P);
759 gp_Pnt2d Proj = ElCLib::LineValue(U,Axe);
760 if (Proj.IsEqual(P,Tol) && U < 0.) {
761 return U + startIntervals.Value(bisInterval);
765 gp_Ax2d Axe(pointEndBis,gp_Dir2d(P.X() - pointEndBis.X(),
766 P.Y() - pointEndBis.Y()));
767 Standard_Real U = ElCLib::LineParameter(Axe,P);
768 gp_Pnt2d Proj = ElCLib::LineValue(U,Axe);
769 if (Proj.IsEqual(P,Tol) && U > 0.) {
770 return U + endIntervals.Value(bisInterval);
773 Standard_Real UOnCurve = 0.;
774 Geom2dAPI_ProjectPointOnCurve Proj(P,curve,
775 curve->FirstParameter(),curve->LastParameter());
776 if (Proj.NbPoints() > 0) {
777 UOnCurve = Proj.LowerDistanceParameter();
779 return LinkCurveBis(UOnCurve);
783 //=============================================================================
786 //=============================================================================
787 static void Indent(const Standard_Integer Offset) {
789 for (Standard_Integer i = 0; i < Offset; i++) {cout << " ";}
793 //=============================================================================
796 //=============================================================================
797 void Bisector_BisecPC::Init (const Handle(Geom2d_Curve)& Curve,
798 const gp_Pnt2d& Point,
799 const Standard_Real Sign,
800 const TColStd_SequenceOfReal& StartIntervals,
801 const TColStd_SequenceOfReal& EndIntervals,
802 const Standard_Integer BisInterval,
803 const Standard_Integer CurrentInterval,
804 const Standard_Real ShiftParameter,
805 const Standard_Real DistMax,
806 const Standard_Boolean IsEmpty,
807 const Standard_Boolean IsConvex,
808 const Standard_Boolean ExtensionStart,
809 const Standard_Boolean ExtensionEnd,
810 const gp_Pnt2d& PointStartBis,
811 const gp_Pnt2d& PointEndBis)
816 startIntervals = StartIntervals;
817 endIntervals = EndIntervals;
818 bisInterval = BisInterval;
819 currentInterval = CurrentInterval;
820 shiftParameter = ShiftParameter;
824 extensionStart = ExtensionStart;
825 extensionEnd = ExtensionEnd;
826 pointStartBis = PointStartBis;
827 pointEndBis = PointEndBis;
830 //=============================================================================
833 //=============================================================================
834 //void Bisector_BisecPC::Dump(const Standard_Integer Deep,
835 void Bisector_BisecPC::Dump(const Standard_Integer ,
836 const Standard_Integer Offset) const
839 cout <<"Bisector_BisecPC :"<<endl;
841 cout <<"Point :"<<endl;
842 cout <<" X = "<<point.X()<<endl;
843 cout <<" Y = "<<point.Y()<<endl;
844 cout <<"Sign :"<<sign<<endl;
845 cout <<"Number Of Intervals :"<<startIntervals.Length()<<endl;
846 for (Standard_Integer i = 1; i <= startIntervals.Length(); i++) {
847 cout <<"Interval number :"<<i<<"Start :"<<startIntervals.Value(i)
848 <<" end :"<< endIntervals.Value(i)<<endl ;
850 cout <<"Index Current Interval :"<<currentInterval<<endl;