Simbody  3.7
SimTK::Geo Class Reference

The Geo class collects geometric primitives intended to deal with raw, fixed-size geometric shapes occupying minimal memory and providing maximum performance through small inline methods and larger high performance algorithms. More...

Classes

class  AlignedBox_
 A 3d box aligned with an unspecified frame F and centered at a given point measured from that frame's origin. More...
 
class  BicubicBezierPatch_
 A primitive useful for computations involving a single bicubic Bezier patch. More...
 
class  BicubicHermitePatch_
 A primitive useful for computations involving a single bicubic Hermite patch. More...
 
class  Box_
 A 3d rectangular box aligned with an unspecified frame F and centered at that frame's origin. More...
 
class  Circle_
 
class  CubicBezierCurve_
 This is a primitive useful for computations involving a single cubic Bezier curve segment. More...
 
class  CubicHermiteCurve_
 A primitive useful for computations involving a single cubic Hermite curve segment in algebraic or geometric (Hermite) form. More...
 
class  Line_
 
class  LineSeg_
 A 3d line segment primitive represented by its end points in an unspecified frame, and a collection of line segment-related utility methods. More...
 
class  OrientedBox_
 TODO: A 3d box oriented and positioned with respect to an unspecified frame F. More...
 
class  Plane_
 
class  Point_
 A 3d point primitive represented by a Vec3 from the origin of an unspecified frame, and a collection of point-related utility methods. More...
 
class  Sphere_
 A geometric primitive representing a sphere by its radius and center point, and a collection of sphere-related utility methods. More...
 
class  Triangle_
 A geometric primitive representing a triangle by its vertices as points in some unspecified frame, and a collection of triangle-related utility methods. More...
 

Public Types

typedef Point_< RealPoint
 
typedef Sphere_< RealSphere
 
typedef LineSeg_< RealLineSeg
 
typedef Line_< RealLine
 
typedef Plane_< RealPlane
 
typedef Circle_< RealCircle
 
typedef Box_< RealBox
 
typedef AlignedBox_< RealAlignedBox
 
typedef OrientedBox_< RealOrientedBox
 
typedef Triangle_< RealTriangle
 
typedef CubicHermiteCurve_< RealCubicHermiteCurve
 
typedef BicubicHermitePatch_< RealBicubicHermitePatch
 
typedef CubicBezierCurve_< RealCubicBezierCurve
 
typedef BicubicBezierPatch_< RealBicubicBezierPatch
 

Static Public Member Functions

Differential geometry of curve segments

These methods calculate geometric quantities from given parametric ones, in an arbitrary parameter u, such that points on the curve segment are given by P(u), with 0<=u<=1.

We consider the direction of increasing arc length to be the same as the direction of u. These are utility methods that can be used with any parametric curve. The idea is that you use the curve evaluators to determine the arguments here, using the same u value for each of them. If you don't use the same u value you'll get meaningless results.

The primary reference for this material is the book "Lectures on Classical Differential Geometry, 2nd ed." (chapter 1) by Dirk Struik, 1961, republished by Dover in 1988. Notation and equation numbers are from that reference. Two exceptions: (1) we use c for the curvature vector rather than Struik's bold k, so we can use k for the scalar value of curvature, and (2) we define the curve normal n to point away (outward) from the center of curvature, while Struik defined it to point inward. Using our definition, if you have a parametric circle the normal points towards the outside, which is more conventional and analogous to surface normals. Our right-handed curve frame is thus x,y,z=n,t,b rather than Struik's "moving trihedron" frame t,n,b. For us the binormal b=n X t, while with Struik's definition it is t X n. Note that only the normal is reversed from Struik's, the tangent and binormal vectors are the same.

template<class RealP , int S>
static bool isCusp (const Vec< 3, RealP, S > &Pu)
 Given the parametric derivative Pu(u)=dP/du, determine whether the point P(u) is at a cusp, that is, a place where the arc length s does not change when parameter u does, so ds/du=0 (within tolerance). More...
 
template<class RealP , int S>
static bool isInflectionPoint (const Vec< 3, RealP, S > &Pu, const Vec< 3, RealP, S > &Puu)
 Given the parametric derivatives Pu(u)=dP/du, and Puu(u)=d2P/du2 determine whether point P(u) is at an inflection point on the curve, that is, a flat place where there is no curvature (within tolerance). More...
 
template<class RealP , int S>
static UnitVec< RealP, 1 > calcUnitTangent (const Vec< 3, RealP, S > &Pu)
 Calculate the unit tangent vector t=dP/ds, given Pu=dP/du. More...
 
