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