Interpolator.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "glm_alias.hpp"
4 #include "math.hpp"
5 #include "utils.hpp"
6 
7 #include <type_traits>
8 
9 namespace iv
10 {
11 
12 namespace interpolator
13 {
14 
15 template< typename T >
16 struct to_void
17 {
18  typedef void type;
19 };
20 
21 template< typename T >
22 struct always_false : std::false_type{};
23 
24 }
25 
26 
27 using Interpolator_float = float;
28 
29 template< typename T, typename dummy = void >
30 struct has_interpolate : std::false_type{};
31 
32 template< typename T >
33 struct has_interpolate< T, typename interpolator::to_void<typename T::interpolate>::type > : std::true_type{};
34 
35 template< typename Type, typename Enabled = void >
37 {
42  Interpolator_float Distance( Type const & from, Type const & to ) const
43  {
44  static_assert( interpolator::always_false< Type >::value, "Interpolator::Distance not defined for given type." );
45  return 0.0f;
46  }
47 
58  std::pair< Type, Interpolator_float > Interpolate( Type const & from, Type const & to, Interpolator_float distance ) const
59  {
60  static_assert( interpolator::always_false< Type >::value, "Interpolator::Interpolate not defined for given type." );
61  }
62 };
63 
64 
65 //---------- optional -------------
66 template< class T >
67 struct Interpolator< std::optional< T > >
68 {
69  Interpolator_float Distance( std::optional< T > const & from, std::optional< T > const & to ) const
70  {
71  if( from.has_value() && to.has_value() )
72  {
73  return Interpolator< T >().Distance( from.value(), to.value() );
74  }
75  else
76  {
77  return 0;
78  }
79  }
80 
81  std::pair< std::optional< T >, Interpolator_float > Interpolate( std::optional< T > const & from, std::optional< T > const & to, Interpolator_float distance ) const
82  {
83  if( from.has_value() && to.has_value() )
84  {
85  return Interpolator< T >().Interpolate( from.value(), to.value(), distance );
86  }
87  else
88  {
89  return std::pair( to, 0 );
90  }
91  }
92 };
93 
94 //---------- float -------------
95 template< class Float >
96 struct Interpolator< Float, std::enable_if_t< std::is_floating_point< Float >::value > >
97 {
98  Interpolator_float Distance( Float const & from, Float const & to ) const
99  {
100  return iv::abs( to - from );
101  }
102 
103  std::pair< Float, Interpolator_float > Interpolate( Float const & from, Float const & to, Interpolator_float distance ) const
104  {
105  if( distance == std::numeric_limits< Interpolator_float >::infinity() )
106  return std::pair( to, 0.0f );
107 
108  return std::pair( mix_max( from, to, Float( distance ) ), 0.0f );
109  }
110 };
111 
112 //---------- int -------------
113 template< class Int >
114 struct Interpolator< Int, std::enable_if_t< std::is_integral< Int >::value > >
115 {
116  Interpolator_float Distance( Int const & from, Int const & to ) const
117  {
118  return iv::abs( to - from );
119  }
120 
121  std::pair< Int, Interpolator_float > Interpolate( Int const & from, Int const & to, Interpolator_float distance ) const
122  {
123  if( distance == std::numeric_limits< Interpolator_float >::infinity() )
124  return std::pair( to, 0.0f );
125 
126  Interpolator_float fresult = mix_max( Interpolator_float( from ), Interpolator_float( to ), distance );
127  Int result = Int( fresult );
128  return std::pair( result, iv::abs( fresult - result ) );
129  }
130 };
131 
132 
133 //#error "ASDF"
134 
135 //-------------- std::string -----------------------
136 template<>
137 struct Interpolator< std::string >
138 {
139  Interpolator_float Distance( std::string const & from, std::string const & to ) const
140  {
141  return 1.0;
142  }
143 
144  std::pair< std::string, Interpolator_float > Interpolate( std::string const & from, std::string const & to, Interpolator_float distance ) const
145  {
146  if( distance < 1.0 )
147  return std::pair( from, distance );
148  else
149  return std::pair( to, distance - 1.0 );
150  }
151 };
152 
153 }