template<class RealP , int S>
static Vec< 3, RealP > calcCurvatureVector (const Vec< 3, RealP, S > &Pu, const Vec< 3, RealP, S > &Puu)
 Return the curvature vector c=dt/ds=d2P/ds2, given Pu=dP/du and Puu=d2P/du2. More...
 
template<class RealP , int S>
static UnitVec< RealP, 1 > calcUnitNormal (const Vec< 3, RealP, S > &Pu, const Vec< 3, RealP, S > &Puu)
 In our definition, the unit normal vector n points in the "outward" direction, that is, it points away from the center of curvature (opposite the curvature vector c so n=-c/|c|). More...
 
template<class RealP , int S>
static RealP calcCurveFrame (const Vec< 3, RealP, S > &P, const Vec< 3, RealP, S > &Pu, const Vec< 3, RealP, S > &Puu, Transform_< RealP > &X_FP)
 Return the the curvature k (always positive), and a frame whose origin is a point along the curve, x axis is the outward unit normal n, y is the unit tangent t, and z=x X y is the binormal b, which is a normal to the osculating plane. More...
 
template<class RealP , int S>
static RealP calcCurvatureSqr (const Vec< 3, RealP, S > &Pu, const Vec< 3, RealP, S > &Puu)
 Return k^2, the square of the scalar curvature k, given Pu=dP/du and Puu=d2P/du2. More...
 
template<class RealP , int S>
static RealP calcTorsion (const Vec< 3, RealP, S > &Pu, const Vec< 3, RealP, S > &Puu, const Vec< 3, RealP, S > &Puuu)
 Return tau, the torsion or "second curvature" given Pu=dP/du, Puu=d2P/du2, Puuu=d3P/du3. More...
 
Lines
template<class RealP >
static void findClosestPointsOfTwoLines (const Vec< 3, RealP > &p0, const UnitVec< RealP, 1 > &d0, const Vec< 3, RealP > &p1, const UnitVec< RealP, 1 > &d1, Vec< 3, RealP > &x0, Vec< 3, RealP > &x1, bool &linesAreParallel)
 Find the points of closest approach on two lines L0 and L1, each represented by an origin point and a direction. More...
 
Miscellaneous utilities
template<class RealP >
static RealP getDefaultTol ()
 Return the default tolerance to use for degeneracy tests and other tests for "too small" or "near enough" that arise in dealing with geometry primitives. More...
 
template<class RealP >
static RealP getDefaultTolSqr ()
 Returns the square of the default tolerance. More...
 
template<class RealP >
static RealP getEps ()
 Return machine precision for floating point calculations at precision RealP. More...
 
template<class RealP >
static RealP getNaN ()
 Return a NaN (not a number) at precision RealP. More...
 
template<class RealP >
static RealP getInfinity ()
 Return Infinity at precision RealP. You can negate this for -Infinity. More...
 
template<class RealP >
static RealP stretchBy (RealP length, RealP tol)
 Stretch a dimension by a given tolerance amount. More...
 
template<class RealP >
static RealP stretch (RealP length)
 Stretch a dimension using the default tolerance for this precision as the tolerance in stretchBy(). More...
 

Detailed Description

The Geo class collects geometric primitives intended to deal with raw, fixed-size geometric shapes occupying minimal memory and providing maximum performance through small inline methods and larger high performance algorithms.

Subclasses collect algorithms relevant to particular shapes. There are no virtual methods or class hierarchies here; each subclass is a "POD" (plain old data) class. The general idea is to make it so that these common methods are implemented in only one place in Simbody.

The Geo class itself is dataless and provides only static methods. It is also used as a namespace for geometric primitives to allow these names to be used elsewhere for more significant objects.

Member Typedef Documentation

◆ Point

◆ Sphere

◆ LineSeg

◆ Line

◆ Plane

◆ Circle

◆ Box

◆ AlignedBox

◆ OrientedBox

◆ Triangle

◆ CubicHermiteCurve

◆ BicubicHermitePatch

◆ CubicBezierCurve

◆ BicubicBezierPatch

Member Function Documentation

◆ isCusp()

template<class RealP , int S>
static bool SimTK::Geo::isCusp ( const Vec< 3, RealP, S > &  Pu)
inlinestatic

Given the parametric derivative Pu(u)=dP/du, determine whether the point P(u) is at a cusp, that is, a place where the arc length s does not change when parameter u does, so ds/du=0 (within tolerance).

Note that an inflection point, where the curvature is zero, is not a cusp; see isInflectionPoint(). Cost is 6 flops.

