00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #pragma once
00023 #ifndef VOLUMILL_CURVE_H
00024 #define VOLUMILL_CURVE_H
00025
00026 #include <Geom/Points.h>
00027 #include <Geom/PointAlg.h>
00028 #include <Util/TypeStripper.h>
00029 #include <Util/Params.h>
00030 #include <boost/mpl/if.hpp>
00031 #include <boost/type_traits/is_base_of.hpp>
00032 #include <loki/Visitor.h>
00033
00034 namespace geom
00035 {
00036
00037 template <typename R, typename Visited>
00038 struct ThrowingCatchAll
00039 {
00040 static R OnUnknownVisitor(Visited&, Loki::BaseVisitor&)
00041 {
00042 VALIDATE(0)("Unknown Visitor type not supported right now");
00043 }
00044 };
00045
00047 template <int n>
00048 class ParametricCurve : public Loki::BaseVisitable<void, Loki::DefaultCatchAll, true>, public util::Parameterized
00049 {
00050 friend class boost::serialization::access;
00051 template<class Archive>
00052 void serialize(Archive &ar, const unsigned int version)
00053 {
00054 if (version > 0)
00055 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(util::Parameterized);
00056 }
00057 public:
00058 LOKI_DEFINE_CONST_VISITABLE();
00060 enum { Dim = n };
00062 typedef PointNd<n> Point;
00064 typedef VecNd<n> Vec;
00065
00066 virtual ~ParametricCurve();
00067
00070 virtual std::pair<double, double> getRange() const = 0;
00073 virtual bool isPeriodic() const = 0;
00080 virtual void evaluate(double param, Point *pPt,
00081 int nderivs = 0, std::vector<Vec> *pDerivs = 0) const = 0;
00084 virtual shared_ptr<ParametricCurve<n> > clone() const = 0;
00086 virtual void reverse() = 0;
00087 };
00088
00089 typedef shared_ptr<ParametricCurve<2> > CurvePtr2d;
00090 typedef shared_ptr<ParametricCurve<3> > CurvePtr3d;
00091 typedef std::vector<CurvePtr2d> CompositeCurve2d;
00092 typedef std::vector<CurvePtr3d> CompositeCurve3d;
00093
00095 template <int n>
00096 class ControlPointCurveBase : virtual public ParametricCurve<n>
00097 {
00098 public:
00099 virtual ~ControlPointCurveBase();
00100
00103 virtual int getNumCpts() const = 0;
00104
00105
00106
00110 virtual PointNd<n> getControlPoint(int i) const = 0;
00114 virtual void setControlPoint(int i, const PointNd<n> &pt) = 0;
00117 virtual double getWeight(int i) const = 0;
00118 };
00119
00120 namespace detail
00121 {
00122 template<class Curve>
00123 struct CurveEndpointAccessor
00124 {
00125 typedef PointNd<Curve::Dim> Point;
00126 inline Point getStartPoint (const Curve& c)
00127 {
00128 Point pt;
00129 c.evaluate (0.0, &pt);
00130 return pt;
00131 }
00132 inline Point getEndPoint (const Curve& c)
00133 {
00134 Point pt;
00135 c.evaluate (1.0, &pt);
00136 return pt;
00137 }
00138 };
00139
00140 template<int n>
00141 struct CurveEndpointAccessor<ControlPointCurveBase<n> >
00142 {
00143 typedef PointNd<n> Point;
00144 typedef ControlPointCurveBase<n> Curve;
00145 inline Point getStartPoint (const Curve& c)
00146 {
00147 return c.getControlPoint (0);
00148 }
00149 inline Point getEndPoint (const Curve& c)
00150 {
00151 return c.getControlPoint (c.getNumCpts() - 1);
00152 }
00153 inline void setStartPoint (Curve& c, const Point& pt)
00154 {
00155 c.setControlPoint (0, pt);
00156 }
00157 inline void setEndPoint (Curve& c, const Point& pt)
00158 {
00159 c.setControlPoint (c.getNumCpts() - 1, pt);
00160 }
00161 };
00162 }
00163
00164 template<class T>
00165 inline PointNd<util::TypeStripper<T>::base_type::Dim>
00166 getStartPoint (T curve)
00167 {
00168 typedef typename util::TypeStripper<T>::base_type Derived;
00169 typedef ControlPointCurveBase<Derived::Dim> Base;
00170 typedef typename boost::mpl::if_<boost::is_base_of<Base, Derived>,
00171 Base,
00172 Derived>::type Arg;
00173 detail::CurveEndpointAccessor<Arg> cea;
00174 return cea.getStartPoint (util::TypeStripper<T>::cstrip (curve));
00175 }
00176
00177 template<class T>
00178 inline PointNd<util::TypeStripper<T>::base_type::Dim>
00179 getEndPoint (T curve)
00180 {
00181 typedef typename util::TypeStripper<T>::base_type Derived;
00182 typedef ControlPointCurveBase<Derived::Dim> Base;
00183 typedef typename boost::mpl::if_<boost::is_base_of<Base, Derived>,
00184 Base,
00185 Derived>::type Arg;
00186 detail::CurveEndpointAccessor<Arg> cea;
00187 return cea.getEndPoint (util::TypeStripper<T>::cstrip (curve));
00188 }
00189
00190 template<class T, class P>
00191 inline void setStartPoint (T curve, const P& pt)
00192 {
00193 typedef typename util::TypeStripper<T>::base_type Derived;
00194 typedef ControlPointCurveBase<Derived::Dim> Base;
00195 typedef typename boost::mpl::if_<boost::is_base_of<Base, Derived>,
00196 Base,
00197 Derived>::type Arg;
00198 detail::CurveEndpointAccessor<Arg> cea;
00199 cea.setStartPoint (util::TypeStripper<T>::strip (curve), pt);
00200 }
00201
00202 template<class T, class P>
00203 inline void setEndPoint (T curve, const P& pt)
00204 {
00205 typedef typename util::TypeStripper<T>::base_type Derived;
00206 typedef ControlPointCurveBase<Derived::Dim> Base;
00207 typedef typename boost::mpl::if_<boost::is_base_of<Base, Derived>,
00208 Base,
00209 Derived>::type Arg;
00210 detail::CurveEndpointAccessor<Arg> cea;
00211 cea.setEndPoint (util::TypeStripper<T>::strip (curve), pt);
00212 }
00213
00215 template <int n>
00216 class Line : virtual public ControlPointCurveBase<n>
00217 {
00218 public:
00219
00220 typedef void ReturnType;
00221 LOKI_DEFINE_CONST_VISITABLE();
00222 };
00223
00224 template<int n>
00225 shared_ptr<Line<n> > makeLine ();
00226
00227 template <int n>
00228 inline shared_ptr<Line<n> > makeLine (const PointNd<n>& start, const PointNd<n>& end)
00229 {
00230 shared_ptr<Line<n> > pLine (makeLine<n>());
00231 setStartPoint (pLine, start);
00232 setEndPoint (pLine, end);
00233
00234 return pLine;
00235 }
00236
00237
00238 typedef Line<2> Line2d;
00239 typedef Line<3> Line3d;
00240
00242 template <int n>
00243 class Polyline : virtual public ControlPointCurveBase<n>
00244 {
00245 public:
00246
00247 typedef void ReturnType;
00248 LOKI_DEFINE_CONST_VISITABLE();
00249
00250 virtual int getSpan (double param) const = 0;
00251 virtual const std::vector<geom::PointNd<n> >& getPts() const = 0;
00252 };
00253
00254 template<int n>
00255 shared_ptr<Polyline<n> > makePolyline (const std::vector<geom::PointNd<n> >& pts);
00256
00257 typedef Polyline<2> Polyline2d;
00258 typedef Polyline<3> Polyline3d;
00259
00261 template <int n>
00262 class Arc
00263 {
00264 };
00265
00266 template<>
00267 class Arc<2> : virtual public ParametricCurve<2>
00268 {
00269 public:
00270 LOKI_DEFINE_CONST_VISITABLE();
00271 virtual const Point2d& getCenter() const = 0;
00272 virtual double getRadius() const = 0;
00273 virtual const std::pair<double, double>& getAngleRange() const = 0;
00274 virtual bool isCCW() const = 0;
00275
00276 virtual void assign (const Arc<2>& otherArc) = 0;
00277 };
00278
00281 shared_ptr<Arc<2> > makeArc (const Point2d& center, double radius, double startAngle, double endAngle);
00282 shared_ptr<Arc<2> > makeCCWArcCenter (const Point2d& center, const Point2d& startPt, const Point2d& endPt);
00283 shared_ptr<Arc<2> > makeCCWArcCenterRadius (
00284 const Point2d& center, const Point2d& startPt, const Point2d& endPt, double radius);
00285 shared_ptr<Arc<2> > makeCWArcCenter (const Point2d& center, const Point2d& startPt, const Point2d& endPt);
00286 shared_ptr<Arc<2> > makeCircle (const Point2d& center, double radius);
00287 CurvePtr2d makeArcTangents (const Point2d& startPt, const Point2d& commonTan, const Point2d& endPt);
00288 typedef Arc<2> Arc2d;
00289 typedef Arc<3> Arc3d;
00290
00291 }
00292
00293 BOOST_IS_ABSTRACT (geom::ParametricCurve<2>);
00294 BOOST_IS_ABSTRACT (geom::ParametricCurve<3>);
00295
00296 BOOST_CLASS_VERSION (geom::ParametricCurve<2>, 1);
00297 BOOST_CLASS_VERSION (geom::ParametricCurve<3>, 1);
00298 #endif