00001
00002 #ifndef vgl_polygon_txx_
00003 #define vgl_polygon_txx_
00004
00005 #include "vgl_polygon.h"
00006
00007
00008
00009 #include "vgl_intersection.h"
00010 #include "vgl_line_2d.h"
00011 #include "vgl_tolerance.h"
00012
00013 #include <vcl_iostream.h>
00014 #include <vcl_set.h>
00015 #include <vcl_cmath.h>
00016 #include <vcl_cassert.h>
00017 #include <vcl_algorithm.h>
00018
00019
00020
00021 template <class T>
00022 vgl_polygon<T>::vgl_polygon(vgl_point_2d<T> const p[], int n):
00023 sheets_(1, sheet_t(n))
00024 {
00025 for (int i = 0; i < n; ++i)
00026 sheets_[0][i].set(p[i].x(), p[i].y());
00027 }
00028
00029 template <class T>
00030 vgl_polygon<T>::vgl_polygon(T const* x, T const* y, int n)
00031 : sheets_(1, sheet_t(n))
00032 {
00033 for (int i = 0; i < n; ++i)
00034 sheets_[0][i].set(x[i], y[i]);
00035 }
00036
00037 template <class T>
00038 vgl_polygon<T>::vgl_polygon(T const x_y[], int n)
00039 : sheets_(1, sheet_t(n))
00040 {
00041 for (int i = 0; i < n; ++i)
00042 sheets_[0][i].set(x_y[2*i], x_y[2*i+1]);
00043 }
00044
00045 template <class T>
00046 void vgl_polygon<T>::add_contour(point_t const p[], int n)
00047 {
00048 sheet_t s(n);
00049 for (int i = 0; i < n; ++i)
00050 s[i].set(p[i].x(), p[i].y());
00051 sheets_.push_back(s);
00052 }
00053
00054 template <class T>
00055 void vgl_polygon<T>::add_contour(T const* x, T const* y, int n)
00056 {
00057 sheet_t s(n);
00058 for (int i = 0; i < n; ++i)
00059 s[i].set(x[i], y[i]);
00060 sheets_.push_back(s);
00061 }
00062
00063 template <class T>
00064 void vgl_polygon<T>::add_contour(T const x_y[], int n)
00065 {
00066 sheet_t s(n);
00067 for (int i = 0; i < n; ++i)
00068 s[i].set(x_y[2*i], x_y[2*i+1]);
00069 sheets_.push_back(s);
00070 }
00071
00072
00073
00074 template <class T>
00075 void vgl_polygon<T>::push_back(T x, T y)
00076 {
00077 sheets_[sheets_.size()-1].push_back(point_t(x,y));
00078 }
00079
00080 template <class T>
00081 void vgl_polygon<T>::push_back(point_t const& p)
00082 {
00083 sheets_[sheets_.size()-1].push_back(p);
00084 }
00085
00086 template <class T>
00087 bool vgl_polygon<T>::contains(T x, T y) const
00088 {
00089 bool c = false;
00090 for (unsigned int s=0; s < sheets_.size(); ++s)
00091 {
00092 sheet_t const& pgon = sheets_[s];
00093 int n = int(pgon.size());
00094 for (int i = 0, j = n-1; i < n; j = i++)
00095 {
00096 const vgl_point_2d<T> &p_i = pgon[i];
00097 const vgl_point_2d<T> &p_j = pgon[j];
00098
00099
00100 if ((p_j.x() - x) * (p_i.y() - y) == (p_i.x() - x) * (p_j.y() - y) &&
00101 (((p_i.x()<=x) && (x<=p_j.x())) || ((p_j.x()<=x) && (x<=p_i.x()))) &&
00102 (((p_i.y()<=y) && (y<=p_j.y())) || ((p_j.y()<=y) && (y<=p_i.y()))))
00103 return true;
00104
00105 if ((((p_i.y()<=y) && (y<p_j.y())) || ((p_j.y()<=y) && (y<p_i.y()))) &&
00106 (x < (p_j.x() - p_i.x()) * (y - p_i.y()) / (p_j.y() - p_i.y()) + p_i.x()))
00107 c = !c;
00108 }
00109 }
00110 return c;
00111 }
00112
00113 template <class T>
00114 vcl_ostream& vgl_polygon<T>::print(vcl_ostream& os) const
00115 {
00116 if (sheets_.size() == 0)
00117 os << "Empty polygon\n";
00118 else {
00119 os << "Polygon with " << num_sheets() << " sheets:\n";
00120 for (unsigned int s = 0; s < sheets_.size(); ++s)
00121 {
00122 os << "Sheet " << s << ' ';
00123 if (sheets_[s].size()==0)
00124 os << "(empty)";
00125 else
00126 for (unsigned int p = 0; p < sheets_[s].size(); ++p)
00127 os << '(' << sheets_[s][p].x() << ',' << sheets_[s][p].y() << ") ";
00128 os << '\n';
00129 }
00130 }
00131 return os;
00132 }
00133
00134 template <class T>
00135 vgl_polygon_sheet_as_array<T>::vgl_polygon_sheet_as_array(vgl_polygon<T> const& p)
00136 {
00137 assert(p.num_sheets()==1);
00138 n = int(p[0].size());
00139 x = new T[n*2];
00140 y = x + n;
00141 for (int v = 0; v < n; ++v)
00142 {
00143 x[v] = p[0][v].x();
00144 y[v] = p[0][v].y();
00145 }
00146 }
00147
00148 template <class T>
00149 vgl_polygon_sheet_as_array<T>::vgl_polygon_sheet_as_array(typename vgl_polygon<T>::sheet_t const& p)
00150 {
00151 n = int(p.size());
00152 x = new T[n*2];
00153 y = x + n;
00154 for (int v = 0; v < n; ++v)
00155 {
00156 x[v] = p[v].x();
00157 y[v] = p[v].y();
00158 }
00159 }
00160
00161 template <class T>
00162 vgl_polygon_sheet_as_array<T>::~vgl_polygon_sheet_as_array()
00163 {
00164 delete [] x;
00165
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175 template <class T>
00176 void vgl_selfintersections(vgl_polygon<T> const& p,
00177 vcl_vector<vcl_pair<unsigned int,unsigned int> >& e1,
00178 vcl_vector<vcl_pair<unsigned int,unsigned int> >& e2,
00179 vcl_vector<vgl_point_2d<T> >& ip)
00180 {
00181 const T tol = vcl_sqrt(vgl_tolerance<T>::position);
00182 vcl_vector<unsigned int> offsets(p.num_sheets()+1,0);
00183 for (unsigned int s = 0; s < p.num_sheets(); ++s) {
00184 offsets[s+1] = offsets[s]+(unsigned int)(p[s].size());
00185 }
00186 e1.clear();
00187 e2.clear();
00188 ip.clear();
00189
00190 typedef vcl_pair<unsigned int, unsigned int> upair;
00191 vcl_set<upair> isect_set;
00192 for (unsigned int s1 = 0; s1 < p.num_sheets(); ++s1)
00193 {
00194 const typename vgl_polygon<T>::sheet_t& sheet1 = p[s1];
00195 if (sheet1.size() < 2)
00196 continue;
00197 for (unsigned int i1=(unsigned int)(sheet1.size()-1), i1n=0; i1n < sheet1.size(); i1=i1n, ++i1n)
00198 {
00199 const vgl_point_2d<T>& v1 = sheet1[i1];
00200 const vgl_point_2d<T>& v2 = sheet1[i1n];
00201
00202
00203 T cx = v1.y()-v2.y();
00204 T cy = v2.x()-v1.x();
00205 T c = v1.x()*v2.y()-v2.x()*v1.y();
00206 T norm = 1/vcl_sqrt(cx*cx+cy*cy);
00207 cx *= norm;
00208 cy *= norm;
00209 c *= norm;
00210
00211 unsigned int idx1 = offsets[s1]+i1;
00212
00213
00214 for (unsigned int s2 = 0; s2 < p.num_sheets(); ++s2)
00215 {
00216 const typename vgl_polygon<T>::sheet_t& sheet2 = p[s2];
00217 const unsigned int size2 = (unsigned int)(sheet2.size());
00218 if (size2 < 2)
00219 continue;
00220 unsigned int start = 0, end = 0;
00221 if (s1 == s2) {
00222 start = (i1n+1)%size2;
00223 end = (i1+size2-1)%size2;
00224 }
00225
00226 T dist = cx*sheet2[start].x()+cy*sheet2[start].y()+c;
00227 bool last_sign = dist > 0;
00228 bool last_zero = vcl_abs(dist) <= tol;
00229 bool first = true;
00230 for (unsigned int i2=start, i2n=(start+1)%size2; i2!=end || first; i2=i2n, i2n=(i2n+1)%size2)
00231 {
00232 const vgl_point_2d<T>& v3 = sheet2[i2];
00233 const vgl_point_2d<T>& v4 = sheet2[i2n];
00234 dist = cx*v4.x()+cy*v4.y()+c;
00235 bool sign = dist > 0;
00236 bool zero = vcl_abs(dist) <= tol;
00237 if (sign != last_sign || zero || last_zero)
00238 {
00239 unsigned int idx2 = offsets[s2]+i2;
00240 upair pair_idx(idx1,idx2);
00241 if (pair_idx.first > pair_idx.second) {
00242 pair_idx = upair(idx2,idx1);
00243 }
00244 vcl_set<upair>::iterator f = isect_set.find(pair_idx);
00245 if (f == isect_set.end())
00246 isect_set.insert(pair_idx);
00247
00248 else if (vgl_intersection(v1,v2,v3,v4,tol)) {
00249
00250 vgl_point_2d<T> ipt;
00251 if (!vgl_intersection(vgl_line_2d<T>(v1,v2),vgl_line_2d<T>(v3,v4),ipt)
00252 || parallel(v2-v1,v4-v3,tol))
00253 {
00254
00255 vgl_vector_2d<T> dir = v2-v1;
00256 normalize(dir);
00257 T t1 = 0;
00258 T t2 = dot_product(dir,v2-v1);
00259 T t3 = dot_product(dir,v3-v1);
00260 T t4 = dot_product(dir,v4-v1);
00261 T t = t1+t2+t3+t4;
00262 t -= vcl_min(vcl_min(t1,t2),vcl_min(t3,t4));
00263 t -= vcl_max(vcl_max(t1,t2),vcl_max(t3,t4));
00264 t /= 2;
00265 ipt = v1 + t*dir;
00266 }
00267 e1.push_back(upair(s2,i2));
00268 e2.push_back(upair(s1,i1));
00269 ip.push_back(ipt);
00270 }
00271 }
00272 last_sign = sign;
00273 last_zero = zero;
00274 first = false;
00275 }
00276 }
00277 }
00278 }
00279 }
00280
00281
00282 #undef VGL_POLYGON_INSTANTIATE
00283 #define VGL_POLYGON_INSTANTIATE(T) \
00284 template class vgl_polygon<T >; \
00285 template struct vgl_polygon_sheet_as_array<T >; \
00286 template vcl_ostream& operator<<(vcl_ostream&,vgl_polygon<T > const&); \
00287 template void vgl_selfintersections(vgl_polygon<T > const& p, \
00288 vcl_vector<vcl_pair<unsigned int,unsigned int> >& e1, \
00289 vcl_vector<vcl_pair<unsigned int,unsigned int> >& e2, \
00290 vcl_vector<vgl_point_2d<T > >& ip)
00291
00292 #endif // vgl_polygon_txx_