1 /* ========================================================================= *
2  *                                                                           *
3  *                               OpenMesh                                    *
4  *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
5  *           Department of Computer Graphics and Multimedia                  *
6  *                          All rights reserved.                             *
7  *                            www.openmesh.org                               *
8  *                                                                           *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh.                                            *
11  *---------------------------------------------------------------------------*
12  *                                                                           *
13  * Redistribution and use in source and binary forms, with or without        *
14  * modification, are permitted provided that the following conditions        *
15  * are met:                                                                  *
16  *                                                                           *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  *    this list of conditions and the following disclaimer.                  *
19  *                                                                           *
20  * 2. Redistributions in binary form must reproduce the above copyright      *
21  *    notice, this list of conditions and the following disclaimer in the    *
22  *    documentation and/or other materials provided with the distribution.   *
23  *                                                                           *
24  * 3. Neither the name of the copyright holder nor the names of its          *
25  *    contributors may be used to endorse or promote products derived from   *
26  *    this software without specific prior written permission.               *
27  *                                                                           *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
39  *                                                                           *
40  * ========================================================================= */
41 
42 #ifndef OPENMESH_SRC_OPENMESH_CORE_GEOMETRY_VECTOR11T_HH_
43 #define OPENMESH_SRC_OPENMESH_CORE_GEOMETRY_VECTOR11T_HH_
44 
45 #include <array>
46 #include <utility>
47 #include <algorithm>
48 #include <numeric>
49 #include <type_traits>
50 #include <cmath>
51 #include <ostream>
52 #include <istream>
53 #include <cassert>
54 #include <cstdlib>
55 
56 // This header is not needed by this file but expected by others including
57 // this file.
58 #include <OpenMesh/Core/System/config.h>
59 
60 
61 /*
62  * Helpers for VectorT
63  */
64 namespace {
65 
66 template<typename ... Ts>
67 struct are_convertible_to;
68 
69 template<typename To, typename From, typename ... Froms>
70 struct are_convertible_to<To, From, Froms...> {
71     static constexpr bool value = std::is_convertible<From, To>::value
72             && are_convertible_to<To, Froms...>::value;
73 };
74 
75 template<typename To, typename From>
76 struct are_convertible_to<To, From> : public std::is_convertible<From, To> {
77 };
78 }
79 
80 namespace OpenMesh {
81 
82 template<typename Scalar, int DIM>
83 class VectorT {
84 
85         static_assert(DIM >= 1, "VectorT requires positive dimensionality.");
86 
87     private:
88         using container = std::array<Scalar, DIM>;
89         container values_;
90 
91     public:
92 
93         //---------------------------------------------------------------- class info
94 
95         /// the type of the scalar used in this template
96         typedef Scalar value_type;
97 
98         /// type of this vector
99         typedef VectorT<Scalar, DIM> vector_type;
100 
101         /// returns dimension of the vector (deprecated)
dim()102         static constexpr int dim() {
103             return DIM;
104         }
105 
106         /// returns dimension of the vector
size()107         static constexpr size_t size() {
108             return DIM;
109         }
110 
111         static constexpr const size_t size_ = DIM;
112 
113         //-------------------------------------------------------------- constructors
114 
115         // Converting constructor: Constructs the vector from DIM values (of
116         // potentially heterogenous types) which are all convertible to Scalar.
117         template<typename T, typename ... Ts,
118             typename = typename std::enable_if<sizeof...(Ts)+1 == DIM>::type,
119             typename = typename std::enable_if<
120                 are_convertible_to<Scalar, T, Ts...>::value>::type>
VectorT(T v,Ts...vs)121         constexpr VectorT(T v, Ts... vs) : values_ { {static_cast<Scalar>(v), static_cast<Scalar>(vs)...} } {
122             static_assert(sizeof...(Ts)+1 == DIM,
123                     "Invalid number of components specified in constructor.");
124             static_assert(are_convertible_to<Scalar, T, Ts...>::value,
125                     "Not all components are convertible to Scalar.");
126         }
127 
128         /// default constructor creates uninitialized values.
VectorT()129         constexpr VectorT() {}
130 
131         /**
132         * Creates a vector with all components set to v.
133         */
VectorT(const Scalar & v)134         explicit VectorT(const Scalar &v) {
135             vectorize(v);
136         }
137 
138         VectorT(const VectorT &rhs) = default;
139         VectorT(VectorT &&rhs) = default;
140         VectorT &operator=(const VectorT &rhs) = default;
141         VectorT &operator=(VectorT &&rhs) = default;
142 
143         /**
144          * Only for 4-component vectors with division operator on their
145          * Scalar: Dehomogenization.
146          */
147         template<typename S = Scalar, int D = DIM>
homogenized() const148         auto homogenized() const ->
149             typename std::enable_if<D == 4,
150                 VectorT<decltype(std::declval<S>()/std::declval<S>()), DIM>>::type {
151             static_assert(D == DIM, "D and DIM need to be identical. (Never "
152                     "override the default template arguments.)");
153             static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
154                     "to be the same type. (Never override the default template "
155                     "arguments.)");
156             return VectorT(
157                     values_[0]/values_[3],
158                     values_[1]/values_[3],
159                     values_[2]/values_[3],
160                     1);
161         }
162 
163         /// construct from a value array or any other iterator
164         template<typename Iterator,
165             typename = decltype(
166                     *std::declval<Iterator&>(), void(),
167                     ++std::declval<Iterator&>(), void())>
VectorT(Iterator it)168         explicit VectorT(Iterator it) {
169             std::copy_n(it, DIM, values_.begin());
170         }
171 
172         /// construct from an array
VectorT(container && _array)173         explicit VectorT(container&& _array) {
174             values_ = _array;
175         }
176 
177         /// copy & cast constructor (explicit)
178         template<typename otherScalarType,
179             typename = typename std::enable_if<
180                 std::is_convertible<otherScalarType, Scalar>::value>>
VectorT(const VectorT<otherScalarType,DIM> & _rhs)181         explicit VectorT(const VectorT<otherScalarType, DIM>& _rhs) {
182             operator=(_rhs);
183         }
184 
185         //--------------------------------------------------------------------- casts
186 
187         /// cast from vector with a different scalar type
188         template<typename OtherScalar,
189             typename = typename std::enable_if<
190                 std::is_convertible<OtherScalar, Scalar>::value>>
operator =(const VectorT<OtherScalar,DIM> & _rhs)191         vector_type& operator=(const VectorT<OtherScalar, DIM>& _rhs) {
192             std::transform(_rhs.cbegin(), _rhs.cend(),
193                     this->begin(), [](OtherScalar rhs) {
194                         return static_cast<Scalar>(std::move(rhs));
195                     });
196             return *this;
197         }
198 
199         /// access to Scalar array
data()200         Scalar* data() { return values_.data(); }
201 
202         /// access to const Scalar array
data() const203         const Scalar* data() const { return values_.data(); }
204 
205         //----------------------------------------------------------- element access
206 
207         /// get i'th element read-write
operator [](size_t _i)208         Scalar& operator[](size_t _i) {
209             assert(_i < DIM);
210             return values_[_i];
211         }
212 
213         /// get i'th element read-only
operator [](size_t _i) const214         const Scalar& operator[](size_t _i) const {
215             assert(_i < DIM);
216             return values_[_i];
217         }
218 
219         //---------------------------------------------------------------- comparsion
220 
221         /// component-wise comparison
operator ==(const vector_type & _rhs) const222         bool operator==(const vector_type& _rhs) const {
223             return std::equal(_rhs.values_.cbegin(), _rhs.values_.cend(), values_.cbegin());
224         }
225 
226         /// component-wise comparison
operator !=(const vector_type & _rhs) const227         bool operator!=(const vector_type& _rhs) const {
228             return !std::equal(_rhs.values_.cbegin(), _rhs.values_.cend(), values_.cbegin());
229         }
230 
231         //---------------------------------------------------------- scalar operators
232 
233         /// component-wise self-multiplication with scalar
234         template<typename OtherScalar>
operator *=(const OtherScalar & _s)235         auto operator*=(const OtherScalar& _s) ->
236             typename std::enable_if<std::is_convertible<
237                 decltype(this->values_[0] * _s), Scalar>::value,
238                 VectorT<Scalar, DIM>&>::type {
239             for (auto& e : *this) {
240                 e *= _s;
241             }
242             return *this;
243         }
244 
245         /// component-wise self-division by scalar
246         template<typename OtherScalar>
operator /=(const OtherScalar & _s)247         auto operator/=(const OtherScalar& _s) ->
248             typename std::enable_if<std::is_convertible<
249                 decltype(this->values_[0] / _s), Scalar>::value,
250                 VectorT<Scalar, DIM>&>::type {
251             for (auto& e : *this) {
252                 e /= _s;
253             }
254             return *this;
255         }
256 
257         /// component-wise multiplication with scalar
258         template<typename OtherScalar>
259         typename std::enable_if<std::is_convertible<
260                 decltype(std::declval<Scalar>() * std::declval<OtherScalar>()),
261                 Scalar>::value,
262             VectorT<Scalar, DIM>>::type
operator *(const OtherScalar & _s) const263         operator*(const OtherScalar& _s) const {
264             return vector_type(*this) *= _s;
265         }
266 
267         /// component-wise division by with scalar
268         template<typename OtherScalar>
269         typename std::enable_if<std::is_convertible<
270                 decltype(std::declval<Scalar>() / std::declval<OtherScalar>()),
271                 Scalar>::value,
272             VectorT<Scalar, DIM>>::type
operator /(const OtherScalar & _s) const273         operator/(const OtherScalar& _s) const {
274             return vector_type(*this) /= _s;
275         }
276 
277         //---------------------------------------------------------- vector operators
278 
279         /// component-wise self-multiplication
280         template<typename OtherScalar>
operator *=(const VectorT<OtherScalar,DIM> & _rhs)281         auto operator*=(const VectorT<OtherScalar, DIM>& _rhs) ->
282             typename std::enable_if<
283                 sizeof(decltype(this->values_[0] * *_rhs.data())) >= 0,
284                 vector_type&>::type {
285             for (int i = 0; i < DIM; ++i) {
286                 data()[i] *= _rhs.data()[i];
287             }
288             return *this;
289         }
290 
291         /// component-wise self-division
292         template<typename OtherScalar>
operator /=(const VectorT<OtherScalar,DIM> & _rhs)293         auto operator/=(const VectorT<OtherScalar, DIM>& _rhs) ->
294             typename std::enable_if<
295                 sizeof(decltype(this->values_[0] / *_rhs.data())) >= 0,
296                 vector_type&>::type {
297             for (int i = 0; i < DIM; ++i) {
298                 data()[i] /= _rhs.data()[i];
299             }
300             return *this;
301         }
302 
303         /// vector difference from this
304         template<typename OtherScalar>
operator -=(const VectorT<OtherScalar,DIM> & _rhs)305         auto operator-=(const VectorT<OtherScalar, DIM>& _rhs) ->
306             typename std::enable_if<
307                 sizeof(decltype(this->values_[0] - *_rhs.data())) >= 0,
308                 vector_type&>::type {
309             for (int i = 0; i < DIM; ++i) {
310                 data()[i] -= _rhs.data()[i];
311             }
312             return *this;
313         }
314 
315         /// vector self-addition
316         template<typename OtherScalar>
operator +=(const VectorT<OtherScalar,DIM> & _rhs)317         auto operator+=(const VectorT<OtherScalar, DIM>& _rhs) ->
318             typename std::enable_if<
319                 sizeof(decltype(this->values_[0] + *_rhs.data())) >= 0,
320                 vector_type&>::type {
321             for (int i = 0; i < DIM; ++i) {
322                 data()[i] += _rhs.data()[i];
323             }
324             return *this;
325         }
326 
327         /// component-wise vector multiplication
328         template<typename OtherScalar>
operator *(const VectorT<OtherScalar,DIM> & _rhs) const329         auto operator*(const VectorT<OtherScalar, DIM>& _rhs) const ->
330             typename std::enable_if<
331                 sizeof(decltype(this->values_[0] * *_rhs.data())) >= 0,
332                 vector_type>::type {
333             return vector_type(*this) *= _rhs;
334         }
335 
336         /// component-wise vector division
337         template<typename OtherScalar>
operator /(const VectorT<OtherScalar,DIM> & _rhs) const338         auto operator/(const VectorT<OtherScalar, DIM>& _rhs) const ->
339             typename std::enable_if<
340                 sizeof(decltype(this->values_[0] / *_rhs.data())) >= 0,
341                 vector_type>::type {
342             return vector_type(*this) /= _rhs;
343         }
344 
345         /// component-wise vector addition
346         template<typename OtherScalar>
operator +(const VectorT<OtherScalar,DIM> & _rhs) const347         auto operator+(const VectorT<OtherScalar, DIM>& _rhs) const ->
348             typename std::enable_if<
349                 sizeof(decltype(this->values_[0] + *_rhs.data())) >= 0,
350                 vector_type>::type {
351             return vector_type(*this) += _rhs;
352         }
353 
354         /// component-wise vector difference
355         template<typename OtherScalar>
operator -(const VectorT<OtherScalar,DIM> & _rhs) const356         auto operator-(const VectorT<OtherScalar, DIM>& _rhs) const ->
357             typename std::enable_if<
358                 sizeof(decltype(this->values_[0] - *_rhs.data())) >= 0,
359                 vector_type>::type {
360             return vector_type(*this) -= _rhs;
361         }
362 
363         /// unary minus
operator -(void) const364         vector_type operator-(void) const {
365             vector_type v;
366             std::transform(values_.begin(), values_.end(), v.values_.begin(),
367                     [](const Scalar &s) { return -s; });
368             return v;
369         }
370 
371         /// cross product: only defined for Vec3* as specialization
372         /// \see OpenMesh::cross and .cross()
373         template<typename OtherScalar>
operator %(const VectorT<OtherScalar,DIM> & _rhs) const374         auto operator% (const VectorT<OtherScalar, DIM> &_rhs) const ->
375             typename std::enable_if<DIM == 3,
376                 VectorT<decltype((*this)[0] * _rhs[0] -
377                                  (*this)[0] * _rhs[0]), DIM>>::type {
378             return {
379                 values_[1] * _rhs[2] - values_[2] * _rhs[1],
380                 values_[2] * _rhs[0] - values_[0] * _rhs[2],
381                 values_[0] * _rhs[1] - values_[1] * _rhs[0]
382             };
383         }
384 
385         /// cross product: only defined for Vec3* as specialization
386         /// \see OpenMesh::cross and .operator%
387         template<typename OtherScalar>
cross(const VectorT<OtherScalar,DIM> & _rhs) const388         auto cross (const VectorT<OtherScalar, DIM> &_rhs) const ->
389             decltype(*this % _rhs)
390         {
391             return *this % _rhs;
392         }
393 
394 
395         /// compute scalar product
396         /// \see OpenMesh::dot and .dot()
397         template<typename OtherScalar>
operator |(const VectorT<OtherScalar,DIM> & _rhs) const398         auto operator|(const VectorT<OtherScalar, DIM>& _rhs) const ->
399             decltype(*this->data() * *_rhs.data()) {
400 
401             return std::inner_product(begin() + 1, begin() + DIM, _rhs.begin() + 1,
402                     *begin() * *_rhs.begin());
403         }
404 
405         /// compute scalar product
406         /// \see OpenMesh::dot and .operator|
407         template<typename OtherScalar>
dot(const VectorT<OtherScalar,DIM> & _rhs) const408         auto dot(const VectorT<OtherScalar, DIM>& _rhs) const ->
409             decltype(*this | _rhs)
410         {
411             return *this | _rhs;
412         }
413 
414         //------------------------------------------------------------ euclidean norm
415 
416         /// \name Euclidean norm calculations
417         //@{
418 
419         /// compute squared euclidean norm
420         template<typename S = Scalar>
sqrnorm() const421         decltype(std::declval<S>() * std::declval<S>()) sqrnorm() const {
422             static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
423                     "to be the same type. (Never override the default template "
424                     "arguments.)");
425             typedef decltype(values_[0] * values_[0]) RESULT;
426             return std::accumulate(values_.cbegin() + 1, values_.cend(),
427                     values_[0] * values_[0],
428                     [](const RESULT &l, const Scalar &r) { return l + r * r; });
429         }
430 
431         /// compute euclidean norm
432         template<typename S = Scalar>
norm() const433         auto norm() const ->
434             decltype(std::sqrt(std::declval<VectorT<S, DIM>>().sqrnorm())) {
435             static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
436                     "to be the same type. (Never override the default template "
437                     "arguments.)");
438             return std::sqrt(sqrnorm());
439         }
440 
441         template<typename S = Scalar>
length() const442         auto length() const ->
443             decltype(std::declval<VectorT<S, DIM>>().norm()) {
444             static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
445                     "to be the same type. (Never override the default template "
446                     "arguments.)");
447             return norm();
448         }
449 
450         /** normalize vector, return normalized vector
451          */
452         template<typename S = Scalar>
normalize()453         auto normalize() ->
454             decltype(*this /= std::declval<VectorT<S, DIM>>().norm()) {
455             static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
456                     "to be the same type. (Never override the default template "
457                     "arguments.)");
458             return *this /= norm();
459         }
460 
461         /** return normalized vector
462          */
463         template<typename S = Scalar>
normalized() const464         auto normalized() const ->
465             decltype(*this / std::declval<VectorT<S, DIM>>().norm()) {
466             static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
467                     "to be the same type. (Never override the default template "
468                     "arguments.)");
469             return *this / norm();
470         }
471 
472         /** normalize vector, return normalized vector and avoids div by zero
473          */
474         template<typename S = Scalar>
475         typename std::enable_if<
476             sizeof(decltype(
477                 static_cast<S>(0),
478                 std::declval<VectorT<S, DIM>>().norm())) >= 0,
479             vector_type&>::type
480         normalize_cond() {
481             static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
482                     "to be the same type. (Never override the default template "
483                     "arguments.)");
484             auto n = norm();
485             if (n != static_cast<decltype(norm())>(0)) {
486                 *this /= n;
487             }
488             return *this;
489         }
490 
491         //@}
492 
493         //------------------------------------------------------------ euclidean norm
494 
495         /// \name Non-Euclidean norm calculations
496         //@{
497 
498         /// compute L1 (Manhattan) norm
l1_norm() const499         Scalar l1_norm() const {
500             return std::accumulate(
501                     values_.cbegin() + 1, values_.cend(), values_[0]);
502         }
503 
504         /// compute l8_norm
l8_norm() const505         Scalar l8_norm() const {
506             return max_abs();
507         }
508 
509         //@}
510 
511         //------------------------------------------------------------ max, min, mean
512 
513         /// \name Minimum maximum and mean
514         //@{
515 
516         /// return the maximal component
max() const517         Scalar max() const {
518             return *std::max_element(values_.cbegin(), values_.cend());
519         }
520 
521         /// return the maximal absolute component
max_abs() const522         Scalar max_abs() const {
523             return std::abs(
524                 *std::max_element(values_.cbegin(), values_.cend(),
525                     [](const Scalar &a, const Scalar &b) {
526                 return std::abs(a) < std::abs(b);
527             }));
528         }
529 
530         /// return the minimal component
min() const531         Scalar min() const {
532             return *std::min_element(values_.cbegin(), values_.cend());
533         }
534 
535         /// return the minimal absolute component
min_abs() const536         Scalar min_abs() const {
537             return std::abs(
538                 *std::min_element(values_.cbegin(), values_.cend(),
539                     [](const Scalar &a, const Scalar &b) {
540                 return std::abs(a) < std::abs(b);
541             }));
542         }
543 
544         /// return arithmetic mean
mean() const545         Scalar mean() const {
546             return l1_norm()/DIM;
547         }
548 
549         /// return absolute arithmetic mean
mean_abs() const550         Scalar mean_abs() const {
551             return std::accumulate(values_.cbegin() + 1, values_.cend(),
552                     std::abs(values_[0]),
553                     [](const Scalar &l, const Scalar &r) {
554                         return l + std::abs(r);
555                     }) / DIM;
556         }
557 
558         /// minimize values: same as *this = min(*this, _rhs), but faster
minimize(const vector_type & _rhs)559         vector_type& minimize(const vector_type& _rhs) {
560             std::transform(values_.cbegin(), values_.cend(),
561                     _rhs.values_.cbegin(),
562                     values_.begin(),
563                     [](const Scalar &l, const Scalar &r) {
564                         return std::min(l, r);
565                     });
566             return *this;
567         }
568 
569         /// minimize values and signalize coordinate minimization
minimized(const vector_type & _rhs)570         bool minimized(const vector_type& _rhs) {
571             bool result = false;
572             std::transform(values_.cbegin(), values_.cend(),
573                     _rhs.values_.cbegin(),
574                     values_.begin(),
575                     [&result](const Scalar &l, const Scalar &r) {
576                         if (l < r) {
577                             return l;
578                         } else {
579                             result = true;
580                             return r;
581                         }
582                     });
583             return result;
584         }
585 
586         /// maximize values: same as *this = max(*this, _rhs), but faster
maximize(const vector_type & _rhs)587         vector_type& maximize(const vector_type& _rhs) {
588             std::transform(values_.cbegin(), values_.cend(),
589                     _rhs.values_.cbegin(),
590                     values_.begin(),
591                     [](const Scalar &l, const Scalar &r) {
592                         return std::max(l, r);
593                     });
594             return *this;
595         }
596 
597         /// maximize values and signalize coordinate maximization
maximized(const vector_type & _rhs)598         bool maximized(const vector_type& _rhs) {
599             bool result = false;
600             std::transform(values_.cbegin(), values_.cend(),
601                     _rhs.values_.cbegin(),
602                     values_.begin(),
603                     [&result](const Scalar &l, const Scalar &r) {
604                         if (l > r) {
605                             return l;
606                         } else {
607                             result = true;
608                             return r;
609                         }
610                     });
611             return result;
612         }
613 
614         /// component-wise min
min(const vector_type & _rhs) const615         inline vector_type min(const vector_type& _rhs) const {
616             return vector_type(*this).minimize(_rhs);
617         }
618 
619         /// component-wise max
max(const vector_type & _rhs) const620         inline vector_type max(const vector_type& _rhs) const {
621             return vector_type(*this).maximize(_rhs);
622         }
623 
624         //@}
625 
626         //------------------------------------------------------------ misc functions
627 
628         /// component-wise apply function object with Scalar operator()(Scalar).
629         template<typename Functor>
apply(const Functor & _func) const630         inline vector_type apply(const Functor& _func) const {
631             vector_type result;
632             std::transform(result.values_.cbegin(), result.values_.cend(),
633                     result.values_.begin(), _func);
634             return result;
635         }
636 
637         /// store the same value in each component (e.g. to clear all entries)
vectorize(const Scalar & _s)638         vector_type& vectorize(const Scalar& _s) {
639             std::fill(values_.begin(), values_.end(), _s);
640             return *this;
641         }
642 
643         /// store the same value in each component
vectorized(const Scalar & _s)644         static vector_type vectorized(const Scalar& _s) {
645             return vector_type().vectorize(_s);
646         }
647 
648         /// lexicographical comparison
operator <(const vector_type & _rhs) const649         bool operator<(const vector_type& _rhs) const {
650             return std::lexicographical_compare(
651                     values_.begin(), values_.end(),
652                     _rhs.values_.begin(), _rhs.values_.end());
653         }
654 
655         /// swap with another vector
swap(VectorT & _other)656         void swap(VectorT& _other)
657         noexcept(noexcept(std::swap(values_, _other.values_))) {
658             std::swap(values_, _other.values_);
659         }
660 
661         //------------------------------------------------------------ component iterators
662 
663         /// \name Component iterators
664         //@{
665 
666         using iterator               = typename container::iterator;
667         using const_iterator         = typename container::const_iterator;
668         using reverse_iterator       = typename container::reverse_iterator;
669         using const_reverse_iterator = typename container::const_reverse_iterator;
670 
begin()671         iterator               begin()         noexcept { return values_.begin();   }
begin() const672         const_iterator         begin()   const noexcept { return values_.cbegin();  }
cbegin() const673         const_iterator         cbegin()  const noexcept { return values_.cbegin();  }
674 
end()675         iterator               end()           noexcept { return values_.end();     }
end() const676         const_iterator         end()     const noexcept { return values_.cend();    }
cend() const677         const_iterator         cend()    const noexcept { return values_.cend();    }
678 
rbegin()679         reverse_iterator       rbegin()        noexcept { return values_.rbegin();  }
rbegin() const680         const_reverse_iterator rbegin()  const noexcept { return values_.crbegin(); }
crbegin() const681         const_reverse_iterator crbegin() const noexcept { return values_.crbegin(); }
682 
rend()683         reverse_iterator       rend()          noexcept { return values_.rend();    }
rend() const684         const_reverse_iterator rend()    const noexcept { return values_.crend();   }
crend() const685         const_reverse_iterator crend()   const noexcept { return values_.crend();   }
686 
687         //@}
688 };
689 
690 /// Component wise multiplication from the left
691 template<typename Scalar, int DIM, typename OtherScalar>
operator *(const OtherScalar & _s,const VectorT<Scalar,DIM> & rhs)692 auto operator*(const OtherScalar& _s, const VectorT<Scalar, DIM> &rhs) ->
693     decltype(rhs.operator*(_s)) {
694 
695     return rhs * _s;
696 }
697 
698 /// output a vector by printing its space-separated compontens
699 template<typename Scalar, int DIM>
operator <<(std::ostream & os,const VectorT<Scalar,DIM> & _vec)700 auto operator<<(std::ostream& os, const VectorT<Scalar, DIM> &_vec) ->
701     typename std::enable_if<
702         sizeof(decltype(os << _vec[0])) >= 0, std::ostream&>::type {
703 
704     os << _vec[0];
705     for (int i = 1; i < DIM; ++i) {
706         os << " " << _vec[i];
707     }
708     return os;
709 }
710 
711 /// read the space-separated components of a vector from a stream
712 template<typename Scalar, int DIM>
operator >>(std::istream & is,VectorT<Scalar,DIM> & _vec)713 auto operator>> (std::istream& is, VectorT<Scalar, DIM> &_vec) ->
714     typename std::enable_if<
715         sizeof(decltype(is >> _vec[0])) >= 0, std::istream &>::type {
716     for (int i = 0; i < DIM; ++i)
717         is >> _vec[i];
718     return is;
719 }
720 
721 /// \relates OpenMesh::VectorT
722 /// symmetric version of the dot product
723 template<typename Scalar, int DIM>
724 Scalar dot(const VectorT<Scalar, DIM>& _v1, const VectorT<Scalar, DIM>& _v2) {
725   return (_v1 | _v2);
726 }
727 
728 /// \relates OpenMesh::VectorT
729 /// symmetric version of the cross product
730 template<typename LScalar, typename RScalar, int DIM>
731 auto
cross(const VectorT<LScalar,DIM> & _v1,const VectorT<RScalar,DIM> & _v2)732 cross(const VectorT<LScalar, DIM>& _v1, const VectorT<RScalar, DIM>& _v2) ->
733     decltype(_v1 % _v2) {
734   return (_v1 % _v2);
735 }
736 
737 /// \relates OpenMesh::VectorT
738 /// non-member swap
739 template<typename Scalar, int DIM>
swap(VectorT<Scalar,DIM> & _v1,VectorT<Scalar,DIM> & _v2)740 void swap(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2)
741 noexcept(noexcept(_v1.swap(_v2))) {
742     _v1.swap(_v2);
743 }
744 
745 /// \relates OpenMesh::VectorT
746 /// non-member norm
747 template<typename Scalar, int DIM>
748 Scalar norm(const VectorT<Scalar, DIM>& _v) {
749     return _v.norm();
750 }
751 
752 /// \relates OpenMesh::VectorT
753 /// non-member sqrnorm
754 template<typename Scalar, int DIM>
755 Scalar sqrnorm(const VectorT<Scalar, DIM>& _v) {
756     return _v.sqrnorm();
757 }
758 /// \relates OpenMesh::VectorT
759 /// non-member vectorize
760 template<typename Scalar, int DIM, typename OtherScalar>
vectorize(VectorT<Scalar,DIM> & _v,OtherScalar const & _val)761 VectorT<Scalar, DIM>& vectorize(VectorT<Scalar, DIM>& _v, OtherScalar const& _val) {
762     return _v.vectorize(_val);
763 }
764 
765 /// \relates OpenMesh::VectorT
766 /// non-member normalize
767 template<typename Scalar, int DIM>
normalize(VectorT<Scalar,DIM> & _v)768 VectorT<Scalar, DIM>& normalize(VectorT<Scalar, DIM>& _v) {
769     return _v.normalize();
770 }
771 
772 /// \relates OpenMesh::VectorT
773 /// non-member maximize
774 template<typename Scalar, int DIM>
maximize(VectorT<Scalar,DIM> & _v1,VectorT<Scalar,DIM> & _v2)775 VectorT<Scalar, DIM>& maximize(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2) {
776     return _v1.maximize(_v2);
777 }
778 
779 /// \relates OpenMesh::VectorT
780 /// non-member minimize
781 template<typename Scalar, int DIM>
minimize(VectorT<Scalar,DIM> & _v1,VectorT<Scalar,DIM> & _v2)782 VectorT<Scalar, DIM>& minimize(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2) {
783     return _v1.minimize(_v2);
784 }
785 
786 /// \relates OpenMesh::VectorT
787 /// non-member max
788 template<typename Scalar, int DIM>
max(const VectorT<Scalar,DIM> & _v1,const VectorT<Scalar,DIM> & _v2)789 VectorT<Scalar, DIM> max(const VectorT<Scalar, DIM>& _v1, const VectorT<Scalar, DIM>& _v2) {
790     return _v1.max(_v2);
791 }
792 
793 /// \relates OpenMesh::VectorT
794 /// non-member min
795 template<typename Scalar, int DIM>
min(const VectorT<Scalar,DIM> & _v1,const VectorT<Scalar,DIM> & _v2)796 VectorT<Scalar, DIM> min(const VectorT<Scalar, DIM>& _v1, const VectorT<Scalar, DIM>& _v2) {
797   return _v1.min(_v2);
798 }
799 
800 
801 //== TYPEDEFS =================================================================
802 
803 /** 1-byte signed vector */
804 typedef VectorT<signed char,1> Vec1c;
805 /** 1-byte unsigned vector */
806 typedef VectorT<unsigned char,1> Vec1uc;
807 /** 1-short signed vector */
808 typedef VectorT<signed short int,1> Vec1s;
809 /** 1-short unsigned vector */
810 typedef VectorT<unsigned short int,1> Vec1us;
811 /** 1-int signed vector */
812 typedef VectorT<signed int,1> Vec1i;
813 /** 1-int unsigned vector */
814 typedef VectorT<unsigned int,1> Vec1ui;
815 /** 1-float vector */
816 typedef VectorT<float,1> Vec1f;
817 /** 1-double vector */
818 typedef VectorT<double,1> Vec1d;
819 
820 /** 2-byte signed vector */
821 typedef VectorT<signed char,2> Vec2c;
822 /** 2-byte unsigned vector */
823 typedef VectorT<unsigned char,2> Vec2uc;
824 /** 2-short signed vector */
825 typedef VectorT<signed short int,2> Vec2s;
826 /** 2-short unsigned vector */
827 typedef VectorT<unsigned short int,2> Vec2us;
828 /** 2-int signed vector */
829 typedef VectorT<signed int,2> Vec2i;
830 /** 2-int unsigned vector */
831 typedef VectorT<unsigned int,2> Vec2ui;
832 /** 2-float vector */
833 typedef VectorT<float,2> Vec2f;
834 /** 2-double vector */
835 typedef VectorT<double,2> Vec2d;
836 
837 /** 3-byte signed vector */
838 typedef VectorT<signed char,3> Vec3c;
839 /** 3-byte unsigned vector */
840 typedef VectorT<unsigned char,3> Vec3uc;
841 /** 3-short signed vector */
842 typedef VectorT<signed short int,3> Vec3s;
843 /** 3-short unsigned vector */
844 typedef VectorT<unsigned short int,3> Vec3us;
845 /** 3-int signed vector */
846 typedef VectorT<signed int,3> Vec3i;
847 /** 3-int unsigned vector */
848 typedef VectorT<unsigned int,3> Vec3ui;
849 /** 3-float vector */
850 typedef VectorT<float,3> Vec3f;
851 /** 3-double vector */
852 typedef VectorT<double,3> Vec3d;
853 /** 3-bool vector */
854 typedef VectorT<bool,3> Vec3b;
855 
856 /** 4-byte signed vector */
857 typedef VectorT<signed char,4> Vec4c;
858 /** 4-byte unsigned vector */
859 typedef VectorT<unsigned char,4> Vec4uc;
860 /** 4-short signed vector */
861 typedef VectorT<signed short int,4> Vec4s;
862 /** 4-short unsigned vector */
863 typedef VectorT<unsigned short int,4> Vec4us;
864 /** 4-int signed vector */
865 typedef VectorT<signed int,4> Vec4i;
866 /** 4-int unsigned vector */
867 typedef VectorT<unsigned int,4> Vec4ui;
868 /** 4-float vector */
869 typedef VectorT<float,4> Vec4f;
870 /** 4-double vector */
871 typedef VectorT<double,4> Vec4d;
872 
873 /** 5-byte signed vector */
874 typedef VectorT<signed char, 5> Vec5c;
875 /** 5-byte unsigned vector */
876 typedef VectorT<unsigned char, 5> Vec5uc;
877 /** 5-short signed vector */
878 typedef VectorT<signed short int, 5> Vec5s;
879 /** 5-short unsigned vector */
880 typedef VectorT<unsigned short int, 5> Vec5us;
881 /** 5-int signed vector */
882 typedef VectorT<signed int, 5> Vec5i;
883 /** 5-int unsigned vector */
884 typedef VectorT<unsigned int, 5> Vec5ui;
885 /** 5-float vector */
886 typedef VectorT<float, 5> Vec5f;
887 /** 5-double vector */
888 typedef VectorT<double, 5> Vec5d;
889 
890 /** 6-byte signed vector */
891 typedef VectorT<signed char,6> Vec6c;
892 /** 6-byte unsigned vector */
893 typedef VectorT<unsigned char,6> Vec6uc;
894 /** 6-short signed vector */
895 typedef VectorT<signed short int,6> Vec6s;
896 /** 6-short unsigned vector */
897 typedef VectorT<unsigned short int,6> Vec6us;
898 /** 6-int signed vector */
899 typedef VectorT<signed int,6> Vec6i;
900 /** 6-int unsigned vector */
901 typedef VectorT<unsigned int,6> Vec6ui;
902 /** 6-float vector */
903 typedef VectorT<float,6> Vec6f;
904 /** 6-double vector */
905 typedef VectorT<double,6> Vec6d;
906 
907 } // namespace OpenMesh
908 
909 /**
910  * Literal operator for inline specification of colors in HTML syntax.
911  *
912  * Example:
913  * \code{.cpp}
914  * OpenMesh::Vec4f light_blue = 0x1FCFFFFF_htmlColor;
915  * \endcode
916  */
operator ""_htmlColor(unsigned long long raw_color)917 constexpr OpenMesh::Vec4f operator"" _htmlColor(unsigned long long raw_color) {
918     return OpenMesh::Vec4f(
919             ((raw_color >> 24) & 0xFF) / 255.0f,
920             ((raw_color >> 16) & 0xFF) / 255.0f,
921             ((raw_color >>  8) & 0xFF) / 255.0f,
922             ((raw_color >>  0) & 0xFF) / 255.0f);
923 }
924 
925 #endif /* OPENMESH_SRC_OPENMESH_CORE_GEOMETRY_VECTOR11T_HH_ */
926