dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/Kernel_d/VectorHd.h

425 lines
14 KiB
C++
Executable File

// 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_VECTORHD_H
#define CGAL_VECTORHD_H
#include <CGAL/basic.h>
#include <CGAL/Quotient.h>
#include <CGAL/Kernel_d/Tuple_d.h>
#include <CGAL/Kernel_d/PointHd.h>
#include <CGAL/Kernel_d/Aff_transformationHd.h>
namespace CGAL {
#define PointHd PointHd2
template <class RT, class LA> class VectorHd;
template <class RT, class LA>
std::istream& operator>>(std::istream&, VectorHd<RT,LA>&);
template <class RT, class LA>
std::ostream& operator<<(std::ostream&, const VectorHd<RT,LA>&);
/*{\Manpage {Vector_d}{R}{Vectors in d-space}{v}}*/
/*{\Msubst
Hd<RT,LA>#_d<R>
VectorHd#Vector_d
PointHd#Point_d
Quotient<RT>#FT
}*/
template <class _RT, class _LA>
class VectorHd : public Handle_for< Tuple_d<_RT,_LA> > {
typedef Tuple_d<_RT,_LA> Tuple;
typedef Handle_for<Tuple> Base;
typedef VectorHd<_RT,_LA> Self;
using Base::ptr;
using Base::copy_on_write;
/*{\Mdefinition
An instance of data type |\Mname| is a vector of Euclidean space in
dimension $d$. A vector $r = (r_0,\ldots,r_{ d - 1})$ can be represented
in homogeneous coordinates $(h_0,\ldots,h_d)$ of number type |RT|,
such that $r_i = h_i/h_d$ which is of type |FT|. We call the
$r_i$'s the Cartesian coordinates of the vector. The homogenizing
coordinate $h_d$ is positive.
This data type is meant for use in computational geometry. It realizes
free vectors as opposed to position vectors (type |PointHd|). The
main difference between position vectors and free vectors is their
behavior under affine transformations, e.g., free vectors are
invariant under translations.}*/
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(); }
VectorHd(const Base& b) : Base(b) {}
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::Cartesian_const_iterator Cartesian_const_iterator;
/*{\Mtypemember a read-only iterator for the Cartesian coordinates.}*/
typedef typename Tuple::const_iterator Homogeneous_const_iterator;
/*{\Mtypemember a read-only iterator for the homogeneous coordinates.}*/
class Base_vector {};
/*{\Mtypemember construction tag.}*/
friend class PointHd<RT,LA>;
friend class DirectionHd<RT,LA>;
friend class HyperplaneHd<RT,LA>;
/*{\Mcreation 4}*/
VectorHd(int d = 0) : Base( Tuple(d+1) )
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| in
$d$-dimensional space.}*/
{ if ( d > 0 ) entry(d) = 1; }
VectorHd(int d, Null_vector) : Base( Tuple(d+1) )
/*{\Mcreate introduces the zero vector |\Mvar| of type |\Mname| in
$d$-dimensional space. There is a constant |CGAL::NULL_VECTOR| that
can be used for the second argument.}*/
{ if ( d > 0 ) entry(d) = 1; }
template <class InputIterator>
VectorHd(int d, InputIterator first, InputIterator last) :
Base( Tuple(d+1,first,last) )
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| in dimension |d|.
If |size [first,last) == d| this creates a vector with Cartesian coordinates
|set [first,last)|. If |size [first,last) == p+1| the range specifies the
homogeneous coordinates $|H = set [first,last)| = (\pm h_0, \pm h_1, \ldots,
\pm h_d)$ where the sign chosen is the sign of $h_d$.
\precond |d| is nonnegative, |[first,last)| has |d| or |d+1| elements where the
last has to be non-zero, and the value type of |InputIterator| is |RT|.}*/
{ RT D = entry(d);
if ( D == RT(0) ) entry(d) = 1;
if ( D < RT(0) ) invert_rep();
}
template <class InputIterator>
VectorHd(int d, InputIterator first, InputIterator last,
const RT& D) : Base( Tuple(d+1,first,last,D) )
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname|
in dimension |d| initialized to the vector with homogeneous
coordinates as defined by |H = set [first,last)| and |D|:
$(\pm |H[0]|, \pm|H[1]|, \ldots, \pm|H[d-1]|, \pm|D|)$. The sign chosen
is the sign of $D$. \precond |D| is non-zero, the iterator range defines
a $d$-tuple of |RT|, and the value type of |InputIterator| is |RT|. }*/
{ CGAL_assertion_msg(D!=RT(0), "VectorHd::constructor: D must be nonzero.");
if (D < RT(0)) invert_rep();
}
VectorHd(int d, Base_vector, int i) : Base( Tuple(d+1) )
/*{\Mcreate returns a variable |\Mvar| of type |\Mname| initialized
to the $i$-th base vector of dimension $d$. }*/
{ entry(d) = 1;
if ( d == 0 ) return;
CGAL_assertion_msg((0<=i&&i<d),"VectorHd::base: index out of range.");
entry(i) = 1;
}
VectorHd(const RT& x, const RT& y, const RT& w = 1)
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| in
$2$-dimensional space. }*/
: Base( Tuple(x,y,w) )
{ CGAL_assertion_msg((w != 0), "VectorHd::construction: w == 0.");
if (w < 0) invert_rep();
}
VectorHd(int a, int b, int c = 1) :
Base( Tuple((RT)a,(RT)b,(RT)c, MatchHelper()) )
{ CGAL_assertion_msg((c != 0), "VectorHd::construction: w == 0.");
if (c < 0) invert_rep();
}
VectorHd(const RT& x, const RT& y, const RT& z, const RT& w)
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname| in
$3$-dimensional space. }*/
: Base( Tuple((RT)x,(RT)y,(RT)z,(RT)w) )
{ CGAL_assertion_msg((w!=0), "VectorHd::construction: w == 0.");
if (w < 0) invert_rep();
}
VectorHd(int a, int b, int c, int d) :
Base( Tuple((RT)a,(RT)b,(RT)c,(RT)d) )
{ CGAL_assertion_msg((d!=0), "VectorHd::construction: w == 0.");
if (d < 0) invert_rep();
}
VectorHd(const VectorHd<RT,LA>& p) : Base(p) {}
~VectorHd() {}
/*{\Moperations 5 3 }*/
int dimension() const { return ptr()->size()-1; }
/*{\Mop returns the dimension of |\Mvar|. }*/
Quotient<RT> cartesian(int i) const
/*{\Mop returns the $i$-th Cartesian coordinate of |\Mvar|.
\precond $0 \leq i < d$.}*/
{ CGAL_assertion_msg((0<=i && i<(dimension())), "VectorHd::cartesian():\
index out of range.");
return Quotient<RT>(entry(i), entry(dimension()));
}
Quotient<RT> operator[](int i) const { return cartesian(i); }
/*{\Marrop returns the $i$-th Cartesian coordinate of |\Mvar|.
\precond $0 \leq i < d$.}*/
RT homogeneous(int i) const
/*{\Mop returns the $i$-th homogeneous coordinate of |\Mvar|.
\precond $0 \leq i \leq d$.}*/
{ CGAL_assertion_msg((0<=i && i<=(dimension())), "VectorHd::homogeneous():\
index out of range.");
return entry(i);
}
Quotient<RT> squared_length() const
/*{\Mop returns the square of the length of |\Mvar|. }*/
{ RT nom = 0;
for (int i = 0; i < dimension(); i++)
nom += CGAL_NTS square(homogeneous(i));
RT denom = CGAL_NTS square(homogeneous(dimension()));
return Quotient<RT>(nom,denom);
}
Cartesian_const_iterator cartesian_begin() const
/*{\Mop returns an iterator pointing to the zeroth Cartesian coordinate
of |\Mvar|. }*/
{ return Cartesian_const_iterator(ptr()->begin(),ptr()->last()); }
Cartesian_const_iterator cartesian_end() const
/*{\Mop returns an iterator pointing beyond the last Cartesian coordinate
of |\Mvar|. }*/
{ return Cartesian_const_iterator(ptr()->last(),ptr()->last()); }
Homogeneous_const_iterator homogeneous_begin() const
/*{\Mop returns an iterator pointing to the zeroth homogeneous coordinate
of |\Mvar|. }*/
{ return ptr()->begin(); }
Homogeneous_const_iterator homogeneous_end() const
/*{\Mop returns an iterator pointing beyond the last homogeneous
coordinate of |\Mvar|. }*/
{ return ptr()->end(); }
inline PointHd<RT,LA> to_point() const;
inline DirectionHd<RT,LA> direction() const;
/*{\Mop returns the direction of |\Mvar|. }*/
VectorHd<RT,LA> transform(const Aff_transformationHd<RT,LA>& t) const;
/*{\Mop returns $t(v)$. }*/
/*{\Mtext \headerline{Arithmetic Operators, Tests and IO}}*/
VectorHd<RT,LA> scale(const RT& m, const RT& n) const
{ int d = dimension();
VectorHd<RT,LA> result(d);
result.entry(d) = entry(d) * n;
for (int i = 0; i < d; i++)
result.entry(i) = entry(i) * m;
return result;
}
void self_scale(const RT& m, const RT& n)
{ int d = dimension();
copy_on_write();
entry(d) *= n;
for (int i = 0; i < d; i++) entry(i) *= m;
}
VectorHd<RT,LA>& operator*=(const RT& n)
/*{\Mbinop multiplies all Cartesian coordinates by |n|.}*/
{ self_scale(n,1); return *this; }
VectorHd<RT,LA>& operator*=(int n)
{ self_scale(n,1); return *this; }
VectorHd<RT,LA>& operator*=(const Quotient<RT>& r)
/*{\Mbinop multiplies all Cartesian coordinates by |r|.}*/
{ self_scale(r.numerator(),r.denominator()); return *this; }
VectorHd<RT,LA> operator/(int n) const
{ return scale(1,n); }
VectorHd<RT,LA> operator/(const RT& n) const
/*{\Mbinop returns the vector with Cartesian coordinates
$v_i/n, 0 \leq i < d$.}*/
{ return scale(1,n); }
VectorHd<RT,LA> operator/(const Quotient<RT>& r) const
/*{\Mbinop returns the vector with Cartesian coordinates
$v_i/r, 0 \leq i < d$.}*/
{ return scale(r.denominator(),r.numerator()); }
VectorHd<RT,LA>& operator/=(const RT& n)
{ self_scale(1,n); return *this; }
/*{\Mbinop divides all Cartesian coordinates by |n|.}*/
VectorHd<RT,LA>& operator/=(int n)
{ self_scale(1,n); return *this; }
VectorHd<RT,LA>& operator/=(const Quotient<RT>& r)
{ self_scale(r.denominator(),r.numerator()); return *this; }
/*{\Mbinop divides all Cartesian coordinates by |r|.}*/
Quotient<RT>
operator* (const VectorHd<RT,LA>& w) const
/*{\Mbinop inner product, i.e., $\sum_{ 0 \le i < d } v_i w_i$,
where $v_i$ and $w_i$ are the Cartesian coordinates of $v$ and $w$
respectively. }*/
{ int d = dimension();
CGAL_assertion_msg((d==w.dimension()),
"inner product: dimensions disagree.");
RT nom = 0;
for (int i = 0; i < d; i++)
nom += homogeneous(i) * w.homogeneous(i);
RT denom = homogeneous(d) * w.homogeneous(d);
return Quotient<RT>(nom,denom);
}
VectorHd<RT,LA> operator+(const VectorHd<RT,LA>& w) const
/*{\Mbinop returns the vector with Cartesian coordinates
$v_i+w_i, 0 \leq i < d$.}*/
{ VectorHd<RT,LA> res(dimension());
res.ptr()->homogeneous_add(ptr(), w.ptr());
return res;
}
VectorHd<RT,LA>& operator+=(const VectorHd<RT,LA>& w)
/*{\Mbinop addition plus assignment.}*/
{ int d = dimension();
VectorHd<RT,LA> old(*this);
*this = VectorHd<RT,LA>(d);
ptr()->homogeneous_add(old.ptr(), w.ptr());
return *this;
}
VectorHd<RT,LA> operator-(const VectorHd<RT,LA>& w) const
/*{\Mbinop returns the vector with Cartesian coordinates
$v_i-w_i, 0 \leq i < d$.}*/
{ VectorHd<RT,LA> res(dimension());
res.ptr()->homogeneous_sub(ptr(), w.ptr());
return res;
}
VectorHd<RT,LA>& operator-=(const VectorHd<RT,LA>& w)
/*{\Mbinop subtraction plus assignment.}*/
{ int d = dimension();
VectorHd<RT,LA> old(*this);
*this = VectorHd<RT,LA>(d);
ptr()->homogeneous_sub(old.ptr(), w.ptr());
return *this;
}
VectorHd<RT,LA> operator-() const
/*{\Munop returns the vector in opposite direction.}*/
{ VectorHd<RT,LA> result(*this);
result.copy_on_write(); // creates a copied object!
result.ptr()->invert(dimension());
return result;
}
static Comparison_result cmp(
const VectorHd<RT,LA>& x, const VectorHd<RT,LA>& y)
{ Compare_homogeneously<RT,LA> cmpobj;
return cmpobj(x.vector_rep(),y.vector_rep());
}
bool operator==(const VectorHd<RT,LA>& w) const
{ if ( this->identical(w) ) return true;
if ( dimension() != w.dimension() ) return false;
return cmp(*this,w) == EQUAL;
}
bool operator!=(const VectorHd<RT,LA>& w) const
{ return !operator==(w); }
bool is_zero() const
/*{\Mop returns true if |\Mvar| is the zero vector. }*/
{ for (int i = 0; i < dimension(); i++)
if ( homogeneous(i) != RT(0) ) return false;
return true;
}
/*{\Mtext \headerline{Downward compatibility}
We provide all operations of the lower dimensional interface |x()|, |y()|,
|z()|, |hx()|, |hy()|, |hz()|, |hw()|.}*/
RT hx() const { return homogeneous(0); }
RT hy() const { return homogeneous(1); }
RT hz() const { return homogeneous(2); }
RT hw() const { return homogeneous(dimension()); }
Quotient<RT> x() const { return Quotient<RT>(hx(),hw());}
Quotient<RT> y() const { return Quotient<RT>(hy(),hw());}
Quotient<RT> z() const { return Quotient<RT>(hz(),hw());}
friend std::istream& operator>> <>
(std::istream& I, VectorHd<RT,LA>& v);
friend std::ostream& operator<< <>
(std::ostream& O, const VectorHd<RT,LA>& v);
}; // end of class VectorHd
template <class RT, class LA>
VectorHd<RT,LA> operator*(const int& n, const VectorHd<RT,LA>& v)
{ return v.scale(n,1); }
template <class RT, class LA>
VectorHd<RT,LA> operator*(const RT& n, const VectorHd<RT,LA>& v)
/*{\Mbinopfunc returns the vector with Cartesian coordinates $n v_i$.}*/
{ return v.scale(n,1); }
template <class RT, class LA>
VectorHd<RT,LA> operator*(const Quotient<RT>& r, const VectorHd<RT,LA>& v)
/*{\Mbinopfunc returns the vector with Cartesian coordinates
$r v_i, 0 \leq i < d$.}*/
{ return v.scale(r.numerator(),r.denominator()); }
/*{\Mimplementation
Vectors are implemented by arrays of variables of type |RT|. All
operations like creation, initialization, tests, vector arithmetic,
input and output on a vector $v$ take time $O(|v.dimension()|)$.
coordinate access, |dimension()| and conversions
take constant time. The space requirement of a vector is
$O(|v.dimension()|)$.}*/
#undef PointHd
} //namespace CGAL
#endif // CGAL_VECTORHD_H
//----------------------- end of file ----------------------------------