00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef N_2D_POINT_H
00024 #define N_2D_POINT_H
00025
00026 #include "claraty/share.h"
00027 #include <iostream>
00028 #include <math.h>
00029
00030 #include "claraty/fdm.h"
00031 #include "claraty/math_limits.h"
00032
00033 namespace claraty {
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 template < class T >
00047 class N_2D_Point;
00048
00049 typedef N_2D_Point< double > N_2D_Point_d;
00050 typedef N_2D_Point< float > N_2D_Point_f;
00051 typedef N_2D_Point< int > N_2D_Point_i;
00052
00053
00054
00055
00056
00057 template < class T >
00058 inline bool operator==( const N_2D_Point< T >&, const N_2D_Point< T >& );
00059
00060 template < class T >
00061 inline N_2D_Point<T> operator+( const N_2D_Point<T>&, const N_2D_Point<T>& );
00062
00063 template < class T >
00064 inline N_2D_Point<T> operator-( const N_2D_Point<T>&, const N_2D_Point<T>& );
00065
00066 template < class T >
00067 inline N_2D_Point<T> operator-( const N_2D_Point<T>& );
00068
00069 template < class T >
00070 inline N_2D_Point<T> operator*( double, const N_2D_Point<T>& );
00071
00072 template < class T >
00073 inline N_2D_Point<T> operator/( const N_2D_Point<T>&, double );
00074
00075
00076
00077
00078
00079
00080 template < class T >
00081 class N_2D_Point
00082 {
00083 public:
00084 enum{ X, Y };
00085
00086
00087
00088
00089
00090
00091
00092 explicit N_2D_Point( T e0 = T(), T e1 = T() )
00093 { _elems[ 0 ] = e0; _elems[ 1 ] = e1; }
00094
00095
00096
00097
00098
00099 int size() const { return 2; }
00100
00101
00102
00103
00104
00105
00106 T operator()( int ix ) const { return _elems[ ix ]; }
00107
00108
00109
00110
00111
00112
00113 T& operator()( int ix ) { return _elems[ ix ]; }
00114
00115
00116
00117
00118
00119 T x() const { return _elems[ 0 ]; }
00120
00121
00122
00123
00124
00125 T& x() { return _elems[ 0 ]; }
00126
00127
00128
00129
00130
00131 T& y() { return _elems[ 1 ]; }
00132
00133
00134
00135
00136
00137 T y() const { return _elems[ 1 ]; }
00138
00139
00140
00141
00142
00143 T get_x() const { return _elems[ 0 ]; }
00144
00145
00146
00147
00148
00149 T get_y() const { return _elems[ 1 ]; }
00150
00151
00152
00153
00154
00155 void set( T x ) { _elems[ 0 ] = x; }
00156
00157
00158
00159
00160
00161
00162 void set( T x, T y ) {
00163 _elems[ 0 ] = x; _elems[ 1 ] = y;
00164 }
00165
00166
00167
00168
00169
00170 void invert_y( T inv_y ) { _elems[ 1 ] = inv_y - _elems[ 1 ]; }
00171
00172 T length() const;
00173 T length2() const;
00174
00175 double angle() const;
00176
00177 bool normalize();
00178 N_2D_Point normalize_copy() const;
00179
00180 T dot( const N_2D_Point& ) const;
00181
00182 T distance ( const N_2D_Point& ) const;
00183 T distance2( const N_2D_Point& ) const;
00184 N_2D_Point interpolate( const N_2D_Point&, T s ) const;
00185 N_2D_Point extrapolate( const T angle, T s ) const;
00186
00187 bool intersect(const N_2D_Point &line1_a,
00188 const N_2D_Point &line1_b,
00189 const N_2D_Point &line2_a,
00190 const N_2D_Point &line2_b,
00191 N_2D_Point & result) const;
00192
00193 N_2D_Point& operator+=( const N_2D_Point& );
00194 N_2D_Point& operator-=( const N_2D_Point& );
00195 N_2D_Point& operator+=( T );
00196 N_2D_Point& operator-=( T );
00197 N_2D_Point& operator*=( T );
00198 N_2D_Point& operator/=( T );
00199
00200 N_2D_Point rotate( double ang ) const;
00201
00202
00203
00204
00205
00206
00207 N_2D_Point rotate_cw_90() const { return N_2D_Point( _elems[1], -_elems[0] ); }
00208
00209
00210
00211
00212
00213 N_2D_Point rotate_ccw_90() const { return N_2D_Point( -_elems[1], _elems[0] ); }
00214
00215
00216
00217
00218
00219
00220 N_2D_Point rotate_cw( float angle ) const
00221 {
00222 return N_2D_Point(
00223 (T)(_elems[0] * cos(angle) + _elems[1] * sin(angle)),
00224 (T)(_elems[1] * cos(angle) - _elems[0] * sin(angle)));
00225 }
00226
00227
00228
00229
00230
00231
00232 N_2D_Point rotate_ccw( float angle ) const
00233 {
00234 return N_2D_Point(
00235 (T)(_elems[0] * cos(angle) - _elems[1] * sin(angle)),
00236 (T)(_elems[1] * cos(angle) + _elems[0] * sin(angle)));
00237 }
00238
00239
00240
00241
00242
00243
00244
00245 N_2D_Point rotate_cw_around_point( float angle, N_2D_Point p ) const
00246 { return ( *this-p ).rotate_cw( angle ) + p; }
00247
00248
00249
00250
00251
00252
00253
00254 N_2D_Point rotate_ccw_around_point( float angle, N_2D_Point p) const
00255 { return ( *this-p ).rotate_ccw( angle ) + p; }
00256
00257 T distance_to_unit_vector( const N_2D_Point& ) const;
00258 T closest_point_to_line( const N_2D_Point&, const N_2D_Point& ) const;
00259 T distance2_to_line( const N_2D_Point&, const N_2D_Point&, N_2D_Point* = 0 ) const;
00260
00261 bool is_origin() const;
00262 std::ostream& display(const char *pmsg, std::ostream &os = std::cout) const;
00263 std::ostream& display_unformatted(std::ostream &os) const;
00264
00265 inline double angle_to(const N_2D_Point &a) const;
00266
00267 private:
00268 T _elems[ 2 ];
00269 };
00270
00271
00272
00273
00274
00275 template < class T >
00276 inline T
00277 N_2D_Point<T>::
00278 length() const
00279 {
00280 return (T)(sqrt( _elems[0]*_elems[0] + _elems[1]*_elems[1]));
00281 }
00282
00283
00284
00285
00286
00287 template < class T >
00288 inline T N_2D_Point<T>::
00289 length2() const
00290 {
00291 return _elems[0]*_elems[0] + _elems[1]*_elems[1];
00292 }
00293
00294
00295
00296
00297
00298 template < class T >
00299 inline double N_2D_Point<T>::
00300 angle() const
00301 {
00302
00303
00304 return atan2(y(), x());
00305 }
00306
00307
00308
00309
00310
00311
00312 template<class T>
00313 inline double N_2D_Point<T>::
00314 angle_to(const N_2D_Point<T> &a) const
00315 {
00316 double delta_angle= a.angle() - angle();
00317 if (delta_angle <= -M_PI) delta_angle += 2*M_PI;
00318 else if (delta_angle >= M_PI) delta_angle -= 2*M_PI;
00319 return delta_angle;
00320 }
00321
00322
00323
00324
00325
00326
00327 template < class T >
00328 inline T N_2D_Point<T>::
00329 dot( const N_2D_Point &v ) const
00330 {
00331 return ( _elems[0]*v._elems[0] + _elems[1]*v._elems[1] );
00332 }
00333
00334
00335
00336
00337
00338
00339 template < class T >
00340 inline T N_2D_Point<T>::
00341 distance2( const N_2D_Point &p ) const
00342 {
00343 double d0 = p._elems[0] - _elems[0];
00344 double d1 = p._elems[1] - _elems[1];
00345
00346 return (T)(d0*d0 + d1*d1);
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 template < class T >
00359 inline T N_2D_Point<T>::
00360 distance( const N_2D_Point &p ) const
00361 {
00362 double d0 = p._elems[0] - _elems[0];
00363 double d1 = p._elems[1] - _elems[1];
00364
00365 return (T)(sqrt( d0*d0 + d1*d1 ));
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 template < class T >
00383 inline N_2D_Point<T> N_2D_Point<T>::
00384 interpolate( const N_2D_Point &p, T s ) const
00385 {
00386 return N_2D_Point<T>
00387 (( p._elems[0]-_elems[0] ) * s+_elems[0],
00388 ( p._elems[1]-_elems[1] ) * s+_elems[1] );
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 template < class T >
00403 inline N_2D_Point<T> N_2D_Point<T>::
00404 extrapolate( const T angle, T s ) const
00405 {
00406 return N_2D_Point<T> (
00407 _elems[0] + s*cos(angle),
00408 _elems[1] + s*sin(angle));
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 template < class T >
00418 inline bool N_2D_Point<T>::
00419 intersect(const N_2D_Point &line1_a,
00420 const N_2D_Point &line1_b,
00421 const N_2D_Point &line2_a,
00422 const N_2D_Point &line2_b,
00423 N_2D_Point & result) const
00424 {
00425
00426
00427 T delta_x1 = line1_a.x() - line1_b.x();
00428 T delta_x2 = line2_a.x() - line2_b.x();
00429 T delta_y1 = line1_a.y() - line1_b.y();
00430 T delta_y2 = line2_a.y() - line2_b.y();
00431
00432 T angle_difference =
00433 atan2(delta_y1, delta_x1) - atan2(delta_y2, delta_x2);
00434
00435 while (angle_difference > M_PI)
00436 angle_difference -= M_2_PI;
00437 while (angle_difference <= -M_PI)
00438 angle_difference += M_2_PI;
00439
00440 if (fabs(angle_difference) < DOUBLE_EPSILON)
00441 return false;
00442
00443 if (fabs(fabs(angle_difference) - M_PI) < DOUBLE_EPSILON)
00444 return false;
00445
00446
00447 T denominator = delta_x1 * delta_y2 - delta_x2 * delta_y1;
00448
00449
00450 if (fabs(denominator) < DOUBLE_EPSILON)
00451 return false;
00452
00453
00454 T sub_det_1 = line1_a.x() * line1_b.y() - line1_b.x() * line1_a.y();
00455 T sub_det_2 = line2_a.x() * line2_b.y() - line2_b.x() * line2_a.y();
00456
00457 result._elems[0]
00458 = ((sub_det_1*delta_x2)-(sub_det_2*delta_x1))/denominator;
00459 result._elems[1]
00460 = ((sub_det_1*delta_y2)-(sub_det_2*delta_y1))/denominator;
00461
00462 return true;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 template < class T >
00478 inline T N_2D_Point<T>::
00479 distance_to_unit_vector( const N_2D_Point &v) const
00480 {
00481 T d = _elems[0]*v._elems[1] - _elems[1]*v._elems[0];
00482 return d < 0 ? -d : d ;
00483 }
00484
00485
00486
00487
00488
00489 template < class T >
00490 inline bool N_2D_Point<T>::
00491 normalize()
00492 {
00493 bool status = false;
00494 double vec_len = length();
00495
00496 if ( vec_len > EPSILON ) {
00497 _elems[0] = (T)(_elems[0] / vec_len);
00498 _elems[1] = (T)(_elems[1] / vec_len);
00499 status = true;
00500 }
00501
00502 return status;
00503 }
00504
00505
00506
00507
00508
00509 template < class T >
00510 inline N_2D_Point<T> N_2D_Point<T>::
00511 normalize_copy() const
00512 {
00513 N_2D_Point<T> test;
00514 double vec_len = length();
00515 if (vec_len > EPSILON){
00516
00517 test(0) = (T)(_elems[0]/vec_len);
00518 test(1) = (T)(_elems[1]/vec_len);
00519 }
00520 return test;
00521
00522
00523
00524
00525 }
00526
00527
00528
00529
00530
00531
00532 template < class T >
00533 inline N_2D_Point<T> N_2D_Point<T>::
00534 rotate( double ang ) const
00535 {
00536 double cosa = cos( ang ); double sina = sin( ang );
00537
00538 return N_2D_Point( (T)(_elems[0]*cosa - _elems[1]*sina),
00539 (T)(_elems[0]*sina + _elems[1]*cosa) );
00540 }
00541
00542
00543
00544
00545
00546 template < class T >
00547 inline bool N_2D_Point<T>::
00548 is_origin() const
00549 {
00550 return ! _elems[0] && ! _elems[1];
00551 }
00552
00553
00554
00555
00556
00557
00558
00559 template < class T >
00560 inline bool
00561 operator==( const N_2D_Point<T> &v0, const N_2D_Point<T> &v1 )
00562 {
00563 return ( v0(0)==v1(0) ) && ( v0(1)==v1(1) );
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 template < class T >
00573 inline N_2D_Point<T>
00574 operator+( const N_2D_Point<T> &v0, const N_2D_Point<T> &v1 )
00575 {
00576 return N_2D_Point<T>( v0(0)+v1(0), v0(1)+v1(1) );
00577 }
00578
00579
00580
00581
00582
00583
00584
00585 template < class T >
00586 inline N_2D_Point<T>
00587 operator-( const N_2D_Point<T> &v0, const N_2D_Point<T> &v1 )
00588 {
00589 return N_2D_Point<T>(v0(0)-v1(0), v0(1)-v1(1));
00590 }
00591
00592
00593
00594
00595
00596
00597 template < class T >
00598 inline N_2D_Point<T>
00599 operator-( const N_2D_Point<T> &v )
00600 {
00601 return N_2D_Point<T>( -v(0), -v(1));
00602 }
00603
00604
00605
00606
00607
00608
00609 template < class T >
00610 inline N_2D_Point<T>& N_2D_Point<T>::
00611 operator+=( const N_2D_Point<T> &v1 )
00612 {
00613 _elems[0] += v1(0); _elems[1] += v1(1);
00614 return *this;
00615 }
00616
00617
00618
00619
00620
00621
00622 template < class T >
00623 inline N_2D_Point<T>& N_2D_Point<T>::
00624 operator-=( const N_2D_Point &v1 )
00625 {
00626 _elems[0] -= v1(0); _elems[1] -= v1(1); return *this;
00627 }
00628
00629
00630
00631
00632
00633
00634 template < class T >
00635 inline N_2D_Point<T>& N_2D_Point<T>::
00636 operator+=( T s )
00637 {
00638 _elems[0] += s; _elems[1] += s;
00639 return *this;
00640 }
00641
00642
00643
00644
00645
00646
00647 template < class T >
00648 inline N_2D_Point<T>& N_2D_Point<T>::
00649 operator-=( T s )
00650 {
00651 _elems[0] -= s; _elems[1] -= s;
00652 return *this;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661 template < class T >
00662 inline N_2D_Point<T>
00663 operator*( const N_2D_Point<T> &v, double s )
00664 {
00665 return N_2D_Point<T>(v(0)*s, v(1)*s);
00666 }
00667
00668
00669
00670
00671
00672
00673
00674 template < class T >
00675 inline N_2D_Point<T>
00676 operator*( double s, const N_2D_Point<T> &v )
00677 {
00678 return N_2D_Point<T>( (T)(v(0)*s),
00679 (T)(v(1)*s) );
00680 }
00681
00682
00683
00684
00685
00686
00687 template < class T >
00688 inline N_2D_Point<T>& N_2D_Point<T>::
00689 operator*=( T s )
00690 {
00691 _elems[0] *= s; _elems[1] *= s; return *this;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700 template < class T >
00701 inline N_2D_Point<T>
00702 operator/( const N_2D_Point<T> &v, double s )
00703 {
00704 return N_2D_Point<T>( v.x()/s, v.y()/s );
00705 }
00706
00707
00708
00709
00710
00711
00712 template < class T >
00713 inline N_2D_Point<T>& N_2D_Point<T>::
00714 operator/=( T s )
00715 {
00716 _elems[0] /= s; _elems[1] /= s; return *this;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726 template < class T >
00727 inline T N_2D_Point<T>::
00728 closest_point_to_line( const N_2D_Point<T> &a, const N_2D_Point<T> &b ) const
00729 {
00730 N_2D_Point<T> v( b - a );
00731 double d2 = v.length2();
00732 return (T)(d2 < 1.0E-6
00733 ? 0.
00734 : v.dot( *this-a )/d2);
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 template < class T >
00747 inline T N_2D_Point<T>::
00748 distance2_to_line( const N_2D_Point<T> &a, const N_2D_Point<T> &b, N_2D_Point<T> *p ) const {
00749 double s = closest_point_to_line( a, b );
00750 N_2D_Point<T> p_on_line = a + s*( b - a );
00751
00752 if ( p != 0 )
00753 *p = p_on_line;
00754
00755 return distance2( p_on_line );
00756 }
00757
00758 template < typename elem_type >
00759 inline std::ostream& N_2D_Point<elem_type>::display_unformatted(std::ostream &os)
00760 const
00761 {
00762 return os << _elems[0] << " " << _elems[1];
00763 }
00764
00765 template < typename elem_type >
00766 inline std::ostream& N_2D_Point<elem_type>::
00767 display( const char* pmsg, std::ostream &os ) const
00768 {
00769 if ( pmsg )
00770 os << pmsg;
00771
00772 os << "[x: "
00773 << _elems[0] << " y: "
00774 << _elems[1] << "]";
00775
00776 return os;
00777 }
00778
00779 template < typename elem_type >
00780 inline std::ostream& operator<<(std::ostream &os, const N_2D_Point<elem_type> &p)
00781 {
00782 return p.display( NULL, os );
00783 }
00784
00785 template <class T>
00786 inline std::istream& operator>>(std::istream& is, N_2D_Point<T>& p)
00787 {
00788 return is >> p.x() >> p.y();
00789 }
00790
00791 template <class T>
00792 bool io_object(FDM_Untyped_Node node, N_2D_Point<T>& rhs)
00793 {
00794 FDM_Array a(node);
00795 bool ok = a.element(rhs(0));
00796 ok &= a.element(rhs(1));
00797 return ok;
00798 }
00799
00800 template <class T>
00801 inline bool cl_isnan(const N_2D_Point<T> &pt) {
00802 return cl_isnan(pt.x()) || cl_isnan(pt.y());
00803 }
00804
00805 template <class T>
00806 inline void cl_setnan(N_2D_Point<T> &pt) {
00807 cl_setnan(pt.x());
00808 cl_setnan(pt.y());
00809 }
00810
00811
00812
00813 #include "claraty/operator_def.h"
00814
00815 #define CL_OP_GENERATE ( CL_OP_NOT_EQUAL )
00816 #define CL_OP_TEMPLATE template < typename T >
00817 #define CL_OP_CLASS N_2D_Point<T>
00818 #include "claraty/operator.h"
00819
00820 #define CL_OP_TEMPLATE template < typename T >
00821 #define CL_OP_CLASS N_2D_Point<T>
00822 #define CL_OP_SCALAR T
00823 #include "claraty/scalar_operator.h"
00824
00825 }
00826
00827 #endif // N2D_POINT_H