/* * Copyright (c) 2014 Oculus Info Inc. * http://www.oculusinfo.com/ * * Released under the MIT License. * * 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: * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * 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. */ package com.oculusinfo.geometry.cartesian; import com.oculusinfo.math.linearalgebra.Vector; import java.util.ArrayList; import java.util.List; public class Spline { private boolean _periodic; private int _n; private List<Vector> _points; private List<Double> _times; public Spline (boolean periodic) { _periodic = periodic; _points = new ArrayList<Vector>(); _times = new ArrayList<Double>(); _n = 0; } // TODO: // (1) Create a spline through a given set of points (requires tridiagonal matrix) // http://www.particleincell.com/2012/bezier-splines/ // (2) Implement distance algorithm for splines // (3) Implement mean algorithm for splines /** * Add a new control point into the spline, in the proper order. * * @param time * The time at which the point occurs * @param point * The point to add */ public void addPoint (double time, Vector point) { // Figure out at what index to add the time for (int i = 0; i < _n; ++i) { if (time < _times.get(i)) { // Add before point i. _points.add(i, point); _times.add(i, time); ++_n; return; } } // New last point _points.add(point); _times.add(time); ++_n; } /* * This method only exists to use the _periodic field, which is here for * future expansion, and isn't actually used yet. */ protected boolean isPeriodic () { return _periodic; } /* * Get t_i for a given i */ private double t (int i) { if (i < 0) throw new IndexOutOfBoundsException("Can't get t_i for i<0"); if (i >= _times.size()) throw new IndexOutOfBoundsException("Can't get t_i for i>n (i="+i+", n="+_n+")"); double t0 = _times.get(0); double tn = _times.get(_times.size()-1); double ti = _times.get(i); return (ti-t0)/(tn-t0); } /* * Get the i at which t lies between t_floor(i) and t_ceil(i) */ protected double i (double t) { if (t < 0) throw new IndexOutOfBoundsException("Attempt to get i for t<0"); if (t >= 1) throw new IndexOutOfBoundsException("Attempt to get i for t>1"); double lastti = 0; for (int i=0; i<_times.size(); ++i) { double ti = t(i); if (ti > t) { return i + (t-lastti)/(ti-lastti); } } // should never get here throw new RuntimeException("Weird i-calculation error in spline calculation - no valid i found"); } }