0031303: Different calculation of offset direction in Adaptor2d_OffsetCurve and Geom2...
[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>
68ad329c 20#include <Geom2dEvaluator.hxx>
7fd59977 21#include <GeomAbs_SurfaceType.hxx>
42cf5bc1 22#include <gp.hxx>
7fd59977 23#include <gp_Ax22d.hxx>
42cf5bc1 24#include <gp_Circ2d.hxx>
7fd59977 25#include <gp_Dir2d.hxx>
42cf5bc1 26#include <gp_Elips2d.hxx>
27#include <gp_Hypr2d.hxx>
28#include <gp_Lin2d.hxx>
29#include <gp_Parab2d.hxx>
30#include <gp_Pnt2d.hxx>
31#include <gp_Vec2d.hxx>
32#include <gp_VectorWithNullMagnitude.hxx>
33#include <Precision.hxx>
34#include <Standard_DomainError.hxx>
35#include <Standard_NoSuchObject.hxx>
36#include <Standard_NotImplemented.hxx>
42cf5bc1 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();
7fd59977 115}
116
117//=======================================================================
118//function : Load
119//purpose :
120//=======================================================================
121
5201d3e6 122void Adaptor2d_OffsetCurve::Load(const Standard_Real Offset,
cbff1e55 123 const Standard_Real WFirst,
124 const Standard_Real WLast)
7fd59977 125{
126 myOffset = Offset;
127 myFirst = WFirst;
128 myLast = WLast;
129}
130
131//=======================================================================
132//function : Continuity
133//purpose :
134//=======================================================================
135
5201d3e6 136GeomAbs_Shape Adaptor2d_OffsetCurve::Continuity() const
7fd59977 137{
138 switch (myCurve->Continuity()) {
139 case GeomAbs_CN: return GeomAbs_CN;
140 case GeomAbs_C3: return GeomAbs_C2;
141 case GeomAbs_C2: return GeomAbs_G2;
142 case GeomAbs_G2: return GeomAbs_C1;
143 case GeomAbs_C1: return GeomAbs_G1;
144 case GeomAbs_G1: return GeomAbs_C0;
145 case GeomAbs_C0:
146// No Continuity !!
9775fa61 147 throw Standard_TypeMismatch("Adaptor2d_OffsetCurve::IntervalContinuity");
7fd59977 148 break;
149 }
150
151 //portage WNT
152 return GeomAbs_C0;
153}
154
155//=======================================================================
156//function : NbIntervals
157//purpose :
158//=======================================================================
159
5201d3e6 160Standard_Integer Adaptor2d_OffsetCurve::NbIntervals(const GeomAbs_Shape S) const
7fd59977 161{
162 GeomAbs_Shape Sh;
163 if ( S >= GeomAbs_C2) Sh = GeomAbs_CN;
164 else
165 Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
166
167 Standard_Integer nbInter = myCurve->NbIntervals(Sh);
168
169 if(nbInter == 1) return nbInter;
170
171 TColStd_Array1OfReal T(1,nbInter+1);
172
173 myCurve->Intervals(T,Sh);
174
175 Standard_Integer first = 1;
176 while (T(first) <= myFirst) first++;
177 Standard_Integer last = nbInter+1;
178 while (T(last) >= myLast) last--;
179 return (last - first + 2);
180}
181
182//=======================================================================
183//function : Intervals
184//purpose :
185//=======================================================================
186
5201d3e6 187void Adaptor2d_OffsetCurve::Intervals(TColStd_Array1OfReal& TI,
7fd59977 188 const GeomAbs_Shape S) const
189{
190 GeomAbs_Shape Sh;
191 if ( S >= GeomAbs_C2) Sh = GeomAbs_CN;
192 else
193 Sh = (GeomAbs_Shape)((Standard_Integer)S + 2);
194
195 Standard_Integer nbInter = myCurve->NbIntervals(Sh);
196
197
198 if(nbInter == 1) {
199 TI(TI.Lower()) = myFirst ;
200 TI(TI.Lower() + 1) = myLast ;
201 return;
202 }
203
204 TColStd_Array1OfReal T(1,nbInter+1);
205 myCurve->Intervals(T,Sh);
206
207 Standard_Integer first = 1;
208 while (T(first) <= myFirst) first++;
209 Standard_Integer last = nbInter+1;
210 while (T(last) >= myLast) last--;
211
212 Standard_Integer i = TI.Lower(), j;
213 for (j = first-1; j <= last+1; j++) {
214 TI(i) = T(j);
215 i++;
216 }
217
218 TI(TI.Lower()) = myFirst ;
219 TI(TI.Lower() + last-first + 2) = myLast ;
220
221}
222
223
224//=======================================================================
225//function : Trim
226//purpose :
227//=======================================================================
228
5201d3e6 229Handle(Adaptor2d_HCurve2d) Adaptor2d_OffsetCurve::Trim
7fd59977 230(const Standard_Real First,
231 const Standard_Real Last,
232 const Standard_Real) const
233{
5201d3e6 234 Handle(Adaptor2d_HOffsetCurve) HO = new Adaptor2d_HOffsetCurve(*this);
7fd59977 235 HO->ChangeCurve2d().Load(myOffset,First,Last);
236 return HO;
237}
238
239
240//=======================================================================
241//function : IsClosed
242//purpose :
243//=======================================================================
244
5201d3e6 245Standard_Boolean Adaptor2d_OffsetCurve::IsClosed() const
7fd59977 246{
247 if ( myOffset == 0.) {
248 return myCurve->IsClosed();
249 }
250 else {
251 if (myCurve->Continuity() == GeomAbs_C0)
252 return Standard_False;
253 else {
254 if ( myCurve->IsClosed()) {
255 gp_Vec2d Dummy[2];
256 gp_Pnt2d P;
257 myCurve->D1
258 (myCurve->FirstParameter(),P,Dummy[0]);
259 myCurve->D1
260 (myCurve->LastParameter(),P,Dummy[1]);
261 if (Dummy[0].IsParallel(Dummy[1],Precision::Angular()) &&
262 !(Dummy[0].IsOpposite(Dummy[1],Precision::Angular())))
263 return Standard_True;
264 else
265 return Standard_False;
266 }
267 else
268 return Standard_False;
269 }
270 }
271}
272
273//=======================================================================
274//function : IsPeriodic
275//purpose :
276//=======================================================================
277
5201d3e6 278Standard_Boolean Adaptor2d_OffsetCurve::IsPeriodic() const
7fd59977 279{
280 return myCurve->IsPeriodic();
281}
282
283//=======================================================================
284//function : Period
285//purpose :
286//=======================================================================
287
5201d3e6 288Standard_Real Adaptor2d_OffsetCurve::Period() const
7fd59977 289{
290 return myCurve->Period();
291}
292
293//=======================================================================
294//function : Value
295//purpose :
296//=======================================================================
297
5201d3e6 298gp_Pnt2d Adaptor2d_OffsetCurve::Value(const Standard_Real U) const
7fd59977 299{
300 if ( myOffset != 0.) {
68ad329c 301 gp_Pnt2d aP;
302 gp_Vec2d aV;
303 myCurve->D1(U, aP, aV);
304 Geom2dEvaluator::CalculateD0(aP, aV, myOffset);
305 return aP;
7fd59977 306 }
307 else {
308 return myCurve->Value(U);
309 }
310}
311
312//=======================================================================
313//function : D0
314//purpose :
315//=======================================================================
316
5201d3e6 317void Adaptor2d_OffsetCurve::D0(const Standard_Real U, gp_Pnt2d& P) const
7fd59977 318{
319 P = Value( U);
320}
321
322//=======================================================================
323//function : D1
324//purpose :
325//=======================================================================
326
5201d3e6 327void Adaptor2d_OffsetCurve::D1
68ad329c 328(const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V) const
7fd59977 329{
68ad329c 330 if (myOffset != 0.) {
331 gp_Vec2d aV2;
332 myCurve->D2(U, P, V, aV2);
333 Geom2dEvaluator::CalculateD1( P, V, aV2, myOffset);
7fd59977 334 }
335 else {
68ad329c 336 myCurve->D1(U, P, V);
7fd59977 337 }
338}
339
340//=======================================================================
341//function : D2
342//purpose :
343//=======================================================================
344
5201d3e6 345void Adaptor2d_OffsetCurve::D2
68ad329c 346(const Standard_Real U, gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
7fd59977 347{
68ad329c 348 if (myOffset != 0.) {
349 gp_Vec2d aV3;
350 myCurve->D3(U, P, V1, V2, aV3);
351 Geom2dEvaluator::CalculateD2(P, V1, V2, aV3, Standard_False, myOffset);
7fd59977 352 }
353 else {
68ad329c 354 myCurve->D2(U, P, V1, V2);
7fd59977 355 }
356}
357
358//=======================================================================
359//function : D3
360//purpose :
361//=======================================================================
362
5201d3e6 363void Adaptor2d_OffsetCurve::D3
68ad329c 364 (const Standard_Real U,
365 gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2, gp_Vec2d& V3) const
7fd59977 366{
68ad329c 367 if (myOffset != 0.) {
368 gp_Vec2d aV4 = myCurve->DN(U, 4);
369 myCurve->D3(U, P, V1, V2, V3);
370 Geom2dEvaluator::CalculateD3(P, V1, V2, V3, aV4, Standard_False, myOffset);
371 }
372 else {
373 myCurve->D3(U, P, V1, V2, V3);
374 }
7fd59977 375}
376
377//=======================================================================
378//function : DN
379//purpose :
380//=======================================================================
381
5201d3e6 382gp_Vec2d Adaptor2d_OffsetCurve::DN
7fd59977 383 (const Standard_Real , const Standard_Integer ) const
384{
9775fa61 385 throw Standard_NotImplemented("Adaptor2d_OffsetCurve::DN");
7fd59977 386}
387
388
389//=======================================================================
390//function : Resolution
391//purpose :
392//=======================================================================
393
5201d3e6 394Standard_Real Adaptor2d_OffsetCurve::Resolution(const Standard_Real R3d) const
7fd59977 395{
396 return Precision::PConfusion(R3d);
397}
398
399
400//=======================================================================
401//function : GetType
402//purpose :
403//=======================================================================
404
5201d3e6 405GeomAbs_CurveType Adaptor2d_OffsetCurve::GetType() const {
7fd59977 406
407 if ( myOffset == 0.) {
408 return myCurve->GetType();
409 }
410 else {
411 switch (myCurve->GetType()) {
412
413 case GeomAbs_Line:
414 return GeomAbs_Line;
415
416 case GeomAbs_Circle:
417 return GeomAbs_Circle;
418
419 default:
833034f3 420 return GeomAbs_OffsetCurve;
7fd59977 421
422 }
423 }
424}
425
426//=======================================================================
427//function : Line
428//purpose :
429//=======================================================================
430
5201d3e6 431gp_Lin2d Adaptor2d_OffsetCurve::Line() const
7fd59977 432{
433 if ( GetType() == GeomAbs_Line) {
434 gp_Pnt2d P;
435 gp_Vec2d V;
436 D1(0,P,V);
437 return gp_Lin2d(P,V);
438 }
439 else {
9775fa61 440 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Line");
7fd59977 441 }
442}
443
444
445//=======================================================================
446//function : Circle
447//purpose :
448//=======================================================================
449
5201d3e6 450gp_Circ2d Adaptor2d_OffsetCurve::Circle() const
7fd59977 451{
452 if ( GetType() == GeomAbs_Circle) {
453 if (myOffset == 0.) {
454 return myCurve->Circle();
455 }
456 else {
457 gp_Circ2d C1( myCurve->Circle());
458 Standard_Real radius = C1.Radius();
459 gp_Ax22d axes( C1.Axis());
460 gp_Dir2d Xd = axes.XDirection();
461 gp_Dir2d Yd = axes.YDirection();
462 Standard_Real Crossed = Xd.X()*Yd.Y()-Xd.Y()*Yd.X();
463 Standard_Real Signe = ( Crossed > 0.) ? 1. : -1.;
464
465 radius += Signe*myOffset;
466 if ( radius > 0.) {
467 return gp_Circ2d( axes,radius);
468 }
469 else if ( radius < 0.) {
470 radius = - radius;
471 axes.SetXDirection( (axes.XDirection()).Reversed());
472 return gp_Circ2d( axes,radius);
473 }
474 else { // Cercle de rayon Nul
9775fa61 475 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
7fd59977 476 }
477 }
478 }
479 else {
9775fa61 480 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Circle");
7fd59977 481 }
7fd59977 482}
483
484//=======================================================================
485//function : Ellipse
486//purpose :
487//=======================================================================
488
5201d3e6 489gp_Elips2d Adaptor2d_OffsetCurve::Ellipse() const
7fd59977 490{
491 if (myCurve->GetType() == GeomAbs_Ellipse && myOffset == 0.) {
8c2d3314 492 return myCurve->Ellipse();
7fd59977 493 }
494 else {
9775fa61 495 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Ellipse");
7fd59977 496 }
7fd59977 497}
498
499//=======================================================================
500//function : Hyperbola
501//purpose :
502//=======================================================================
503
5201d3e6 504gp_Hypr2d Adaptor2d_OffsetCurve::Hyperbola() const
7fd59977 505{
506 if (myCurve->GetType()==GeomAbs_Hyperbola && myOffset==0.) {
507 return myCurve->Hyperbola();
508 }
509 else {
9775fa61 510 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Hyperbola");
7fd59977 511 }
7fd59977 512}
513
514//=======================================================================
515//function : Parabola
516//purpose :
517//=======================================================================
518
5201d3e6 519gp_Parab2d Adaptor2d_OffsetCurve::Parabola() const
7fd59977 520{
521 if (myCurve->GetType() == GeomAbs_Parabola && myOffset == 0.) {
522 return myCurve->Parabola();
523 }
524 else {
9775fa61 525 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve:Parabola");
7fd59977 526 }
7fd59977 527}
528//=======================================================================
529//function : Degree
530//purpose :
531//=======================================================================
532
5201d3e6 533Standard_Integer Adaptor2d_OffsetCurve::Degree() const
7fd59977 534{
535 GeomAbs_CurveType type = myCurve->GetType();
536 if ( (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve)
537 && myOffset == 0.) {
538 return myCurve->Degree();
539 }
540 else {
9775fa61 541 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::Degree");
7fd59977 542 }
543}
544//=======================================================================
545//function : IsRational
546//purpose :
547//=======================================================================
548
5201d3e6 549Standard_Boolean Adaptor2d_OffsetCurve::IsRational() const
7fd59977 550{
551 if ( myOffset == 0.) {
552 return myCurve->IsRational();
553 }
554 return Standard_False;
555}
556//=======================================================================
557//function : NbPoles
558//purpose :
559//=======================================================================
560
5201d3e6 561Standard_Integer Adaptor2d_OffsetCurve::NbPoles() const
7fd59977 562{
563 GeomAbs_CurveType type = myCurve->GetType();
564 if ( (type==GeomAbs_BezierCurve || type==GeomAbs_BSplineCurve)
565 && myOffset == 0.) {
566 return myCurve->NbPoles();
567 }
568 else {
9775fa61 569 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbPoles");
7fd59977 570 }
571}
572
573//=======================================================================
574//function : NbKnots
575//purpose :
576//=======================================================================
577
5201d3e6 578Standard_Integer Adaptor2d_OffsetCurve::NbKnots() const
7fd59977 579{
580 if( myOffset == 0.) {
581 return myCurve->NbKnots();
582 }
583 else {
9775fa61 584 throw Standard_NoSuchObject("Adaptor2d_OffsetCurve::NbKnots");
7fd59977 585 }
586}
587
588//=======================================================================
589//function : Bezier
590//purpose :
591//=======================================================================
592
5201d3e6 593Handle(Geom2d_BezierCurve) Adaptor2d_OffsetCurve::Bezier() const
7fd59977 594{
2d2b3d53 595 Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BezierCurve,
596 "Adaptor2d_OffsetCurve::Bezier() - wrong curve type");
7fd59977 597 return myCurve->Bezier();
598}
599
600
601//=======================================================================
602//function : BSpline
603//purpose :
604//=======================================================================
605
5201d3e6 606Handle(Geom2d_BSplineCurve) Adaptor2d_OffsetCurve::BSpline() const
7fd59977 607{
2d2b3d53 608 Standard_NoSuchObject_Raise_if (myOffset != 0.0e0 || GetType() != GeomAbs_BSplineCurve,
609 "Adaptor2d_OffsetCurve::BSpline() - wrong curve type");
7fd59977 610 return myCurve->BSpline();
611}
833034f3 612
613static Standard_Integer nbPoints(const Handle(Adaptor2d_HCurve2d)& theCurve)
614{
615
616 Standard_Integer nbs = 20;
617
389f5b59 618 if (theCurve->GetType() == GeomAbs_BezierCurve)
833034f3 619 {
389f5b59 620 nbs = Max(nbs, 3 + theCurve->NbPoles());
833034f3 621 }
622 else if (theCurve->GetType() == GeomAbs_BSplineCurve) {
389f5b59 623 nbs = Max(nbs, theCurve->NbKnots() * theCurve->Degree());
833034f3 624 }
625
389f5b59 626 if (nbs > 300)
627 nbs = 300;
833034f3 628 return nbs;
629
630}
631//=======================================================================
632//function : NbSamples
633//purpose :
634//=======================================================================
635
636Standard_Integer Adaptor2d_OffsetCurve::NbSamples() const
637{
638 return nbPoints(myCurve);
639}