├── .gitignore ├── README.md ├── example ├── bin │ └── data │ │ └── .gitkeep └── src │ ├── main.cpp │ ├── testApp.cpp │ └── testApp.h ├── license.md └── src ├── MSAInterpolationTypes.h ├── MSAInterpolator.h ├── MSAInterpolator1D.h ├── MSAInterpolator2D.h ├── MSAInterpolator3D.h └── MSAInterpolatorT.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Some general ignore patterns 2 | 3 | */bin/* 4 | !*/bin/data/ 5 | # for bin folder in root 6 | /bin/* 7 | !/bin/data/ 8 | 9 | build/ 10 | obj/ 11 | *.o 12 | Debug*/ 13 | Release*/ 14 | *.mode* 15 | *.app/ 16 | *.pyc 17 | .svn/ 18 | 19 | # IDE-specific ignore patterns (e.g. user-specific files) 20 | 21 | #XCode 22 | *.pbxuser 23 | *.perspective 24 | *.perspectivev3 25 | *.mode1v3 26 | *.mode2v3 27 | #XCode 4 28 | xcuserdata 29 | *.xcworkspace 30 | 31 | #Code::Blocks 32 | *.depend 33 | *.layout 34 | *.cbTemp 35 | 36 | #Visual Studio 37 | *.sdf 38 | *.opensdf 39 | *.suo 40 | ipch/ 41 | 42 | #Eclipse 43 | .metadata 44 | local.properties 45 | .externalToolBuilders 46 | 47 | # OS-specific ignore patterns 48 | 49 | #Linux 50 | *~ 51 | # KDE 52 | .directory 53 | 54 | #OSX 55 | .DS_Store 56 | *.swp 57 | *~.nib 58 | # Thumbnails 59 | ._* 60 | 61 | #Windows 62 | # Windows image file caches 63 | Thumbs.db 64 | # Folder config file 65 | Desktop.ini 66 | 67 | #Android 68 | .csettings 69 | 70 | # Packages 71 | # it's better to unpack these files and commit the raw source 72 | # git has its own built in compression methods 73 | *.7z 74 | *.dmg 75 | *.gz 76 | *.iso 77 | *.jar 78 | *.rar 79 | *.tar 80 | *.zip 81 | 82 | # Logs and databases 83 | *.log 84 | *.sql 85 | *.sqlite 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MyAddon 2 | ===================================== 3 | 4 | Introduction 5 | ------------ 6 | C++ openFrameworks addon with a set of template classes for doing various types of interpolations on data with any number of dimensions. You can feed the system an arbitrary number of data, then resample at any resolution, or ask for the value at any percentage along the data. Input data can be floats (for 1D splines, Vec2f (for 2D splines), Vec3f (for 3D splines), or even matrices, or custom data types (e.g. biped pose). 7 | Demo at [www.memo.tv/msainterpolator](http://www.memo.tv/msainterpolator) 8 | 9 | 10 | Licence 11 | ------- 12 | The code in this repository is available under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). 13 | Copyright (c) 2008-2012 Memo Akten, [www.memo.tv](http://www.memo.tv) 14 | The Mega Super Awesome Visuals Company 15 | 16 | 17 | Installation 18 | ------------ 19 | Copy to your openFrameworks/addons folder. 20 | 21 | Dependencies 22 | ------------ 23 | - MSACore 24 | 25 | Compatibility 26 | ------------ 27 | openFrameworks 0072 28 | I am generally testing only with [openFrameworks](www.openframeworks.cc), however it should work with [Cinder](www.libcinder.org) too. If it doesn't, please file an issue. 29 | 30 | 31 | Known issues 32 | ------------ 33 | none 34 | 35 | Version history 36 | ------------ 37 | ### v2.1 23/09/2012 38 | - compatible with OF0072 39 | - renamed (uppercase) MSA namespace to (lowercase) msa. (kept MSA as an alias for backwards compatibility) 40 | - interpolating by distance seems broken 41 | 42 | ### v2.0 43 | - move to centralized MSALibs (requires MSACore) 44 | - everything is msa:: namespace 45 | - renamed useDistance to useLength (and all relevant functions) 46 | - using length now uses length of interpolated spline, not linear 47 | - fixed rare crash bug 48 | 49 | ### v1.1 07/04/2009 50 | - changed license to revised BSD (a lot more more permissive than GPL) 51 | 52 | ### v1.0 03/10/08 53 | - initial version 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /example/bin/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memo/ofxMSAInterpolator/8af25eea55cb29e5545ad2c7454f5c8ba0e18dad/example/bin/data/.gitkeep -------------------------------------------------------------------------------- /example/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "testApp.h" 3 | 4 | //======================================================================== 5 | int main( ){ 6 | 7 | // can be OF_WINDOW or OF_FULLSCREEN 8 | // pass in width and height too: 9 | ofSetupOpenGL(1024, 768, OF_WINDOW); // <-------- setup the GL context 10 | 11 | // this kicks off the running of my app 12 | ofRunApp(new testApp); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /example/src/testApp.cpp: -------------------------------------------------------------------------------- 1 | #include "testApp.h" 2 | #include "MSAInterpolator.h" 3 | 4 | 5 | msa::Interpolator2D spline2D; 6 | msa::Interpolator3D spline3D; 7 | 8 | msa::InterpolationType interpolationType = msa::kInterpolationCubic; 9 | bool useLength = false; 10 | 11 | float currentRot; 12 | bool rotateView; 13 | 14 | float spherePosPerc = 0; // 0....1 percentage of how far along the 3D path the sphere is 15 | float sphereSpeed = 0.005f; 16 | 17 | 18 | //-------------------------------------------------------------- 19 | void testApp::setup(){ 20 | ofSetVerticalSync(true); 21 | rotateView = true; 22 | currentRot = 0; 23 | 24 | // create a 2D spline with ofVec2f's 25 | int numItems = 10; 26 | int padding = 30; 27 | float len = (ofGetWidth() - padding*2.0f) / numItems; 28 | 29 | spline2D.reserve(numItems); // not essential, but good habit if you know how big its gonna be 30 | for(int i=0; i 1) { 89 | spherePosPerc = 1; 90 | sphereSpeed *= -1; 91 | } else if(spherePosPerc < 0) { 92 | spherePosPerc = 0; 93 | sphereSpeed *= -1; 94 | } 95 | 96 | 97 | glPopMatrix(); 98 | 99 | ofSetColor(0); 100 | string uiLin = interpolationType == msa::kInterpolationLinear ? "* " : " "; 101 | string uiCub = interpolationType == msa::kInterpolationCubic ? "* " : " "; 102 | string uiDist = spline3D.getUseLength() ? "* " : " "; 103 | ofDrawBitmapString( ofToString(ofGetFrameRate(), 2) + "\n" 104 | + "numSteps (resampling resolution - mouseX to change): " + ofToString(numSteps) + "\n" 105 | + "mouse click around the area to draw a 3D spline (length = " + ofToString(spline3D.getLength()) + "\n" 106 | + "\n" 107 | + uiLin + "'1' to use linear interpolation\n" 108 | + uiCub + "'2' to use cubic (catmull rom) interpolation\n" 109 | + "\n" 110 | + uiDist + "'d' to toggle 'using Length in interpolation'\n" 111 | + "\n" 112 | + "'c' to clear 3D spline\n" 113 | , 20, 20); 114 | 115 | } 116 | 117 | void testApp::keyPressed(int key) { 118 | switch(key) { 119 | case '1': 120 | interpolationType = msa::kInterpolationLinear; 121 | spline3D.setInterpolation(interpolationType); 122 | spline2D.setInterpolation(interpolationType); 123 | break; 124 | case '2': 125 | interpolationType = msa::kInterpolationCubic; 126 | spline3D.setInterpolation(interpolationType); 127 | spline2D.setInterpolation(interpolationType); 128 | break; 129 | 130 | case 'd': 131 | useLength ^=true; 132 | spline3D.setUseLength(useLength); 133 | spline2D.setUseLength(useLength); 134 | break; 135 | 136 | case 'c': 137 | case 'C': 138 | spline3D.clear(); 139 | break; 140 | 141 | case 'r': 142 | case 'R': 143 | rotateView ^= true; 144 | break; 145 | } 146 | } 147 | 148 | //-------------------------------------------------------------- 149 | void testApp::mousePressed(int x, int y, int button) { 150 | // when you add a new point, the length of the spline increases 151 | // so the sphere will jump to a new position because it's position is based on percentage 152 | // so a little bit of maths to calculate what the new position percentage should be to stay at the same physical location 153 | // (not precise, but close enough) 154 | int numPoints = spline3D.size(); 155 | spherePosPerc = spherePosPerc * numPoints / (numPoints + 1); 156 | 157 | 158 | ofVec3f pt(x-ofGetWidth()/2, y, 0); 159 | pt.rotate(-currentRot, ofVec3f(0, 1, 0)); 160 | spline3D.push_back(pt); 161 | } 162 | 163 | -------------------------------------------------------------------------------- /example/src/testApp.h: -------------------------------------------------------------------------------- 1 | #ifndef _TEST_APP 2 | #define _TEST_APP 3 | 4 | #include "ofMain.h" 5 | 6 | 7 | class testApp : public ofBaseApp { 8 | 9 | public: 10 | 11 | void setup(); 12 | void draw(); 13 | 14 | void mousePressed(int x, int y, int button); 15 | void keyPressed(int key); 16 | }; 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The code in this repository is available under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). 2 | 3 | Copyright (c) 2008-2012 Memo Akten, [www.memo.tv](http://www.memo.tv) 4 | The Mega Super Awesome Visuals Company 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/MSAInterpolationTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace msa { 4 | 5 | typedef enum { 6 | kInterpolationLinear, 7 | kInterpolationCubic, 8 | } InterpolationType; 9 | 10 | } -------------------------------------------------------------------------------- /src/MSAInterpolator.h: -------------------------------------------------------------------------------- 1 | /**************************** InterpolatorT Classes **************************** 2 | Usage: 3 | msa::InterpolatorT myInterpolator1; // create spline of floats 4 | msa::InterpolatorT myInterpolator2; // create spline of custom data types (more info below) 5 | 6 | // OR use preset classes: 7 | 8 | msa::Interpolator1D myInterpolator1D; // create spline of floats (1D) 9 | msa::Interpolator2D myInterpolator2D; // create spline of Vec2f (2D) 10 | msa::Interpolator3D myInterpolator3D; // create spline of Vec3f (3D) 11 | 12 | 13 | // splines wrap basic functionality of stl::vector: 14 | myInterpolator.size(); // return number of data elements 15 | myInterpolator.reserve(int count); // if you know how many elements up front it will improved performance when adding (you can still add more than this number of elements) 16 | myInterpolator.at(int i); // return data at i'th index 17 | myInterpolator.clear(); // remove all elements 18 | myInterpolator.push_back(data1); // add some data to the spline 19 | myInterpolator.push_back(data2); 20 | 21 | myInterpolator.sampleAt(float t); // (e.g. t:0.34 =>) samples along 34% of the whole spline using the current interpolation method and options 22 | 23 | setInterpolation(i); // set interpolation type, see MSAInterpolationTypes.h (currently cubic catmull rom and linear) 24 | int getInterpolation(); // get interpolation type 25 | 26 | setUseLength(bool b); // whether to use Length or not. using Length is slightly slower than not using (depending on number of data points) 27 | bool getUseLength(); // if useLength is true, sampleAt(0.57) means sample at 57% along the physical length of the spline (using the interpolated spline for Length calculation) 28 | // if useLength is false, the %t refers to % along the data points. If data points are evenly spaced its no problem, but if they are randomly spaced, the interpolation will not be uniform 29 | 30 | 31 | myInterpolator.drawRaw(int dotSize, int lineWidth); // draws raw data with dotSize and lineWidth (make either zero to not draw dots or lines) 32 | myInterpolator.drawSmooth(int numSteps, int dotSize, int lineWidth); // draws smoothed data in (make either zero to not draw dots or lines) 33 | 34 | Using custom data type: 35 | msa::InterpolatorT myInterpolator2; // create spline of custom data types (more info below) 36 | myDataType has to be a scalar or class with the overloaded operators: 37 | + (myDataType&) 38 | - (myDataType&) 39 | == (myDataType&) 40 | = (myDataType&) 41 | * (float) 42 | 43 | and also define the function lengthOf(myDataType&) to return a scalar float value depicting the 'magnitude' of the data type (used in calculating Length) 44 | 45 | 46 | *************************************************************************/ 47 | 48 | /*************** 49 | DEPENDENCIES: 50 | - MSACore 51 | ***************/ 52 | 53 | #pragma once 54 | 55 | #include "MSAInterpolationTypes.h" 56 | #include "MSAInterpolatorT.h" 57 | #include "MSAInterpolator1D.h" 58 | #include "MSAInterpolator2D.h" 59 | #include "MSAInterpolator3D.h" 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/MSAInterpolator1D.h: -------------------------------------------------------------------------------- 1 | 2 | /**************************** 1D InterpolatorT (of floats) ****************************/ 3 | 4 | #pragma once 5 | 6 | #include "MSAInterpolatorT.h" 7 | 8 | namespace msa { 9 | 10 | //-------------------------------------------------------------- 11 | inline float lengthOf(float f) { 12 | return f; 13 | } 14 | 15 | 16 | //-------------------------------------------------------------- 17 | typedef InterpolatorT Interpolator1D; 18 | } 19 | -------------------------------------------------------------------------------- /src/MSAInterpolator2D.h: -------------------------------------------------------------------------------- 1 | 2 | /**************************** 2D InterpolatorT (of Vec2) ****************************/ 3 | 4 | #pragma once 5 | 6 | #include "MSAInterpolatorT.h" 7 | 8 | namespace msa { 9 | 10 | typedef InterpolatorT Interpolator2D; 11 | 12 | 13 | //-------------------------------------------------------------- 14 | inline float lengthOf(const Vec2f& v) { 15 | return v.length(); 16 | } 17 | 18 | 19 | //-------------------------------------------------------------- 20 | // OpenGL ES compatibility added by Rob Seward 21 | // http://www.openframeworks.cc/forum/viewtopic.php?f=25&t=3767&p=19865 22 | inline void drawInterpolatorRaw(Interpolator2D &spline, int dotSize = 20, int lineWidth = 4){ 23 | int numItems = spline.size(); 24 | 25 | if(lineWidth) { 26 | glLineWidth(lineWidth); 27 | GLfloat vertex[numItems * 2]; 28 | for(int i=0; i Interpolator3D; 11 | 12 | 13 | //-------------------------------------------------------------- 14 | inline float lengthOf(const Vec3f& v) { 15 | return v.length(); 16 | } 17 | 18 | 19 | //-------------------------------------------------------------- 20 | // OpenGL ES compatibility added by Rob Seward 21 | // http://www.openframeworks.cc/forum/viewtopic.php?f=25&t=3767&p=19865 22 | inline void drawInterpolatorRaw(Interpolator3D spline, int dotSize = 20, int lineWidth = 4){ 23 | int numItems = spline.size(); 24 | if(numItems == 0) return; 25 | 26 | if(lineWidth) { 27 | glLineWidth(lineWidth); 28 | GLfloat vertex[numItems * 3]; 29 | for(int i=0; i inline float lengthOf(const T &v) { 11 | return 1; 12 | } 13 | 14 | 15 | template 16 | class InterpolatorT { 17 | public: 18 | 19 | bool verbose; 20 | 21 | InterpolatorT(); 22 | 23 | // interpolate and re-sample at t position along the spline 24 | // where t: 0....1 based on length of spline 25 | T sampleAt(float t) const; 26 | 27 | void setInterpolation(InterpolationType i = kInterpolationCubic); 28 | int getInterpolation() const; 29 | 30 | void setUseLength(bool b); 31 | bool getUseLength() const; 32 | 33 | // return length upto data point i 34 | // leave blank (-1) to return length of entire data set 35 | // only valid if setUseLength is true 36 | // uses current interpolation settings for lenth calculation 37 | // returns cached value, no calculations done in this function 38 | const float getLength(int i=-1) const; 39 | 40 | // set number of subdivisions used to calculation length of segment 41 | void setLengthSubdivisions(int i = 100); 42 | int getLengthSubdivisions() const; 43 | 44 | 45 | /******************* stl::container wrapper functions *******************/ 46 | void push_back(const T& newData); 47 | int size() const; 48 | void reserve(int i); 49 | void clear(); 50 | const T& at(int i) const; 51 | vector& getData(); 52 | const vector& getData() const; 53 | 54 | protected: 55 | InterpolationType _interpolationMethod; 56 | bool _useLength; 57 | int _lengthSubdivisions; // number of subdivisions used for length calculation 58 | vector _data; // vector of all data 59 | vector _dist; // vector of cumulative Lengths from i'th data point to beginning of spline 60 | 61 | 62 | // calculates length of segment prior to (leading up to) i'th point 63 | float calcSegmentLength(int i); 64 | 65 | // update all Lengths in _dist array 66 | void updateAllLengths(); 67 | 68 | // given t(0...1) find the node index directly to the left of the point 69 | void findPosition(float t, int &leftIndex, float &mu) const; 70 | 71 | T linearInterpolate(const T& y1, const T& y2, float mu) const; 72 | 73 | // this function is from Paul Bourke's site 74 | // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/ 75 | T cubicInterpolate(const T& y0, const T& y1, const T& y2, const T& y3, float mu) const; 76 | 77 | }; 78 | 79 | 80 | //---------------------------------------------------------------------------- 81 | //-------------------------------------------------------------- 82 | 83 | //-------------------------------------------------------------- 84 | template 85 | InterpolatorT::InterpolatorT() { 86 | setInterpolation(); 87 | setUseLength(false); 88 | setLengthSubdivisions(); 89 | verbose = false; 90 | } 91 | 92 | 93 | //-------------------------------------------------------------- 94 | // use catmull rom interpolation to re-sample At normT position along the spline 95 | // where normT: 0....1 based on length of spline 96 | template 97 | T InterpolatorT::sampleAt(float t) const { 98 | int numItems = size(); 99 | if(numItems == 0) { 100 | // if(verbose) printf("InterpolatorT: not enough samples", t); 101 | return T(); 102 | } 103 | 104 | if(t>1) t = 1; 105 | else if(t<0) t=0; 106 | int i0, i1, i2, i3; 107 | float mu; 108 | 109 | findPosition(t, i1, mu); 110 | 111 | // if less than 4 data points, force linear interpolation 112 | InterpolationType it = _interpolationMethod; 113 | if(numItems<4) it = kInterpolationLinear; 114 | 115 | switch(it) { 116 | case kInterpolationCubic: 117 | i0 = i1 - 1; 118 | i2 = i1 + 1; 119 | i3 = i2 + 1; 120 | 121 | if(i0 < 0) i0 = 0; 122 | if(i3 >= numItems) i3 = numItems-1; 123 | 124 | return cubicInterpolate(at(i0), at(i1), at(i2), at(i3), mu); 125 | break; 126 | 127 | case kInterpolationLinear: 128 | i2 = i1 + 1; 129 | if(i2 >= numItems) i2 = numItems-1; 130 | return linearInterpolate(at(i1), at(i2), mu); 131 | break; 132 | } 133 | } 134 | 135 | //-------------------------------------------------------------- 136 | template 137 | void InterpolatorT::setInterpolation(InterpolationType i) { 138 | _interpolationMethod = i; 139 | updateAllLengths(); 140 | } 141 | 142 | //-------------------------------------------------------------- 143 | template 144 | int InterpolatorT::getInterpolation() const { 145 | return _interpolationMethod; 146 | } 147 | 148 | //-------------------------------------------------------------- 149 | template 150 | void InterpolatorT::setUseLength(bool b) { 151 | _useLength = b; 152 | if(_useLength) updateAllLengths(); 153 | else _dist.clear(); 154 | } 155 | 156 | //-------------------------------------------------------------- 157 | template 158 | bool InterpolatorT::getUseLength() const { 159 | return _useLength; 160 | } 161 | 162 | //-------------------------------------------------------------- 163 | template 164 | const float InterpolatorT::getLength(int i) const { 165 | if(_useLength) { 166 | return i < 0 ? _dist[_dist.size()-1] : _dist.at(i); 167 | } else { 168 | return 0; 169 | } 170 | } 171 | 172 | 173 | //-------------------------------------------------------------- 174 | template 175 | void InterpolatorT::setLengthSubdivisions(int i) { 176 | _lengthSubdivisions = i; 177 | } 178 | 179 | //-------------------------------------------------------------- 180 | template 181 | int InterpolatorT::getLengthSubdivisions() const { 182 | return _lengthSubdivisions; 183 | } 184 | 185 | 186 | //-------------------------------------------------------------- 187 | template 188 | void InterpolatorT::push_back(const T& newData) { 189 | _data.push_back(newData); // add data 190 | 191 | if(getUseLength()) { 192 | float segmentLength; 193 | float totalLength; 194 | 195 | if(size() > 1) { 196 | // T distT = newData - _data.at(prevIndex); // get offset to previous node 197 | // float dist = lengthOf(distT); // actual Length to node 198 | 199 | segmentLength = calcSegmentLength(size()-1); 200 | totalLength = segmentLength + _dist.at(size()-2); 201 | } else { 202 | segmentLength = 0; 203 | totalLength = 0; 204 | } 205 | 206 | _dist.push_back(totalLength); 207 | 208 | // if(verbose) printf("segment length = %f | total length = %f\n", segmentLength, totalLength); 209 | } 210 | } 211 | 212 | //-------------------------------------------------------------- 213 | template 214 | int InterpolatorT::size() const { 215 | return _data.size(); 216 | } 217 | 218 | //-------------------------------------------------------------- 219 | template 220 | void InterpolatorT::reserve(int i) { 221 | _data.reserve(i); 222 | _dist.reserve(i); 223 | } 224 | 225 | //-------------------------------------------------------------- 226 | template 227 | void InterpolatorT::clear() { 228 | _data.clear(); 229 | _dist.clear(); 230 | } 231 | 232 | //-------------------------------------------------------------- 233 | template 234 | const T& InterpolatorT::at(int i) const { 235 | return _data.at(clamp(i, 0, size()-1)); 236 | } 237 | 238 | //-------------------------------------------------------------- 239 | template 240 | vector& InterpolatorT::getData() { 241 | return _data; 242 | } 243 | 244 | //-------------------------------------------------------------- 245 | template 246 | const vector& InterpolatorT::getData() const { 247 | return _data; 248 | } 249 | 250 | //-------------------------------------------------------------- 251 | template 252 | float InterpolatorT::calcSegmentLength(int i) { 253 | ofLogVerbose("msa::InterpolatorT::calcSegmentLength(int i) isn't working anymore"); 254 | int numItems = size(); 255 | 256 | if(numItems < 2 || i < 1 || i >= numItems) return 0; 257 | 258 | bool saveUseLength = _useLength; 259 | _useLength = false; 260 | 261 | float startPerc = (i-1) * 1.0f/(numItems-1); 262 | float endPerc = (i) * 1.0f/(numItems-1); 263 | float incPerc = (endPerc - startPerc)/_lengthSubdivisions; 264 | 265 | T prev = sampleAt(startPerc); 266 | T cur; 267 | 268 | float segmentLength = 0; 269 | for(float f = startPerc; f <= endPerc; f+= incPerc) { 270 | cur = sampleAt(f); 271 | segmentLength += lengthOf(cur - prev); // TODO: this isn't compiling anymore! 272 | prev = cur; 273 | } 274 | 275 | _useLength = saveUseLength; 276 | 277 | if(verbose) printf("segment length for %i is %f\n", i, segmentLength); 278 | 279 | 280 | return segmentLength; 281 | } 282 | 283 | //-------------------------------------------------------------- 284 | template 285 | void InterpolatorT::updateAllLengths() { 286 | _dist.clear(); 287 | 288 | float curTotal = 0; 289 | 290 | for(int i=0; i 300 | void InterpolatorT::findPosition(float t, int &leftIndex, float &mu) const { 301 | int numItems = size(); 302 | 303 | switch(numItems) { 304 | case 0: 305 | leftIndex = 0; 306 | mu = 0; 307 | break; 308 | 309 | case 1: 310 | leftIndex = 0; 311 | mu = 0; 312 | break; 313 | 314 | case 2: 315 | leftIndex = 0; 316 | mu = t; 317 | break; 318 | 319 | default: 320 | if(_useLength) { // need to use 321 | float totalLengthOfInterpolator = _dist.at(numItems-1); 322 | float tDist = totalLengthOfInterpolator * t; // the Length we want to be from the start 323 | int startIndex = floor(t * (numItems - 1)); // start approximation here 324 | int i1 = startIndex; 325 | int limitLeft = 0; 326 | int limitRight = numItems-1; 327 | 328 | float distAt1, distAt2; 329 | // do { 330 | for(int iterations = 0; iterations < 100; iterations ++) { // limit iterations 331 | distAt1 = _dist.at(i1); 332 | if(distAt1 <= tDist) { // if Length at i1 is less than desired Length (this is good) 333 | distAt2 = _dist.at(clamp(i1+1, 0, (int)_dist.size()-1)); 334 | if(distAt2 > tDist) { 335 | leftIndex = i1; 336 | mu = (tDist - distAt1) / (distAt2-distAt1); 337 | return; 338 | } else { 339 | limitLeft = i1; 340 | } 341 | } else { 342 | limitRight = i1; 343 | } 344 | i1 = (limitLeft + limitRight)>>1; 345 | } 346 | // } while(true); 347 | 348 | } else { 349 | float actT = t * (numItems - 1); 350 | leftIndex = floor(actT); 351 | mu = actT - leftIndex; 352 | } 353 | } 354 | } 355 | 356 | 357 | //-------------------------------------------------------------- 358 | template 359 | T InterpolatorT::linearInterpolate(const T& y1, const T& y2, float mu) const { 360 | return (y2-y1) * mu + y1; 361 | } 362 | 363 | 364 | //-------------------------------------------------------------- 365 | // this function is from Paul Bourke's site 366 | // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/ 367 | template 368 | T InterpolatorT::cubicInterpolate(const T& y0, const T& y1, const T& y2, const T& y3, float mu) const { 369 | float mu2 = mu * mu; 370 | T a0 = y3 - y2 - y0 + y1; 371 | T a1 = y0 - y1 - a0; 372 | T a2 = y2 - y0; 373 | T a3 = y1; 374 | 375 | return(a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3); 376 | } 377 | 378 | } --------------------------------------------------------------------------------