Simbody  3.4 (development)
Geo_CubicBezierCurve.h
Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATH_GEO_CUBIC_BEZIER_CURVE_H_
00002 #define SimTK_SIMMATH_GEO_CUBIC_BEZIER_CURVE_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 
00031 #include "SimTKcommon.h"
00032 #include "simmath/internal/common.h"
00033 #include "simmath/internal/Geo.h"
00034 #include "simmath/internal/Geo_Point.h"
00035 #include "simmath/internal/Geo_Sphere.h"
00036 #include "simmath/internal/Geo_Box.h"
00037 
00038 #include <cassert>
00039 #include <cmath>
00040 #include <algorithm>
00041 
00042 namespace SimTK {
00043 
00044 
00045 //==============================================================================
00046 //                          GEO CUBIC BEZIER CURVE
00047 //==============================================================================
00136 template <class P>
00137 class Geo::CubicBezierCurve_ {
00138 typedef P               RealP;
00139 typedef Vec<3,RealP>    Vec3P;
00140 typedef UnitVec<P,1>    UnitVec3P;
00141 typedef Rotation_<P>    RotationP;
00142 typedef Transform_<P>   TransformP;
00143 
00144 public:
00146 CubicBezierCurve_() {}
00147 
00150 template <int S>
00151 explicit CubicBezierCurve_(const Vec<4,Vec3P,S>& controlPoints) 
00152 :   B(controlPoints) {} 
00153 
00156 template <int S>
00157 explicit CubicBezierCurve_(const Row<4,Vec3P,S>& controlPoints) 
00158 :   B(controlPoints.positionalTranspose()) {} 
00159 
00162 const Vec<4,Vec3P>& getControlPoints() const {return B;}
00165 Vec<4,Vec3P> calcAlgebraicCoefficients() const {return calcAFromB(B);}
00168 Vec<4,Vec3P> calcHermiteCoefficients() const {return calcHFromB(B);}
00172 Vec3P evalP(RealP u) const {return evalPUsingB(B,u);}
00176 Vec3P evalPu(RealP u) const {return evalPuUsingB(B,u);}
00180 Vec3P evalPuu(RealP u) const {return evalPuuUsingB(B,u);}
00184 Vec3P evalPuuu(RealP u) const {return evalPuuuUsingB(B,u);}
00185 
00189 RealP calcDsdu(RealP u) const {return evalPu(u).norm();}
00190 
00194 UnitVec3P calcUnitTangent(RealP u) const {
00195     const Vec3P Pu=evalPu(u);                               //  15 flops
00196     return Geo::calcUnitTangent(Pu);                        // ~40 flops
00197 }
00198 
00202 Vec3P calcCurvatureVector(RealP u) const {
00203     const Vec3P Pu=evalPu(u), Puu=evalPuu(u);               //  25 flops
00204     return Geo::calcCurvatureVector(Pu,Puu);                // ~30 flops
00205 }
00206 
00210 RealP calcCurvatureSqr(RealP u) {
00211     const Vec3P Pu=evalPu(u), Puu=evalPuu(u);               //  25 flops
00212     return Geo::calcCurvatureSqr(Pu,Puu);                   // ~30 flops
00213 }
00214 
00221 RealP calcTorsion(RealP u) {
00222     const Vec3P Pu=evalPu(u), Puu=evalPuu(u), Puuu=evalPuuu(u); //  28 flops
00223     return Geo::calcTorsion(Pu,Puu,Puuu);
00224 }
00225 
00226 
00234 UnitVec3P calcUnitNormal(RealP u) const {
00235     const Vec3P Pu=evalPu(u), Puu=evalPuu(u);               //  25 flops
00236     return Geo::calcUnitNormal(Pu,Puu);                     // ~80 flops
00237 }
00238 
00248 RealP calcCurveFrame(RealP u, TransformP& X_FP) const {
00249     const Vec3P Pval=evalP(u), Pu=evalPu(u), Puu=evalPuu(u); //  45 flops
00250     return Geo::calcCurveFrame(Pval,Pu,Puu,X_FP);
00251 }
00252 
00259 void split(RealP u, CubicBezierCurve_<P>& left, 
00260                     CubicBezierCurve_<P>& right) const {
00261     const RealP tol = getDefaultTol<RealP>();
00262     SimTK_ERRCHK1(tol <= u && u <= 1-tol, "Geo::CubicBezierCurve::split()",
00263         "Can't split curve at parameter %g; it is either out of range or"
00264         " too close to an end point.", (double)u);
00265 
00266     const RealP u1 = 1-u;
00267     const Vec3P p01 = u1*B[0] + u*B[1];                     // 3x9 flops
00268     const Vec3P p12 = u1*B[1] + u*B[2];
00269     const Vec3P p23 = u1*B[2] + u*B[3];
00270     left.B[0] = B[0];
00271     left.B[1] = p01;
00272     left.B[2] = u1*p01 + u*p12;                             // 3x3 flops
00273 
00274     right.B[3] = B[3];
00275     right.B[2] = p23;
00276     right.B[1] = u1*p12 + u*p23;
00277     left.B[3] = right.B[0] = u1*left.B[2] + u*right.B[1];   // 3x3 flops
00278 }
00279 
00283 void bisect(CubicBezierCurve_<P>& left, 
00284             CubicBezierCurve_<P>& right) const {
00285     const Vec3P p01 = (B[0] + B[1])/2;                     // 3x6 flops
00286     const Vec3P p12 = (B[1] + B[2])/2;
00287     const Vec3P p23 = (B[2] + B[3])/2;
00288     left.B[0] = B[0];
00289     left.B[1] = p01;
00290     left.B[2] = (p01 + p12)/2;                             // 3x2 flops
00291 
00292     right.B[3] = B[3];
00293     right.B[2] = p23;
00294     right.B[1] = (p12 + p23)/2;
00295     left.B[3] = right.B[0] = (left.B[2] + right.B[1])/2;   // 3x2 flops
00296 }
00297 
00298 
00303 Geo::Sphere_<P> calcBoundingSphere() const 
00304 {   return Geo::Point_<P>::calcBoundingSphere(B[0],B[1],B[2],B[3]); }
00305 
00310 Geo::AlignedBox_<P> calcAxisAlignedBoundingBox() const 
00311 {   const ArrayViewConst_<Vec3P> points(&B[0], &B[0]+4); // no copy or heap use
00312     return Geo::Point_<P>::calcAxisAlignedBoundingBox(points); }
00313 
00318 Geo::OrientedBox_<P> calcOrientedBoundingBox() const 
00319 {   const ArrayViewConst_<Vec3P> points(&B[0], &B[0]+4); // no copy or heap use
00320     return Geo::Point_<P>::calcOrientedBoundingBox(points); }
00321 
00328 static Row<4,P> calcFb(RealP u) {
00329     const RealP u2 = u*u, u3 = u*u2;                // powers of u
00330     const RealP u1 = 1-u, u12=u1*u1, u13=u1*u12;    // powers of 1-u
00331     return Row<4,P>(u13, 3*u*u12, 3*u2*u1, u3); 
00332 }
00333 
00336 static Row<4,P> calcDFb(RealP u) {
00337     const RealP u6=6*u, u2 = u*u, u23 = 3*u2, u29 = 9*u2;
00338     return Row<4,P>(u6-u23-3, u29-12*u+3, u6-u29, u23); 
00339 }
00340 
00343 static Row<4,P> calcD2Fb(RealP u) {
00344     const RealP u6  = 6*u, u18 = 18*u;
00345     return Row<4,P>(6-u6, u18-12, 6-u18, u6); 
00346 }
00347 
00351 static Row<4,P> calcD3Fb(RealP u) {
00352     return Row<4,P>(-6, 18, -18, 6); 
00353 }
00354 
00358 template <int S>
00359 static Vec<4,Vec3P> calcAFromB(const Vec<4,Vec3P,S>& B) {
00360     const Vec3P& b0=B[0]; const Vec3P& b1=B[1];    // aliases for beauty
00361     const Vec3P& b2=B[2]; const Vec3P& b3=B[3];
00362     return Vec<4,Vec3P>(b3-b0+3*(b1-b2), 3*(b0+b2)-6*b1, 3*(b1-b0), b0);
00363 }
00364 
00368 template <int S>
00369 static Vec<4,Vec3P> calcBFromA(const Vec<4,Vec3P,S>& A) {
00370     const Vec3P& a3=A[0]; const Vec3P& a2=A[1];    // aliases for beauty
00371     const Vec3P& a1=A[2]; const Vec3P& a0=A[3];
00372     return Vec<4,Vec3P>(a0, a1/3 + a0, (a2+2*a1)/3 + a0, a3+a2+a1+a0);
00373 }
00374 
00378 template <int S>
00379 static Vec<4,Vec3P> calcHFromB(const Vec<4,Vec3P,S>& B) {
00380     const Vec3P& b0=B[0]; const Vec3P& b1=B[1];    // aliases for beauty
00381     const Vec3P& b2=B[2]; const Vec3P& b3=B[3];
00382     return Vec<4,Vec3P>(b0, b3, 3*(b1-b0), 3*(b3-b2));
00383 }
00384 
00388 template <int S>
00389 static Vec<4,Vec3P> calcBFromH(const Vec<4,Vec3P,S>& H) {
00390     const Vec3P& h0= H[0]; const Vec3P& h1= H[1];    // aliases for beauty
00391     const Vec3P& hu0=H[2]; const Vec3P& hu1=H[3];
00392     return Vec<4,Vec3P>(h0, h0 + hu0/3, h1 - hu1/3, h1);
00393 }
00394 
00400 template <int S>
00401 static Vec3P evalPUsingB(const Vec<4,Vec3P,S>& B, RealP u) { 
00402     return calcFb(u)*B; // 9 + 3*7 = 30 flops
00403 }
00409 template <int S>
00410 static Vec3P evalPuUsingB(const Vec<4,Vec3P,S>& B, RealP u) { 
00411     return calcDFb(u)*B; // 10 + 3*7 = 31 flops
00412 }
00418 template <int S>
00419 static Vec3P evalPuuUsingB(const Vec<4,Vec3P,S>& B, RealP u) { 
00420     return calcD2Fb(u)*B; // 5 + 3*7 = 26 flops
00421 }
00427 template <int S>
00428 static Vec3P evalPuuuUsingB(const Vec<4,Vec3P,S>& B, RealP u) { 
00429     return calcD3Fb(u)*B; // 0 + 3*7 = 21 flops
00430 }
00435 static Mat<4,4,P> getMb() {
00436     return Mat<4,4,P>( -1,  3, -3,  1,
00437                         3, -6,  3,  0,
00438                        -3,  3,  0,  0,
00439                         1,  0,  0,  0);
00440 }
00441 
00446 template <int S>
00447 static Vec<4,P> multiplyByMb(const Vec<4,P,S>& b) {
00448     const RealP b0=b[0], b1=b[1], b2=b[2], b3=b[3];
00449     return Vec<4,P>(3*(b1-b2)+b3-b0, 3*(b0+b2)-6*b1, 3*(b1-b0), b0);
00450 }
00451 
00457 static Mat<4,4,P> getMbInv() {
00458     return Mat<4,4,P>( 0,    0,       0,   1,
00459                        0,    0,   P(1)/3,  1,
00460                        0, P(1)/3, P(2)/3,  1,
00461                        1,    1,       1,   1 );
00462 }
00463 
00468 template <int S>
00469 static Vec<4,P> multiplyByMbInv(const Vec<4,P,S>& b) {
00470     const RealP b0=b[0], b1=b[1], b2=b[2], b3=b[3];
00471     return Vec<4,P>(b3, b2/3+b3, (b1+2*b2)/3+b3, b0+b1+b2+b3);
00472 }
00473 
00481 static Mat<4,4,P> getMhInvMb() {
00482     return Mat<4,4,P>(  1,  0,  0,  0,
00483                         0,  0,  0,  1,
00484                        -3,  3,  0,  0,
00485                         0,  0, -3,  3 );
00486 }
00489 template <int S>
00490 static Vec<4,P> multiplyByMhInvMb(const Vec<4,P,S>& v) {
00491     const RealP v0=v[0], v1=v[1], v2=v[2], v3=v[3];
00492     return Vec<4,P>(v0, v3, 3*(v1-v0), 3*(v3-v2));
00493 }
00494 
00503 static Mat<4,4,P> getMbInvMh() {
00504     return Mat<4,4,P>(  1,  0,    0,      0,
00505                         1,  0, P(1)/3,    0,
00506                         0,  1,    0,   P(-1)/3,
00507                         0,  1,    0,      0 );
00508 }
00511 template <int S>
00512 static Vec<4,P> multiplyByMbInvMh(const Vec<4,P,S>& v) {
00513     const RealP v0=v[0], v1=v[1], v2=v[2], v3=v[3];
00514     return Vec<4,P>(v0, v0+v2/3, v1-v3/3, v1);
00515 }
00518 private:
00519 Vec<4,Vec3P> B;
00520 };
00521 
00522 
00523 
00524 } // namespace SimTK
00525 
00526 #endif // SimTK_SIMMATH_GEO_CUBIC_BEZIER_CURVE_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines