// ====================================================================== // // 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 : PlaneH3.h // package : H3 // revision : $Revision$ // revision_date : $Date$ // author(s) : Stefan Schirra // // // coordinator : MPI, Saarbruecken () // ====================================================================== #ifndef CGAL_PLANEH3_H #define CGAL_PLANEH3_H #include #include #include #include #include #include CGAL_BEGIN_NAMESPACE template < class R_ > class PlaneH3 : public R_::Plane_handle_3 { public: typedef R_ R; typedef typename R::RT RT; typedef typename R::FT FT; typedef typename R::Plane_handle_3 Plane_handle_3_; typedef typename Plane_handle_3_::element_type Plane_ref_3; PlaneH3() : Plane_handle_3_(Plane_ref_3()) {} PlaneH3(const PointH3&, const PointH3&, const PointH3& ); PlaneH3(const RT& a, const RT& b, const RT& c, const RT& d ); PlaneH3(const PointH3&, const RayH3& ); PlaneH3(const PointH3&, const LineH3& ); PlaneH3(const PointH3&, const SegmentH3& ); PlaneH3(const LineH3&, const PointH3& ); PlaneH3(const SegmentH3&, const PointH3& ); PlaneH3(const RayH3&, const PointH3& ); PlaneH3(const PointH3&, const DirectionH3& ); PlaneH3(const PointH3&, const VectorH3& ); PlaneH3(const PointH3&, const DirectionH3&, const DirectionH3& ); const RT & a() const; const RT & b() const; const RT & c() const; const RT & d() const; bool operator==( const PlaneH3& ) const; bool operator!=( const PlaneH3& ) const; LineH3 perpendicular_line(const PointH3& ) const; PlaneH3 opposite() const; // plane with opposite orientation PointH3 projection(const PointH3& ) const; PointH3 point() const; // same point on the plane DirectionH3 orthogonal_direction() const; VectorH3 orthogonal_vector() const; Oriented_side oriented_side(const PointH3 &p) const; bool has_on(const PointH3 &p) const; bool has_on(const LineH3 &p) const; #ifndef CGAL_NO_DEPRECATED_CODE bool has_on_boundary(const PointH3 &p) const; bool has_on_boundary(const LineH3 &p) const; #endif // CGAL_NO_DEPRECATED_CODE bool has_on_positive_side(const PointH3&l) const; bool has_on_negative_side(const PointH3&l) const; bool is_degenerate() const; PlaneH3 transform(const Aff_transformationH3& ) const; Aff_transformationH3 transform_to_2d() const; PointH2 to_2d(const PointH3& ) const; PointH3 to_3d(const PointH2& ) const; VectorH3 base1() const; VectorH3 base2() const; protected: PointH3 point1() const; // same point different from point() PointH3 point2() const; // same point different from point() // and point1() void new_rep(const PointH3 &p, const PointH3 &q, const PointH3 &r); void new_rep(const RT &a, const RT &b, const RT &c, const RT &d); }; // // a() * X + b() * Y + c() * Z() + d() * W() == 0 // // | X Y Z W | // | p.hx() p.hy() p.hz() p.hw() | // | q.hx() q.hy() q.hz() q.hw() | // | r.hx() r.hy() r.hz() r.hw() | // // Fourtuple ( a(), b(), c(), d() ) template < class R > inline void PlaneH3::new_rep(const PointH3 &p, const PointH3 &q, const PointH3 &r) { RT phx = p.hx(); RT phy = p.hy(); RT phz = p.hz(); RT phw = p.hw(); RT qhx = q.hx(); RT qhy = q.hy(); RT qhz = q.hz(); RT qhw = q.hw(); RT rhx = r.hx(); RT rhy = r.hy(); RT rhz = r.hz(); RT rhw = r.hw(); initialize_with( Plane_ref_3 ( phy*( qhz*rhw - qhw*rhz ) - qhy*( phz*rhw - phw*rhz ) // * X + rhy*( phz*qhw - phw*qhz ), - phx*( qhz*rhw - qhw*rhz ) + qhx*( phz*rhw - phw*rhz ) // * Y - rhx*( phz*qhw - phw*qhz ), phx*( qhy*rhw - qhw*rhy ) - qhx*( phy*rhw - phw*rhy ) // * Z + rhx*( phy*qhw - phw*qhy ), - phx*( qhy*rhz - qhz*rhy ) + qhx*( phy*rhz - phz*rhy ) // * W - rhx*( phy*qhz - phz*qhy ) ) ); } template < class R > inline void PlaneH3::new_rep(const RT &a, const RT &b, const RT &c, const RT &d) { initialize_with( Plane_ref_3 (a, b, c, d) ); } template < class R > inline bool PlaneH3::operator!=(const PlaneH3& l) const { return !(*this == l); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const PointH3& p, const PointH3& q, const PointH3& r) { new_rep(p,q,r); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const RT& a, const RT& b, const RT& c, const RT& d) { new_rep(a,b,c,d); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const PointH3& p , const LineH3& l) { new_rep(p, l.point(0), l.point(1) ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const PointH3& p, const SegmentH3& s) { new_rep(p, s.source(), s.target() ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const PointH3& p , const RayH3& r) { new_rep(p, r.start(), r.start() + r.direction().to_vector() ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const LineH3& l , const PointH3& p) { new_rep(l.point(0), p, l.point(1) ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const SegmentH3& s, const PointH3& p) { new_rep(s.source(), p, s.target() ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const RayH3& r, const PointH3& p) { new_rep(r.start(), p, r.start() + r.direction().to_vector() ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const PointH3& p, const DirectionH3& d) { VectorH3 ov = d.to_vector(); new_rep( ov.hx()*p.hw(), ov.hy()*p.hw(), ov.hz()*p.hw(), -(ov.hx()*p.hx() + ov.hy()*p.hy() + ov.hz()*p.hz() ) ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const PointH3& p, const VectorH3& ov) { new_rep( ov.hx()*p.hw(), ov.hy()*p.hw(), ov.hz()*p.hw(), -(ov.hx()*p.hx() + ov.hy()*p.hy() + ov.hz()*p.hz() ) ); } template < class R > CGAL_KERNEL_CTOR_INLINE PlaneH3::PlaneH3(const PointH3& p, const DirectionH3& d1, const DirectionH3& d2) { new_rep( p, p + d1.to_vector(), p + d2.to_vector() ); } template < class R > inline const typename PlaneH3::RT & PlaneH3::a() const { return Ptr()->e0; } template < class R > inline const typename PlaneH3::RT & PlaneH3::b() const { return Ptr()->e1; } template < class R > inline const typename PlaneH3::RT & PlaneH3::c() const { return Ptr()->e2; } template < class R > inline const typename PlaneH3::RT & PlaneH3::d() const { return Ptr()->e3; } template < class R > CGAL_KERNEL_INLINE LineH3 PlaneH3::perpendicular_line(const PointH3& p) const { return LineH3( p, orthogonal_direction() ); } template < class R > CGAL_KERNEL_INLINE PlaneH3 PlaneH3::opposite() const { return PlaneH3(-a(), -b(), -c(), -d() ); } template < class R > CGAL_KERNEL_INLINE PointH3 PlaneH3::projection(const PointH3& p) const { return _projection( p, *this ); } template < class R > CGAL_KERNEL_INLINE PointH3 PlaneH3::point() const { const RT RT0(0); if ( a() != RT0 ) { return PointH3( -d(), RT0, RT0, a() ); } if ( b() != RT0 ) { return PointH3( RT0, -d(), RT0, b() ); } CGAL_kernel_assertion ( c() != RT0); return PointH3( RT0, RT0, -d(), c() ); } template < class R > CGAL_KERNEL_INLINE VectorH3 PlaneH3::base1() const { // point(): // a() != RT0 : PointH3( -d(), RT0, RT0, a() ); // b() != RT0 : PointH3( RT0, -d(), RT0, b() ); // : PointH3( RT0, RT0, -d(), c() ); // point1(): // a() != RT0 : PointH3( -b()-d(), a(), RT0, a() ); // b() != RT0 : PointH3( RT0, -c()-d(), b(), b() ); // : PointH3( c(), RT0, -a()-d(), c() ); const RT RT0(0); if ( a() != RT0 ) { return VectorH3( -b(), a(), RT0, a() ); } if ( b() != RT0 ) { return VectorH3( RT0, -c(), b(), b() ); } CGAL_kernel_assertion ( c() != RT(0) ); return VectorH3( c(), RT0, -a(), c() ); } template < class R > inline VectorH3 PlaneH3::base2() const { VectorH3 a = orthogonal_vector(); VectorH3 b = base1(); return VectorH3(a.hy()*b.hz() - a.hz()*b.hy(), a.hz()*b.hx() - a.hx()*b.hz(), a.hx()*b.hy() - a.hy()*b.hx(), a.hw()*b.hw() ); } // Actually, the following should work, but bcc doesn't like it: // { return cross_product( orthogonal_vector(), base1() ); } template < class R > inline PointH3 PlaneH3::point1() const { return point() + base1(); } template < class R > inline PointH3 PlaneH3::point2() const { return point() + base2(); } template < class R > inline DirectionH3 PlaneH3::orthogonal_direction() const { return DirectionH3(a(), b(), c() ); } template < class R > inline VectorH3 PlaneH3::orthogonal_vector() const { return VectorH3(a(), b(), c() ); } template < class R > PlaneH3 PlaneH3::transform(const Aff_transformationH3& t) const { return t.transform(*this); } #ifndef CGAL_NO_OSTREAM_INSERT_PLANE3 template < class R > std::ostream &operator<<(std::ostream &os, const PlaneH3 &p) { switch(os.iword(IO::mode)) { case IO::ASCII : return os << p.a() << ' ' << p.b() << ' ' << p.c() << ' ' << p.d(); case IO::BINARY : write(os, p.a()); write(os, p.b()); write(os, p.c()); write(os, p.d()); return os; default: os << "PlaneC3(" << p.a() << ", " << p.b() << ", "; os << p.c() << ", " << p.d() <<")"; return os; } } #endif // CGAL_NO_OSTREAM_INSERT_PLANE3 #ifndef CGAL_NO_ISTREAM_EXTRACT_PLANE3 template < class R > std::istream &operator>>(std::istream &is, PlaneH3 &p) { typename R::RT a, b, c, d; switch(is.iword(IO::mode)) { case IO::ASCII : is >> a >> b >> c >> d; break; case IO::BINARY : read(is, a); read(is, b); read(is, c); read(is, d); break; default: std::cerr << "" << std::endl; std::cerr << "Stream must be in ascii or binary mode" << std::endl; break; } p = PlaneH3(a, b, c, d); return is; } #endif // CGAL_NO_ISTREAM_EXTRACT_PLANE3 template < class R > bool PlaneH3::is_degenerate() const { const RT RT0(0); return ( (a() == RT0 ) && (b() == RT0 ) && (c() == RT0 ) ); } template < class R > bool PlaneH3::has_on_positive_side( const PointH3& p) const { return (a()*p.hx() + b()*p.hy() + c()*p.hz() + d()*p.hw() > RT(0) ); } template < class R > bool PlaneH3::has_on_negative_side( const PointH3& p) const { return (a()*p.hx() + b()*p.hy() + c()*p.hz() + d()*p.hw() < RT(0) ); } template < class R > bool PlaneH3::has_on( const PointH3& p) const { return (a()*p.hx() + b()*p.hy() + c()*p.hz() + d()*p.hw() == RT(0) ); } template < class R > bool PlaneH3::has_on( const LineH3& l) const { PointH3 p = l.point(); VectorH3 ld = l.direction().to_vector(); VectorH3 ov = orthogonal_vector(); return ( ( a()*p.hx() + b()*p.hy() + c()*p.hz() + d()*p.hw() == RT(0) ) &&( ld.hx()*ov.hx() + ld.hy()*ov.hy() + ld.hz()*ov.hz() == RT(0) ) ); } #ifndef CGAL_NO_DEPRECATED_CODE template < class R > bool PlaneH3::has_on_boundary( const PointH3& p) const { return has_on(p); } template < class R > bool PlaneH3::has_on_boundary( const LineH3& l) const { return has_on(l); } #endif template < class R > Oriented_side PlaneH3::oriented_side( const PointH3& p) const { RT value = a()*p.hx() + b()*p.hy() + c()*p.hz() + d()*p.hw() ; if (value > RT(0) ) { return ON_POSITIVE_SIDE; } else { return (value < RT(0) ) ? ON_NEGATIVE_SIDE : ON_ORIENTED_BOUNDARY; } } template < class R > bool PlaneH3::operator==(const PlaneH3& l) const { if ( (a() * l.d() != l.a() * d() ) ||(b() * l.d() != l.b() * d() ) ||(c() * l.d() != l.c() * d() ) ) { return false; } int sd = static_cast(CGAL_NTS sign(d())); int sld = static_cast(CGAL_NTS sign(l.d())); if ( sd == sld ) { if (sd == 0) { return ( (a()*l.b() == b()*l.a() ) &&(a()*l.c() == c()*l.a() ) &&(b()*l.c() == c()*l.b() ) &&(CGAL_NTS sign(a() )== CGAL_NTS sign( l.a() )) &&(CGAL_NTS sign(b() )== CGAL_NTS sign( l.b() )) &&(CGAL_NTS sign(c() )== CGAL_NTS sign( l.c() )) ); } else { return true; } } else { return false; } } CGAL_END_NAMESPACE #include CGAL_BEGIN_NAMESPACE template < class R > Aff_transformationH3 PlaneH3::transform_to_2d() const { const RT RT0(0); const RT RT1(1); VectorH3 nov = orthogonal_vector(); VectorH3 e1v = point1()-point() ; VectorH3 e2v = point2()-point() ; RT orthohx = nov.hx(); RT orthohy = nov.hy(); RT orthohz = nov.hz(); RT e1phx = e1v.hx(); RT e1phy = e1v.hy(); RT e1phz = e1v.hz(); RT e2phx = e2v.hx(); RT e2phy = e2v.hy(); RT e2phz = e2v.hz(); RT t11 = -( orthohy*e2phz - orthohz*e2phy ); RT t12 = ( orthohx*e2phz - orthohz*e2phx ); RT t13 = -( orthohx*e2phy - orthohy*e2phx ); RT t21 = ( orthohy*e1phz - orthohz*e1phy ); RT t22 = -( orthohx*e1phz - orthohz*e1phx ); RT t23 = ( orthohx*e1phy - orthohy*e1phx ); RT t31 = ( e1phy*e2phz - e1phz*e2phy ); RT t32 = -( e1phx*e2phz - e1phz*e2phx ); RT t33 = ( e1phx*e2phy - e1phy*e2phx ); RT scale = det3x3_by_formula( orthohx, orthohy, orthohz, e1phx, e1phy, e1phz, e2phx, e2phy, e2phz ); Aff_transformationH3 point_to_origin(TRANSLATION, - ( point() - ORIGIN ) ); Aff_transformationH3 rotate_and_more( t11, t12, t13, RT0, t21, t22, t23, RT0, t31, t32, t33, RT0, scale); PointH3 ortho( orthohx, orthohy, orthohz ); PointH3 e1p( e1phx, e1phy, e1phz ); PointH3 e2p( e2phx, e2phy, e2phz ); CGAL_kernel_assertion(( ortho.transform(rotate_and_more) == PointH3( RT(0), RT(0), RT(1)) )); CGAL_kernel_assertion(( e1p.transform(rotate_and_more) == PointH3( RT(1), RT(0), RT(0)) )); CGAL_kernel_assertion(( e2p.transform(rotate_and_more) == PointH3( RT(0), RT(1), RT(0)) )); return rotate_and_more * point_to_origin; } template < class R > CGAL_KERNEL_INLINE PointH2 PlaneH3::to_2d(const PointH3& p) const { PointH3 tp = p.transform( transform_to_2d() ); return PointH2( tp.hx(), tp.hy(), tp.hw()); } template < class R > CGAL_KERNEL_INLINE PointH3 PlaneH3::to_3d(const PointH2& p) const { PointH3 hp( p.hx(), p.hy(), RT(0.0), p.hw()); return hp.transform( transform_to_2d().inverse() ); } CGAL_END_NAMESPACE #endif // CGAL_PLANEH3_H