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