// ====================================================================== // // Copyright (c) 1999 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------- // // release : // release_date : // // file : PVDH2.h // package : H2 // revision : $Revision$ // revision_date : $Date$ // author(s) : Stefan Schirra // // // coordinator : MPI, Saarbruecken () // ====================================================================== #ifndef CGAL_PVDH2_H #define CGAL_PVDH2_H #include #include #include CGAL_BEGIN_NAMESPACE template < class R_ > class PointH2 : public R_::Point_handle_2 { public: typedef R_ R; typedef typename R::FT FT; typedef typename R::RT RT; typedef typename R::Point_handle_2 Point_handle_2_; typedef typename Point_handle_2_::element_type Point_ref_2; PointH2(); PointH2(const Origin & o); PointH2(const PointH2 & p); PointH2(const VectorH2& v); PointH2(const RT& hx, const RT& hy ); PointH2(const RT& hx, const RT& hy, const RT& hw ); bool operator==( const PointH2& p) const; bool operator!=( const PointH2& p) const; const RT & hx() const { return Ptr()->e0; }; const RT & hy() const { return Ptr()->e1; }; const RT & hw() const { return Ptr()->e2; }; FT x() const { return FT(hx()) / FT(hw()); }; FT y() const { return FT(hy()) / FT(hw()); }; FT cartesian(int i) const; FT operator[](int i) const; const RT & homogeneous(int i) const; int dimension() const; Bbox_2 bbox() const; PointH2 transform( const Aff_transformationH2 & t) const; DirectionH2 direction() const; }; template < class R_ > class VectorH2 : public R_::Vector_handle_2 { public: typedef R_ R; typedef typename R::FT FT; typedef typename R::RT RT; typedef typename R::Vector_handle_2 Vector_handle_2_; typedef typename Vector_handle_2_::element_type Vector_ref_2; VectorH2(); VectorH2(const VectorH2& v); VectorH2(const PointH2& a, const PointH2& b); VectorH2(const Null_vector &); VectorH2(const RT& x, const RT& y); VectorH2(const RT& x, const RT& y, const RT& w ); bool operator==( const VectorH2& v) const; bool operator!=( const VectorH2& v) const; bool operator==( const Null_vector&) const; bool operator!=( const Null_vector& v) const; const RT & hx() const { return Ptr()->e0; }; const RT & hy() const { return Ptr()->e1; }; const RT & hw() const { return Ptr()->e2; }; FT x() const { return FT(hx()) / FT(hw()); }; FT y() const { return FT(hy()) / FT(hw()); }; FT cartesian(int i) const; const RT & homogeneous(int i) const; FT operator[](int i) const; int dimension() const; DirectionH2 direction() const; VectorH2 transform(const Aff_transformationH2& t ) const; VectorH2 perpendicular(const Orientation& o ) const; FT operator*( const VectorH2& v) const; VectorH2 operator-() const; VectorH2 opposite() const; // undocumented: VectorH2(const DirectionH2 & dir); protected: VectorH2(const PointH2 & p); }; template < class R_ > class DirectionH2 : public R_::Direction_handle_2 { public: typedef R_ R; typedef typename R::FT FT; typedef typename R::RT RT; typedef typename R::Direction_handle_2 Direction_handle_2_; typedef typename Direction_handle_2_::element_type Direction_ref_2; DirectionH2(); DirectionH2(const DirectionH2& d ); DirectionH2(const PointH2 & p ); DirectionH2(const VectorH2 & v ); DirectionH2(const LineH2 & l ); DirectionH2(const RayH2 & r ); DirectionH2(const SegmentH2 & s ); DirectionH2(const RT& x, const RT& y); DirectionH2(const RT& x, const RT& y, const RT& w ); bool operator==( const DirectionH2& d) const; bool operator!=( const DirectionH2& d) const; bool operator< ( const DirectionH2& d) const; bool operator<=( const DirectionH2& d) const; bool operator> ( const DirectionH2& d) const; bool operator>=( const DirectionH2& d) const; bool counterclockwise_in_between( const DirectionH2& d1, const DirectionH2& d2 ) const; DirectionH2 operator-() const; VectorH2 to_vector() const; const RT & x() const { return Ptr()->e0; }; const RT & y() const { return Ptr()->e1; }; const RT & delta(int i) const; const RT & dx() const { return Ptr()->e0; }; const RT & dy() const { return Ptr()->e1; }; DirectionH2 perpendicular(const Orientation &o) const; DirectionH2 transform(const Aff_transformationH2 &) const; }; #ifdef CGAL_CFG_TYPENAME_BUG #define typename #endif template < class R > CGAL_KERNEL_CTOR_INLINE PointH2::PointH2() : Point_handle_2_ ( Point_ref_2()) {} template < class R > CGAL_KERNEL_CTOR_INLINE PointH2::PointH2(const Origin&) : Point_handle_2_ ( Point_ref_2( RT(0), RT(0), RT(1))) {} template < class R > CGAL_KERNEL_CTOR_INLINE PointH2::PointH2(const PointH2& p) : Point_handle_2_ (p) {} template < class R > CGAL_KERNEL_CTOR_INLINE PointH2::PointH2(const RT& hx, const RT& hy) : Point_handle_2_ ( Point_ref_2( hx, hy, RT(1) )) {} template < class R > CGAL_KERNEL_CTOR_INLINE PointH2::PointH2(const RT& hx, const RT& hy, const RT& hw) { if ( hw >= RT(0) ) { initialize_with( Point_ref_2( hx, hy, hw)); } else { initialize_with( Point_ref_2(-hx,-hy,-hw)); } } template < class R > CGAL_KERNEL_CTOR_INLINE PointH2::PointH2(const VectorH2& v) : Point_handle_2_ (v) {} template < class R > CGAL_KERNEL_INLINE bool PointH2::operator==( const PointH2& p) const { return ( (hx() * p.hw() == p.hx() * hw() ) &&(hy() * p.hw() == p.hy() * hw() ) ); } template < class R > inline bool PointH2::operator!=( const PointH2& p) const { return !(*this == p); } /* XXX */ template < class R > CGAL_KERNEL_INLINE typename PointH2::FT PointH2::cartesian(int i) const { CGAL_kernel_precondition( (i==0 || i==1) ); if (i==0) return x(); return y(); } template < class R > CGAL_KERNEL_INLINE const typename PointH2::RT & PointH2::homogeneous(int i) const { CGAL_kernel_precondition( (i>=0) && (i<=2) ); if (i==0) return hx(); if (i==1) return hy(); return hw(); } template < class R > inline typename PointH2::FT PointH2::operator[](int i) const { return cartesian(i); } template < class R > inline int PointH2::dimension() const { return 2; } template < class R > CGAL_KERNEL_INLINE DirectionH2 PointH2::direction() const { return DirectionH2(*this); } template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2() : Vector_handle_2_ ( Vector_ref_2()) {} template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2(const Null_vector &) : Vector_handle_2_ ( Vector_ref_2(RT(0), RT(0), RT(1) )) {} template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2(const VectorH2& v) : Vector_handle_2_ (v) {} template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2(const PointH2& a, const PointH2& b) : Vector_handle_2_ (b-a) {} template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2(const RT& x, const RT& y) : Vector_handle_2_ ( Vector_ref_2( x, y, RT(1) )) {} template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2(const RT& x, const RT& y, const RT& w) { if ( w >= RT(0) ) { initialize_with( Vector_ref_2( x, y, w)); } else { initialize_with( Vector_ref_2(-x, -y, -w)); } } template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2(const PointH2 & p) : Vector_handle_2_ ( p) {} template < class R > CGAL_KERNEL_CTOR_INLINE VectorH2::VectorH2(const DirectionH2 & dir) : Vector_handle_2_ ( dir) {} template < class R > inline bool VectorH2::operator==( const Null_vector&) const { return (hx() == RT(0)) && (hy() == RT(0)); } template < class R > inline bool VectorH2::operator!=( const Null_vector& v) const { return !(*this == v); } template < class R > CGAL_KERNEL_INLINE bool VectorH2::operator==( const VectorH2& v) const { return ( (hx() * v.hw() == v.hx() * hw() ) &&(hy() * v.hw() == v.hy() * hw() ) ); } template < class R > inline bool VectorH2::operator!=( const VectorH2& v) const { return !(*this == v); } /* XXX */ template < class R > CGAL_KERNEL_INLINE typename VectorH2::FT VectorH2::cartesian(int i) const { CGAL_kernel_precondition( (i==0 || i==1) ); if (i==0) return x(); return y(); } template < class R > CGAL_KERNEL_INLINE const typename VectorH2::RT & VectorH2::homogeneous(int i) const { CGAL_kernel_precondition( (i>=0) && (i<=2) ); if (i==0) return hx(); if (i==1) return hy(); return hw(); } template < class R > inline typename VectorH2::FT VectorH2::operator[](int i) const { return cartesian(i); } template < class R > inline int VectorH2::dimension() const { return 2; } template < class R > CGAL_KERNEL_INLINE DirectionH2 VectorH2::direction() const { return DirectionH2(*this); } template < class R > inline VectorH2 VectorH2::operator-() const { return VectorH2(- hx(), - hy(), hw() ); } template < class R > inline VectorH2 VectorH2::opposite() const { return VectorH2(- hx(), - hy(), hw() ); } template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2() : Direction_handle_2_ ( Direction_ref_2()) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const DirectionH2& d ) : Direction_handle_2_ ( d ) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const PointH2 & p ) : Direction_handle_2_ ( p) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const VectorH2 & v ) : Direction_handle_2_ ( v) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const LineH2 & l ) : Direction_handle_2_ ( l.direction()) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const RayH2 & r ) : Direction_handle_2_ ( r.direction()) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const SegmentH2 & s ) : Direction_handle_2_ ( s.direction()) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const RT& x, const RT& y) : Direction_handle_2_ ( Direction_ref_2( x, y, RT(1) )) {} template CGAL_KERNEL_CTOR_INLINE DirectionH2::DirectionH2(const RT& x, const RT& y, const RT& w ) { if (w > RT(0) ) { initialize_with( Direction_ref_2( x, y, w)); } else { initialize_with( Direction_ref_2(-x,-y,-w)); } } template CGAL_KERNEL_INLINE bool DirectionH2::operator==( const DirectionH2& d) const { return ( ( x() * d.y() == y() * d.x() ) &&( CGAL_NTS sign( x() ) == CGAL_NTS sign( d.x() ) ) &&( CGAL_NTS sign( y() ) == CGAL_NTS sign( d.y() ) ) ); } template inline bool DirectionH2::operator!=( const DirectionH2& d) const { return !(*this == d); } template inline DirectionH2 DirectionH2::operator-() const { return DirectionH2( - x(), - y() ); } template CGAL_KERNEL_INLINE const typename DirectionH2::RT & DirectionH2::delta(int i) const { CGAL_kernel_precondition( ( i == 0 ) || ( i == 1 ) ); if (i == 0) return dx(); return dy(); } template CGAL_KERNEL_INLINE VectorH2 operator+(const VectorH2& u, const VectorH2& v) { return VectorH2( u.hx()*v.hw() + v.hx()*u.hw(), u.hy()*v.hw() + v.hy()*u.hw(), u.hw()*v.hw() ); } template CGAL_KERNEL_INLINE VectorH2 operator-(const VectorH2& u, const VectorH2& v) { return VectorH2( u.hx()*v.hw() - v.hx()*u.hw(), u.hy()*v.hw() - v.hy()*u.hw(), u.hw()*v.hw() ); } template CGAL_KERNEL_INLINE typename VectorH2::FT VectorH2::operator*(const VectorH2& v) const { typedef typename R::RT RT; typedef typename R::FT FT; return FT( RT(hx()*v.hx() + hy()*v.hy()) ) / FT( RT(hw()*v.hw() ) ); } template CGAL_KERNEL_INLINE VectorH2 operator/(const VectorH2& v, const typename R::RT& f) { return VectorH2( v.hx(), v.hy(), v.hw()*f ); } template CGAL_KERNEL_INLINE VectorH2 operator*(const VectorH2& v, const typename R::RT& f) { return VectorH2( v.hx()*f, v.hy()*f, v.hw() ); } #ifdef __SUNPRO_CC template CGAL_KERNEL_INLINE VectorH2 operator*(const RT& f, const VectorH2& v) #else template CGAL_KERNEL_INLINE VectorH2 operator*(const typename R::RT& f, const VectorH2& v) #endif { return VectorH2( v.hx()*f, v.hy()*f, v.hw() ); } template inline PointH2 origin_plus_vector(const VectorH2& v) { return PointH2( v ); } template inline PointH2 operator+(const Origin&, const VectorH2& v) { return origin_plus_vector( v ); } template inline PointH2 origin_minus_vector(const VectorH2& v) { return PointH2( v.opposite() ); } template inline PointH2 operator-(const Origin&, const VectorH2& v) { return origin_minus_vector( v ); } template inline VectorH2 point_minus_origin(const PointH2& p) { return VectorH2( p ); } template inline VectorH2 operator-(const PointH2& p, const Origin&) { return point_minus_origin( p ); } template inline VectorH2 origin_minus_point(const PointH2& p) { return VectorH2( p ).opposite(); } template inline VectorH2 operator-(const Origin&, const PointH2& p) { return origin_minus_point( p ); } template CGAL_KERNEL_INLINE PointH2 operator+(const PointH2& p, const VectorH2& v) { return PointH2( p.hx()*v.hw() + v.hx()*p.hw(), p.hy()*v.hw() + v.hy()*p.hw(), p.hw()*v.hw() ); } template CGAL_KERNEL_INLINE PointH2 operator-(const PointH2& p, const VectorH2& v) { return PointH2( p.hx()*v.hw() - v.hx()*p.hw(), p.hy()*v.hw() - v.hy()*p.hw(), p.hw()*v.hw() ); } template CGAL_KERNEL_INLINE VectorH2 operator-(const PointH2& p, const PointH2& q) { return VectorH2( p.hx()*q.hw() - q.hx()*p.hw(), p.hy()*q.hw() - q.hy()*p.hw(), p.hw()*q.hw() ); } #ifdef CGAL_CFG_TYPENAME_BUG #undef typename #endif CGAL_END_NAMESPACE #include CGAL_BEGIN_NAMESPACE template inline bool DirectionH2::operator< (const DirectionH2& d) const { return (compare_angle_with_x_axis(*this,d) == SMALLER); } template inline bool DirectionH2::operator> (const DirectionH2& d) const { return (compare_angle_with_x_axis(*this,d) == LARGER); } template inline bool DirectionH2::operator>= (const DirectionH2& d) const { return !(compare_angle_with_x_axis(*this,d) == SMALLER); } template inline bool DirectionH2::operator<= (const DirectionH2& d) const { return !(compare_angle_with_x_axis(*this,d) == LARGER); } template CGAL_KERNEL_INLINE bool DirectionH2:: counterclockwise_in_between( const DirectionH2& d1, const DirectionH2& d2) const { if ( d1 < *this) { return ( *this < d2 )||( d2 <= d1 ); } else { return ( *this < d2 )&&( d2 <= d1 ); } } CGAL_END_NAMESPACE #include CGAL_BEGIN_NAMESPACE template < class R > CGAL_KERNEL_MEDIUM_INLINE Bbox_2 PointH2::bbox() const { #ifndef CGAL_CFG_NO_NAMESPACE using std::swap; #endif // CGAL_CFG_NO_NAMESPACE // double eps = exp2(-52); // the following is faster as it can be evaluated at compile time // and it is machine independent double eps = double(1.0) /(double(1<<26) * double(1<<26)); double hxd = CGAL::to_double( hx() ); double hyd = CGAL::to_double( hy() ); double hwd = CGAL::to_double( hw() ); double xmin = ( hxd - eps*hxd ) / ( hwd + eps*hwd ); double xmax = ( hxd + eps*hxd ) / ( hwd - eps*hwd ); double ymin = ( hyd - eps*hyd ) / ( hwd + eps*hwd ); double ymax = ( hyd + eps*hyd ) / ( hwd - eps*hwd ); if ( hx() < RT(0) ) { swap(xmin, xmax); } if ( hy() < RT(0) ) { swap(ymin, ymax); } return Bbox_2(xmin, ymin, xmax, ymax); } template < class R > inline PointH2 PointH2::transform(const Aff_transformationH2& t) const { return t.transform(*this); } #ifndef CGAL_NO_OSTREAM_INSERT_POINTH2 template < class R > std::ostream & operator<<(std::ostream &os, const PointH2 &p) { switch(os.iword(IO::mode)) { case IO::ASCII : return os << p.hx() << ' ' << p.hy() << ' ' << p.hw(); case IO::BINARY : write(os, p.hx()); write(os, p.hy()); write(os, p.hw()); return os; default: return os << "PointH2(" << p.hx() << ", " << p.hy() << ", " << p.hw() << ')'; } } #endif // CGAL_NO_OSTREAM_INSERT_POINTH2 #ifndef CGAL_NO_ISTREAM_EXTRACT_POINTH2 template < class R > std::istream & operator>>(std::istream &is, PointH2 &p) { typename R::RT hx, hy, hw; switch(is.iword(IO::mode)) { case IO::ASCII : is >> hx >> hy >> hw; break; case IO::BINARY : read(is, hx); read(is, hy); read(is, hw); break; default: std::cerr << "" << std::endl; std::cerr << "Stream must be in ascii or binary mode" << std::endl; break; } p = PointH2(hx, hy, hw); return is; } #endif // CGAL_NO_ISTREAM_EXTRACT_POINTH2 template < class R > CGAL_KERNEL_INLINE VectorH2 VectorH2::perpendicular(const Orientation& o) const { CGAL_kernel_precondition(o != COLLINEAR); if (o == COUNTERCLOCKWISE) { return VectorH2(-hy(), hx(), hw()); } else { return VectorH2(hy(), -hx(), hw()); } } template < class R > inline VectorH2 VectorH2::transform(const Aff_transformationH2& t) const { return t.transform(*this); } #ifndef CGAL_NO_OSTREAM_INSERT_VECTORH2 template < class R > std::ostream & operator<<(std::ostream &os, const VectorH2 &p) { switch(os.iword(IO::mode)) { case IO::ASCII : return os << p.hx() << ' ' << p.hy() << ' ' << p.hw(); case IO::BINARY : write(os, p.hx()); write(os, p.hy()); write(os, p.hw()); return os; default: return os << "VectorH2(" << p.hx() << ", " << p.hy() << ", " << p.hw() << ')'; } } #endif // CGAL_NO_OSTREAM_INSERT_VECTORH2 #ifndef CGAL_NO_ISTREAM_EXTRACT_VECTORH2 template < class R > std::istream & operator>>(std::istream &is, VectorH2 &p) { typename R::RT hx, hy, hw; switch(is.iword(IO::mode)) { case IO::ASCII : is >> hx >> hy >> hw; break; case IO::BINARY : read(is, hx); read(is, hy); read(is, hw); break; default: std::cerr << "" << std::endl; std::cerr << "Stream must be in ascii or binary mode" << std::endl; break; } p = VectorH2(hx, hy, hw); return is; } #endif // CGAL_NO_ISTREAM_EXTRACT_VECTORH2 template CGAL_KERNEL_INLINE DirectionH2 DirectionH2::perpendicular(const Orientation& o) const { CGAL_kernel_precondition(o != COLLINEAR); if (o == COUNTERCLOCKWISE) { return DirectionH2(-dy(), dx()); } else { return DirectionH2(dy(), -dx()); } } template inline DirectionH2 DirectionH2:: transform(const Aff_transformationH2& t) const { return t.transform(*this); } template CGAL_KERNEL_INLINE VectorH2 DirectionH2::to_vector() const { return VectorH2( x(), y() ); } #ifndef CGAL_NO_OSTREAM_INSERT_DIRECTIONH2 template < class R > std::ostream & operator<<(std::ostream &os, const DirectionH2 &p) { switch(os.iword(IO::mode)) { case IO::ASCII : return os << p.dx() << ' ' << p.dy(); case IO::BINARY : write(os, p.dx()); write(os, p.dy()); return os; default: return os << "DirectionH2(" << p.dx() << ", " << p.dy() << ')'; } } #endif // CGAL_NO_OSTREAM_INSERT_DIRECTIONH2 #ifndef CGAL_NO_ISTREAM_EXTRACT_DIRECTIONH2 template < class R > std::istream & operator>>(std::istream &is, DirectionH2 &p) { typename R::RT x, y; switch(is.iword(IO::mode)) { case IO::ASCII : is >> x >> y; break; case IO::BINARY : read(is, x); read(is, y); break; default: std::cerr << "" << std::endl; std::cerr << "Stream must be in ascii or binary mode" << std::endl; break; } p = DirectionH2(x, y); return is; } #endif // CGAL_NO_ISTREAM_EXTRACT_DIRECTIONH2 CGAL_END_NAMESPACE #endif // CGAL_PVDH2_H