1 // File: Geom2d_OffsetCurve.cxx
2 // Created: Wed Mar 24 19:23:58 1993
5 // Copyright: Matra Datavision 1993
7 // File: Geom2d_OffsetCurve.cxx
8 // Created: Tue Jun 25 15:36:30 1991
11 // modified by Edward AGAPOV (eap) Jan 28 2002 --- DN(), occ143(BUC60654)
15 #include <Geom2d_OffsetCurve.ixx>
17 #include <Standard_ConstructionError.hxx>
18 #include <Standard_RangeError.hxx>
19 #include <Standard_NotImplemented.hxx>
20 #include <Geom2d_UndefinedDerivative.hxx>
21 #include <Geom2d_UndefinedValue.hxx>
22 #include <Geom2d_Line.hxx>
23 #include <Geom2d_Circle.hxx>
24 #include <Geom2d_Ellipse.hxx>
25 #include <Geom2d_Hyperbola.hxx>
26 #include <Geom2d_Parabola.hxx>
27 #include <Geom2d_BezierCurve.hxx>
28 #include <Geom2d_BSplineCurve.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
32 typedef Handle(Geom2d_OffsetCurve) Handle(OffsetCurve);
33 typedef Geom2d_OffsetCurve OffsetCurve;
34 typedef Handle(Geom2d_Geometry) Handle(Geometry);
35 typedef Handle(Geom2d_Curve) Handle(Curve);
36 typedef Geom2d_Curve Curve;
37 typedef gp_Dir2d Dir2d;
38 typedef gp_Pnt2d Pnt2d;
39 typedef gp_Vec2d Vec2d;
40 typedef gp_Trsf2d Trsf2d;
45 static const int MaxDegree = 9;
46 //ordre de derivation maximum pour la recherche de la premiere
51 //=======================================================================
54 //=======================================================================
56 Handle(Geom2d_Geometry) Geom2d_OffsetCurve::Copy () const
58 Handle(OffsetCurve) C;
59 C = new OffsetCurve (basisCurve, offsetValue);
64 //=======================================================================
65 //function : Geom2d_OffsetCurve
67 //=======================================================================
69 Geom2d_OffsetCurve::Geom2d_OffsetCurve (const Handle(Curve)& C,
70 const Standard_Real Offset)
71 : offsetValue (Offset)
73 if (C->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)) {
74 Handle(OffsetCurve) OC = Handle(OffsetCurve)::DownCast(C->Copy());
75 if ((OC->BasisCurve())->Continuity() == GeomAbs_C0)
76 Standard_ConstructionError::Raise();
78 basisCurve = Handle(Curve)::DownCast((OC->BasisCurve())->Copy());
79 offsetValue += OC->Offset();
81 if (C->Continuity() == GeomAbs_C0)
82 Standard_ConstructionError::Raise();
84 basisCurve = Handle(Curve)::DownCast(C->Copy());
88 //=======================================================================
91 //=======================================================================
93 void Geom2d_OffsetCurve::Reverse ()
95 basisCurve->Reverse();
96 offsetValue = -offsetValue;
99 //=======================================================================
100 //function : ReversedParameter
102 //=======================================================================
104 Standard_Real Geom2d_OffsetCurve::ReversedParameter( const Standard_Real U) const
106 return basisCurve->ReversedParameter( U);
109 //=======================================================================
110 //function : SetBasisCurve
112 //=======================================================================
114 void Geom2d_OffsetCurve::SetBasisCurve (const Handle(Curve)& C)
116 if (C->Continuity() == GeomAbs_C0) Standard_ConstructionError::Raise();
117 basisCurve = Handle(Geom2d_Curve)::DownCast(C->Copy());
120 //=======================================================================
121 //function : SetOffsetValue
123 //=======================================================================
125 void Geom2d_OffsetCurve::SetOffsetValue (const Standard_Real D) { offsetValue = D; }
127 //=======================================================================
128 //function : BasisCurve
130 //=======================================================================
132 Handle(Curve) Geom2d_OffsetCurve::BasisCurve () const
137 //=======================================================================
138 //function : Continuity
140 //=======================================================================
142 GeomAbs_Shape Geom2d_OffsetCurve::Continuity () const
144 GeomAbs_Shape OffsetShape=GeomAbs_C0;
145 switch (basisCurve->Continuity()) {
146 case GeomAbs_C0 : OffsetShape = GeomAbs_C0; break;
147 case GeomAbs_C1 : OffsetShape = GeomAbs_C0; break;
148 case GeomAbs_C2 : OffsetShape = GeomAbs_C1; break;
149 case GeomAbs_C3 : OffsetShape = GeomAbs_C2; break;
150 case GeomAbs_CN : OffsetShape = GeomAbs_CN; break;
151 case GeomAbs_G1 : OffsetShape = GeomAbs_G1; break;
152 case GeomAbs_G2 : OffsetShape = GeomAbs_G2; break;
157 //=======================================================================
160 //=======================================================================
162 void Geom2d_OffsetCurve::D0 (const Standard_Real U,
167 basisCurve->D1 (U, P, V1);
168 Standard_Integer Index = 2;
169 while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
170 V1 = basisCurve->DN (U, Index);
173 Standard_Real A = V1.Y();
174 Standard_Real B = - V1.X();
175 Standard_Real R = Sqrt(A*A + B * B);
176 if (R <= gp::Resolution()) Geom2d_UndefinedValue::Raise();
177 A = A * offsetValue/R;
178 B = B * offsetValue/R;
179 P.SetCoord(P.X() + A, P.Y() + B);
182 //=======================================================================
185 //=======================================================================
187 void Geom2d_OffsetCurve::D1 (const Standard_Real U, Pnt2d& P, Vec2d& V1) const {
189 // P(u) = p(u) + Offset * Ndir / R
190 // with R = || p' ^ Z|| and Ndir = P' ^ Z
192 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
196 GeomAbs_Shape Continuity = basisCurve->Continuity();
198 basisCurve->Continuity();
201 basisCurve->D2 (U, P, V1, V2);
202 Standard_Integer Index = 2;
203 while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
204 V1 = basisCurve->DN (U, Index);
207 if (Index != 2) { V2 = basisCurve->DN (U, Index); }
208 XY Ndir (V1.Y(), -V1.X());
209 XY DNdir (V2.Y(), -V2.X());
210 Standard_Real R2 = Ndir.SquareModulus();
211 Standard_Real R = Sqrt (R2);
212 Standard_Real R3 = R * R2;
213 Standard_Real Dr = Ndir.Dot (DNdir);
214 if (R3 <= gp::Resolution()) {
215 //We try another computation but the stability is not very good.
216 if (R2 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
218 DNdir.Subtract (Ndir.Multiplied (Dr/R));
219 DNdir.Multiply (offsetValue/R2);
220 V1.Add (Vec2d(DNdir));
223 // Same computation as IICURV in EUCLID-IS because the stability is
225 DNdir.Multiply (offsetValue/R);
226 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
227 V1.Add (Vec2d(DNdir));
229 Ndir.Multiply (offsetValue/R);
234 //=======================================================================
237 //=======================================================================
239 void Geom2d_OffsetCurve::D2 (const Standard_Real U,
241 Vec2d& V1, Vec2d& V2) const
243 // P(u) = p(u) + Offset * Ndir / R
244 // with R = || p' ^ Z|| and Ndir = P' ^ Z
246 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
248 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
249 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
252 GeomAbs_Shape Continuity = basisCurve->Continuity();
254 basisCurve->Continuity();
257 basisCurve->D3 (U, P, V1, V2, V3);
258 Standard_Integer Index = 2;
259 while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
260 V1 = basisCurve->DN (U, Index);
264 V2 = basisCurve->DN (U, Index);
265 V3 = basisCurve->DN (U, Index + 1);
267 XY Ndir (V1.Y(), -V1.X());
268 XY DNdir (V2.Y(), -V2.X());
269 XY D2Ndir (V3.Y(), -V3.X());
270 Standard_Real R2 = Ndir.SquareModulus();
271 Standard_Real R = Sqrt (R2);
272 Standard_Real R3 = R2 * R;
273 Standard_Real R4 = R2 * R2;
274 Standard_Real R5 = R3 * R2;
275 Standard_Real Dr = Ndir.Dot (DNdir);
276 Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
277 if (R5 <= gp::Resolution()) {
278 //We try another computation but the stability is not very good
280 if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
282 Standard_Real R4 = R2 * R2;
283 D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
284 D2Ndir.Add (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
285 D2Ndir.Multiply (offsetValue / R);
286 V2.Add (Vec2d(D2Ndir));
289 DNdir.Subtract (Ndir.Multiplied (Dr/R));
290 DNdir.Multiply (offsetValue/R2);
291 V1.Add (Vec2d(DNdir));
294 // Same computation as IICURV in EUCLID-IS because the stability is
297 D2Ndir.Multiply (offsetValue/R);
298 D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
299 D2Ndir.Add (Ndir.Multiplied
300 (offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))));
301 V2.Add (Vec2d(D2Ndir));
303 DNdir.Multiply (offsetValue/R);
304 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
305 V1.Add (Vec2d(DNdir));
308 Ndir.Multiply (offsetValue/R);
314 //=======================================================================
317 //=======================================================================
319 void Geom2d_OffsetCurve::D3 (const Standard_Real U,
321 Vec2d& V1, Vec2d& V2, Vec2d& V3) const {
324 // P(u) = p(u) + Offset * Ndir / R
325 // with R = || p' ^ Z|| and Ndir = P' ^ Z
327 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
329 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
330 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
332 //P"'(u) = p"'(u) + (Offset / R) * (D3Ndir - (3.0 * Dr/R**2 ) * D2Ndir -
333 // (3.0 * D2r / R2) * DNdir) + (3.0 * Dr * Dr / R4) * DNdir -
334 // (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
335 // (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
339 basisCurve->D3 (U, P, V1, V2, V3);
340 Vec2d V4 = basisCurve->DN (U, 4);
341 Standard_Integer Index = 2;
342 while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
343 V1 = basisCurve->DN (U, Index);
347 V2 = basisCurve->DN (U, Index);
348 V3 = basisCurve->DN (U, Index + 1);
349 V4 = basisCurve->DN (U, Index + 2);
351 XY Ndir (V1.Y(), -V1.X());
352 XY DNdir (V2.Y(), -V2.X());
353 XY D2Ndir (V3.Y(), -V3.X());
354 XY D3Ndir (V4.Y(), -V4.X());
355 Standard_Real R2 = Ndir.SquareModulus();
356 Standard_Real R = Sqrt (R2);
357 Standard_Real R3 = R2 * R;
358 Standard_Real R4 = R2 * R2;
359 Standard_Real R5 = R3 * R2;
360 Standard_Real R6 = R3 * R3;
361 Standard_Real R7 = R5 * R2;
362 Standard_Real Dr = Ndir.Dot (DNdir);
363 Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
364 Standard_Real D3r = Ndir.Dot (D3Ndir) + 3.0 * DNdir.Dot (D2Ndir);
365 if (R7 <= gp::Resolution()) {
366 //We try another computation but the stability is not very good
368 if (R6 <= gp::Resolution()) Geom2d_UndefinedDerivative::Raise();
370 D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R2));
372 (DNdir.Multiplied ((3.0 * offsetValue) * ((D2r/R2) + (Dr*Dr)/R4))));
373 D3Ndir.Add (Ndir.Multiplied (
374 (offsetValue * (6.0*Dr*Dr/R4 + 6.0*Dr*D2r/R4 - 15.0*Dr*Dr*Dr/R6 - D3r))
376 D3Ndir.Multiply (offsetValue/R);
377 V3.Add (Vec2d(D3Ndir));
379 Standard_Real R4 = R2 * R2;
380 D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
381 D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
382 D2Ndir.Multiply (offsetValue / R);
383 V2.Add (Vec2d(D2Ndir));
386 DNdir.Subtract (Ndir.Multiplied (Dr/R));
387 DNdir.Multiply (offsetValue/R2);
388 V1.Add (Vec2d(DNdir));
391 // Same computation as IICURV in EUCLID-IS because the stability is
394 D3Ndir.Multiply (offsetValue/R);
395 D3Ndir.Subtract (D2Ndir.Multiplied (3.0 * offsetValue * Dr / R3));
396 D3Ndir.Subtract (DNdir.Multiplied (
397 ((3.0 * offsetValue) * ((D2r/R3) + (Dr*Dr)/R5))) );
398 D3Ndir.Add (Ndir.Multiplied (
399 (offsetValue * (6.0*Dr*Dr/R5 + 6.0*Dr*D2r/R5 - 15.0*Dr*Dr*Dr/R7 - D3r))
401 V3.Add (Vec2d(D3Ndir));
403 D2Ndir.Multiply (offsetValue/R);
404 D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
405 D2Ndir.Subtract (Ndir.Multiplied (
406 offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
409 V2.Add (Vec2d(D2Ndir));
411 DNdir.Multiply (offsetValue/R);
412 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
413 V1.Add (Vec2d(DNdir));
416 Ndir.Multiply (offsetValue/R);
421 //=======================================================================
424 //=======================================================================
426 Vec2d Geom2d_OffsetCurve::DN (const Standard_Real U,
427 const Standard_Integer N) const
429 Standard_RangeError_Raise_if (N < 1, "Geom2d_OffsetCurve::DN()");
434 case 1: D1( U, PBidon, VN); break;
435 case 2: D2( U, PBidon, VBidon, VN); break;
436 case 3: D3( U, PBidon, VBidon, VBidon, VN); break;
438 Standard_NotImplemented::Raise();
445 //=======================================================================
448 //=======================================================================
450 void Geom2d_OffsetCurve::Value (const Standard_Real U,
451 Pnt2d& P, Pnt2d& Pbasis,
452 Vec2d& V1basis ) const
455 basisCurve->D1 (U, Pbasis, V1basis);
456 Standard_Integer Index = 2;
457 while (V1basis.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
458 V1basis = basisCurve->DN (U, Index);
461 Standard_Real A = V1basis.Y();
462 Standard_Real B = - V1basis.X();
463 Standard_Real R = Sqrt(A*A + B * B);
464 if (R <= gp::Resolution()) Geom2d_UndefinedValue::Raise();
465 A = A * offsetValue/R;
466 B = B * offsetValue/R;
467 P.SetCoord (A + Pbasis.X(), B + Pbasis.Y());
471 //=======================================================================
474 //=======================================================================
476 void Geom2d_OffsetCurve::D1 (const Standard_Real U,
477 Pnt2d& P, Pnt2d& Pbasis,
478 Vec2d& V1, Vec2d& V1basis,
479 Vec2d& V2basis ) const
481 // P(u) = p(u) + Offset * Ndir / R
482 // with R = || p' ^ Z|| and Ndir = P' ^ Z
484 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
487 GeomAbs_Shape Continuity = basisCurve->Continuity();
489 basisCurve->Continuity();
492 basisCurve->D2 (U, Pbasis, V1basis, V2basis);
495 Standard_Integer Index = 2;
496 while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
497 V1 = basisCurve->DN (U, Index);
501 V2 = basisCurve->DN (U, Index);
503 XY Ndir (V1.Y(), -V1.X());
504 XY DNdir (V2.Y(), -V2.X());
505 Standard_Real R2 = Ndir.SquareModulus();
506 Standard_Real R = Sqrt (R2);
507 Standard_Real R3 = R * R2;
508 Standard_Real Dr = Ndir.Dot (DNdir);
509 if (R3 <= gp::Resolution()) {
510 //We try another computation but the stability is not very good.
511 if (R2 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
513 DNdir.Subtract (Ndir.Multiplied (Dr/R));
514 DNdir.Multiply (offsetValue / R2);
515 V1.Add (Vec2d(DNdir));
518 // Same computation as IICURV in EUCLID-IS because the stability is
520 DNdir.Multiply (offsetValue/R);
521 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
522 V1.Add (Vec2d(DNdir));
524 Ndir.Multiply (offsetValue/R);
525 Ndir.Add (Pbasis.XY());
530 //=======================================================================
533 //=======================================================================
535 void Geom2d_OffsetCurve::D2 (const Standard_Real U,
536 Pnt2d& P, Pnt2d& Pbasis,
537 Vec2d& V1, Vec2d& V2,
538 Vec2d& V1basis, Vec2d& V2basis,
539 Vec2d& V3basis ) const
541 // P(u) = p(u) + Offset * Ndir / R
542 // with R = || p' ^ Z|| and Ndir = P' ^ Z
544 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
546 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
547 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
550 GeomAbs_Shape Continuity = basisCurve->Continuity();
552 basisCurve->Continuity();
555 basisCurve->D3 (U, Pbasis, V1basis, V2basis, V3basis);
556 Standard_Integer Index = 2;
560 while (V1.Magnitude() <= gp::Resolution() && Index <= MaxDegree) {
561 V1 = basisCurve->DN (U, Index);
565 V2 = basisCurve->DN (U, Index);
566 V3 = basisCurve->DN (U, Index + 1);
568 XY Ndir (V1.Y(), -V1.X());
569 XY DNdir (V2.Y(), -V2.X());
570 XY D2Ndir (V3.Y(), -V3.X());
571 Standard_Real R2 = Ndir.SquareModulus();
572 Standard_Real R = Sqrt (R2);
573 Standard_Real R3 = R2 * R;
574 Standard_Real R4 = R2 * R2;
575 Standard_Real R5 = R3 * R2;
576 Standard_Real Dr = Ndir.Dot (DNdir);
577 Standard_Real D2r = Ndir.Dot (D2Ndir) + DNdir.Dot (DNdir);
578 if (R5 <= gp::Resolution()) {
579 //We try another computation but the stability is not very good
581 if (R4 <= gp::Resolution()) { Geom2d_UndefinedDerivative::Raise(); }
583 Standard_Real R4 = R2 * R2;
584 D2Ndir.Subtract (DNdir.Multiplied (2.0 * Dr / R2));
585 D2Ndir.Subtract (Ndir.Multiplied (((3.0 * Dr * Dr)/R4) - (D2r/R2)));
586 D2Ndir.Multiply (offsetValue / R);
587 V2.Add (Vec2d(D2Ndir));
590 DNdir.Subtract (Ndir.Multiplied (Dr/R));
591 DNdir.Multiply (offsetValue/R2);
592 V1.Add (Vec2d(DNdir));
595 // Same computation as IICURV in EUCLID-IS because the stability is
598 D2Ndir.Multiply (offsetValue/R);
599 D2Ndir.Subtract (DNdir.Multiplied (2.0 * offsetValue * Dr / R3));
600 D2Ndir.Subtract (Ndir.Multiplied (
601 offsetValue * (((3.0 * Dr * Dr) / R5) - (D2r / R3))
604 V2.Add (Vec2d(D2Ndir));
606 DNdir.Multiply (offsetValue/R);
607 DNdir.Subtract (Ndir.Multiplied (offsetValue*Dr/R3));
608 V1.Add (Vec2d(DNdir));
611 Ndir.Multiply (offsetValue/R);
612 Ndir.Add (Pbasis.XY());
616 //=======================================================================
617 //function : FirstParameter
619 //=======================================================================
621 Standard_Real Geom2d_OffsetCurve::FirstParameter () const
623 return basisCurve->FirstParameter();
626 //=======================================================================
627 //function : LastParameter
629 //=======================================================================
631 Standard_Real Geom2d_OffsetCurve::LastParameter () const
633 return basisCurve->LastParameter();
637 //=======================================================================
640 //=======================================================================
642 Standard_Real Geom2d_OffsetCurve::Offset () const { return offsetValue; }
644 //=======================================================================
645 //function : IsClosed
647 //=======================================================================
649 Standard_Boolean Geom2d_OffsetCurve::IsClosed () const
652 D0(FirstParameter(),PF);
653 D0(LastParameter(),PL);
654 return ( PF.Distance(PL) <= gp::Resolution());
657 //=======================================================================
660 //=======================================================================
662 Standard_Boolean Geom2d_OffsetCurve::IsCN (const Standard_Integer N) const
664 Standard_RangeError_Raise_if (N < 0, " " );
665 return basisCurve->IsCN (N + 1);
668 //=======================================================================
669 //function : IsPeriodic
671 //=======================================================================
673 Standard_Boolean Geom2d_OffsetCurve::IsPeriodic () const
675 return basisCurve->IsPeriodic();
678 //=======================================================================
681 //=======================================================================
683 Standard_Real Geom2d_OffsetCurve::Period() const
685 return basisCurve->Period();
688 //=======================================================================
689 //function : Transform
691 //=======================================================================
693 void Geom2d_OffsetCurve::Transform (const Trsf2d& T)
695 basisCurve->Transform (T);
696 offsetValue *= Abs(T.ScaleFactor());
700 //=======================================================================
701 //function : TransformedParameter
703 //=======================================================================
705 Standard_Real Geom2d_OffsetCurve::TransformedParameter(const Standard_Real U,
706 const gp_Trsf2d& T) const
708 return basisCurve->TransformedParameter(U,T);
711 //=======================================================================
712 //function : ParametricTransformation
714 //=======================================================================
716 Standard_Real Geom2d_OffsetCurve::ParametricTransformation(const gp_Trsf2d& T) const
718 return basisCurve->ParametricTransformation(T);