Simbody
3.4 (development)
|
00001 #ifndef SimTK_SIMMATH_SPLINE_H_ 00002 #define SimTK_SIMMATH_SPLINE_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKmath * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2008-13 Stanford University and the Authors. * 00013 * Authors: Peter Eastman * 00014 * Contributors: Michael Sherman * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 #include "SimTKcommon.h" 00028 #include "simmath/internal/common.h" 00029 #include "simmath/internal/GCVSPLUtil.h" 00030 00031 #include <limits> 00032 00033 namespace SimTK { 00034 00051 template <class T> 00052 class Spline_ : public Function_<T> { 00053 public: 00064 Spline_(int degree, const Vector& x, const Vector_<T>& y) 00065 : impl(new SplineImpl(degree, x, y)) {} 00066 00069 Spline_() : impl(NULL) {} 00070 00073 Spline_(const Spline_& source) : impl(source.impl) 00074 { if (impl) impl->referenceCount++; } 00075 00078 Spline_& operator=(const Spline_& source) { 00079 if (impl) { 00080 impl->referenceCount--; 00081 if (impl->referenceCount == 0) 00082 delete impl; 00083 } 00084 impl = source.impl; 00085 if (impl) impl->referenceCount++; 00086 return *this; 00087 } 00088 00091 ~Spline_() { 00092 if (impl) { 00093 impl->referenceCount--; 00094 if (impl->referenceCount == 0) 00095 delete impl; 00096 } 00097 } 00098 00103 T calcValue(Real x) const { 00104 assert(impl); 00105 return impl->getValue(x); 00106 } 00107 00118 T calcDerivative(int order, Real x) const { 00119 assert(impl); 00120 assert(order > 0); 00121 return impl->getDerivative(order, x); 00122 } 00123 00126 const Vector& getControlPointLocations() const { 00127 assert(impl); 00128 return impl->x; 00129 } 00132 const Vector_<T>& getControlPointValues() const { 00133 assert(impl); 00134 return impl->y; 00135 } 00136 00138 int getSplineDegree() const { 00139 assert(impl); 00140 return impl->degree; 00141 } 00142 00145 T calcValue(const Vector& x) const OVERRIDE_11 { 00146 assert(x.size() == 1); 00147 return calcValue(x[0]); 00148 } 00155 T calcDerivative(const Array_<int>& derivComponents, const Vector& x) const 00156 OVERRIDE_11 00157 { assert(x.size() == 1); 00158 return calcDerivative((int)derivComponents.size(), x[0]); } 00161 T calcDerivative(const std::vector<int>& derivComponents, 00162 const Vector& x) const 00163 { assert(x.size() == 1); 00164 return calcDerivative((int)derivComponents.size(), x[0]); } 00165 00167 int getArgumentSize() const OVERRIDE_11 {return 1;} 00169 int getMaxDerivativeOrder() const OVERRIDE_11 00170 { return std::numeric_limits<int>::max(); } 00171 00172 private: 00173 class SplineImpl; 00174 SplineImpl* impl; 00175 }; 00176 00178 typedef Spline_<Real> Spline; 00179 00181 template <class T> 00182 class Spline_<T>::SplineImpl { 00183 public: 00184 SplineImpl(int degree, const Vector& x, const Vector_<T>& y) 00185 : referenceCount(1), degree(degree), x(x), y(y) {} 00186 ~SplineImpl() { 00187 assert(referenceCount == 0); 00188 } 00189 T getValue(Real t) const { 00190 return GCVSPLUtil::splder(0, degree, t, x, y); 00191 } 00192 T getDerivative(int derivOrder, Real t) const { 00193 return GCVSPLUtil::splder(derivOrder, degree, t, x, y); 00194 } 00195 int referenceCount; 00196 int degree; 00197 Vector x; 00198 Vector_<T> y; 00199 }; 00200 00201 } // namespace SimTK 00202 00203 #endif // SimTK_SIMMATH_SPLINE_H_ 00204 00205