Trax3 3.1.0
trax track library
Loading...
Searching...
No Matches
Vector.h
1// trax track library
2// AD 2013
3//
4// "I am the defector and you're the farmer's daughter"
5//
6// Bell X1
7//
8// Copyright (c) 2025 Trend Redaktions- und Verlagsgesellschaft mbH
9// Copyright (c) 2019 Marc-Michael Horstmann
10//
11// Permission is hereby granted to any person obtaining a copy of this software
12// and associated source code (the "Software"), to use, view, and study the
13// Software for personal or internal business purposes, subject to the following
14// conditions:
15//
16// 1. Redistribution, modification, sublicensing, or commercial use of the
17// Software is NOT permitted without prior written consent from the copyright
18// holder.
19//
20// 2. The Software is provided "AS IS", without warranty of any kind, express
21// or implied.
22//
23// 3. All copies of the Software must retain this license notice.
24//
25// For further information, please contact: horstmann.marc@trendverlag.de
26
27#pragma once
28
29#include "common/Helpers.h"
30
31#include <cassert>
32#include <cmath>
33#include <vector>
34
35
36namespace spat{
37
38 template<typename> struct Position;
39 template<typename> struct Position2D;
40 template<typename> struct Vector2D;
41
46 template<typename Valtype>
47 struct Vector
48 {
49 typedef Valtype value_type;
50
51 Valtype dx;
52 Valtype dy;
53 Valtype dz;
54
55
57 enum class specials{
58 null= -1,
59 ex = 0,
60 ey = 1,
61 ez = 2
62 };
63
64
73 constexpr Vector() noexcept = default;
74 constexpr Vector( Valtype dx, Valtype dy, Valtype dz ) noexcept;
75 explicit constexpr Vector( specials s ) noexcept;
76 explicit Vector( const Position<Valtype>& p ) = delete;
77 explicit constexpr Vector( const Vector2D<Valtype>& v2D ) noexcept;
78 template<typename Valtype2>
79 explicit Vector( const Valtype2* pVal ) noexcept;
81
82
87 template<typename Valtype2>
88 Vector& operator=( const Valtype2* pVal ) noexcept;
89
90 template<typename Valtype2>
91 Vector& operator=( const Vector2D<Valtype2>& vector ) noexcept;
93
94
95 //template<typename Valtype2>
96 //inline auto operator*( Valtype2 f ) const noexcept -> Vector<decltype(Valtype{}*Valtype2{})> {
97 // return { dx * f, dy * f, dz * f };
98 //}
99
100
104 const Valtype& operator[]( size_t index ) const;
105
106 Valtype& operator[]( size_t index );
108
109
111 Valtype* ptr() noexcept;
112
113
115 const Valtype* ptr() const noexcept;
116
117
120 Vector& Init( specials s = specials::ex ) noexcept;
121
122
125 constexpr bool Is( specials s ) const noexcept;
126
127
130 constexpr Valtype Length() const noexcept;
131
132
133 using AngleType = decltype(Valtype{}/Valtype{});
134
145 Vector& AircraftPrincipalAxes( AngleType yaw, AngleType pitch );
146
147 Vector& AircraftPrincipalAxes( const Position2D<AngleType>& angles );
148
149 Position2D<AngleType> AircraftPrincipalAxes( Valtype epsilon = std::numeric_limits<Valtype>::epsilon() ) const;
151
152
155 auto Normalize() noexcept -> decltype(Valtype{}/Valtype{});
156
157
159 constexpr inline bool IsNormal( Valtype epsilon_length = 2*std::numeric_limits<Valtype>::epsilon() ) const noexcept;
160
161
163 Vector& Rotate( const Vector<AngleType>& r, AngleType angle ) noexcept;
164
165
167 Vector& Rotate( const Vector<AngleType>& r ) noexcept;
168
169
173 template<typename Valtype2> constexpr
174 Vector<Valtype> ParallelProjection( const Vector<Valtype2>& normal ) const noexcept;
175
176
180 template<typename Valtype2> constexpr
181 Vector<Valtype> OrthogonalProjection( const Vector<Valtype2>& normal ) const noexcept;
182
183
193 constexpr bool Equals( const Vector& v, Valtype epsilon = Valtype{0} ) const noexcept;
194
195
197 Vector& Round( int toDigit ) noexcept;
198 };
199
202 template<typename Valtype>
203 constexpr Vector<Valtype> Null{Valtype{0},Valtype{0},Valtype{0}};
204
205 template<typename Valtype>
206 constexpr Vector<Valtype> Ex{Valtype{1},Valtype{0},Valtype{0}};
207
208 template<typename Valtype>
209 constexpr Vector<Valtype> Ey{Valtype{0},Valtype{1},Valtype{0}};
210
211 template<typename Valtype>
212 constexpr Vector<Valtype> Ez{Valtype{0},Valtype{0},Valtype{1}};
214
216 template<typename Valtype,typename Valtype2>
218
220 template<typename Valtype,typename Valtype2>
221 const Vector<Valtype>& spatial_cast( const Vector<Valtype2>& from ) noexcept;
222
223
227
229 template<typename Valtype> constexpr
230 Vector<Valtype> operator+( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept;
231 template<typename Valtype>
232 Vector<Valtype>& operator+=( Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept;
233 template<typename Valtype> constexpr
234 Vector<Valtype> operator+( const Vector<Valtype>& v ) noexcept;
235 template<typename Valtype> constexpr
236 Vector<Valtype> operator-( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept;
237 template<typename Valtype>
238 Vector<Valtype>& operator-=( Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept;
239 template<typename Valtype> constexpr
240 Vector<Valtype> operator-( const Vector<Valtype>& v ) noexcept;
241 template<typename Valtype,typename Valtype2> constexpr
242 auto operator*( const Vector<Valtype>& v1, const Vector<Valtype2>& v2 ) noexcept -> decltype(Valtype{}*Valtype2{});
243 template<typename Valtype> constexpr
244 auto operator*( Valtype f, const Vector<Valtype>& v ) noexcept -> Vector<decltype(Valtype{}*Valtype{})>;
245 template<typename Valtype> constexpr
246 auto operator*( const Vector<Valtype>& v, Valtype f ) noexcept -> Vector<decltype(Valtype{}*Valtype{})>;
247 template<typename Valtype,typename Valtype2> constexpr
248 auto operator*( Valtype f, const Vector<Valtype2>& v ) noexcept -> Vector<decltype(Valtype{}*Valtype2{})>;
249 template<typename Valtype,typename Valtype2> constexpr
250 auto operator*( const Vector<Valtype>& v, Valtype2 f ) noexcept -> Vector<decltype(Valtype{}*Valtype2{})>;
251 template<typename Valtype,typename Valtype2>
252 Vector<Valtype>& operator*=( Vector<Valtype>& v, Valtype2 f ) noexcept;
253 template<typename Valtype>
254 Vector<Valtype>& operator*=( Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept = delete;
255 template<typename Valtype,typename Valtype2> constexpr
256 auto operator%( const Vector<Valtype>& v1, const Vector<Valtype2>& v2 ) noexcept -> Vector<decltype(Valtype{}*Valtype2{})>;
257 template<typename Valtype>
258 Vector<Valtype>& operator%=( Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept;
259 template<typename Valtype,typename Valtype2> constexpr
260 auto operator/( const Vector<Valtype>&, const Vector<Valtype2>& ) = delete;
261 template<typename Valtype,typename Valtype2> constexpr
262 auto operator/( const Vector<Valtype>& v, Valtype2 f ) noexcept -> Vector<decltype(Valtype{}/Valtype2{})>;
263 template<typename Valtype,typename Valtype2> constexpr
264 auto operator/( const Valtype& f, const Vector<Valtype2>& v ) = delete;
265 template<typename Valtype,typename Valtype2>
266 Vector<Valtype>& operator/=( Vector<Valtype>& v, Valtype2 f ) noexcept;
267 template<typename Valtype> constexpr
268 bool operator==( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept;
269 template<typename Valtype> constexpr
270 bool operator!=( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept;
272
273
281 template<typename Valtype>
282 void Rotate( Vector<Valtype>* pVec, unsigned int nVec, const Vector<Valtype>& r ) noexcept;
283
284 template<typename Valtype>
285 void Rotate( std::vector<Vector<Valtype>>& vec, const Vector<Valtype>& r ) noexcept;
287
288
299 template<typename Valtype>
300 constexpr bool Equals( const Vector<Valtype>& v1, const Vector<Valtype>& v2, Valtype epsilon = Valtype{0} ) noexcept;
301
302
314 template<typename Valtype> constexpr
315 bool Parallel( const Vector<Valtype>& V1, const Vector<Valtype>& V2, decltype(Valtype{}/Valtype{}) epsilon = std::numeric_limits<decltype(Valtype{}/Valtype{})>::epsilon() ) noexcept;
316
317 template<typename Valtype> constexpr
318 bool OrthoParallel( const Vector<Valtype>& V1, const Vector<Valtype>& v2, decltype(Valtype{}/Valtype{}) epsilon = std::numeric_limits<decltype(Valtype{}/Valtype{})>::epsilon() ) noexcept;
319
320 template<typename Valtype> constexpr
321 bool AntiParallel( const Vector<Valtype>& V1, const Vector<Valtype>& V2, decltype(Valtype{}/Valtype{}) epsilon = std::numeric_limits<decltype(Valtype{}/Valtype{})>::epsilon() ) noexcept;
323
324
327 template<typename Valtype>
328 auto Normalize( const Vector<Valtype>& v ) noexcept -> std::pair<Valtype,Vector<decltype(Valtype{}/Valtype{})>>;
329
330
337 template<typename Valtype>
338 Vector<Valtype> Slerp( const Vector<Valtype>& a, const Vector<Valtype>& b, Valtype t ) noexcept;
339
340 template<typename Valtype>
341 Vector<Valtype> SlerpNormals( const Vector<Valtype>& na, const Vector<Valtype>& nb, Valtype t ) noexcept;
342
343 template<typename Valtype>
344 std::pair<Vector<Valtype>,Vector<Valtype>> SlerpDNormals( const Vector<Valtype>& na, const Vector<Valtype>& nb, Valtype t ) noexcept;
346
347
348 template<typename Valtype>
349 constexpr size_t size( const Vector<Valtype> ) noexcept {
350 return 3;
351 }
352
353
354template<typename Valtype>
355inline constexpr Vector<Valtype>::Vector( Valtype dx, Valtype dy, Valtype dz ) noexcept
356 : dx{dx}, dy{dy}, dz{dz}
357{}
358
359template<typename Valtype>
360inline constexpr Vector<Valtype>::Vector( specials s ) noexcept
361 : dx{s == specials::ex ? Valtype{1} : Valtype{0}},
362 dy{s == specials::ey ? Valtype{1} : Valtype{0}},
363 dz{s == specials::ez ? Valtype{1} : Valtype{0}}
364{}
365
366template<typename Valtype>
367inline constexpr Vector<Valtype>::Vector( const Vector2D<Valtype>& v2D ) noexcept
368 : dx{v2D.dx}, dy{v2D.dy}, dz{0}
369{}
370
371template<typename Valtype>
372template<typename Valtype2>
373inline Vector<Valtype>::Vector( const Valtype2* pVal ) noexcept
374 : dx{Valtype{static_cast<Valtype>(pVal[0])}},
375 dy{Valtype{static_cast<Valtype>(pVal[1])}},
376 dz{Valtype{static_cast<Valtype>(pVal[2])}}
377{}
378
379template<typename Valtype>
380template<typename Valtype2>
381inline Vector<Valtype>& Vector<Valtype>::operator=( const Valtype2* pVal ) noexcept{
382 dx = Valtype{pVal[0]};
383 dy = Valtype{pVal[1]};
384 dz = Valtype{pVal[2]};
385 return *this;
386}
387
388template<typename Valtype>
389template<typename Valtype2>
390inline Vector<Valtype>& Vector<Valtype>::operator=( const Vector2D<Valtype2>& vector ) noexcept{
391 dx = static_cast<Valtype>(vector.dx);
392 dy = static_cast<Valtype>(vector.dy);
393 return *this;
394}
395
396template<typename Valtype>
397inline const Valtype& Vector<Valtype>::operator[]( size_t index ) const{
398 if( index < 3 )
399 return (&dx)[index];
400
401 throw std::out_of_range( "invalid Vector subscript" );
402}
403
404template<typename Valtype>
405inline Valtype& Vector<Valtype>::operator[]( size_t index ){
406 if( index < 3 )
407 return (&dx)[index];
408
409 throw std::out_of_range( "invalid Vector subscript" );
410}
411
412template<typename Valtype>
413inline Valtype* Vector<Valtype>::ptr() noexcept{
414 return &dx;
415}
416
417template<typename Valtype>
418inline const Valtype* Vector<Valtype>::ptr() const noexcept{
419 return &dx;
420}
421
422template<typename Valtype>
424 dx = s == specials::ex ? Valtype{1} : Valtype{0};
425 dy = s == specials::ey ? Valtype{1} : Valtype{0};
426 dz = s == specials::ez ? Valtype{1} : Valtype{0};
427 return *this;
428}
429
430template<typename Valtype>
431constexpr bool Vector<Valtype>::Is( specials s ) const noexcept{
432 switch(s){
433 case specials::null:
434 return *this == Null<Valtype>;
435 case specials::ex:
436 return *this == Ex<Valtype>;
437 case specials::ey:
438 return *this == Ey<Valtype>;
439 case specials::ez:
440 return *this == Ez<Valtype>;
441 default:
442 assert( false );
443 }
444
445 return false;
446}
447
448template<typename Valtype> constexpr
449inline Valtype Vector<Valtype>::Length() const noexcept{
450 return sqrt( dx*dx + dy*dy + dz*dz );
451}
452
453template<typename Valtype>
454inline Vector<Valtype>& Vector<Valtype>::AircraftPrincipalAxes( AngleType yaw, AngleType pitch )
455{
456 *this = Length() * Ex<AngleType>;
457 Vector<AngleType> N = Ey<AngleType>;
458 N.Rotate( Ez<AngleType>, yaw );
459
460 return Rotate( Ez<AngleType>, yaw ).Rotate( N, pitch );
461}
462
463template<typename Valtype>
464inline Vector<Valtype>& Vector<Valtype>::AircraftPrincipalAxes( const Position2D<AngleType>& angles )
465{
466 return AircraftPrincipalAxes( angles.x, angles.y );
467}
468
469template<typename Valtype>
470inline Position2D<typename Vector<Valtype>::AngleType> Vector<Valtype>::AircraftPrincipalAxes( Valtype _epsilon ) const
471{
472 Valtype sqrtdxdxplusdydy = sqrt( dx*dx + dy*dy );
473 if( common::Equals( sqrtdxdxplusdydy, Valtype{0}, _epsilon ) ){
474 const Vector<Valtype>::AngleType pi__{3.141592654f};
475
476 return { Vector<Valtype>::AngleType{0},
477 -common::Sign( dz ) * pi__ / 2 };
478 }
479
480 return {
481 atan2( dy, dx ),
482 atan2( -dz, sqrtdxdxplusdydy )
483 };
484}
485
486template<typename Valtype>
487inline auto Vector<Valtype>::Normalize() noexcept -> decltype(Valtype{}/Valtype{}){
488 decltype(Valtype{}/Valtype{}) L = Length() / Valtype{1};
489 if( !L ){
490 Init();
491 return decltype(Valtype{}/Valtype{}){0};
492 }
493 *this /= L;
494 return L;
495}
496
497template<typename Valtype> constexpr
498inline bool Vector<Valtype>::IsNormal( Valtype _epsilon_length ) const noexcept{
499 return abs(Length() - Valtype{1}) <= _epsilon_length;
500}
501
502template<typename Valtype>
503Vector<Valtype>& Vector<Valtype>::Rotate( const Vector<AngleType>& r, AngleType angle ) noexcept{
504 if( angle == AngleType{ 0 } )
505 return *this;
506 Vector& v = *this;
507 const Vector rxv = r % v;
508
509 Valtype IrxvI = rxv.Length();
510 if( IrxvI == Valtype{0} )
511 return *this;
512
513 const Vector rvr = (r * v) * r;
514 const Vector vmrvr = v - rvr;
515
516 v = rvr + cos( angle ) * vmrvr + sin( angle ) * vmrvr.Length()/IrxvI * rxv;
517 return *this;
518}
519
520template<typename Valtype>
522 Vector<AngleType> nr{r};
523 AngleType angle = nr.Normalize();
524
525 Rotate( nr, angle );
526 return *this;
527}
528
529template<typename Valtype>
530template<typename Valtype2> constexpr
532 Valtype2 nl2 = normal * normal;
533 if( nl2 == Valtype2{0} )
534 return Null<Valtype>;
535
536 return (*this * normal) / nl2 * normal;
537}
538
539template<typename Valtype>
540template<typename Valtype2> constexpr
542 return *this - ParallelProjection( normal );
543}
544
545template<typename Valtype>
546constexpr bool Vector<Valtype>::Equals( const Vector<Valtype>& v, Valtype epsilon_ ) const noexcept{
547 const Vector<Valtype> d{*this - v};
548 return d*d <= epsilon_*epsilon_;
549}
550
551template<typename Valtype>
552inline Vector<Valtype>& Vector<Valtype>::Round( int toDigit ) noexcept{
553 dx = common::Round(dx,toDigit);
554 dy = common::Round(dy,toDigit);
555 dz = common::Round(dz,toDigit);
556 return *this;
557}
558
559template<typename Valtype,typename Valtype2>
561 static_assert( sizeof(Valtype) == sizeof(Valtype2), "Can not spatial_cast with different memory layout" );
562 return reinterpret_cast<Vector<Valtype>&>(from);
563}
564
565template<typename Valtype,typename Valtype2>
566inline const Vector<Valtype>& spatial_cast( const Vector<Valtype2>& from ) noexcept{
567 static_assert( sizeof(Valtype) == sizeof(Valtype2), "Can not spatial_cast with different memory layout" );
568 return reinterpret_cast<const Vector<Valtype>&>(from);
569}
570
571template<typename Valtype> constexpr
572inline Vector<Valtype> operator+( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept{
573 return { v1.dx + v2.dx,
574 v1.dy + v2.dy,
575 v1.dz + v2.dz };
576}
577
578template<typename Valtype>
580 v1.dx += v2.dx;
581 v1.dy += v2.dy;
582 v1.dz += v2.dz;
583 return v1;
584}
585
586template<typename Valtype> constexpr
587inline Vector<Valtype> operator+( const Vector<Valtype>& v ) noexcept{
588 return { +v.dx, +v.dy, +v.dz };
589}
590
591template<typename Valtype> constexpr
592inline Vector<Valtype> operator-( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept{
593 return { v1.dx - v2.dx,
594 v1.dy - v2.dy,
595 v1.dz - v2.dz };
596}
597
598template<typename Valtype>
600 v1.dx -= v2.dx;
601 v1.dy -= v2.dy;
602 v1.dz -= v2.dz;
603 return v1;
604}
605
606template<typename Valtype> constexpr
607inline Vector<Valtype> operator-( const Vector<Valtype>& v ) noexcept{
608 return { -v.dx, -v.dy, -v.dz };
609}
610
611template<typename Valtype,typename Valtype2> constexpr
612inline auto operator*( const Vector<Valtype>& v1, const Vector<Valtype2>& v2 ) noexcept -> decltype(Valtype{}*Valtype2{}){
613 return v1.dx*v2.dx + v1.dy*v2.dy + v1.dz*v2.dz;
614}
615
616template<typename Valtype> constexpr
617inline auto operator*( Valtype f, const Vector<Valtype>& v ) noexcept -> Vector<decltype(Valtype{}*Valtype{})>{
618 return { v.dx * f,
619 v.dy * f,
620 v.dz * f };
621}
622
623template<typename Valtype> constexpr
624inline auto operator*( const Vector<Valtype>& v, Valtype f ) noexcept -> Vector<decltype(Valtype{}*Valtype{})>{
625 return f * v;
626}
627
628template<typename Valtype,typename Valtype2> constexpr
629inline auto operator*( Valtype f, const Vector<Valtype2>& v ) noexcept -> Vector<decltype(Valtype{}*Valtype2{})>{
630 static_assert( !std::is_integral<Valtype2>::value, "Possible data loss on integral values, proper implementation provided for int only!" );
631 return { v.dx * f,
632 v.dy * f,
633 v.dz * f };
634}
635
636template<typename Valtype,typename Valtype2> constexpr
637inline auto operator*( const Vector<Valtype>& v, Valtype2 f ) noexcept -> Vector<decltype(Valtype{}*Valtype2{})>{
638 static_assert( !std::is_integral<Valtype>::value, "Possible data loss on integral values, proper implementation provided for int only!" );
639 return f * v;
640}
641
642template<typename Valtype> constexpr
643inline Vector<int> operator*( const Vector<int>& v, Valtype f ) noexcept {
644 return { static_cast<int>(static_cast<Valtype>(v.dx) * f),
645 static_cast<int>(static_cast<Valtype>(v.dy) * f),
646 static_cast<int>(static_cast<Valtype>(v.dz) * f) };
647}
648
649template<typename Valtype> constexpr
650inline Vector<int> operator*( Valtype f, const Vector<int>& v ) noexcept{
651 return v * f;
652}
653
654template<typename Valtype,typename Valtype2>
655inline Vector<Valtype>& operator*=( Vector<Valtype>& v, Valtype2 f ) noexcept{
656 static_assert( !std::is_integral<Valtype>::value, "Possible data loss on integral values, proper implementation provided for int only!" );
657 v.dx *= f;
658 v.dy *= f;
659 v.dz *= f;
660 return v;
661}
662
663template<typename Valtype>
664inline Vector<int>& operator*=( Vector<int>& v, Valtype f ) noexcept{
665 v.dx = static_cast<int>(static_cast<Valtype>(v.dx) * f);
666 v.dy = static_cast<int>(static_cast<Valtype>(v.dy) * f);
667 v.dz = static_cast<int>(static_cast<Valtype>(v.dz) * f);
668 return v;
669}
670
671template<typename Valtype,typename Valtype2> constexpr
672inline auto operator%( const Vector<Valtype>& v1, const Vector<Valtype2>& v2 ) noexcept -> Vector<decltype(Valtype{}*Valtype2{})>{
673 return { v1.dy * v2.dz - v1.dz * v2.dy,
674 v1.dz * v2.dx - v1.dx * v2.dz,
675 v1.dx * v2.dy - v1.dy * v2.dx };
676}
677
678template<typename Valtype>
680 v1 = v1 % v2;
681 return v1;
682}
683
684template<typename Valtype,typename Valtype2> constexpr
685inline auto operator/( const Vector<Valtype>& v, Valtype2 f ) noexcept -> Vector<decltype(Valtype{}/Valtype2{})>{
686 static_assert( !std::is_integral<Valtype>::value, "Possible data loss on integral values, proper implementation provided for int only!" );
687 return { v.dx / f,
688 v.dy / f,
689 v.dz / f };
690}
691
692template<typename Valtype> constexpr
693inline Vector<int> operator/( const Vector<int>& v, Valtype f ) noexcept{
694 return { static_cast<int>(static_cast<Valtype>(v.dx) / f),
695 static_cast<int>(static_cast<Valtype>(v.dy) / f),
696 static_cast<int>(static_cast<Valtype>(v.dz) / f) };
697}
698
699template<typename Valtype,typename Valtype2>
700inline Vector<Valtype>& operator/=( Vector<Valtype>& v, Valtype2 f ) noexcept{
701 static_assert( !std::is_integral<Valtype>::value, "Possible data loss on integral values, proper implementation provided for int only!" );
702 v.dx /= f;
703 v.dy /= f;
704 v.dz /= f;
705 return v;
706}
707
708template<typename Valtype>
709inline Vector<int>& operator/=( Vector<int>& v, Valtype f ) noexcept{
710 v.dx = static_cast<int>(static_cast<Valtype>(v.dx) / f);
711 v.dy = static_cast<int>(static_cast<Valtype>(v.dy) / f);
712 v.dz = static_cast<int>(static_cast<Valtype>(v.dz) / f);
713 return v;
714}
715
716template<typename Valtype> constexpr
717inline bool operator==( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept{
718 return v1.dx == v2.dx && v1.dy == v2.dy && v1.dz == v2.dz;
719}
720
721template<typename Valtype> constexpr
722inline bool operator!=( const Vector<Valtype>& v1, const Vector<Valtype>& v2 ) noexcept{
723 return !(v1 == v2);
724}
725
726template<typename Valtype>
727void Rotate( Vector<Valtype>* pVec, unsigned int nVec, const Vector<Valtype>& rot ) noexcept{
728 Vector<Valtype> r{rot};
729 Valtype angle = r.Normalize();
730
731 for( size_t idx = 0; idx < nVec; ++idx )
732 pVec[idx].Rotate( r, angle );
733}
734
735template<typename Valtype>
736void Rotate( std::vector<Vector<Valtype>>& vec, const Vector<Valtype>& r ) noexcept{
737 Vector<Valtype> nr{r};
738 Valtype angle = nr.Normalize();
739
740 for( auto iter = vec.begin(); iter != vec.end(); ++iter )
741 (*iter).Rotate( nr, angle );
742}
743
744template<typename Valtype>
745inline constexpr bool Equals(const Vector<Valtype>& v1,const Vector<Valtype>& v2,Valtype epsilon) noexcept{
746 return v1.Equals( v2, epsilon );
747}
748
749template<typename Valtype> constexpr
750inline bool Parallel( const Vector<Valtype>& V1, const Vector<Valtype>& V2, decltype(Valtype{}/Valtype{}) epsilon ) noexcept{
751 Valtype v1 = V1.Length();
752 Valtype v2 = V2.Length();
753 if( v1 == Valtype{0} || v2 == Valtype{0} )
754 return true;
755
756 if( (V1 % V2).Length() / v1 / v2 > epsilon )
757 return false;
758
759 return true;
760}
761
762template<typename Valtype> constexpr
763inline bool OrthoParallel( const Vector<Valtype>& V1, const Vector<Valtype>& V2, decltype(Valtype{}/Valtype{}) epsilon ) noexcept{
764 if( !Parallel( V1, V2, epsilon ) )
765 return false;
766
767 return V1 * V2 >= decltype(Valtype{}*Valtype{}){0};
768}
769
770template<typename Valtype> constexpr
771inline bool AntiParallel( const Vector<Valtype>& V1, const Vector<Valtype>& V2, decltype(Valtype{}/Valtype{}) epsilon ) noexcept{
772 if( !Parallel( V1, V2, epsilon ) )
773 return false;
774
775 return V1 * V2 < decltype(Valtype{}*Valtype{}){0};
776}
777
778template<typename Valtype>
779auto Normalize( const Vector<Valtype>& v ) noexcept -> std::pair<Valtype,Vector<decltype(Valtype{}/Valtype{})>> {
780 Vector<decltype(Valtype{}/Valtype{})> V{ v.dx / Valtype{1},
781 v.dy / Valtype{1},
782 v.dz / Valtype{1} };
783 Valtype L = V.Normalize() * Valtype{1};
784 return std::make_pair( L, V );
785}
786
787template<typename Valtype>
788inline Vector<Valtype> Slerp( const Vector<Valtype>& a_, const Vector<Valtype>& b_, Valtype t ) noexcept
789{
790 t = common::Clamp( t, Valtype{0}, Valtype{1} );
791 Vector<Valtype> na = a_;
792 const Valtype a = na.Normalize();
793 Vector<Valtype> nb = b_;
794 const Valtype b = nb.Normalize();
795
796 Vector<Valtype> r = na % nb;
797 const Valtype angle = t*asin( r.Normalize() );
798
799 return ((1-t)*a + t*b) * (cos(angle) * na + sin(angle) * (r % na));
800}
801
802template<typename Valtype>
803inline Vector<Valtype> SlerpNormals( const Vector<Valtype>& na, const Vector<Valtype>& nb, Valtype t ) noexcept
804{
805 t = common::Clamp( t, Valtype{0}, Valtype{1} );
806
807 Vector<Valtype> r = na % nb;
808 const Valtype angle = t*asin( r.Normalize() );
809
810 return cos(angle) * na + sin(angle) * (r % na);
811}
812
813template<typename Valtype>
814inline std::pair<Vector<Valtype>,Vector<Valtype>> SlerpDNormals(
815 const Vector<Valtype>& na,
816 const Vector<Valtype>& nb,
817 Valtype t ) noexcept
818{
819 t = common::Clamp( t, Valtype{0}, Valtype{1} );
820
821 Vector<Valtype> r = na % nb;
822 const Valtype angle = asin( r.Normalize() );
823
824 return { cos(t*angle) * na + sin(t*angle) * (r % na), angle*(-sin(t*angle) * na + cos(t*angle) * (r % na)) };
825}
826
827} // namespace spat
constexpr auto Sign(T val) noexcept -> decltype(T{}/T{})
Definition Helpers.h:72
T Round(T value, int toDigit) noexcept
Rounding of floating point number to a certain digit aftzer the point.
Definition Helpers.h:140
constexpr const T & Clamp(const T &v, const T &lo, const T &hi) noexcept
Clips a val to a specified range.
Definition Helpers.h:105
constexpr bool Equals(T a, T b, T epsilon) noexcept
Tests equality in the sense |a-b| < epsilon.
Definition Helpers.h:66
constexpr Value< Dimension< L/2, M/2, T/2 > > sqrt(Value< Dimension< L, M, T > > a) noexcept
Dimensionated Values math function.
Definition DimensionedValues.h:670
constexpr Value< Dimension< 0, 0, 0 > > asin(Value< Dimension< 0, 0, 0 > > a) noexcept
Dimensionated Values math function.
Definition DimensionedValues.h:706
constexpr Value< Dimension< 0, 0, 0 > > cos(Value< Dimension< 0, 0, 0 > > a) noexcept
Dimensionated Values math function.
Definition DimensionedValues.h:698
constexpr Value< Dimension< 0, 0, 0 > > atan2(Value< Dimension< L, M, T > > y, Value< Dimension< L, M, T > > x) noexcept
Dimensionated Values math function.
Definition DimensionedValues.h:719
Value< Dimension< 1, 0, 0 > > Length
Length.
Definition DimensionedValues.h:324
constexpr Value< Dimension< 0, 0, 0 > > sin(Value< Dimension< 0, 0, 0 > > a) noexcept
Dimensionated Values math function.
Definition DimensionedValues.h:694
constexpr Real epsilon
Marginal difference in calculations.
Definition DimensionedValues.h:344
The namespace provides classes and methods for spatial computations.
Definition Box.h:32
Position< Valtype2 > operator*(const Frame< Valtype1, ValtypeT1 > &frame, const Position< Valtype2 > &p) noexcept
Frame operator.
Definition Frame.h:1089
Position< Valtype > & operator%=(const Position< Valtype > &, const Position< Valtype > &)=delete
Position operator.
Position< Valtype > & operator+=(Position< Valtype > &, const Position< Valtype > &)=delete
Position operator.
constexpr Position< Valtype > operator%(const Position< Valtype > &, const Position< Valtype > &)=delete
Position operator.
Position< Valtype > & operator-=(Position< Valtype > &, const Position< Valtype > &)=delete
Position operator.
auto Normalize(const Frame< Valtype, ValtypeT > &f) noexcept -> std::pair< Vector< ValtypeT >, Frame< Valtype, decltype(ValtypeT{}/ValtypeT{})> >
Outer normalizing.
Definition Frame.h:1144
constexpr bool Equals(const Vector< Valtype > &v1, const Vector< Valtype > &v2, Valtype epsilon=Valtype{0}) noexcept
Comparison within some range.
Definition Vector.h:745
bool Slerp(Transformation< Valtype > &out, const Transformation< Valtype > &inA, const Transformation< Valtype > &inB, Valtype t)
Spherical interpolates two matrices weighting them by t.
Definition Matrix.h:1722
Frame< Valtype2, ValtypeT2 > & operator*=(Frame< Valtype1, ValtypeT1 > &frame, const Frame< Valtype2, ValtypeT2 > &f) noexcept
right side multiplication of f to frame.
Definition Frame.h:1131
Frame< Valtype, ValtypeT > & spatial_cast(Frame< Valtype2, ValtypeT2 > &from) noexcept
Cast to Frame with different underlying value types.
Definition Frame.h:1062
constexpr Valtype operator/(const Position< Valtype > &, const Position< Valtype > &)=delete
Position operator.
Implements a 2D - position in cartesian coordinates.
Definition Position2D.h:45
Implements a 3D - position in cartesian coordinates.
Definition Position.h:46
Implements a 2D - vector in cartesian coordinates.
Definition Vector2D.h:46
Implements a 3D - vector in cartesian coordinates.
Definition Vector.h:48
constexpr bool Is(specials s) const noexcept
constexpr Vector< One > OrthogonalProjection(const Vector< Valtype2 > &normal) const noexcept
One * ptr() noexcept
Vector & Init(specials s=specials::ex) noexcept
constexpr One Length() const noexcept
constexpr bool Equals(const Vector &v, One epsilon=One{0}) const noexcept
Vector & Round(int toDigit) noexcept
Rounds the vectors values to a certain digit after the point.
Definition Vector.h:552
Vector & Rotate(const Vector< AngleType > &r, AngleType angle) noexcept
specials
Identifiers for special vectors.
Definition Vector.h:57
@ ez
Unit vector in z-direction.
Definition Vector.h:61
@ null
Vector with all parameters zeroed.
Definition Vector.h:58
@ ex
Unit vector in x-direction.
Definition Vector.h:59
@ ey
Unit vector in y-direction.
Definition Vector.h:60
One dy
Definition Vector.h:52
One dx
Definition Vector.h:51
constexpr Vector< One > ParallelProjection(const Vector< Valtype2 > &normal) const noexcept
constexpr bool IsNormal(Valtype epsilon_length=2 *std::numeric_limits< Valtype >::epsilon()) const noexcept
Definition Vector.h:498
One dz
Definition Vector.h:53
constexpr Vector() noexcept=default
Does not initialize the members.
auto Normalize() noexcept -> decltype(Valtype{}/Valtype{})
Normalizes the vector to length 1.
Definition Vector.h:487