// Copyright (c) 2000,2001 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // // // Author(s) : Michael Seel #ifndef CGAL_DIRECTIONHD_H #define CGAL_DIRECTIONHD_H #include #include #include #include #include #include namespace CGAL { template class DirectionHd; template std::istream& operator>>(std::istream&, DirectionHd&); template std::ostream& operator<<(std::ostream&, const DirectionHd&); /*{\Manpage{Direction_d}{R}{Directions in d-space}{dir}}*/ /*{\Msubst Hd#_d VectorHd#Vector_d DirectionHd#Direction_d Quotient#FT }*/ template class DirectionHd : public Handle_for< Tuple_d<_RT,_LA> > { typedef Tuple_d<_RT,_LA> Tuple; typedef Handle_for Base; typedef DirectionHd<_RT,_LA> Self; using Base::ptr; /*{\Mdefinition A |DirectionHd| is a vector in the $d$-dimensional vector space where we forget about its length. We represent directions in $d$-dimensional space as a tuple $(h_0,\ldots,h_d)$ of variables of type |RT| which we call the homogeneous coordinates of the direction. The coordinate $h_d$ must be positive. The Cartesian coordinates of a direction are $c_i = h_i/h_d$ for $0 \le i < d$, which are of type |Quotient|. Two directions are equal if their Cartesian coordinates are positive multiples of each other. Directions are in one-to-one correspondence to points on the unit sphere.}*/ const typename _LA::Vector& vector_rep() const { return ptr()->v; } _RT& entry(int i) { return ptr()->v[i]; } const _RT& entry(int i) const { return ptr()->v[i]; } void invert_rep() { ptr()->invert(); } public: /*{\Mtypes 4}*/ typedef _RT RT; /*{\Mtypemember the ring type.}*/ typedef Quotient<_RT> FT; /*{\Mtypemember the field type.}*/ typedef _LA LA; /*{\Mtypemember the linear algebra layer.}*/ typedef typename Tuple::const_iterator Delta_const_iterator; /*{\Mtypemember a read-only iterator for the deltas of |\Mvar|.}*/ class Base_direction {}; /*{\Mtypemember construction tag.}*/ friend class VectorHd; /*{\Mcreation 4}*/ DirectionHd(int d = 0) : Base( Tuple(d+1) ) /*{\Mcreate introduces a variable |\Mvar| of type |DirectionHd| initialized to some direction in $d$-dimensional space.}*/ { if (d>0) entry(d) = 1; } DirectionHd(const VectorHd& v); /*{\Mcreate introduces a variable |\Mvar| of type |DirectionHd| initialized to the direction of |v|.}*/ template DirectionHd(int d, InputIterator first, InputIterator last) : Base( Tuple(d+1,first,last,1) ) {} /*{\Mcreate introduces a variable |\Mvar| of type |\Mname| in dimension |d| with representation tuple |set [first,last)|. \precond |d| is nonnegative, |[first,last)| has |d| elements and the value type of |InputIterator| is |RT|.}*/ DirectionHd(int d, Base_direction, int i) : Base( Tuple(d+1) ) /*{\Mcreate returns a variable |\Mvar| of type |\Mname| initialized to the direction of the $i$-th base vector of dimension $d$. \precond $0 \leq i < d$.}*/ { entry(d) = 1; if ( d==0 ) return; CGAL_assertion_msg((0<=i&&i& p) : Base(p) {} ~DirectionHd() {} /*{\Moperations 5 3}*/ int dimension() const { return ptr()->size()-1; } /*{\Mop returns the dimension of |\Mvar|. }*/ RT delta(int i) const /*{\Mop returns the $i$-th component of |\Mvar|. \precond $0 \leq i < d$.}*/ { CGAL_assertion_msg((0<=i && i<(dimension())), "DirectionHd::delta():\ index out of range."); return entry(i); } RT D() { return entry(dimension()); } RT operator[](int i) const /*{\Marrop returns the $i$-th delta of |\Mvar|. \precond $0 \leq i < d$.}*/ { return delta(i); } Delta_const_iterator deltas_begin() const { return ptr()->begin(); } /*{\Mop returns an iterator pointing to the first delta of |\Mvar|. }*/ Delta_const_iterator deltas_end() const { return ptr()->last(); } /*{\Mop returns an iterator pointing beyond the last delta of |\Mvar|. }*/ VectorHd vector() const; /*{\Mop returns a vector pointing in direction |\Mvar|. }*/ bool is_degenerate() const /*{\Mop returns true iff |\Mvar.vector()| is the zero vector.}*/ { for (int i=0; i transform(const Aff_transformationHd& t) const; /*{\Mop returns $t(p)$. }*/ DirectionHd opposite() const /*{\Mop returns the direction opposite to |\Mvar|. }*/ { DirectionHd result(*this); // creates a copied object! result.copy_on_write(); // creates a copied object! result.ptr()->invert(dimension()); return result; } DirectionHd operator- () const /*{\Munop returns the direction opposite to |\Mvar|.}*/ { return opposite(); } static Comparison_result cmp( const DirectionHd& h1, const DirectionHd& h2); bool operator==(const DirectionHd& w) const { if ( this->identical(w) ) return true; if ( dimension()!=w.dimension() ) return false; return (DirectionHd::cmp(*this,w) == EQUAL); } bool operator!=(const DirectionHd& w) const { return !operator==(w); } /*{\Mtext \headerline{Downward compatibility} We provide all operations of the lower dimensional interface |dx()|, |dy()|, |dz()|.}*/ RT dx() const { return delta(0); } RT dy() const { return delta(1); } RT dz() const { return delta(2); } friend std::istream& operator>> <> (std::istream& I, DirectionHd& d); friend std::ostream& operator<< <> (std::ostream& O, const DirectionHd& d); }; // end of class DirectionHd /*{\Mimplementation Directions are implemented by arrays of integers as an item type. All operations like creation, initialization, tests, inversion, input and output on a direction $d$ take time $O(|d.dimension()|)$. |dimension()|, coordinate access and conversion take constant time. The space requirement is $O(|d.dimension()|)$. }*/ } //namespace CGAL #endif // CGAL_DIRECTIONHD_H //----------------------- end of file ----------------------------------