Yasiu Math 1
Collection of mathematic functions that help create game mechanics and procedural tools
Loading...
Searching...
No Matches
YasiuMathLib.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025 Grzegorz Krug.
3 * All Rights Reserved.
4 */
5
7
8#pragma once
9
10
11#include <vector>
12#include <cassert>
13#include <cmath>
14#include <stdexcept>
15// #include <numbers>
16// #include <iostream>
17// #include <math.h>
18// #include <ostream>
19#include <algorithm>
20#include <unordered_set>
21
22
23#include "Constants.h"
24
25
26#include "YasiuMathDataTypes.h"
27
28
29/* Fixes for 5.0~5.1 */
30#if __cplusplus >= 202002L
31#define CPP20_OR_LATER 1
32#else
33#define CPP20_OR_LATER 0
34#endif
35
36
37namespace YasiuMath {
38 template<typename T>
39 using Vec3 = YasiuMath::Types::Vec3<T>;
40 using Vec3f = YasiuMath::Types::Vec3<float>;
41 using Vec3d = YasiuMath::Types::Vec3<double>;
42
43
45 namespace Rotation {
46 template<typename T>
47 T Degrees2Radians( T degree )
48 {
49 return static_cast<T>(YasiuMath::Constants::Y_PI * degree / 180.f);
50 }
51
52 template<typename T>
53 T Radians2Degrees( T radian )
54 {
55 return static_cast<T>(radian * 180.f / YasiuMath::Constants::Y_PI);
56 }
57
72 template<typename T>
73 T NormalizeAngleToPeriod( T angle, T period = 360.f )
74 {
75 if ( period < 0 ) {
76 return angle;
77 }
78
79 T temp = static_cast<T>(fmod(angle, period));
80 if ( temp < 0 ) {
81 temp += period;
82 }
83 return temp;
84 }
85 }
86
87
91 namespace Trigonometry {
101 template<typename T>
102 std::vector<std::pair<T, T>> SpreadPointsOnTangentByAngleRadius( const T angle, const T radius, const T spreadDistance )
103 {
104 assert(radius > 0);
105 assert(spreadDistance > 0);
106
107 std::vector<std::pair<T, T>> result;
108
109 /* Beta = 90 - alfa */
110 T beta = static_cast<T>(YasiuMath::Constants::Y_PI / 2. - angle);
111
112 /*
113 * sin(B) = opposite / hypotenuse -> dy = sin * hypotenuse
114 * cos(B) = adjacent / hypotenuse -> dx = cos * hypotenuse
115 */
116
117 // T halfSpread = spreadDistance / 2;
118 T dy = sin(beta) * spreadDistance;
119 T dx = cos(beta) * spreadDistance;
120
121 T X = cos(angle) * radius;
122 T Y = sin(angle) * radius;
123
124
125 // Projected triangle aligns with axis different than +X +Y
126 // Axis for X is positive, for Y is Negative ( angle goes anti-clockwise )
127 // Starting from 0 = +X
128 result.push_back({X + dx, Y - dy});
129 // This is just negated vector
130 result.push_back({X - dx, Y + dy});
131
132 // std::tuple<float> test;
133 // test
134 // test.g
135
136 return result;
137 }
138
150 template<typename T>
151 std::vector<std::pair<T, T>> SpreadPointsOnTangentByXY( const T X, const T Y, const T spreadDistance )
152 {
153 T angle = atan2f(Y, X);
154 T radius = sqrtf((X * X) + (Y * Y));
155 return SpreadPointsOnTangentByAngleRadius(angle, radius, spreadDistance);
156 }
157
178 template<typename T>
179 T FindMinimalRadiusForIntersectingTangentsOnArc( const T alfa, const T beta, const T symmetricWidth )
180 {
181 /*
182 * sin (alfa) * A - sin(beta) * b
183 * R = ----------------------------------
184 * cos(beta) - cos(alfa)
185 */
186 T angleDiff = fmod(abs(alfa - beta), 360);
187 assert(symmetricWidth > 0);
188 assert(angleDiff > 0);
189 assert(angleDiff != 180); // Only place when they don't meet in infinite space
190
191 T nominator = symmetricWidth * (sin(alfa) + sin(beta));
192 T denominator = cos(beta) - cos(alfa);
193 T result = abs(nominator / denominator);
194
195 return result;
196 }
197
217 template<typename T>
219 const T alfa,
220 const T beta,
221 const T widthA,
222 const T widthB
223 )
224 {
225 std::pair<T, T> result;
226
227 T angleDiff = fmod(abs(alfa - beta), 360); /* Keep angle in 0-360 range */
228 assert(widthA > 0);
229 assert(widthB > 0);
230 assert(angleDiff > 0);
231 assert(angleDiff != 180);
232
233 /* X - formula case */
234 T nominator1 = sin(alfa) * widthA + sin(beta) * widthB;
235 T denominator1 = cos(alfa) - cos(beta);
236 T radius1 = abs(nominator1 / denominator1);
237
238 /* Y - formula case */
239 T nominator2 = -(cos(alfa) * widthA + cos(beta) * widthB);
240 T denominator2 = sin(alfa) - sin(beta);
241 T radius2 = abs(nominator2 / denominator2);
242
243 if ( widthA < widthB ) {
244 /* Pack longer radius to first */
245 if ( radius1 > radius2 ) {
246 result.first = radius1;
247 result.second = radius2;
248 }
249 else {
250 result.first = radius2;
251 result.second = radius1;
252 }
253 }
254 else {
255 /* Pack shorter radius to first */
256 if ( radius1 < radius2 ) {
257 result.first = radius1;
258 result.second = radius2;
259 }
260 else {
261 result.first = radius2;
262 result.second = radius1;
263 }
264 }
265 return result;
266 }
267 }
268
269
273 namespace ConvexHull {
274 /* @cond INTERNAL */
275 /* Helper function for convex hull */
276 template<typename T>
277 inline std::pair<T, T> CalculateVector(
278 const std::vector<std::pair<T, T>>& polygonPoints,
279 const int& ind1,
280 const int& ind2
281 )
282 {
283 // if ( convexStack.size() < 2 ) {
284 // return {static_cast<T>(0), static_cast<T>(0)};
285 // }
286
287 // const int ind1 = convexStack.at(convexStack.size() - 2);
288 // const int ind2 = convexStack.at(convexStack.size() - 1);
289 // std::cout << "Polygon array size: " << polygonPoints.size() << ", ind1: " << ind1 << ", ind2: " << ind2
290 // << std::endl;
291 T dX = polygonPoints.at(ind1).first - polygonPoints.at(ind2).first;
292 T dY = polygonPoints.at(ind1).second - polygonPoints.at(ind2).second;
293
294 // std::cout << "Last vector: " << dX << " " << dY << " ( " << ind1 << ", " << ind2 << " )" << std::endl;
295 return {dX, dY};
296 }
297
298 template<typename T>
299 T Cross( const std::pair<T, T>& A, const std::pair<T, T>& B )
300 {
301 auto temp1 = A.first * B.second; //- B.second * A.first;
302 auto temp2 = A.second * B.first;
303 return temp1 - temp2;
304 }
305
306 /* Function to check backwards if any previous points need to be removed */
307 template<typename T>
308 void CheckHullBackwards(
309 std::vector<int>& currentConvex,
310 const int& checkIndex,
311 const std::vector<std::pair<T, T>>& allPoints,
312 const bool clockWise = false
313 )
314 {
315 if ( currentConvex.size() < 2 ) { return; }
316
317 T cross;
318 if ( clockWise ) {
319 std::pair<T, T> vec1 = CalculateVector<T>(allPoints, currentConvex.at(currentConvex.size() - 1), checkIndex);
320 std::pair<T, T> vec2 = CalculateVector<T>(
321 allPoints,
322 currentConvex.at(currentConvex.size() - 2),
323 currentConvex.at(currentConvex.size() - 1)
324 );
325 cross = Cross<T>(vec1, vec2);
326 }
327 else {
328 std::pair<T, T> vec1 = CalculateVector<T>(
329 allPoints,
330 currentConvex.at(currentConvex.size() - 1),
331 currentConvex.at(currentConvex.size() - 2)
332 );
333 std::pair<T, T> vec2 = CalculateVector<T>(allPoints, checkIndex, currentConvex.at(currentConvex.size() - 1));
334 cross = Cross<T>(vec1, vec2);
335 }
336 // std::cout << "Checking point: " << checkIndex << ", cross: " << cross << std::endl;
337
338 if ( cross <= 0 ) {
339 /* Pop invalid, reassign new */
340 // std::cout << " - Removing previous point: " << currentConvex.at(currentConvex.size() - 1) << ", for: " << checkIndex << "\n";
341 currentConvex.pop_back();
342 // std::cout << " Last element now: " << currentConvex.at(currentConvex.size() - 1) << "\n";
343 CheckHullBackwards(currentConvex, checkIndex, allPoints, clockWise);
344 }
345 else {
346 // std::cout << " Checked pt: " << checkIndex << "\n";
347 }
348 return;
349 }
350
351
355 template<typename T>
356 void AddPointToConvex(
357 std::vector<int>& currentConvex,
358 const int& index,
359 const std::vector<std::pair<T, T>>& allPoints,
360 const bool clockWise = false
361 )
362 {
363 if ( currentConvex.size() <= 1 ) {
364 currentConvex.push_back(index);
365 return;
366 }
367
368 CheckHullBackwards(currentConvex, index, allPoints, clockWise);
369 currentConvex.push_back(index);
370 // std::cout << " +Hull point added: " << index << "\n";
371 };
372
373 /* @endcond */
374
381 template<typename T>
382 std::vector<int> ConvexHull2D( const std::vector<std::pair<T, T>>& polygonPoints )
383 {
384 using namespace Types;
385 if ( polygonPoints.size() == 0 ) {
386 return {};
387 }
388 else if ( polygonPoints.size() == 1 ) {
389 return {0};
390 }
391 else if ( polygonPoints.size() == 2 ) {
392 return {0, 1};
393 }
394
395 std::vector<IndexedPair<int, T>> sortedPoints; /* Points sorted in Y Axis */
396 sortedPoints.reserve(polygonPoints.size() + 1);
397 for ( int i = 0; i < static_cast<int>(polygonPoints.size()); i++ ) {
398 sortedPoints.emplace_back(IndexedPair<int, T>(i, polygonPoints.at(i).first, polygonPoints.at(i).second));
399 }
400
401 std::sort(
402 sortedPoints.begin(),
403 sortedPoints.end(),
404 [] ( const auto& a, const auto& b ) {
405 /* Ascending Y [y -> Y] */
406 return a.second < b.second;
407 }
408 );
409
410 IndexedPair<int, T> bottom = sortedPoints.at(0);
411 IndexedPair<int, T> top = sortedPoints.at(sortedPoints.size() - 1);
412 Point<T> startEndDiff = top - bottom;
413 T angleThreshold = startEndDiff.fastAngleModded();
414
415 std::vector<PointAngle<T>> pointsOnLeft;
416 std::vector<PointAngle<T>> pointsOnRight;
417
418 /* == Splitting points to left and right == */
419 for ( IndexedPair<int, T> point : sortedPoints ) {
420 // std::cout << "\t" << point.index << " : " << point.first << ", " << point.second << std::endl;
421 if ( point == bottom || point == top ) {
422 continue;
423 }
424
425 Point<T> temp = (point - bottom);
426 T angle = temp.fastAngleModded();
427 // std::cout << "Comparing angle(" << point.index << "): " << angle << " < " << angleThreshold << "\n";
428 if ( point.first == top.first && point.first == bottom.second ) {
429 /* Ignore */
430 }
431 else if ( angle > angleThreshold ) {
432 pointsOnLeft.emplace_back(point.index, angle);
433 }
434 else {
435 pointsOnRight.emplace_back(point.index, angle);
436 }
437 }
438 // std::cout << "\n";
439
440 std::sort(pointsOnLeft.begin(), pointsOnLeft.end(), std::greater<PointAngle<T>>());
441 std::sort(pointsOnRight.begin(), pointsOnRight.end());
442 // return {};
443
444 std::unordered_set<int> visitedPoints;
445 visitedPoints.reserve(polygonPoints.size());
446
447 /* GOING COUNTERCLOCKWISE FROM TOP */
448 std::vector<int> convexLeft;
449 std::vector<int> convexRight;
450 convexLeft.reserve(polygonPoints.size());
451 convexRight.reserve(polygonPoints.size());
452
453 /* Initial 2 points */
454 convexLeft.push_back(bottom.index);
455 visitedPoints.insert(bottom.index);
456 if ( pointsOnLeft.size() > 0 ) {
457 convexLeft.push_back(pointsOnLeft.at(0).index);
458 visitedPoints.insert(pointsOnLeft.at(0).index);
459 Point<T> pt = CalculateVector<T>(polygonPoints, pointsOnLeft.at(0).index, bottom.index);
460
461 // std::cout << "\nLeft Hull\n";
462 for ( const PointAngle<T>& nextPoint : pointsOnLeft ) {
463 if ( nextPoint.index == top.index ) {
464 // std::cout << "This is top index, stop loop: " << nextPoint.index << "\n";
465 break;
466 }
467#if CPP20_OR_LATER
468 if ( visitedPoints.contains(nextPoint.index) ) {
469 // std::cout << "Skipping visited point: " << nextPoint.index << "\n";
470 continue;
471 }
472#else
473 if ( visitedPoints.find(nextPoint.index) != visitedPoints.end() ) {
474 // std::cout << "Skipping visited point: " << nextPoint.index << "\n";
475 continue;
476 }
477#endif
478
479 // std::cout << nextPoint.index << "\n";
480
481 visitedPoints.insert(nextPoint.index);
482 AddPointToConvex<T>(convexLeft, nextPoint.index, polygonPoints, true);
483 }
484 }
485 AddPointToConvex<T>(convexLeft, top.index, polygonPoints, true);
486 // std::cout << "Convex L:\n";
487 // for ( auto pt : convexLeft ) {
488 // // std::cout << ", " << pt;
489 // }
490 // std::cout << std::endl;
491
492 visitedPoints.clear();
493 convexRight.push_back(bottom.index);
494 visitedPoints.insert(bottom.index);
495 if ( pointsOnRight.size() > 0 ) {
496 convexRight.push_back(pointsOnRight.at(0).index);
497 visitedPoints.insert(pointsOnRight.at(0).index);
498
499 /* GOING COUNTERCLOCKWISE FROM BOTTOM */
500 // std::cout << "\n\nPoints with angles right:\n";
501 // std::cout << "\nRight Hull\n";
502 for ( const PointAngle<T>& nextPoint : pointsOnRight ) {
503 if ( nextPoint.index == top.index ) {
504 // std::cout << "This is top index, stop loop: " << nextPoint.index << "\n";
505 break;
506 }
507 if ( visitedPoints.find(nextPoint.index) != visitedPoints.end() ) {
508 // std::cout << "Skipping visited point: " << nextPoint.index << "\n";
509 continue;
510 }
511
512 // std::cout << "= Next PT:" << nextPoint.index << "\n";
513 visitedPoints.insert(nextPoint.index);
514 AddPointToConvex<T>(convexRight, nextPoint.index, polygonPoints);
515 }
516 }
517 AddPointToConvex<T>(convexRight, top.index, polygonPoints);
518 // std::cout << "Convex R:\n";
519 // for ( auto pt : convexRight ) {
520 // std::cout << ", " << pt;
521 // }
522 // std::cout << std::endl;
523
524
525 /* RESULTS */
526 // std::cout << "\nPrinting points:\n";
527 // std::cout << "\n";
528
529 // std::cout << "Convex hull:\n";
530 // for ( int ind : convexRight ) {
531 // std::pair<T, T> point = polygonPoints.at(ind);
532 // std::cout << " == " << ind << "\t" << point.first << " _ " << point.second << "\n";
533 // }
534 // std::cout << "===\n";
535
536 // for ( int ind : convexLeft ) {
537 // auto point = polygonPoints.at(ind);
538 // std::cout << " == " << ind << "\t" << point.first << " _ " << point.second << "\n";
539 // }
540
541 // convexLeft.pop_back();
542 // convexRight.pop_back();
543
544 // for ( auto it = convexLeft.end() - 1; it != convexRight.begin(); --it ) {}
545 // for ( int point : convexLeft ) {
546 for ( auto it = convexLeft.end(); it != convexLeft.begin(); ) {
547 --it;
548 int point = *(it);
549 if ( point == top.index || point == bottom.index ) { continue; }
550 convexRight.push_back(point);
551 }
552
553 return convexRight;
554 };
555
556 // template<typename T>
557 // static std::vector<std::pair<T, T>> MinBoundingBoxFromHull( const std::vector<std::pair<T, T>>& convexPoints )
558 // {
559 // auto temp = std::vector<std::pair<T, T>>{};
560 // return temp;
561 // };
562 //
563 // template<typename T>
564 // static std::vector<std::pair<T, T>> MinBoundingBox( const std::vector<std::pair<T, T>>& polygonPoints )
565 // {
566 // const std::vector<int> indexes = ConvexHull<T>(polygonPoints);
567 // std::vector<std::pair<T, T>> hullPoints;
568 // hullPoints.reserve(indexes.size());
569 // for ( auto ind : indexes ) {
570 // hullPoints.push_back(polygonPoints.at(ind));
571 // }
572 // return MinBoundingBoxFromHull(hullPoints);
573 // };
574 }
575
576
578 namespace Ballistics {
585
586 template<typename T>
588 virtual ~ProjectileDynamicState() {};
589
591 Vec3<T> Position = 0;
592
594 Vec3<T> Velocity = 0;
595
597 Vec3<T> Acceleration = 0;
598
604
606 T MaxSpeed = 1000;
607
608
617 ProjectileDynamicState Predict( T QueryTime, T DeltaTime ) const
618 {
619 ProjectileDynamicState<T> TempState = *this;
620 TempState.AutoStep(QueryTime, DeltaTime);
621 return TempState;
622 }
623
635 {
636 /* Static because must return bool ( can not return Copied value )
637 * Formula:
638 * | V + At | = V_max
639 * V_max is scalar, max speed
640 * V - Velocity vec
641 * A - Acceleration/Thrust vec
642 * t - time
643 *
644 * 0 = t^2 * A^2 + 2t * VA + V^2 - V_max^2
645 * Now-> do components sum x+y+z
646 */
647 ProjectileDynamicState<T> ProjectileState = *this;
648
649 if ( ProjectileState.Acceleration.IsNearly0() ) {
650 ProjectileState.Position = ProjectileState.Position + ProjectileState.Velocity * QueryTime;
651 return ProjectileState;
652 }
653
654 const T Xa = ProjectileState.Acceleration.LengthSquared();
655 const T Xb = 2 * (ProjectileState.Velocity * ProjectileState.Acceleration).Sum();
656 const T Xc = ProjectileState.Velocity.LengthSquared() - ProjectileState.MaxSpeed * ProjectileState.MaxSpeed;
657
658 const T delta = Xb * Xb - 4 * Xa * Xc;
659 T TimeToMaxSpeed = -1;
660
661 if ( delta < 0 ) {
662 /* Technically should never occur
663 * Case(Accel=0) is computed before (Accel 0 can't fall into negative delta condition)
664 */
665 // throw std::runtime_error("Delta negative. Can't return false. Solution is not Valid at all.");
666 return {};
667 }
668 else if ( fabs(delta) <= YasiuMath::Constants::EPSILON ) {
669 /* 1 solution close to ~0 */
670 TimeToMaxSpeed = -Xb / (2 * Xa);
671 }
672 else {
673 /* 2 Solutions */
674 T x1 = (-Xb - std::sqrt(delta)) / (2 * Xa);
675 T x2 = (-Xb + std::sqrt(delta)) / (2 * Xa);
676
677 if ( x1 > 0 ) {
678 TimeToMaxSpeed = x1;
679 }
680 else if ( x2 > 0 ) {
681 TimeToMaxSpeed = x2;
682 }
683
684 if ( x1 > 0 && x2 > 0 && x1 < x2 ) {
685 /* Pick smaller X only when both are valid */
686 TimeToMaxSpeed = x1;
687 }
688 }
689
690 /*
691 * /\ Accel
692 * | / |
693 * | / |
694 * | / |
695 * | / X |
696 * ----------> Time
697 * X - Area is velocity -> Triangle formula
698 */
699
700 /* TimeMax<0 to catch error when limit is set 0, not to use <= to not use clamping */
701 if ( QueryTime < TimeToMaxSpeed || TimeToMaxSpeed < 0 ) {
702 /* Keep acceleration, Cap not reached */
703 ProjectileState.Position += ProjectileState.Velocity * QueryTime + ProjectileState.Acceleration * (0.5 *
704 QueryTime * QueryTime);
705 ProjectileState.Velocity += ProjectileState.Acceleration * QueryTime;
706 }
707 else {
708 /* Acceleration Phase */
709 ProjectileState.Position += ProjectileState.Velocity * TimeToMaxSpeed + ProjectileState.Acceleration * (0.5 *
710 TimeToMaxSpeed * TimeToMaxSpeed);
711 /* Account for velocity changes */
712 ProjectileState.Velocity += ProjectileState.Acceleration * TimeToMaxSpeed;
713
714 /* Normalize to Max */
715 ProjectileState.Velocity = ProjectileState.Velocity.NormalizeInPlace() * ProjectileState.MaxSpeed;
716
717 /* Max Speed reached */
718 float RestofTime = QueryTime - TimeToMaxSpeed;
719 if ( RestofTime > 0 ) {
720 /* Add rest travel time */
721 ProjectileState.Position += ProjectileState.Velocity * RestofTime;
722 }
723 }
724
725 return ProjectileState;
726 }
727
737 virtual void DiscreteStep( T deltaTime )
738 {
739 auto oldVel = Velocity;
740 /* Acceleration */
741 if ( !Acceleration.IsNearly0() ) {
742 Velocity += (Acceleration) * deltaTime;
743 }
744
745 /* Friction as last step to damp all forces */
746 if ( AirFrictionCoeff > 0 ) {
747 /* Using unclamped value for reduction */
748 const auto TrapezVelocity = (oldVel + Velocity) / 2;
749
750 /* Preserve sign! not loose it with square */
751 Vec3<T> drag = (TrapezVelocity * TrapezVelocity.Abs()) * AirFrictionCoeff * deltaTime;
752 if ( drag.Length() >= Velocity.Length() ) {
753 Velocity = 0;
754 }
755 else {
756 Velocity -= drag;
757 }
758 }
759
760 /* Speed limit */
761 const auto CurSpeed = Velocity.Length();
762 if ( MaxSpeed > 0 && CurSpeed > MaxSpeed ) {
763 Velocity = Velocity.NormalizeInPlace() * MaxSpeed;
764
765 /* Trapezoid approximation of position from acceleration */
766 Position += (oldVel + Velocity) * deltaTime * 0.5;
767 }
768 else {
769 /* Trapezoid approximation of position from acceleration */
770 Position += (oldVel + Velocity) * 0.5 * deltaTime;
771 }
772 };
773
774
787 void AutoStep( T QueryTime, T DeltaTime )
788 {
789 if ( AirFrictionCoeff == 0 ) {
790 const auto Result = PredictQuick(QueryTime);
791 *this = Result;
792 }
793 else {
794 const int N = QueryTime / DeltaTime;
795 for ( int i = 0; i < N; i++ ) {
796 DiscreteStep(DeltaTime);
797 }
798
799 const T missingTime = QueryTime - (DeltaTime * N);
800 if ( missingTime > 0 ) {
801 DiscreteStep(missingTime);
802 }
803 }
804 }
805 };
806
807
811 template<typename T>
814 Vec3f Position{0};
815
818
821
823 T MaxSpeed = 0;
824
827 };
828
829
839 template<typename T>
841 const Types::Vec3<T>& MissilePosition,
842 const Types::Vec3<T>& MissileVelocity,
843 const T BulletSpeed,
844 Types::Vec3<T>& InterceptLocation,
845 T& ImpactTime
846 );
847
856 template<typename T>
858 const Vec3<T>& TargetPosition,
859 const Vec3<T>& TargetVelocity,
860 const T BulletSpeed,
861 Vec3<T>& InterceptLocation
862 )
863 {
864 T TempTime;
865 return InterceptMissile_Linear(TargetPosition, TargetVelocity, BulletSpeed, InterceptLocation, TempTime);
866 }
867
884 template<typename T>
887 const InterceptorParams<T>& Interceptor,
888 const T MaxQueryTime,
889 const T StepTime,
890 Types::Vec3<T>& PredictedLocation
891 )
892 {
893 T TempTime = 0;
894 constexpr T val = 0;
895 return InterceptMissile_Dynamic(Target, Interceptor, MaxQueryTime, StepTime, val, PredictedLocation, TempTime);
896 };
897
898
917 template<typename T>
920 const InterceptorParams<T>& Interceptor,
921 const T MaxQueryTime,
922 const T StepTime,
923 Types::Vec3<T>& HitLocation,
924 T& HitTime
925 )
926 {
927 T TempTime = 0;
928 constexpr T val = 0;
929 return InterceptMissile_Dynamic(Target, Interceptor, MaxQueryTime, StepTime, val, HitLocation, HitTime);
930 };
931
948 template<typename T>
951 const InterceptorParams<T>& Interceptor,
952 const T MaxQueryTime,
953 const T StepTime,
954 const T AccurateStepTime,
955 Types::Vec3<T>& HitLocation
956 )
957 {
958 T TempTime = 0;
959 return InterceptMissile_Dynamic(Target, Interceptor, MaxQueryTime, StepTime, AccurateStepTime, HitLocation, TempTime);
960 };
961
963
984 template<typename T>
987 const InterceptorParams<T>& Interceptor,
988 const T MaxQueryTime,
989 const T StepTime,
990 const T AccurateStepTime,
991 Types::Vec3<T>& HitLocation,
992 T& HitTime
993 );
994 }
995
996
998 namespace Numeric {
1000 template<typename T>
1001 bool IsNearly0( T Value )
1002 {
1003 return std::fabs(Value) <= YasiuMath::Constants::EPSILON;
1004 }
1005 }
1006
1007
1009 namespace Algebra {
1021 template<typename T>
1022 T Remap( const T Value, const T InMin, const T InMax, T OutMin, T OutMax, const bool ClampOutput = false )
1023 {
1024 const T SubVal = Value - InMin;
1025 const T Divid = InMax - InMin;
1026
1027 if ( OutMax < OutMin ) {
1028 std::swap(OutMin, OutMax);
1029 }
1030
1031 if ( Numeric::IsNearly0(Divid) ) {
1032 /* What to return? Any result will not be accurate, but 0 division goes to max */
1033 return OutMax;
1034 }
1035
1036 const T Factor = SubVal / Divid;
1037
1038
1039 const T SubValOut = OutMax - OutMin;
1040 const T Output = (Factor * SubValOut) + OutMin;
1041 if ( ClampOutput ) {
1042 return std::clamp(Output, OutMin, OutMax);
1043 }
1044
1045 return Output;
1046 }
1047 }
1048};
1049
1050
1051#include "YasiuMathLib.inl"
Linear algebra problems.
Definition YasiuMathLib.h:1009
T Remap(const T Value, const T InMin, const T InMax, T OutMin, T OutMax, const bool ClampOutput=false)
Remaps Value between input range to output range with optional clamping.
Definition YasiuMathLib.h:1022
Linear and dynamic objects simulation / prediction.
Definition YasiuMathLib.h:578
bool InterceptMissile_Dynamic(ProjectileDynamicState< T > Target, const InterceptorParams< T > &Interceptor, const T MaxQueryTime, const T StepTime, Types::Vec3< T > &PredictedLocation)
Iterative state prediction. Returns first possible intercept location and time.
Definition YasiuMathLib.h:885
bool InterceptMissile_Linear(const Types::Vec3< T > &MissilePosition, const Types::Vec3< T > &MissileVelocity, const T BulletSpeed, Types::Vec3< T > &InterceptLocation, T &ImpactTime)
Linear movement with linear velocity, Fast: O(1).
constexpr double Y_PI
Famous PI value.
Definition Constants.h:14
constexpr double EPSILON
Value used for number stability check.
Definition Constants.h:17
Convex hull functions and helper functions.
Definition YasiuMathLib.h:273
std::vector< int > ConvexHull2D(const std::vector< std::pair< T, T > > &polygonPoints)
Find Convex Hull in 2D space from given points.
Definition YasiuMathLib.h:382
Generic functions.
Definition YasiuMathLib.h:998
bool IsNearly0(T Value)
Checks if value is nearly 0, YasiuMath::Constants::EPSILON.
Definition YasiuMathLib.h:1001
Manipulation of rotation or angles.
Definition YasiuMathLib.h:45
T NormalizeAngleToPeriod(T angle, T period=360.f)
Normalize angle to range <0, period>. Unit independent.
Definition YasiuMathLib.h:73
Trigonometry problems in 2D or 3D space.
Definition YasiuMathLib.h:91
std::vector< std::pair< T, T > > SpreadPointsOnTangentByAngleRadius(const T angle, const T radius, const T spreadDistance)
Definition YasiuMathLib.h:102
T FindMinimalRadiusForIntersectingTangentsOnArc(const T alfa, const T beta, const T symmetricWidth)
Finds radius of circle for both tangent line that intersect.
Definition YasiuMathLib.h:179
std::vector< std::pair< T, T > > SpreadPointsOnTangentByXY(const T X, const T Y, const T spreadDistance)
Spread points on tangent line to arc.
Definition YasiuMathLib.h:151
std::pair< T, T > FindMinimalRadiusForIntersectingTangentsOnArcAsymmetric(const T alfa, const T beta, const T widthA, const T widthB)
Finds radius of 2 circles for both tangent line that intersect. Tangents on circle are defined by ang...
Definition YasiuMathLib.h:218
Generic Types used in library.
Definition YasiuMathDataTypes.h:24
Categorized name spaces.
Definition Constants.h:10
Params used for ballistics predictions.
Definition YasiuMathLib.h:812
T InitialSpeed
Speed at which object starts moving.
Definition YasiuMathLib.h:817
T Acceleration
Acceleration in any direction.
Definition YasiuMathLib.h:820
T AirResistance
Keep in <0, 1> range!
Definition YasiuMathLib.h:826
T MaxSpeed
Max speed object can reach with acceleration, 0 or less is ignored.
Definition YasiuMathLib.h:823
Ballistic state. Can move in time with DiscreteStep function.
Definition YasiuMathLib.h:587
T MaxSpeed
Maximal speed(length) of velocity vector.
Definition YasiuMathLib.h:606
ProjectileDynamicState PredictQuick(T QueryTime) const
Quick prediction of ballistic state at time. Limitation: Only constant acceleration and no Air Drag....
Definition YasiuMathLib.h:634
Vec3< T > Acceleration
Acceleration or Deceleration or combined with Gravity Forces.
Definition YasiuMathLib.h:597
virtual void DiscreteStep(T deltaTime)
Discrete Step. Function used to modify state in time.
Definition YasiuMathLib.h:737
void AutoStep(T QueryTime, T DeltaTime)
Step function. O(1) for AirDrag=0.
Definition YasiuMathLib.h:787
Vec3< T > Position
Current position.
Definition YasiuMathLib.h:591
ProjectileDynamicState Predict(T QueryTime, T DeltaTime) const
Prediction.
Definition YasiuMathLib.h:617
T AirFrictionCoeff
Movement resistance opposite to current velocity vector. Must be in <0, 1> range. More in details....
Definition YasiuMathLib.h:603
Vec3< T > Velocity
Movement velocity vector.
Definition YasiuMathLib.h:594
Helper object, for point description in algorithm. Index and 2 values.
Definition YasiuMathDataTypes.h:69
T second
Definition YasiuMathDataTypes.h:75
U index
Definition YasiuMathDataTypes.h:71
T first
Definition YasiuMathDataTypes.h:73
Helper Struct. Point description with index and angle.
Definition YasiuMathDataTypes.h:105
Pair-like type, Helper for point description in ConvexHull algorithm.
Definition YasiuMathDataTypes.h:33
Structure reflecting vector of size 3, Templated Type.
Definition YasiuMathDataTypes.h:142
T Length() const
Default Pythagoras Length.
Definition YasiuMathDataTypes.h:292