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 | |
31 | Adaptor3d_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 |
42 | Adaptor3d_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 | |
54 | Adaptor3d_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 | |
68 | Adaptor3d_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 | |
82 | void 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 | |
93 | void 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 | |
106 | void 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 | |
120 | GeomAbs_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 | |
144 | Standard_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 | |
171 | void 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 | |
213 | Handle(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 | |
229 | Standard_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 | |
262 | Standard_Boolean Adaptor3d_OffsetCurve::IsPeriodic() const |
263 | { |
264 | return myCurve->IsPeriodic(); |
265 | } |
266 | |
267 | //======================================================================= |
268 | //function : Period |
269 | //purpose : |
270 | //======================================================================= |
271 | |
272 | Standard_Real Adaptor3d_OffsetCurve::Period() const |
273 | { |
274 | return myCurve->Period(); |
275 | } |
276 | |
277 | //======================================================================= |
278 | //function : Value |
279 | //purpose : |
280 | //======================================================================= |
281 | |
282 | gp_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 | |
309 | void 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 | |
319 | void 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 | |
350 | void 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 |
394 | void 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 | |
406 | gp_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 | |
420 | Standard_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 | |
431 | GeomAbs_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 | |
457 | gp_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 | |
477 | gp_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 | |
518 | gp_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 | |
535 | gp_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 | |
552 | gp_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 | |
568 | Standard_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 | |
585 | Standard_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 | |
597 | Standard_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 | |
615 | Standard_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 | |
631 | Handle(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 | |
644 | Handle(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 | |