Field3D
Curve.h
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
43 //----------------------------------------------------------------------------//
44 
45 #ifndef _INCLUDED_Field3D_Curve_H_
46 #define _INCLUDED_Field3D_Curve_H_
47 
48 //----------------------------------------------------------------------------//
49 
50 #include <algorithm>
51 #include <utility>
52 #include <vector>
53 
54 #include <boost/lexical_cast.hpp>
55 
56 // The version can reliably be found in this header file from OpenEXR,
57 // for both 2.x and 3.x:
58 #include <OpenEXR/OpenEXRConfig.h>
59 #define COMBINED_OPENEXR_VERSION ((10000*OPENEXR_VERSION_MAJOR) + \
60  (100*OPENEXR_VERSION_MINOR) + \
61  OPENEXR_VERSION_PATCH)
62 
63 // There's just no easy way to have an `#include` that works in both
64 // cases, so we use the version to switch which set of include files we
65 // use.
66 #if COMBINED_OPENEXR_VERSION >= 20599 /* 2.5.99: pre-3.0 */
67 # include <Imath/ImathFun.h>
68 # include <Imath/ImathMatrix.h>
69 #else
70  // OpenEXR 2.x, use the old locations
71 # include <OpenEXR/ImathFun.h>
72 # include <OpenEXR/ImathMatrix.h>
73 #endif
74 
75 
76 //----------------------------------------------------------------------------//
77 
78 #include "ns.h"
79 
81 
82 //----------------------------------------------------------------------------//
83 // Curve
84 //----------------------------------------------------------------------------//
85 
92 //----------------------------------------------------------------------------//
93 
94 template <typename T>
95 class Curve
96 {
97 public:
98 
99  // Typedefs ------------------------------------------------------------------
100 
101  typedef std::pair<float, T> Sample;
102  typedef std::vector<Sample> SampleVec;
103 
104  // Main methods --------------------------------------------------------------
105 
109  void addSample(const float t, const T &value);
110 
113  T linear(const float t) const;
114 
116  size_t numSamples() const
117  { return m_samples.size(); }
118 
120  const SampleVec& samples() const
121  { return m_samples; }
122 
124  void clear()
125  { SampleVec().swap(m_samples); }
126 
127 private:
128 
129  // Structs -------------------------------------------------------------------
130 
133  public std::unary_function<std::pair<float, T>, bool>
134  {
136  : m_match(match)
137  { }
138  bool operator()(std::pair<float, T> test)
139  {
140  return test.first > m_match;
141  }
142  private:
143  float m_match;
144  };
145 
147  struct CheckTEqual :
148  public std::unary_function<std::pair<float, T>, bool>
149  {
151  : m_match(match)
152  { }
153  bool operator()(std::pair<float, T> test)
154  {
155  return test.first == m_match;
156  }
157  private:
158  float m_match;
159  };
160 
161  // Utility methods -----------------------------------------------------------
162 
168  { return T(0); }
169 
173  T lerp(const Sample &lower, const Sample &upper, const float t) const
174  { return Imath::lerp(lower.second, upper.second, t); }
175 
176  // Private data members ------------------------------------------------------
177 
180  SampleVec m_samples;
181 
182 };
183 
184 //----------------------------------------------------------------------------//
185 // Template implementations
186 //----------------------------------------------------------------------------//
187 
188 template <typename T>
189 void Curve<T>::addSample(const float t, const T &value)
190 {
191  using namespace std;
192  // Check that sample time is not already in curve
193  typename SampleVec::iterator i =
194  find_if(m_samples.begin(), m_samples.end(), CheckTEqual(t));
195  if (i != m_samples.end()) {
196  // Sample position already exists, so we replace it
197  i->second = value;
198  return;
199  }
200  // Find the first sample location that is greater than the interpolation
201  // position
202  i = find_if(m_samples.begin(), m_samples.end(), CheckTGreaterThan(t));
203  // If we get something other than end() back then we insert the new
204  // sample before that. If there wasn't a larger value we add this sample
205  // to the end of the vector.
206  if (i != m_samples.end()) {
207  m_samples.insert(i, make_pair(t, value));
208  } else {
209  m_samples.push_back(make_pair(t, value));
210  }
211 }
212 
213 //----------------------------------------------------------------------------//
214 
215 template <typename T>
216 T Curve<T>::linear(const float t) const
217 {
218  using namespace std;
219  // If there are no samples, return zero
220  if (m_samples.size() == 0) {
221  return defaultReturnValue();
222  }
223  // Find the first sample location that is greater than the interpolation
224  // position
225  typename SampleVec::const_iterator i =
226  find_if(m_samples.begin(), m_samples.end(), CheckTGreaterThan(t));
227  // If we get end() back then there was no sample larger, so we return the
228  // last value. If we got the first value then there is only one value and
229  // we return that.
230  if (i == m_samples.end()) {
231  return m_samples.back().second;
232  } else if (i == m_samples.begin()) {
233  return m_samples.front().second;
234  }
235  // Interpolate between the nearest two samples.
236  const Sample &upper = *i;
237  const Sample &lower = *(--i);
238  const float interpT = Imath::lerpfactor(t, lower.first, upper.first);
239  return lerp(lower, upper, interpT);
240 }
241 
242 //----------------------------------------------------------------------------//
243 // Template specializations
244 //----------------------------------------------------------------------------//
245 
246 template <>
247 inline Imath::Matrix44<float>
248 Curve<Imath::Matrix44<float> >::defaultReturnValue() const
249 {
250  Imath::Matrix44<float> identity;
251  identity.makeIdentity();
252  return identity;
253 }
254 
255 //----------------------------------------------------------------------------//
256 
257 template <>
258 inline Imath::Matrix44<double>
259 Curve<Imath::Matrix44<double> >::defaultReturnValue() const
260 {
261  Imath::Matrix44<double> identity;
262  identity.makeIdentity();
263  return identity;
264 }
265 
266 //----------------------------------------------------------------------------//
267 
269 
270 //----------------------------------------------------------------------------//
271 
272 #endif // Include guard
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Definition: ns.h:58
size_t numSamples() const
Returns the number of samples in the curve.
Definition: Curve.h:116
T defaultReturnValue() const
The default return value is used when no sample points are available. This defaults to zero...
Definition: Curve.h:167
std::pair< float, T > Sample
Definition: Curve.h:101
SampleVec m_samples
Stores the samples that define the curve. Sample insertion ensures that the samples are sorted accord...
Definition: Curve.h:180
bool operator()(std::pair< float, T > test)
Definition: Curve.h:153
CheckTGreaterThan(float match)
Definition: Curve.h:135
void addSample(const float t, const T &value)
Adds a sample point to the curve.
Definition: Curve.h:189
Used when finding values in the m_samples vector.
Definition: Curve.h:132
CheckTEqual(float match)
Definition: Curve.h:150
const SampleVec & samples() const
Returns a const reference to the samples in the curve.
Definition: Curve.h:120
T lerp(const Sample &lower, const Sample &upper, const float t) const
The default implementation for linear interpolation. Works for all classes for which Imath::lerp is i...
Definition: Curve.h:173
Implements a simple function curve where samples of type T can be added along a 1D axis...
Definition: Curve.h:95
bool match(const std::string &name, const std::string &attribute, const std::vector< std::string > &patterns, const MatchFlags flags=MatchEmptyPattern)
Matches a : string against a set of patterns.
T linear(const float t) const
Linearly interpolates a value from the curve.
Definition: Curve.h:216
std::vector< Sample > SampleVec
Definition: Curve.h:102
void clear()
Clears all samples in curve.
Definition: Curve.h:124
Used when finding values in the m_samples vector.
Definition: Curve.h:147
bool operator()(std::pair< float, T > test)
Definition: Curve.h:138