Commit cc84b82c authored by Max Lyon's avatar Max Lyon

updated vector class to newest OpenMesh vector

parent ff5ebe90
......@@ -41,28 +41,28 @@ if (NOT APPLE AND ${PROJECT_NAME} MATCHES "OpenVolumeMesh")
# Install Header Files)
install(DIRECTORY .
DESTINATION include
DESTINATION include
FILES_MATCHING
PATTERN "*.hh"
PATTERN "*.hh"
PATTERN "Unittests" EXCLUDE
PATTERN "FileConverter" EXCLUDE
PATTERN "CVS" EXCLUDE
PATTERN ".svn" EXCLUDE
PATTERN "tmp" EXCLUDE
PATTERN "Templates" EXCLUDE
PATTERN "Templates" EXCLUDE
PATTERN "Debian*" EXCLUDE)
#install Template cc files (required by headers)
install(DIRECTORY .
DESTINATION include
DESTINATION include
FILES_MATCHING
PATTERN "*T.cc"
PATTERN "*T.cc"
PATTERN "Unittests" EXCLUDE
PATTERN "FileConverter" EXCLUDE
PATTERN "CVS" EXCLUDE
PATTERN ".svn" EXCLUDE
PATTERN "tmp" EXCLUDE
PATTERN "Templates" EXCLUDE
PATTERN "tmp" EXCLUDE
PATTERN "Templates" EXCLUDE
PATTERN "Debian*" EXCLUDE)
endif ()
......
/* ========================================================================= *
* *
* OPENVOLUMEMESHMesh *
* Copyright (c) 2001-2016, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.OPENVOLUMEMESHmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OPENVOLUMEMESHMesh. *
* This file was originally taken from OpenMesh *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
#ifndef OPENVOLUMEMESH_SRC_OPENVOLUMEMESH_GEOMETRY_VECTOR11T_HH_
#define OPENVOLUMEMESH_SRC_OPENVOLUMEMESH_GEOMETRY_VECTOR11T_HH_
#include <array>
#include <utility>
#include <algorithm>
#include <numeric>
#include <type_traits>
#include <cmath>
#include <ostream>
#include <istream>
#include <cassert>
#include <cstdlib>
/*
* Helpers for VectorT
*/
namespace {
template<typename ... Ts>
struct are_convertible_to;
template<typename To, typename From, typename ... Froms>
struct are_convertible_to<To, From, Froms...> {
static constexpr bool value = std::is_convertible<From, To>::value
&& are_convertible_to<To, Froms...>::value;
};
template<typename To, typename From>
struct are_convertible_to<To, From> : public std::is_convertible<From, To> {
};
}
namespace OpenVolumeMesh {
namespace Geometry {
template<typename Scalar, int DIM>
class VectorT {
static_assert(DIM >= 1, "VectorT requires positive dimensionality.");
private:
using container = std::array<Scalar, DIM>;
container values_;
public:
//---------------------------------------------------------------- class info
/// the type of the scalar used in this template
typedef Scalar value_type;
/// type of this vector
typedef VectorT<Scalar, DIM> vector_type;
/// returns dimension of the vector (deprecated)
static constexpr int dim() {
return DIM;
}
/// returns dimension of the vector
static constexpr size_t size() {
return DIM;
}
static constexpr const size_t size_ = DIM;
//-------------------------------------------------------------- constructors
/// default constructor creates uninitialized values.
constexpr VectorT() {}
/**
* Creates a vector with all components set to v.
*/
explicit VectorT(const Scalar &v) {
vectorize(v);
}
template<typename ... T,
typename = typename std::enable_if<sizeof...(T) == DIM>::type,
typename = typename std::enable_if<
are_convertible_to<Scalar, T...>::value>::type>
constexpr VectorT(T... vs) : values_ { {static_cast<Scalar>(vs)...} } {
static_assert(sizeof...(T) == DIM,
"Invalid number of components specified in constructor.");
static_assert(are_convertible_to<Scalar, T...>::value,
"Not all components are convertible to Scalar.");
}
VectorT(const VectorT &rhs) = default;
VectorT(VectorT &&rhs) = default;
VectorT &operator=(const VectorT &rhs) = default;
VectorT &operator=(VectorT &&rhs) = default;
/**
* Only for 4-component vectors with division operator on their
* Scalar: Dehomogenization.
*/
template<typename S = Scalar, int D = DIM>
auto homogenized() const ->
typename std::enable_if<D == 4,
VectorT<decltype(std::declval<S>()/std::declval<S>()), DIM>>::type {
static_assert(D == DIM, "D and DIM need to be identical. (Never "
"override the default template arguments.)");
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return VectorT(
values_[0]/values_[3],
values_[1]/values_[3],
values_[2]/values_[3],
1);
}
/// construct from a value array or any other iterator
template<typename Iterator,
typename = decltype(
*std::declval<Iterator&>(), void(),
++std::declval<Iterator&>(), void())>
explicit VectorT(Iterator it) {
std::copy_n(it, DIM, values_.begin());
}
/// copy & cast constructor (explicit)
template<typename otherScalarType,
typename = typename std::enable_if<
std::is_convertible<otherScalarType, Scalar>::value>>
explicit VectorT(const VectorT<otherScalarType, DIM>& _rhs) {
operator=(_rhs);
}
//--------------------------------------------------------------------- casts
/// cast from vector with a different scalar type
template<typename OtherScalar,
typename = typename std::enable_if<
std::is_convertible<OtherScalar, Scalar>::value>>
vector_type& operator=(const VectorT<OtherScalar, DIM>& _rhs) {
std::transform(_rhs.data(), _rhs.data() + DIM,
data(), [](OtherScalar rhs) {
return static_cast<Scalar>(std::move(rhs));
});
return *this;
}
/// access to Scalar array
Scalar* data() { return values_.data(); }
/// access to const Scalar array
const Scalar *data() const { return values_.data(); }
//----------------------------------------------------------- element access
/// get i'th element read-write
Scalar& operator[](size_t _i) {
assert(_i < DIM);
return values_[_i];
}
/// get i'th element read-only
const Scalar& operator[](size_t _i) const {
assert(_i < DIM);
return values_[_i];
}
//---------------------------------------------------------------- comparsion
/// component-wise comparison
bool operator==(const vector_type& _rhs) const {
return std::equal(_rhs.values_.cbegin(), _rhs.values_.cend(), values_.cbegin());
}
/// component-wise comparison
bool operator!=(const vector_type& _rhs) const {
return !std::equal(_rhs.values_.cbegin(), _rhs.values_.cend(), values_.cbegin());
}
//---------------------------------------------------------- scalar operators
/// component-wise self-multiplication with scalar
template<typename OtherScalar>
auto operator*=(const OtherScalar& _s) ->
typename std::enable_if<std::is_convertible<
decltype(this->values_[0] * _s), Scalar>::value,
VectorT<Scalar, DIM>&>::type {
for (auto& e : *this) {
e *= _s;
}
return *this;
}
/// component-wise self-division by scalar
template<typename OtherScalar>
auto operator/=(const OtherScalar& _s) ->
typename std::enable_if<std::is_convertible<
decltype(this->values_[0] / _s), Scalar>::value,
VectorT<Scalar, DIM>&>::type {
for (auto& e : *this) {
e /= _s;
}
return *this;
}
/// component-wise multiplication with scalar
template<typename OtherScalar>
typename std::enable_if<std::is_convertible<
decltype(std::declval<Scalar>() * std::declval<OtherScalar>()),
Scalar>::value,
VectorT<Scalar, DIM>>::type
operator*(const OtherScalar& _s) const {
return vector_type(*this) *= _s;
}
/// component-wise division by with scalar
template<typename OtherScalar>
typename std::enable_if<std::is_convertible<
decltype(std::declval<Scalar>() / std::declval<OtherScalar>()),
Scalar>::value,
VectorT<Scalar, DIM>>::type
operator/(const OtherScalar& _s) const {
return vector_type(*this) /= _s;
}
//---------------------------------------------------------- vector operators
/// component-wise self-multiplication
template<typename OtherScalar>
auto operator*=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] * *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] *= _rhs.data()[i];
}
return *this;
}
/// component-wise self-division
template<typename OtherScalar>
auto operator/=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] / *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] /= _rhs.data()[i];
}
return *this;
}
/// vector difference from this
template<typename OtherScalar>
auto operator-=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] - *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] -= _rhs.data()[i];
}
return *this;
}
/// vector self-addition
template<typename OtherScalar>
auto operator+=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] + *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] += _rhs.data()[i];
}
return *this;
}
/// component-wise vector multiplication
template<typename OtherScalar>
auto operator*(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] * *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) *= _rhs;
}
/// component-wise vector division
template<typename OtherScalar>
auto operator/(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] / *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) /= _rhs;
}
/// component-wise vector addition
template<typename OtherScalar>
auto operator+(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] + *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) += _rhs;
}
/// component-wise vector difference
template<typename OtherScalar>
auto operator-(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] - *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) -= _rhs;
}
/// unary minus
vector_type operator-(void) const {
vector_type v;
std::transform(values_.begin(), values_.end(), v.values_.begin(),
[](const Scalar &s) { return -s; });
return v;
}
/// cross product: only defined for Vec3* as specialization
/// \see OpenVolumeMesh::cross
template<typename OtherScalar>
auto operator% (const VectorT<OtherScalar, DIM> &_rhs) const ->
typename std::enable_if<DIM == 3,
VectorT<decltype(this->values_[0] * _rhs[0] -
this->values_[0] * _rhs[0]),
DIM>>::type {
return {
values_[1] * _rhs[2] - values_[2] * _rhs[1],
values_[2] * _rhs[0] - values_[0] * _rhs[2],
values_[0] * _rhs[1] - values_[1] * _rhs[0]
};
}
/// compute scalar product
/// \see OpenVolumeMesh::dot
template<typename OtherScalar>
auto operator|(const VectorT<OtherScalar, DIM>& _rhs) const ->
decltype(*this->data() * *_rhs.data()) {
return std::inner_product(data() + 1, data() + DIM, _rhs.data() + 1,
*data() * *_rhs.data());
}
//------------------------------------------------------------ euclidean norm
/// \name Euclidean norm calculations
//@{
/// compute squared euclidean norm
template<typename S = Scalar>
decltype(std::declval<S>() * std::declval<S>()) sqrnorm() const {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
typedef decltype(values_[0] * values_[0]) RESULT;
return std::accumulate(values_.cbegin() + 1, values_.cend(),
values_[0] * values_[0],
[](const RESULT &l, const Scalar &r) { return l + r * r; });
}
/// compute euclidean norm
template<typename S = Scalar>
auto norm() const ->
decltype(std::sqrt(std::declval<VectorT<S, DIM>>().sqrnorm())) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return std::sqrt(sqrnorm());
}
template<typename S = Scalar>
auto length() const ->
decltype(std::declval<VectorT<S, DIM>>().norm()) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return norm();
}
/** normalize vector, return normalized vector
*/
template<typename S = Scalar>
auto normalize() ->
decltype(*this /= std::declval<VectorT<S, DIM>>().norm()) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return *this /= norm();
}
/** return normalized vector
*/
template<typename S = Scalar>
auto normalized() const ->
decltype(*this / std::declval<VectorT<S, DIM>>().norm()) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return *this / norm();
}
/** normalize vector, return normalized vector and avoids div by zero
*/
template<typename S = Scalar>
typename std::enable_if<
sizeof(decltype(
static_cast<S>(0),
std::declval<VectorT<S, DIM>>().norm())) >= 0,
vector_type&>::type
normalize_cond() {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
auto n = norm();
if (n != static_cast<decltype(norm())>(0)) {
*this /= n;
}
return *this;
}
//@}
//------------------------------------------------------------ euclidean norm
/// \name Non-Euclidean norm calculations
//@{
/// compute L1 (Manhattan) norm
Scalar l1_norm() const {
return std::accumulate(
values_.cbegin() + 1, values_.cend(), values_[0]);
}
/// compute l8_norm
Scalar l8_norm() const {
return max_abs();
}
//@}
//------------------------------------------------------------ max, min, mean
/// \name Minimum maximum and mean
//@{
/// return the maximal component
Scalar max() const {
return *std::max_element(values_.cbegin(), values_.cend());
}
/// return the maximal absolute component
Scalar max_abs() const {
return std::abs(
*std::max_element(values_.cbegin(), values_.cend(),
[](const Scalar &a, const Scalar &b) {
return std::abs(a) < std::abs(b);
}));
}
/// return the minimal component
Scalar min() const {
return *std::min_element(values_.cbegin(), values_.cend());
}
/// return the minimal absolute component
Scalar min_abs() const {
return std::abs(
*std::min_element(values_.cbegin(), values_.cend(),
[](const Scalar &a, const Scalar &b) {
return std::abs(a) < std::abs(b);
}));
}
/// return arithmetic mean
Scalar mean() const {
return l1_norm()/DIM;
}
/// return absolute arithmetic mean
Scalar mean_abs() const {
return std::accumulate(values_.cbegin() + 1, values_.cend(),
std::abs(values_[0]),
[](const Scalar &l, const Scalar &r) {
return l + std::abs(r);
}) / DIM;
}
/// minimize values: same as *this = min(*this, _rhs), but faster
vector_type& minimize(const vector_type& _rhs) {
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[](const Scalar &l, const Scalar &r) {
return std::min(l, r);
});
return *this;
}
/// minimize values and signalize coordinate minimization
bool minimized(const vector_type& _rhs) {
bool result = false;
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[&result](const Scalar &l, const Scalar &r) {
if (l < r) {
return l;
} else {
result = true;
return r;
}
});
return result;
}
/// maximize values: same as *this = max(*this, _rhs), but faster
vector_type& maximize(const vector_type& _rhs) {
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[](const Scalar &l, const Scalar &r) {
return std::max(l, r);
});
return *this;
}
/// maximize values and signalize coordinate maximization
bool maximized(const vector_type& _rhs) {
bool result = false;
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[&result](const Scalar &l, const Scalar &r) {
if (l > r) {
return l;
} else {
result = true;
return r;
}
});
return result;
}