Trax3 3.1.0
trax track library
Loading...
Searching...
No Matches
Curve_Imp.h
1// trax track library
2// AD 2013
3//
4// "where is my mind"
5//
6// Pixies
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 "Curve.h"
30#include "UnitsHelper.h"
31#include "Numerics.h"
32
33#include "common/NarrowCast.h"
34#include "dim/support/DimSupportStream.h"
35#include "spat/Matrix.h"
36
37#include <cmath>
38#include <iostream>
39
40namespace trax{
41
42 using namespace common;
43 using namespace spat;
44
45
77 template<class Function, class Base>
78 class Curve_Imp : public Base{
79 protected:
80 Function f;
81 public:
82 using DataType = typename Base::Data;
83
84 Curve_Imp() = default;
85 Curve_Imp( Real length ) noexcept
86 : f{ length }
87 {}
88
89 // Curve:
90 bool IsValid() const noexcept override{
91 return f.IsValid() && L >= 0_m;
92 }
93
94 AnglePerLength Curvature( Length s ) const override{
95 const Real ts = t(s);
96 const Vector<Length> D1 = f.D1( ts );
97 const Vector<Length> D2 = f.D2( ts );
98 const auto D1D1 = D1*D1;
99
100 return sqrt(k2(D1,D2,D1D1));
101 }
102
103 AnglePerLength Torsion( Length s ) const override
104 // Bronstein 1991 4.3.2.2.
105 {
106 const Real ts = t(s);
107 Vector<Length> D1 = f.D1( ts );
108 Vector<Length> D2 = f.D2( ts );
109 Vector<Length> D3 = f.D3( ts );
110
111 const auto D1D1 = D1*D1;
112 const auto k2_ = k2(D1,D2,D1D1);
113 if( k2_.Units() ){
115 m(0,0) = D1.dx;
116 m(1,0) = D1.dy;
117 m(2,0) = D1.dz;
118
119 m(0,1) = D2.dx;
120 m(1,1) = D2.dy;
121 m(2,1) = D2.dz;
122
123 m(0,2) = D3.dx;
124 m(1,2) = D3.dy;
125 m(2,2) = D3.dz;
126
127 return Determinant( m ) / (k2_ * pow<3>(D1D1)); //Why is that?
128 }
129
130 return 0_1Im;
131 }
132
133 void Transition( Length s, Position<Length>& pos ) const override{
134 pos = f( t(s) );
135 }
136
137 void Transition( Length s, Vector<One>& tan ) const override{
138 tan = f.D1( t(s) ) / Length{1};
139 if( tan == Null<One> )
140 tan = f.D2( t(s) ) / Length{1};
141
142 tan.Normalize();
143 }
144
145 void Transition( Length s, VectorBundle<Length,One>& bundle ) const override{
146 const Real ts = t(s);
147
148 bundle.P = f.P( ts );
149 bundle.T = f.D1( ts ) / Length{1};
150 if( bundle.T == Null<One> )
151 bundle.T = f.D2( t(s) ) / Length{1};
152
153 bundle.T.Normalize();
154 }
155
156 void Transition( Length s, VectorBundle2<Length,One>& bundle ) const override{
157 Real ts = t(s);
158 Vector<One> D1{ f.D1(ts) / Length{1} }, D2{ f.D2(ts) / Length{1} };
159
160 bundle.P = f.P( ts );
161 if( D1 == Null<One> )
162 // If D1 is zero, T = D1/|D1| is undefined, but we can define T then to be
163 // the direction of D2, since this is the direction D1 will have in the
164 // following point.
165 {
166 bundle.T = f.D2( t(s) ) / Length{1};
167 if( ts == 1.f )
168 // since there is no following point, we have
169 //to take the direction at the previous one.
170 bundle.T *= -1;
171
172 bundle.T.Normalize();
173 bundle.N = Null<One>; // trigger calculations below...
174 }
175 else{
176 bundle.T = D1;
177 bundle.T.Normalize();
178 bundle.N = D2 - (D1*D2)/(D1*D1) * D1;
179 }
180
181 if( bundle.N.Length() < (1.0f + D2.Length()) * 10 * epsilon )
182 // If N is quite small we try to derive it from a
183 // neighbouring point. If this doesn't work, use Up.
184 {
185 ts += (ts >= 100*epsilon ? -100*epsilon : +100*epsilon);
186 D1 = f.D1(ts) / Length{1};
187 D2 = f.D2(ts) / Length{1};
188
189 if( D1 == Null<One> )
190 bundle.N = D2;
191 else
192 bundle.N = D2 - (D1*D2)/(D1*D1) * D1;
193
194 if( bundle.N.Length() < (1.0f + D2.Length()) * 10 * epsilon )
195 bundle.N = Up % bundle.T;
196 }
197
198 bundle.N = bundle.N - (bundle.N * bundle.T) * bundle.T;
199 bundle.N.Normalize();
200 assert( abs(bundle.T * bundle.N) < 10 * epsilon );
201 }
202
203 void Transition( Length s, Frame<Length,One>& frame ) const override{
204 Transition( s, reinterpret_cast<VectorBundle2<Length,One>&>(frame) );
205 frame.B = frame.T % frame.N;
206 }
207
208 std::vector<Length> ZeroSet() const override{
209 if( !IsValid() )
210 throw std::runtime_error( "This curve has to be created prior to receiving the zero set." );
211
212 std::vector<Length> retval;
214 Transition( 0_m, b2 );
216 Length s1{0}, s2{0};
217 do{
218 s1 = s2;
219 if( (s2 += ds) > L )
220 s2 = L;
221
222 b1 = b2;
223 Transition( s2, b2 );
224 if( b1.N * b2.N < -0.9 && !(b1.T * b2.T < -0.9) )
225 retval.push_back( CloseInOnCurvatureZero( s1, b1.N, s2, b2.N ) );
226 }
227 while( s2 < L );
228
229 return retval;
230 }
231
232 common::Interval<Length> Range() const override{
233 if( !IsValid() )
234 throw std::runtime_error( "This curve has to be created prior to receiving its maximum range." );
235
236 return {0_m,L};
237 }
238
239 spat::Frame<Length,One> GetCurveLocalTransformation() const override{
241 Transition( 0_m, retval );
242 return retval;
243 }
244
245 bool Mirror( const spat::VectorBundle<Length,One>& mirrorPlane ) noexcept(noexcept(f.Mirror(mirrorPlane))) override{
246 if( !f.IsValid() )
247 return false;
248
249 return f.Mirror( mirrorPlane );
250 }
251
252 bool Equals( const Curve& toCurve, common::Interval<Length> range, Length epsilon_length, Angle epsilon_angle ) const noexcept override{
253 if( this == &toCurve )
254 return true;
255
256 if( auto pToCurve = dynamic_cast<const Base*>(&toCurve) )
257 return trax::Equals( GetData(), pToCurve->GetData(), range, epsilon_length, epsilon_angle );
258
259 return false;
260 }
261
262 common::Interval<Length> Create( const DataType& data ) override{
263 f.Create(data);
264 return f.IsValid() ? Sample() : common::Interval<Length>{0_m,0_m};
265 }
266
267 const DataType& GetData() const noexcept override{
268 return f.GetData();
269 }
270
271 protected:
272
278 Length SampleStep() const noexcept{
279 return ds;
280 }
281
307 assert( f.IsValid() );
308 assert( ds > 0_m );
309 assert( dtMax > One{0} );
310
311 m_Samples.clear();
312 m_Samples.reserve( static_cast<std::size_t>(std::ceil(10_m/ds)) + 1 );
313 One t = 0;
314 Length s{0};
315 int i = 1;
316
317 m_Samples.push_back( 0 );
318 while( t < One{1} ){
319 const auto d1 = f.D1(t);
320 const auto d2 = f.D2(t);
321 const Length D1 = d1.Length();
322 const Length D2 = d2.Length();
323
324 One dt = D2 > (2*dL/dtMax) ? 2*dL/D2 : dtMax;
325 if( dt < dtMin )
326 dt = dtMin;
327
328 t += dt;
329 if( t > One{1} ){
330 dt -= t - One{1};
331 t = One{1};
332 }
333 s += D1*dt;
334
335 while( s >= i*ds )
336 //sample
337 {
338 m_Samples.push_back( t - (s - i*ds) / D1 );
339 ++i;
340 }
341 }
342 m_Samples.push_back( One{1} );
343 m_Samples.shrink_to_fit();
344
345 dsLast = s - (i-1)*ds + epsilon__length;
346 L = s;
347 return {0_m,L};
348 }
349
351 One t( Length s ) const noexcept{
352 if( s <= 0_m ) return 0;
353 if( L <= s ) return 1;
354
355 Real integer;
356 Real fraction = std::modf( s / ds, &integer );
357 const std::size_t i = static_cast<std::size_t>(integer);
358
359 if( i+1 == m_Samples.size()-1 )// the last sample does correspond not to ds but to dsLast
360 fraction = fraction * ds / dsLast;
361
362 return (1.f - fraction) * m_Samples[i] + fraction * m_Samples[i+1];
363 }
364
366 Length s( One t ) const noexcept{
367 if( t <= 0 ) return 0_m;
368 if( t >= 1 ) return L;
369
370 common::Interval<int> r{ -1, narrow_cast<int>(m_Samples.size()) };
371 while( r.Length() > 1 ){
372 const int middle = r.Center();
373 t >= m_Samples[middle] ? r.Near( middle ) : r.Far( middle );
374 }
375
376 return r.Near() * ds + (t - m_Samples[r.Near()]) / (m_Samples[r.Far()] - m_Samples[r.Near()]) * (r.Near() == narrow_cast<int>(m_Samples.size())-2 ? dsLast : ds);
377 }
378
379 bool CheckSamples() const noexcept{
380 bool retval = true;
381 for( std::size_t i = 1; i < m_Samples.size(); ++i )
382 if( m_Samples[i] <= m_Samples[i-1] ){
383 std::cerr << "Samples are not monotonically increasing! At s=" << ds * i << std::endl;
384 retval = false;
385 }
386 return retval;
387 }
388 private:
389 Length L{-1}; // total length of curve
390 const Length dL = epsilon__length; // maximum error in total curve length
391 const Length ds = 100 * epsilon__length;// sample step
392 const One dtMax = 1.0f/100; // max integrator step
393 const One dtMin = 1.0f/10000; // min integrator step
394 std::vector<One> m_Samples; // samples of t(i*ds)
395 Length dsLast{0}; // length of the last sample. L = n*ds + dsLast with n = m_Samples.size() - 2
396
397
398 Length CloseInOnCurvatureZero( Length s1, const Vector<One>& N1, Length s2, const Vector<One>& N2 ) const{
399 Length s = (s1+s2)/2;
400 if( common::Equals( s1, s2, epsilon__length ) )
401 return s;
402
403 VectorBundle2<Length,One> bundle;
404 Transition( s, bundle );
405
406 if( N1 * bundle.N < 0 )
407 return CloseInOnCurvatureZero( s1, N1, s, bundle.N );
408 else if( bundle.N * N2 < 0 )
409 return CloseInOnCurvatureZero( s, bundle.N, s2, N2 );
410
411 return s;
412 }
413
414 inline Value<Dimension<-2,0,0>> k2( const Vector<Length>& D1, const Vector<Length>& D2, Area D1D1 ) const{
415 if( D1D1 == 0_m2 ) return Value<Dimension<-2,0,0>>{0};
416 const Value<Dimension<-2,0,0>> k2{ std::max( (D2*D2 - (pow<2>(D1*D2)/D1D1))/D1D1/D1D1, 0_1Im2 ) };
417 return k2;
418 }
419 };
420
421
429 template<class Function, class Base>
430 class CurveTInterpolator_Imp : public Curve_Imp<Function,Base>{
431 public:
432 AnglePerLength Curvature( Length s ) const override{
433 return DTds( s ).Length();
434 }
435
436 AnglePerLength Torsion( Length s ) const override{
437 Vector<One> T;
438 Transition( s, T );
439 return -DBds( s ) * N( T, DTds( s ) );
440 }
441
442 using Curve_Imp<Function,Base>::Transition;
443
444 void Transition( Length s, VectorBundle2<Length,One>& bundle ) const override{
445 Transition( s, bundle.P );
446 Transition( s, bundle.T );
447 bundle.N = N( bundle.T, DTds( s ) );
448 }
449
450 using Curve_Imp<Function,Base>::Range;
451 using Curve_Imp<Function,Base>::GetData;
452 protected:
453 using Curve_Imp<Function,Base>::f;
454 private:
455 static inline const Length h4 = 0.15_m; // can not evaluate for s out of range; 4h ~ 1.8_m see finite_difference_derivative8
456
457 Vector<AnglePerLength> DTds( Length s ) const{
458 const auto T = [this]( Length s ) -> Vector<One>{
459 Vector<One> T;
460 Transition( s, T );
461 return T;
462 };
463
464 return finite_difference_derivative6<Vector<AnglePerLength>>( T, Range().Deflate( h4 ).Clip( s ) );
465 }
466
467 Vector<AnglePerLength> DBds( Length s ) const{
468 const auto B = [this]( Length s ) -> Vector<One>{
470 Transition( s, F );
471 return F.B;
472 };
473
474 return finite_difference_derivative6<Vector<AnglePerLength>>( B, Range().Deflate( h4 ).Clip( s ) );
475 }
476
477 static Vector<One> N( const Vector<One>& T, const Vector<AnglePerLength>& dTds ) noexcept{
478 Vector<One> N;
479 if( dTds != Null<AnglePerLength> )
480 N = Normalize( dTds ).second;
481 else{
482 N = Up % T;
483 if( N == Null<One> )
484 N = Parallel( Up, Ex<One> ) ? Ey<One> : Ex<One>;
485 }
486
487 N = N - (N * T) * T;
488 N.Normalize();
489 return N;
490 }
491 };
492
493
505 template<class FunctionParametrizedByArcLength, class Base>
506 class CurveArcLength_Imp : public Base{
507 protected:
508 FunctionParametrizedByArcLength f;
509 public:
510 using DataType = typename Base::Data;
511
512
513 // Curve:
514 bool IsValid() const noexcept override{
515 return f.IsValid();
516 }
517
518 AnglePerLength Curvature( Length s ) const noexcept override{
519 return f.D2(s).Length();
520 }
521
522 AnglePerLength Torsion( Length s ) const override
523 // (D1 % D2) * D3 / (D2*D2) (see Chapter3)
524 {
525 const auto D2 = f.D2(s);
526 if( const auto D2D2 = D2*D2 )
527 return (f.D1(s) % D2) * f.D3(s) / (D2D2);
528 else
529 return 0_1Im;
530 }
531
532 void Transition( Length s, Position<Length>& pos ) const override{
533 pos = f(s);
534 }
535
536 void Transition( Length s, Vector<One>& tan ) const override{
537 tan = f.D1(s);
538 }
539
540 void Transition( Length s, VectorBundle<Length,One>& bundle ) const override{
541 bundle.P = f(s);
542 bundle.T = f.D1(s);
543 }
544
545 void Transition( Length s, VectorBundle2<Length,One>& bundle ) const override{
546 bundle.P = f(s);
547 bundle.T = f.D1(s);
548
549 bundle.N = f.D2(s) / Value<Dimension<-1,0,0>>{1};
550 if( bundle.N.Length() < 10 * epsilon ){
551 s += (s >= (f.Range().Normal() ? f.Range().Near() : f.Range().Far()) + epsilon__length ? -epsilon__length : +epsilon__length);
552
553 bundle.N = f.D2(s) / Value<Dimension<-1,0,0>>{1};
554
555 if( bundle.N.Length() < 10 * epsilon )
556 bundle.N = Up % bundle.T;
557 }
558
559 bundle.N = bundle.N - (bundle.N * bundle.T) * bundle.T;
560 bundle.N.Normalize();
561 assert( abs(bundle.T * bundle.N) < 10 * epsilon );
562 }
563
564 void Transition( Length s, Frame<Length,One>& frame ) const override{
565 Transition( s, reinterpret_cast<VectorBundle2<Length,One>&>(frame) );
566 frame.B = frame.T % frame.N;
567 }
568
569 std::vector<Length> ZeroSet() const override{
570 if( !IsValid() )
571 throw std::runtime_error( "This curve has to be created prior to receiving the zero set." );
572
573 return {};
574 }
575
576 common::Interval<Length> Range() const noexcept(noexcept(f.Range())) override{
577 return f.Range();
578 }
579
580 spat::Frame<Length,One> GetCurveLocalTransformation() const override{
582 Transition( 0_m, retval );
583 return retval;
584 }
585
586 bool Mirror( const spat::VectorBundle<Length,One>& mirrorPlane ) noexcept(noexcept(f.Mirror(mirrorPlane))) override{
587 if( !f.IsValid() )
588 return false;
589
590 return f.Mirror( mirrorPlane );
591 }
592
593 bool Equals( const Curve& toCurve, common::Interval<Length> range, Length epsilon_length, Angle epsilon_angle ) const override{
594 if( this == &toCurve )
595 return true;
596
597 if( auto pToCurve = dynamic_cast<const Base*>(&toCurve) )
598 return trax::Equals( GetData(), pToCurve->GetData(), range, epsilon_length, epsilon_angle );
599
600 return false;
601 }
602
603 common::Interval<Length> Create( const DataType& data ) override{
604 f.Create(data);
605 return f.Range();
606 }
607
608 const DataType& GetData() const noexcept override{
609 return f.GetData();
610 }
611 };
612
613
618 template<class Function>
619 class Reparametrization{
620 public:
621 Reparametrization() noexcept
622 : m_Length {-1},
623 m_Length2 {-1},
624 m_Length3 {-1}
625 {
626 }
627
628 Reparametrization( Real length ) noexcept
629 : m_Length {length},
630 m_Length2 {m_Length*m_Length},
631 m_Length3 {m_Length*m_Length2}
632 {
633 assert( m_Length >= 0 );
634 }
635
636 Reparametrization( const Reparametrization& ) = default;
637 Reparametrization( Reparametrization&& ) = default;
638 Reparametrization& operator=( const Reparametrization& ) = default;
639 Reparametrization& operator=( Reparametrization&& ) = default;
640 ~Reparametrization() = default;
641
642
643 void Length( Real length ) noexcept{
644 assert( length >= 0 );
645 m_Length = length;
646 m_Length2 = m_Length*m_Length;
647 m_Length3 = m_Length*m_Length2;
648 }
649
650 Real Length() const noexcept{
651 return m_Length;
652 }
653
654 bool IsValid() const noexcept{
655 return f.IsValid() && m_Length >= 0;
656 }
657
658 inline Position<dim::Length> operator()( Real t ) const{
659 return P(t);
660 }
661
662 Position<dim::Length> P( Real t ) const{
663 return f( m_Length * t );
664 }
665
666 Vector<dim::Length> D1( Real t ) const{
667 return m_Length * f.D1( m_Length * t );
668 }
669
670 Vector<dim::Length> D2( Real t ) const{
671 return m_Length2 * f.D2( m_Length * t );
672 }
673
674 Vector<dim::Length> D3( Real t ) const{
675 return m_Length3 * f.D3( m_Length * t );
676 }
677
678 bool Mirror( const spat::VectorBundle<dim::Length,One>& mirrorPlane ){
679 return f.Mirror( mirrorPlane );
680 }
681
682 common::Interval<Real> Create( const typename Function::DataType& data ){
683 Length( f.Create(data).Length() );
684 return { 0.f, 1.f };
685 }
686
687 const typename Function::DataType& GetData() const noexcept{
688 return f.GetData();
689 }
690
691 Function f;
692 private:
693 One m_Length;
694 One m_Length2;
695 One m_Length3;
696 };
697
698
699 template<class MainBase>
700 class CurvatureStrecher_Imp : public MainBase,
701 public CurvatureStrecher{
702 public:
703
704 AnglePerLength Start( Length s, const spat::Position<Length>& Z, common::Interval<AnglePerLength> curvatureLimits ) override{
705 m_CurvatureLimits = curvatureLimits;
706 m_ZStart = Z;
708 this->Transition( s, E );
709 m_TargetOffset = (Z - E) * this->Direction( s );
710 return this->Curvature(s);
711 }
712 protected:
713 template<class FunctionType>
714 AnglePerLength solve_root( FunctionType f, AnglePerLength bestGuess ) const{
715 if( m_CurvatureLimits.Touches(bestGuess) ){
716 constexpr boost::uintmax_t maxit = 30;
717 boost::uintmax_t it = maxit;
718
719 try{
720 const Interval<AnglePerLength> bracket{ trax::bracket_and_solve_root(
721 f,
722 bestGuess, // good news: we have quite a plausible guess value
723 1.1f, // use small intervals, since f is not strictly monotonic
724 f( bestGuess + epsilon__curvature ) - f( bestGuess - epsilon__curvature ) >= 0_m, // f rising or falling around k? Cannot figure it out less stupid ...
725 boost::math::tools::eps_tolerance<Real>{std::numeric_limits<Real>::digits-3}, // allow for inaccuracy in f(k)
726 it // coming close to a straight line manifests in exceeding maxit...
727 ) };
728
729 AnglePerLength k = bracket.Center();
730 std::cout << "[" << bracket.Near() << "," << bracket.Far() << "] iterations: " << it << " k= " << k << std::endl;
731
732 if( it <= maxit && m_CurvatureLimits.Touches( k ) )
733 return k;
734 }
735 catch( const boost::math::evaluation_error& e ){
736 std::cerr << e.what() << std::endl;
737 }
738 catch( const std::invalid_argument& e ){
739 std::cerr << e.what() << std::endl;
740 }
741 }
742
743 return bestGuess;
744 }
745
746 common::Interval<AnglePerLength> m_CurvatureLimits = {epsilon__angle/maximum__length,180_deg/epsilon__length};
748 Length m_TargetOffset = 0_m;
749 };
750}
Value type, dependend from dimensions.
Definition DimensionedValues.h:233
Square matrix with nColumns == nRows.
Definition Matrix.h:278
Definition Curve_Imp.h:701
One t(Length s) const noexcept
Parameter from arc length function to evaluate f.
Definition Curve_Imp.h:351
common::Interval< Length > Sample()
Definition Curve_Imp.h:306
Length SampleStep() const noexcept
Definition Curve_Imp.h:278
Length s(One t) const noexcept
Arc length s from parameter t calculated by bisection.
Definition Curve_Imp.h:366
If the curve function happens to be parameterized by arc length, this implementation for a curve can ...
Definition Curve_Imp.h:506
This calculates the normal vector, curvature and torsion numerically using the relations derived from...
Definition Curve_Imp.h:430
constexpr T pow(T val) noexcept
power function with templated integer exponent.
Definition Helpers.h:61
constexpr bool Equals(T a, T b, T epsilon) noexcept
Tests equality in the sense |a-b| < epsilon.
Definition Helpers.h:66
Target narrow_cast(Source v)
Safe cast for casting numeric values.
Definition NarrowCast.h:60
Value< Dimension< 2, 0, 0 > > Area
Area.
Definition DimensionedValues.h:325
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
Value< Dimension< 0, 0, 0 > > One
Dimensionless value.
Definition DimensionedValues.h:319
constexpr Real _1Im(AnglePerLength a) noexcept
Dimensionated Values conversion functions.
Definition DimensionedValues.h:1347
Value< Dimension< 1, 0, 0 > > Length
Length.
Definition DimensionedValues.h:324
constexpr Real _1Im2(Value< Dimension<-2, 0, 0 > > a) noexcept
Dimensionated Values conversion functions.
Definition DimensionedValues.h:1379
constexpr Real _m(Length l) noexcept
Dimensionated Values conversion functions.
Definition DimensionedValues.h:1210
Value< Dimension<-1, 0, 0 > > AnglePerLength
Angle per length.
Definition DimensionedValues.h:321
float Real
Underlying floating point type to be used with the dim library.
Definition DimensionedValues.h:190
constexpr Real epsilon
Marginal difference in calculations.
Definition DimensionedValues.h:344
constexpr Real _deg(Angle a) noexcept
Dimensionated Values conversion functions.
Definition DimensionedValues.h:1194
Value< Dimension< 0, 0, 0 > > Angle
Angle in radians.
Definition DimensionedValues.h:320
constexpr Value< Dimension< L, M, T > > abs(Value< Dimension< L, M, T > > x) noexcept
Dimensionated Values math function.
Definition DimensionedValues.h:680
constexpr Value< Dimension< 0, 0, 0 > > tan(Value< Dimension< 0, 0, 0 > > a) noexcept
Dimensionated Values math function.
Definition DimensionedValues.h:702
constexpr Real _m2(Area a) noexcept
Dimensionated Values conversion functions.
Definition DimensionedValues.h:1299
constexpr auto Determinant(const SquareMatrix< Valtype, nColsAndRows > &m) -> decltype(pow< nColsAndRows >(Valtype{}))
Determinant of the matrix.
Definition Matrix.h:1147
auto Normalize(const Frame< Valtype, ValtypeT > &f) noexcept -> std::pair< Vector< ValtypeT >, Frame< Valtype, decltype(ValtypeT{}/ValtypeT{})> >
Outer normalizing.
Definition Frame.h:1144
constexpr Position< Valtype > Origin3D
Origin of coordinate system.
Definition Position.h:143
Namespace of all the trax track libraries classes and methods.
Definition Collection.h:17
constexpr spat::Vector< One > Up
Vector pointing in the up direction with respect to gravity.
Definition Units.h:144
constexpr AnglePerLength epsilon__curvature
Marginal curvature is earth's curvature.
Definition Units.h:149
An interval describes the area between two numbers. It is understood to contain the near one and exlu...
Definition Interval.h:42
constexpr Valtype Near() const noexcept
Definition Interval.h:381
constexpr Valtype Length() const noexcept
Distance from m_Near to m_Far.
Definition Interval.h:413
constexpr Valtype Far() const noexcept
Definition Interval.h:386
constexpr Valtype Center() const noexcept
gets the value centered in the interval.
Definition Interval.h:431
Type selection for class Value.
Definition DimensionedValues.h:224
A Frame ("TNBFrame") describes a location in 3d space and an orientation using a right handed coordin...
Definition Frame.h:52
Vector< ValtypeT > B
Binormal axis or z-axis.
Definition Frame.h:56
Vector< ValtypeT > N
Normal axis or y-axis.
Definition Frame.h:55
Vector< ValtypeT > T
Tangential axis or x-axis.
Definition Frame.h:54
Implements a 3D - position in cartesian coordinates.
Definition Position.h:46
Implements a tangential space bundle.
Definition VectorBundle2.h:43
Vector< ValtypeT > T
Tangent vector or x-axis.
Definition VectorBundle2.h:45
Vector< ValtypeT > N
Normal axis or y-axis.
Definition VectorBundle2.h:46
Position< Valtype > P
Base space postion.
Definition VectorBundle2.h:44
Implements a Vector bundle.
Definition VectorBundle.h:42
Position< Valtype > P
Base space postion.
Definition VectorBundle.h:43
Vector< ValtypeT > T
Tangent vector or x-axis.
Definition VectorBundle.h:44
Implements a 3D - vector in cartesian coordinates.
Definition Vector.h:48
Valtype dy
cartesian y component.
Definition Vector.h:52
Valtype dx
cartesian x component.
Definition Vector.h:51
Valtype dz
cartesian z component.
Definition Vector.h:53
auto Normalize() noexcept -> decltype(Valtype{}/Valtype{})
Normalizes the vector to length 1.
Definition Vector.h:487
virtual spat::Vector< One > Direction(Length s) const =0
Curves implement this interface that then can get attached to a track to define the tracks geometry.
Definition Curve.h:198