1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
15 #include <Adaptor2d_HCurve2d.hxx>
16 #include <Adaptor2d_HOffsetCurve.hxx>
17 #include <Adaptor2d_OffsetCurve.hxx>
18 #include <Geom2d_BezierCurve.hxx>
19 #include <Geom2d_BSplineCurve.hxx>
20 #include <GeomAbs_SurfaceType.hxx>
22 #include <gp_Ax22d.hxx>
23 #include <gp_Circ2d.hxx>
24 #include <gp_Dir2d.hxx>
25 #include <gp_Elips2d.hxx>
26 #include <gp_Hypr2d.hxx>
27 #include <gp_Lin2d.hxx>
28 #include <gp_Parab2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <gp_Vec2d.hxx>
31 #include <gp_VectorWithNullMagnitude.hxx>
32 #include <Precision.hxx>
33 #include <Standard_DomainError.hxx>
34 #include <Standard_NoSuchObject.hxx>
35 #include <Standard_NotImplemented.hxx>
36 #include <Standard_OutOfRange.hxx>
37 #include <Standard_TypeMismatch.hxx>
39 //=======================================================================
40 //function : Adaptor2d_OffsetCurve
42 //=======================================================================
43 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve()
50 //=======================================================================
51 //function : Adaptor2d_OffsetCurve
53 //=======================================================================
55 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve(const Handle(Adaptor2d_HCurve2d)& theCurve)
63 //=======================================================================
64 //function : Adaptor2d_OffsetCurve
66 //=======================================================================
68 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve
69 (const Handle(Adaptor2d_HCurve2d)& theCurve, const Standard_Real theOffset)
72 myFirst (theCurve->FirstParameter()),
73 myLast (theCurve->LastParameter())
77 //=======================================================================
78 //function : Adaptor2d_OffsetCurve
80 //=======================================================================
82 Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve(
83 const Handle(Adaptor2d_HCurve2d)& theCurve,
84 const Standard_Real theOffset,
85 const Standard_Real theWFirst,
86 const Standard_Real theWLast )
94 //=======================================================================
97 //=======================================================================
99 void Adaptor2d_OffsetCurve::Load(const Handle(Adaptor2d_HCurve2d)& C )
105 //=======================================================================
108 //=======================================================================
110 void Adaptor2d_OffsetCurve::Load( const Standard_Real Offset)
113 myFirst = myCurve->FirstParameter();
114 myLast = myCurve->LastParameter();
118 //=======================================================================
121 //=======================================================================
123 void Adaptor2d_OffsetCurve::Load(const Standard_Real Offset,
124 const Standard_Real WFirst,
125 const Standard_Real WLast)
132 //=======================================================================
133 //function : Continuity
135 //=======================================================================
137 GeomAbs_Shape Adaptor2d_OffsetCurve::Continuity() const
139 switch (myCurve->Continuity()) {
140 case GeomAbs_CN: return GeomAbs_CN;
141 case GeomAbs_C3: return GeomAbs_C2;
142 case GeomAbs_C2: return GeomAbs_G2;
143 case GeomAbs_G2: return GeomAbs_C1;
144 case GeomAbs_C1: return GeomAbs_G1;
145 case GeomAbs_G1: return GeomAbs_C0;
148 throw Standard_TypeMismatch("Adaptor2d_OffsetCurve::IntervalContinuity");
156 //=======================================================================
157 //function : NbIntervals
159 //=======================================================================
161 Standard_Integer Adaptor2d_OffsetCurve::NbIntervals(const GeomAbs_Shape S) const
164 if ( S >= GeomAbs_C2) Sh = GeomAbs_CN;
166 Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
168 Standard_Integer nbInter = myCurve->NbIntervals(Sh);
170 if(nbInter == 1) return nbInter;
172 TColStd_Array1OfReal T(1,nbInter+1);
174 myCurve->Intervals(T,Sh);
176 Standard_Integer first = 1;
177 while (T(first) <= myFirst) first++;
178 Standard_Integer last = nbInter+1;
179 while (T(last) >= myLast) last--;
180 return (last - first + 2);
183 //=======================================================================
184 //function : Intervals
186 //=======================================================================
188 void Adaptor2d_OffsetCurve::Intervals(TColStd_Array1OfReal& TI,
189 const GeomAbs_Shape S) const
192 if ( S >= GeomAbs_C2) Sh = GeomAbs_CN;
194 Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
196 Standard_Integer nbInter = myCurve->NbIntervals(Sh);
200 TI(TI.Lower()) = myFirst ;
201 TI(TI.Lower() + 1) = myLast ;
205 TColStd_Array1OfReal T(1,nbInter+1);
206 myCurve->Intervals(T,Sh);
208 Standard_Integer first = 1;
209 while (T(first) <= myFirst) first++;
210 Standard_Integer last = nbInter+1;
211 while (T(last) >= myLast) last--;
213 Standard_Integer i = TI.Lower(), j;
214 for (j = first-1; j <= last+1; j++) {
219 TI(TI.Lower()) = myFirst ;
220 TI(TI.Lower() + last-first + 2) = myLast ;
225 //=======================================================================
228 //=======================================================================
230 Handle(Adaptor2d_HCurve2d) Adaptor2d_OffsetCurve::Trim
231 (const Standard_Real First,
232 const Standard_Real Last,
233 const Standard_Real) const
235 Handle(Adaptor2d_HOffsetCurve) HO = new Adaptor2d_HOffsetCurve(*this);
236 HO->ChangeCurve2d().Load(myOffset,First,Last);
241 //=======================================================================
242 //function : IsClosed
244 //=======================================================================
246 Standard_Boolean Adaptor2d_OffsetCurve::IsClosed() const
248 if ( myOffset == 0.) {
249 return myCurve->IsClosed();
252 if (myCurve->Continuity() == GeomAbs_C0)
253 return Standard_False;
255 if ( myCurve->IsClosed()) {
259 (myCurve->FirstParameter(),P,Dummy[0]);
261 (myCurve->LastParameter(),P,Dummy[1]);
262 if (Dummy[0].IsParallel(Dummy[1],Precision::Angular()) &&
263 !(Dummy[0].IsOpposite(Dummy[1],Precision::Angular())))
264 return Standard_True;
266 return Standard_False;
269 return Standard_False;
274 //=======================================================================
275 //function : IsPeriodic
277 //=======================================================================
279 Standard_Boolean Adaptor2d_OffsetCurve::IsPeriodic() const
281 return myCurve->IsPeriodic();
284 //=======================================================================
287 //=======================================================================
289 Standard_Real Adaptor2d_OffsetCurve::Period() const
291 return myCurve->Period();
294 //=======================================================================
297 //=======================================================================
299 gp_Pnt2d Adaptor2d_OffsetCurve::Value(const Standard_Real U) const
301 if ( myOffset != 0.) {
305 myCurve->D1(U, P, V);
306 Norme = V.Magnitude();
307 V.SetCoord(-V.Y(),V.X());
308 if (Norme >= gp::Resolution()) {
309 return gp_Pnt2d(P.XY()+myOffset*V.XY()/Norme);
312 throw gp_VectorWithNullMagnitude("Adaptor2d_OffsetCurve::Value");
316 return myCurve->Value(U);
320 //=======================================================================
323 //=======================================================================
325 void Adaptor2d_OffsetCurve::D0(const Standard_Real U, gp_Pnt2d& P) const
330 //=======================================================================
333 //=======================================================================
335 void Adaptor2d_OffsetCurve::D1
336 (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V) const
341 if ( myOffset != 0. ) {
342 myCurve->D2(U,PP,V1,V2);
343 Norme = V1.Magnitude();
344 V3.SetCoord( -V1.Y(),V1.X());
345 V2.SetCoord( -V2.Y(),V2.X());
346 if ( Norme >= gp::Resolution()) {
347 P = gp_Pnt2d( PP.XY()+myOffset*V3.XY()/Norme);
348 V = gp_Vec2d( V1.XY()+
349 (myOffset/Norme)*(V2.XY()-V3.XY()*
350 (V2.XY()*V3.XY())/(Norme*Norme)));
353 throw gp_VectorWithNullMagnitude("Adaptor2d_OffsetCurve::D1");
361 //=======================================================================
364 //=======================================================================
366 void Adaptor2d_OffsetCurve::D2
367 (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
369 if ( myOffset != 0.) {
373 myCurve->D3(U,PP,T1,T2,T3);
375 Norme = T1.Magnitude();
376 if ( Norme >= gp::Resolution()) {
377 gp_Vec2d N1,N2,N3; // Ni = Z ^ Ti
378 N1.SetCoord( -T1.Y(), T1.X());
379 N2.SetCoord( -T2.Y(), T2.X());
380 N3.SetCoord( -T3.Y(), T3.X());
381 Standard_Real d12,d13,d22,Nor3,Nor11;
385 Nor3 = Norme*Norme*Norme;
386 Nor11 = Nor3*Nor3*Nor3*Norme*Norme;
387 V2 = gp_Vec2d( -1 * ( (d22+d13)/Nor3 + 3*d12*d12/Nor11) * N1.XY());
388 V2 = gp_Vec2d( V2.XY() - (2*d12/Nor3)*N2.XY() + N3.XY()/Norme);
389 V2 = gp_Vec2d( myOffset*V2.XY() + T2.XY());
394 throw gp_VectorWithNullMagnitude("Adaptor2d_OffsetCurve::D2");
398 myCurve->D2(U,P,V1,V2);
402 //=======================================================================
405 //=======================================================================
407 //void Adaptor2d_OffsetCurve::D3
408 // (const Standard_Real T,
409 // gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2, gp_Vec2d& V3) const
410 void Adaptor2d_OffsetCurve::D3
411 (const Standard_Real ,
412 gp_Pnt2d& , gp_Vec2d& , gp_Vec2d& , gp_Vec2d& ) const
414 throw Standard_NotImplemented("Adaptor2d_OffsetCurve::D3");
417 //=======================================================================
420 //=======================================================================
422 gp_Vec2d Adaptor2d_OffsetCurve::DN
423 // (const Standard_Real T, const Standard_Integer N) const
424 (const Standard_Real , const Standard_Integer ) const
426 throw Standard_NotImplemented("Adaptor2d_OffsetCurve::DN");
430 //=======================================================================
431 //function : Resolution
433 //=======================================================================
435 Standard_Real Adaptor2d_OffsetCurve::Resolution(const Standard_Real R3d) const
437 return Precision::PConfusion(R3d);
441 //=======================================================================
444 //=======================================================================
446 GeomAbs_CurveType Adaptor2d_OffsetCurve::GetType() const {
448 if ( myOffset == 0.) {
449 return myCurve->GetType();
452 switch (myCurve->GetType()) {
458 return GeomAbs_Circle;
461 return GeomAbs_OffsetCurve;
467 //=======================================================================
470 //=======================================================================
472 gp_Lin2d Adaptor2d_OffsetCurve::Line() const
474 if ( GetType() == GeomAbs_Line) {
478 return gp_Lin2d(P,V);
481 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Line");
486 //=======================================================================
489 //=======================================================================
491 gp_Circ2d Adaptor2d_OffsetCurve::Circle() const
493 if ( GetType() == GeomAbs_Circle) {
494 if (myOffset == 0.) {
495 return myCurve->Circle();
498 gp_Circ2d C1( myCurve->Circle());
499 Standard_Real radius = C1.Radius();
500 gp_Ax22d axes( C1.Axis());
501 gp_Dir2d Xd = axes.XDirection();
502 gp_Dir2d Yd = axes.YDirection();
503 Standard_Real Crossed = Xd.X()*Yd.Y()-Xd.Y()*Yd.X();
504 Standard_Real Signe = ( Crossed > 0.) ? 1. : -1.;
506 radius += Signe*myOffset;
508 return gp_Circ2d( axes,radius);
510 else if ( radius < 0.) {
512 axes.SetXDirection( (axes.XDirection()).Reversed());
513 return gp_Circ2d( axes,radius);
515 else { // Cercle de rayon Nul
516 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
521 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
525 //=======================================================================
528 //=======================================================================
530 gp_Elips2d Adaptor2d_OffsetCurve::Ellipse() const
532 if (myCurve->GetType() == GeomAbs_Ellipse && myOffset == 0.) {
533 return myCurve->Ellipse();
536 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Ellipse");
540 //=======================================================================
541 //function : Hyperbola
543 //=======================================================================
545 gp_Hypr2d Adaptor2d_OffsetCurve::Hyperbola() const
547 if (myCurve->GetType()==GeomAbs_Hyperbola && myOffset==0.) {
548 return myCurve->Hyperbola();
551 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Hyperbola");
555 //=======================================================================
556 //function : Parabola
558 //=======================================================================
560 gp_Parab2d Adaptor2d_OffsetCurve::Parabola() const
562 if (myCurve->GetType() == GeomAbs_Parabola && myOffset == 0.) {
563 return myCurve->Parabola();
566 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Parabola");
569 //=======================================================================
572 //=======================================================================
574 Standard_Integer Adaptor2d_OffsetCurve::Degree() const
576 GeomAbs_CurveType type = myCurve->GetType();
577 if ( (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve)
579 return myCurve->Degree();
582 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Degree");
585 //=======================================================================
586 //function : IsRational
588 //=======================================================================
590 Standard_Boolean Adaptor2d_OffsetCurve::IsRational() const
592 if ( myOffset == 0.) {
593 return myCurve->IsRational();
595 return Standard_False;
597 //=======================================================================
600 //=======================================================================
602 Standard_Integer Adaptor2d_OffsetCurve::NbPoles() const
604 GeomAbs_CurveType type = myCurve->GetType();
605 if ( (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve)
607 return myCurve->NbPoles();
610 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbPoles");
614 //=======================================================================
617 //=======================================================================
619 Standard_Integer Adaptor2d_OffsetCurve::NbKnots() const
621 if( myOffset == 0.) {
622 return myCurve->NbKnots();
625 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbKnots");
629 //=======================================================================
632 //=======================================================================
634 Handle(Geom2d_BezierCurve) Adaptor2d_OffsetCurve::Bezier() const
636 Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BezierCurve,
637 "Adaptor2d_OffsetCurve::Bezier() - wrong curve type");
638 return myCurve->Bezier();
642 //=======================================================================
645 //=======================================================================
647 Handle(Geom2d_BSplineCurve) Adaptor2d_OffsetCurve::BSpline() const
649 Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BSplineCurve,
650 "Adaptor2d_OffsetCurve::BSpline() - wrong curve type");
651 return myCurve->BSpline();
654 static Standard_Integer nbPoints(const Handle(Adaptor2d_HCurve2d)& theCurve)
657 Standard_Integer nbs = 20;
659 if (theCurve->GetType() == GeomAbs_BezierCurve)
661 nbs = Max(nbs, 3 + theCurve->NbPoles());
663 else if (theCurve->GetType() == GeomAbs_BSplineCurve) {
664 nbs = Max(nbs, theCurve->NbKnots() * theCurve->Degree());
672 //=======================================================================
673 //function : NbSamples
675 //=======================================================================
677 Standard_Integer Adaptor2d_OffsetCurve::NbSamples() const
679 return nbPoints(myCurve);