00001 #ifndef XDKWRL_TRIANGULATOR_H
00002 #define XDKWRL_TRIANGULATOR_H
00003
00004 #include <vector>
00005 #include <list>
00006 #include <numeric>
00007 #include <stdexcept>
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 template<class P>
00037 class Triangulator
00038 {
00039 public:
00040 class Face;
00041 typedef P PointType;
00042 typedef typename std::list<Face>::const_iterator face_const_iterator;
00043 template<class T>
00044 inline Triangulator(T first,const T& last);
00045 inline void process() throw(std::runtime_error);
00046 inline unsigned int faces_size() const;
00047 inline face_const_iterator faces_begin() const;
00048 inline face_const_iterator faces_end() const;
00049 protected:
00050 static inline bool isInTriangle(const PointType& A,
00051 const PointType& B,
00052 const PointType& C,
00053 const PointType& M);
00054 inline bool snip(const int u,const int v,const int w,const int nv);
00055 inline int nbPoints() const;
00056 inline const PointType& point(const int i) const;
00057 inline void addFace(const int u,const int v,const int w);
00058 private:
00059 std::vector<const PointType*> contour_;
00060 std::vector<int> V_;
00061 std::list<Face> faces_;
00062 };
00063
00064
00065
00066 template<class P>
00067 class Triangulator<P>::Face
00068 {
00069 public:
00070 inline const Triangulator<P>::PointType* vertex(const int i) const;
00071 protected:
00072 friend class Triangulator;
00073 inline Face(const Triangulator<P>::PointType* const p0,
00074 const Triangulator<P>::PointType* const p1,
00075 const Triangulator<P>::PointType* const p2);
00076 private:
00077 const Triangulator<P>::PointType* vertices_[3];
00078 };
00079
00080
00081
00082 template<class P>
00083 inline const typename Triangulator<P>::PointType*
00084 Triangulator<P>::Face::vertex(const int i) const
00085 {
00086 return vertices_[i];
00087 }
00088 template<class P>
00089 inline
00090 Triangulator<P>::Face::Face(const Triangulator<P>::PointType* const p0,
00091 const Triangulator<P>::PointType* const p1,
00092 const Triangulator<P>::PointType* const p2)
00093 {
00094 vertices_[0] = p0;
00095 vertices_[1] = p1;
00096 vertices_[2] = p2;
00097 }
00098
00099
00100
00101 template<class P>
00102 template<class T>
00103 inline
00104 Triangulator<P>::Triangulator(T first,const T& last)
00105 {
00106 while (first != last)
00107 {
00108 contour_.push_back(&(*first++));
00109 }
00110 V_ = std::vector<int>(nbPoints());
00111 float A=0.0f;
00112 for(int p=nbPoints()-1,q=0; q<nbPoints(); p=q++)
00113 {
00114 A +=
00115 (*contour_[p])[0]*(*contour_[q])[1] -
00116 (*contour_[q])[0]*(*contour_[p])[1];
00117 }
00118 if (A > 0.0f)
00119 {
00120
00121
00122
00123 int n=0;
00124 for (std::vector<int>::iterator iter =V_.begin();
00125 iter != V_.end();++iter)
00126 {
00127 *iter = n++;
00128 }
00129 }
00130 else
00131 {
00132 int n=0;
00133 for (std::vector<int>::reverse_iterator iter =V_.rbegin();
00134 iter != V_.rend();++iter)
00135 {
00136 *iter == ++n;
00137 }
00138 }
00139 }
00140 template<class P>
00141 inline void
00142 Triangulator<P>::process() throw(std::runtime_error)
00143 {
00144 if (nbPoints() < 3)
00145 {
00146 throw std::runtime_error("Empty polygon");
00147 }
00148 int nv = nbPoints();
00149
00150 int count = 2*nv;
00151 for(int m=0, v=nv-1; nv>2; )
00152 {
00153
00154 if (0 >= (count--))
00155 {
00156 throw std::runtime_error("Bad polygon");
00157 }
00158
00159 const int u = nv <= v ? 0 : v;
00160 v = nv <= u+1 ? 0 : u+1;
00161 const int w = nv <= v+1 ? 0 : v+1;
00162 if ( snip(u,v,w,nv) )
00163 {
00164
00165 addFace(u,v,w);
00166 ++m;
00167
00168 for(int s=v,t=v+1;t<nv;++s,++t)
00169 {
00170 V_[s] = V_[t];
00171 }
00172
00173 count = 2*(--nv);
00174 }
00175 }
00176 }
00177 template<class P>
00178 inline unsigned int
00179 Triangulator<P>::faces_size() const
00180 {
00181 return faces_.size();
00182 }
00183 template<class P>
00184 inline typename Triangulator<P>::face_const_iterator
00185 Triangulator<P>::faces_begin() const
00186 {
00187 return faces_.begin();
00188 }
00189 template<class P>
00190 inline typename Triangulator<P>::face_const_iterator
00191 Triangulator<P>::faces_end() const
00192 {
00193 return faces_.end();
00194 }
00195 template<class P>
00196 inline bool
00197 Triangulator<P>::isInTriangle(const Triangulator<P>::PointType& A,
00198 const Triangulator<P>::PointType& B,
00199 const Triangulator<P>::PointType& C,
00200 const Triangulator<P>::PointType& M)
00201 {
00202 const float a[2] = { C[0]-B[0],C[1]-B[1] };
00203 const float b[2] = { A[0]-C[0],A[1]-C[1] };
00204 const float c[2] = { B[0]-A[0],B[1]-A[1] };
00205 const float am[2]= { M[0]-A[0],M[1]-A[1] };
00206 const float bm[2]= { M[0]-B[0],M[1]-B[1] };
00207 const float cm[2]= { M[0]-C[0],M[1]-C[1] };
00208
00209 return ((a[0]*bm[1] >= a[1]*bm[0]) &&
00210 (c[0]*am[1] >= c[1]*am[0]) &&
00211 (b[0]*cm[1] >= b[1]*cm[0]));
00212 }
00213 template<class P>
00214 inline bool
00215 Triangulator<P>::snip(const int u,const int v,const int w,const int nv)
00216 {
00217 static const float EPSILON=0.0000000001f;
00218 const PointType& A = point(u);
00219 const PointType& B = point(v);
00220 const PointType& C = point(w);
00221 if (EPSILON > (((B[0]-A[0])*(C[1]-A[1]))-((B[1]-A[1])*(C[0]-A[0]))))
00222 {
00223 return false;
00224 }
00225 for (int p=0;p < nv;++p)
00226 {
00227 if( (p == u) || (p == v) || (p == w) )
00228 {
00229 continue;
00230 }
00231 if (isInTriangle(A,B,C,point(p)))
00232 {
00233 return false;
00234 }
00235 }
00236 return true;
00237 }
00238 template<class P>
00239 inline int
00240 Triangulator<P>::nbPoints() const
00241 {
00242 return contour_.size();
00243 }
00244 template<class P>
00245 inline const P&
00246 Triangulator<P>::point(const int i) const
00247 {
00248 return *contour_[V_[i]];
00249 }
00250 template<class P>
00251 inline void
00252 Triangulator<P>::addFace(const int u,const int v,const int w)
00253 {
00254 faces_.push_back(Face(contour_[V_[u]],
00255 contour_[V_[v]],
00256 contour_[V_[w]]));
00257 };
00258 #endif // XDKWRL_TRIANGULATOR_H
00259
00260
00261
00262
00263
00264