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