◆ isInflectionPoint()

template<class RealP , int S>
static bool SimTK::Geo::isInflectionPoint ( const Vec< 3, RealP, S > &  Pu,
const Vec< 3, RealP, S > &  Puu 
)
inlinestatic

Given the parametric derivatives Pu(u)=dP/du, and Puu(u)=d2P/du2 determine whether point P(u) is at an inflection point on the curve, that is, a flat place where there is no curvature (within tolerance).

We will also return true if this point is a cusp, where curvature is not defined. Cost is 15 flops.

Theory

If Puu is zero or parallel to Pu (meaning it changes the parametric tangent's length but not its direction) then we are at an inflection point. We consider a cusp to be an inflection point even though curvature is undefined there, so we define an inflection point to be any place where |Pu X Puu|==0 to within tolerance.

See also
isCusp()

◆ calcUnitTangent()

template<class RealP , int S>
static UnitVec<RealP,1> SimTK::Geo::calcUnitTangent ( const Vec< 3, RealP, S > &  Pu)
inlinestatic

Calculate the unit tangent vector t=dP/ds, given Pu=dP/du.

This is undefined at a cusp (Pu==0). See Struik, eq. 2-2. Cost is about 40 flops.

◆ calcCurvatureVector()

template<class RealP , int S>
static Vec<3,RealP> SimTK::Geo::calcCurvatureVector ( const Vec< 3, RealP, S > &  Pu,
const Vec< 3, RealP, S > &  Puu 
)
inlinestatic

Return the curvature vector c=dt/ds=d2P/ds2, given Pu=dP/du and Puu=d2P/du2.

This vector points towards the center of curvature, with length equal to the magnitude of the curvature (it's not a unit vector). Curvature is undefined at a cusp (where Pu==0). Since we define the curve unit normal n to point away from the center of curvature (see above), we have c=-k*n where k is the (scalar) curvature. Cost is about 30 flops.

Theory

See Struik, eqn. 4-3, 4-4. Let prime denote differentiation with respect to arclength:

    u' = du/ds = 1/|Pu|
    u'' = -(~Pu Puu)/Pu^4 = -(~Pu Puu) * u'^4
    t = P' = Pu u' = Pu/|Pu|
    c = t' = P'' = Puu u'^2 + Pu u''
      = Puu/Pu^2 - Pu (~Pu Puu)/Pu^4
      = -k * n, k is signed curvature, n is unit normal

Note that c can be used to determine the magnitude |k|, but you can't get the sign until the normal n has been defined. We're going to define n from c, so that n=-c/|c| so dot(c,n) is always negative meaning that k is always positive for us.

◆ calcUnitNormal()

template<class RealP , int S>
static UnitVec<RealP,1> SimTK::Geo::calcUnitNormal ( const Vec< 3, RealP, S > &  Pu,
const Vec< 3, RealP, S > &  Puu 
)
inlinestatic

In our definition, the unit normal vector n points in the "outward" direction, that is, it points away from the center of curvature (opposite the curvature vector c so n=-c/|c|).

This convention is the opposite of Struik's, where he has the normal point in the same direction as the curvature vector. The normal is undefined at a cusp (Pu(u)==0), and is an arbitrary perpendicular to the tangent at an inflection point (a flat place where there is no curvature, i.e. |Pu(u) X Puu(u)|==0). If the curve is a straight line then every point is an inflection point, so the normal is arbitrary everywhere. Cost is about 80 flops.

See also
calcCurvatureVector() for theory.

◆ calcCurveFrame()

template<class RealP , int S>
static RealP SimTK::Geo::calcCurveFrame ( const Vec< 3, RealP, S > &  P,
const Vec< 3, RealP, S > &  Pu,
const Vec< 3, RealP, S > &  Puu,
Transform_< RealP > &  X_FP 
)
inlinestatic

Return the the curvature k (always positive), and a frame whose origin is a point along the curve, x axis is the outward unit normal n, y is the unit tangent t, and z=x X y is the binormal b, which is a normal to the osculating plane.

So the vectors n,t,b form a right-handed set; this convention is different from Struik's since he has n pointing the opposite direction. This frame is undefined at a cusp (Pu==0), and the normal is arbitrary at an inflection point (|Pu(u) X Puu(u)|==0) or if the curve is a line. Cost is about 115 flops.

◆ calcCurvatureSqr()

template<class RealP , int S>
static RealP SimTK::Geo::calcCurvatureSqr ( const Vec< 3, RealP, S > &  Pu,
const Vec< 3, RealP, S > &  Puu 
)
inlinestatic

Return k^2, the square of the scalar curvature k, given Pu=dP/du and Puu=d2P/du2.

Using our definition for the curve normal n (see above), k is always positive so the curvature is the positive square root of the value returned here. Curvature is undefined at a cusp (where Pu==0) and is zero at an inflection point (|Pu X Puu|==0). Cost is about 30 flops.

Theory

                  |Pu X Puu|^2
    k^2 = |c|^2 = ------------
                     |Pu|^6

See Struik, pg. 17, eq. 5-5a.

◆ calcTorsion()

template<class RealP , int S>
static RealP SimTK::Geo::calcTorsion ( const Vec< 3, RealP, S > &  Pu,
const Vec< 3, RealP, S > &  Puu,
const Vec< 3, RealP, S > &  Puuu 
)
inlinestatic

Return tau, the torsion or "second curvature" given Pu=dP/du, Puu=d2P/du2, Puuu=d3P/du3.

Torsion is a signed quantity related to the rate of change of the osculating plane binormal b, with db/ds=tau*n where n is the "outward" unit normal (see above). Torsion is undefined at either a cusp (where Pu==0) or an inflection point (where |Pu X Puu|==0). Cost is about 30 flops.

Theory

          ~(Pu X Puu) * Puuu
    tau = ------------------
             |Pu X Puu|^2

See Struik, pg. 17, eq. 5-5b and discussion on page 16.

◆ findClosestPointsOfTwoLines()

template<class RealP >
static void SimTK::Geo::findClosestPointsOfTwoLines ( const Vec< 3, RealP > &  p0,
const UnitVec< RealP, 1 > &  d0,
const Vec< 3, RealP > &  p1,
const UnitVec< RealP, 1 > &  d1,
Vec< 3, RealP > &  x0,
Vec< 3, RealP > &  x1,
bool &  linesAreParallel 
)
inlinestatic

Find the points of closest approach on two lines L0 and L1, each represented by an origin point and a direction.

Points and vectors must be in a common frame. We return point x0 on L0 and x1 on L1 such that the distance |x1-x0| is the smallest for any points on the two lines. If the lines are parallel or nearly so (all points same distance) we'll pick the point on each line closest to midway between the origins as the closest points and return an indication that the returned points weren't unique.

Parameters
[in]p0The origin point of line L0, that is, any point through which line L0 passes.
[in]d0A unit vector giving the direction of L0.
[in]p1The origin point of line L1.
[in]d1A unit vector giving the direction of L1.
[out]x0The point of L0 that is closest to L1.
[out]x1The point of L1 that is closest to L0.
[out]linesAreParallelTrue if the lines were treated as effectively parallel.

Cost is about 65 flops.

◆ getDefaultTol()

template<class RealP >
static RealP SimTK::Geo::getDefaultTol ( )
inlinestatic

Return the default tolerance to use for degeneracy tests and other tests for "too small" or "near enough" that arise in dealing with geometry primitives.

The value depends on the precision being used; we use the SimTK constant SignificantReal which is eps^(7/8) where eps is the resolution of the template argument RealP (which must be float or double) That makes this tolerance around 2e-14 in double precision and 9e-7 in float.

◆ getDefaultTolSqr()

template<class RealP >
static RealP SimTK::Geo::getDefaultTolSqr ( )
inlinestatic

Returns the square of the default tolerance.

See also
getDefaultTol()

◆ getEps()

template<class RealP >
static RealP SimTK::Geo::getEps ( )
inlinestatic

Return machine precision for floating point calculations at precision RealP.

◆ getNaN()

template<class RealP >
static RealP SimTK::Geo::getNaN ( )
inlinestatic

Return a NaN (not a number) at precision RealP.

◆ getInfinity()

template<class RealP >
static RealP SimTK::Geo::getInfinity ( )
inlinestatic

Return Infinity at precision RealP. You can negate this for -Infinity.

◆ stretchBy()

template<class RealP >
static RealP SimTK::Geo::stretchBy ( RealP  length,
RealP  tol 
)
inlinestatic

Stretch a dimension by a given tolerance amount.

The result is the given length increased by at least an absolute amount tol, or by a relative amount length*tol if length > 1. Don't call this with tol less than machine precision or an exception will be thrown. Cost is 3 flops.

◆ stretch()

template<class RealP >
static RealP SimTK::Geo::stretch ( RealP  length)
inlinestatic

Stretch a dimension using the default tolerance for this precision as the tolerance in stretchBy().

Cost is 3 flops.


The documentation for this class was generated from the following file: