acme
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages Concepts
sequence.h
1/*
2 NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>.
3 The widget drawing code is based on the NanoVG demo application
4 by Mikko Mononen.
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE.txt file.
8*/
9// Merge with estamira/particle/vec4:minimum_maximum_rand
10#pragma once
11
12
13//#include "common.h"
14//#include "traits.h"
15//#include <cassert>
16#include <cmath>
17//#include <iosfwd>
18//#include <string.h> // ::memory_set
19
20
21
22template < primitive_number COORDINATE, ::collection::count t_iSize >
23struct sequence_type
24{
25
26 using sequence_tag = sequence_t;
27 using sequence_size = sequence_size_t < t_iSize >;
28 using BASE_COORDINATE = COORDINATE;
29 using UNIT_TYPE = COORDINATE;
30
31
32 COORDINATE m_coordinatea[t_iSize];
33
34
35 static constexpr bool IS_MATRIX = false;
36 static constexpr ::collection::count SIZE = t_iSize;
37
38
39 constexpr sequence_type()
40 {
41
42 set_all(0);
43
44 }
45
46 sequence_type(no_initialize_t)
47 {
48
49
50 }
51
52
53 constexpr sequence_type(UNIT_TYPE n)
54 {
55
56 set_all(n);
57
58 }
59
60// sequence_type(const sequence_type&) = default;
61
62// template <primitive_number T,
63// std::enable_if_t<T::SIZE == SIZE &&
64// std::is_same_v<typename T::COORDINATE, COORDINATE>, int> = 0>
65// sequence_type(const T & a) {
66// for (::collection::count i = 0; i < SIZE; ++i)
67// m_coordinatea[i] = (COORDINATE)a[i];
68// }
69
70 template < primitive_number NUMBER1, ::collection::count S = SIZE, std::enable_if_t<S == 2, int> = 0 >
71 constexpr sequence_type(const sequence_type < NUMBER1, 2 > & sequence)
72 {
73 m_coordinatea[0] = (UNIT_TYPE) sequence.m_coordinatea[0];
74 m_coordinatea[1] = (UNIT_TYPE) sequence.m_coordinatea[1];
75 }
76
77
78 template < primitive_number NUMBER1, ::collection::count S = SIZE, std::enable_if_t<S == 3, int> = 0 >
79 constexpr sequence_type(const sequence_type < NUMBER1, 3 > & sequence)
80 {
81 m_coordinatea[0] = (UNIT_TYPE) sequence.m_coordinatea[0];
82 m_coordinatea[1] = (UNIT_TYPE) sequence.m_coordinatea[1];
83 m_coordinatea[2] = (UNIT_TYPE) sequence.m_coordinatea[2];
84 }
85
86
87 template < primitive_number NUMBER1, ::collection::count S = SIZE, std::enable_if_t<S == 4, int> = 0 >
88 constexpr sequence_type(const sequence_type < NUMBER1, 4 > & sequence)
89 {
90 m_coordinatea[0] = (UNIT_TYPE) sequence.m_coordinatea[0];
91 m_coordinatea[1] = (UNIT_TYPE) sequence.m_coordinatea[1];
92 m_coordinatea[2] = (UNIT_TYPE) sequence.m_coordinatea[2];
93 m_coordinatea[3] = (UNIT_TYPE) sequence.m_coordinatea[3];
94 }
95
96// sequence_type(COORDINATE s) {
97// for (::collection::count i = 0; i < SIZE; ++i)
98// m_coordinatea[i] = s;
99// }
100
101 template < ::collection::count S = SIZE, std::enable_if_t<S == 2, int> = 0 >
102 constexpr sequence_type(COORDINATE coordinate0, COORDINATE coordinate1)
103 {
104 m_coordinatea[0] = coordinate0;
105 m_coordinatea[1] = coordinate1;
106 }
107
108
109 template <::collection::count S = SIZE, std::enable_if_t<S == 3, int> = 0>
110 constexpr sequence_type(COORDINATE coordinate0, COORDINATE coordinate1,
111 COORDINATE coordinate2)
112 {
113 m_coordinatea[0] = coordinate0;
114 m_coordinatea[1] = coordinate1;
115 m_coordinatea[2] = coordinate2;
116 }
117
118
119 template <::collection::count S = SIZE, std::enable_if_t<S == 4, int> = 0>
120 constexpr sequence_type(
121 COORDINATE coordinate0, COORDINATE coordinate1,
122 COORDINATE coordinate2, COORDINATE coordinate3)
123 {
124 m_coordinatea[0] = coordinate0;
125 m_coordinatea[1] = coordinate1;
126 m_coordinatea[2] = coordinate2;
127 m_coordinatea[3] = coordinate3;
128 }
129
130
131 constexpr ::collection::count get_size() const { return SIZE; }
132 constexpr ::collection::count get_count() const { return this->get_size(); }
133
134
135 constexpr COORDINATE & set_coordinate(::collection::index i, COORDINATE coordinate)
136 {
137
138 return m_coordinatea[i] = coordinate;
139
140 }
141
142
143 constexpr COORDINATE coordinate(::collection::index i) const
144 {
145
146 return m_coordinatea[i];
147
148 }
149
150
151 constexpr COORDINATE & coordinate(::collection::index i)
152 {
153
154 return m_coordinatea[i];
155
156 }
157
158
159 void set_all(COORDINATE coordinate)
160 {
161
162 for (::collection::count i = 0; i < SIZE; ++i)
163 {
164
165 m_coordinatea[i] = coordinate;
166
167 }
168
169 }
170
171 bool is_all(COORDINATE coordinate) const
172 {
173
174 for (::collection::count i = 0; i < SIZE; ++i)
175 {
176
177 if(m_coordinatea[i] != coordinate)
178 {
179
180 return false;
181
182 }
183
184 }
185
186 return true;
187
188 }
189
190
191
192 // simple menthods: operates on x, y
193 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2, int> = 0 >
194 inline void add2(const sequence_type & a)
195 {
196 this->a() += a.a();
197 this->b() += a.b();
198 }
199 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2, int> = 0 >
200 inline void sub2(const sequence_type & a)
201 {
202 this->a() -= a.a();
203 this->b() -= a.b();
204 }
205 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2, int> = 0 >
206 inline void mul2(UNIT_TYPE n)
207 {
208 this->a() *= n;
209 this->b() *= n;
210 }
211 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2, int> = 0 >
212 inline void set2(UNIT_TYPE a, UNIT_TYPE b)
213 {
214 this->a() = a;
215 this->b() = b;
216 }
217
218 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2, int> = 0 >
219 static inline void mix2(const sequence_type &a, const sequence_type &b, UNIT_TYPE t, sequence_type &c)
220 {
221 c.a() = a.a()*((UNIT_TYPE)1.0 - t) + b.a()*t;
222 c.b() = a.b()*((UNIT_TYPE)1.0 - t) + b.b()*t;
223 }
224
225 // simple menthods: operates on x, y, z
226 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3, int> = 0 >
227 inline void add3(const sequence_type & a)
228 {
229 this->a() += a.a();
230 this->b() += a.b();
231 this->c() += a.c();
232 }
233 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3, int> = 0 >
234 inline void sub3(const sequence_type & a)
235 {
236 this->a() -= a.a();
237 this->b() -= a.b();
238 this->c() -= a.c();
239 }
240 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3, int> = 0 >
241 inline void mul3(UNIT_TYPE n)
242 {
243 this->a() *= n;
244 this->b() *= n;
245 this->c() *= n;
246 }
247 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3, int> = 0 >
248 inline void set3(UNIT_TYPE a, UNIT_TYPE b, UNIT_TYPE c)
249 {
250 this->a() = a;
251 this->b() = b;
252 this->c() = c;
253 }
254
255 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3, int> = 0 >
256 static inline void mix3(const sequence_type &a, const sequence_type &b, UNIT_TYPE t, sequence_type &c)
257 {
258 c.a() = a.a()*((UNIT_TYPE)1.0 - t) + b.a()*t;
259 c.b() = a.b()*((UNIT_TYPE)1.0 - t) + b.b()*t;
260 c.c() = a.c()*((UNIT_TYPE)1.0 - t) + b.c()*t;
261 }
262
263 // simple menthods: operates on x, y, z, w
264 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4, int> = 0 >
265 inline void add4(const sequence_type & q)
266 {
267 this->a() += q.a();
268 this->b() += q.b();
269 this->c() += q.c();
270 this->d() += q.d();
271 }
272 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4, int> = 0 >
273 inline void sub4(const sequence_type & q)
274 {
275 this->a() -= q.a();
276 this->b() -= q.b();
277 this->c() -= q.c();
278 this->d() -= q.d();
279 }
280 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4, int> = 0 >
281 inline void mul4(UNIT_TYPE n)
282 {
283 this->a() *= n;
284 this->b() *= n;
285 this->c() *= n;
286 this->d() *= n;
287 }
288 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4, int> = 0 >
289 inline void set4(UNIT_TYPE a, UNIT_TYPE b, UNIT_TYPE c, UNIT_TYPE d)
290 {
291 this->a() = a;
292 this->b() = b;
293 this->c() = c;
294 this->d() = d;
295 }
296
297 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4, int> = 0 >
298 static inline void mix4(const sequence_type &a, const sequence_type &b, UNIT_TYPE t, sequence_type &c)
299 {
300 c.a() = a.a()*((UNIT_TYPE)1.0 - t) + b.a()*t;
301 c.b() = a.b()*((UNIT_TYPE)1.0 - t) + b.b()*t;
302 c.c() = a.c()*((UNIT_TYPE)1.0 - t) + b.c()*t;
303 c.d() = a.d()*((UNIT_TYPE)1.0 - t) + b.d()*t;
304 }
305
306
307 sequence_type operator-() const
308 {
309 sequence_type result;
310 for (::collection::count i = 0; i < SIZE; ++i)
311 result[i] = -m_coordinatea[i];
312 return result;
313 }
314
315
316 friend sequence_type operator+(const sequence_type& a, const sequence_type& b)
317 {
318 sequence_type result;
319 for (::collection::count i = 0; i < SIZE; ++i)
320 result[i] = a.m_coordinatea[i] + b.m_coordinatea[i];
321 return result;
322 }
323
324 sequence_type& operator+=(const sequence_type& a) {
325 for (::collection::count i = 0; i < SIZE; ++i)
326 m_coordinatea[i] += a.m_coordinatea[i];
327 return *this;
328 }
329
330 friend sequence_type operator-(const sequence_type& a, const sequence_type& b) {
331 sequence_type result;
332 for (::collection::count i = 0; i < SIZE; ++i)
333 result[i] = a.m_coordinatea[i] - b.m_coordinatea[i];
334 return result;
335 }
336
337 sequence_type& operator-=(const sequence_type& a) {
338 for (::collection::count i = 0; i < SIZE; ++i)
339 m_coordinatea[i] -= a.m_coordinatea[i];
340 return *this;
341 }
342
343 friend sequence_type operator *(const sequence_type& a, const sequence_type& b) {
344 sequence_type result;
345 for (::collection::count i = 0; i < SIZE; ++i)
346 result[i] = a.m_coordinatea[i] * b.m_coordinatea[i];
347 return result;
348 }
349
350 template < primitive_number NUMBER1 >
351 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > operator *(NUMBER1 n) const
352 {
353 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > result;
354 for (::collection::count i = 0; i < SIZE; ++i)
355 result[i] = (largest_number < UNIT_TYPE, NUMBER1 >) (this->m_coordinatea[i] * n);
356 return result;
357 }
358
359
360 sequence_type& operator*=(const sequence_type& a) {
361 for (::collection::count i = 0; i < SIZE; ++i)
362 m_coordinatea[i] *= a.m_coordinatea[i];
363 return *this;
364 }
365
366
367 friend sequence_type operator/(const sequence_type& a, const sequence_type& b) {
368 sequence_type result;
369 for (::collection::count i = 0; i < SIZE; ++i)
370 result[i] = a.m_coordinatea[i] / b.m_coordinatea[i];
371 return result;
372 }
373
374
375 template < primitive_number NUMBER1 >
376 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > operator /(NUMBER1 n) const
377 {
378 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > result;
379 for (::collection::count i = 0; i < SIZE; ++i)
380 result[i] = (largest_number < UNIT_TYPE, NUMBER1 >) (this->m_coordinatea[i] / n);
381 return result;
382 }
383
384
385 sequence_type& operator/=(const sequence_type& a) {
386 for (::collection::count i = 0; i < SIZE; ++i)
387 m_coordinatea[i] /= a.m_coordinatea[i];
388 return *this;
389 }
390
391 bool operator==(const sequence_type& a) const {
392 for (::collection::count i = 0; i < SIZE; ++i) {
393 if (m_coordinatea[i] != a.m_coordinatea[i])
394 return false;
395 }
396 return true;
397 }
398
399
400 template < typename PREDICATE >
401 bool is_every(PREDICATE predicate) const
402 {
403
404 for (::collection::count i = 0; i < SIZE; ++i)
405 {
406
407 if (!predicate(m_coordinatea[i]))
408 {
409
410 return false;
411
412 }
413
414 }
415
416 return true;
417
418 }
419
420
421 bool is_empty() const
422 {
423
424 return is_every([](auto coordinate) {return coordinate == COORDINATE{}; });
425
426 }
427
428
429 bool is_set() const
430 {
431
432 return !is_empty();
433
434 }
435
436
437 bool is_all_set() const
438 {
439
440 return is_every([](auto coordinate) {return coordinate != COORDINATE{}; });
441
442 }
443
444
445 bool is_all_positive() const
446 {
447
448 return is_every([](auto coordinate) {return coordinate > COORDINATE{}; });
449
450 }
451
452
453 template < typename PREDICATE >
454 sequence_type prefer_self_coordinate_if(const sequence_type &vectorOther, PREDICATE predicate) const
455 {
456
457 sequence_type vector;
458
459 for (::collection::count i = 0; i < SIZE; ++i)
460 {
461
462 if (predicate(m_coordinatea[i]))
463 {
464
465 vector[i] = m_coordinatea[i];
466
467 }
468 else
469 {
470
471 vector[i] = vectorOther.m_coordinatea[i];
472
473 }
474
475 }
476
477 return vector;
478
479 }
480
481
482 sequence_type prefer_self_coordinate_if_set(const sequence_type& vectorOther) const
483 {
484
485 return prefer_self_coordinate_if(vectorOther, [](auto coordinate) {return coordinate != 0; });
486
487 }
488
489
490 sequence_type prefer_self_coordinate_if_positive(const sequence_type& vectorOther) const
491 {
492
493 return prefer_self_coordinate_if(vectorOther, [](auto coordinate) {return coordinate > COORDINATE{}; });
494
495 }
496
497
498 template < typename PREDICATE, typename SOURCE_PREDICATE >
499 sequence_type pred_prefer_self_coordinate_if(PREDICATE predicate, SOURCE_PREDICATE sourcepredicate) const
500 {
501
502 if (is_every(predicate))
503 {
504
505 return *this;
506
507 }
508
509 auto vectorOther = sourcepredicate();
510
511 return prefer_self_coordinate_if(vectorOther, predicate);
512
513 }
514
515
516 template < typename SOURCE_PREDICATE >
517 sequence_type pred_prefer_self_coordinate_if_set(SOURCE_PREDICATE sourcepredicate) const
518 {
519
520 return pred_prefer_self_coordinate_if([](auto coordinate) {return coordinate != COORDINATE{}; }, sourcepredicate);
521
522 }
523
524
525 template < typename SOURCE_PREDICATE >
526 sequence_type pred_prefer_self_coordinate_if_positive(SOURCE_PREDICATE sourcepredicate) const
527 {
528
529 return pred_prefer_self_coordinate_if([](auto coordinate) {return coordinate > COORDINATE{}; }, sourcepredicate);
530
531 }
532
533
534
535 constexpr bool operator!=(const sequence_type& a) const { return !operator==(a); }
536
537 constexpr const COORDINATE& operator[](::collection::count i) const { return m_coordinatea[i]; }
538
539 constexpr COORDINATE& operator[](::collection::count i) { return m_coordinatea[i]; }
540
541 template <::collection::count S = SIZE, std::enable_if_t<(S >= 1), int> = 0>
542 constexpr const COORDINATE& a() const { return m_coordinatea[0]; }
543 template <::collection::count S = SIZE, std::enable_if_t<(S >= 1), int> = 0>
544 COORDINATE& a() { return m_coordinatea[0]; }
545
546 template <::collection::count S = SIZE, std::enable_if_t<(S >= 2), int> = 0>
547 constexpr const COORDINATE& b() const { return m_coordinatea[1]; }
548 template <::collection::count S = SIZE, std::enable_if_t<(S >= 2), int> = 0>
549 COORDINATE& b() { return m_coordinatea[1]; }
550
551 template <::collection::count S = SIZE, std::enable_if_t<(S >= 3), int> = 0>
552 constexpr const COORDINATE& c() const { return m_coordinatea[2]; }
553 template <::collection::count S = SIZE, std::enable_if_t<(S >= 3), int> = 0>
554 COORDINATE& c() { return m_coordinatea[2]; }
555
556 template <::collection::count S = SIZE, std::enable_if_t<(S >= 4), int> = 0>
557 constexpr const COORDINATE& d() const { return m_coordinatea[3]; }
558 template <::collection::count S = SIZE, std::enable_if_t<(S >= 4), int> = 0>
559 COORDINATE& d() { return m_coordinatea[3]; }
560
561
562 template <::collection::count S = SIZE, std::enable_if_t<(S == 2), int> = 0>
563 COORDINATE dot_with_left_perpendicular_of(const sequence_type & b)
564 {
565
566 return (this->b() * b.a()) - (this->a() * b.b());
567
568 }
569
570
571 template <::collection::count S = SIZE, std::enable_if_t<(S == 2), int> = 0>
572 COORDINATE angle(const sequence_type & b)
573 {
574
575 return ::std::atan2(this->dot_with_left_perpendicular_of(b), this->dot(b));
576
577 }
578
579
580 sequence_type maximum(const sequence_type & vector) const
581 {
582
583 sequence_type result;
584
585 for (::collection::count i = 0; i < SIZE; ++i)
586 {
587
588 result.m_coordinatea[i] = ::maximum(m_coordinatea[i], vector.m_coordinatea[i]);
589
590 }
591
592 return result;
593
594 }
595
596 sequence_type minimum(const sequence_type& vector) const
597 {
598
599 sequence_type result;
600
601 for (::collection::count i = 0; i < SIZE; ++i)
602 {
603
604 result.m_coordinatea[i] = ::minimum(m_coordinatea[i], vector.m_coordinatea[i]);
605
606 }
607
608 return result;
609
610 }
611
612
613 UNIT_TYPE minimum() const
614 {
615
616 UNIT_TYPE nMinimum = this->m_coordinatea[0];
617
618 for (::collection::count i = 1; i < SIZE; ++i)
619 {
620
621 nMinimum = ::minimum(nMinimum, this->m_coordinatea[i]);
622
623 }
624
625 return nMinimum;
626
627 }
628
629
630 UNIT_TYPE maximum() const
631 {
632
633 UNIT_TYPE nMaximum = this->m_coordinatea[0];
634
635 for (::collection::count i = 1; i < SIZE; ++i)
636 {
637
638 nMaximum = ::maximum(nMaximum, this->m_coordinatea[i]);
639
640 }
641
642 return nMaximum;
643
644 }
645
646
647 COORDINATE dot(const sequence_type & vector) const
648 {
649
650 COORDINATE result = m_coordinatea[0] * vector.m_coordinatea[0];
651
652 for (::collection::count i = 1; i < SIZE; ++i)
653 {
654
655 result += m_coordinatea[i] * vector.m_coordinatea[i];
656
657 }
658
659 return result;
660
661 }
662
663
664 COORDINATE squared_modulus() const
665 {
666
667 return dot(*this);
668
669 }
670
671
672 COORDINATE modulus() const
673 {
674
675 return ::sqrt(squared_modulus());
676
677 }
678
679
680 sequence_type make_unitary() const
681 {
682
683 return *this / modulus();
684
685 }
686
687
688 const UNIT_TYPE & get_dimension(enum_orientation eorientation) const
689 {
690
691 return this->m_coordinatea[eorientation];
692
693 }
694
695 UNIT_TYPE & get_dimension(enum_orientation eorientation)
696 {
697
698 return this->m_coordinatea[eorientation];
699
700 }
701
702
703 template < ::collection::count S = SIZE, std::enable_if_t<S == 2, int> = 0 >
704 const UNIT_TYPE & get_normal_dimension(enum_orientation eorientation) const
705 {
706
707 return this->m_coordinatea[orthogonal2_index_of(eorientation)];
708
709 }
710
711
712 template < ::collection::count S = SIZE, std::enable_if_t<S == 2, int> = 0 >
713 UNIT_TYPE & get_normal_dimension(enum_orientation eorientation)
714 {
715
716 return this->m_coordinatea[orthogonal2_index_of(eorientation)];
717
718 }
719
720
721 inline UNIT_TYPE & set_dimension(enum_orientation eorientation, UNIT_TYPE l) noexcept
722 {
723
724 return this->m_coordinatea[eorientation] = l;
725
726 }
727
728
729 inline UNIT_TYPE & set_orthogonal_dimension(enum_orientation eorientation, UNIT_TYPE l) noexcept
730 {
731
732 return this->m_coordinatea[orthogonal2_index_of(eorientation)] = l;
733
734 }
735
736
737
738};
739
740
741
742template <typename COORDINATE>
745 a.b() * b.c() - a.c() * b.b(),
746 a.c() * b.a() - a.a() * b.c(),
747 a.a() * b.b() - a.b() * b.a()
748 );
749}
750
751
752
753//template <typename COORDINATE, ::collection::count SIZE>
754//sequence_type<COORDINATE, SIZE> min(const sequence_type<COORDINATE, SIZE>& a1, const sequence_type<COORDINATE, SIZE>& a2) {
755// sequence_type<COORDINATE, SIZE> result;
756// for (::collection::count i = 0; i < SIZE; ++i)
757// result.m_coordinatea[i] = std::min(a1.m_coordinatea[i], a2.m_coordinatea[i]);
758// return result;
759//}
760//
761//template < primitive_number NUMBER >
762//class sequence2_type :
763// public sequence_type < NUMBER, 2 >
764//{
765//public:
766//
767//
768// using sequence_type < NUMBER, 2 >::sequence_type;
769//
770//
771// NUMBER dot_with_left_perpendicular_of(const sequence2_type & b)
772// {
773//
774// return (this->b() * b.a()) - (this->a() * b.b());
775//
776// }
777//
778//
779// NUMBER angle(const sequence2_type & b)
780// {
781//
782// return atan2f(this->dot_with_left_perpendicular_of(b), this->dot(b));
783//
784// }
785//
786//
787//
788//};
789
790// Import some common Enoki types
791using sequence2_int = sequence_type<int, 2>;
792using sequence3_int = sequence_type<int, 3>;
793using sequence4_int = sequence_type<int, 4>;
794
795using sequence2_long_long = sequence_type<long long, 2>;
796using sequence3_long_long = sequence_type<long long, 3>;
797using sequence4_long_long = sequence_type<long long, 4>;
798
799using sequence2_float = sequence_type<float, 2>;
800using sequence3_float = sequence_type<float, 3>;
801using sequence4_float = sequence_type<float, 4>;
802
803using sequence2_double = sequence_type<double, 2>;
804using sequence3_double = sequence_type<double, 3>;
805using sequence4_double = sequence_type<double, 4>;
806
808// * \class Color common.h nanoui/common.h
809// *
810// * \brief Stores an RGBA floating point color value.
811// *
812// * This class simply wraps around an ``Vector4f``, providing some convenient
813// * methods and terminology for thinking of it as a color. The data operates in the
814// * same way as ``Vector4f``, and the following values are identical:
815// *
816// * \rst
817// * +---------+-------------+----------------+-------------+
818// * | Channel | sequence_type Index | Vector4f field | Color field |
819// * +=========+=============+================+=============+
820// * | Red | ``0`` | x() | r() |
821// * +---------+-------------+----------------+-------------+
822// * | Green | ``1`` | y() | g() |
823// * +---------+-------------+----------------+-------------+
824// * | Blue | ``2`` | z() | b() |
825// * +---------+-------------+----------------+-------------+
826// * | Alpha | ``3`` | w() | a() |
827// * +---------+-------------+----------------+-------------+
828// * \endrst
829// */
830//class Color : public Vector4f {
831//public:
832// using Vector4f::Vector4f;
833// using Vector4f::operator=;
834//
835// /// Default constructor: represents black (``r, g, b, a = 0``)
836// Color() : Color(0, 0, 0, 0) { }
837//
838// /// Initialize from a 4D vector
839// Color(const Vector4f & color) : Vector4f(color) { }
840//
841// Color(const color::color & color) : Color(color.r, color.g, color.b, color.a) { }
842//
843// /**
844// * Copies (x, y, z) from the input vector, and uses the value specified by
845// * the ``alpha`` parameter for this Color object's alpha component.
846// *
847// * \param color
848// * The three dimensional float vector being copied.
849// *
850// * \param alpha
851// * The value to set this object's alpha component to.
852// */
853// Color(const Vector3f & color, float alpha)
854// : Color(color[0], color[1], color[2], alpha) { }
855//
856// /**
857// * Copies (x, y, z) from the input vector, casted as floats first and then
858// * divided by ``255.0``, and uses the value specified by the ``alpha``
859// * parameter, casted to a float and divided by ``255.0`` as well, for this
860// * Color object's alpha component.
861// *
862// * \param color
863// * The three dimensional integer vector being copied, will be divided by ``255.0``.
864// *
865// * \param alpha
866// * The value to set this object's alpha component to, will be divided by ``255.0``.
867// */
868// Color(const Vector3i & color, int alpha)
869// : Color(Vector3f(color) / 255.f, alpha / 255.f) { }
870//
871// /**
872// * Copies (x, y, z) from the input vector, and sets the alpha of this color
873// * to be ``1.0``.
874// *
875// * \param color
876// * The three dimensional float vector being copied.
877// */
878// Color(const Vector3f & color) : Color(color, 1.0f) {}
879//
880// /**
881// * Copies (x, y, z) from the input vector, casting to floats and dividing by
882// * ``255.0``. The alpha of this color will be set to ``1.0``.
883// *
884// * \param color
885// * The three dimensional integer vector being copied, will be divided by ``255.0``.
886// */
887// Color(const Vector3i & color)
888// : Color(Vector3f(color) / 255.f, 1.f) { }
889//
890// /**
891// * Copies (x, y, z, w) from the input vector, casting to floats and dividing
892// * by ``255.0``.
893// *
894// * \param color
895// * The three dimensional integer vector being copied, will be divided by ``255.0``.
896// */
897// Color(const Vector4i & color)
898// : Color(Vector4f(color) / 255.f) { }
899//
900// /**
901// * Creates the Color ``(intensity, intensity, intensity, alpha)``.
902// *
903// * \param intensity
904// * The value to be used for red, green, and blue.
905// *
906// * \param alpha
907// * The alpha component of the color.
908// */
909// Color(float intensity, float alpha)
910// : Color(Vector3f(intensity), alpha) { }
911//
912// /**
913// * Creates the Color ``(intensity, intensity, intensity, alpha) / 255.0``.
914// * Values are casted to floats before division.
915// *
916// * \param intensity
917// * The value to be used for red, green, and blue, will be divided by ``255.0``.
918// *
919// * \param alpha
920// * The alpha component of the color, will be divided by ``255.0``.
921// */
922// Color(int intensity, int alpha)
923// : Color(Vector3i(intensity), alpha) { }
924//
925// /**
926// * Explicit constructor: creates the Color ``(r, g, b, a)``.
927// *
928// * \param r
929// * The red component of the color.
930// *
931// * \param g
932// * The green component of the color.
933// *
934// * \param b
935// * The blue component of the color.
936// *
937// * \param a
938// * The alpha component of the color.
939// */
940// Color(float r, float g, float b, float a) : Color(Vector4f(r, g, b, a)) { }
941//
942// /**
943// * Explicit constructor: creates the Color ``(r, g, b, a) / 255.0``.
944// * Values are casted to floats before division.
945// *
946// * \param r
947// * The red component of the color, will be divided by ``255.0``.
948// *
949// * \param g
950// * The green component of the color, will be divided by ``255.0``.
951// *
952// * \param b
953// * The blue component of the color, will be divided by ``255.0``.
954// *
955// * \param a
956// * The alpha component of the color, will be divided by ``255.0``.
957// */
958// Color(int r, int g, int b, int a) : Color(Vector4f((float)r, (float)g, (float)b, (float)a) / 255.f) { }
959//
960// /// Return a reference to the red channel
961// float & r() { return x(); }
962// /// Return a reference to the red channel (const version)
963// const float & r() const { return x(); }
964// /// Return a reference to the green channel
965// float & g() { return y(); }
966// /// Return a reference to the green channel (const version)
967// const float & g() const { return y(); }
968// /// Return a reference to the blue channel
969// float & b() { return z(); }
970// /// Return a reference to the blue channel (const version)
971// const float & b() const { return z(); }
972// /// Return a reference to the alpha channel
973// float & a() { return w(); }
974// /// Return a reference to the alpha channel (const version)
975// const float & a() const { return w(); }
976//
977// /**
978// * Computes the luminance as ``l = 0.299r + 0.587g + 0.144b + 0.0a``. If
979// * the luminance is less than 0.5, white is returned. If the luminance is
980// * greater than or equal to 0.5, black is returned. Both returns will have
981// * an alpha component of 1.0.
982// */
983// Color contrasting_color() const {
984// float luminance = dot(*this, Color(0.299f, 0.587f, 0.144f, 0.f));
985// return Color(luminance < 0.5f ? 1.f : 0.f, 1.f);
986// }
987//
988// /// Allows for conversion between this Color and NanoVG's representation.
989// inline operator const ::color::color & () const;
990//};
991
993template <typename Value_, ::collection::count Size_> struct Matrix {
994 static constexpr bool IsNanoGUI = true;
995 static constexpr bool IsMatrix = true;
996
997 using COORDINATE = Value_;
998 static constexpr ::collection::count SIZE = Size_;
999
1000 Matrix() { }
1001
1002 explicit Matrix(COORDINATE s) {
1003 ::memory_set(m, 0, sizeof(COORDINATE) * SIZE * SIZE);
1004 for (::collection::count i = 0; i < SIZE; ++i)
1005 m[i][i] = s;
1006 }
1007
1008 friend Matrix operator*(const Matrix& a, const Matrix& b) {
1009 Matrix c;
1010 for (::collection::count i = 0; i < SIZE; ++i) {
1011 for (::collection::count j = 0; j < SIZE; ++j) {
1012 COORDINATE accum = 0;
1013 for (::collection::count k = 0; k < SIZE; ++k)
1014 accum += a.m[k][i] * b.m[j][k];
1015 c.m[j][i] = accum;
1016 }
1017 }
1018 return c;
1019 }
1020
1021 static Matrix scale(const sequence_type<COORDINATE, SIZE - 1>& m_coordinatea) {
1022 Matrix result;
1023 ::memory_set(result.m, 0, sizeof(COORDINATE) * SIZE * SIZE);
1024 for (::collection::count i = 0; i < SIZE; ++i)
1025 result.m[i][i] = i < SIZE - 1 ? m_coordinatea[i] : 1;
1026 return result;
1027 }
1028
1029 static Matrix scale(const sequence_type<COORDINATE, SIZE>& m_coordinatea) {
1030 Matrix result;
1031 ::memory_set(result.m, 0, sizeof(COORDINATE) * SIZE * SIZE);
1032 for (::collection::count i = 0; i < SIZE; ++i)
1033 result.m[i][i] = m_coordinatea[i];
1034 return result;
1035 }
1036
1037 static Matrix translate(const sequence_type<COORDINATE, SIZE - 1>& m_coordinatea) {
1038 Matrix result;
1039 ::memory_set(result.m, 0, sizeof(COORDINATE) * SIZE * SIZE);
1040 for (::collection::count i = 0; i < SIZE; ++i) {
1041 result.m[i][i] = 1.f;
1042 if (i < SIZE - 1)
1043 result.m[SIZE - 1][i] = m_coordinatea[i];
1044 }
1045 return result;
1046 }
1047
1048
1049 template <::collection::count S = SIZE, std::enable_if_t<S == 4, int> = 0>
1050 static Matrix rotate(const sequence_type<COORDINATE, 3>& axis, COORDINATE angle)
1051 {
1052
1053 COORDINATE s = ::sin(angle);
1054 COORDINATE c = ::cos(angle);
1055 COORDINATE t = 1 - c;
1056
1057 Matrix result(0);
1058 result.m[3][3] = 1;
1059 result.m[0][0] = c + axis.a() * axis.a() * t;
1060 result.m[1][1] = c + axis.b() * axis.b() * t;
1061 result.m[2][2] = c + axis.c() * axis.c() * t;
1062
1063 COORDINATE tmp1 = axis.a() * axis.b() * t;
1064 COORDINATE tmp2 = axis.c() * s;
1065
1066 result.m[0][1] = tmp1 + tmp2;
1067 result.m[1][0] = tmp1 - tmp2;
1068
1069 tmp1 = axis.a() * axis.c() * t;
1070 tmp2 = axis.b() * s;
1071 result.m[0][2] = tmp1 - tmp2;
1072 result.m[2][0] = tmp1 + tmp2;
1073
1074 tmp1 = axis.b() * axis.c() * t;
1075 tmp2 = axis.a() * s;
1076 result.m[1][2] = tmp1 + tmp2;
1077 result.m[2][1] = tmp1 - tmp2;
1078
1079 return result;
1080
1081 }
1082
1083
1084 template <::collection::count S = SIZE, std::enable_if_t<S == 4, int> = 0>
1085 static Matrix perspective(COORDINATE fov, COORDINATE near_, COORDINATE far_, COORDINATE aspect = 1.f)
1086 {
1087
1088 COORDINATE recip = 1 / (near_ - far_);
1089 COORDINATE c = 1 / ::tan(.5f * fov);
1090
1091 Matrix trafo = Matrix::scale(sequence_type<COORDINATE, SIZE>(c / aspect, c, (near_ + far_) * recip, 0.f));
1092
1093 trafo.m[3][2] = 2.f * near_ * far_ * recip;
1094 trafo.m[2][3] = -1.f;
1095
1096 return trafo;
1097 }
1098
1099 template <::collection::count S = SIZE, std::enable_if_t<S == 4, int> = 0>
1100 static Matrix ortho(COORDINATE left, COORDINATE right,
1101 COORDINATE bottom, COORDINATE top,
1102 COORDINATE near_, COORDINATE far_)
1103 {
1104
1105 COORDINATE rl = 1 / (right - left);
1106 COORDINATE tb = 1 / (top - bottom);
1107 COORDINATE fn = 1 / (far_ - near_);
1108
1109 Matrix result(0);
1110
1111 result.m[0][0] = 2 * rl;
1112 result.m[1][1] = 2 * tb;
1113 result.m[2][2] = -2 * fn;
1114 result.m[3][3] = 1;
1115 result.m[3][0] = -(right + left) * rl;
1116 result.m[3][1] = -(top + bottom) * tb;
1117 result.m[3][2] = -(far_ + near_) * fn;
1118
1119 return result;
1120 }
1121
1122 template <::collection::count S = SIZE, std::enable_if_t<S == 4, int> = 0>
1123 static Matrix look_at(const sequence_type<COORDINATE, 3>& origin,
1124 const sequence_type<COORDINATE, 3>& target,
1126 {
1127
1128 auto dir = normalize(target - origin);
1129 auto left = normalize(cross(dir, up));
1130 auto new_up = cross(left, dir);
1131 dir = -dir;
1132
1133 Matrix result(0);
1134 result.m[0][0] = left.a();
1135 result.m[0][1] = left.b();
1136 result.m[0][2] = left.c();
1137 result.m[1][0] = new_up.a();
1138 result.m[1][1] = new_up.b();
1139 result.m[1][2] = new_up.c();
1140 result.m[2][0] = dir.a();
1141 result.m[2][1] = dir.b();
1142 result.m[2][2] = dir.c();
1143 result.m[3][0] = -dot(left, origin);
1144 result.m[3][1] = -dot(new_up, origin);
1145 result.m[3][2] = -dot(dir, origin);
1146 result.m[3][3] = 1.f;
1147 return result;
1148 }
1149
1150 COORDINATE m[SIZE][SIZE];
1151};
1152
1153using Matrix2f = Matrix<float, 2>;
1154using Matrix3f = Matrix<float, 3>;
1155using Matrix4f = Matrix<float, 4>;
1156
1157
1159//inline Color::operator const ::color::color & () const {
1160// return reinterpret_cast<const ::color::color &>(*(this->m_coordinatea));
1161//}
1162
1163template < primitive_sequence SEQUENCE, typename COORDINATE_TRANSFORM >
1164auto transform(const SEQUENCE & sequence, COORDINATE_TRANSFORM coordinatetransform)
1165{
1166
1167 SEQUENCE sequenceResult(no_initialize_t{});
1168
1169 for (::collection::count i = 0; i < sequence.get_size(); ++i)
1170 {
1171
1172 sequenceResult.set_coordinate(i, coordinatetransform(sequence.coordinate(i)));
1173
1174 }
1175
1176 return sequenceResult;
1177
1178}
1179
1180
1181template < primitive_sequence SEQUENCE >
1182auto floor(const SEQUENCE & sequence)
1183{
1184
1185 return transform(sequence, [](auto a) {return floor(a); });
1186
1187}
1188
1189
1190template < primitive_sequence SEQUENCE >
1191auto ceil(const SEQUENCE & sequence)
1192{
1193
1194 return transform(sequence, [](auto a) {return ceil(a); });
1195
1196}
1197
1198
1199
Simple matrix class with column-major storage.
Definition sequence.h:993
Definition _tags.h:5
Definition _structures.h:11
Definition sequence.h:24