Simbody  3.4 (development)
Geo.h
Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATH_GEO_H_
00002 #define SimTK_SIMMATH_GEO_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) 2011-12 Stanford University and the Authors.        *
00013  * Authors: 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 #include "SimTKcommon.h"
00031 #include "simmath/internal/common.h"
00032 
00033 #include <cassert>
00034 #include <cmath>
00035 #include <algorithm>
00036 
00037 namespace SimTK {
00038 
00039 //==============================================================================
00040 //                                    GEO
00041 //==============================================================================
00053 class SimTK_SIMMATH_EXPORT Geo {
00054 public:
00055 template <class P> class Point_;
00056 template <class P> class Sphere_;
00057 template <class P> class LineSeg_;
00058 template <class P> class Line_;
00059 template <class P> class Plane_;
00060 template <class P> class Circle_;
00061 template <class P> class Box_;
00062 template <class P> class AlignedBox_;
00063 template <class P> class OrientedBox_;
00064 template <class P> class Triangle_;
00065 template <class P> class CubicHermiteCurve_;
00066 template <class P> class BicubicHermitePatch_;
00067 template <class P> class CubicBezierCurve_;
00068 template <class P> class BicubicBezierPatch_;
00069 
00070 typedef Point_<Real>        Point;
00071 typedef Sphere_<Real>       Sphere;
00072 typedef LineSeg_<Real>      LineSeg;
00073 typedef Line_<Real>         Line;
00074 typedef Plane_<Real>        Plane;
00075 typedef Circle_<Real>       Circle;
00076 typedef Box_<Real>          Box;
00077 typedef AlignedBox_<Real>   AlignedBox;
00078 typedef OrientedBox_<Real>  OrientedBox;
00079 typedef Triangle_<Real>     Triangle;
00080 typedef CubicHermiteCurve_<Real>    CubicHermiteCurve;
00081 typedef BicubicHermitePatch_<Real>  BicubicHermitePatch;
00082 typedef CubicBezierCurve_<Real>     CubicBezierCurve;
00083 typedef BicubicBezierPatch_<Real>   BicubicBezierPatch;
00084 
00115 template <class RealP, int S> static bool
00116 isCusp(const Vec<3,RealP,S>& Pu) 
00117 {   return Pu.normSqr() < getDefaultTolSqr<RealP>(); }
00118 
00132 template <class RealP, int S> static bool
00133 isInflectionPoint(const Vec<3,RealP,S>& Pu, const Vec<3,RealP,S>& Puu) 
00134 { return (Pu % Puu).normSqr() < getDefaultTolSqr<RealP>(); }
00135 
00139 template <class RealP, int S> static UnitVec<RealP,1> 
00140 calcUnitTangent(const Vec<3,RealP,S>& Pu) {
00141     const RealP dsdu = Pu.norm();               // ~25 flops
00142     SimTK_ERRCHK(dsdu >= getDefaultTol<RealP>(), 
00143         "Geo::calcUnitTangent()", "Unit tangent undefined at a cusp.");
00144 
00145     return UnitVec<RealP,1>(Pu/dsdu, true);     // ~13 flops
00146 }
00147 
00170 template <class RealP, int S> static Vec<3,RealP> 
00171 calcCurvatureVector(const Vec<3,RealP,S>& Pu, const Vec<3,RealP,S>& Puu) {
00172     const RealP Pu2 = Pu.normSqr();                 // (ds/du)^2, 5 flops
00173     SimTK_ERRCHK(Pu2 >= getDefaultTolSqr<RealP>(), 
00174         "Geo::calcCurvatureVector()", "Curvature undefined at a cusp.");
00175     const RealP PuPuu     = dot(Pu,Puu);
00176     const RealP uPrimeSqr = 1/Pu2;                          // ~10 flops
00177     const RealP u2Prime   = -PuPuu * square(uPrimeSqr);     //   8 flops
00178     return uPrimeSqr*Puu + u2Prime*Pu;                      //   9 flops
00179 }
00180 
00191 template <class RealP, int S> static UnitVec<RealP,1> 
00192 calcUnitNormal(const Vec<3,RealP,S>& Pu, const Vec<3,RealP,S>& Puu) {
00193     typedef UnitVec<RealP,1> UnitVec3P;
00194 
00195     const RealP Pu2 = Pu.normSqr();                 // (ds/du)^2, 5 flops
00196     SimTK_ERRCHK(Pu2 >= getDefaultTolSqr<RealP>(), 
00197         "Geo::calcUnitNormal()", "The normal is undefined at a cusp.");
00198 
00199     // Now check if we're at an inflection point, meaning |Pu X Puu|==0.
00200     // Use this handy identity from Struik eq. 3-9 to avoid calculating
00201     // the cross product: (Pu X Puu)^2 = Pu^2Puu^2 - (~Pu*Puu)^2
00202     const RealP Puu2 = Puu.normSqr();                   // 5 flops
00203     const RealP PuPuu = dot(Pu,Puu);                    // 5 flops
00204     const RealP PuXPuu2 = Pu2*Puu2 - square(PuPuu);     // 3 flops
00205     if (PuXPuu2 < getDefaultTolSqr<RealP>())            // 1 flop
00206         return UnitVec3P(Pu).perp();
00207     // Calculate the curvature vector, negate, and normalize.
00208     const RealP uPrimeSqr = 1/Pu2;                      // ~10 flops
00209     const RealP u2Prime   = -PuPuu * square(uPrimeSqr); //   3 flops
00210     const Vec<3,RealP> c = uPrimeSqr*Puu + u2Prime*Pu;  //   9 flops
00211     return UnitVec3P(-c);                               // ~40 flops
00212 }
00213 
00223 template <class RealP, int S> static RealP 
00224 calcCurveFrame(const Vec<3,RealP,S>&    P, 
00225                const Vec<3,RealP,S>&    Pu, 
00226                const Vec<3,RealP,S>&    Puu,
00227                Transform_<RealP>&       X_FP) {
00228     typedef UnitVec<RealP,1> UnitVec3P;
00229 
00230     const RealP Pu2 = Pu.normSqr();                 // (ds/du)^2, 5 flops
00231     SimTK_ERRCHK(Pu2 >= getDefaultTolSqr<RealP>(), 
00232         "Geo::calcCurveFrame()", "Curve frame is undefined at a cusp.");
00233 
00234     // Set the point P(u) as the frame origin.
00235     X_FP.updP() = P;
00236 
00237     // Calculate the unit tangent t, our y axis.
00238     const RealP uPrimeSqr = 1/Pu2;                          // ~10 flops
00239     const RealP uPrime    = std::sqrt(uPrimeSqr);           // ~20 flops
00240     const UnitVec3P t(uPrime*Pu, true);                     //   3 flops 
00241 
00242     // Next calculate unit normal n, our x axis. See calcUnitNormal() above
00243     // for theory.
00244     const RealP Puu2 = Puu.normSqr();                       // 5 flops
00245     const RealP PuPuu = dot(Pu,Puu);                        // 5 flops
00246     const RealP PuXPuu2 = Pu2*Puu2 - square(PuPuu);         // 3 flops
00247     UnitVec3P n; // unit normal
00248     RealP     k; // curvature magnitude
00249     if (PuXPuu2 < getDefaultTolSqr<RealP>()) {              // 1 flop
00250         k = 0;
00251         n = t.perp(); // arbitrary
00252     } else {
00253         // Calculate the curvature vector, negate, and normalize.
00254         const RealP u2Prime = -PuPuu * square(uPrimeSqr);   //   8 flops
00255         const Vec<3,RealP> c = uPrimeSqr*Puu + u2Prime*Pu;  //   9 flops
00256         k = c.norm();                       // curvature >= 0, ~25 flops
00257         n = UnitVec3P((-1/k)*c, true);                      // ~13 flops
00258     }
00259 
00260     // Finally calculate the binormal, our z axis. No need to normalize
00261     // here because n and t are perpendicular unit vectors.
00262     const UnitVec3P b(n % t, true);                      // 9 flops
00263 
00264     // Construct the coordinate frame without normalizing.
00265     X_FP.updR().setRotationFromUnitVecsTrustMe(n,t,b);
00266 
00267     return k;
00268 }
00269 
00282 template <class RealP, int S> static RealP
00283 calcCurvatureSqr(const Vec<3,RealP,S>& Pu, const Vec<3,RealP,S>& Puu) {
00284     const RealP Pu2 = Pu.normSqr();   // (ds/du)^2, 5 flops
00285     SimTK_ERRCHK(Pu2 >= getDefaultTolSqr<RealP>(), 
00286         "Geo::calcCurvatureSqr()", "Curvature is undefined at a cusp.");
00287     const RealP num = cross(Pu,Puu).normSqr();      //  14 flops
00288     const RealP den = cube(Pu2);                    //   2 flops
00289     return num/den;                                 // ~10 flops
00290 }
00291 
00305 template <class RealP, int S> static RealP
00306 calcTorsion(const Vec<3,RealP,S>& Pu, const Vec<3,RealP,S>& Puu, 
00307             const Vec<3,RealP,S>& Puuu) {
00308     const Vec<3,RealP> PuXPuu = cross(Pu,Puu);              //   9 flops
00309     const RealP PuXPuu2 = PuXPuu.normSqr();                 //   5 flops  
00310     SimTK_ERRCHK(PuXPuu2 >= getDefaultTolSqr<RealP>(), "Geo::calcTorsion()", 
00311         "Torsion is undefined at a cusp or inflection point.");
00312     const RealP num = dot(PuXPuu, Puuu);                    //   5 flops
00313     return num/PuXPuu2;                                     // ~10 flops
00314 }
00338 template <class RealP> static void
00339 findClosestPointsOfTwoLines
00340    (const Vec<3,RealP>& p0, const UnitVec<RealP,1>& d0,
00341     const Vec<3,RealP>& p1, const UnitVec<RealP,1>& d1,
00342     Vec<3,RealP>& x0, Vec<3,RealP>& x1, bool& linesAreParallel)
00343 {
00344     const Vec<3,RealP> w = p1-p0; // vector from p0 to p1; 3 flops
00345     const RealP s2Theta = (d0 % d1).normSqr(); // sin^2(angle); 14 flops
00346     const RealP d =  dot(w,d0);     // 5 flops
00347     const RealP e = -dot(w,d1);     // 6 flops
00348 
00349     RealP t0, t1; // line parameters of closest points
00350     if (s2Theta < square(NTraits<RealP>::getSignificant())) { // 3 flops
00351         // Lines are parallel. Return a point on each line midway between
00352         // the origin points.
00353         linesAreParallel = true; // parallel
00354         t0 = d/2; t1 = e/2;      // 2 flops
00355     } else {
00356         linesAreParallel = false;
00357         const RealP cTheta = dot(d0,d1); // cos(angle between lines); 5 flops
00358         const RealP oos2Theta = 1/s2Theta; // about 10 flops
00359         t0 = (e*cTheta + d) * oos2Theta;   // 3 flops
00360         t1 = (d*cTheta + e) * oos2Theta;   // 3 flops
00361     }
00362 
00363     x0 = p0 + t0*d0;    // 6 flops
00364     x1 = p1 + t1*d1;    // 6 flops
00365 }
00366 
00376 template <class RealP> static RealP getDefaultTol() 
00377 {   return NTraits<RealP>::getSignificant(); }
00380 template <class RealP> static RealP getDefaultTolSqr()
00381 {   return square(getDefaultTol<RealP>()); }
00382 
00385 template <class RealP> static RealP getEps() 
00386 {   return NTraits<RealP>::getEps(); }
00388 template <class RealP> static RealP getNaN() 
00389 {   return NTraits<RealP>::getNaN(); }
00391 template <class RealP> static RealP getInfinity() 
00392 {   return NTraits<RealP>::getInfinity(); }
00393 
00398 template <class RealP> static RealP stretchBy(RealP length, RealP tol) {
00399     SimTK_ERRCHK2(tol >= getEps<RealP>(), "Geo::stretchBy()",
00400         "The supplied tolerance %g is too small; must be at least %g"
00401         " for significance at this precision.", 
00402         (double)tol, (double)getEps<RealP>());
00403 
00404     return length + std::max(length*tol, tol);
00405 }
00406 
00409 template <class RealP> static RealP stretch(RealP length)
00410 {   return stretchBy(length, getDefaultTol<RealP>()); }
00411 
00414 };
00415 
00416 
00417 } // namespace SimTK
00418 
00419 #endif // SimTK_SIMMATH_GEO_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines