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.
18 #include <Bisector.hxx>
19 #include <Bisector_BisecPC.hxx>
21 #include <Geom2d_Curve.hxx>
22 #include <Geom2d_Geometry.hxx>
23 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
24 #include <Geom2dLProp_CLProps2d.hxx>
26 #include <gp_Ax2d.hxx>
27 #include <gp_Pnt2d.hxx>
28 #include <gp_Trsf2d.hxx>
29 #include <gp_Vec2d.hxx>
30 #include <Precision.hxx>
31 #include <Standard_NotImplemented.hxx>
32 #include <Standard_Type.hxx>
34 IMPLEMENT_STANDARD_RTTIEXT(Bisector_BisecPC,Bisector_Curve)
36 //=============================================================================
39 //=============================================================================
40 Bisector_BisecPC::Bisector_BisecPC()
46 isEmpty(Standard_True),
47 isConvex(Standard_False),
48 extensionStart(Standard_False),
49 extensionEnd(Standard_False)
53 //=============================================================================
56 //=============================================================================
57 Bisector_BisecPC::Bisector_BisecPC(const Handle(Geom2d_Curve)& Cu,
59 const Standard_Real Side,
60 const Standard_Real DistMax)
62 Perform (Cu,P,Side,DistMax);
65 //=============================================================================
68 //=============================================================================
69 Bisector_BisecPC::Bisector_BisecPC(const Handle(Geom2d_Curve)& Cu,
71 const Standard_Real Side,
72 const Standard_Real UMin,
73 const Standard_Real UMax)
76 curve = Handle (Geom2d_Curve)::DownCast(Cu->Copy());
79 startIntervals.Append(UMin);
80 endIntervals .Append(UMax);
82 extensionStart = Standard_False;
83 extensionEnd = Standard_False;
84 pointStartBis = Value(UMin);
85 pointEndBis = Value(UMax);
86 isConvex = Bisector::IsConvex(curve,sign);
89 //=============================================================================
92 //=============================================================================
93 void Bisector_BisecPC::Perform(const Handle(Geom2d_Curve)& Cu,
95 const Standard_Real Side,
96 const Standard_Real DistMax)
98 curve = Handle (Geom2d_Curve)::DownCast(Cu->Copy());
102 isConvex = Bisector::IsConvex(curve,sign);
103 //--------------------------------------------
104 // Calculate interval of definition.
105 //--------------------------------------------
109 //-------------------------
110 // Construction extensions.
111 //-------------------------
113 extensionStart = Standard_False;
114 extensionEnd = Standard_False;
115 pointStartBis = Value(startIntervals.First());
116 pointEndBis = Value(endIntervals .Last());
119 if (point.IsEqual(curve->Value(curve->FirstParameter()),
120 Precision::Confusion()) ) {
121 extensionStart = Standard_True;
122 Standard_Real UFirst = startIntervals.First() - P.Distance(pointStartBis);
123 startIntervals.InsertBefore(1,UFirst);
124 endIntervals .InsertBefore(1,startIntervals.Value(2));
127 else if (point.IsEqual(curve->Value(curve->LastParameter()),
128 Precision::Confusion()) ) {
129 extensionEnd = Standard_True;
130 Standard_Real ULast = endIntervals.Last() + P.Distance(pointEndBis);
131 startIntervals.Append(endIntervals.Last());
132 endIntervals .Append(ULast);
138 //=============================================================================
139 //function : IsExtendAtStart
141 //=============================================================================
142 Standard_Boolean Bisector_BisecPC::IsExtendAtStart() const
144 return extensionStart;
147 //=============================================================================
148 //function : IsExtendAtEnd
150 //=============================================================================
151 Standard_Boolean Bisector_BisecPC::IsExtendAtEnd() const
156 //=============================================================================
159 //=============================================================================
160 void Bisector_BisecPC::Reverse()
162 throw Standard_NotImplemented();
165 //=============================================================================
166 //function : ReversedParameter
168 //=============================================================================
169 Standard_Real Bisector_BisecPC::ReversedParameter(const Standard_Real U) const
171 return LastParameter() + FirstParameter() - U;
174 //=============================================================================
177 //=============================================================================
178 Handle(Geom2d_Geometry) Bisector_BisecPC::Copy() const
180 Handle(Geom2d_Curve) CopyC = Handle(Geom2d_Curve)::DownCast(curve->Copy());
181 Handle(Bisector_BisecPC) C = new Bisector_BisecPC();
183 C->Init (CopyC,point,sign,
184 startIntervals,endIntervals,bisInterval,currentInterval,
185 shiftParameter,distMax,isEmpty,isConvex,extensionStart,extensionEnd,
186 pointStartBis,pointEndBis);
190 //=============================================================================
191 //function : Transform
193 //=============================================================================
194 void Bisector_BisecPC::Transform(const gp_Trsf2d& T)
196 curve ->Transform(T);
197 point . Transform(T);
198 pointStartBis. Transform(T);
199 pointEndBis . Transform(T);
202 //=============================================================================
205 //=============================================================================
206 Standard_Boolean Bisector_BisecPC::IsCN(const Standard_Integer N) const
208 return curve->IsCN(N+1);
211 //=============================================================================
212 //function : FirstParameter
214 //=============================================================================
215 Standard_Real Bisector_BisecPC::FirstParameter() const
217 return startIntervals.First();
220 //=============================================================================
221 //function : LastParameter
223 //=============================================================================
224 Standard_Real Bisector_BisecPC::LastParameter() const
226 return endIntervals.Last();
229 //=============================================================================
230 //function : Continuity
232 //=============================================================================
233 GeomAbs_Shape Bisector_BisecPC::Continuity() const
235 GeomAbs_Shape Cont = curve->Continuity();
237 case GeomAbs_C1 : return GeomAbs_C0;
238 case GeomAbs_C2 : return GeomAbs_C1;
239 case GeomAbs_C3 : return GeomAbs_C2;
240 case GeomAbs_CN : return GeomAbs_CN;
246 //=============================================================================
247 //function : NbIntervals
249 //=============================================================================
250 Standard_Integer Bisector_BisecPC::NbIntervals() const
252 return startIntervals.Length();
255 //=============================================================================
256 //function : IntervalFirst
258 //=============================================================================
259 Standard_Real Bisector_BisecPC::IntervalFirst(const Standard_Integer I) const
261 return startIntervals.Value(I);
264 //=============================================================================
265 //function : IntervalLast
267 //=============================================================================
268 Standard_Real Bisector_BisecPC::IntervalLast(const Standard_Integer I) const
270 return endIntervals.Value(I);
273 //=============================================================================
274 //function : IntervalContinuity
276 //=============================================================================
277 GeomAbs_Shape Bisector_BisecPC::IntervalContinuity() const
279 GeomAbs_Shape Cont = curve->Continuity();
281 case GeomAbs_C1 : return GeomAbs_C0;
282 case GeomAbs_C2 : return GeomAbs_C1;
283 case GeomAbs_C3 : return GeomAbs_C2;
284 case GeomAbs_CN : return GeomAbs_CN;
290 //=============================================================================
291 //function : IsClosed
293 //=============================================================================
294 Standard_Boolean Bisector_BisecPC::IsClosed() const
296 if (curve->IsClosed()) {
297 //-----------------------------------------------------------------------
298 // The bisectrice is closed if the curve is closed and the bissectrice
299 // has only one domain of continuity equal to the one of the curve.
300 // -----------------------------------------------------------------------
301 if (startIntervals.First() == curve->FirstParameter() &&
302 endIntervals .First() == curve->LastParameter () )
303 return Standard_True;
305 return Standard_False;
308 //=============================================================================
309 //function : IsPeriodic
311 //=============================================================================
312 Standard_Boolean Bisector_BisecPC::IsPeriodic() const
314 return Standard_False;
317 //=============================================================================
318 //function : Extension
320 //=============================================================================
321 void Bisector_BisecPC::Extension(const Standard_Real U,
332 if ( U < startIntervals.Value(bisInterval)) {
333 if (pointStartBis.IsEqual(point, Precision::PConfusion()))
336 dU = U - startIntervals.Value(bisInterval);
337 gp_Dir2d DirExt(pointStartBis.X() - point.X(),
338 pointStartBis.Y() - point.Y());
339 P.SetCoord(pointStartBis.X() + dU*DirExt.X(),
340 pointStartBis.Y() + dU*DirExt.Y());
341 V1.SetCoord(DirExt.X(), DirExt.Y());
344 else if ( U > endIntervals.Value(bisInterval)) {
345 if (pointEndBis.IsEqual(point, Precision::PConfusion()))
348 dU = U - endIntervals.Value(bisInterval);
349 gp_Dir2d DirExt(point.X() - pointEndBis.X(),
350 point.Y() - pointEndBis.Y());
351 P.SetCoord(pointEndBis.X() + dU*DirExt.X(),
352 pointEndBis.Y() + dU*DirExt.Y());
353 V1.SetCoord(DirExt.X(), DirExt.Y());
359 //=============================================================================
361 // purpose : To each point of the curve is associated a point on the
362 // bissectrice. The equation of the bissectrice is:
364 // F(u) = P(u) - 1/2* -------------- * N(u)
367 // N(u) normal to the curve by u.
368 // ( | ) designation of the scalar product.
369 //=============================================================================
370 void Bisector_BisecPC::Values(const Standard_Real U,
371 const Standard_Integer N,
377 if ( U < startIntervals.Value(bisInterval)) {
378 Extension(U,P,V1,V2,V3);
381 else if ( U > endIntervals.Value(bisInterval)) {
382 Extension(U,P,V1,V2,V3);
385 Standard_Real UOnCurve = LinkBisCurve(U);
391 case 0 : {curve->D1(UOnCurve,PC,Tu) ;break;}
392 case 1 : {curve->D2(UOnCurve,PC,Tu,Tuu) ;break;}
393 case 2 : {curve->D3(UOnCurve,PC,Tu,Tuu,T3u);break;}
396 gp_Vec2d aPPC(PC.X() - point.X(), PC.Y() - point.Y());
397 gp_Vec2d Nor( - Tu.Y(), Tu.X());
399 Standard_Real SquarePPC = aPPC.SquareMagnitude();
400 Standard_Real NorPPC = Nor.Dot(aPPC);
403 if (Abs(NorPPC) > gp::Resolution() && (NorPPC*sign) < 0.) {
404 A1 = 0.5*SquarePPC/NorPPC;
405 P.SetCoord(PC.X() - Nor.X()*A1, PC.Y() - Nor.Y()*A1);
409 if (N == 0) return; // End Calculation Point;
411 gp_Vec2d Nu ( - Tuu.Y() , Tuu.X()); // derivative of the normal by U.
412 Standard_Real NuPPC = Nu .Dot(aPPC);
413 Standard_Real TuPPC = Tu .Dot(aPPC);
414 Standard_Real NorPPCE2 = NorPPC*NorPPC;
415 Standard_Real A2 = TuPPC/NorPPC - 0.5*NuPPC*SquarePPC/NorPPCE2;
417 //--------------------------
418 V1 = Tu - A1*Nu - A2*Nor;
419 //--------------------------
420 if (N == 1) return; // End calculation D1.
422 gp_Vec2d Nuu ( - T3u.Y() , T3u.X());
424 Standard_Real NorPPCE4 = NorPPCE2*NorPPCE2;
425 Standard_Real NuuPPC = Nuu.Dot(aPPC);
426 Standard_Real TuuPPC = Tuu.Dot(aPPC);
428 Standard_Real A21 = TuuPPC/NorPPC - TuPPC*NuPPC/NorPPCE2;
429 Standard_Real A22 = (0.5*NuuPPC*SquarePPC + NuPPC*TuPPC)/NorPPCE2 -
430 NuPPC*SquarePPC*NorPPC*NuPPC/NorPPCE4;
431 Standard_Real A2u = A21 - A22;
432 //----------------------------------------
433 V2 = Tuu - 2*A2*Nu - A1*Nuu - A2u*Nor;
434 //----------------------------------------
437 //=============================================================================
438 //function : Curvature
440 //=============================================================================
442 #ifdef OCCT_DEBUG_CUR
443 static Standard_Real Curvature (const Handle(Geom2d_Curve)& C,
451 Standard_Real Norm2 = D1.SquareMagnitude();
456 K1 = (D1^D2)/(Norm2*sqrt(Norm2));
462 //=============================================================================
463 //function : Distance
464 //purpose : distance at the square of the point of parameter U to the curve and at point:
467 // d = 1/4* ------------------- ||Nor||
470 // where Nor is the normal to the curve by U.
471 //=============================================================================
472 Standard_Real Bisector_BisecPC::Distance (const Standard_Real U) const
477 Standard_Real UOnCurve = LinkBisCurve(U);
479 curve->D1(UOnCurve,PC,Tan);
480 gp_Vec2d aPPC(PC.X() - point.X(), PC.Y() - point.Y());
481 gp_Vec2d Nor( - Tan.Y(), Tan.X());
483 Standard_Real NorNor = Nor.SquareMagnitude();
484 Standard_Real SquareMagPPC = aPPC.SquareMagnitude();
485 Standard_Real Prosca = Nor.Dot(aPPC);
487 if (point.IsEqual(PC,Precision::Confusion())) {
488 if (isConvex) { return 0.;}
489 //----------------------------------------------------
490 // the point is on a concave curve.
491 // The required point is not the common point.
492 // This can avoid the discontinuity of the bisectrice.
493 //----------------------------------------------------
494 else { return Precision::Infinite();}
497 if (Abs(Prosca) < Precision::Confusion() || (Prosca*sign) > 0. ) {
498 return Precision::Infinite();
501 Standard_Real A = 0.5*SquareMagPPC/Prosca;
502 Standard_Real Dist = A*A*NorNor;
503 #ifdef OCCT_DEBUG_CUR
504 //----------------------------------------
505 // Test Curvature if the curve is concave.
506 //----------------------------------------
508 Standard_Real K = Curvature(curve,UOnCurve,Precision::Confusion());
510 if (Dist > 1/(K*K)) { Dist = Precision::Infinite();}
520 //=============================================================================
523 //=============================================================================
524 void Bisector_BisecPC::D0(const Standard_Real U,
529 Values(U,0,P,V1,V2,V3);
533 //=============================================================================
536 //=============================================================================
537 void Bisector_BisecPC::D1(const Standard_Real U,
544 Values(U,1,P,V,V2,V3);
548 //=============================================================================
551 //=============================================================================
552 void Bisector_BisecPC::D2(const Standard_Real U,
561 Values(U,2,P,V1,V2,V3);
564 //=============================================================================
567 //=============================================================================
568 void Bisector_BisecPC::D3(const Standard_Real U,
578 Values(U,3,P,V1,V2,V3);
582 //=============================================================================
585 //=============================================================================
586 gp_Vec2d Bisector_BisecPC::DN (const Standard_Real U,
587 const Standard_Integer N) const
593 Values (U,N,P,V1,V2,V3);
599 throw Standard_NotImplemented();
604 //=============================================================================
605 //function : SearchBound
607 //=============================================================================
608 Standard_Real Bisector_BisecPC::SearchBound (const Standard_Real U1,
609 const Standard_Real U2) const
611 Standard_Real Dist1,DistMid,U11,U22;
612 Standard_Real UMid = 0.;
613 Standard_Real Tol = Precision::PConfusion();
614 Standard_Real DistMax2 = distMax*distMax;
616 Dist1 = Distance(U11);
618 while ((U22 - U11) > Tol) {
619 UMid = 0.5*( U22 + U11);
620 DistMid = Distance(UMid);
621 if ((Dist1 > DistMax2) == (DistMid > DistMax2)) {
632 //=============================================================================
633 //function : CuspFilter
635 //=============================================================================
636 void Bisector_BisecPC::CuspFilter()
638 throw Standard_NotImplemented();
641 //=============================================================================
642 //function : ComputeIntervals
644 //=============================================================================
645 void Bisector_BisecPC::ComputeIntervals ()
647 Standard_Real U1 =0.,U2 =0.,UProj =0.;
648 Standard_Real UStart = 0., UEnd = 0.;
649 Standard_Real Dist1,Dist2,DistProj;
650 isEmpty = Standard_False;
652 Standard_Boolean YaProj = Standard_False;
653 Standard_Real DistMax2 = distMax*distMax;
655 U1 = curve->FirstParameter();
656 U2 = curve->LastParameter();
657 Dist1 = Distance(U1);
658 Dist2 = Distance(U2);
659 DistProj = Precision::Infinite();
661 Geom2dAPI_ProjectPointOnCurve Proj(point,curve,U1,U2);
662 if (Proj.NbPoints() > 0) {
663 UProj = Proj.LowerDistanceParameter();
664 DistProj = Distance(UProj);
665 YaProj = Standard_True;
668 if (Dist1 < DistMax2 && Dist2 < DistMax2) {
669 if (DistProj > DistMax2 && YaProj) {
670 isEmpty = Standard_True;
673 startIntervals.Append(U1);
674 endIntervals .Append(U2);
678 else if (Dist1 > DistMax2 && Dist2 > DistMax2) {
679 if (DistProj < DistMax2) {
680 UStart = SearchBound(U1,UProj);
681 UEnd = SearchBound(UProj,U2);
684 isEmpty = Standard_True;
688 else if (Dist1 < DistMax2) {
690 UEnd = SearchBound(U1,U2);
692 else if (Dist2 < DistMax2) {
694 UStart = SearchBound(U1,U2);
696 startIntervals.Append(UStart);
697 endIntervals .Append(UEnd);
699 //------------------------------------------------------------------------
700 // Eventual offset of the parameter on the curve correspondingly to the one
701 // on the curve. The offset can be done if the curve is periodical and the
702 // point of initial parameter is less then the interval of continuity.
703 //------------------------------------------------------------------------
704 if (curve->IsPeriodic()) {
705 if (startIntervals.Length() > 1) { // Plusieurs intervals.
706 if (endIntervals .Last() == curve->LastParameter() &&
707 startIntervals.First() == curve->FirstParameter() ) {
708 //---------------------------------------------------------------
709 // the bissectrice is defined at the origin.
710 // => Fusion of the first and the last interval.
711 // => 0 on the bisectrice becomes the start of the first interval
712 // => offset of parameter on all limits of intervals.
713 //---------------------------------------------------------------
714 startIntervals.Remove(1);
715 endIntervals .Remove(endIntervals.Length());
717 shiftParameter = Period() - startIntervals.First() ;
718 for (Standard_Integer k = 1; k <= startIntervals.Length(); k++) {
719 endIntervals .ChangeValue(k) += shiftParameter;
720 startIntervals.ChangeValue(k) += shiftParameter;
722 startIntervals.ChangeValue(1) = 0.;
728 //=============================================================================
729 //function : LinkBisCurve
731 //=============================================================================
732 Standard_Real Bisector_BisecPC::LinkBisCurve(const Standard_Real U) const
734 return (U - shiftParameter);
737 //=============================================================================
738 //function : LinkCurveBis
740 //=============================================================================
741 Standard_Real Bisector_BisecPC::LinkCurveBis(const Standard_Real U) const
743 return (U + shiftParameter);
746 //=============================================================================
749 //=============================================================================
750 Standard_Boolean Bisector_BisecPC::IsEmpty() const
755 //==========================================================================
756 //function : Parameter
758 //==========================================================================
759 Standard_Real Bisector_BisecPC::Parameter(const gp_Pnt2d& P) const
761 Standard_Real Tol = Precision::Confusion();
763 if (P.IsEqual(pointStartBis,Tol)) {return startIntervals.Value(bisInterval);}
764 if (P.IsEqual(pointEndBis ,Tol)) {return endIntervals .Value(bisInterval);}
766 if (extensionStart) {
767 gp_Ax2d Axe(pointStartBis,gp_Dir2d(pointStartBis.X() - P.X(),
768 pointStartBis.Y() - P.Y()));
769 Standard_Real U = ElCLib::LineParameter(Axe,P);
770 gp_Pnt2d Proj = ElCLib::LineValue(U,Axe);
771 if (Proj.IsEqual(P,Tol) && U < 0.) {
772 return U + startIntervals.Value(bisInterval);
776 gp_Ax2d Axe(pointEndBis,gp_Dir2d(P.X() - pointEndBis.X(),
777 P.Y() - pointEndBis.Y()));
778 Standard_Real U = ElCLib::LineParameter(Axe,P);
779 gp_Pnt2d Proj = ElCLib::LineValue(U,Axe);
780 if (Proj.IsEqual(P,Tol) && U > 0.) {
781 return U + endIntervals.Value(bisInterval);
784 Standard_Real UOnCurve = 0.;
785 Geom2dAPI_ProjectPointOnCurve Proj(P,curve,
786 curve->FirstParameter(),curve->LastParameter());
787 if (Proj.NbPoints() > 0) {
788 UOnCurve = Proj.LowerDistanceParameter();
790 return LinkCurveBis(UOnCurve);
794 //=============================================================================
797 //=============================================================================
798 static void Indent(const Standard_Integer Offset) {
800 for (Standard_Integer i = 0; i < Offset; i++) {std::cout << " ";}
804 //=============================================================================
807 //=============================================================================
808 void Bisector_BisecPC::Init (const Handle(Geom2d_Curve)& Curve,
809 const gp_Pnt2d& Point,
810 const Standard_Real Sign,
811 const TColStd_SequenceOfReal& StartIntervals,
812 const TColStd_SequenceOfReal& EndIntervals,
813 const Standard_Integer BisInterval,
814 const Standard_Integer CurrentInterval,
815 const Standard_Real ShiftParameter,
816 const Standard_Real DistMax,
817 const Standard_Boolean IsEmpty,
818 const Standard_Boolean IsConvex,
819 const Standard_Boolean ExtensionStart,
820 const Standard_Boolean ExtensionEnd,
821 const gp_Pnt2d& PointStartBis,
822 const gp_Pnt2d& PointEndBis)
827 startIntervals = StartIntervals;
828 endIntervals = EndIntervals;
829 bisInterval = BisInterval;
830 currentInterval = CurrentInterval;
831 shiftParameter = ShiftParameter;
835 extensionStart = ExtensionStart;
836 extensionEnd = ExtensionEnd;
837 pointStartBis = PointStartBis;
838 pointEndBis = PointEndBis;
841 //=============================================================================
844 //=============================================================================
845 //void Bisector_BisecPC::Dump(const Standard_Integer Deep,
846 void Bisector_BisecPC::Dump(const Standard_Integer ,
847 const Standard_Integer Offset) const
850 std::cout <<"Bisector_BisecPC :"<<std::endl;
852 std::cout <<"Point :"<<std::endl;
853 std::cout <<" X = "<<point.X()<<std::endl;
854 std::cout <<" Y = "<<point.Y()<<std::endl;
855 std::cout <<"Sign :"<<sign<<std::endl;
856 std::cout <<"Number Of Intervals :"<<startIntervals.Length()<<std::endl;
857 for (Standard_Integer i = 1; i <= startIntervals.Length(); i++) {
858 std::cout <<"Interval number :"<<i<<"Start :"<<startIntervals.Value(i)
859 <<" end :"<< endIntervals.Value(i)<<std::endl ;
861 std::cout <<"Index Current Interval :"<<currentInterval<<std::endl;