0031260: Geom2dGcc_Circ2d2TanRad fails in this case (720)
[occt.git] / src / Adaptor2d / Adaptor2d_OffsetCurve.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 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
973c2be1 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.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14
42cf5bc1 15#include <Adaptor2d_HCurve2d.hxx>
5201d3e6 16#include <Adaptor2d_HOffsetCurve.hxx>
17#include <Adaptor2d_OffsetCurve.hxx>
42cf5bc1 18#include <Geom2d_BezierCurve.hxx>
19#include <Geom2d_BSplineCurve.hxx>
7fd59977 20#include <GeomAbs_SurfaceType.hxx>
42cf5bc1 21#include <gp.hxx>
7fd59977 22#include <gp_Ax22d.hxx>
42cf5bc1 23#include <gp_Circ2d.hxx>
7fd59977 24#include <gp_Dir2d.hxx>
42cf5bc1 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>
7fd59977 38
39//=======================================================================
5201d3e6 40//function : Adaptor2d_OffsetCurve
7fd59977 41//purpose :
42//=======================================================================
5201d3e6 43Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve()
cbff1e55 44: myOffset(0.0),
45 myFirst (0.0),
46 myLast (0.0)
47{
48}
7fd59977 49
50//=======================================================================
5201d3e6 51//function : Adaptor2d_OffsetCurve
7fd59977 52//purpose :
53//=======================================================================
54
5201d3e6 55Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve(const Handle(Adaptor2d_HCurve2d)& theCurve)
cbff1e55 56: myCurve (theCurve),
57 myOffset(0.0),
58 myFirst (0.0),
59 myLast (0.0)
7fd59977 60{
7fd59977 61}
62
63//=======================================================================
5201d3e6 64//function : Adaptor2d_OffsetCurve
7fd59977 65//purpose :
66//=======================================================================
67
5201d3e6 68Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve
cbff1e55 69 (const Handle(Adaptor2d_HCurve2d)& theCurve, const Standard_Real theOffset)
70: myCurve (theCurve),
71 myOffset(theOffset),
72 myFirst (theCurve->FirstParameter()),
73 myLast (theCurve->LastParameter())
7fd59977 74{
7fd59977 75}
76
77//=======================================================================
5201d3e6 78//function : Adaptor2d_OffsetCurve
7fd59977 79//purpose :
80//=======================================================================
81
5201d3e6 82Adaptor2d_OffsetCurve::Adaptor2d_OffsetCurve(
cbff1e55 83 const Handle(Adaptor2d_HCurve2d)& theCurve,
84 const Standard_Real theOffset,
85 const Standard_Real theWFirst,
86 const Standard_Real theWLast )
87: myCurve (theCurve),
88 myOffset(theOffset),
89 myFirst (theWFirst),
90 myLast (theWLast)
7fd59977 91{
7fd59977 92}
93
94//=======================================================================
95//function : Load
96//purpose :
97//=======================================================================
98
5201d3e6 99void Adaptor2d_OffsetCurve::Load(const Handle(Adaptor2d_HCurve2d)& C )
7fd59977 100{
101 myCurve = C;
102 myOffset = 0.;
103}
104
105//=======================================================================
106//function : Load
107//purpose :
108//=======================================================================
109
5201d3e6 110void Adaptor2d_OffsetCurve::Load( const Standard_Real Offset)
7fd59977 111{
112 myOffset = Offset;
113 myFirst = myCurve->FirstParameter();
114 myLast = myCurve->LastParameter();
115
116}
117
118//=======================================================================
119//function : Load
120//purpose :
121//=======================================================================
122
5201d3e6 123void Adaptor2d_OffsetCurve::Load(const Standard_Real Offset,
cbff1e55 124 const Standard_Real WFirst,
125 const Standard_Real WLast)
7fd59977 126{
127 myOffset = Offset;
128 myFirst = WFirst;
129 myLast = WLast;
130}
131
132//=======================================================================
133//function : Continuity
134//purpose :
135//=======================================================================
136
5201d3e6 137GeomAbs_Shape Adaptor2d_OffsetCurve::Continuity() const
7fd59977 138{
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;
146 case GeomAbs_C0:
147// No Continuity !!
9775fa61 148 throw Standard_TypeMismatch("Adaptor2d_OffsetCurve::IntervalContinuity");
7fd59977 149 break;
150 }
151
152 //portage WNT
153 return GeomAbs_C0;
154}
155
156//=======================================================================
157//function : NbIntervals
158//purpose :
159//=======================================================================
160
5201d3e6 161Standard_Integer Adaptor2d_OffsetCurve::NbIntervals(const GeomAbs_Shape S) const
7fd59977 162{
163 GeomAbs_Shape Sh;
164 if ( S >= GeomAbs_C2) Sh = GeomAbs_CN;
165 else
166 Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
167
168 Standard_Integer nbInter = myCurve->NbIntervals(Sh);
169
170 if(nbInter == 1) return nbInter;
171
172 TColStd_Array1OfReal T(1,nbInter+1);
173
174 myCurve->Intervals(T,Sh);
175
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);
181}
182
183//=======================================================================
184//function : Intervals
185//purpose :
186//=======================================================================
187
5201d3e6 188void Adaptor2d_OffsetCurve::Intervals(TColStd_Array1OfReal& TI,
7fd59977 189 const GeomAbs_Shape S) const
190{
191 GeomAbs_Shape Sh;
192 if ( S >= GeomAbs_C2) Sh = GeomAbs_CN;
193 else
194 Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
195
196 Standard_Integer nbInter = myCurve->NbIntervals(Sh);
197
198
199 if(nbInter == 1) {
200 TI(TI.Lower()) = myFirst ;
201 TI(TI.Lower() + 1) = myLast ;
202 return;
203 }
204
205 TColStd_Array1OfReal T(1,nbInter+1);
206 myCurve->Intervals(T,Sh);
207
208 Standard_Integer first = 1;
209 while (T(first) <= myFirst) first++;
210 Standard_Integer last = nbInter+1;
211 while (T(last) >= myLast) last--;
212
213 Standard_Integer i = TI.Lower(), j;
214 for (j = first-1; j <= last+1; j++) {
215 TI(i) = T(j);
216 i++;
217 }
218
219 TI(TI.Lower()) = myFirst ;
220 TI(TI.Lower() + last-first + 2) = myLast ;
221
222}
223
224
225//=======================================================================
226//function : Trim
227//purpose :
228//=======================================================================
229
5201d3e6 230Handle(Adaptor2d_HCurve2d) Adaptor2d_OffsetCurve::Trim
7fd59977 231(const Standard_Real First,
232 const Standard_Real Last,
233 const Standard_Real) const
234{
5201d3e6 235 Handle(Adaptor2d_HOffsetCurve) HO = new Adaptor2d_HOffsetCurve(*this);
7fd59977 236 HO->ChangeCurve2d().Load(myOffset,First,Last);
237 return HO;
238}
239
240
241//=======================================================================
242//function : IsClosed
243//purpose :
244//=======================================================================
245
5201d3e6 246Standard_Boolean Adaptor2d_OffsetCurve::IsClosed() const
7fd59977 247{
248 if ( myOffset == 0.) {
249 return myCurve->IsClosed();
250 }
251 else {
252 if (myCurve->Continuity() == GeomAbs_C0)
253 return Standard_False;
254 else {
255 if ( myCurve->IsClosed()) {
256 gp_Vec2d Dummy[2];
257 gp_Pnt2d P;
258 myCurve->D1
259 (myCurve->FirstParameter(),P,Dummy[0]);
260 myCurve->D1
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;
265 else
266 return Standard_False;
267 }
268 else
269 return Standard_False;
270 }
271 }
272}
273
274//=======================================================================
275//function : IsPeriodic
276//purpose :
277//=======================================================================
278
5201d3e6 279Standard_Boolean Adaptor2d_OffsetCurve::IsPeriodic() const
7fd59977 280{
281 return myCurve->IsPeriodic();
282}
283
284//=======================================================================
285//function : Period
286//purpose :
287//=======================================================================
288
5201d3e6 289Standard_Real Adaptor2d_OffsetCurve::Period() const
7fd59977 290{
291 return myCurve->Period();
292}
293
294//=======================================================================
295//function : Value
296//purpose :
297//=======================================================================
298
5201d3e6 299gp_Pnt2d Adaptor2d_OffsetCurve::Value(const Standard_Real U) const
7fd59977 300{
301 if ( myOffset != 0.) {
302 gp_Pnt2d P;
303 gp_Vec2d V;
304 Standard_Real Norme;
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);
310 }
311 else {
9775fa61 312 throw gp_VectorWithNullMagnitude("Adaptor2d_OffsetCurve::Value");
7fd59977 313 }
314 }
315 else {
316 return myCurve->Value(U);
317 }
318}
319
320//=======================================================================
321//function : D0
322//purpose :
323//=======================================================================
324
5201d3e6 325void Adaptor2d_OffsetCurve::D0(const Standard_Real U, gp_Pnt2d& P) const
7fd59977 326{
327 P = Value( U);
328}
329
330//=======================================================================
331//function : D1
332//purpose :
333//=======================================================================
334
5201d3e6 335void Adaptor2d_OffsetCurve::D1
7fd59977 336 (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V) const
337{
338 gp_Vec2d V1,V2,V3;
339 gp_Pnt2d PP;
340 Standard_Real Norme;
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)));
351 }
352 else {
9775fa61 353 throw gp_VectorWithNullMagnitude("Adaptor2d_OffsetCurve::D1");
7fd59977 354 }
355 }
356 else {
357 myCurve->D1(U,P,V);
358 }
359}
360
361//=======================================================================
362//function : D2
363//purpose :
364//=======================================================================
365
5201d3e6 366void Adaptor2d_OffsetCurve::D2
7fd59977 367 (const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
368{
369 if ( myOffset != 0.) {
370 gp_Vec2d T1,T2,T3;
371 gp_Pnt2d PP;
372 Standard_Real Norme;
373 myCurve->D3(U,PP,T1,T2,T3);
374
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;
382 d12 = T1*T2;
383 d22 = T2*T2;
384 d13 = T1*T3;
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());
390
391 D1( U,P,V1);
392 }
393 else {
9775fa61 394 throw gp_VectorWithNullMagnitude("Adaptor2d_OffsetCurve::D2");
7fd59977 395 }
396 }
397 else {
398 myCurve->D2(U,P,V1,V2);
399 }
400}
401
402//=======================================================================
403//function : D3
404//purpose :
405//=======================================================================
406
5201d3e6 407//void Adaptor2d_OffsetCurve::D3
7fd59977 408// (const Standard_Real T,
409// gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2, gp_Vec2d& V3) const
5201d3e6 410void Adaptor2d_OffsetCurve::D3
7fd59977 411 (const Standard_Real ,
412 gp_Pnt2d& , gp_Vec2d& , gp_Vec2d& , gp_Vec2d& ) const
413{
9775fa61 414 throw Standard_NotImplemented("Adaptor2d_OffsetCurve::D3");
7fd59977 415}
416
417//=======================================================================
418//function : DN
419//purpose :
420//=======================================================================
421
5201d3e6 422gp_Vec2d Adaptor2d_OffsetCurve::DN
7fd59977 423// (const Standard_Real T, const Standard_Integer N) const
424 (const Standard_Real , const Standard_Integer ) const
425{
9775fa61 426 throw Standard_NotImplemented("Adaptor2d_OffsetCurve::DN");
7fd59977 427}
428
429
430//=======================================================================
431//function : Resolution
432//purpose :
433//=======================================================================
434
5201d3e6 435Standard_Real Adaptor2d_OffsetCurve::Resolution(const Standard_Real R3d) const
7fd59977 436{
437 return Precision::PConfusion(R3d);
438}
439
440
441//=======================================================================
442//function : GetType
443//purpose :
444//=======================================================================
445
5201d3e6 446GeomAbs_CurveType Adaptor2d_OffsetCurve::GetType() const {
7fd59977 447
448 if ( myOffset == 0.) {
449 return myCurve->GetType();
450 }
451 else {
452 switch (myCurve->GetType()) {
453
454 case GeomAbs_Line:
455 return GeomAbs_Line;
456
457 case GeomAbs_Circle:
458 return GeomAbs_Circle;
459
460 default:
833034f3 461 return GeomAbs_OffsetCurve;
7fd59977 462
463 }
464 }
465}
466
467//=======================================================================
468//function : Line
469//purpose :
470//=======================================================================
471
5201d3e6 472gp_Lin2d Adaptor2d_OffsetCurve::Line() const
7fd59977 473{
474 if ( GetType() == GeomAbs_Line) {
475 gp_Pnt2d P;
476 gp_Vec2d V;
477 D1(0,P,V);
478 return gp_Lin2d(P,V);
479 }
480 else {
9775fa61 481 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Line");
7fd59977 482 }
483}
484
485
486//=======================================================================
487//function : Circle
488//purpose :
489//=======================================================================
490
5201d3e6 491gp_Circ2d Adaptor2d_OffsetCurve::Circle() const
7fd59977 492{
493 if ( GetType() == GeomAbs_Circle) {
494 if (myOffset == 0.) {
495 return myCurve->Circle();
496 }
497 else {
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.;
505
506 radius += Signe*myOffset;
507 if ( radius > 0.) {
508 return gp_Circ2d( axes,radius);
509 }
510 else if ( radius < 0.) {
511 radius = - radius;
512 axes.SetXDirection( (axes.XDirection()).Reversed());
513 return gp_Circ2d( axes,radius);
514 }
515 else { // Cercle de rayon Nul
9775fa61 516 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
7fd59977 517 }
518 }
519 }
520 else {
9775fa61 521 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
7fd59977 522 }
7fd59977 523}
524
525//=======================================================================
526//function : Ellipse
527//purpose :
528//=======================================================================
529
5201d3e6 530gp_Elips2d Adaptor2d_OffsetCurve::Ellipse() const
7fd59977 531{
532 if (myCurve->GetType() == GeomAbs_Ellipse && myOffset == 0.) {
8c2d3314 533 return myCurve->Ellipse();
7fd59977 534 }
535 else {
9775fa61 536 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Ellipse");
7fd59977 537 }
7fd59977 538}
539
540//=======================================================================
541//function : Hyperbola
542//purpose :
543//=======================================================================
544
5201d3e6 545gp_Hypr2d Adaptor2d_OffsetCurve::Hyperbola() const
7fd59977 546{
547 if (myCurve->GetType()==GeomAbs_Hyperbola && myOffset==0.) {
548 return myCurve->Hyperbola();
549 }
550 else {
9775fa61 551 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Hyperbola");
7fd59977 552 }
7fd59977 553}
554
555//=======================================================================
556//function : Parabola
557//purpose :
558//=======================================================================
559
5201d3e6 560gp_Parab2d Adaptor2d_OffsetCurve::Parabola() const
7fd59977 561{
562 if (myCurve->GetType() == GeomAbs_Parabola && myOffset == 0.) {
563 return myCurve->Parabola();
564 }
565 else {
9775fa61 566 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Parabola");
7fd59977 567 }
7fd59977 568}
569//=======================================================================
570//function : Degree
571//purpose :
572//=======================================================================
573
5201d3e6 574Standard_Integer Adaptor2d_OffsetCurve::Degree() const
7fd59977 575{
576 GeomAbs_CurveType type = myCurve->GetType();
577 if ( (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve)
578 && myOffset == 0.) {
579 return myCurve->Degree();
580 }
581 else {
9775fa61 582 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Degree");
7fd59977 583 }
584}
585//=======================================================================
586//function : IsRational
587//purpose :
588//=======================================================================
589
5201d3e6 590Standard_Boolean Adaptor2d_OffsetCurve::IsRational() const
7fd59977 591{
592 if ( myOffset == 0.) {
593 return myCurve->IsRational();
594 }
595 return Standard_False;
596}
597//=======================================================================
598//function : NbPoles
599//purpose :
600//=======================================================================
601
5201d3e6 602Standard_Integer Adaptor2d_OffsetCurve::NbPoles() const
7fd59977 603{
604 GeomAbs_CurveType type = myCurve->GetType();
605 if ( (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve)
606 && myOffset == 0.) {
607 return myCurve->NbPoles();
608 }
609 else {
9775fa61 610 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbPoles");
7fd59977 611 }
612}
613
614//=======================================================================
615//function : NbKnots
616//purpose :
617//=======================================================================
618
5201d3e6 619Standard_Integer Adaptor2d_OffsetCurve::NbKnots() const
7fd59977 620{
621 if( myOffset == 0.) {
622 return myCurve->NbKnots();
623 }
624 else {
9775fa61 625 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbKnots");
7fd59977 626 }
627}
628
629//=======================================================================
630//function : Bezier
631//purpose :
632//=======================================================================
633
5201d3e6 634Handle(Geom2d_BezierCurve) Adaptor2d_OffsetCurve::Bezier() const
7fd59977 635{
2d2b3d53 636 Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BezierCurve,
637 "Adaptor2d_OffsetCurve::Bezier() - wrong curve type");
7fd59977 638 return myCurve->Bezier();
639}
640
641
642//=======================================================================
643//function : BSpline
644//purpose :
645//=======================================================================
646
5201d3e6 647Handle(Geom2d_BSplineCurve) Adaptor2d_OffsetCurve::BSpline() const
7fd59977 648{
2d2b3d53 649 Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BSplineCurve,
650 "Adaptor2d_OffsetCurve::BSpline() - wrong curve type");
7fd59977 651 return myCurve->BSpline();
652}
833034f3 653
654static Standard_Integer nbPoints(const Handle(Adaptor2d_HCurve2d)& theCurve)
655{
656
657 Standard_Integer nbs = 20;
658
389f5b59 659 if (theCurve->GetType() == GeomAbs_BezierCurve)
833034f3 660 {
389f5b59 661 nbs = Max(nbs, 3 + theCurve->NbPoles());
833034f3 662 }
663 else if (theCurve->GetType() == GeomAbs_BSplineCurve) {
389f5b59 664 nbs = Max(nbs, theCurve->NbKnots() * theCurve->Degree());
833034f3 665 }
666
389f5b59 667 if (nbs > 300)
668 nbs = 300;
833034f3 669 return nbs;
670
671}
672//=======================================================================
673//function : NbSamples
674//purpose :
675//=======================================================================
676
677Standard_Integer Adaptor2d_OffsetCurve::NbSamples() const
678{
679 return nbPoints(myCurve);
680}