contrib/oul/ouml/CardinalSpline.h
Go to the documentation of this file.
00001 #ifndef CARDINAL_SPLINE_D_
00002 #define CARDINAL_SPLINE_D_
00003 
00004 #include <vnl/vnl_matrix.h>
00005 #include <vnl/vnl_vector_fixed.h>
00006 #include <vnl/vnl_matrix_fixed.h>
00007 #include <vcl_vector.h>
00008 #include <vcl_string.h>
00009 #include <vcl_cassert.h>
00010 #include <vnl/io/vnl_io_vector_fixed.txx>
00011 #include <vnl/io/vnl_io_matrix.txx>
00012 #include <vsl/vsl_binary_io.h>
00013 #include <vsl/vsl_vector_io.h>
00014 
00015 // A 3D cardinal spline class. See Hearn and Baker, "Computer
00016 // Graphics", C Version, Second Edition, page 325. Cardinal splines
00017 // are cubic interpolating splines where the tangents are set equal to
00018 // the chord passing through the points on either side of the current
00019 // control point.
00020 //
00021 // This spline could possibly be templated to allow for plane or space
00022 // curves. At the moment, if you want a space curve, just set the 3rd
00023 // coordinate of all the control points to some constant value (or
00024 // more generally, ensure all control points lie on a plane).
00025 //
00026 // Actually, at the moment, these are Catmull-Rom splines (t=0.5)
00027 //
00028 // \author Brendan McCane
00029 // \status Under Development
00030 
00031 class CardinalSpline
00032 {
00033  public:
00034     typedef vnl_vector_fixed<double, 3> Vector3D;
00035     CardinalSpline(): Mc(4,4,0.0), s(0.25) {}
00036     CardinalSpline(vcl_vector<Vector3D> &cPoints)
00037     : controlPoints(cPoints), Mc(4,4,0.0), s(0.25)
00038     {
00039         setMc(s);
00040     }
00041     CardinalSpline(const CardinalSpline &cs):
00042         controlPoints(cs.controlPoints), Mc(cs.Mc), s(cs.s) {}
00043     CardinalSpline &operator =(const CardinalSpline &cs) {
00044         if (&cs != this)
00045         {
00046             controlPoints = cs.controlPoints;
00047             Mc = cs.Mc;
00048             s = cs.s;
00049         }
00050         return *this;
00051     }
00052     ~CardinalSpline() {}
00053 
00054     Vector3D getPoint(double t) const;
00055     vcl_vector<Vector3D> getPoints(int num_points) const;
00056     vcl_vector<Vector3D> getControlPoints() const {return controlPoints;}
00057     void setT(double t){setMc((1-t)/2.0);}
00058     Vector3D closest_point(const Vector3D &point) const {
00059         double t = closest_point_t(point);
00060         assert(t>=0.0);
00061         assert(t<=1.0);
00062         return getPoint(t);
00063     }
00064     double closest_point_t(const Vector3D &point) const;
00065     Vector3D firstDerivative(double t) const;
00066     Vector3D secondDerivative(double t) const;
00067     // return the mean of the control pts
00068     Vector3D mean_control_pts() const {
00069         Vector3D mean(0.0);
00070         for (unsigned i=0; i<controlPoints.size(); i++)
00071             mean += controlPoints[i];
00072         mean /= (double)controlPoints.size();
00073         return mean;
00074     }
00075 
00076     // binary IO stuff
00077     void b_write(vsl_b_ostream &os) const;
00078     void b_read(vsl_b_istream &os);
00079     short version() const {return 1;}
00080     void print_summary(vcl_ostream &os) const {
00081         os << "Cardinal Spline:\n"
00082            << "\tcontrolPts =\n";
00083         for (unsigned i=0; i<controlPoints.size(); i++)
00084             os << "\t\t" << controlPoints[i] << vcl_endl;
00085     }
00086     vcl_string is_a() const {return vcl_string("CardinalSpline");}
00087     bool is_class(const vcl_string &s) const {return s==is_a();}
00088 
00089     #ifdef VCL_SGI_CC
00090     friend bool operator!=(Vector3D const& a, Vector3D const& b) {
00091         return a[0]!=b[0] || a[1]!=b[1] || a[2]!=b[2];
00092     }
00093     #endif
00094 
00095     bool operator==(const CardinalSpline &c) const {
00096         return (controlPoints==c.controlPoints) && (Mc==c.Mc) && (s==c.s);
00097     }
00098 
00099     bool operator!=(const CardinalSpline &c) const {
00100         return !(*this==c);
00101     }
00102 
00103     void translate(const Vector3D &t){
00104         for (unsigned i=0; i<controlPoints.size(); i++)
00105             controlPoints[i] += t;
00106     }
00107 
00108  private:
00109     double distanceFunctionFirstDerivative(double t,
00110                                            const Vector3D &point) const;
00111     double distanceFunctionSecondDerivative(double t,
00112                                             const Vector3D &point) const;
00113     Vector3D getVal(const vnl_matrix_fixed<double, 1, 4> &uvec, int pk) const;
00114     double convert_t(double t) const{
00115         if (t<0.0)
00116             while (t<0.0) t+=1.0;
00117         else if (t>1.0)
00118             while (t>1.0) t-=1.0;
00119         return t;
00120     }
00121 
00122     void setMc(double s_)
00123     {
00124         s = s_;
00125         Mc(0,0)=-s; Mc(0,1)=2-s; Mc(0,2)=s-2; Mc(0,3)=s;
00126         Mc(1,0)=2*s; Mc(1,1)=s-3; Mc(1,2)=3-2*s; Mc(1,3)=-s;
00127         Mc(2,0)=-s; Mc(2,1)=0; Mc(2,2)=s; Mc(2,3)=0;
00128         Mc(3,0)=0; Mc(3,1)=1; Mc(3,2)=0; Mc(3,3)=0;
00129     }
00130     vcl_vector<Vector3D> controlPoints;
00131     vnl_matrix<double> Mc;
00132     double s;
00133 };
00134 
00135 void vsl_b_write(vsl_b_ostream &os, const CardinalSpline &e);
00136 void vsl_b_read(vsl_b_istream &is, CardinalSpline &e);
00137 void vsl_print_summary(vcl_ostream &is, const CardinalSpline &e);
00138 
00139 #endif // CARDINAL_SPLINE_D_