Simbody
3.7
|
A primitive useful for computations involving a single cubic Hermite curve segment in algebraic or geometric (Hermite) form. More...
Public Member Functions | |
CubicHermiteCurve_ () | |
Construct an uninitialized curve; coefficients will be garbage. More... | |
CubicHermiteCurve_ (const Vec< 4, Vec3P > &A) | |
Construct a cubic Hermite curve using the given algebraic coefficients A=[a3 a2 a1 a0], such that points on the curve are P(u)=sum_i(ai*u^i). More... | |
const Vec< 4, Vec3P > & | getAlgebraicCoefficients () const |
Return a reference to the algebraic coefficients A=[a3 a2 a1 a0] that are stored in this object. More... | |
Vec< 4, Vec3P > | calcGeometricCoefficients () const |
Calculate the Hermite coefficients H=[h0 h1 hu0 hu1] from the stored algebraic coefficients. More... | |
Vec3P | evalP (RealP u) const |
Evaluate a point P(u) on this curve given a value for parameter u in [0,1]. More... | |
Vec3P | evalPu (RealP u) const |
Evaluate the tangent Pu=dP/du on this curve given a value for parameter u in [0,1]. More... | |
Vec3P | evalPuu (RealP u) const |
Evaluate the second derivative Puu=d2P/du2 on this curve given a value for parameter u in [0,1]. More... | |
Vec3P | evalPuuu (RealP u) const |
Evaluate the third derivative Puuu=d3P/du3 on this curve. More... | |
Static Public Member Functions | |
Utility methods | |
These static methods provide operations useful for working with cubic Hermite curves. | |
static Row< 4, P > | calcU (RealP u) |
Return the row vector U=[u^3 u^2 u 1]. More... | |
static Row< 4, P > | calcFh (RealP u) |
Calculate the Hermite basis functions Fh=[F1..F4] for a given value of the parameter u. More... | |
static Row< 4, P > | calcFhu (RealP u) |
Calculate first derivatives Fhu=[F1u..F4u] of the Hermite basis functions for a given value of the parameter u. More... | |
static Row< 4, P > | calcFhuu (RealP u) |
Calculate second derivatives Fhuu=[F1uu..F4uu] of the Hermite basis functions for a given value of the parameter u. More... | |
static Row< 4, P > | calcFhuuu (RealP u) |
Calculate third derivatives Fhuuu=[F1uuu..F4uuu] of the Hermite basis functions for a given value of the parameter u. More... | |
static Vec< 4, Vec3P > | calcAFromH (const Vec< 4, Vec3P > &H) |
Given the Hermite coefficients H=~[h0 h1 hu0 hu1], return the algebraic coefficients A=~[a3 a2 a1 a0]. More... | |
static Vec< 4, Vec3P > | calcHFromA (const Vec< 4, Vec3P > &A) |
Given the algebraic coefficients A=~[a3 a2 a1 a0], return the Hermite coefficients H=~[h0 h1 hu0 hu1]. More... | |
static Vec3P | evalPUsingA (const Vec< 4, Vec3P > &A, RealP u) |
Given algebraic coefficients A and a value for the curve parameter u, return the point P(u) at that location. More... | |
static Vec3P | evalPuUsingA (const Vec< 4, Vec3P > &A, RealP u) |
Given algebraic coefficients A and a value for the curve parameter u, return the first derivative Pu(u)=dP/du at that location. More... | |
static Vec3P | evalPuuUsingA (const Vec< 4, Vec3P > &A, RealP u) |
Given algebraic coefficients A and a value for the curve parameter u, return the second derivative Puu(u)=d2P/du2 at that location. More... | |
static Vec3P | evalPuuuUsingA (const Vec< 4, Vec3P > &A, RealP u) |
Given algebraic coefficients A and a value for the curve parameter u, return the third derivative Puuu(u)=d3P/du3 at that location. More... | |
static Vec3P | evalPUsingH (const Vec< 4, Vec3P > &H, RealP u) |
Given Hermite coefficients H and a value for the curve parameter u, return the point P(u) at that location. More... | |
static Vec3P | evalPuUsingH (const Vec< 4, Vec3P > &H, RealP u) |
Given Hermite coefficients H and a value for the curve parameter u, return the first derivative Pu(u)=dP/du at that location. More... | |
static Vec3P | evalPuuUsingH (const Vec< 4, Vec3P > &H, RealP u) |
Given Hermite coefficients H and a value for the curve parameter u, return the second derivative Puu(u)=d2P/du2 at that location. More... | |
static Vec3P | evalPuuuUsingH (const Vec< 4, Vec3P > &H, RealP u) |
Given Hermite coefficients H and a value for the curve parameter u, return the third derivative Puuu(u)=d3P/du3 at that location. More... | |
static Mat< 4, 4, P > | getMh () |
Obtain the Hermite basis matrix Mh explicitly. More... | |
static Vec< 4, P > | multiplyByMh (const Vec< 4, P > &v) |
Form the product of the Hermite basis matrix Mh and a 4-vector, exploiting the structure of Mh (which is not symmetric). More... | |
static Mat< 4, 4, P > | getMhInv () |
Obtain the inverse inv(Mh) of the Hermite basis matrix explicitly. More... | |
static Vec< 4, P > | multiplyByMhInv (const Vec< 4, P > &v) |
Form the product of the inverse Hermite basis matrix inv(Mh) and a 4-vector, exploiting the structure of inv(Mh) (which is not symmetric). More... | |
A primitive useful for computations involving a single cubic Hermite curve segment in algebraic or geometric (Hermite) form.
Objects of this class contain the algebraic coefficients because most operations are more efficient in that form, but methods are provided for easy conversion to or from Hermite form and for working directly with the Hermite form.
Note that a cubic Hermite spline (made up of multiple segments) would not necessarily be composed of these because they can be constructed more compactly with shared end points. However, the primitive and inline methods here can be used for fast curve segment computations.
The primary reference for this implementation is the book "Geometric Modeling, 3rd ed." by Michael E. Mortenson, Industrial Press 2006, chapter 3. We follow Mortenson's notation here (with a few exceptions) and equation numbers are from the text. We're using h's for the Hermite coefficients rather than Mortenson's b's to avoid confusion with Bezier control points B, so that we can use A for algebraic, H for Hermite, and B for Bezier coefficient matrices.
The curve is parameterized by a scalar u in [0..1], such that points on the curve, and their derivatives with respect to u are given by
P(u) = a3 u^3 + a2 u^2 + a1 u + a0 (3.2) Pu(u) = 3 a3 u^2 + 2 a2 u + a1 Puu(u) = 6 a3 u + 2 a2 Puuu(u) = 6 a3
where Pu=dP/du, Puu=d2P/du2, Puuu=d3P/du3. Note that all higher derivatives are zero for a cubic. The 3-vectors ai are the algebraic coefficients, and that is the algebraic form of this cubic curve. The Hermite, or geometric, form is parameterized by position and tangent at the end points, given by
h0=P(0)=a0, h1=P(1)=a3+a2+a1+a0, hu0=Pu(0)=a1, hu1=Pu(1)=3*a3+2*a2+a1
These define the Hermite coefficients h0, h1, hu0, hu1. In this form the curve's points are
P(u) = F1(u) h0 + F2(u) h1 + F3(u) hu0 + F4(u) hu1 (3.6) Pu(u) = F1u(u) h0 + F2u(u) h1 + F3u(u) hu0 + F4u(u) hu1 Puu(u) = F1uu(u) h0 + F2uu(u) h1 + F3uu(u) hu0 + F4uu(u) hu1 Puuu(u) = F1uuu(u) h0 + F2uuu(u) h1 + F3uuu(u) hu0 + F4uuu(u) hu1
where the Fi's are the (scalar) Hermite basis functions given by
F1(u) = 2 u^3 - 3 u^2 + 1 F2(u) = -2 u^3 + 3 u^2 (3.4) F3(u) = u^3 - 2 u^2 + u F4(u) = u^3 - u^2
F1u(u) = 6 u^2 - 6 u F1uu(u) = 12 u - 6 F1uuu(u) = 12 (3.7) F2u(u) = -6 u^2 + 6 u F2uu(u) = -12 u + 6 F2uuu(u) = -12 (3.8) F3u(u) = 3 u^2 - 4 u + 1 F3uu(u) = 6 u - 4 F3uuu(u) = 6 F4u(u) = 3 u^2 - 2 u F4uu(u) = 6 u - 2 F4uuu(u) = 6
In matrix notation, let Fh=[F1 F2 F3 F4], and U=[u^3 u^2 u 1]. Then Fh = U Mh where Mh, the Hermite basis transformation matrix, and its inverse are:
[ 2 -2 1 1 ] [ 0 0 0 1 ] Mh = [-3 3 -2 -1 ] inv(Mh) = [ 1 1 1 1 ] (3.18) [ 0 0 1 0 ] [ 0 0 1 0 ] (3.23) [ 1 0 0 0 ] [ 3 2 1 0 ]
(Mortenson calls this matrix "Mf".) Now we can write the algebraic and Hermite forms in matrix notation. Let A=~[a3 a2 a1 a0], H=~[h0 h1 hu0 hu1]. We have
P(u) = U A = U Mh H A = Mh H (3.20-22) H = inv(Mh) A
where the last two equations show how to convert between the algebraic and geometric forms. Note that while U, Fh, and Mh are ordinary matrices, A and H are hypermatrices since their elements are 3-vectors.
Because of the sparsity of the matrices and the many common subexpressions above, it saves a considerable amount of computation to work out the necessary products by hand, and this implementation does that. For example, to find the algebraic coefficients A given the Hermite coefficients H the matrix-vector multiply Mh*H would take 3x28=84 flops, while the hand-worked version is:
[ a3 ] [ 2 (h0 - h1) + hu0 + hu1 ] A = [ a2 ] = [-3 (h0 - h1) - 2 hu0 - hu1 ] [ a1 ] [ hu0 ] [ a0 ] [ h0 ]
which instead takes 3x8=24 flops, 3.5X faster.
|
inline |
Construct an uninitialized curve; coefficients will be garbage.
|
inlineexplicit |
Construct a cubic Hermite curve using the given algebraic coefficients A=[a3 a2 a1 a0], such that points on the curve are P(u)=sum_i(ai*u^i).
If you have Hermite coefficients H, convert them to algebraic using static method calcAFromH().
|
inline |
Return a reference to the algebraic coefficients A=[a3 a2 a1 a0] that are stored in this object.
|
inline |
Calculate the Hermite coefficients H=[h0 h1 hu0 hu1] from the stored algebraic coefficients.
Here h0=P(0), h1=P(1), hu0=(dP/du)(0), hu1=(dP/du)(1) where P(u) is the curve evaluation function. Cost is 21 flops.
|
inline |
Evaluate a point P(u) on this curve given a value for parameter u in [0,1].
Values outside this range are permitted but do not lie on the curve segment. Cost is 20 flops.
|
inline |
Evaluate the tangent Pu=dP/du on this curve given a value for parameter u in [0,1].
Values outside this range are permitted but do not lie on the curve segment. Cost is 15 flops.
|
inline |
Evaluate the second derivative Puu=d2P/du2 on this curve given a value for parameter u in [0,1].
Values outside this range are permitted but do not lie on the curve segment. Cost is 10 flops.
|
inline |
Evaluate the third derivative Puuu=d3P/du3 on this curve.
Parameter u is ignored here since the 3rd derivative of a cubic curve is a constant. Cost is 3 flops.
|
inlinestatic |
Return the row vector U=[u^3 u^2 u 1].
Cost is 2 flops.
|
inlinestatic |
Calculate the Hermite basis functions Fh=[F1..F4] for a given value of the parameter u.
This is an optimized calculation of U*Mh, taking 10 flops.
|
inlinestatic |
Calculate first derivatives Fhu=[F1u..F4u] of the Hermite basis functions for a given value of the parameter u.
Cost is 10 flops.
|
inlinestatic |
Calculate second derivatives Fhuu=[F1uu..F4uu] of the Hermite basis functions for a given value of the parameter u.
Cost is 6 flops.
|
inlinestatic |
Calculate third derivatives Fhuuu=[F1uuu..F4uuu] of the Hermite basis functions for a given value of the parameter u.
For a cubic curve the third derivative is a constants so the cost is 0 flops.
|
inlinestatic |
Given the Hermite coefficients H=~[h0 h1 hu0 hu1], return the algebraic coefficients A=~[a3 a2 a1 a0].
All coefficients are 3-vectors. Cost is 24 flops.
|
inlinestatic |
Given the algebraic coefficients A=~[a3 a2 a1 a0], return the Hermite coefficients H=~[h0 h1 hu0 hu1].
All coefficients are 3-vectors. Cost is 21 flops.
|
inlinestatic |
Given algebraic coefficients A and a value for the curve parameter u, return the point P(u) at that location.
Cost is 20 flops.
|
inlinestatic |
Given algebraic coefficients A and a value for the curve parameter u, return the first derivative Pu(u)=dP/du at that location.
Cost is 15 flops.
|
inlinestatic |
Given algebraic coefficients A and a value for the curve parameter u, return the second derivative Puu(u)=d2P/du2 at that location.
Cost is 10 flops.
|
inlinestatic |
Given algebraic coefficients A and a value for the curve parameter u, return the third derivative Puuu(u)=d3P/du3 at that location.
The parameter u is ignored since the third derivative of a cubic is just a constant. Cost is 3 flops.
|
inlinestatic |
Given Hermite coefficients H and a value for the curve parameter u, return the point P(u) at that location.
Cost is 31 flops. Note that if you need to do this for the same curve more than twice, it is cheaper to convert to algebraic form using calcAFromH() (24 flops) and then evaluate using A (20 flops).
|
inlinestatic |
Given Hermite coefficients H and a value for the curve parameter u, return the first derivative Pu(u)=dP/du at that location.
Cost is 31 flops. Note that if you need to do this for the same curve more than once, it is cheaper to convert to algebraic form using calcAFromH() (24 flops) and then evaluate using A (15 flops).
|
inlinestatic |
Given Hermite coefficients H and a value for the curve parameter u, return the second derivative Puu(u)=d2P/du2 at that location.
Cost is 27 flops. Note that if you need to do this for the same curve more than once, it is cheaper to convert to algebraic form using calcAFromH() (24 flops) and then evaluate using A (10 flops).
|
inlinestatic |
Given Hermite coefficients H and a value for the curve parameter u, return the third derivative Puuu(u)=d3P/du3 at that location.
Cost is 21 flops. Note that if you need to do this for the same curve more than once, it is cheaper to convert to algebraic form using calcAFromH() (24 flops) and then evaluate using A (3 flops).
|
inlinestatic |
Obtain the Hermite basis matrix Mh explicitly.
This is mostly useful for testing since specialized routines can save a lot of CPU time over working directly in matrix form. This is a constant matrix so there is no computation cost.
|
inlinestatic |
Form the product of the Hermite basis matrix Mh and a 4-vector, exploiting the structure of Mh (which is not symmetric).
Cost is 8 flops.
|
inlinestatic |
Obtain the inverse inv(Mh) of the Hermite basis matrix explicitly.
This is mostly useful for testing since specialized routines can save a lot of CPU time over working directly in matrix form. This is a constant matrix so there is no computation cost.
|
inlinestatic |
Form the product of the inverse Hermite basis matrix inv(Mh) and a 4-vector, exploiting the structure of inv(Mh) (which is not symmetric).
Cost is 7 flops.