1 // Created on: 1991-06-25
3 // Copyright (c) 1991-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 Edward AGAPOV (eap) Jan 28 2002 --- DN(), occ143(BUC60654)
21 #include <Geom2d_OffsetCurve.ixx>
23 #include <Standard_ConstructionError.hxx>
24 #include <Standard_RangeError.hxx>
25 #include <Standard_NotImplemented.hxx>
26 #include <Geom2d_UndefinedDerivative.hxx>
27 #include <Geom2d_UndefinedValue.hxx>
28 #include <Geom2d_Line.hxx>
29 #include <Geom2d_Circle.hxx>
30 #include <Geom2d_Ellipse.hxx>
31 #include <Geom2d_Hyperbola.hxx>
32 #include <Geom2d_Parabola.hxx>
33 #include <Geom2d_BezierCurve.hxx>
34 #include <Geom2d_BSplineCurve.hxx>
35 #include <Geom2d_TrimmedCurve.hxx>
37 #include <Precision.hxx>
39 typedef Handle(Geom2d_OffsetCurve) Handle(OffsetCurve);
40 typedef Geom2d_OffsetCurve OffsetCurve;
41 typedef Handle(Geom2d_Geometry) Handle(Geometry);
42 typedef Handle(Geom2d_Curve) Handle(Curve);
43 typedef Geom2d_Curve Curve;
44 typedef gp_Dir2d Dir2d;
45 typedef gp_Pnt2d Pnt2d;
46 typedef gp_Vec2d Vec2d;
47 typedef gp_Trsf2d Trsf2d;
51 //ordre de derivation maximum pour la recherche de la premiere
53 static const int maxDerivOrder = 3;
54 static const Standard_Real MinStep = 1e-7;
55 static const Standard_Real MyAngularToleranceForG1 = Precision::Angular();
57 //=======================================================================
60 //=======================================================================
62 Handle(Geom2d_Geometry) Geom2d_OffsetCurve::Copy () const
64 Handle(OffsetCurve) C;
65 C = new OffsetCurve (basisCurve, offsetValue);
70 //=======================================================================
71 //function : Geom2d_OffsetCurve
72 //purpose : Basis curve cannot be an Offset curve or trimmed from
74 //=======================================================================
76 Geom2d_OffsetCurve::Geom2d_OffsetCurve (const Handle(Geom2d_Curve)& theCurve,
77 const Standard_Real theOffset,
78 const Standard_Boolean isTheNotCheckC0)
79 : offsetValue (theOffset)
81 SetBasisCurve (theCurve, isTheNotCheckC0);
84 //=======================================================================
87 //=======================================================================
89 void Geom2d_OffsetCurve::Reverse ()
91 basisCurve->Reverse();
92 offsetValue = -offsetValue;
95 //=======================================================================
96 //function : ReversedParameter
98 //=======================================================================
100 Standard_Real Geom2d_OffsetCurve::ReversedParameter( const Standard_Real U) const
102 return basisCurve->ReversedParameter( U);
105 //=======================================================================
106 //function : SetBasisCurve
108 //=======================================================================
110 void Geom2d_OffsetCurve::SetBasisCurve (const Handle(Curve)& C,
111 const Standard_Boolean isNotCheckC0)
113 const Standard_Real aUf = C->FirstParameter(),
114 aUl = C->LastParameter();
115 Handle(Geom2d_Curve) aCheckingCurve = C;
116 Standard_Boolean isTrimmed = Standard_False;
118 while(aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) ||
119 aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
121 if (aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
123 Handle(Geom2d_TrimmedCurve) aTrimC =
124 Handle(Geom2d_TrimmedCurve)::DownCast(aCheckingCurve);
125 aCheckingCurve = aTrimC->BasisCurve();
126 isTrimmed = Standard_True;
129 if (aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
131 Handle(Geom2d_OffsetCurve) aOC =
132 Handle(Geom2d_OffsetCurve)::DownCast(aCheckingCurve);
133 aCheckingCurve = aOC->BasisCurve();
134 offsetValue += aOC->Offset();
138 myBasisCurveContinuity = aCheckingCurve->Continuity();
140 Standard_Boolean isC0 = !isNotCheckC0 &&
141 (myBasisCurveContinuity == GeomAbs_C0);
143 // Basis curve must be at least C1
144 if (isC0 && aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)))
146 Handle(Geom2d_BSplineCurve) aBC = Handle(Geom2d_BSplineCurve)::DownCast(aCheckingCurve);
147 if(aBC->IsG1(aUf, aUl, MyAngularToleranceForG1))
149 //Checking if basis curve has more smooth (C1, G2 and above) is not done.
150 //It can be done in case of need.
151 myBasisCurveContinuity = GeomAbs_G1;
152 isC0 = Standard_False;
155 // Raise exception if still C0
157 Standard_ConstructionError::Raise("Offset on C0 curve");
162 basisCurve = new Geom2d_TrimmedCurve(aCheckingCurve, aUf, aUl);
166 basisCurve = aCheckingCurve;
171 //=======================================================================
172 //function : SetOffsetValue
174 //=======================================================================
176 void Geom2d_OffsetCurve::SetOffsetValue (const Standard_Real D) { offsetValue = D; }
178 //=======================================================================
179 //function : BasisCurve
181 //=======================================================================
183 Handle(Curve) Geom2d_OffsetCurve::BasisCurve () const
188 //=======================================================================
189 //function : Continuity
191 //=======================================================================
193 GeomAbs_Shape Geom2d_OffsetCurve::Continuity () const
195 GeomAbs_Shape OffsetShape=GeomAbs_C0;
196 switch (myBasisCurveContinuity) {
197 case GeomAbs_C0 : OffsetShape = GeomAbs_C0; break;
198 case GeomAbs_C1 : OffsetShape = GeomAbs_C0; break;
199 case GeomAbs_C2 : OffsetShape = GeomAbs_C1; break;
200 case GeomAbs_C3 : OffsetShape = GeomAbs_C2; break;
201 case GeomAbs_CN : OffsetShape = GeomAbs_CN; break;
202 case GeomAbs_G1 : OffsetShape = GeomAbs_G1; break;
203 case GeomAbs_G2 : OffsetShape = GeomAbs_G2; break;
209 //=======================================================================
212 //=======================================================================
214 void Geom2d_OffsetCurve::D0 (const Standard_Real theU,
217 const Standard_Real aTol = gp::Resolution();
221 basisCurve->D1 (theU, theP, vD1);
222 Standard_Real Ndu = vD1.Magnitude();
226 const Standard_Real anUinfium = basisCurve->FirstParameter();
227 const Standard_Real anUsupremum = basisCurve->LastParameter();
229 const Standard_Real DivisionFactor = 1.e-3;
231 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
234 du = anUsupremum-anUinfium;
236 const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
237 //Derivative is approximated by Taylor-series
239 Standard_Integer anIndex = 1; //Derivative order
244 V = basisCurve->DN(theU,++anIndex);
247 while((Ndu <= aTol) && anIndex < maxDerivOrder);
251 if(theU-anUinfium < aDelta)
257 basisCurve->D0(Min(theU, u),P1);
258 basisCurve->D0(Max(theU, u),P2);
261 Standard_Real aDirFactor = V.Dot(V1);
268 Ndu = vD1.Magnitude();
272 Geom2d_UndefinedValue::Raise("Exception: Undefined normal vector "
273 "because tangent vector has zero-magnitude!");
275 Standard_Real A = vD1.Y();
276 Standard_Real B = - vD1.X();
277 A = A * offsetValue/Ndu;
278 B = B * offsetValue/Ndu;
279 theP.SetCoord(theP.X() + A, theP.Y() + B);
282 //=======================================================================
285 //=======================================================================
286 void Geom2d_OffsetCurve::D1 (const Standard_Real theU, Pnt2d& P, Vec2d& theV1) const
288 // P(u) = p(u) + Offset * Ndir / R
289 // with R = || p' ^ Z|| and Ndir = P' ^ Z
291 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
293 const Standard_Real aTol = gp::Resolution();
296 basisCurve->D2 (theU, P, theV1, V2);
298 if(theV1.Magnitude() <= aTol)
300 const Standard_Real anUinfium = basisCurve->FirstParameter();
301 const Standard_Real anUsupremum = basisCurve->LastParameter();
303 const Standard_Real DivisionFactor = 1.e-3;
305 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
308 du = anUsupremum-anUinfium;
310 const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
311 //Derivative is approximated by Taylor-series
313 Standard_Integer anIndex = 1; //Derivative order
318 V = basisCurve->DN(theU,++anIndex);
320 while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
324 if(theU-anUinfium < aDelta)
330 basisCurve->D0(Min(theU, u),P1);
331 basisCurve->D0(Max(theU, u),P2);
334 Standard_Real aDirFactor = V.Dot(V1);
339 V2 = - basisCurve->DN (theU, anIndex+1);
344 V2 = basisCurve->DN (theU, anIndex+1);
346 }//if(theV1.Magnitude() <= aTol)
348 XY Ndir (theV1.Y(), -theV1.X());
349 XY DNdir (V2.Y(), -V2.X());
350 Standard_Real R2 = Ndir.SquareModulus();
351 Standard_Real R = Sqrt (R2);
352 Standard_Real R3 = R * R2;
353 Standard_Real Dr = Ndir.Dot (DNdir);
354 if (R3 <= gp::Resolution()) {
355 //We try another computation but the stability is not very good.
356 if (R2 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
358 DNdir.Subtract (Ndir.Multiplied (Dr/R));
359 DNdir.Multiply (offsetValue/R2);
360 theV1.Add (Vec2d(DNdir));
363 // Same computation as IICURV in EUCLID-IS because the stability is
365 DNdir.Multiply (offsetValue/R);
366 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
367 theV1.Add (Vec2d(DNdir));
373 //=======================================================================
376 //=======================================================================
378 void Geom2d_OffsetCurve::D2 (const Standard_Real theU,
380 Vec2d& theV1, Vec2d& V2) const
382 // P(u) = p(u) + Offset * Ndir / R
383 // with R = || p' ^ Z|| and Ndir = P' ^ Z
385 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
387 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
388 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
391 basisCurve->D3 (theU, P, theV1, V2, V3);
393 const Standard_Real aTol = gp::Resolution();
395 Standard_Boolean IsDirectionChange = Standard_False;
397 if(theV1.Magnitude() <= aTol)
399 const Standard_Real anUinfium = basisCurve->FirstParameter();
400 const Standard_Real anUsupremum = basisCurve->LastParameter();
402 const Standard_Real DivisionFactor = 1.e-3;
404 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
407 du = anUsupremum-anUinfium;
409 const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
410 //Derivative is approximated by Taylor-series
412 Standard_Integer anIndex = 1; //Derivative order
417 V = basisCurve->DN(theU,++anIndex);
419 while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
423 if(theU-anUinfium < aDelta)
429 basisCurve->D0(Min(theU, u),P1);
430 basisCurve->D0(Max(theU, u),P2);
433 Standard_Real aDirFactor = V.Dot(V1);
438 V2 = -basisCurve->DN (theU, anIndex+1);
439 V3 = -basisCurve->DN (theU, anIndex + 2);
441 IsDirectionChange = Standard_True;
446 V2 = basisCurve->DN (theU, anIndex+1);
447 V3 = basisCurve->DN (theU, anIndex + 2);
449 }//if(V1.Magnitude() <= aTol)
451 XY Ndir (theV1.Y(), -theV1.X());
452 XY DNdir (V2.Y(), -V2.X());
453 XY D2Ndir (V3.Y(), -V3.X());
454 Standard_Real R2 = Ndir.SquareModulus();
455 Standard_Real R = Sqrt (R2);
456 Standard_Real R3 = R2 * R;
457 Standard_Real R4 = R2 * R2;
458 Standard_Real R5 = R3 * R2;
459 Standard_Real Dr = Ndir.Dot (DNdir);
460 Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
461 if (R5 <= gp::Resolution())
463 //We try another computation but the stability is not very good
465 if (R4 <= gp::Resolution())
467 Geom2d_UndefinedDerivative::Raise();
470 Standard_Real R4 = R2 * R2;
471 D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
472 D2Ndir.Add (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
473 D2Ndir.Multiply (offsetValue / R);
475 if(IsDirectionChange)
478 V2.Add (Vec2d(D2Ndir));
482 DNdir.Subtract (Ndir.Multiplied (Dr/R));
483 DNdir.Multiply (offsetValue/R2);
484 theV1.Add (Vec2d(DNdir));
488 // Same computation as IICURV in EUCLID-IS because the stability is
491 D2Ndir.Multiply (offsetValue/R);
492 D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
493 D2Ndir.Add (Ndir.Multiplied
494 (offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))));
496 if(IsDirectionChange)
499 V2.Add (Vec2d(D2Ndir));
502 DNdir.Multiply (offsetValue/R);
503 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
504 theV1.Add (Vec2d(DNdir));
512 //=======================================================================
515 //=======================================================================
517 void Geom2d_OffsetCurve::D3 (const Standard_Real theU,
519 Vec2d& theV1, Vec2d& V2, Vec2d& V3) const {
522 // P(u) = p(u) + Offset * Ndir / R
523 // with R = || p' ^ Z|| and Ndir = P' ^ Z
525 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
527 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
528 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
530 //P"'(u) = p"'(u) + (Offset / R) * (D3Ndir - (3.0 * Dr/R**2 ) * D2Ndir -
531 // (3.0 * D2r / R2) * DNdir) + (3.0 * Dr * Dr / R4) * DNdir -
532 // (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
533 // (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
535 const Standard_Real aTol = gp::Resolution();
537 Standard_Boolean IsDirectionChange = Standard_False;
539 basisCurve->D3 (theU, P, theV1, V2, V3);
540 Vec2d V4 = basisCurve->DN (theU, 4);
542 if(theV1.Magnitude() <= aTol)
544 const Standard_Real anUinfium = basisCurve->FirstParameter();
545 const Standard_Real anUsupremum = basisCurve->LastParameter();
547 const Standard_Real DivisionFactor = 1.e-3;
549 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
552 du = anUsupremum-anUinfium;
554 const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
555 //Derivative is approximated by Taylor-series
557 Standard_Integer anIndex = 1; //Derivative order
562 V = basisCurve->DN(theU,++anIndex);
564 while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
568 if(theU-anUinfium < aDelta)
574 basisCurve->D0(Min(theU, u),P1);
575 basisCurve->D0(Max(theU, u),P2);
578 Standard_Real aDirFactor = V.Dot(V1);
583 V2 = -basisCurve->DN (theU, anIndex + 1);
584 V3 = -basisCurve->DN (theU, anIndex + 2);
585 V4 = -basisCurve->DN (theU, anIndex + 3);
587 IsDirectionChange = Standard_True;
592 V2 = basisCurve->DN (theU, anIndex + 1);
593 V3 = basisCurve->DN (theU, anIndex + 2);
594 V4 = basisCurve->DN (theU, anIndex + 3);
596 }//if(V1.Magnitude() <= aTol)
598 XY Ndir (theV1.Y(), -theV1.X());
599 XY DNdir (V2.Y(), -V2.X());
600 XY D2Ndir (V3.Y(), -V3.X());
601 XY D3Ndir (V4.Y(), -V4.X());
602 Standard_Real R2 = Ndir.SquareModulus();
603 Standard_Real R = Sqrt (R2);
604 Standard_Real R3 = R2 * R;
605 Standard_Real R4 = R2 * R2;
606 Standard_Real R5 = R3 * R2;
607 Standard_Real R6 = R3 * R3;
608 Standard_Real R7 = R5 * R2;
609 Standard_Real Dr = Ndir.Dot (DNdir);
610 Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
611 Standard_Real D3r = Ndir.Dot (D3Ndir) + 3.0 * DNdir.Dot (D2Ndir);
613 if (R7 <= gp::Resolution())
615 //We try another computation but the stability is not very good
618 if (R6 <= gp::Resolution())
619 Geom2d_UndefinedDerivative::Raise();
622 D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R2));
624 (DNdir.Multiplied ((3.0 * offsetValue) * ((D2r/R2) + (Dr*Dr)/R4))));
625 D3Ndir.Add (Ndir.Multiplied (
626 (offsetValue * (6.0*Dr*Dr/R4 + 6.0*Dr*D2r/R4 - 15.0*Dr*Dr*Dr/R6 - D3r))));
627 D3Ndir.Multiply (offsetValue/R);
629 if(IsDirectionChange)
632 V3.Add (Vec2d(D3Ndir));
636 Standard_Real R4 = R2 * R2;
637 D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
638 D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
639 D2Ndir.Multiply (offsetValue / R);
640 V2.Add (Vec2d(D2Ndir));
643 DNdir.Subtract (Ndir.Multiplied (Dr/R));
644 DNdir.Multiply (offsetValue/R2);
645 theV1.Add (Vec2d(DNdir));
649 // Same computation as IICURV in EUCLID-IS because the stability is
652 D3Ndir.Multiply (offsetValue/R);
653 D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R3));
654 D3Ndir.Subtract (DNdir.Multiplied (
655 ((3.0 * offsetValue) * ((D2r/R3) + (Dr*Dr)/R5))) );
656 D3Ndir.Add (Ndir.Multiplied (
657 (offsetValue * (6.0*Dr*Dr/R5 + 6.0*Dr*D2r/R5 - 15.0*Dr*Dr*Dr/R7 - D3r))));
659 if(IsDirectionChange)
662 V3.Add (Vec2d(D3Ndir));
665 D2Ndir.Multiply (offsetValue/R);
666 D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
667 D2Ndir.Subtract (Ndir.Multiplied (
668 offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))));
669 V2.Add (Vec2d(D2Ndir));
671 DNdir.Multiply (offsetValue/R);
672 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
673 theV1.Add (Vec2d(DNdir));
679 //=======================================================================
682 //=======================================================================
684 Vec2d Geom2d_OffsetCurve::DN (const Standard_Real U,
685 const Standard_Integer N) const
687 Standard_RangeError_Raise_if (N < 1, "Exception: Geom2d_OffsetCurve::DN(). N<1.");
692 case 1: D1( U, PBidon, VN); break;
693 case 2: D2( U, PBidon, VBidon, VN); break;
694 case 3: D3( U, PBidon, VBidon, VBidon, VN); break;
696 Standard_NotImplemented::Raise("Exception: Derivative order is greater than 3. "
697 "Cannot compute of derivative.");
704 //=======================================================================
707 //=======================================================================
709 void Geom2d_OffsetCurve::Value (const Standard_Real theU,
710 Pnt2d& theP, Pnt2d& thePbasis,
711 Vec2d& theV1basis ) const
713 basisCurve->D1(theU, thePbasis, theV1basis);
718 //=======================================================================
721 //=======================================================================
723 void Geom2d_OffsetCurve::D1 (const Standard_Real U,
724 Pnt2d& P, Pnt2d& Pbasis,
725 Vec2d& V1, Vec2d& V1basis,
726 Vec2d& V2basis ) const
728 // P(u) = p(u) + Offset * Ndir / R
729 // with R = || p' ^ Z|| and Ndir = P' ^ Z
731 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
733 basisCurve->D2 (U, Pbasis, V1basis, V2basis);
736 Standard_Integer Index = 2;
737 while (V1.Magnitude() <= gp::Resolution() && Index <= maxDerivOrder) {
738 V1 = basisCurve->DN (U, Index);
742 V2 = basisCurve->DN (U, Index);
744 XY Ndir (V1.Y(), -V1.X());
745 XY DNdir (V2.Y(), -V2.X());
746 Standard_Real R2 = Ndir.SquareModulus();
747 Standard_Real R = Sqrt (R2);
748 Standard_Real R3 = R * R2;
749 Standard_Real Dr = Ndir.Dot (DNdir);
750 if (R3 <= gp::Resolution()) {
751 //We try another computation but the stability is not very good.
752 if (R2 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
754 DNdir.Subtract (Ndir.Multiplied (Dr/R));
755 DNdir.Multiply (offsetValue / R2);
756 V1.Add (Vec2d(DNdir));
759 // Same computation as IICURV in EUCLID-IS because the stability is
761 DNdir.Multiply (offsetValue/R);
762 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
763 V1.Add (Vec2d(DNdir));
765 Ndir.Multiply (offsetValue/R);
766 Ndir.Add (Pbasis.XY());
771 //=======================================================================
774 //=======================================================================
776 void Geom2d_OffsetCurve::D2 (const Standard_Real U,
777 Pnt2d& P, Pnt2d& Pbasis,
778 Vec2d& V1, Vec2d& V2,
779 Vec2d& V1basis, Vec2d& V2basis,
780 Vec2d& V3basis ) const
782 // P(u) = p(u) + Offset * Ndir / R
783 // with R = || p' ^ Z|| and Ndir = P' ^ Z
785 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
787 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
788 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
790 basisCurve->D3 (U, Pbasis, V1basis, V2basis, V3basis);
791 Standard_Integer Index = 2;
795 while (V1.Magnitude() <= gp::Resolution() && Index <= maxDerivOrder) {
796 V1 = basisCurve->DN (U, Index);
800 V2 = basisCurve->DN (U, Index);
801 V3 = basisCurve->DN (U, Index + 1);
803 XY Ndir (V1.Y(), -V1.X());
804 XY DNdir (V2.Y(), -V2.X());
805 XY D2Ndir (V3.Y(), -V3.X());
806 Standard_Real R2 = Ndir.SquareModulus();
807 Standard_Real R = Sqrt (R2);
808 Standard_Real R3 = R2 * R;
809 Standard_Real R4 = R2 * R2;
810 Standard_Real R5 = R3 * R2;
811 Standard_Real Dr = Ndir.Dot (DNdir);
812 Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
813 if (R5 <= gp::Resolution()) {
814 //We try another computation but the stability is not very good
816 if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
818 Standard_Real R4 = R2 * R2;
819 D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
820 D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
821 D2Ndir.Multiply (offsetValue / R);
822 V2.Add (Vec2d(D2Ndir));
825 DNdir.Subtract (Ndir.Multiplied (Dr/R));
826 DNdir.Multiply (offsetValue/R2);
827 V1.Add (Vec2d(DNdir));
830 // Same computation as IICURV in EUCLID-IS because the stability is
833 D2Ndir.Multiply (offsetValue/R);
834 D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
835 D2Ndir.Subtract (Ndir.Multiplied (
836 offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
839 V2.Add (Vec2d(D2Ndir));
841 DNdir.Multiply (offsetValue/R);
842 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
843 V1.Add (Vec2d(DNdir));
846 Ndir.Multiply (offsetValue/R);
847 Ndir.Add (Pbasis.XY());
851 //=======================================================================
852 //function : FirstParameter
854 //=======================================================================
856 Standard_Real Geom2d_OffsetCurve::FirstParameter () const
858 return basisCurve->FirstParameter();
861 //=======================================================================
862 //function : LastParameter
864 //=======================================================================
866 Standard_Real Geom2d_OffsetCurve::LastParameter () const
868 return basisCurve->LastParameter();
872 //=======================================================================
875 //=======================================================================
877 Standard_Real Geom2d_OffsetCurve::Offset () const { return offsetValue; }
879 //=======================================================================
880 //function : IsClosed
882 //=======================================================================
884 Standard_Boolean Geom2d_OffsetCurve::IsClosed () const
887 D0(FirstParameter(),PF);
888 D0(LastParameter(),PL);
889 return ( PF.Distance(PL) <= gp::Resolution());
892 //=======================================================================
895 //=======================================================================
897 Standard_Boolean Geom2d_OffsetCurve::IsCN (const Standard_Integer N) const
899 Standard_RangeError_Raise_if (N < 0, " " );
900 return basisCurve->IsCN (N + 1);
903 //=======================================================================
904 //function : IsPeriodic
906 //=======================================================================
908 Standard_Boolean Geom2d_OffsetCurve::IsPeriodic () const
910 return basisCurve->IsPeriodic();
913 //=======================================================================
916 //=======================================================================
918 Standard_Real Geom2d_OffsetCurve::Period() const
920 return basisCurve->Period();
923 //=======================================================================
924 //function : Transform
926 //=======================================================================
928 void Geom2d_OffsetCurve::Transform (const Trsf2d& T)
930 basisCurve->Transform (T);
931 offsetValue *= Abs(T.ScaleFactor());
935 //=======================================================================
936 //function : TransformedParameter
938 //=======================================================================
940 Standard_Real Geom2d_OffsetCurve::TransformedParameter(const Standard_Real U,
941 const gp_Trsf2d& T) const
943 return basisCurve->TransformedParameter(U,T);
946 //=======================================================================
947 //function : ParametricTransformation
949 //=======================================================================
951 Standard_Real Geom2d_OffsetCurve::ParametricTransformation(const gp_Trsf2d& T) const
953 return basisCurve->ParametricTransformation(T);
956 //=======================================================================
957 //function : GetBasisCurveContinuity
959 //=======================================================================
960 GeomAbs_Shape Geom2d_OffsetCurve::GetBasisCurveContinuity() const
962 return myBasisCurveContinuity;