Trax3 3.1.0
trax track library
Loading...
Searching...
No Matches
ImplementationHelper.h
1// trax track library
2// AD 2014
3//
4// "the resolution of all the fruitless searches"
5//
6// Peter Gabriel
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 "trax/ObjectID.h"
30#include "trax/Units.h"
31
32#include <stack>
33#include <map>
34#include <memory>
35
36#include "spat/Frame.h"
37
38namespace trax{
39
40 template<class Base>
41 class Pose_Imp : public Base{
42 public:
43 Pose_Imp() noexcept{
44 m_Frame.Init();
45 m_AbsoluteFrame.Init();
46 }
47
48 void SetFrame( const spat::Frame<Length,One>& frame ) noexcept override{
49 //assert( frame.IsOrthoNormal() );
50 m_Frame = frame;
51 PropagateAbsoluteFrameToClients();
52 }
53
54 const spat::Frame<Length,One>& GetFrame() const noexcept override{
55 return m_Frame;
56 }
57
58#if defined(__clang__)
59# pragma GCC diagnostic push
60# pragma GCC diagnostic ignored "-Winconsistent-missing-override"
61#endif
62 virtual void SetAbsoluteFrame( const spat::Frame<Length,One>& frame ) noexcept
63 // no 'override' here, since the template might introduce the method for some Bases.
64 {
65 //assert( frame.IsOrthoNormal() );
66 m_AbsoluteFrame = frame;
67 PropagateAbsoluteFrameToClients();
68 }
69
70 virtual const spat::Frame<Length,One>& GetAbsoluteFrame() const noexcept
71 // no 'override' here, since the template might introduce the method for some Bases.
72 {
73 return m_AbsoluteFrame;
74 }
75#if defined(__clang__)
76# pragma GCC diagnostic pop
77#endif
78
79 void SetFrames( const spat::Frame<Length,One>& frame, const spat::Frame<Length,One>& absolutFrame ) noexcept{
80 m_Frame = frame;
81 m_AbsoluteFrame = absolutFrame;
82 PropagateAbsoluteFrameToClients();
83 }
84 protected:
85 // Override this to brief clients about a change of its
86 // absolute frame of reference.
87 virtual void PropagateAbsoluteFrameToClients() noexcept{}
88 private:
90 spat::Frame<Length,One> m_AbsoluteFrame;
91 };
92
93
94 template<class TraxType, class Base>
95 class Container_Imp : public Base{
96 public:
97 Container_Imp() noexcept;
98
99 using Base::Add;
100 using Base::Remove;
101 using Base::Take;
102 using Base::GetNext;
103 using Base::IsMember;
104
105 bool IsValid () const noexcept override;
106
107 IDType Add ( std::shared_ptr<TraxType> pTraxType ) override;
108
109 IDType AddRelaxed ( std::shared_ptr<TraxType> pTraxType ) override;
110
111 bool Remove ( TraxType* pTraxType, bool zeroIDs = false ) override;
112
113 int Take ( typename Base::collection_type& collection ) override;
114
115 void Clear () noexcept override;
116
117 int Count () const noexcept override;
118
119 typename Base::collection_type::iterator begin () noexcept override;
120
121 typename Base::collection_type::iterator end () noexcept override;
122
123 typename Base::collection_type::const_iterator begin() const noexcept override;
124
125 typename Base::collection_type::const_iterator cbegin() const noexcept override;
126
127 typename Base::collection_type::const_iterator end() const noexcept override;
128
129 typename Base::collection_type::const_iterator cend() const noexcept override;
130
131 std::shared_ptr<TraxType> GetFirst () const noexcept override;
132
133 std::shared_ptr<TraxType> GetNext ( const std::shared_ptr<TraxType>& pTraxType ) const override;
134
135 std::shared_ptr<TraxType> GetLast () const override;
136
137 std::shared_ptr<TraxType> GetPrevious ( const std::shared_ptr<TraxType>& pTraxType ) const override;
138
139 std::shared_ptr<TraxType> Get ( IDType id ) const override;
140
141 std::shared_ptr<TraxType> Get ( const std::string& name ) const override;
142
143 void PushActive ( IDType id ) override;
144
145 void PopActive () override;
146
147 std::shared_ptr<TraxType> GetActive () const override;
148
149 bool IsMember ( const TraxType& item ) const override;
150
151 bool IsMember ( IDType id ) const override;
152
153 void ShiftIDs ( int offset ) override;
154
155 IDType MaxID () const override;
156
157 IDType MinID () const override;
158
159
160 protected:
161 void SetDecorator( Base* pDecorator ) noexcept override; // has to derive immediatley from the collection interface
162 Base* Decorator() const noexcept{ return m_pDecorator; }
163
164 using ContainerType = std::map<IDType,std::shared_ptr<TraxType>>;
165 ContainerType m_Container;
166 private:
167 Base* m_pDecorator;
168
169 bool IsFree( IDType id ) const{
170 return m_Container.find( id ) == m_Container.end();
171 }
172
173 std::stack<IDType> m_ActiveStack;
174
175 IDType GetFree() const{
176 IDType x = 1;
177 for( auto citer = m_Container.begin();
178 citer != m_Container.end(); ++x, ++citer )
179 {
180 if( x == (*citer).first )
181 continue;
182
183 return x;
184 }
185
186 return x;
187 }
188 };
189
190
191// inlines:
193template<class TraxType, class Base>
194inline Container_Imp<TraxType, Base>::Container_Imp() noexcept
195 : Base{}
196{
197 SetDecorator( this );
198}
199
200template<class TraxType, class Base>
201inline bool Container_Imp<TraxType, Base>::IsValid() const noexcept
202{
203 return false;
204}
205
206template<class TraxType, class Base>
207IDType Container_Imp<TraxType,Base>::Add( std::shared_ptr<TraxType> pTraxType ){
208 if( !pTraxType )
209 return 0;
210
211 if( Decorator()->IsMember( *pTraxType ) ){
212 Decorator()->PushActive( pTraxType->ID() );
213 return pTraxType->ID();
214 }
215
216 if( pTraxType->ID() ){
217 if( !IsFree( pTraxType->ID() ) )
218 throw std::invalid_argument( "The item ID is already used in the container! ID: " + std::to_string( pTraxType->ID().GetID() ) );
219 }
220 else
221 pTraxType->ID( GetFree() );
222
223 m_Container.insert( std::make_pair( pTraxType->ID(), pTraxType ) );
224 Decorator()->PushActive(pTraxType->ID());
225
226 return pTraxType->ID();
227}
228
229template<class TraxType, class Base>
230IDType Container_Imp<TraxType,Base>::AddRelaxed( std::shared_ptr<TraxType> pTraxType ){
231 if( !pTraxType )
232 return 0;
233
234 if( Decorator()->IsMember( *pTraxType ) ){
235 Decorator()->PushActive( pTraxType->ID() );
236 return pTraxType->ID();
237 }
238
239 if( pTraxType->ID() ){
240 if( !IsFree( pTraxType->ID() ) )
241 pTraxType->ID( GetFree() );
242 }
243 else
244 pTraxType->ID( GetFree() );
245
246 m_Container.insert( std::make_pair( pTraxType->ID(), pTraxType ) );
247 Decorator()->PushActive(pTraxType->ID());
248
249 return pTraxType->ID();
250}
251
252template<class TraxType, class Base>
253bool Container_Imp<TraxType,Base>::Remove( TraxType* pTraxType, bool zeroIDs ){
254 assert( pTraxType );
255
256 if( pTraxType ){
257 if( zeroIDs ){
258 const IDType id = pTraxType->ID();
259 pTraxType->ID( 0 );
260 if( m_Container.erase( id ) > 0 )
261 return true; // the object might be deleted here
262 else
263 pTraxType->ID( id );
264 }
265 else
266 return m_Container.erase( pTraxType->ID() ) > 0;
267 }
268
269 return false;
270}
271
272template<class TraxType, class Base>
273int Container_Imp<TraxType,Base>::Take( typename Base::collection_type& collection ){
274 const int offset = MaxID();
275 collection.ShiftIDs( offset ); // make sure the ids stay unique.
276
277 auto pTraxType = collection.GetFirst();
278 while( pTraxType ){
279 collection.Remove( pTraxType.get() );
280 Decorator()->Add( pTraxType );
281
282 pTraxType = collection.GetFirst();
283 }
284
285 return offset;
286}
287
288template<class TraxType, class Base>
289std::shared_ptr<TraxType> Container_Imp<TraxType,Base>::GetNext( const std::shared_ptr<TraxType>& pTraxType ) const{
290 assert( pTraxType );
291 auto iter = m_Container.find( pTraxType->ID() );
292 if( iter != m_Container.end() &&
293 ++iter != m_Container.end() )
294 return (*iter).second;
295
296 return nullptr;
297}
298
299template<class TraxType, class Base>
300std::shared_ptr<TraxType> Container_Imp<TraxType,Base>::GetPrevious( const std::shared_ptr<TraxType>& pTraxType ) const{
301 assert( pTraxType );
302 auto iter = m_Container.find( pTraxType->ID() );
303 if( iter != m_Container.end() &&
304 iter != m_Container.begin() )
305 return (*--iter).second;
306
307 return nullptr;
308}
309
310template<class TraxType, class Base>
311bool Container_Imp<TraxType,Base>::IsMember( const TraxType& item ) const{
312 if( !item.ID() )
313 return false;
314
315 const auto iter = m_Container.find( item.ID() );
316 if( iter == m_Container.end() )
317 return false;
318
319 return iter->second.get() == &item;
320}
321
322template<class TraxType, class Base>
323void Container_Imp<TraxType,Base>::Clear() noexcept{
324 m_Container.clear();
325 while( !m_ActiveStack.empty() )
326 m_ActiveStack.pop();
327}
328
329template<class TraxType, class Base>
330int Container_Imp<TraxType,Base>::Count() const noexcept{
331 return static_cast<int>(m_Container.size());
332}
333
334template<class TraxType, class Base>
335typename Base::collection_type::iterator Container_Imp<TraxType,Base>::begin() noexcept{
336 return { m_Container.begin() };
337}
338
339template<class TraxType, class Base>
340typename Base::collection_type::iterator Container_Imp<TraxType,Base>::end() noexcept{
341 return { m_Container.end() };
342}
343
344template<class TraxType, class Base>
345typename Base::collection_type::const_iterator Container_Imp<TraxType,Base>::begin() const noexcept{
346 return { m_Container.begin() };
347}
348
349template<class TraxType, class Base>
350typename Base::collection_type::const_iterator Container_Imp<TraxType,Base>::end() const noexcept{
351 return { m_Container.end() };
352}
353
354template<class TraxType, class Base>
355typename Base::collection_type::const_iterator Container_Imp<TraxType,Base>::cbegin() const noexcept{
356 return { m_Container.begin() };
357}
358
359template<class TraxType, class Base>
360typename Base::collection_type::const_iterator Container_Imp<TraxType,Base>::cend() const noexcept{
361 return { m_Container.end() };
362}
363
364template<class TraxType, class Base>
365std::shared_ptr<TraxType> Container_Imp<TraxType,Base>::GetFirst() const noexcept{
366 const auto iter = m_Container.begin();
367 if( iter != m_Container.end() )
368 return (*iter).second;
369
370 return nullptr;
371}
372
373template<class TraxType, class Base>
374std::shared_ptr<TraxType> Container_Imp<TraxType,Base>::GetLast() const{
375 const auto iter = m_Container.rbegin();
376 if( iter != m_Container.rend() )
377 return (*iter).second;
378
379 return nullptr;
380}
381
382template<class TraxType, class Base>
383std::shared_ptr<TraxType> Container_Imp<TraxType,Base>::Get( IDType id ) const{
384 const auto iter = m_Container.find( id );
385 if( iter != m_Container.end() )
386 return (*iter).second;
387
388 return nullptr;
389}
390
391template<class TraxType, class Base>
392std::shared_ptr<TraxType> Container_Imp<TraxType,Base>::Get( const std::string& name ) const{
393 for( auto iter = m_Container.begin(); iter != m_Container.end(); ++iter )
394 if( (*iter).second->Reference( "name" ).compare( name ) == 0 )
395 return (*iter).second;
396
397 return nullptr;
398}
399
400template<class TraxType, class Base>
401void Container_Imp<TraxType,Base>::PushActive( IDType id ){
402 m_ActiveStack.push(id);
403}
404
405template<class TraxType, class Base>
406void Container_Imp<TraxType,Base>::PopActive(){
407 if( m_ActiveStack.empty() )
408 throw std::underflow_error( "Popped an empty stack!" );
409
410 m_ActiveStack.pop();
411}
412
413template<class TraxType, class Base>
414std::shared_ptr<TraxType> Container_Imp<TraxType,Base>::GetActive() const{
415 if( m_ActiveStack.empty() )
416 return nullptr;
417
418 return Decorator()->Get(m_ActiveStack.top());
419}
420
421template<class TraxType, class Base>
422bool Container_Imp<TraxType,Base>::IsMember( IDType id ) const{
423 return !IsFree( id );
424}
425
426template<class TraxType, class Base>
427inline void Container_Imp<TraxType, Base>::ShiftIDs( int offset ){
428 if( m_Container.empty() )
429 return;
430 if( MinID().GetID() + offset <= 0 )
431 throw std::out_of_range( "Can not shift id space." );
432
433 std::stack<IDType> tempStack;
434 while( !m_ActiveStack.empty() ){
435 tempStack.push( m_ActiveStack.top() + offset );
436 m_ActiveStack.pop();
437 }
438 while( !tempStack.empty() ){
439 m_ActiveStack.push( tempStack.top() );
440 tempStack.pop();
441 }
442
443 ContainerType tempContainer;
444 for( const auto& pair : m_Container ){
445 pair.second->ID( pair.second->ID() + offset );
446 tempContainer[pair.first+offset] = pair.second;
447 }
448
449 m_Container.swap( tempContainer );
450}
451
452template<class TraxType, class Base>
453inline IDType Container_Imp<TraxType, Base>::MaxID() const{
454 if( m_Container.empty() )
455 return 0;
456
457 return m_Container.rbegin()->first;
458}
459
460template<class TraxType, class Base>
461inline IDType Container_Imp<TraxType, Base>::MinID() const{
462 if( m_Container.empty() )
463 return 0;
464
465 return m_Container.begin()->first;
466}
467
468template<class TraxType, class Base>
469void Container_Imp<TraxType, Base>::SetDecorator( Base* pDecorator ) noexcept{
470 if( pDecorator )
471 m_pDecorator = pDecorator;
472 else
473 m_pDecorator = this;
474}
475
476template<class ContainerType>
477inline bool IsValid_Imp( const ContainerType& container ){
478 bool bOK = true;
479 for( const auto& pair : container ){
480 auto& element = *(pair.second);
481 if( !element.IsValid() ){
482 bOK = false;
483 }
484 }
485
486 return bOK;
487}
488
489}
490
The base for decorator implementations. Needed as BaseDecorator to combine other decorator implemente...
Definition ObjectIDDecorator.h:27
Namespace of all the trax track libraries classes and methods.
Definition Collection.h:17
A Frame ("TNBFrame") describes a location in 3d space and an orientation using a right handed coordin...
Definition Frame.h:52
Type used for IDs in the trax library.
Definition IDType.h:43