Simbody
3.4 (development)
|
00001 #ifndef SimTK_SIMMATH_GEODESIC_H_ 00002 #define SimTK_SIMMATH_GEODESIC_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) 2012 Stanford University and the Authors. * 00013 * Authors: Ian Stavness, Michael Sherman * 00014 * Contributors: * 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 00030 //============================================================================== 00031 // GEODESIC CLASS 00032 //============================================================================== 00033 00034 00035 #include "SimTKcommon.h" 00036 #include "simmath/internal/common.h" 00037 00038 namespace SimTK { 00039 00051 class SimTK_SIMMATH_EXPORT Geodesic { 00052 public: 00054 Geodesic() {clear();} 00055 00056 int getNumPoints() const {return (int)frenetFrames.size(); } 00057 00066 const Array_<Transform>& getFrenetFrames() const {return frenetFrames;} 00067 Array_<Transform>& updFrenetFrames() {return frenetFrames;} 00068 void addFrenetFrame(const Transform& Kf) {frenetFrames.push_back(Kf);} 00069 00070 Array_<Real>& updArcLengths() {return arcLengths;} 00071 const Array_<Real>& getArcLengths() const {return arcLengths;} 00072 void addArcLength(Real s) {arcLengths.push_back(s);} 00073 00074 Array_<Real>& updCurvatures() {return curvature;} 00075 const Array_<Real>& getCurvatures() const {return curvature;} 00076 void addCurvature(Real kappa) {curvature.push_back(kappa);} 00077 00078 Array_<Vec2>& updDirectionalSensitivityPtoQ() 00079 { return directionalSensitivityPtoQ; } 00080 const Array_<Vec2>& getDirectionalSensitivityPtoQ() const 00081 { return directionalSensitivityPtoQ; } 00082 void addDirectionalSensitivityPtoQ(const Vec2& jP) { 00083 directionalSensitivityPtoQ.push_back(jP); 00084 } 00085 00086 Array_<Vec2>& updDirectionalSensitivityQtoP() 00087 { return directionalSensitivityQtoP; } 00088 const Array_<Vec2>& getDirectionalSensitivityQtoP() const 00089 { return directionalSensitivityQtoP; } 00090 void addDirectionalSensitivityQtoP(const Vec2& jQ) { 00091 directionalSensitivityQtoP.push_back(jQ); 00092 } 00093 00094 Array_<Vec2>& updPositionalSensitivityPtoQ() 00095 { return positionalSensitivityPtoQ; } 00096 const Array_<Vec2>& getPositionalSensitivityPtoQ() const 00097 { return positionalSensitivityPtoQ; } 00098 void addPositionalSensitivityPtoQ(const Vec2& jtP) { 00099 positionalSensitivityPtoQ.push_back(jtP); 00100 } 00101 00102 Array_<Vec2>& updPositionalSensitivityQtoP() 00103 { return positionalSensitivityQtoP; } 00104 const Array_<Vec2>& getPositionalSensitivityQtoP() const 00105 { return positionalSensitivityQtoP; } 00106 void addPositionalSensitivityQtoP(const Vec2& jtQ) { 00107 positionalSensitivityQtoP.push_back(jtQ); 00108 } 00109 00110 void setTorsionAtP(Real tauP) {torsionAtP = tauP;} 00111 void setTorsionAtQ(Real tauQ) {torsionAtQ = tauQ;} 00112 void setBinormalCurvatureAtP(Real muP) {binormalCurvatureAtP = muP;} 00113 void setBinormalCurvatureAtQ(Real muQ) {binormalCurvatureAtQ = muQ;} 00114 00117 Real getLength() const {return arcLengths.empty() ? 0 : arcLengths.back();} 00118 00124 Real calcLengthDot(const Vec3& xdotP, const Vec3& xdotQ) const 00125 { return ~xdotQ*getTangentQ() - ~xdotP*getTangentP(); } 00126 00129 const Vec3& getPointP() const {return frenetFrames.front().p();} 00132 const Vec3& getPointQ() const {return frenetFrames.back().p();} 00133 00137 const UnitVec3& getNormalP() const {return frenetFrames.front().z();} 00141 const UnitVec3& getNormalQ() const {return frenetFrames.back().z();} 00142 00145 const UnitVec3& getTangentP() const {return frenetFrames.front().y();} 00148 const UnitVec3& getTangentQ() const {return frenetFrames.back().y();} 00149 00152 const UnitVec3& getBinormalP() const {return frenetFrames.front().x();} 00155 const UnitVec3& getBinormalQ() const {return frenetFrames.back().x();} 00156 00162 Real getCurvatureP() const {return curvature.front();} 00170 Real getCurvatureQ() const {return curvature.back();} 00171 00176 Real getTorsionP() const {return torsionAtP;} 00181 Real getTorsionQ() const {return torsionAtQ;} 00182 00186 Real getBinormalCurvatureP() const {return binormalCurvatureAtP;} 00190 Real getBinormalCurvatureQ() const {return binormalCurvatureAtQ;} 00191 00197 Real getJacobiP() const {return directionalSensitivityQtoP.front()[0];} 00203 Real getJacobiQ() const {return directionalSensitivityPtoQ.back()[0];} 00204 00207 // Note sign change here -- we calculated this by integrating backwards 00208 // so the arc length we used had the opposite sign from the true arc 00209 // length parameter. 00210 Real getJacobiPDot() const {return -directionalSensitivityQtoP.front()[1];} 00213 Real getJacobiQDot() const {return directionalSensitivityPtoQ.back()[1];} 00214 00215 // XXX testing 00216 Real getJacobiTransP() const {return positionalSensitivityQtoP.front()[0];} 00217 Real getJacobiTransQ() const {return positionalSensitivityPtoQ.back()[0];} 00218 Real getJacobiTransPDot() const {return -positionalSensitivityQtoP.front()[1];} 00219 Real getJacobiTransQDot() const {return positionalSensitivityPtoQ.back()[1];} 00220 00223 void clear() { 00224 arcLengths.clear(); 00225 frenetFrames.clear(); 00226 directionalSensitivityPtoQ.clear(); 00227 directionalSensitivityQtoP.clear(); 00228 positionalSensitivityPtoQ.clear(); 00229 positionalSensitivityQtoP.clear(); 00230 curvature.clear(); 00231 torsionAtP = torsionAtQ = NaN; 00232 binormalCurvatureAtP = binormalCurvatureAtQ = NaN; 00233 convexFlag = shortestFlag = false; 00234 initialStepSizeHint = achievedAccuracy = NaN; 00235 } 00236 00237 void setIsConvex(bool isConvex) {convexFlag = isConvex;} 00238 void setIsShortest(bool isShortest) {shortestFlag = isShortest;} 00239 void setInitialStepSizeHint(Real sz) {initialStepSizeHint=sz;} 00240 void setAchievedAccuracy(Real acc) {achievedAccuracy=acc;} 00241 00242 bool isConvex() const {return convexFlag;} 00243 bool isShortest() const {return shortestFlag;} 00244 Real getInitialStepSizeHint() const {return initialStepSizeHint;} 00245 Real getAchievedAccuracy() const {return achievedAccuracy;} 00246 00247 void dump(std::ostream& o) const; 00248 00249 private: 00250 // All these arrays are the same length when the geodesic is complete. 00251 Array_<Real> arcLengths; // arc length coord corresponding to point 00252 Array_<Transform> frenetFrames; // see above for more info 00253 Array_<Vec2> directionalSensitivityPtoQ; // jQ and jQdot 00254 Array_<Vec2> directionalSensitivityQtoP; // jP and -jPdot 00255 Array_<Vec2> positionalSensitivityPtoQ; // jtQ and jtQdot 00256 Array_<Vec2> positionalSensitivityQtoP; // jtP and -jtPdot 00257 Array_<Real> curvature; // normal curvature kappa in tangent direction 00258 // These are only calculated at the end points. 00259 Real torsionAtP, torsionAtQ; // torsion tau (only at ends) 00260 Real binormalCurvatureAtP, binormalCurvatureAtQ; 00261 00262 // This flag is set true if curvature[i]>=0 for all i. 00263 bool convexFlag; // is this geodesic over a convex surface? 00264 00265 bool shortestFlag; // XXX is this geodesic the shortest one of the surface? 00266 Real initialStepSizeHint; // the initial step size to be tried when integrating this geodesic 00267 Real achievedAccuracy; // the accuracy to which this geodesic curve has been calculated 00268 }; 00269 00270 00274 class GeodesicDecorator : public DecorationGenerator { 00275 public: 00276 GeodesicDecorator(const Geodesic& geod, const Vec3& color) : 00277 m_geod(geod), m_color(color) { } 00278 00279 virtual void generateDecorations(const State& state, 00280 Array_<DecorativeGeometry>& geometry) { 00281 // m_system.realize(state, Stage::Position); 00282 00283 // draw connected line segments from pts 00284 const Array_<Transform>& Kfs = m_geod.getFrenetFrames(); 00285 Vec3 prevPt; 00286 for (int i = 0; i < (int) Kfs.size(); ++i) { 00287 Vec3 cur = Kfs[i].p(); 00288 if (i > 0) { 00289 geometry.push_back( 00290 DecorativeLine(prevPt, cur) 00291 .setColor(m_color) 00292 .setLineThickness(3)); 00293 } 00294 prevPt = cur; 00295 00296 geometry.push_back(DecorativeFrame(Real(.2)).setTransform(Kfs[i])); 00297 } 00298 } 00299 00300 private: 00301 const Geodesic& m_geod; 00302 const Vec3& m_color; 00303 }; 00304 00305 00306 00307 00311 class GeodesicOptions { 00312 // XXX stub 00313 }; 00314 00315 00316 } // namespace SimTK 00317 00318 #endif // SimTK_SIMMATH_GEODESIC_H_