diff options
Diffstat (limited to 'extern/draco/dracoenc/src/draco/core/vector_d.h')
-rw-r--r-- | extern/draco/dracoenc/src/draco/core/vector_d.h | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/extern/draco/dracoenc/src/draco/core/vector_d.h b/extern/draco/dracoenc/src/draco/core/vector_d.h new file mode 100644 index 00000000000..57dcd102663 --- /dev/null +++ b/extern/draco/dracoenc/src/draco/core/vector_d.h @@ -0,0 +1,260 @@ +// Copyright 2016 The Draco Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef DRACO_CORE_VECTOR_D_H_ +#define DRACO_CORE_VECTOR_D_H_ + +#include <inttypes.h> +#include <algorithm> +#include <array> +#include <cmath> + +#include "draco/core/macros.h" + +namespace draco { +// D-dimensional vector class with basic operations. +template <class CoeffT, int dimension_t> +class VectorD { + public: + typedef VectorD<CoeffT, dimension_t> Self; + typedef CoeffT CoefficientType; + static constexpr int dimension = dimension_t; + + VectorD() { + for (int i = 0; i < dimension_t; ++i) + (*this)[i] = CoeffT(0); + } + + // The following constructor does not compile in opt mode, which for now led + // to the constructors further down, which is not ideal. + // TODO(hemmer): fix constructor below and remove others. + // template <typename... Args> + // explicit VectorD(Args... args) : v_({args...}) {} + + VectorD(const CoeffT &c0, const CoeffT &c1) : v_({{c0, c1}}) { + DRACO_DCHECK_EQ(dimension_t, 2); + v_[0] = c0; + v_[1] = c1; + } + + VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2) + : v_({{c0, c1, c2}}) { + DRACO_DCHECK_EQ(dimension_t, 3); + } + + VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, + const CoeffT &c3) + : v_({{c0, c1, c2, c3}}) { + DRACO_DCHECK_EQ(dimension_t, 4); + } + + VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, + const CoeffT &c3, const CoeffT &c4) + : v_({{c0, c1, c2, c3, c4}}) { + DRACO_DCHECK_EQ(dimension_t, 5); + } + + VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, + const CoeffT &c3, const CoeffT &c4, const CoeffT &c5) + : v_({{c0, c1, c2, c3, c4, c5}}) { + DRACO_DCHECK_EQ(dimension_t, 6); + } + + VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, + const CoeffT &c3, const CoeffT &c4, const CoeffT &c5, + const CoeffT &c6) + : v_({{c0, c1, c2, c3, c4, c5, c6}}) { + DRACO_DCHECK_EQ(dimension_t, 7); + } + + VectorD(const Self &o) { + for (int i = 0; i < dimension_t; ++i) + (*this)[i] = o[i]; + } + + CoeffT &operator[](int i) { return v_[i]; } + const CoeffT &operator[](int i) const { return v_[i]; } + // TODO(hemmer): remove. + // Similar to interface of Eigen library. + CoeffT &operator()(int i) { return v_[i]; } + const CoeffT &operator()(int i) const { return v_[i]; } + + // Unary operators. + Self operator-() const { + Self ret; + for (int i = 0; i < dimension_t; ++i) { + ret[i] = -(*this)[i]; + } + return ret; + } + + // Binary operators. + Self operator+(const Self &o) const { + Self ret; + for (int i = 0; i < dimension_t; ++i) { + ret[i] = (*this)[i] + o[i]; + } + return ret; + } + + Self operator-(const Self &o) const { + Self ret; + for (int i = 0; i < dimension_t; ++i) { + ret[i] = (*this)[i] - o[i]; + } + return ret; + } + + Self operator*(const CoeffT &o) const { + Self ret; + for (int i = 0; i < dimension_t; ++i) { + ret[i] = (*this)[i] * o; + } + return ret; + } + + Self operator/(const CoeffT &o) const { + Self ret; + for (int i = 0; i < dimension_t; ++i) { + ret[i] = (*this)[i] / o; + } + return ret; + } + + bool operator==(const Self &o) const { + for (int i = 0; i < dimension_t; ++i) { + if ((*this)[i] != o[i]) + return false; + } + return true; + } + + bool operator!=(const Self &x) const { return !((*this) == x); } + + bool operator<(const Self &x) const { + for (int i = 0; i < dimension_t - 1; ++i) { + if (v_[i] < x.v_[i]) + return true; + if (v_[i] > x.v_[i]) + return false; + } + // Only one check needed for the last dimension. + if (v_[dimension_t - 1] < x.v_[dimension_t - 1]) + return true; + return false; + } + + // Functions. + CoeffT SquaredNorm() const { return this->Dot(*this); } + + // Computes L1, the sum of absolute values of all entries. + CoeffT AbsSum() const { + CoeffT result(0); + for (int i = 0; i < dimension_t; ++i) { + result += std::abs(v_[i]); + } + return result; + } + + CoeffT Dot(const Self &o) const { + CoeffT ret(0); + for (int i = 0; i < dimension_t; ++i) { + ret += (*this)[i] * o[i]; + } + return ret; + } + + void Normalize() { + const CoeffT magnitude = std::sqrt(this->SquaredNorm()); + if (magnitude == 0) { + return; + } + for (int i = 0; i < dimension_t; ++i) { + (*this)[i] /= magnitude; + } + } + + CoeffT *data() { return &(v_[0]); } + + private: + std::array<CoeffT, dimension_t> v_; +}; + +// Scalar multiplication from the other side too. +template <class CoeffT, int dimension_t> +VectorD<CoeffT, dimension_t> operator*(const CoeffT &o, + const VectorD<CoeffT, dimension_t> &v) { + return v * o; +} + +// Calculates the squared distance between two points. +template <class CoeffT, int dimension_t> +CoeffT SquaredDistance(const VectorD<CoeffT, dimension_t> &v1, + const VectorD<CoeffT, dimension_t> &v2) { + CoeffT difference; + CoeffT squared_distance = 0; + // Check each index separately so difference is never negative and underflow + // is avoided for unsigned types. + for (int i = 0; i < dimension_t; ++i) { + if (v1[i] >= v2[i]) { + difference = v1[i] - v2[i]; + } else { + difference = v2[i] - v1[i]; + } + squared_distance += (difference * difference); + } + return squared_distance; +} + +// Global function computing the cross product of two 3D vectors. +template <class CoeffT> +VectorD<CoeffT, 3> CrossProduct(const VectorD<CoeffT, 3> &u, + const VectorD<CoeffT, 3> &v) { + // Preventing accidental use with uint32_t and the like. + static_assert(std::is_signed<CoeffT>::value, + "CoeffT must be a signed type. "); + VectorD<CoeffT, 3> r; + r[0] = (u[1] * v[2]) - (u[2] * v[1]); + r[1] = (u[2] * v[0]) - (u[0] * v[2]); + r[2] = (u[0] * v[1]) - (u[1] * v[0]); + return r; +} + +template <class CoeffT, int dimension_t> +inline std::ostream &operator<<( + std::ostream &out, const draco::VectorD<CoeffT, dimension_t> &vec) { + for (int i = 0; i < dimension_t - 1; ++i) { + out << vec[i] << " "; + } + out << vec[dimension_t - 1]; + return out; +} + +typedef VectorD<float, 2> Vector2f; +typedef VectorD<float, 3> Vector3f; +typedef VectorD<float, 4> Vector4f; +typedef VectorD<float, 5> Vector5f; +typedef VectorD<float, 6> Vector6f; +typedef VectorD<float, 7> Vector7f; + +typedef VectorD<uint32_t, 2> Vector2ui; +typedef VectorD<uint32_t, 3> Vector3ui; +typedef VectorD<uint32_t, 4> Vector4ui; +typedef VectorD<uint32_t, 5> Vector5ui; +typedef VectorD<uint32_t, 6> Vector6ui; +typedef VectorD<uint32_t, 7> Vector7ui; + +} // namespace draco + +#endif // DRACO_CORE_VECTOR_D_H_ |