annotate DEPENDENCIES/generic/include/boost/polygon/detail/polygon_arbitrary_formation.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 /*
Chris@16 2 Copyright 2008 Intel Corporation
Chris@16 3
Chris@16 4 Use, modification and distribution are subject to the Boost Software License,
Chris@16 5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 http://www.boost.org/LICENSE_1_0.txt).
Chris@16 7 */
Chris@16 8 #ifndef BOOST_POLYGON_POLYGON_ARBITRARY_FORMATION_HPP
Chris@16 9 #define BOOST_POLYGON_POLYGON_ARBITRARY_FORMATION_HPP
Chris@16 10 namespace boost { namespace polygon{
Chris@16 11 template <typename T, typename T2>
Chris@16 12 struct PolyLineArbitraryByConcept {};
Chris@16 13
Chris@16 14 template <typename T>
Chris@16 15 class poly_line_arbitrary_polygon_data;
Chris@16 16 template <typename T>
Chris@16 17 class poly_line_arbitrary_hole_data;
Chris@16 18
Chris@16 19 template <typename Unit>
Chris@16 20 struct scanline_base {
Chris@16 21
Chris@16 22 typedef point_data<Unit> Point;
Chris@16 23 typedef std::pair<Point, Point> half_edge;
Chris@16 24
Chris@16 25 class less_point : public std::binary_function<Point, Point, bool> {
Chris@16 26 public:
Chris@16 27 inline less_point() {}
Chris@16 28 inline bool operator () (const Point& pt1, const Point& pt2) const {
Chris@16 29 if(pt1.get(HORIZONTAL) < pt2.get(HORIZONTAL)) return true;
Chris@16 30 if(pt1.get(HORIZONTAL) == pt2.get(HORIZONTAL)) {
Chris@16 31 if(pt1.get(VERTICAL) < pt2.get(VERTICAL)) return true;
Chris@16 32 }
Chris@16 33 return false;
Chris@16 34 }
Chris@16 35 };
Chris@16 36
Chris@16 37 static inline bool between(Point pt, Point pt1, Point pt2) {
Chris@16 38 less_point lp;
Chris@16 39 if(lp(pt1, pt2))
Chris@16 40 return lp(pt, pt2) && lp(pt1, pt);
Chris@16 41 return lp(pt, pt1) && lp(pt2, pt);
Chris@16 42 }
Chris@16 43
Chris@16 44 template <typename area_type>
Chris@16 45 static inline Unit compute_intercept(const area_type& dy2,
Chris@16 46 const area_type& dx1,
Chris@16 47 const area_type& dx2) {
Chris@16 48 //intercept = dy2 * dx1 / dx2
Chris@16 49 //return (Unit)(((area_type)dy2 * (area_type)dx1) / (area_type)dx2);
Chris@16 50 area_type dx1_q = dx1 / dx2;
Chris@16 51 area_type dx1_r = dx1 % dx2;
Chris@16 52 return dx1_q * dy2 + (dy2 * dx1_r)/dx2;
Chris@16 53 }
Chris@16 54
Chris@16 55 template <typename area_type>
Chris@16 56 static inline bool equal_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) {
Chris@16 57 typedef typename coordinate_traits<Unit>::unsigned_area_type unsigned_product_type;
Chris@16 58 unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1);
Chris@16 59 unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2);
Chris@16 60 int dx1_sign = dx1 < 0 ? -1 : 1;
Chris@16 61 int dx2_sign = dx2 < 0 ? -1 : 1;
Chris@16 62 int dy1_sign = dy1 < 0 ? -1 : 1;
Chris@16 63 int dy2_sign = dy2 < 0 ? -1 : 1;
Chris@16 64 int cross_1_sign = dx2_sign * dy1_sign;
Chris@16 65 int cross_2_sign = dx1_sign * dy2_sign;
Chris@16 66 return cross_1 == cross_2 && (cross_1_sign == cross_2_sign || cross_1 == 0);
Chris@16 67 }
Chris@16 68
Chris@16 69 template <typename T>
Chris@16 70 static inline bool equal_slope_hp(const T& dx1, const T& dy1, const T& dx2, const T& dy2) {
Chris@16 71 return dx1 * dy2 == dx2 * dy1;
Chris@16 72 }
Chris@16 73
Chris@16 74 static inline bool equal_slope(const Unit& x, const Unit& y,
Chris@16 75 const Point& pt1, const Point& pt2) {
Chris@16 76 const Point* pts[2] = {&pt1, &pt2};
Chris@16 77 typedef typename coordinate_traits<Unit>::manhattan_area_type at;
Chris@16 78 at dy2 = (at)pts[1]->get(VERTICAL) - (at)y;
Chris@16 79 at dy1 = (at)pts[0]->get(VERTICAL) - (at)y;
Chris@16 80 at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x;
Chris@16 81 at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x;
Chris@16 82 return equal_slope(dx1, dy1, dx2, dy2);
Chris@16 83 }
Chris@16 84
Chris@16 85 template <typename area_type>
Chris@16 86 static inline bool less_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) {
Chris@16 87 //reflext x and y slopes to right hand side half plane
Chris@16 88 if(dx1 < 0) {
Chris@16 89 dy1 *= -1;
Chris@16 90 dx1 *= -1;
Chris@16 91 } else if(dx1 == 0) {
Chris@16 92 //if the first slope is vertical the first cannot be less
Chris@16 93 return false;
Chris@16 94 }
Chris@16 95 if(dx2 < 0) {
Chris@16 96 dy2 *= -1;
Chris@16 97 dx2 *= -1;
Chris@16 98 } else if(dx2 == 0) {
Chris@16 99 //if the second slope is vertical the first is always less unless it is also vertical, in which case they are equal
Chris@16 100 return dx1 != 0;
Chris@16 101 }
Chris@16 102 typedef typename coordinate_traits<Unit>::unsigned_area_type unsigned_product_type;
Chris@16 103 unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1);
Chris@16 104 unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2);
Chris@16 105 int dx1_sign = dx1 < 0 ? -1 : 1;
Chris@16 106 int dx2_sign = dx2 < 0 ? -1 : 1;
Chris@16 107 int dy1_sign = dy1 < 0 ? -1 : 1;
Chris@16 108 int dy2_sign = dy2 < 0 ? -1 : 1;
Chris@16 109 int cross_1_sign = dx2_sign * dy1_sign;
Chris@16 110 int cross_2_sign = dx1_sign * dy2_sign;
Chris@16 111 if(cross_1_sign < cross_2_sign) return true;
Chris@16 112 if(cross_2_sign < cross_1_sign) return false;
Chris@16 113 if(cross_1_sign == -1) return cross_2 < cross_1;
Chris@16 114 return cross_1 < cross_2;
Chris@16 115 }
Chris@16 116
Chris@16 117 static inline bool less_slope(const Unit& x, const Unit& y,
Chris@16 118 const Point& pt1, const Point& pt2) {
Chris@16 119 const Point* pts[2] = {&pt1, &pt2};
Chris@16 120 //compute y value on edge from pt_ to pts[1] at the x value of pts[0]
Chris@16 121 typedef typename coordinate_traits<Unit>::manhattan_area_type at;
Chris@16 122 at dy2 = (at)pts[1]->get(VERTICAL) - (at)y;
Chris@16 123 at dy1 = (at)pts[0]->get(VERTICAL) - (at)y;
Chris@16 124 at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x;
Chris@16 125 at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x;
Chris@16 126 return less_slope(dx1, dy1, dx2, dy2);
Chris@16 127 }
Chris@16 128
Chris@16 129 //return -1 below, 0 on and 1 above line
Chris@16 130 static inline int on_above_or_below(Point pt, const half_edge& he) {
Chris@16 131 if(pt == he.first || pt == he.second) return 0;
Chris@16 132 if(equal_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second)) return 0;
Chris@16 133 bool less_result = less_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second);
Chris@16 134 int retval = less_result ? -1 : 1;
Chris@16 135 less_point lp;
Chris@16 136 if(lp(he.second, he.first)) retval *= -1;
Chris@16 137 if(!between(pt, he.first, he.second)) retval *= -1;
Chris@16 138 return retval;
Chris@16 139 }
Chris@16 140
Chris@16 141 //returns true is the segment intersects the integer grid square with lower
Chris@16 142 //left corner at point
Chris@16 143 static inline bool intersects_grid(Point pt, const half_edge& he) {
Chris@16 144 if(pt == he.second) return true;
Chris@16 145 if(pt == he.first) return true;
Chris@16 146 rectangle_data<Unit> rect1;
Chris@16 147 set_points(rect1, he.first, he.second);
Chris@16 148 if(contains(rect1, pt, true)) {
Chris@16 149 if(is_vertical(he) || is_horizontal(he)) return true;
Chris@16 150 } else {
Chris@16 151 return false; //can't intersect a grid not within bounding box
Chris@16 152 }
Chris@16 153 Unit x = pt.get(HORIZONTAL);
Chris@16 154 Unit y = pt.get(VERTICAL);
Chris@16 155 if(equal_slope(x, y, he.first, he.second) &&
Chris@16 156 between(pt, he.first, he.second)) return true;
Chris@16 157 Point pt01(pt.get(HORIZONTAL), pt.get(VERTICAL) + 1);
Chris@16 158 Point pt10(pt.get(HORIZONTAL) + 1, pt.get(VERTICAL));
Chris@16 159 Point pt11(pt.get(HORIZONTAL) + 1, pt.get(VERTICAL) + 1);
Chris@16 160 // if(pt01 == he.first) return true;
Chris@16 161 // if(pt10 == he.first) return true;
Chris@16 162 // if(pt11 == he.first) return true;
Chris@16 163 // if(pt01 == he.second) return true;
Chris@16 164 // if(pt10 == he.second) return true;
Chris@16 165 // if(pt11 == he.second) return true;
Chris@16 166 //check non-integer intersections
Chris@16 167 half_edge widget1(pt, pt11);
Chris@16 168 //intersects but not just at pt11
Chris@16 169 if(intersects(widget1, he) && on_above_or_below(pt11, he)) return true;
Chris@16 170 half_edge widget2(pt01, pt10);
Chris@16 171 //intersects but not just at pt01 or 10
Chris@16 172 if(intersects(widget2, he) && on_above_or_below(pt01, he) && on_above_or_below(pt10, he)) return true;
Chris@16 173 return false;
Chris@16 174 }
Chris@16 175
Chris@16 176 static inline Unit evalAtXforYlazy(Unit xIn, Point pt, Point other_pt) {
Chris@16 177 long double
Chris@16 178 evalAtXforYret, evalAtXforYxIn, evalAtXforYx1, evalAtXforYy1, evalAtXforYdx1, evalAtXforYdx,
Chris@16 179 evalAtXforYdy, evalAtXforYx2, evalAtXforYy2, evalAtXforY0;
Chris@16 180 //y = (x - x1)dy/dx + y1
Chris@16 181 //y = (xIn - pt.x)*(other_pt.y-pt.y)/(other_pt.x-pt.x) + pt.y
Chris@16 182 //assert pt.x != other_pt.x
Chris@16 183 if(pt.y() == other_pt.y())
Chris@16 184 return pt.y();
Chris@16 185 evalAtXforYxIn = xIn;
Chris@16 186 evalAtXforYx1 = pt.get(HORIZONTAL);
Chris@16 187 evalAtXforYy1 = pt.get(VERTICAL);
Chris@16 188 evalAtXforYdx1 = evalAtXforYxIn - evalAtXforYx1;
Chris@16 189 evalAtXforY0 = 0;
Chris@16 190 if(evalAtXforYdx1 == evalAtXforY0) return (Unit)evalAtXforYy1;
Chris@16 191 evalAtXforYx2 = other_pt.get(HORIZONTAL);
Chris@16 192 evalAtXforYy2 = other_pt.get(VERTICAL);
Chris@16 193
Chris@16 194 evalAtXforYdx = evalAtXforYx2 - evalAtXforYx1;
Chris@16 195 evalAtXforYdy = evalAtXforYy2 - evalAtXforYy1;
Chris@16 196 evalAtXforYret = ((evalAtXforYdx1) * evalAtXforYdy / evalAtXforYdx + evalAtXforYy1);
Chris@16 197 return (Unit)evalAtXforYret;
Chris@16 198 }
Chris@16 199
Chris@16 200 static inline typename high_precision_type<Unit>::type evalAtXforY(Unit xIn, Point pt, Point other_pt) {
Chris@16 201 typename high_precision_type<Unit>::type
Chris@16 202 evalAtXforYret, evalAtXforYxIn, evalAtXforYx1, evalAtXforYy1, evalAtXforYdx1, evalAtXforYdx,
Chris@16 203 evalAtXforYdy, evalAtXforYx2, evalAtXforYy2, evalAtXforY0;
Chris@16 204 //y = (x - x1)dy/dx + y1
Chris@16 205 //y = (xIn - pt.x)*(other_pt.y-pt.y)/(other_pt.x-pt.x) + pt.y
Chris@16 206 //assert pt.x != other_pt.x
Chris@16 207 typedef typename high_precision_type<Unit>::type high_precision;
Chris@16 208 if(pt.y() == other_pt.y())
Chris@16 209 return (high_precision)pt.y();
Chris@16 210 evalAtXforYxIn = (high_precision)xIn;
Chris@16 211 evalAtXforYx1 = pt.get(HORIZONTAL);
Chris@16 212 evalAtXforYy1 = pt.get(VERTICAL);
Chris@16 213 evalAtXforYdx1 = evalAtXforYxIn - evalAtXforYx1;
Chris@16 214 evalAtXforY0 = high_precision(0);
Chris@16 215 if(evalAtXforYdx1 == evalAtXforY0) return evalAtXforYret = evalAtXforYy1;
Chris@16 216 evalAtXforYx2 = (high_precision)other_pt.get(HORIZONTAL);
Chris@16 217 evalAtXforYy2 = (high_precision)other_pt.get(VERTICAL);
Chris@16 218
Chris@16 219 evalAtXforYdx = evalAtXforYx2 - evalAtXforYx1;
Chris@16 220 evalAtXforYdy = evalAtXforYy2 - evalAtXforYy1;
Chris@16 221 evalAtXforYret = ((evalAtXforYdx1) * evalAtXforYdy / evalAtXforYdx + evalAtXforYy1);
Chris@16 222 return evalAtXforYret;
Chris@16 223 }
Chris@16 224
Chris@16 225 struct evalAtXforYPack {
Chris@16 226 typename high_precision_type<Unit>::type
Chris@16 227 evalAtXforYret, evalAtXforYxIn, evalAtXforYx1, evalAtXforYy1, evalAtXforYdx1, evalAtXforYdx,
Chris@16 228 evalAtXforYdy, evalAtXforYx2, evalAtXforYy2, evalAtXforY0;
Chris@16 229 inline const typename high_precision_type<Unit>::type& evalAtXforY(Unit xIn, Point pt, Point other_pt) {
Chris@16 230 //y = (x - x1)dy/dx + y1
Chris@16 231 //y = (xIn - pt.x)*(other_pt.y-pt.y)/(other_pt.x-pt.x) + pt.y
Chris@16 232 //assert pt.x != other_pt.x
Chris@16 233 typedef typename high_precision_type<Unit>::type high_precision;
Chris@16 234 if(pt.y() == other_pt.y()) {
Chris@16 235 evalAtXforYret = (high_precision)pt.y();
Chris@16 236 return evalAtXforYret;
Chris@16 237 }
Chris@16 238 evalAtXforYxIn = (high_precision)xIn;
Chris@16 239 evalAtXforYx1 = pt.get(HORIZONTAL);
Chris@16 240 evalAtXforYy1 = pt.get(VERTICAL);
Chris@16 241 evalAtXforYdx1 = evalAtXforYxIn - evalAtXforYx1;
Chris@16 242 evalAtXforY0 = high_precision(0);
Chris@16 243 if(evalAtXforYdx1 == evalAtXforY0) return evalAtXforYret = evalAtXforYy1;
Chris@16 244 evalAtXforYx2 = (high_precision)other_pt.get(HORIZONTAL);
Chris@16 245 evalAtXforYy2 = (high_precision)other_pt.get(VERTICAL);
Chris@16 246
Chris@16 247 evalAtXforYdx = evalAtXforYx2 - evalAtXforYx1;
Chris@16 248 evalAtXforYdy = evalAtXforYy2 - evalAtXforYy1;
Chris@16 249 evalAtXforYret = ((evalAtXforYdx1) * evalAtXforYdy / evalAtXforYdx + evalAtXforYy1);
Chris@16 250 return evalAtXforYret;
Chris@16 251 }
Chris@16 252 };
Chris@16 253
Chris@16 254 static inline bool is_vertical(const half_edge& he) {
Chris@16 255 return he.first.get(HORIZONTAL) == he.second.get(HORIZONTAL);
Chris@16 256 }
Chris@16 257
Chris@16 258 static inline bool is_horizontal(const half_edge& he) {
Chris@16 259 return he.first.get(VERTICAL) == he.second.get(VERTICAL);
Chris@16 260 }
Chris@16 261
Chris@16 262 static inline bool is_45_degree(const half_edge& he) {
Chris@16 263 return euclidean_distance(he.first, he.second, HORIZONTAL) == euclidean_distance(he.first, he.second, VERTICAL);
Chris@16 264 }
Chris@16 265
Chris@16 266 //scanline comparator functor
Chris@16 267 class less_half_edge : public std::binary_function<half_edge, half_edge, bool> {
Chris@16 268 private:
Chris@16 269 Unit *x_; //x value at which to apply comparison
Chris@16 270 int *justBefore_;
Chris@16 271 evalAtXforYPack * pack_;
Chris@16 272 public:
Chris@16 273 inline less_half_edge() : x_(0), justBefore_(0), pack_(0) {}
Chris@16 274 inline less_half_edge(Unit *x, int *justBefore, evalAtXforYPack * packIn) : x_(x), justBefore_(justBefore), pack_(packIn) {}
Chris@16 275 inline less_half_edge(const less_half_edge& that) : x_(that.x_), justBefore_(that.justBefore_),
Chris@16 276 pack_(that.pack_){}
Chris@16 277 inline less_half_edge& operator=(const less_half_edge& that) {
Chris@16 278 x_ = that.x_;
Chris@16 279 justBefore_ = that.justBefore_;
Chris@16 280 pack_ = that.pack_;
Chris@16 281 return *this; }
Chris@16 282 inline bool operator () (const half_edge& elm1, const half_edge& elm2) const {
Chris@16 283 if((std::max)(elm1.first.y(), elm1.second.y()) < (std::min)(elm2.first.y(), elm2.second.y()))
Chris@16 284 return true;
Chris@16 285 if((std::min)(elm1.first.y(), elm1.second.y()) > (std::max)(elm2.first.y(), elm2.second.y()))
Chris@16 286 return false;
Chris@16 287
Chris@16 288 //check if either x of elem1 is equal to x_
Chris@16 289 Unit localx = *x_;
Chris@16 290 Unit elm1y = 0;
Chris@16 291 bool elm1_at_x = false;
Chris@16 292 if(localx == elm1.first.get(HORIZONTAL)) {
Chris@16 293 elm1_at_x = true;
Chris@16 294 elm1y = elm1.first.get(VERTICAL);
Chris@16 295 } else if(localx == elm1.second.get(HORIZONTAL)) {
Chris@16 296 elm1_at_x = true;
Chris@16 297 elm1y = elm1.second.get(VERTICAL);
Chris@16 298 }
Chris@16 299 Unit elm2y = 0;
Chris@16 300 bool elm2_at_x = false;
Chris@16 301 if(localx == elm2.first.get(HORIZONTAL)) {
Chris@16 302 elm2_at_x = true;
Chris@16 303 elm2y = elm2.first.get(VERTICAL);
Chris@16 304 } else if(localx == elm2.second.get(HORIZONTAL)) {
Chris@16 305 elm2_at_x = true;
Chris@16 306 elm2y = elm2.second.get(VERTICAL);
Chris@16 307 }
Chris@16 308 bool retval = false;
Chris@16 309 if(!(elm1_at_x && elm2_at_x)) {
Chris@16 310 //at least one of the segments doesn't have an end point a the current x
Chris@16 311 //-1 below, 1 above
Chris@16 312 int pt1_oab = on_above_or_below(elm1.first, half_edge(elm2.first, elm2.second));
Chris@16 313 int pt2_oab = on_above_or_below(elm1.second, half_edge(elm2.first, elm2.second));
Chris@16 314 if(pt1_oab == pt2_oab) {
Chris@16 315 if(pt1_oab == -1)
Chris@16 316 retval = true; //pt1 is below elm2 so elm1 is below elm2
Chris@16 317 } else {
Chris@16 318 //the segments can't cross so elm2 is on whatever side of elm1 that one of its ends is
Chris@16 319 int pt3_oab = on_above_or_below(elm2.first, half_edge(elm1.first, elm1.second));
Chris@16 320 if(pt3_oab == 1)
Chris@16 321 retval = true; //elm1's point is above elm1
Chris@16 322 }
Chris@16 323 } else {
Chris@16 324 if(elm1y < elm2y) {
Chris@16 325 retval = true;
Chris@16 326 } else if(elm1y == elm2y) {
Chris@16 327 if(elm1 == elm2)
Chris@16 328 return false;
Chris@16 329 retval = less_slope(elm1.second.get(HORIZONTAL) - elm1.first.get(HORIZONTAL),
Chris@16 330 elm1.second.get(VERTICAL) - elm1.first.get(VERTICAL),
Chris@16 331 elm2.second.get(HORIZONTAL) - elm2.first.get(HORIZONTAL),
Chris@16 332 elm2.second.get(VERTICAL) - elm2.first.get(VERTICAL));
Chris@16 333 retval = ((*justBefore_) != 0) ^ retval;
Chris@16 334 }
Chris@16 335 }
Chris@16 336 return retval;
Chris@16 337 }
Chris@16 338 };
Chris@16 339
Chris@16 340 template <typename unsigned_product_type>
Chris@16 341 static inline void unsigned_mod(unsigned_product_type& result, int& result_sign, unsigned_product_type a, int a_sign, unsigned_product_type b, int b_sign) {
Chris@16 342 result = a % b;
Chris@16 343 result_sign = a_sign;
Chris@16 344 }
Chris@16 345
Chris@16 346 template <typename unsigned_product_type>
Chris@16 347 static inline void unsigned_add(unsigned_product_type& result, int& result_sign, unsigned_product_type a, int a_sign, unsigned_product_type b, int b_sign) {
Chris@16 348 int switcher = 0;
Chris@16 349 if(a_sign < 0) switcher += 1;
Chris@16 350 if(b_sign < 0) switcher += 2;
Chris@16 351 if(a < b) switcher += 4;
Chris@16 352 switch (switcher) {
Chris@16 353 case 0: //both positive
Chris@16 354 result = a + b;
Chris@16 355 result_sign = 1;
Chris@16 356 break;
Chris@16 357 case 1: //a is negative
Chris@16 358 result = a - b;
Chris@16 359 result_sign = -1;
Chris@16 360 break;
Chris@16 361 case 2: //b is negative
Chris@16 362 result = a - b;
Chris@16 363 result_sign = 1;
Chris@16 364 break;
Chris@16 365 case 3: //both negative
Chris@16 366 result = a + b;
Chris@16 367 result_sign = -1;
Chris@16 368 break;
Chris@16 369 case 4: //both positive
Chris@16 370 result = a + b;
Chris@16 371 result_sign = 1;
Chris@16 372 break;
Chris@16 373 case 5: //a is negative
Chris@16 374 result = b - a;
Chris@16 375 result_sign = 1;
Chris@16 376 break;
Chris@16 377 case 6: //b is negative
Chris@16 378 result = b - a;
Chris@16 379 result_sign = -1;
Chris@16 380 break;
Chris@16 381 case 7: //both negative
Chris@16 382 result = b + a;
Chris@16 383 result_sign = -1;
Chris@16 384 break;
Chris@16 385 };
Chris@16 386 }
Chris@16 387
Chris@16 388 struct compute_intersection_pack {
Chris@16 389 typedef typename high_precision_type<Unit>::type high_precision;
Chris@16 390 high_precision y_high, dx1, dy1, dx2, dy2, x11, x21, y11, y21, x_num, y_num, x_den, y_den, x, y;
Chris@16 391 static inline bool compute_lazy_intersection(Point& intersection, const half_edge& he1, const half_edge& he2,
Chris@16 392 bool projected = false, bool round_closest = false) {
Chris@16 393 long double y_high, dx1, dy1, dx2, dy2, x11, x21, y11, y21, x_num, y_num, x_den, y_den, x, y;
Chris@16 394 typedef rectangle_data<Unit> Rectangle;
Chris@16 395 Rectangle rect1, rect2;
Chris@16 396 set_points(rect1, he1.first, he1.second);
Chris@16 397 set_points(rect2, he2.first, he2.second);
Chris@16 398 if(!projected && !::boost::polygon::intersects(rect1, rect2, true)) return false;
Chris@16 399 if(is_vertical(he1)) {
Chris@16 400 if(is_vertical(he2)) return false;
Chris@16 401 y_high = evalAtXforYlazy(he1.first.get(HORIZONTAL), he2.first, he2.second);
Chris@16 402 Unit y_local = (Unit)y_high;
Chris@16 403 if(y_high < y_local) --y_local;
Chris@16 404 if(projected || contains(rect1.get(VERTICAL), y_local, true)) {
Chris@16 405 intersection = Point(he1.first.get(HORIZONTAL), y_local);
Chris@16 406 return true;
Chris@16 407 } else {
Chris@16 408 return false;
Chris@16 409 }
Chris@16 410 } else if(is_vertical(he2)) {
Chris@16 411 y_high = evalAtXforYlazy(he2.first.get(HORIZONTAL), he1.first, he1.second);
Chris@16 412 Unit y_local = (Unit)y_high;
Chris@16 413 if(y_high < y_local) --y_local;
Chris@16 414 if(projected || contains(rect2.get(VERTICAL), y_local, true)) {
Chris@16 415 intersection = Point(he2.first.get(HORIZONTAL), y_local);
Chris@16 416 return true;
Chris@16 417 } else {
Chris@16 418 return false;
Chris@16 419 }
Chris@16 420 }
Chris@16 421 //the bounding boxes of the two line segments intersect, so we check closer to find the intersection point
Chris@16 422 dy2 = (he2.second.get(VERTICAL)) -
Chris@16 423 (he2.first.get(VERTICAL));
Chris@16 424 dy1 = (he1.second.get(VERTICAL)) -
Chris@16 425 (he1.first.get(VERTICAL));
Chris@16 426 dx2 = (he2.second.get(HORIZONTAL)) -
Chris@16 427 (he2.first.get(HORIZONTAL));
Chris@16 428 dx1 = (he1.second.get(HORIZONTAL)) -
Chris@16 429 (he1.first.get(HORIZONTAL));
Chris@16 430 if(equal_slope_hp(dx1, dy1, dx2, dy2)) return false;
Chris@16 431 //the line segments have different slopes
Chris@16 432 //we can assume that the line segments are not vertical because such an intersection is handled elsewhere
Chris@16 433 x11 = (he1.first.get(HORIZONTAL));
Chris@16 434 x21 = (he2.first.get(HORIZONTAL));
Chris@16 435 y11 = (he1.first.get(VERTICAL));
Chris@16 436 y21 = (he2.first.get(VERTICAL));
Chris@16 437 //Unit exp_x = ((at)x11 * (at)dy1 * (at)dx2 - (at)x21 * (at)dy2 * (at)dx1 + (at)y21 * (at)dx1 * (at)dx2 - (at)y11 * (at)dx1 * (at)dx2) / ((at)dy1 * (at)dx2 - (at)dy2 * (at)dx1);
Chris@16 438 //Unit exp_y = ((at)y11 * (at)dx1 * (at)dy2 - (at)y21 * (at)dx2 * (at)dy1 + (at)x21 * (at)dy1 * (at)dy2 - (at)x11 * (at)dy1 * (at)dy2) / ((at)dx1 * (at)dy2 - (at)dx2 * (at)dy1);
Chris@16 439 x_num = (x11 * dy1 * dx2 - x21 * dy2 * dx1 + y21 * dx1 * dx2 - y11 * dx1 * dx2);
Chris@16 440 x_den = (dy1 * dx2 - dy2 * dx1);
Chris@16 441 y_num = (y11 * dx1 * dy2 - y21 * dx2 * dy1 + x21 * dy1 * dy2 - x11 * dy1 * dy2);
Chris@16 442 y_den = (dx1 * dy2 - dx2 * dy1);
Chris@16 443 x = x_num / x_den;
Chris@16 444 y = y_num / y_den;
Chris@16 445 //std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << "\n";
Chris@16 446 //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << "\n";
Chris@16 447 //Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
Chris@16 448 //Unit exp_y = compute_x_intercept<at>(y11, y21, x11, x21, dx1, dx2, dy1, dy2);
Chris@16 449 if(round_closest) {
Chris@16 450 x = x + 0.5;
Chris@16 451 y = y + 0.5;
Chris@16 452 }
Chris@16 453 Unit x_unit = (Unit)(x);
Chris@16 454 Unit y_unit = (Unit)(y);
Chris@16 455 //truncate downward if it went up due to negative number
Chris@16 456 if(x < x_unit) --x_unit;
Chris@16 457 if(y < y_unit) --y_unit;
Chris@16 458 if(is_horizontal(he1))
Chris@16 459 y_unit = he1.first.y();
Chris@16 460 if(is_horizontal(he2))
Chris@16 461 y_unit = he2.first.y();
Chris@16 462 //if(x != exp_x || y != exp_y)
Chris@16 463 // std::cout << exp_x << " " << exp_y << " " << x << " " << y << "\n";
Chris@16 464 //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second);
Chris@16 465 //Unit y2 = evalAtXforY(exp_x, he2.first, he2.second);
Chris@16 466 //std::cout << exp_x << " " << exp_y << " " << y1 << " " << y2 << "\n";
Chris@16 467 Point result(x_unit, y_unit);
Chris@16 468 if(!projected && !contains(rect1, result, true)) return false;
Chris@16 469 if(!projected && !contains(rect2, result, true)) return false;
Chris@16 470 if(projected) {
Chris@16 471 rectangle_data<long double> inf_rect(-(long double)(std::numeric_limits<Unit>::max)(),
Chris@16 472 -(long double) (std::numeric_limits<Unit>::max)(),
Chris@16 473 (long double)(std::numeric_limits<Unit>::max)(),
Chris@16 474 (long double) (std::numeric_limits<Unit>::max)() );
Chris@16 475 if(contains(inf_rect, point_data<long double>(x, y), true)) {
Chris@16 476 intersection = result;
Chris@16 477 return true;
Chris@16 478 } else
Chris@16 479 return false;
Chris@16 480 }
Chris@16 481 intersection = result;
Chris@16 482 return true;
Chris@16 483 }
Chris@16 484
Chris@16 485 inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2,
Chris@16 486 bool projected = false, bool round_closest = false) {
Chris@16 487 if(!projected && !intersects(he1, he2))
Chris@16 488 return false;
Chris@16 489 bool lazy_success = compute_lazy_intersection(intersection, he1, he2, projected);
Chris@16 490 if(!projected) {
Chris@16 491 if(lazy_success) {
Chris@16 492 if(intersects_grid(intersection, he1) &&
Chris@16 493 intersects_grid(intersection, he2))
Chris@16 494 return true;
Chris@16 495 }
Chris@16 496 } else {
Chris@16 497 return lazy_success;
Chris@16 498 }
Chris@16 499 return compute_exact_intersection(intersection, he1, he2, projected, round_closest);
Chris@16 500 }
Chris@16 501
Chris@16 502 inline bool compute_exact_intersection(Point& intersection, const half_edge& he1, const half_edge& he2,
Chris@16 503 bool projected = false, bool round_closest = false) {
Chris@16 504 if(!projected && !intersects(he1, he2))
Chris@16 505 return false;
Chris@16 506 typedef rectangle_data<Unit> Rectangle;
Chris@16 507 Rectangle rect1, rect2;
Chris@16 508 set_points(rect1, he1.first, he1.second);
Chris@16 509 set_points(rect2, he2.first, he2.second);
Chris@16 510 if(!::boost::polygon::intersects(rect1, rect2, true)) return false;
Chris@16 511 if(is_vertical(he1)) {
Chris@16 512 if(is_vertical(he2)) return false;
Chris@16 513 y_high = evalAtXforY(he1.first.get(HORIZONTAL), he2.first, he2.second);
Chris@16 514 Unit y = convert_high_precision_type<Unit>(y_high);
Chris@16 515 if(y_high < (high_precision)y) --y;
Chris@16 516 if(contains(rect1.get(VERTICAL), y, true)) {
Chris@16 517 intersection = Point(he1.first.get(HORIZONTAL), y);
Chris@16 518 return true;
Chris@16 519 } else {
Chris@16 520 return false;
Chris@16 521 }
Chris@16 522 } else if(is_vertical(he2)) {
Chris@16 523 y_high = evalAtXforY(he2.first.get(HORIZONTAL), he1.first, he1.second);
Chris@16 524 Unit y = convert_high_precision_type<Unit>(y_high);
Chris@16 525 if(y_high < (high_precision)y) --y;
Chris@16 526 if(contains(rect2.get(VERTICAL), y, true)) {
Chris@16 527 intersection = Point(he2.first.get(HORIZONTAL), y);
Chris@16 528 return true;
Chris@16 529 } else {
Chris@16 530 return false;
Chris@16 531 }
Chris@16 532 }
Chris@16 533 //the bounding boxes of the two line segments intersect, so we check closer to find the intersection point
Chris@16 534 dy2 = (high_precision)(he2.second.get(VERTICAL)) -
Chris@16 535 (high_precision)(he2.first.get(VERTICAL));
Chris@16 536 dy1 = (high_precision)(he1.second.get(VERTICAL)) -
Chris@16 537 (high_precision)(he1.first.get(VERTICAL));
Chris@16 538 dx2 = (high_precision)(he2.second.get(HORIZONTAL)) -
Chris@16 539 (high_precision)(he2.first.get(HORIZONTAL));
Chris@16 540 dx1 = (high_precision)(he1.second.get(HORIZONTAL)) -
Chris@16 541 (high_precision)(he1.first.get(HORIZONTAL));
Chris@16 542 if(equal_slope_hp(dx1, dy1, dx2, dy2)) return false;
Chris@16 543 //the line segments have different slopes
Chris@16 544 //we can assume that the line segments are not vertical because such an intersection is handled elsewhere
Chris@16 545 x11 = (high_precision)(he1.first.get(HORIZONTAL));
Chris@16 546 x21 = (high_precision)(he2.first.get(HORIZONTAL));
Chris@16 547 y11 = (high_precision)(he1.first.get(VERTICAL));
Chris@16 548 y21 = (high_precision)(he2.first.get(VERTICAL));
Chris@16 549 //Unit exp_x = ((at)x11 * (at)dy1 * (at)dx2 - (at)x21 * (at)dy2 * (at)dx1 + (at)y21 * (at)dx1 * (at)dx2 - (at)y11 * (at)dx1 * (at)dx2) / ((at)dy1 * (at)dx2 - (at)dy2 * (at)dx1);
Chris@16 550 //Unit exp_y = ((at)y11 * (at)dx1 * (at)dy2 - (at)y21 * (at)dx2 * (at)dy1 + (at)x21 * (at)dy1 * (at)dy2 - (at)x11 * (at)dy1 * (at)dy2) / ((at)dx1 * (at)dy2 - (at)dx2 * (at)dy1);
Chris@16 551 x_num = (x11 * dy1 * dx2 - x21 * dy2 * dx1 + y21 * dx1 * dx2 - y11 * dx1 * dx2);
Chris@16 552 x_den = (dy1 * dx2 - dy2 * dx1);
Chris@16 553 y_num = (y11 * dx1 * dy2 - y21 * dx2 * dy1 + x21 * dy1 * dy2 - x11 * dy1 * dy2);
Chris@16 554 y_den = (dx1 * dy2 - dx2 * dy1);
Chris@16 555 x = x_num / x_den;
Chris@16 556 y = y_num / y_den;
Chris@16 557 //std::cout << x << " " << y << "\n";
Chris@16 558 //std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << "\n";
Chris@16 559 //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << "\n";
Chris@16 560 //Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
Chris@16 561 //Unit exp_y = compute_x_intercept<at>(y11, y21, x11, x21, dx1, dx2, dy1, dy2);
Chris@16 562 if(round_closest) {
Chris@16 563 x = x + (high_precision)0.5;
Chris@16 564 y = y + (high_precision)0.5;
Chris@16 565 }
Chris@16 566 Unit x_unit = convert_high_precision_type<Unit>(x);
Chris@16 567 Unit y_unit = convert_high_precision_type<Unit>(y);
Chris@16 568 //truncate downward if it went up due to negative number
Chris@16 569 if(x < (high_precision)x_unit) --x_unit;
Chris@16 570 if(y < (high_precision)y_unit) --y_unit;
Chris@16 571 if(is_horizontal(he1))
Chris@16 572 y_unit = he1.first.y();
Chris@16 573 if(is_horizontal(he2))
Chris@16 574 y_unit = he2.first.y();
Chris@16 575 //if(x != exp_x || y != exp_y)
Chris@16 576 // std::cout << exp_x << " " << exp_y << " " << x << " " << y << "\n";
Chris@16 577 //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second);
Chris@16 578 //Unit y2 = evalAtXforY(exp_x, he2.first, he2.second);
Chris@16 579 //std::cout << exp_x << " " << exp_y << " " << y1 << " " << y2 << "\n";
Chris@16 580 Point result(x_unit, y_unit);
Chris@16 581 if(!contains(rect1, result, true)) return false;
Chris@16 582 if(!contains(rect2, result, true)) return false;
Chris@16 583 if(projected) {
Chris@16 584 high_precision b1 = (high_precision) (std::numeric_limits<Unit>::min)();
Chris@16 585 high_precision b2 = (high_precision) (std::numeric_limits<Unit>::max)();
Chris@16 586 if(x > b2 || y > b2 || x < b1 || y < b1)
Chris@16 587 return false;
Chris@16 588 }
Chris@16 589 intersection = result;
Chris@16 590 return true;
Chris@16 591 }
Chris@16 592 };
Chris@16 593
Chris@16 594 static inline bool compute_intersection(Point& intersection, const half_edge& he1, const half_edge& he2) {
Chris@16 595 typedef typename high_precision_type<Unit>::type high_precision;
Chris@16 596 typedef rectangle_data<Unit> Rectangle;
Chris@16 597 Rectangle rect1, rect2;
Chris@16 598 set_points(rect1, he1.first, he1.second);
Chris@16 599 set_points(rect2, he2.first, he2.second);
Chris@16 600 if(!::boost::polygon::intersects(rect1, rect2, true)) return false;
Chris@16 601 if(is_vertical(he1)) {
Chris@16 602 if(is_vertical(he2)) return false;
Chris@16 603 high_precision y_high = evalAtXforY(he1.first.get(HORIZONTAL), he2.first, he2.second);
Chris@16 604 Unit y = convert_high_precision_type<Unit>(y_high);
Chris@16 605 if(y_high < (high_precision)y) --y;
Chris@16 606 if(contains(rect1.get(VERTICAL), y, true)) {
Chris@16 607 intersection = Point(he1.first.get(HORIZONTAL), y);
Chris@16 608 return true;
Chris@16 609 } else {
Chris@16 610 return false;
Chris@16 611 }
Chris@16 612 } else if(is_vertical(he2)) {
Chris@16 613 high_precision y_high = evalAtXforY(he2.first.get(HORIZONTAL), he1.first, he1.second);
Chris@16 614 Unit y = convert_high_precision_type<Unit>(y_high);
Chris@16 615 if(y_high < (high_precision)y) --y;
Chris@16 616 if(contains(rect2.get(VERTICAL), y, true)) {
Chris@16 617 intersection = Point(he2.first.get(HORIZONTAL), y);
Chris@16 618 return true;
Chris@16 619 } else {
Chris@16 620 return false;
Chris@16 621 }
Chris@16 622 }
Chris@16 623 //the bounding boxes of the two line segments intersect, so we check closer to find the intersection point
Chris@16 624 high_precision dy2 = (high_precision)(he2.second.get(VERTICAL)) -
Chris@16 625 (high_precision)(he2.first.get(VERTICAL));
Chris@16 626 high_precision dy1 = (high_precision)(he1.second.get(VERTICAL)) -
Chris@16 627 (high_precision)(he1.first.get(VERTICAL));
Chris@16 628 high_precision dx2 = (high_precision)(he2.second.get(HORIZONTAL)) -
Chris@16 629 (high_precision)(he2.first.get(HORIZONTAL));
Chris@16 630 high_precision dx1 = (high_precision)(he1.second.get(HORIZONTAL)) -
Chris@16 631 (high_precision)(he1.first.get(HORIZONTAL));
Chris@16 632 if(equal_slope_hp(dx1, dy1, dx2, dy2)) return false;
Chris@16 633 //the line segments have different slopes
Chris@16 634 //we can assume that the line segments are not vertical because such an intersection is handled elsewhere
Chris@16 635 high_precision x11 = (high_precision)(he1.first.get(HORIZONTAL));
Chris@16 636 high_precision x21 = (high_precision)(he2.first.get(HORIZONTAL));
Chris@16 637 high_precision y11 = (high_precision)(he1.first.get(VERTICAL));
Chris@16 638 high_precision y21 = (high_precision)(he2.first.get(VERTICAL));
Chris@16 639 //Unit exp_x = ((at)x11 * (at)dy1 * (at)dx2 - (at)x21 * (at)dy2 * (at)dx1 + (at)y21 * (at)dx1 * (at)dx2 - (at)y11 * (at)dx1 * (at)dx2) / ((at)dy1 * (at)dx2 - (at)dy2 * (at)dx1);
Chris@16 640 //Unit exp_y = ((at)y11 * (at)dx1 * (at)dy2 - (at)y21 * (at)dx2 * (at)dy1 + (at)x21 * (at)dy1 * (at)dy2 - (at)x11 * (at)dy1 * (at)dy2) / ((at)dx1 * (at)dy2 - (at)dx2 * (at)dy1);
Chris@16 641 high_precision x_num = (x11 * dy1 * dx2 - x21 * dy2 * dx1 + y21 * dx1 * dx2 - y11 * dx1 * dx2);
Chris@16 642 high_precision x_den = (dy1 * dx2 - dy2 * dx1);
Chris@16 643 high_precision y_num = (y11 * dx1 * dy2 - y21 * dx2 * dy1 + x21 * dy1 * dy2 - x11 * dy1 * dy2);
Chris@16 644 high_precision y_den = (dx1 * dy2 - dx2 * dy1);
Chris@16 645 high_precision x = x_num / x_den;
Chris@16 646 high_precision y = y_num / y_den;
Chris@16 647 //std::cout << "cross1 " << dy1 << " " << dx2 << " " << dy1 * dx2 << "\n";
Chris@16 648 //std::cout << "cross2 " << dy2 << " " << dx1 << " " << dy2 * dx1 << "\n";
Chris@16 649 //Unit exp_x = compute_x_intercept<at>(x11, x21, y11, y21, dy1, dy2, dx1, dx2);
Chris@16 650 //Unit exp_y = compute_x_intercept<at>(y11, y21, x11, x21, dx1, dx2, dy1, dy2);
Chris@16 651 Unit x_unit = convert_high_precision_type<Unit>(x);
Chris@16 652 Unit y_unit = convert_high_precision_type<Unit>(y);
Chris@16 653 //truncate downward if it went up due to negative number
Chris@16 654 if(x < (high_precision)x_unit) --x_unit;
Chris@16 655 if(y < (high_precision)y_unit) --y_unit;
Chris@16 656 if(is_horizontal(he1))
Chris@16 657 y_unit = he1.first.y();
Chris@16 658 if(is_horizontal(he2))
Chris@16 659 y_unit = he2.first.y();
Chris@16 660 //if(x != exp_x || y != exp_y)
Chris@16 661 // std::cout << exp_x << " " << exp_y << " " << x << " " << y << "\n";
Chris@16 662 //Unit y1 = evalAtXforY(exp_x, he1.first, he1.second);
Chris@16 663 //Unit y2 = evalAtXforY(exp_x, he2.first, he2.second);
Chris@16 664 //std::cout << exp_x << " " << exp_y << " " << y1 << " " << y2 << "\n";
Chris@16 665 Point result(x_unit, y_unit);
Chris@16 666 if(!contains(rect1, result, true)) return false;
Chris@16 667 if(!contains(rect2, result, true)) return false;
Chris@16 668 intersection = result;
Chris@16 669 return true;
Chris@16 670 }
Chris@16 671
Chris@16 672 static inline bool intersects(const half_edge& he1, const half_edge& he2) {
Chris@16 673 typedef rectangle_data<Unit> Rectangle;
Chris@16 674 Rectangle rect1, rect2;
Chris@16 675 set_points(rect1, he1.first, he1.second);
Chris@16 676 set_points(rect2, he2.first, he2.second);
Chris@16 677 if(::boost::polygon::intersects(rect1, rect2, false)) {
Chris@16 678 if(he1.first == he2.first) {
Chris@16 679 if(he1.second != he2.second && equal_slope(he1.first.get(HORIZONTAL), he1.first.get(VERTICAL),
Chris@16 680 he1.second, he2.second)) {
Chris@16 681 return true;
Chris@16 682 } else {
Chris@16 683 return false;
Chris@16 684 }
Chris@16 685 }
Chris@16 686 if(he1.first == he2.second) {
Chris@16 687 if(he1.second != he2.first && equal_slope(he1.first.get(HORIZONTAL), he1.first.get(VERTICAL),
Chris@16 688 he1.second, he2.first)) {
Chris@16 689 return true;
Chris@16 690 } else {
Chris@16 691 return false;
Chris@16 692 }
Chris@16 693 }
Chris@16 694 if(he1.second == he2.first) {
Chris@16 695 if(he1.first != he2.second && equal_slope(he1.second.get(HORIZONTAL), he1.second.get(VERTICAL),
Chris@16 696 he1.first, he2.second)) {
Chris@16 697 return true;
Chris@16 698 } else {
Chris@16 699 return false;
Chris@16 700 }
Chris@16 701 }
Chris@16 702 if(he1.second == he2.second) {
Chris@16 703 if(he1.first != he2.first && equal_slope(he1.second.get(HORIZONTAL), he1.second.get(VERTICAL),
Chris@16 704 he1.first, he2.first)) {
Chris@16 705 return true;
Chris@16 706 } else {
Chris@16 707 return false;
Chris@16 708 }
Chris@16 709 }
Chris@16 710 int oab1 = on_above_or_below(he1.first, he2);
Chris@16 711 if(oab1 == 0 && between(he1.first, he2.first, he2.second)) return true;
Chris@16 712 int oab2 = on_above_or_below(he1.second, he2);
Chris@16 713 if(oab2 == 0 && between(he1.second, he2.first, he2.second)) return true;
Chris@16 714 if(oab1 == oab2 && oab1 != 0) return false; //both points of he1 are on same side of he2
Chris@16 715 int oab3 = on_above_or_below(he2.first, he1);
Chris@16 716 if(oab3 == 0 && between(he2.first, he1.first, he1.second)) return true;
Chris@16 717 int oab4 = on_above_or_below(he2.second, he1);
Chris@16 718 if(oab4 == 0 && between(he2.second, he1.first, he1.second)) return true;
Chris@16 719 if(oab3 == oab4) return false; //both points of he2 are on same side of he1
Chris@16 720 return true; //they must cross
Chris@16 721 }
Chris@16 722 if(is_vertical(he1) && is_vertical(he2) && he1.first.get(HORIZONTAL) == he2.first.get(HORIZONTAL))
Chris@16 723 return ::boost::polygon::intersects(rect1.get(VERTICAL), rect2.get(VERTICAL), false) &&
Chris@16 724 rect1.get(VERTICAL) != rect2.get(VERTICAL);
Chris@16 725 if(is_horizontal(he1) && is_horizontal(he2) && he1.first.get(VERTICAL) == he2.first.get(VERTICAL))
Chris@16 726 return ::boost::polygon::intersects(rect1.get(HORIZONTAL), rect2.get(HORIZONTAL), false) &&
Chris@16 727 rect1.get(HORIZONTAL) != rect2.get(HORIZONTAL);
Chris@16 728 return false;
Chris@16 729 }
Chris@16 730
Chris@16 731 class vertex_half_edge {
Chris@16 732 public:
Chris@16 733 typedef typename high_precision_type<Unit>::type high_precision;
Chris@16 734 Point pt;
Chris@16 735 Point other_pt; // 1, 0 or -1
Chris@16 736 int count; //dxdydTheta
Chris@16 737 inline vertex_half_edge() : pt(), other_pt(), count() {}
Chris@16 738 inline vertex_half_edge(const Point& point, const Point& other_point, int countIn) : pt(point), other_pt(other_point), count(countIn) {}
Chris@16 739 inline vertex_half_edge(const vertex_half_edge& vertex) : pt(vertex.pt), other_pt(vertex.other_pt), count(vertex.count) {}
Chris@16 740 inline vertex_half_edge& operator=(const vertex_half_edge& vertex){
Chris@16 741 pt = vertex.pt; other_pt = vertex.other_pt; count = vertex.count; return *this; }
Chris@16 742 inline vertex_half_edge(const std::pair<Point, Point>& vertex) : pt(), other_pt(), count() {}
Chris@16 743 inline vertex_half_edge& operator=(const std::pair<Point, Point>& vertex){ return *this; }
Chris@16 744 inline bool operator==(const vertex_half_edge& vertex) const {
Chris@16 745 return pt == vertex.pt && other_pt == vertex.other_pt && count == vertex.count; }
Chris@16 746 inline bool operator!=(const vertex_half_edge& vertex) const { return !((*this) == vertex); }
Chris@16 747 inline bool operator==(const std::pair<Point, Point>& vertex) const { return false; }
Chris@16 748 inline bool operator!=(const std::pair<Point, Point>& vertex) const { return !((*this) == vertex); }
Chris@16 749 inline bool operator<(const vertex_half_edge& vertex) const {
Chris@16 750 if(pt.get(HORIZONTAL) < vertex.pt.get(HORIZONTAL)) return true;
Chris@16 751 if(pt.get(HORIZONTAL) == vertex.pt.get(HORIZONTAL)) {
Chris@16 752 if(pt.get(VERTICAL) < vertex.pt.get(VERTICAL)) return true;
Chris@16 753 if(pt.get(VERTICAL) == vertex.pt.get(VERTICAL)) { return less_slope(pt.get(HORIZONTAL), pt.get(VERTICAL),
Chris@16 754 other_pt, vertex.other_pt);
Chris@16 755 }
Chris@16 756 }
Chris@16 757 return false;
Chris@16 758 }
Chris@16 759 inline bool operator>(const vertex_half_edge& vertex) const { return vertex < (*this); }
Chris@16 760 inline bool operator<=(const vertex_half_edge& vertex) const { return !((*this) > vertex); }
Chris@16 761 inline bool operator>=(const vertex_half_edge& vertex) const { return !((*this) < vertex); }
Chris@16 762 inline high_precision evalAtX(Unit xIn) const { return evalAtXforYlazy(xIn, pt, other_pt); }
Chris@16 763 inline bool is_vertical() const {
Chris@16 764 return pt.get(HORIZONTAL) == other_pt.get(HORIZONTAL);
Chris@16 765 }
Chris@16 766 inline bool is_begin() const {
Chris@16 767 return pt.get(HORIZONTAL) < other_pt.get(HORIZONTAL) ||
Chris@16 768 (pt.get(HORIZONTAL) == other_pt.get(HORIZONTAL) &&
Chris@16 769 (pt.get(VERTICAL) < other_pt.get(VERTICAL)));
Chris@16 770 }
Chris@16 771 };
Chris@16 772
Chris@16 773 //when scanning Vertex45 for polygon formation we need a scanline comparator functor
Chris@16 774 class less_vertex_half_edge : public std::binary_function<vertex_half_edge, vertex_half_edge, bool> {
Chris@16 775 private:
Chris@16 776 Unit *x_; //x value at which to apply comparison
Chris@16 777 int *justBefore_;
Chris@16 778 public:
Chris@16 779 inline less_vertex_half_edge() : x_(0), justBefore_(0) {}
Chris@16 780 inline less_vertex_half_edge(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {}
Chris@16 781 inline less_vertex_half_edge(const less_vertex_half_edge& that) : x_(that.x_), justBefore_(that.justBefore_) {}
Chris@16 782 inline less_vertex_half_edge& operator=(const less_vertex_half_edge& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; }
Chris@16 783 inline bool operator () (const vertex_half_edge& elm1, const vertex_half_edge& elm2) const {
Chris@16 784 if((std::max)(elm1.pt.y(), elm1.other_pt.y()) < (std::min)(elm2.pt.y(), elm2.other_pt.y()))
Chris@16 785 return true;
Chris@16 786 if((std::min)(elm1.pt.y(), elm1.other_pt.y()) > (std::max)(elm2.pt.y(), elm2.other_pt.y()))
Chris@16 787 return false;
Chris@16 788 //check if either x of elem1 is equal to x_
Chris@16 789 Unit localx = *x_;
Chris@16 790 Unit elm1y = 0;
Chris@16 791 bool elm1_at_x = false;
Chris@16 792 if(localx == elm1.pt.get(HORIZONTAL)) {
Chris@16 793 elm1_at_x = true;
Chris@16 794 elm1y = elm1.pt.get(VERTICAL);
Chris@16 795 } else if(localx == elm1.other_pt.get(HORIZONTAL)) {
Chris@16 796 elm1_at_x = true;
Chris@16 797 elm1y = elm1.other_pt.get(VERTICAL);
Chris@16 798 }
Chris@16 799 Unit elm2y = 0;
Chris@16 800 bool elm2_at_x = false;
Chris@16 801 if(localx == elm2.pt.get(HORIZONTAL)) {
Chris@16 802 elm2_at_x = true;
Chris@16 803 elm2y = elm2.pt.get(VERTICAL);
Chris@16 804 } else if(localx == elm2.other_pt.get(HORIZONTAL)) {
Chris@16 805 elm2_at_x = true;
Chris@16 806 elm2y = elm2.other_pt.get(VERTICAL);
Chris@16 807 }
Chris@16 808 bool retval = false;
Chris@16 809 if(!(elm1_at_x && elm2_at_x)) {
Chris@16 810 //at least one of the segments doesn't have an end point a the current x
Chris@16 811 //-1 below, 1 above
Chris@16 812 int pt1_oab = on_above_or_below(elm1.pt, half_edge(elm2.pt, elm2.other_pt));
Chris@16 813 int pt2_oab = on_above_or_below(elm1.other_pt, half_edge(elm2.pt, elm2.other_pt));
Chris@16 814 if(pt1_oab == pt2_oab) {
Chris@16 815 if(pt1_oab == -1)
Chris@16 816 retval = true; //pt1 is below elm2 so elm1 is below elm2
Chris@16 817 } else {
Chris@16 818 //the segments can't cross so elm2 is on whatever side of elm1 that one of its ends is
Chris@16 819 int pt3_oab = on_above_or_below(elm2.pt, half_edge(elm1.pt, elm1.other_pt));
Chris@16 820 if(pt3_oab == 1)
Chris@16 821 retval = true; //elm1's point is above elm1
Chris@16 822 }
Chris@16 823 } else {
Chris@16 824 if(elm1y < elm2y) {
Chris@16 825 retval = true;
Chris@16 826 } else if(elm1y == elm2y) {
Chris@16 827 if(elm1.pt == elm2.pt && elm1.other_pt == elm2.other_pt)
Chris@16 828 return false;
Chris@16 829 retval = less_slope(elm1.other_pt.get(HORIZONTAL) - elm1.pt.get(HORIZONTAL),
Chris@16 830 elm1.other_pt.get(VERTICAL) - elm1.pt.get(VERTICAL),
Chris@16 831 elm2.other_pt.get(HORIZONTAL) - elm2.pt.get(HORIZONTAL),
Chris@16 832 elm2.other_pt.get(VERTICAL) - elm2.pt.get(VERTICAL));
Chris@16 833 retval = ((*justBefore_) != 0) ^ retval;
Chris@16 834 }
Chris@16 835 }
Chris@16 836 return retval;
Chris@16 837 }
Chris@16 838 };
Chris@16 839
Chris@16 840 };
Chris@16 841
Chris@16 842 template <typename Unit>
Chris@16 843 class polygon_arbitrary_formation : public scanline_base<Unit> {
Chris@16 844 public:
Chris@16 845 typedef typename scanline_base<Unit>::Point Point;
Chris@16 846 typedef typename scanline_base<Unit>::half_edge half_edge;
Chris@16 847 typedef typename scanline_base<Unit>::vertex_half_edge vertex_half_edge;
Chris@16 848 typedef typename scanline_base<Unit>::less_vertex_half_edge less_vertex_half_edge;
Chris@16 849
Chris@16 850 class poly_line_arbitrary {
Chris@16 851 public:
Chris@16 852 typedef typename std::list<Point>::const_iterator iterator;
Chris@16 853
Chris@16 854 // default constructor of point does not initialize x and y
Chris@16 855 inline poly_line_arbitrary() : points() {} //do nothing default constructor
Chris@16 856
Chris@16 857 // initialize a polygon from x,y values, it is assumed that the first is an x
Chris@16 858 // and that the input is a well behaved polygon
Chris@16 859 template<class iT>
Chris@16 860 inline poly_line_arbitrary& set(iT inputBegin, iT inputEnd) {
Chris@16 861 points.clear(); //just in case there was some old data there
Chris@16 862 while(inputBegin != inputEnd) {
Chris@16 863 points.insert(points.end(), *inputBegin);
Chris@16 864 ++inputBegin;
Chris@16 865 }
Chris@16 866 return *this;
Chris@16 867 }
Chris@16 868
Chris@16 869 // copy constructor (since we have dynamic memory)
Chris@16 870 inline poly_line_arbitrary(const poly_line_arbitrary& that) : points(that.points) {}
Chris@16 871
Chris@16 872 // assignment operator (since we have dynamic memory do a deep copy)
Chris@16 873 inline poly_line_arbitrary& operator=(const poly_line_arbitrary& that) {
Chris@16 874 points = that.points;
Chris@16 875 return *this;
Chris@16 876 }
Chris@16 877
Chris@16 878 // get begin iterator, returns a pointer to a const Unit
Chris@16 879 inline iterator begin() const { return points.begin(); }
Chris@16 880
Chris@16 881 // get end iterator, returns a pointer to a const Unit
Chris@16 882 inline iterator end() const { return points.end(); }
Chris@16 883
Chris@16 884 inline std::size_t size() const { return points.size(); }
Chris@16 885
Chris@16 886 //public data member
Chris@16 887 std::list<Point> points;
Chris@16 888 };
Chris@16 889
Chris@16 890 class active_tail_arbitrary {
Chris@16 891 protected:
Chris@16 892 //data
Chris@16 893 poly_line_arbitrary* tailp_;
Chris@16 894 active_tail_arbitrary *otherTailp_;
Chris@16 895 std::list<active_tail_arbitrary*> holesList_;
Chris@16 896 bool head_;
Chris@16 897 public:
Chris@16 898
Chris@16 899 /**
Chris@16 900 * @brief iterator over coordinates of the figure
Chris@16 901 */
Chris@16 902 typedef typename poly_line_arbitrary::iterator iterator;
Chris@16 903
Chris@16 904 /**
Chris@16 905 * @brief iterator over holes contained within the figure
Chris@16 906 */
Chris@16 907 typedef typename std::list<active_tail_arbitrary*>::const_iterator iteratorHoles;
Chris@16 908
Chris@16 909 //default constructor
Chris@16 910 inline active_tail_arbitrary() : tailp_(), otherTailp_(), holesList_(), head_() {}
Chris@16 911
Chris@16 912 //constructor
Chris@16 913 inline active_tail_arbitrary(const vertex_half_edge& vertex, active_tail_arbitrary* otherTailp = 0) : tailp_(), otherTailp_(), holesList_(), head_() {
Chris@16 914 tailp_ = new poly_line_arbitrary;
Chris@16 915 tailp_->points.push_back(vertex.pt);
Chris@16 916 //bool headArray[4] = {false, true, true, true};
Chris@16 917 bool inverted = vertex.count == -1;
Chris@16 918 head_ = (!vertex.is_vertical) ^ inverted;
Chris@16 919 otherTailp_ = otherTailp;
Chris@16 920 }
Chris@16 921
Chris@16 922 inline active_tail_arbitrary(Point point, active_tail_arbitrary* otherTailp, bool head = true) :
Chris@16 923 tailp_(), otherTailp_(), holesList_(), head_() {
Chris@16 924 tailp_ = new poly_line_arbitrary;
Chris@16 925 tailp_->points.push_back(point);
Chris@16 926 head_ = head;
Chris@16 927 otherTailp_ = otherTailp;
Chris@16 928
Chris@16 929 }
Chris@16 930 inline active_tail_arbitrary(active_tail_arbitrary* otherTailp) :
Chris@16 931 tailp_(), otherTailp_(), holesList_(), head_() {
Chris@16 932 tailp_ = otherTailp->tailp_;
Chris@16 933 otherTailp_ = otherTailp;
Chris@16 934 }
Chris@16 935
Chris@16 936 //copy constructor
Chris@16 937 inline active_tail_arbitrary(const active_tail_arbitrary& that) :
Chris@16 938 tailp_(), otherTailp_(), holesList_(), head_() { (*this) = that; }
Chris@16 939
Chris@16 940 //destructor
Chris@16 941 inline ~active_tail_arbitrary() {
Chris@16 942 destroyContents();
Chris@16 943 }
Chris@16 944
Chris@16 945 //assignment operator
Chris@16 946 inline active_tail_arbitrary& operator=(const active_tail_arbitrary& that) {
Chris@16 947 tailp_ = new poly_line_arbitrary(*(that.tailp_));
Chris@16 948 head_ = that.head_;
Chris@16 949 otherTailp_ = that.otherTailp_;
Chris@16 950 holesList_ = that.holesList_;
Chris@16 951 return *this;
Chris@16 952 }
Chris@16 953
Chris@16 954 //equivalence operator
Chris@16 955 inline bool operator==(const active_tail_arbitrary& b) const {
Chris@16 956 return tailp_ == b.tailp_ && head_ == b.head_;
Chris@16 957 }
Chris@16 958
Chris@16 959 /**
Chris@16 960 * @brief get the pointer to the polyline that this is an active tail of
Chris@16 961 */
Chris@16 962 inline poly_line_arbitrary* getTail() const { return tailp_; }
Chris@16 963
Chris@16 964 /**
Chris@16 965 * @brief get the pointer to the polyline at the other end of the chain
Chris@16 966 */
Chris@16 967 inline poly_line_arbitrary* getOtherTail() const { return otherTailp_->tailp_; }
Chris@16 968
Chris@16 969 /**
Chris@16 970 * @brief get the pointer to the activetail at the other end of the chain
Chris@16 971 */
Chris@16 972 inline active_tail_arbitrary* getOtherActiveTail() const { return otherTailp_; }
Chris@16 973
Chris@16 974 /**
Chris@16 975 * @brief test if another active tail is the other end of the chain
Chris@16 976 */
Chris@16 977 inline bool isOtherTail(const active_tail_arbitrary& b) const { return &b == otherTailp_; }
Chris@16 978
Chris@16 979 /**
Chris@16 980 * @brief update this end of chain pointer to new polyline
Chris@16 981 */
Chris@16 982 inline active_tail_arbitrary& updateTail(poly_line_arbitrary* newTail) { tailp_ = newTail; return *this; }
Chris@16 983
Chris@16 984 inline bool join(active_tail_arbitrary* tail) {
Chris@16 985 if(tail == otherTailp_) {
Chris@16 986 //std::cout << "joining to other tail!\n";
Chris@16 987 return false;
Chris@16 988 }
Chris@16 989 if(tail->head_ == head_) {
Chris@16 990 //std::cout << "joining head to head!\n";
Chris@16 991 return false;
Chris@16 992 }
Chris@16 993 if(!tailp_) {
Chris@16 994 //std::cout << "joining empty tail!\n";
Chris@16 995 return false;
Chris@16 996 }
Chris@16 997 if(!(otherTailp_->head_)) {
Chris@16 998 otherTailp_->copyHoles(*tail);
Chris@16 999 otherTailp_->copyHoles(*this);
Chris@16 1000 } else {
Chris@16 1001 tail->otherTailp_->copyHoles(*this);
Chris@16 1002 tail->otherTailp_->copyHoles(*tail);
Chris@16 1003 }
Chris@16 1004 poly_line_arbitrary* tail1 = tailp_;
Chris@16 1005 poly_line_arbitrary* tail2 = tail->tailp_;
Chris@16 1006 if(head_) std::swap(tail1, tail2);
Chris@16 1007 typename std::list<point_data<Unit> >::reverse_iterator riter = tail1->points.rbegin();
Chris@16 1008 typename std::list<point_data<Unit> >::iterator iter = tail2->points.begin();
Chris@16 1009 if(*riter == *iter) {
Chris@16 1010 tail1->points.pop_back(); //remove duplicate point
Chris@16 1011 }
Chris@16 1012 tail1->points.splice(tail1->points.end(), tail2->points);
Chris@16 1013 delete tail2;
Chris@16 1014 otherTailp_->tailp_ = tail1;
Chris@16 1015 tail->otherTailp_->tailp_ = tail1;
Chris@16 1016 otherTailp_->otherTailp_ = tail->otherTailp_;
Chris@16 1017 tail->otherTailp_->otherTailp_ = otherTailp_;
Chris@16 1018 tailp_ = 0;
Chris@16 1019 tail->tailp_ = 0;
Chris@16 1020 tail->otherTailp_ = 0;
Chris@16 1021 otherTailp_ = 0;
Chris@16 1022 return true;
Chris@16 1023 }
Chris@16 1024
Chris@16 1025 /**
Chris@16 1026 * @brief associate a hole to this active tail by the specified policy
Chris@16 1027 */
Chris@16 1028 inline active_tail_arbitrary* addHole(active_tail_arbitrary* hole) {
Chris@16 1029 holesList_.push_back(hole);
Chris@16 1030 copyHoles(*hole);
Chris@16 1031 copyHoles(*(hole->otherTailp_));
Chris@16 1032 return this;
Chris@16 1033 }
Chris@16 1034
Chris@16 1035 /**
Chris@16 1036 * @brief get the list of holes
Chris@16 1037 */
Chris@16 1038 inline const std::list<active_tail_arbitrary*>& getHoles() const { return holesList_; }
Chris@16 1039
Chris@16 1040 /**
Chris@16 1041 * @brief copy holes from that to this
Chris@16 1042 */
Chris@16 1043 inline void copyHoles(active_tail_arbitrary& that) { holesList_.splice(holesList_.end(), that.holesList_); }
Chris@16 1044
Chris@16 1045 /**
Chris@16 1046 * @brief find out if solid to right
Chris@16 1047 */
Chris@16 1048 inline bool solidToRight() const { return !head_; }
Chris@16 1049 inline bool solidToLeft() const { return head_; }
Chris@16 1050
Chris@16 1051 /**
Chris@16 1052 * @brief get vertex
Chris@16 1053 */
Chris@16 1054 inline Point getPoint() const {
Chris@16 1055 if(head_) return tailp_->points.front();
Chris@16 1056 return tailp_->points.back();
Chris@16 1057 }
Chris@16 1058
Chris@16 1059 /**
Chris@16 1060 * @brief add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate
Chris@16 1061 */
Chris@16 1062 inline void pushPoint(Point point) {
Chris@16 1063 if(head_) {
Chris@16 1064 //if(tailp_->points.size() < 2) {
Chris@16 1065 // tailp_->points.push_front(point);
Chris@16 1066 // return;
Chris@16 1067 //}
Chris@16 1068 typename std::list<Point>::iterator iter = tailp_->points.begin();
Chris@16 1069 if(iter == tailp_->points.end()) {
Chris@16 1070 tailp_->points.push_front(point);
Chris@16 1071 return;
Chris@16 1072 }
Chris@16 1073 ++iter;
Chris@16 1074 if(iter == tailp_->points.end()) {
Chris@16 1075 tailp_->points.push_front(point);
Chris@16 1076 return;
Chris@16 1077 }
Chris@16 1078 --iter;
Chris@16 1079 if(*iter != point) {
Chris@16 1080 tailp_->points.push_front(point);
Chris@16 1081 }
Chris@16 1082 return;
Chris@16 1083 }
Chris@16 1084 //if(tailp_->points.size() < 2) {
Chris@16 1085 // tailp_->points.push_back(point);
Chris@16 1086 // return;
Chris@16 1087 //}
Chris@16 1088 typename std::list<Point>::reverse_iterator iter = tailp_->points.rbegin();
Chris@16 1089 if(iter == tailp_->points.rend()) {
Chris@16 1090 tailp_->points.push_back(point);
Chris@16 1091 return;
Chris@16 1092 }
Chris@16 1093 ++iter;
Chris@16 1094 if(iter == tailp_->points.rend()) {
Chris@16 1095 tailp_->points.push_back(point);
Chris@16 1096 return;
Chris@16 1097 }
Chris@16 1098 --iter;
Chris@16 1099 if(*iter != point) {
Chris@16 1100 tailp_->points.push_back(point);
Chris@16 1101 }
Chris@16 1102 }
Chris@16 1103
Chris@16 1104 /**
Chris@16 1105 * @brief joins the two chains that the two active tail tails are ends of
Chris@16 1106 * checks for closure of figure and writes out polygons appropriately
Chris@16 1107 * returns a handle to a hole if one is closed
Chris@16 1108 */
Chris@16 1109 template <class cT>
Chris@16 1110 static inline active_tail_arbitrary* joinChains(Point point, active_tail_arbitrary* at1, active_tail_arbitrary* at2, bool solid,
Chris@16 1111 cT& output) {
Chris@16 1112 if(at1->otherTailp_ == at2) {
Chris@16 1113 //if(at2->otherTailp_ != at1) std::cout << "half closed error\n";
Chris@16 1114 //we are closing a figure
Chris@16 1115 at1->pushPoint(point);
Chris@16 1116 at2->pushPoint(point);
Chris@16 1117 if(solid) {
Chris@16 1118 //we are closing a solid figure, write to output
Chris@16 1119 //std::cout << "test1\n";
Chris@16 1120 at1->copyHoles(*(at1->otherTailp_));
Chris@16 1121 typename PolyLineArbitraryByConcept<Unit, typename geometry_concept<typename cT::value_type>::type>::type polyData(at1);
Chris@16 1122 //poly_line_arbitrary_polygon_data polyData(at1);
Chris@16 1123 //std::cout << "test2\n";
Chris@16 1124 //std::cout << poly << "\n";
Chris@16 1125 //std::cout << "test3\n";
Chris@16 1126 typedef typename cT::value_type result_type;
Chris@16 1127 output.push_back(result_type());
Chris@16 1128 assign(output.back(), polyData);
Chris@16 1129 //std::cout << "test4\n";
Chris@16 1130 //std::cout << "delete " << at1->otherTailp_ << "\n";
Chris@16 1131 //at1->print();
Chris@16 1132 //at1->otherTailp_->print();
Chris@16 1133 delete at1->otherTailp_;
Chris@16 1134 //at1->print();
Chris@16 1135 //at1->otherTailp_->print();
Chris@16 1136 //std::cout << "test5\n";
Chris@16 1137 //std::cout << "delete " << at1 << "\n";
Chris@16 1138 delete at1;
Chris@16 1139 //std::cout << "test6\n";
Chris@16 1140 return 0;
Chris@16 1141 } else {
Chris@16 1142 //we are closing a hole, return the tail end active tail of the figure
Chris@16 1143 return at1;
Chris@16 1144 }
Chris@16 1145 }
Chris@16 1146 //we are not closing a figure
Chris@16 1147 at1->pushPoint(point);
Chris@16 1148 at1->join(at2);
Chris@16 1149 delete at1;
Chris@16 1150 delete at2;
Chris@16 1151 return 0;
Chris@16 1152 }
Chris@16 1153
Chris@16 1154 inline void destroyContents() {
Chris@16 1155 if(otherTailp_) {
Chris@16 1156 //std::cout << "delete p " << tailp_ << "\n";
Chris@16 1157 if(tailp_) delete tailp_;
Chris@16 1158 tailp_ = 0;
Chris@16 1159 otherTailp_->otherTailp_ = 0;
Chris@16 1160 otherTailp_->tailp_ = 0;
Chris@16 1161 otherTailp_ = 0;
Chris@16 1162 }
Chris@16 1163 for(typename std::list<active_tail_arbitrary*>::iterator itr = holesList_.begin(); itr != holesList_.end(); ++itr) {
Chris@16 1164 //std::cout << "delete p " << (*itr) << "\n";
Chris@16 1165 if(*itr) {
Chris@16 1166 if((*itr)->otherTailp_) {
Chris@16 1167 delete (*itr)->otherTailp_;
Chris@16 1168 (*itr)->otherTailp_ = 0;
Chris@16 1169 }
Chris@16 1170 delete (*itr);
Chris@16 1171 }
Chris@16 1172 (*itr) = 0;
Chris@16 1173 }
Chris@16 1174 holesList_.clear();
Chris@16 1175 }
Chris@16 1176
Chris@16 1177 inline void print() {
Chris@16 1178 //std::cout << this << " " << tailp_ << " " << otherTailp_ << " " << holesList_.size() << " " << head_ << "\n";
Chris@16 1179 }
Chris@16 1180
Chris@16 1181 static inline std::pair<active_tail_arbitrary*, active_tail_arbitrary*> createActiveTailsAsPair(Point point, bool solid,
Chris@16 1182 active_tail_arbitrary* phole, bool fractureHoles) {
Chris@16 1183 active_tail_arbitrary* at1 = 0;
Chris@16 1184 active_tail_arbitrary* at2 = 0;
Chris@16 1185 if(phole && fractureHoles) {
Chris@16 1186 //std::cout << "adding hole\n";
Chris@16 1187 at1 = phole;
Chris@16 1188 //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole
Chris@16 1189 at2 = at1->getOtherActiveTail();
Chris@16 1190 at2->pushPoint(point);
Chris@16 1191 at1->pushPoint(point);
Chris@16 1192 } else {
Chris@16 1193 at1 = new active_tail_arbitrary(point, at2, solid);
Chris@16 1194 at2 = new active_tail_arbitrary(at1);
Chris@16 1195 at1->otherTailp_ = at2;
Chris@16 1196 at2->head_ = !solid;
Chris@16 1197 if(phole)
Chris@16 1198 at2->addHole(phole); //assert fractureHoles == false
Chris@16 1199 }
Chris@16 1200 return std::pair<active_tail_arbitrary*, active_tail_arbitrary*>(at1, at2);
Chris@16 1201 }
Chris@16 1202
Chris@16 1203 };
Chris@16 1204
Chris@16 1205
Chris@16 1206 typedef std::vector<std::pair<Point, int> > vertex_arbitrary_count;
Chris@16 1207
Chris@16 1208 class less_half_edge_count : public std::binary_function<vertex_half_edge, vertex_half_edge, bool> {
Chris@16 1209 private:
Chris@16 1210 Point pt_;
Chris@16 1211 public:
Chris@16 1212 inline less_half_edge_count() : pt_() {}
Chris@16 1213 inline less_half_edge_count(Point point) : pt_(point) {}
Chris@16 1214 inline bool operator () (const std::pair<Point, int>& elm1, const std::pair<Point, int>& elm2) const {
Chris@16 1215 return scanline_base<Unit>::less_slope(pt_.get(HORIZONTAL), pt_.get(VERTICAL), elm1.first, elm2.first);
Chris@16 1216 }
Chris@16 1217 };
Chris@16 1218
Chris@16 1219 static inline void sort_vertex_arbitrary_count(vertex_arbitrary_count& count, const Point& pt) {
Chris@16 1220 less_half_edge_count lfec(pt);
Chris@16 1221 polygon_sort(count.begin(), count.end(), lfec);
Chris@16 1222 }
Chris@16 1223
Chris@16 1224 typedef std::vector<std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*> > incoming_count;
Chris@16 1225
Chris@16 1226 class less_incoming_count : public std::binary_function<std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>,
Chris@16 1227 std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>, bool> {
Chris@16 1228 private:
Chris@16 1229 Point pt_;
Chris@16 1230 public:
Chris@16 1231 inline less_incoming_count() : pt_() {}
Chris@16 1232 inline less_incoming_count(Point point) : pt_(point) {}
Chris@16 1233 inline bool operator () (const std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>& elm1,
Chris@16 1234 const std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>& elm2) const {
Chris@16 1235 Unit dx1 = elm1.first.first.first.get(HORIZONTAL) - elm1.first.first.second.get(HORIZONTAL);
Chris@16 1236 Unit dx2 = elm2.first.first.first.get(HORIZONTAL) - elm2.first.first.second.get(HORIZONTAL);
Chris@16 1237 Unit dy1 = elm1.first.first.first.get(VERTICAL) - elm1.first.first.second.get(VERTICAL);
Chris@16 1238 Unit dy2 = elm2.first.first.first.get(VERTICAL) - elm2.first.first.second.get(VERTICAL);
Chris@16 1239 return scanline_base<Unit>::less_slope(dx1, dy1, dx2, dy2);
Chris@16 1240 }
Chris@16 1241 };
Chris@16 1242
Chris@16 1243 static inline void sort_incoming_count(incoming_count& count, const Point& pt) {
Chris@16 1244 less_incoming_count lfec(pt);
Chris@16 1245 polygon_sort(count.begin(), count.end(), lfec);
Chris@16 1246 }
Chris@16 1247
Chris@16 1248 static inline void compact_vertex_arbitrary_count(const Point& pt, vertex_arbitrary_count &count) {
Chris@16 1249 if(count.empty()) return;
Chris@16 1250 vertex_arbitrary_count tmp;
Chris@16 1251 tmp.reserve(count.size());
Chris@16 1252 tmp.push_back(count[0]);
Chris@16 1253 //merge duplicates
Chris@16 1254 for(std::size_t i = 1; i < count.size(); ++i) {
Chris@16 1255 if(!equal_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), tmp[i-1].first, count[i].first)) {
Chris@16 1256 tmp.push_back(count[i]);
Chris@16 1257 } else {
Chris@16 1258 tmp.back().second += count[i].second;
Chris@16 1259 }
Chris@16 1260 }
Chris@16 1261 count.clear();
Chris@16 1262 count.swap(tmp);
Chris@16 1263 }
Chris@16 1264
Chris@16 1265 // inline std::ostream& operator<< (std::ostream& o, const vertex_arbitrary_count& c) {
Chris@16 1266 // for(unsinged int i = 0; i < c.size(); ++i) {
Chris@16 1267 // o << c[i].first << " " << c[i].second << " ";
Chris@16 1268 // }
Chris@16 1269 // return o;
Chris@16 1270 // }
Chris@16 1271
Chris@16 1272 class vertex_arbitrary_compact {
Chris@16 1273 public:
Chris@16 1274 Point pt;
Chris@16 1275 vertex_arbitrary_count count;
Chris@16 1276 inline vertex_arbitrary_compact() : pt(), count() {}
Chris@16 1277 inline vertex_arbitrary_compact(const Point& point, const Point& other_point, int countIn) : pt(point), count() {
Chris@16 1278 count.push_back(std::pair<Point, int>(other_point, countIn));
Chris@16 1279 }
Chris@16 1280 inline vertex_arbitrary_compact(const vertex_half_edge& vertex) : pt(vertex.pt), count() {
Chris@16 1281 count.push_back(std::pair<Point, int>(vertex.other_pt, vertex.count));
Chris@16 1282 }
Chris@16 1283 inline vertex_arbitrary_compact(const vertex_arbitrary_compact& vertex) : pt(vertex.pt), count(vertex.count) {}
Chris@16 1284 inline vertex_arbitrary_compact& operator=(const vertex_arbitrary_compact& vertex){
Chris@16 1285 pt = vertex.pt; count = vertex.count; return *this; }
Chris@16 1286 //inline vertex_arbitrary_compact(const std::pair<Point, Point>& vertex) {}
Chris@16 1287 inline vertex_arbitrary_compact& operator=(const std::pair<Point, Point>& vertex){ return *this; }
Chris@16 1288 inline bool operator==(const vertex_arbitrary_compact& vertex) const {
Chris@16 1289 return pt == vertex.pt && count == vertex.count; }
Chris@16 1290 inline bool operator!=(const vertex_arbitrary_compact& vertex) const { return !((*this) == vertex); }
Chris@16 1291 inline bool operator==(const std::pair<Point, Point>& vertex) const { return false; }
Chris@16 1292 inline bool operator!=(const std::pair<Point, Point>& vertex) const { return !((*this) == vertex); }
Chris@16 1293 inline bool operator<(const vertex_arbitrary_compact& vertex) const {
Chris@16 1294 if(pt.get(HORIZONTAL) < vertex.pt.get(HORIZONTAL)) return true;
Chris@16 1295 if(pt.get(HORIZONTAL) == vertex.pt.get(HORIZONTAL)) {
Chris@16 1296 return pt.get(VERTICAL) < vertex.pt.get(VERTICAL);
Chris@16 1297 }
Chris@16 1298 return false;
Chris@16 1299 }
Chris@16 1300 inline bool operator>(const vertex_arbitrary_compact& vertex) const { return vertex < (*this); }
Chris@16 1301 inline bool operator<=(const vertex_arbitrary_compact& vertex) const { return !((*this) > vertex); }
Chris@16 1302 inline bool operator>=(const vertex_arbitrary_compact& vertex) const { return !((*this) < vertex); }
Chris@16 1303 inline bool have_vertex_half_edge(int index) const { return count[index]; }
Chris@16 1304 inline vertex_half_edge operator[](int index) const { return vertex_half_edge(pt, count[index]); }
Chris@16 1305 };
Chris@16 1306
Chris@16 1307 // inline std::ostream& operator<< (std::ostream& o, const vertex_arbitrary_compact& c) {
Chris@16 1308 // o << c.pt << ", " << c.count;
Chris@16 1309 // return o;
Chris@16 1310 // }
Chris@16 1311
Chris@16 1312 protected:
Chris@16 1313 //definitions
Chris@16 1314 typedef std::map<vertex_half_edge, active_tail_arbitrary*, less_vertex_half_edge> scanline_data;
Chris@16 1315 typedef typename scanline_data::iterator iterator;
Chris@16 1316 typedef typename scanline_data::const_iterator const_iterator;
Chris@16 1317
Chris@16 1318 //data
Chris@16 1319 scanline_data scanData_;
Chris@16 1320 Unit x_;
Chris@16 1321 int justBefore_;
Chris@16 1322 int fractureHoles_;
Chris@16 1323 public:
Chris@16 1324 inline polygon_arbitrary_formation() :
Chris@16 1325 scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(0) {
Chris@16 1326 less_vertex_half_edge lessElm(&x_, &justBefore_);
Chris@16 1327 scanData_ = scanline_data(lessElm);
Chris@16 1328 }
Chris@16 1329 inline polygon_arbitrary_formation(bool fractureHoles) :
Chris@16 1330 scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(fractureHoles) {
Chris@16 1331 less_vertex_half_edge lessElm(&x_, &justBefore_);
Chris@16 1332 scanData_ = scanline_data(lessElm);
Chris@16 1333 }
Chris@16 1334 inline polygon_arbitrary_formation(const polygon_arbitrary_formation& that) :
Chris@16 1335 scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(0) { (*this) = that; }
Chris@16 1336 inline polygon_arbitrary_formation& operator=(const polygon_arbitrary_formation& that) {
Chris@16 1337 x_ = that.x_;
Chris@16 1338 justBefore_ = that.justBefore_;
Chris@16 1339 fractureHoles_ = that.fractureHoles_;
Chris@16 1340 less_vertex_half_edge lessElm(&x_, &justBefore_);
Chris@16 1341 scanData_ = scanline_data(lessElm);
Chris@16 1342 for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){
Chris@16 1343 scanData_.insert(scanData_.end(), *itr);
Chris@16 1344 }
Chris@16 1345 return *this;
Chris@16 1346 }
Chris@16 1347
Chris@16 1348 //cT is an output container of Polygon45 or Polygon45WithHoles
Chris@16 1349 //iT is an iterator over vertex_half_edge elements
Chris@16 1350 //inputBegin - inputEnd is a range of sorted iT that represents
Chris@16 1351 //one or more scanline stops worth of data
Chris@16 1352 template <class cT, class iT>
Chris@16 1353 void scan(cT& output, iT inputBegin, iT inputEnd) {
Chris@16 1354 //std::cout << "1\n";
Chris@16 1355 while(inputBegin != inputEnd) {
Chris@16 1356 //std::cout << "2\n";
Chris@16 1357 x_ = (*inputBegin).pt.get(HORIZONTAL);
Chris@16 1358 //std::cout << "SCAN FORMATION " << x_ << "\n";
Chris@16 1359 //std::cout << "x_ = " << x_ << "\n";
Chris@16 1360 //std::cout << "scan line size: " << scanData_.size() << "\n";
Chris@16 1361 inputBegin = processEvent_(output, inputBegin, inputEnd);
Chris@16 1362 }
Chris@16 1363 //std::cout << "scan line size: " << scanData_.size() << "\n";
Chris@16 1364 }
Chris@16 1365
Chris@16 1366 protected:
Chris@16 1367 //functions
Chris@16 1368 template <class cT, class cT2>
Chris@16 1369 inline std::pair<std::pair<Point, int>, active_tail_arbitrary*> processPoint_(cT& output, cT2& elements, Point point,
Chris@16 1370 incoming_count& counts_from_scanline, vertex_arbitrary_count& incoming_count) {
Chris@16 1371 //std::cout << "\nAT POINT: " << point << "\n";
Chris@16 1372 //join any closing solid corners
Chris@16 1373 std::vector<int> counts;
Chris@16 1374 std::vector<int> incoming;
Chris@16 1375 std::vector<active_tail_arbitrary*> tails;
Chris@16 1376 counts.reserve(counts_from_scanline.size());
Chris@16 1377 tails.reserve(counts_from_scanline.size());
Chris@16 1378 incoming.reserve(incoming_count.size());
Chris@16 1379 for(std::size_t i = 0; i < counts_from_scanline.size(); ++i) {
Chris@16 1380 counts.push_back(counts_from_scanline[i].first.second);
Chris@16 1381 tails.push_back(counts_from_scanline[i].second);
Chris@16 1382 }
Chris@16 1383 for(std::size_t i = 0; i < incoming_count.size(); ++i) {
Chris@16 1384 incoming.push_back(incoming_count[i].second);
Chris@16 1385 if(incoming_count[i].first < point) {
Chris@16 1386 incoming.back() = 0;
Chris@16 1387 }
Chris@16 1388 }
Chris@16 1389
Chris@16 1390 active_tail_arbitrary* returnValue = 0;
Chris@16 1391 std::pair<Point, int> returnCount(Point(0, 0), 0);
Chris@16 1392 int i_size_less_1 = (int)(incoming.size()) -1;
Chris@16 1393 int c_size_less_1 = (int)(counts.size()) -1;
Chris@16 1394 int i_size = incoming.size();
Chris@16 1395 int c_size = counts.size();
Chris@16 1396
Chris@16 1397 bool have_vertical_tail_from_below = false;
Chris@16 1398 if(c_size &&
Chris@16 1399 scanline_base<Unit>::is_vertical(counts_from_scanline.back().first.first)) {
Chris@16 1400 have_vertical_tail_from_below = true;
Chris@16 1401 }
Chris@16 1402 //assert size = size_less_1 + 1
Chris@16 1403 //std::cout << tails.size() << " " << incoming.size() << " " << counts_from_scanline.size() << " " << incoming_count.size() << "\n";
Chris@16 1404 // for(std::size_t i = 0; i < counts.size(); ++i) {
Chris@16 1405 // std::cout << counts_from_scanline[i].first.first.first.get(HORIZONTAL) << ",";
Chris@16 1406 // std::cout << counts_from_scanline[i].first.first.first.get(VERTICAL) << " ";
Chris@16 1407 // std::cout << counts_from_scanline[i].first.first.second.get(HORIZONTAL) << ",";
Chris@16 1408 // std::cout << counts_from_scanline[i].first.first.second.get(VERTICAL) << ":";
Chris@16 1409 // std::cout << counts_from_scanline[i].first.second << " ";
Chris@16 1410 // } std::cout << "\n";
Chris@16 1411 // print(incoming_count);
Chris@16 1412 {
Chris@16 1413 for(int i = 0; i < c_size_less_1; ++i) {
Chris@16 1414 //std::cout << i << "\n";
Chris@16 1415 if(counts[i] == -1) {
Chris@16 1416 //std::cout << "fixed i\n";
Chris@16 1417 for(int j = i + 1; j < c_size; ++j) {
Chris@16 1418 //std::cout << j << "\n";
Chris@16 1419 if(counts[j]) {
Chris@16 1420 if(counts[j] == 1) {
Chris@16 1421 //std::cout << "case1: " << i << " " << j << "\n";
Chris@16 1422 //if a figure is closed it will be written out by this function to output
Chris@16 1423 active_tail_arbitrary::joinChains(point, tails[i], tails[j], true, output);
Chris@16 1424 counts[i] = 0;
Chris@16 1425 counts[j] = 0;
Chris@16 1426 tails[i] = 0;
Chris@16 1427 tails[j] = 0;
Chris@16 1428 }
Chris@16 1429 break;
Chris@16 1430 }
Chris@16 1431 }
Chris@16 1432 }
Chris@16 1433 }
Chris@16 1434 }
Chris@16 1435 //find any pairs of incoming edges that need to create pair for leading solid
Chris@16 1436 //std::cout << "checking case2\n";
Chris@16 1437 {
Chris@16 1438 for(int i = 0; i < i_size_less_1; ++i) {
Chris@16 1439 //std::cout << i << "\n";
Chris@16 1440 if(incoming[i] == 1) {
Chris@16 1441 //std::cout << "fixed i\n";
Chris@16 1442 for(int j = i + 1; j < i_size; ++j) {
Chris@16 1443 //std::cout << j << "\n";
Chris@16 1444 if(incoming[j]) {
Chris@16 1445 //std::cout << incoming[j] << "\n";
Chris@16 1446 if(incoming[j] == -1) {
Chris@16 1447 //std::cout << "case2: " << i << " " << j << "\n";
Chris@16 1448 //std::cout << "creating active tail pair\n";
Chris@16 1449 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> tailPair =
Chris@16 1450 active_tail_arbitrary::createActiveTailsAsPair(point, true, 0, fractureHoles_ != 0);
Chris@16 1451 //tailPair.first->print();
Chris@16 1452 //tailPair.second->print();
Chris@16 1453 if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 1454 //vertical active tail becomes return value
Chris@16 1455 returnValue = tailPair.first;
Chris@16 1456 returnCount.first = point;
Chris@16 1457 returnCount.second = 1;
Chris@16 1458 } else {
Chris@16 1459 //std::cout << "new element " << j-1 << " " << -1 << "\n";
Chris@16 1460 //std::cout << point << " " << incoming_count[j].first << "\n";
Chris@16 1461 elements.push_back(std::pair<vertex_half_edge,
Chris@16 1462 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 1463 incoming_count[j].first, -1), tailPair.first));
Chris@16 1464 }
Chris@16 1465 //std::cout << "new element " << i-1 << " " << 1 << "\n";
Chris@16 1466 //std::cout << point << " " << incoming_count[i].first << "\n";
Chris@16 1467 elements.push_back(std::pair<vertex_half_edge,
Chris@16 1468 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 1469 incoming_count[i].first, 1), tailPair.second));
Chris@16 1470 incoming[i] = 0;
Chris@16 1471 incoming[j] = 0;
Chris@16 1472 }
Chris@16 1473 break;
Chris@16 1474 }
Chris@16 1475 }
Chris@16 1476 }
Chris@16 1477 }
Chris@16 1478 }
Chris@16 1479 //find any active tail that needs to pass through to an incoming edge
Chris@16 1480 //we expect to find no more than two pass through
Chris@16 1481
Chris@16 1482 //find pass through with solid on top
Chris@16 1483 {
Chris@16 1484 //std::cout << "checking case 3\n";
Chris@16 1485 for(int i = 0; i < c_size; ++i) {
Chris@16 1486 //std::cout << i << "\n";
Chris@16 1487 if(counts[i] != 0) {
Chris@16 1488 if(counts[i] == 1) {
Chris@16 1489 //std::cout << "fixed i\n";
Chris@16 1490 for(int j = i_size_less_1; j >= 0; --j) {
Chris@16 1491 if(incoming[j] != 0) {
Chris@16 1492 if(incoming[j] == 1) {
Chris@16 1493 //std::cout << "case3: " << i << " " << j << "\n";
Chris@16 1494 //tails[i]->print();
Chris@16 1495 //pass through solid on top
Chris@16 1496 tails[i]->pushPoint(point);
Chris@16 1497 //std::cout << "after push\n";
Chris@16 1498 if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 1499 returnValue = tails[i];
Chris@16 1500 returnCount.first = point;
Chris@16 1501 returnCount.second = -1;
Chris@16 1502 } else {
Chris@16 1503 elements.push_back(std::pair<vertex_half_edge,
Chris@16 1504 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 1505 incoming_count[j].first, incoming[j]), tails[i]));
Chris@16 1506 }
Chris@16 1507 tails[i] = 0;
Chris@16 1508 counts[i] = 0;
Chris@16 1509 incoming[j] = 0;
Chris@16 1510 }
Chris@16 1511 break;
Chris@16 1512 }
Chris@16 1513 }
Chris@16 1514 }
Chris@16 1515 break;
Chris@16 1516 }
Chris@16 1517 }
Chris@16 1518 }
Chris@16 1519 //std::cout << "checking case 4\n";
Chris@16 1520 //find pass through with solid on bottom
Chris@16 1521 {
Chris@16 1522 for(int i = c_size_less_1; i >= 0; --i) {
Chris@16 1523 //std::cout << "i = " << i << " with count " << counts[i] << "\n";
Chris@16 1524 if(counts[i] != 0) {
Chris@16 1525 if(counts[i] == -1) {
Chris@16 1526 for(int j = 0; j < i_size; ++j) {
Chris@16 1527 if(incoming[j] != 0) {
Chris@16 1528 if(incoming[j] == -1) {
Chris@16 1529 //std::cout << "case4: " << i << " " << j << "\n";
Chris@16 1530 //pass through solid on bottom
Chris@16 1531 tails[i]->pushPoint(point);
Chris@16 1532 if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 1533 returnValue = tails[i];
Chris@16 1534 returnCount.first = point;
Chris@16 1535 returnCount.second = 1;
Chris@16 1536 } else {
Chris@16 1537 //std::cout << "new element " << j-1 << " " << incoming[j] << "\n";
Chris@16 1538 //std::cout << point << " " << incoming_count[j].first << "\n";
Chris@16 1539 elements.push_back(std::pair<vertex_half_edge,
Chris@16 1540 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 1541 incoming_count[j].first, incoming[j]), tails[i]));
Chris@16 1542 }
Chris@16 1543 tails[i] = 0;
Chris@16 1544 counts[i] = 0;
Chris@16 1545 incoming[j] = 0;
Chris@16 1546 }
Chris@16 1547 break;
Chris@16 1548 }
Chris@16 1549 }
Chris@16 1550 }
Chris@16 1551 break;
Chris@16 1552 }
Chris@16 1553 }
Chris@16 1554 }
Chris@16 1555 //find the end of a hole or the beginning of a hole
Chris@16 1556
Chris@16 1557 //find end of a hole
Chris@16 1558 {
Chris@16 1559 for(int i = 0; i < c_size_less_1; ++i) {
Chris@16 1560 if(counts[i] != 0) {
Chris@16 1561 for(int j = i+1; j < c_size; ++j) {
Chris@16 1562 if(counts[j] != 0) {
Chris@16 1563 //std::cout << "case5: " << i << " " << j << "\n";
Chris@16 1564 //we are ending a hole and may potentially close a figure and have to handle the hole
Chris@16 1565 returnValue = active_tail_arbitrary::joinChains(point, tails[i], tails[j], false, output);
Chris@16 1566 if(returnValue) returnCount.first = point;
Chris@16 1567 //std::cout << returnValue << "\n";
Chris@16 1568 tails[i] = 0;
Chris@16 1569 tails[j] = 0;
Chris@16 1570 counts[i] = 0;
Chris@16 1571 counts[j] = 0;
Chris@16 1572 break;
Chris@16 1573 }
Chris@16 1574 }
Chris@16 1575 break;
Chris@16 1576 }
Chris@16 1577 }
Chris@16 1578 }
Chris@16 1579 //find beginning of a hole
Chris@16 1580 {
Chris@16 1581 for(int i = 0; i < i_size_less_1; ++i) {
Chris@16 1582 if(incoming[i] != 0) {
Chris@16 1583 for(int j = i+1; j < i_size; ++j) {
Chris@16 1584 if(incoming[j] != 0) {
Chris@16 1585 //std::cout << "case6: " << i << " " << j << "\n";
Chris@16 1586 //we are beginning a empty space
Chris@16 1587 active_tail_arbitrary* holep = 0;
Chris@16 1588 //if(c_size && counts[c_size_less_1] == 0 &&
Chris@16 1589 // counts_from_scanline[c_size_less_1].first.first.first.get(HORIZONTAL) == point.get(HORIZONTAL))
Chris@16 1590 if(have_vertical_tail_from_below) {
Chris@16 1591 holep = tails[c_size_less_1];
Chris@16 1592 tails[c_size_less_1] = 0;
Chris@16 1593 have_vertical_tail_from_below = false;
Chris@16 1594 }
Chris@16 1595 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> tailPair =
Chris@16 1596 active_tail_arbitrary::createActiveTailsAsPair(point, false, holep, fractureHoles_ != 0);
Chris@16 1597 if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 1598 //std::cout << "vertical element " << point << "\n";
Chris@16 1599 returnValue = tailPair.first;
Chris@16 1600 returnCount.first = point;
Chris@16 1601 //returnCount = incoming_count[j];
Chris@16 1602 returnCount.second = -1;
Chris@16 1603 } else {
Chris@16 1604 //std::cout << "new element " << j-1 << " " << incoming[j] << "\n";
Chris@16 1605 //std::cout << point << " " << incoming_count[j].first << "\n";
Chris@16 1606 elements.push_back(std::pair<vertex_half_edge,
Chris@16 1607 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 1608 incoming_count[j].first, incoming[j]), tailPair.first));
Chris@16 1609 }
Chris@16 1610 //std::cout << "new element " << i-1 << " " << incoming[i] << "\n";
Chris@16 1611 //std::cout << point << " " << incoming_count[i].first << "\n";
Chris@16 1612 elements.push_back(std::pair<vertex_half_edge,
Chris@16 1613 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 1614 incoming_count[i].first, incoming[i]), tailPair.second));
Chris@16 1615 incoming[i] = 0;
Chris@16 1616 incoming[j] = 0;
Chris@16 1617 break;
Chris@16 1618 }
Chris@16 1619 }
Chris@16 1620 break;
Chris@16 1621 }
Chris@16 1622 }
Chris@16 1623 }
Chris@16 1624 if(have_vertical_tail_from_below) {
Chris@16 1625 if(tails.back()) {
Chris@16 1626 tails.back()->pushPoint(point);
Chris@16 1627 returnValue = tails.back();
Chris@16 1628 returnCount.first = point;
Chris@16 1629 returnCount.second = counts.back();
Chris@16 1630 }
Chris@16 1631 }
Chris@16 1632 //assert that tails, counts and incoming are all null
Chris@16 1633 return std::pair<std::pair<Point, int>, active_tail_arbitrary*>(returnCount, returnValue);
Chris@16 1634 }
Chris@16 1635
Chris@16 1636 static inline void print(const vertex_arbitrary_count& count) {
Chris@16 1637 for(unsigned i = 0; i < count.size(); ++i) {
Chris@16 1638 //std::cout << count[i].first.get(HORIZONTAL) << ",";
Chris@16 1639 //std::cout << count[i].first.get(VERTICAL) << ":";
Chris@16 1640 //std::cout << count[i].second << " ";
Chris@16 1641 } //std::cout << "\n";
Chris@16 1642 }
Chris@16 1643
Chris@16 1644 static inline void print(const scanline_data& data) {
Chris@16 1645 for(typename scanline_data::const_iterator itr = data.begin(); itr != data.end(); ++itr){
Chris@16 1646 //std::cout << itr->first.pt << ", " << itr->first.other_pt << "; ";
Chris@16 1647 } //std::cout << "\n";
Chris@16 1648 }
Chris@16 1649
Chris@16 1650 template <class cT, class iT>
Chris@16 1651 inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) {
Chris@16 1652 typedef typename high_precision_type<Unit>::type high_precision;
Chris@16 1653 //std::cout << "processEvent_\n";
Chris@16 1654 justBefore_ = true;
Chris@16 1655 //collect up all elements from the tree that are at the y
Chris@16 1656 //values of events in the input queue
Chris@16 1657 //create vector of new elements to add into tree
Chris@16 1658 active_tail_arbitrary* verticalTail = 0;
Chris@16 1659 std::pair<Point, int> verticalCount(Point(0, 0), 0);
Chris@16 1660 iT currentIter = inputBegin;
Chris@16 1661 std::vector<iterator> elementIters;
Chris@16 1662 std::vector<std::pair<vertex_half_edge, active_tail_arbitrary*> > elements;
Chris@16 1663 while(currentIter != inputEnd && currentIter->pt.get(HORIZONTAL) == x_) {
Chris@16 1664 //std::cout << "loop\n";
Chris@16 1665 Unit currentY = (*currentIter).pt.get(VERTICAL);
Chris@16 1666 //std::cout << "current Y " << currentY << "\n";
Chris@16 1667 //std::cout << "scanline size " << scanData_.size() << "\n";
Chris@16 1668 //print(scanData_);
Chris@16 1669 iterator iter = lookUp_(currentY);
Chris@16 1670 //std::cout << "found element in scanline " << (iter != scanData_.end()) << "\n";
Chris@16 1671 //int counts[4] = {0, 0, 0, 0};
Chris@16 1672 incoming_count counts_from_scanline;
Chris@16 1673 //std::cout << "finding elements in tree\n";
Chris@16 1674 //if(iter != scanData_.end())
Chris@16 1675 // std::cout << "first iter y is " << iter->first.evalAtX(x_) << "\n";
Chris@16 1676 while(iter != scanData_.end() &&
Chris@16 1677 ((iter->first.pt.x() == x_ && iter->first.pt.y() == currentY) ||
Chris@16 1678 (iter->first.other_pt.x() == x_ && iter->first.other_pt.y() == currentY))) {
Chris@16 1679 //iter->first.evalAtX(x_) == (high_precision)currentY) {
Chris@16 1680 //std::cout << "loop2\n";
Chris@16 1681 elementIters.push_back(iter);
Chris@16 1682 counts_from_scanline.push_back(std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>
Chris@16 1683 (std::pair<std::pair<Point, Point>, int>(std::pair<Point, Point>(iter->first.pt,
Chris@16 1684 iter->first.other_pt),
Chris@16 1685 iter->first.count),
Chris@16 1686 iter->second));
Chris@16 1687 ++iter;
Chris@16 1688 }
Chris@16 1689 Point currentPoint(x_, currentY);
Chris@16 1690 //std::cout << "counts_from_scanline size " << counts_from_scanline.size() << "\n";
Chris@16 1691 sort_incoming_count(counts_from_scanline, currentPoint);
Chris@16 1692
Chris@16 1693 vertex_arbitrary_count incoming;
Chris@16 1694 //std::cout << "aggregating\n";
Chris@16 1695 do {
Chris@16 1696 //std::cout << "loop3\n";
Chris@16 1697 const vertex_half_edge& elem = *currentIter;
Chris@16 1698 incoming.push_back(std::pair<Point, int>(elem.other_pt, elem.count));
Chris@16 1699 ++currentIter;
Chris@16 1700 } while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY &&
Chris@16 1701 currentIter->pt.get(HORIZONTAL) == x_);
Chris@16 1702 //print(incoming);
Chris@16 1703 sort_vertex_arbitrary_count(incoming, currentPoint);
Chris@16 1704 //std::cout << currentPoint.get(HORIZONTAL) << "," << currentPoint.get(VERTICAL) << "\n";
Chris@16 1705 //print(incoming);
Chris@16 1706 //std::cout << "incoming counts from input size " << incoming.size() << "\n";
Chris@16 1707 //compact_vertex_arbitrary_count(currentPoint, incoming);
Chris@16 1708 vertex_arbitrary_count tmp;
Chris@16 1709 tmp.reserve(incoming.size());
Chris@16 1710 for(std::size_t i = 0; i < incoming.size(); ++i) {
Chris@16 1711 if(currentPoint < incoming[i].first) {
Chris@16 1712 tmp.push_back(incoming[i]);
Chris@16 1713 }
Chris@16 1714 }
Chris@16 1715 incoming.swap(tmp);
Chris@16 1716 //std::cout << "incoming counts from input size " << incoming.size() << "\n";
Chris@16 1717 //now counts_from_scanline has the data from the left and
Chris@16 1718 //incoming has the data from the right at this point
Chris@16 1719 //cancel out any end points
Chris@16 1720 if(verticalTail) {
Chris@16 1721 //std::cout << "adding vertical tail to counts from scanline\n";
Chris@16 1722 //std::cout << -verticalCount.second << "\n";
Chris@16 1723 counts_from_scanline.push_back(std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>
Chris@16 1724 (std::pair<std::pair<Point, Point>, int>(std::pair<Point, Point>(verticalCount.first,
Chris@16 1725 currentPoint),
Chris@16 1726 -verticalCount.second),
Chris@16 1727 verticalTail));
Chris@16 1728 }
Chris@16 1729 if(!incoming.empty() && incoming.back().first.get(HORIZONTAL) == x_) {
Chris@16 1730 //std::cout << "inverted vertical event\n";
Chris@16 1731 incoming.back().second *= -1;
Chris@16 1732 }
Chris@16 1733 //std::cout << "calling processPoint_\n";
Chris@16 1734 std::pair<std::pair<Point, int>, active_tail_arbitrary*> result = processPoint_(output, elements, Point(x_, currentY), counts_from_scanline, incoming);
Chris@16 1735 verticalCount = result.first;
Chris@16 1736 verticalTail = result.second;
Chris@16 1737 //if(verticalTail) {
Chris@16 1738 // std::cout << "have vertical tail\n";
Chris@16 1739 // std::cout << verticalCount.second << "\n";
Chris@16 1740 //}
Chris@16 1741 if(verticalTail && !(verticalCount.second)) {
Chris@16 1742 //we got a hole out of the point we just processed
Chris@16 1743 //iter is still at the next y element above the current y value in the tree
Chris@16 1744 //std::cout << "checking whether ot handle hole\n";
Chris@16 1745 if(currentIter == inputEnd ||
Chris@16 1746 currentIter->pt.get(HORIZONTAL) != x_ ||
Chris@16 1747 scanline_base<Unit>::on_above_or_below(currentIter->pt, half_edge(iter->first.pt, iter->first.other_pt)) != -1) {
Chris@16 1748 //(high_precision)(currentIter->pt.get(VERTICAL)) >= iter->first.evalAtX(x_)) {
Chris@16 1749
Chris@16 1750 //std::cout << "handle hole here\n";
Chris@16 1751 if(fractureHoles_) {
Chris@16 1752 //std::cout << "fracture hole here\n";
Chris@16 1753 //we need to handle the hole now and not at the next input vertex
Chris@16 1754 active_tail_arbitrary* at = iter->second;
Chris@16 1755 high_precision precise_y = iter->first.evalAtX(x_);
Chris@16 1756 Unit fracture_y = convert_high_precision_type<Unit>(precise_y);
Chris@16 1757 if(precise_y < fracture_y) --fracture_y;
Chris@16 1758 Point point(x_, fracture_y);
Chris@16 1759 verticalTail->getOtherActiveTail()->pushPoint(point);
Chris@16 1760 iter->second = verticalTail->getOtherActiveTail();
Chris@16 1761 at->pushPoint(point);
Chris@16 1762 verticalTail->join(at);
Chris@16 1763 delete at;
Chris@16 1764 delete verticalTail;
Chris@16 1765 verticalTail = 0;
Chris@16 1766 } else {
Chris@16 1767 //std::cout << "push hole onto list\n";
Chris@16 1768 iter->second->addHole(verticalTail);
Chris@16 1769 verticalTail = 0;
Chris@16 1770 }
Chris@16 1771 }
Chris@16 1772 }
Chris@16 1773 }
Chris@16 1774 //std::cout << "erasing\n";
Chris@16 1775 //erase all elements from the tree
Chris@16 1776 for(typename std::vector<iterator>::iterator iter = elementIters.begin();
Chris@16 1777 iter != elementIters.end(); ++iter) {
Chris@16 1778 //std::cout << "erasing loop\n";
Chris@16 1779 scanData_.erase(*iter);
Chris@16 1780 }
Chris@16 1781 //switch comparison tie breaking policy
Chris@16 1782 justBefore_ = false;
Chris@16 1783 //add new elements into tree
Chris@16 1784 //std::cout << "inserting\n";
Chris@16 1785 for(typename std::vector<std::pair<vertex_half_edge, active_tail_arbitrary*> >::iterator iter = elements.begin();
Chris@16 1786 iter != elements.end(); ++iter) {
Chris@16 1787 //std::cout << "inserting loop\n";
Chris@16 1788 scanData_.insert(scanData_.end(), *iter);
Chris@16 1789 }
Chris@16 1790 //std::cout << "end processEvent\n";
Chris@16 1791 return currentIter;
Chris@16 1792 }
Chris@16 1793
Chris@16 1794 inline iterator lookUp_(Unit y){
Chris@16 1795 //if just before then we need to look from 1 not -1
Chris@16 1796 //std::cout << "just before " << justBefore_ << "\n";
Chris@16 1797 return scanData_.lower_bound(vertex_half_edge(Point(x_, y), Point(x_, y+1), 0));
Chris@16 1798 }
Chris@16 1799
Chris@16 1800 public: //test functions
Chris@16 1801
Chris@16 1802 template <typename stream_type>
Chris@16 1803 static inline bool testPolygonArbitraryFormationRect(stream_type& stdcout) {
Chris@16 1804 stdcout << "testing polygon formation\n";
Chris@16 1805 polygon_arbitrary_formation pf(true);
Chris@16 1806 std::vector<polygon_data<Unit> > polys;
Chris@16 1807 std::vector<vertex_half_edge> data;
Chris@16 1808 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1));
Chris@16 1809 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 1810 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 1811 data.push_back(vertex_half_edge(Point(0, 10), Point(10, 10), -1));
Chris@16 1812 data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1));
Chris@16 1813 data.push_back(vertex_half_edge(Point(10, 0), Point(10, 10), -1));
Chris@16 1814 data.push_back(vertex_half_edge(Point(10, 10), Point(10, 0), 1));
Chris@16 1815 data.push_back(vertex_half_edge(Point(10, 10), Point(0, 10), 1));
Chris@16 1816 polygon_sort(data.begin(), data.end());
Chris@16 1817 pf.scan(polys, data.begin(), data.end());
Chris@16 1818 stdcout << "result size: " << polys.size() << "\n";
Chris@16 1819 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 1820 stdcout << polys[i] << "\n";
Chris@16 1821 }
Chris@16 1822 stdcout << "done testing polygon formation\n";
Chris@16 1823 return true;
Chris@16 1824 }
Chris@16 1825
Chris@16 1826 template <typename stream_type>
Chris@16 1827 static inline bool testPolygonArbitraryFormationP1(stream_type& stdcout) {
Chris@16 1828 stdcout << "testing polygon formation P1\n";
Chris@16 1829 polygon_arbitrary_formation pf(true);
Chris@16 1830 std::vector<polygon_data<Unit> > polys;
Chris@16 1831 std::vector<vertex_half_edge> data;
Chris@16 1832 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 10), 1));
Chris@16 1833 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 1834 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 1835 data.push_back(vertex_half_edge(Point(0, 10), Point(10, 20), -1));
Chris@16 1836 data.push_back(vertex_half_edge(Point(10, 10), Point(0, 0), -1));
Chris@16 1837 data.push_back(vertex_half_edge(Point(10, 10), Point(10, 20), -1));
Chris@16 1838 data.push_back(vertex_half_edge(Point(10, 20), Point(10, 10), 1));
Chris@16 1839 data.push_back(vertex_half_edge(Point(10, 20), Point(0, 10), 1));
Chris@16 1840 polygon_sort(data.begin(), data.end());
Chris@16 1841 pf.scan(polys, data.begin(), data.end());
Chris@16 1842 stdcout << "result size: " << polys.size() << "\n";
Chris@16 1843 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 1844 stdcout << polys[i] << "\n";
Chris@16 1845 }
Chris@16 1846 stdcout << "done testing polygon formation\n";
Chris@16 1847 return true;
Chris@16 1848 }
Chris@16 1849
Chris@16 1850 template <typename stream_type>
Chris@16 1851 static inline bool testPolygonArbitraryFormationP2(stream_type& stdcout) {
Chris@16 1852 stdcout << "testing polygon formation P2\n";
Chris@16 1853 polygon_arbitrary_formation pf(true);
Chris@16 1854 std::vector<polygon_data<Unit> > polys;
Chris@16 1855 std::vector<vertex_half_edge> data;
Chris@16 1856 data.push_back(vertex_half_edge(Point(-3, 1), Point(2, -4), 1));
Chris@16 1857 data.push_back(vertex_half_edge(Point(-3, 1), Point(-2, 2), -1));
Chris@16 1858 data.push_back(vertex_half_edge(Point(-2, 2), Point(2, 4), -1));
Chris@16 1859 data.push_back(vertex_half_edge(Point(-2, 2), Point(-3, 1), 1));
Chris@16 1860 data.push_back(vertex_half_edge(Point(2, -4), Point(-3, 1), -1));
Chris@16 1861 data.push_back(vertex_half_edge(Point(2, -4), Point(2, 4), -1));
Chris@16 1862 data.push_back(vertex_half_edge(Point(2, 4), Point(-2, 2), 1));
Chris@16 1863 data.push_back(vertex_half_edge(Point(2, 4), Point(2, -4), 1));
Chris@16 1864 polygon_sort(data.begin(), data.end());
Chris@16 1865 pf.scan(polys, data.begin(), data.end());
Chris@16 1866 stdcout << "result size: " << polys.size() << "\n";
Chris@16 1867 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 1868 stdcout << polys[i] << "\n";
Chris@16 1869 }
Chris@16 1870 stdcout << "done testing polygon formation\n";
Chris@16 1871 return true;
Chris@16 1872 }
Chris@16 1873
Chris@16 1874
Chris@16 1875 template <typename stream_type>
Chris@16 1876 static inline bool testPolygonArbitraryFormationPolys(stream_type& stdcout) {
Chris@16 1877 stdcout << "testing polygon formation polys\n";
Chris@16 1878 polygon_arbitrary_formation pf(false);
Chris@16 1879 std::vector<polygon_with_holes_data<Unit> > polys;
Chris@16 1880 polygon_arbitrary_formation pf2(true);
Chris@16 1881 std::vector<polygon_with_holes_data<Unit> > polys2;
Chris@16 1882 std::vector<vertex_half_edge> data;
Chris@16 1883 data.push_back(vertex_half_edge(Point(0, 0), Point(100, 1), 1));
Chris@16 1884 data.push_back(vertex_half_edge(Point(0, 0), Point(1, 100), -1));
Chris@16 1885 data.push_back(vertex_half_edge(Point(1, 100), Point(0, 0), 1));
Chris@16 1886 data.push_back(vertex_half_edge(Point(1, 100), Point(101, 101), -1));
Chris@16 1887 data.push_back(vertex_half_edge(Point(100, 1), Point(0, 0), -1));
Chris@16 1888 data.push_back(vertex_half_edge(Point(100, 1), Point(101, 101), 1));
Chris@16 1889 data.push_back(vertex_half_edge(Point(101, 101), Point(100, 1), -1));
Chris@16 1890 data.push_back(vertex_half_edge(Point(101, 101), Point(1, 100), 1));
Chris@16 1891
Chris@16 1892 data.push_back(vertex_half_edge(Point(2, 2), Point(10, 2), -1));
Chris@16 1893 data.push_back(vertex_half_edge(Point(2, 2), Point(2, 10), -1));
Chris@16 1894 data.push_back(vertex_half_edge(Point(2, 10), Point(2, 2), 1));
Chris@16 1895 data.push_back(vertex_half_edge(Point(2, 10), Point(10, 10), 1));
Chris@16 1896 data.push_back(vertex_half_edge(Point(10, 2), Point(2, 2), 1));
Chris@16 1897 data.push_back(vertex_half_edge(Point(10, 2), Point(10, 10), 1));
Chris@16 1898 data.push_back(vertex_half_edge(Point(10, 10), Point(10, 2), -1));
Chris@16 1899 data.push_back(vertex_half_edge(Point(10, 10), Point(2, 10), -1));
Chris@16 1900
Chris@16 1901 data.push_back(vertex_half_edge(Point(2, 12), Point(10, 12), -1));
Chris@16 1902 data.push_back(vertex_half_edge(Point(2, 12), Point(2, 22), -1));
Chris@16 1903 data.push_back(vertex_half_edge(Point(2, 22), Point(2, 12), 1));
Chris@16 1904 data.push_back(vertex_half_edge(Point(2, 22), Point(10, 22), 1));
Chris@16 1905 data.push_back(vertex_half_edge(Point(10, 12), Point(2, 12), 1));
Chris@16 1906 data.push_back(vertex_half_edge(Point(10, 12), Point(10, 22), 1));
Chris@16 1907 data.push_back(vertex_half_edge(Point(10, 22), Point(10, 12), -1));
Chris@16 1908 data.push_back(vertex_half_edge(Point(10, 22), Point(2, 22), -1));
Chris@16 1909
Chris@16 1910 polygon_sort(data.begin(), data.end());
Chris@16 1911 pf.scan(polys, data.begin(), data.end());
Chris@16 1912 stdcout << "result size: " << polys.size() << "\n";
Chris@16 1913 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 1914 stdcout << polys[i] << "\n";
Chris@16 1915 }
Chris@16 1916 pf2.scan(polys2, data.begin(), data.end());
Chris@16 1917 stdcout << "result size: " << polys2.size() << "\n";
Chris@16 1918 for(std::size_t i = 0; i < polys2.size(); ++i) {
Chris@16 1919 stdcout << polys2[i] << "\n";
Chris@16 1920 }
Chris@16 1921 stdcout << "done testing polygon formation\n";
Chris@16 1922 return true;
Chris@16 1923 }
Chris@16 1924
Chris@16 1925 template <typename stream_type>
Chris@16 1926 static inline bool testPolygonArbitraryFormationSelfTouch1(stream_type& stdcout) {
Chris@16 1927 stdcout << "testing polygon formation self touch 1\n";
Chris@16 1928 polygon_arbitrary_formation pf(true);
Chris@16 1929 std::vector<polygon_data<Unit> > polys;
Chris@16 1930 std::vector<vertex_half_edge> data;
Chris@16 1931 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1));
Chris@16 1932 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 1933
Chris@16 1934 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 1935 data.push_back(vertex_half_edge(Point(0, 10), Point(5, 10), -1));
Chris@16 1936
Chris@16 1937 data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1));
Chris@16 1938 data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1));
Chris@16 1939
Chris@16 1940 data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1));
Chris@16 1941 data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1));
Chris@16 1942
Chris@16 1943 data.push_back(vertex_half_edge(Point(5, 10), Point(5, 5), 1));
Chris@16 1944 data.push_back(vertex_half_edge(Point(5, 10), Point(0, 10), 1));
Chris@16 1945
Chris@16 1946 data.push_back(vertex_half_edge(Point(5, 2), Point(5, 5), -1));
Chris@16 1947 data.push_back(vertex_half_edge(Point(5, 2), Point(7, 2), -1));
Chris@16 1948
Chris@16 1949 data.push_back(vertex_half_edge(Point(5, 5), Point(5, 10), -1));
Chris@16 1950 data.push_back(vertex_half_edge(Point(5, 5), Point(5, 2), 1));
Chris@16 1951 data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1));
Chris@16 1952 data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1));
Chris@16 1953
Chris@16 1954 data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1));
Chris@16 1955 data.push_back(vertex_half_edge(Point(7, 2), Point(5, 2), 1));
Chris@16 1956
Chris@16 1957 polygon_sort(data.begin(), data.end());
Chris@16 1958 pf.scan(polys, data.begin(), data.end());
Chris@16 1959 stdcout << "result size: " << polys.size() << "\n";
Chris@16 1960 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 1961 stdcout << polys[i] << "\n";
Chris@16 1962 }
Chris@16 1963 stdcout << "done testing polygon formation\n";
Chris@16 1964 return true;
Chris@16 1965 }
Chris@16 1966
Chris@16 1967 template <typename stream_type>
Chris@16 1968 static inline bool testPolygonArbitraryFormationSelfTouch2(stream_type& stdcout) {
Chris@16 1969 stdcout << "testing polygon formation self touch 2\n";
Chris@16 1970 polygon_arbitrary_formation pf(true);
Chris@16 1971 std::vector<polygon_data<Unit> > polys;
Chris@16 1972 std::vector<vertex_half_edge> data;
Chris@16 1973 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1));
Chris@16 1974 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 1975
Chris@16 1976 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 1977 data.push_back(vertex_half_edge(Point(0, 10), Point(5, 10), -1));
Chris@16 1978
Chris@16 1979 data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1));
Chris@16 1980 data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1));
Chris@16 1981
Chris@16 1982 data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1));
Chris@16 1983 data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1));
Chris@16 1984
Chris@16 1985 data.push_back(vertex_half_edge(Point(5, 10), Point(4, 1), -1));
Chris@16 1986 data.push_back(vertex_half_edge(Point(5, 10), Point(0, 10), 1));
Chris@16 1987
Chris@16 1988 data.push_back(vertex_half_edge(Point(4, 1), Point(5, 10), 1));
Chris@16 1989 data.push_back(vertex_half_edge(Point(4, 1), Point(7, 2), -1));
Chris@16 1990
Chris@16 1991 data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1));
Chris@16 1992 data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1));
Chris@16 1993
Chris@16 1994 data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1));
Chris@16 1995 data.push_back(vertex_half_edge(Point(7, 2), Point(4, 1), 1));
Chris@16 1996
Chris@16 1997 polygon_sort(data.begin(), data.end());
Chris@16 1998 pf.scan(polys, data.begin(), data.end());
Chris@16 1999 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2000 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2001 stdcout << polys[i] << "\n";
Chris@16 2002 }
Chris@16 2003 stdcout << "done testing polygon formation\n";
Chris@16 2004 return true;
Chris@16 2005 }
Chris@16 2006
Chris@16 2007 template <typename stream_type>
Chris@16 2008 static inline bool testPolygonArbitraryFormationSelfTouch3(stream_type& stdcout) {
Chris@16 2009 stdcout << "testing polygon formation self touch 3\n";
Chris@16 2010 polygon_arbitrary_formation pf(true);
Chris@16 2011 std::vector<polygon_data<Unit> > polys;
Chris@16 2012 std::vector<vertex_half_edge> data;
Chris@16 2013 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1));
Chris@16 2014 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 2015
Chris@16 2016 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 2017 data.push_back(vertex_half_edge(Point(0, 10), Point(6, 10), -1));
Chris@16 2018
Chris@16 2019 data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1));
Chris@16 2020 data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1));
Chris@16 2021
Chris@16 2022 data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1));
Chris@16 2023 data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1));
Chris@16 2024
Chris@16 2025 data.push_back(vertex_half_edge(Point(6, 10), Point(4, 1), -1));
Chris@16 2026 data.push_back(vertex_half_edge(Point(6, 10), Point(0, 10), 1));
Chris@16 2027
Chris@16 2028 data.push_back(vertex_half_edge(Point(4, 1), Point(6, 10), 1));
Chris@16 2029 data.push_back(vertex_half_edge(Point(4, 1), Point(7, 2), -1));
Chris@16 2030
Chris@16 2031 data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1));
Chris@16 2032 data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1));
Chris@16 2033
Chris@16 2034 data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1));
Chris@16 2035 data.push_back(vertex_half_edge(Point(7, 2), Point(4, 1), 1));
Chris@16 2036
Chris@16 2037 polygon_sort(data.begin(), data.end());
Chris@16 2038 pf.scan(polys, data.begin(), data.end());
Chris@16 2039 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2040 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2041 stdcout << polys[i] << "\n";
Chris@16 2042 }
Chris@16 2043 stdcout << "done testing polygon formation\n";
Chris@16 2044 return true;
Chris@16 2045 }
Chris@16 2046
Chris@16 2047 template <typename stream_type>
Chris@16 2048 static inline bool testPolygonArbitraryFormationColinear(stream_type& stdcout) {
Chris@16 2049 stdcout << "testing polygon formation colinear 3\n";
Chris@16 2050 stdcout << "Polygon Set Data { <-3 2, -2 2>:1 <-3 2, -1 4>:-1 <-2 2, 0 2>:1 <-1 4, 0 2>:-1 } \n";
Chris@16 2051 polygon_arbitrary_formation pf(true);
Chris@16 2052 std::vector<polygon_data<Unit> > polys;
Chris@16 2053 std::vector<vertex_half_edge> data;
Chris@16 2054 data.push_back(vertex_half_edge(Point(-3, 2), Point(-2, 2), 1));
Chris@16 2055 data.push_back(vertex_half_edge(Point(-2, 2), Point(-3, 2), -1));
Chris@16 2056
Chris@16 2057 data.push_back(vertex_half_edge(Point(-3, 2), Point(-1, 4), -1));
Chris@16 2058 data.push_back(vertex_half_edge(Point(-1, 4), Point(-3, 2), 1));
Chris@16 2059
Chris@16 2060 data.push_back(vertex_half_edge(Point(-2, 2), Point(0, 2), 1));
Chris@16 2061 data.push_back(vertex_half_edge(Point(0, 2), Point(-2, 2), -1));
Chris@16 2062
Chris@16 2063 data.push_back(vertex_half_edge(Point(-1, 4), Point(0, 2), -1));
Chris@16 2064 data.push_back(vertex_half_edge(Point(0, 2), Point(-1, 4), 1));
Chris@16 2065 polygon_sort(data.begin(), data.end());
Chris@16 2066 pf.scan(polys, data.begin(), data.end());
Chris@16 2067 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2068 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2069 stdcout << polys[i] << "\n";
Chris@16 2070 }
Chris@16 2071 stdcout << "done testing polygon formation\n";
Chris@16 2072 return true;
Chris@16 2073 }
Chris@16 2074
Chris@16 2075 template <typename stream_type>
Chris@16 2076 static inline bool testSegmentIntersection(stream_type& stdcout) {
Chris@16 2077 stdcout << "testing segment intersection\n";
Chris@16 2078 half_edge he1, he2;
Chris@16 2079 he1.first = Point(0, 0);
Chris@16 2080 he1.second = Point(10, 10);
Chris@16 2081 he2.first = Point(0, 0);
Chris@16 2082 he2.second = Point(10, 20);
Chris@16 2083 Point result;
Chris@16 2084 bool b = scanline_base<Unit>::compute_intersection(result, he1, he2);
Chris@16 2085 if(!b || result != Point(0, 0)) return false;
Chris@16 2086 he1.first = Point(0, 10);
Chris@16 2087 b = scanline_base<Unit>::compute_intersection(result, he1, he2);
Chris@16 2088 if(!b || result != Point(5, 10)) return false;
Chris@16 2089 he1.first = Point(0, 11);
Chris@16 2090 b = scanline_base<Unit>::compute_intersection(result, he1, he2);
Chris@16 2091 if(!b || result != Point(5, 10)) return false;
Chris@16 2092 he1.first = Point(0, 0);
Chris@16 2093 he1.second = Point(1, 9);
Chris@16 2094 he2.first = Point(0, 9);
Chris@16 2095 he2.second = Point(1, 0);
Chris@16 2096 b = scanline_base<Unit>::compute_intersection(result, he1, he2);
Chris@16 2097 if(!b || result != Point(0, 4)) return false;
Chris@16 2098
Chris@16 2099 he1.first = Point(0, -10);
Chris@16 2100 he1.second = Point(1, -1);
Chris@16 2101 he2.first = Point(0, -1);
Chris@16 2102 he2.second = Point(1, -10);
Chris@16 2103 b = scanline_base<Unit>::compute_intersection(result, he1, he2);
Chris@16 2104 if(!b || result != Point(0, -5)) return false;
Chris@16 2105 he1.first = Point((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)()-1);
Chris@16 2106 he1.second = Point((std::numeric_limits<int>::min)(), (std::numeric_limits<int>::max)());
Chris@16 2107 //he1.second = Point(0, (std::numeric_limits<int>::max)());
Chris@16 2108 he2.first = Point((std::numeric_limits<int>::max)()-1, (std::numeric_limits<int>::max)());
Chris@16 2109 he2.second = Point((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::min)());
Chris@16 2110 //he2.second = Point((std::numeric_limits<int>::max)(), 0);
Chris@16 2111 b = scanline_base<Unit>::compute_intersection(result, he1, he2);
Chris@16 2112 //b is false because of overflow error
Chris@16 2113 he1.first = Point(1000, 2000);
Chris@16 2114 he1.second = Point(1010, 2010);
Chris@16 2115 he2.first = Point(1000, 2000);
Chris@16 2116 he2.second = Point(1010, 2020);
Chris@16 2117 b = scanline_base<Unit>::compute_intersection(result, he1, he2);
Chris@16 2118 if(!b || result != Point(1000, 2000)) return false;
Chris@16 2119
Chris@16 2120 return b;
Chris@16 2121 }
Chris@16 2122
Chris@16 2123 };
Chris@16 2124
Chris@16 2125 template <typename Unit>
Chris@16 2126 class poly_line_arbitrary_hole_data {
Chris@16 2127 private:
Chris@16 2128 typedef typename polygon_arbitrary_formation<Unit>::active_tail_arbitrary active_tail_arbitrary;
Chris@16 2129 active_tail_arbitrary* p_;
Chris@16 2130 public:
Chris@16 2131 typedef point_data<Unit> Point;
Chris@16 2132 typedef Point point_type;
Chris@16 2133 typedef Unit coordinate_type;
Chris@16 2134 typedef typename active_tail_arbitrary::iterator iterator_type;
Chris@16 2135 //typedef iterator_points_to_compact<iterator_type, Point> compact_iterator_type;
Chris@16 2136
Chris@16 2137 typedef iterator_type iterator;
Chris@16 2138 inline poly_line_arbitrary_hole_data() : p_(0) {}
Chris@16 2139 inline poly_line_arbitrary_hole_data(active_tail_arbitrary* p) : p_(p) {}
Chris@16 2140 //use default copy and assign
Chris@16 2141 inline iterator begin() const { return p_->getTail()->begin(); }
Chris@16 2142 inline iterator end() const { return p_->getTail()->end(); }
Chris@16 2143 //inline compact_iterator_type begin_compact() const { return compact_iterator_type(begin()); }
Chris@16 2144 //inline compact_iterator_type end_compact() const { return compact_iterator_type(end()); }
Chris@16 2145 inline std::size_t size() const { return 0; }
Chris@16 2146 template<class iT>
Chris@16 2147 inline poly_line_arbitrary_hole_data& set(iT inputBegin, iT inputEnd) {
Chris@16 2148 //assert this is not called
Chris@16 2149 return *this;
Chris@16 2150 }
Chris@16 2151 template<class iT>
Chris@16 2152 inline poly_line_arbitrary_hole_data& set_compact(iT inputBegin, iT inputEnd) {
Chris@16 2153 //assert this is not called
Chris@16 2154 return *this;
Chris@16 2155 }
Chris@16 2156 };
Chris@16 2157
Chris@16 2158 template <typename Unit>
Chris@16 2159 class poly_line_arbitrary_polygon_data {
Chris@16 2160 private:
Chris@16 2161 typedef typename polygon_arbitrary_formation<Unit>::active_tail_arbitrary active_tail_arbitrary;
Chris@16 2162 active_tail_arbitrary* p_;
Chris@16 2163 public:
Chris@16 2164 typedef point_data<Unit> Point;
Chris@16 2165 typedef Point point_type;
Chris@16 2166 typedef Unit coordinate_type;
Chris@16 2167 typedef typename active_tail_arbitrary::iterator iterator_type;
Chris@16 2168 //typedef iterator_points_to_compact<iterator_type, Point> compact_iterator_type;
Chris@16 2169 typedef typename coordinate_traits<Unit>::coordinate_distance area_type;
Chris@16 2170
Chris@16 2171 class iterator_holes_type {
Chris@16 2172 private:
Chris@16 2173 typedef poly_line_arbitrary_hole_data<Unit> holeType;
Chris@16 2174 mutable holeType hole_;
Chris@16 2175 typename active_tail_arbitrary::iteratorHoles itr_;
Chris@16 2176
Chris@16 2177 public:
Chris@16 2178 typedef std::forward_iterator_tag iterator_category;
Chris@16 2179 typedef holeType value_type;
Chris@16 2180 typedef std::ptrdiff_t difference_type;
Chris@16 2181 typedef const holeType* pointer; //immutable
Chris@16 2182 typedef const holeType& reference; //immutable
Chris@16 2183 inline iterator_holes_type() : hole_(), itr_() {}
Chris@16 2184 inline iterator_holes_type(typename active_tail_arbitrary::iteratorHoles itr) : hole_(), itr_(itr) {}
Chris@16 2185 inline iterator_holes_type(const iterator_holes_type& that) : hole_(that.hole_), itr_(that.itr_) {}
Chris@16 2186 inline iterator_holes_type& operator=(const iterator_holes_type& that) {
Chris@16 2187 itr_ = that.itr_;
Chris@16 2188 return *this;
Chris@16 2189 }
Chris@16 2190 inline bool operator==(const iterator_holes_type& that) { return itr_ == that.itr_; }
Chris@16 2191 inline bool operator!=(const iterator_holes_type& that) { return itr_ != that.itr_; }
Chris@16 2192 inline iterator_holes_type& operator++() {
Chris@16 2193 ++itr_;
Chris@16 2194 return *this;
Chris@16 2195 }
Chris@16 2196 inline const iterator_holes_type operator++(int) {
Chris@16 2197 iterator_holes_type tmp = *this;
Chris@16 2198 ++(*this);
Chris@16 2199 return tmp;
Chris@16 2200 }
Chris@16 2201 inline reference operator*() {
Chris@16 2202 hole_ = holeType(*itr_);
Chris@16 2203 return hole_;
Chris@16 2204 }
Chris@16 2205 };
Chris@16 2206
Chris@16 2207 typedef poly_line_arbitrary_hole_data<Unit> hole_type;
Chris@16 2208
Chris@16 2209 inline poly_line_arbitrary_polygon_data() : p_(0) {}
Chris@16 2210 inline poly_line_arbitrary_polygon_data(active_tail_arbitrary* p) : p_(p) {}
Chris@16 2211 //use default copy and assign
Chris@16 2212 inline iterator_type begin() const { return p_->getTail()->begin(); }
Chris@16 2213 inline iterator_type end() const { return p_->getTail()->end(); }
Chris@16 2214 //inline compact_iterator_type begin_compact() const { return p_->getTail()->begin(); }
Chris@16 2215 //inline compact_iterator_type end_compact() const { return p_->getTail()->end(); }
Chris@16 2216 inline iterator_holes_type begin_holes() const { return iterator_holes_type(p_->getHoles().begin()); }
Chris@16 2217 inline iterator_holes_type end_holes() const { return iterator_holes_type(p_->getHoles().end()); }
Chris@16 2218 inline active_tail_arbitrary* yield() { return p_; }
Chris@16 2219 //stub out these four required functions that will not be used but are needed for the interface
Chris@16 2220 inline std::size_t size_holes() const { return 0; }
Chris@16 2221 inline std::size_t size() const { return 0; }
Chris@16 2222 template<class iT>
Chris@16 2223 inline poly_line_arbitrary_polygon_data& set(iT inputBegin, iT inputEnd) {
Chris@16 2224 return *this;
Chris@16 2225 }
Chris@16 2226 template<class iT>
Chris@16 2227 inline poly_line_arbitrary_polygon_data& set_compact(iT inputBegin, iT inputEnd) {
Chris@16 2228 return *this;
Chris@16 2229 }
Chris@16 2230 template<class iT>
Chris@16 2231 inline poly_line_arbitrary_polygon_data& set_holes(iT inputBegin, iT inputEnd) {
Chris@16 2232 return *this;
Chris@16 2233 }
Chris@16 2234 };
Chris@16 2235
Chris@16 2236 template <typename Unit>
Chris@16 2237 class trapezoid_arbitrary_formation : public polygon_arbitrary_formation<Unit> {
Chris@16 2238 private:
Chris@16 2239 typedef typename scanline_base<Unit>::Point Point;
Chris@16 2240 typedef typename scanline_base<Unit>::half_edge half_edge;
Chris@16 2241 typedef typename scanline_base<Unit>::vertex_half_edge vertex_half_edge;
Chris@16 2242 typedef typename scanline_base<Unit>::less_vertex_half_edge less_vertex_half_edge;
Chris@16 2243
Chris@16 2244 typedef typename polygon_arbitrary_formation<Unit>::poly_line_arbitrary poly_line_arbitrary;
Chris@16 2245
Chris@16 2246 typedef typename polygon_arbitrary_formation<Unit>::active_tail_arbitrary active_tail_arbitrary;
Chris@16 2247
Chris@16 2248 typedef std::vector<std::pair<Point, int> > vertex_arbitrary_count;
Chris@16 2249
Chris@16 2250 typedef typename polygon_arbitrary_formation<Unit>::less_half_edge_count less_half_edge_count;
Chris@16 2251
Chris@16 2252 typedef std::vector<std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*> > incoming_count;
Chris@16 2253
Chris@16 2254 typedef typename polygon_arbitrary_formation<Unit>::less_incoming_count less_incoming_count;
Chris@16 2255
Chris@16 2256 typedef typename polygon_arbitrary_formation<Unit>::vertex_arbitrary_compact vertex_arbitrary_compact;
Chris@16 2257
Chris@16 2258 private:
Chris@16 2259 //definitions
Chris@16 2260 typedef std::map<vertex_half_edge, active_tail_arbitrary*, less_vertex_half_edge> scanline_data;
Chris@16 2261 typedef typename scanline_data::iterator iterator;
Chris@16 2262 typedef typename scanline_data::const_iterator const_iterator;
Chris@16 2263
Chris@16 2264 //data
Chris@16 2265 public:
Chris@16 2266 inline trapezoid_arbitrary_formation() : polygon_arbitrary_formation<Unit>() {}
Chris@16 2267 inline trapezoid_arbitrary_formation(const trapezoid_arbitrary_formation& that) : polygon_arbitrary_formation<Unit>(that) {}
Chris@16 2268 inline trapezoid_arbitrary_formation& operator=(const trapezoid_arbitrary_formation& that) {
Chris@16 2269 * static_cast<polygon_arbitrary_formation<Unit>*>(this) = * static_cast<polygon_arbitrary_formation<Unit>*>(&that);
Chris@16 2270 return *this;
Chris@16 2271 }
Chris@16 2272
Chris@16 2273 //cT is an output container of Polygon45 or Polygon45WithHoles
Chris@16 2274 //iT is an iterator over vertex_half_edge elements
Chris@16 2275 //inputBegin - inputEnd is a range of sorted iT that represents
Chris@16 2276 //one or more scanline stops worth of data
Chris@16 2277 template <class cT, class iT>
Chris@16 2278 void scan(cT& output, iT inputBegin, iT inputEnd) {
Chris@16 2279 //std::cout << "1\n";
Chris@16 2280 while(inputBegin != inputEnd) {
Chris@16 2281 //std::cout << "2\n";
Chris@16 2282 polygon_arbitrary_formation<Unit>::x_ = (*inputBegin).pt.get(HORIZONTAL);
Chris@16 2283 //std::cout << "SCAN FORMATION " << x_ << "\n";
Chris@16 2284 //std::cout << "x_ = " << x_ << "\n";
Chris@16 2285 //std::cout << "scan line size: " << scanData_.size() << "\n";
Chris@16 2286 inputBegin = processEvent_(output, inputBegin, inputEnd);
Chris@16 2287 }
Chris@16 2288 //std::cout << "scan line size: " << scanData_.size() << "\n";
Chris@16 2289 }
Chris@16 2290
Chris@16 2291 private:
Chris@16 2292 //functions
Chris@16 2293 inline void getVerticalPair_(std::pair<active_tail_arbitrary*,
Chris@16 2294 active_tail_arbitrary*>& verticalPair,
Chris@16 2295 iterator previter) {
Chris@16 2296 active_tail_arbitrary* iterTail = (*previter).second;
Chris@16 2297 Point prevPoint(polygon_arbitrary_formation<Unit>::x_,
Chris@16 2298 convert_high_precision_type<Unit>(previter->first.evalAtX(polygon_arbitrary_formation<Unit>::x_)));
Chris@16 2299 iterTail->pushPoint(prevPoint);
Chris@16 2300 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> tailPair =
Chris@16 2301 active_tail_arbitrary::createActiveTailsAsPair(prevPoint, true, 0, false);
Chris@16 2302 verticalPair.first = iterTail;
Chris@16 2303 verticalPair.second = tailPair.first;
Chris@16 2304 (*previter).second = tailPair.second;
Chris@16 2305 }
Chris@16 2306
Chris@16 2307 template <class cT, class cT2>
Chris@16 2308 inline std::pair<std::pair<Point, int>, active_tail_arbitrary*>
Chris@16 2309 processPoint_(cT& output, cT2& elements,
Chris@16 2310 std::pair<active_tail_arbitrary*, active_tail_arbitrary*>& verticalPair,
Chris@16 2311 iterator previter, Point point, incoming_count& counts_from_scanline,
Chris@16 2312 vertex_arbitrary_count& incoming_count) {
Chris@16 2313 //std::cout << "\nAT POINT: " << point << "\n";
Chris@16 2314 //join any closing solid corners
Chris@16 2315 std::vector<int> counts;
Chris@16 2316 std::vector<int> incoming;
Chris@16 2317 std::vector<active_tail_arbitrary*> tails;
Chris@16 2318 counts.reserve(counts_from_scanline.size());
Chris@16 2319 tails.reserve(counts_from_scanline.size());
Chris@16 2320 incoming.reserve(incoming_count.size());
Chris@16 2321 for(std::size_t i = 0; i < counts_from_scanline.size(); ++i) {
Chris@16 2322 counts.push_back(counts_from_scanline[i].first.second);
Chris@16 2323 tails.push_back(counts_from_scanline[i].second);
Chris@16 2324 }
Chris@16 2325 for(std::size_t i = 0; i < incoming_count.size(); ++i) {
Chris@16 2326 incoming.push_back(incoming_count[i].second);
Chris@16 2327 if(incoming_count[i].first < point) {
Chris@16 2328 incoming.back() = 0;
Chris@16 2329 }
Chris@16 2330 }
Chris@16 2331
Chris@16 2332 active_tail_arbitrary* returnValue = 0;
Chris@16 2333 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> verticalPairOut;
Chris@16 2334 verticalPairOut.first = 0;
Chris@16 2335 verticalPairOut.second = 0;
Chris@16 2336 std::pair<Point, int> returnCount(Point(0, 0), 0);
Chris@16 2337 int i_size_less_1 = (int)(incoming.size()) -1;
Chris@16 2338 int c_size_less_1 = (int)(counts.size()) -1;
Chris@16 2339 int i_size = incoming.size();
Chris@16 2340 int c_size = counts.size();
Chris@16 2341
Chris@16 2342 bool have_vertical_tail_from_below = false;
Chris@16 2343 if(c_size &&
Chris@16 2344 scanline_base<Unit>::is_vertical(counts_from_scanline.back().first.first)) {
Chris@16 2345 have_vertical_tail_from_below = true;
Chris@16 2346 }
Chris@16 2347 //assert size = size_less_1 + 1
Chris@16 2348 //std::cout << tails.size() << " " << incoming.size() << " " << counts_from_scanline.size() << " " << incoming_count.size() << "\n";
Chris@16 2349 // for(std::size_t i = 0; i < counts.size(); ++i) {
Chris@16 2350 // std::cout << counts_from_scanline[i].first.first.first.get(HORIZONTAL) << ",";
Chris@16 2351 // std::cout << counts_from_scanline[i].first.first.first.get(VERTICAL) << " ";
Chris@16 2352 // std::cout << counts_from_scanline[i].first.first.second.get(HORIZONTAL) << ",";
Chris@16 2353 // std::cout << counts_from_scanline[i].first.first.second.get(VERTICAL) << ":";
Chris@16 2354 // std::cout << counts_from_scanline[i].first.second << " ";
Chris@16 2355 // } std::cout << "\n";
Chris@16 2356 // print(incoming_count);
Chris@16 2357 {
Chris@16 2358 for(int i = 0; i < c_size_less_1; ++i) {
Chris@16 2359 //std::cout << i << "\n";
Chris@16 2360 if(counts[i] == -1) {
Chris@16 2361 //std::cout << "fixed i\n";
Chris@16 2362 for(int j = i + 1; j < c_size; ++j) {
Chris@16 2363 //std::cout << j << "\n";
Chris@16 2364 if(counts[j]) {
Chris@16 2365 if(counts[j] == 1) {
Chris@16 2366 //std::cout << "case1: " << i << " " << j << "\n";
Chris@16 2367 //if a figure is closed it will be written out by this function to output
Chris@16 2368 active_tail_arbitrary::joinChains(point, tails[i], tails[j], true, output);
Chris@16 2369 counts[i] = 0;
Chris@16 2370 counts[j] = 0;
Chris@16 2371 tails[i] = 0;
Chris@16 2372 tails[j] = 0;
Chris@16 2373 }
Chris@16 2374 break;
Chris@16 2375 }
Chris@16 2376 }
Chris@16 2377 }
Chris@16 2378 }
Chris@16 2379 }
Chris@16 2380 //find any pairs of incoming edges that need to create pair for leading solid
Chris@16 2381 //std::cout << "checking case2\n";
Chris@16 2382 {
Chris@16 2383 for(int i = 0; i < i_size_less_1; ++i) {
Chris@16 2384 //std::cout << i << "\n";
Chris@16 2385 if(incoming[i] == 1) {
Chris@16 2386 //std::cout << "fixed i\n";
Chris@16 2387 for(int j = i + 1; j < i_size; ++j) {
Chris@16 2388 //std::cout << j << "\n";
Chris@16 2389 if(incoming[j]) {
Chris@16 2390 //std::cout << incoming[j] << "\n";
Chris@16 2391 if(incoming[j] == -1) {
Chris@16 2392 //std::cout << "case2: " << i << " " << j << "\n";
Chris@16 2393 //std::cout << "creating active tail pair\n";
Chris@16 2394 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> tailPair =
Chris@16 2395 active_tail_arbitrary::createActiveTailsAsPair(point, true, 0, polygon_arbitrary_formation<Unit>::fractureHoles_ != 0);
Chris@16 2396 //tailPair.first->print();
Chris@16 2397 //tailPair.second->print();
Chris@16 2398 if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 2399 //vertical active tail becomes return value
Chris@16 2400 returnValue = tailPair.first;
Chris@16 2401 returnCount.first = point;
Chris@16 2402 returnCount.second = 1;
Chris@16 2403 } else {
Chris@16 2404 //std::cout << "new element " << j-1 << " " << -1 << "\n";
Chris@16 2405 //std::cout << point << " " << incoming_count[j].first << "\n";
Chris@16 2406 elements.push_back(std::pair<vertex_half_edge,
Chris@16 2407 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 2408 incoming_count[j].first, -1), tailPair.first));
Chris@16 2409 }
Chris@16 2410 //std::cout << "new element " << i-1 << " " << 1 << "\n";
Chris@16 2411 //std::cout << point << " " << incoming_count[i].first << "\n";
Chris@16 2412 elements.push_back(std::pair<vertex_half_edge,
Chris@16 2413 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 2414 incoming_count[i].first, 1), tailPair.second));
Chris@16 2415 incoming[i] = 0;
Chris@16 2416 incoming[j] = 0;
Chris@16 2417 }
Chris@16 2418 break;
Chris@16 2419 }
Chris@16 2420 }
Chris@16 2421 }
Chris@16 2422 }
Chris@16 2423 }
Chris@16 2424 //find any active tail that needs to pass through to an incoming edge
Chris@16 2425 //we expect to find no more than two pass through
Chris@16 2426
Chris@16 2427 //find pass through with solid on top
Chris@16 2428 {
Chris@16 2429 //std::cout << "checking case 3\n";
Chris@16 2430 for(int i = 0; i < c_size; ++i) {
Chris@16 2431 //std::cout << i << "\n";
Chris@16 2432 if(counts[i] != 0) {
Chris@16 2433 if(counts[i] == 1) {
Chris@16 2434 //std::cout << "fixed i\n";
Chris@16 2435 for(int j = i_size_less_1; j >= 0; --j) {
Chris@16 2436 if(incoming[j] != 0) {
Chris@16 2437 if(incoming[j] == 1) {
Chris@16 2438 //std::cout << "case3: " << i << " " << j << "\n";
Chris@16 2439 //tails[i]->print();
Chris@16 2440 //pass through solid on top
Chris@16 2441 tails[i]->pushPoint(point);
Chris@16 2442 //std::cout << "after push\n";
Chris@16 2443 if(j == i_size_less_1 && incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 2444 returnValue = tails[i];
Chris@16 2445 returnCount.first = point;
Chris@16 2446 returnCount.second = -1;
Chris@16 2447 } else {
Chris@16 2448 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> tailPair =
Chris@16 2449 active_tail_arbitrary::createActiveTailsAsPair(point, true, 0, false);
Chris@16 2450 verticalPairOut.first = tails[i];
Chris@16 2451 verticalPairOut.second = tailPair.first;
Chris@16 2452 elements.push_back(std::pair<vertex_half_edge,
Chris@16 2453 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 2454 incoming_count[j].first, incoming[j]), tailPair.second));
Chris@16 2455 }
Chris@16 2456 tails[i] = 0;
Chris@16 2457 counts[i] = 0;
Chris@16 2458 incoming[j] = 0;
Chris@16 2459 }
Chris@16 2460 break;
Chris@16 2461 }
Chris@16 2462 }
Chris@16 2463 }
Chris@16 2464 break;
Chris@16 2465 }
Chris@16 2466 }
Chris@16 2467 }
Chris@16 2468 //std::cout << "checking case 4\n";
Chris@16 2469 //find pass through with solid on bottom
Chris@16 2470 {
Chris@16 2471 for(int i = c_size_less_1; i >= 0; --i) {
Chris@16 2472 //std::cout << "i = " << i << " with count " << counts[i] << "\n";
Chris@16 2473 if(counts[i] != 0) {
Chris@16 2474 if(counts[i] == -1) {
Chris@16 2475 for(int j = 0; j < i_size; ++j) {
Chris@16 2476 if(incoming[j] != 0) {
Chris@16 2477 if(incoming[j] == -1) {
Chris@16 2478 //std::cout << "case4: " << i << " " << j << "\n";
Chris@16 2479 //pass through solid on bottom
Chris@16 2480
Chris@16 2481 //if count from scanline is vertical
Chris@16 2482 if(i == c_size_less_1 &&
Chris@16 2483 counts_from_scanline[i].first.first.first.get(HORIZONTAL) ==
Chris@16 2484 point.get(HORIZONTAL)) {
Chris@16 2485 //if incoming count is vertical
Chris@16 2486 if(j == i_size_less_1 &&
Chris@16 2487 incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 2488 returnValue = tails[i];
Chris@16 2489 returnCount.first = point;
Chris@16 2490 returnCount.second = 1;
Chris@16 2491 } else {
Chris@16 2492 tails[i]->pushPoint(point);
Chris@16 2493 elements.push_back(std::pair<vertex_half_edge,
Chris@16 2494 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 2495 incoming_count[j].first, incoming[j]), tails[i]));
Chris@16 2496 }
Chris@16 2497 } else if(j == i_size_less_1 &&
Chris@16 2498 incoming_count[j].first.get(HORIZONTAL) ==
Chris@16 2499 point.get(HORIZONTAL)) {
Chris@16 2500 if(verticalPair.first == 0) {
Chris@16 2501 getVerticalPair_(verticalPair, previter);
Chris@16 2502 }
Chris@16 2503 active_tail_arbitrary::joinChains(point, tails[i], verticalPair.first, true, output);
Chris@16 2504 returnValue = verticalPair.second;
Chris@16 2505 returnCount.first = point;
Chris@16 2506 returnCount.second = 1;
Chris@16 2507 } else {
Chris@16 2508 //neither is vertical
Chris@16 2509 if(verticalPair.first == 0) {
Chris@16 2510 getVerticalPair_(verticalPair, previter);
Chris@16 2511 }
Chris@16 2512 active_tail_arbitrary::joinChains(point, tails[i], verticalPair.first, true, output);
Chris@16 2513 verticalPair.second->pushPoint(point);
Chris@16 2514 elements.push_back(std::pair<vertex_half_edge,
Chris@16 2515 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 2516 incoming_count[j].first, incoming[j]), verticalPair.second));
Chris@16 2517 }
Chris@16 2518 tails[i] = 0;
Chris@16 2519 counts[i] = 0;
Chris@16 2520 incoming[j] = 0;
Chris@16 2521 }
Chris@16 2522 break;
Chris@16 2523 }
Chris@16 2524 }
Chris@16 2525 }
Chris@16 2526 break;
Chris@16 2527 }
Chris@16 2528 }
Chris@16 2529 }
Chris@16 2530 //find the end of a hole or the beginning of a hole
Chris@16 2531
Chris@16 2532 //find end of a hole
Chris@16 2533 {
Chris@16 2534 for(int i = 0; i < c_size_less_1; ++i) {
Chris@16 2535 if(counts[i] != 0) {
Chris@16 2536 for(int j = i+1; j < c_size; ++j) {
Chris@16 2537 if(counts[j] != 0) {
Chris@16 2538 //std::cout << "case5: " << i << " " << j << "\n";
Chris@16 2539 //we are ending a hole and may potentially close a figure and have to handle the hole
Chris@16 2540 tails[i]->pushPoint(point);
Chris@16 2541 verticalPairOut.first = tails[i];
Chris@16 2542 if(j == c_size_less_1 &&
Chris@16 2543 counts_from_scanline[j].first.first.first.get(HORIZONTAL) ==
Chris@16 2544 point.get(HORIZONTAL)) {
Chris@16 2545 verticalPairOut.second = tails[j];
Chris@16 2546 } else {
Chris@16 2547 //need to close a trapezoid below
Chris@16 2548 if(verticalPair.first == 0) {
Chris@16 2549 getVerticalPair_(verticalPair, previter);
Chris@16 2550 }
Chris@16 2551 active_tail_arbitrary::joinChains(point, tails[j], verticalPair.first, true, output);
Chris@16 2552 verticalPairOut.second = verticalPair.second;
Chris@16 2553 }
Chris@16 2554 tails[i] = 0;
Chris@16 2555 tails[j] = 0;
Chris@16 2556 counts[i] = 0;
Chris@16 2557 counts[j] = 0;
Chris@16 2558 break;
Chris@16 2559 }
Chris@16 2560 }
Chris@16 2561 break;
Chris@16 2562 }
Chris@16 2563 }
Chris@16 2564 }
Chris@16 2565 //find beginning of a hole
Chris@16 2566 {
Chris@16 2567 for(int i = 0; i < i_size_less_1; ++i) {
Chris@16 2568 if(incoming[i] != 0) {
Chris@16 2569 for(int j = i+1; j < i_size; ++j) {
Chris@16 2570 if(incoming[j] != 0) {
Chris@16 2571 //std::cout << "case6: " << i << " " << j << "\n";
Chris@16 2572 //we are beginning a empty space
Chris@16 2573 if(verticalPair.first == 0) {
Chris@16 2574 getVerticalPair_(verticalPair, previter);
Chris@16 2575 }
Chris@16 2576 verticalPair.second->pushPoint(point);
Chris@16 2577 if(j == i_size_less_1 &&
Chris@16 2578 incoming_count[j].first.get(HORIZONTAL) == point.get(HORIZONTAL)) {
Chris@16 2579 returnValue = verticalPair.first;
Chris@16 2580 returnCount.first = point;
Chris@16 2581 returnCount.second = -1;
Chris@16 2582 } else {
Chris@16 2583 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> tailPair =
Chris@16 2584 active_tail_arbitrary::createActiveTailsAsPair(point, false, 0, false);
Chris@16 2585 elements.push_back(std::pair<vertex_half_edge,
Chris@16 2586 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 2587 incoming_count[j].first, incoming[j]), tailPair.second));
Chris@16 2588 verticalPairOut.second = tailPair.first;
Chris@16 2589 verticalPairOut.first = verticalPair.first;
Chris@16 2590 }
Chris@16 2591 elements.push_back(std::pair<vertex_half_edge,
Chris@16 2592 active_tail_arbitrary*>(vertex_half_edge(point,
Chris@16 2593 incoming_count[i].first, incoming[i]), verticalPair.second));
Chris@16 2594 incoming[i] = 0;
Chris@16 2595 incoming[j] = 0;
Chris@16 2596 break;
Chris@16 2597 }
Chris@16 2598 }
Chris@16 2599 break;
Chris@16 2600 }
Chris@16 2601 }
Chris@16 2602 }
Chris@16 2603 if(have_vertical_tail_from_below) {
Chris@16 2604 if(tails.back()) {
Chris@16 2605 tails.back()->pushPoint(point);
Chris@16 2606 returnValue = tails.back();
Chris@16 2607 returnCount.first = point;
Chris@16 2608 returnCount.second = counts.back();
Chris@16 2609 }
Chris@16 2610 }
Chris@16 2611 verticalPair = verticalPairOut;
Chris@16 2612 //assert that tails, counts and incoming are all null
Chris@16 2613 return std::pair<std::pair<Point, int>, active_tail_arbitrary*>(returnCount, returnValue);
Chris@16 2614 }
Chris@16 2615
Chris@16 2616 static inline void print(const vertex_arbitrary_count& count) {
Chris@16 2617 for(unsigned i = 0; i < count.size(); ++i) {
Chris@16 2618 //std::cout << count[i].first.get(HORIZONTAL) << ",";
Chris@16 2619 //std::cout << count[i].first.get(VERTICAL) << ":";
Chris@16 2620 //std::cout << count[i].second << " ";
Chris@16 2621 } //std::cout << "\n";
Chris@16 2622 }
Chris@16 2623
Chris@16 2624 static inline void print(const scanline_data& data) {
Chris@16 2625 for(typename scanline_data::const_iterator itr = data.begin(); itr != data.end(); ++itr){
Chris@16 2626 //std::cout << itr->first.pt << ", " << itr->first.other_pt << "; ";
Chris@16 2627 } //std::cout << "\n";
Chris@16 2628 }
Chris@16 2629
Chris@16 2630 template <class cT, class iT>
Chris@16 2631 inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) {
Chris@101 2632 //typedef typename high_precision_type<Unit>::type high_precision;
Chris@16 2633 //std::cout << "processEvent_\n";
Chris@16 2634 polygon_arbitrary_formation<Unit>::justBefore_ = true;
Chris@16 2635 //collect up all elements from the tree that are at the y
Chris@16 2636 //values of events in the input queue
Chris@16 2637 //create vector of new elements to add into tree
Chris@16 2638 active_tail_arbitrary* verticalTail = 0;
Chris@16 2639 std::pair<active_tail_arbitrary*, active_tail_arbitrary*> verticalPair;
Chris@16 2640 std::pair<Point, int> verticalCount(Point(0, 0), 0);
Chris@16 2641 iT currentIter = inputBegin;
Chris@16 2642 std::vector<iterator> elementIters;
Chris@16 2643 std::vector<std::pair<vertex_half_edge, active_tail_arbitrary*> > elements;
Chris@16 2644 while(currentIter != inputEnd && currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation<Unit>::x_) {
Chris@16 2645 //std::cout << "loop\n";
Chris@16 2646 Unit currentY = (*currentIter).pt.get(VERTICAL);
Chris@16 2647 //std::cout << "current Y " << currentY << "\n";
Chris@16 2648 //std::cout << "scanline size " << scanData_.size() << "\n";
Chris@16 2649 //print(scanData_);
Chris@16 2650 iterator iter = this->lookUp_(currentY);
Chris@16 2651 //std::cout << "found element in scanline " << (iter != scanData_.end()) << "\n";
Chris@16 2652 //int counts[4] = {0, 0, 0, 0};
Chris@16 2653 incoming_count counts_from_scanline;
Chris@16 2654 //std::cout << "finding elements in tree\n";
Chris@16 2655 //if(iter != scanData_.end())
Chris@16 2656 // std::cout << "first iter y is " << iter->first.evalAtX(x_) << "\n";
Chris@16 2657 iterator previter = iter;
Chris@16 2658 if(previter != polygon_arbitrary_formation<Unit>::scanData_.end() &&
Chris@16 2659 previter->first.evalAtX(polygon_arbitrary_formation<Unit>::x_) >= currentY &&
Chris@16 2660 previter != polygon_arbitrary_formation<Unit>::scanData_.begin())
Chris@16 2661 --previter;
Chris@16 2662 while(iter != polygon_arbitrary_formation<Unit>::scanData_.end() &&
Chris@16 2663 ((iter->first.pt.x() == polygon_arbitrary_formation<Unit>::x_ && iter->first.pt.y() == currentY) ||
Chris@16 2664 (iter->first.other_pt.x() == polygon_arbitrary_formation<Unit>::x_ && iter->first.other_pt.y() == currentY))) {
Chris@16 2665 //iter->first.evalAtX(polygon_arbitrary_formation<Unit>::x_) == (high_precision)currentY) {
Chris@16 2666 //std::cout << "loop2\n";
Chris@16 2667 elementIters.push_back(iter);
Chris@16 2668 counts_from_scanline.push_back(std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>
Chris@16 2669 (std::pair<std::pair<Point, Point>, int>(std::pair<Point, Point>(iter->first.pt,
Chris@16 2670 iter->first.other_pt),
Chris@16 2671 iter->first.count),
Chris@16 2672 iter->second));
Chris@16 2673 ++iter;
Chris@16 2674 }
Chris@16 2675 Point currentPoint(polygon_arbitrary_formation<Unit>::x_, currentY);
Chris@16 2676 //std::cout << "counts_from_scanline size " << counts_from_scanline.size() << "\n";
Chris@16 2677 this->sort_incoming_count(counts_from_scanline, currentPoint);
Chris@16 2678
Chris@16 2679 vertex_arbitrary_count incoming;
Chris@16 2680 //std::cout << "aggregating\n";
Chris@16 2681 do {
Chris@16 2682 //std::cout << "loop3\n";
Chris@16 2683 const vertex_half_edge& elem = *currentIter;
Chris@16 2684 incoming.push_back(std::pair<Point, int>(elem.other_pt, elem.count));
Chris@16 2685 ++currentIter;
Chris@16 2686 } while(currentIter != inputEnd && currentIter->pt.get(VERTICAL) == currentY &&
Chris@16 2687 currentIter->pt.get(HORIZONTAL) == polygon_arbitrary_formation<Unit>::x_);
Chris@16 2688 //print(incoming);
Chris@16 2689 this->sort_vertex_arbitrary_count(incoming, currentPoint);
Chris@16 2690 //std::cout << currentPoint.get(HORIZONTAL) << "," << currentPoint.get(VERTICAL) << "\n";
Chris@16 2691 //print(incoming);
Chris@16 2692 //std::cout << "incoming counts from input size " << incoming.size() << "\n";
Chris@16 2693 //compact_vertex_arbitrary_count(currentPoint, incoming);
Chris@16 2694 vertex_arbitrary_count tmp;
Chris@16 2695 tmp.reserve(incoming.size());
Chris@16 2696 for(std::size_t i = 0; i < incoming.size(); ++i) {
Chris@16 2697 if(currentPoint < incoming[i].first) {
Chris@16 2698 tmp.push_back(incoming[i]);
Chris@16 2699 }
Chris@16 2700 }
Chris@16 2701 incoming.swap(tmp);
Chris@16 2702 //std::cout << "incoming counts from input size " << incoming.size() << "\n";
Chris@16 2703 //now counts_from_scanline has the data from the left and
Chris@16 2704 //incoming has the data from the right at this point
Chris@16 2705 //cancel out any end points
Chris@16 2706 if(verticalTail) {
Chris@16 2707 //std::cout << "adding vertical tail to counts from scanline\n";
Chris@16 2708 //std::cout << -verticalCount.second << "\n";
Chris@16 2709 counts_from_scanline.push_back(std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*>
Chris@16 2710 (std::pair<std::pair<Point, Point>, int>(std::pair<Point, Point>(verticalCount.first,
Chris@16 2711 currentPoint),
Chris@16 2712 -verticalCount.second),
Chris@16 2713 verticalTail));
Chris@16 2714 }
Chris@16 2715 if(!incoming.empty() && incoming.back().first.get(HORIZONTAL) == polygon_arbitrary_formation<Unit>::x_) {
Chris@16 2716 //std::cout << "inverted vertical event\n";
Chris@16 2717 incoming.back().second *= -1;
Chris@16 2718 }
Chris@16 2719 //std::cout << "calling processPoint_\n";
Chris@16 2720 std::pair<std::pair<Point, int>, active_tail_arbitrary*> result = processPoint_(output, elements, verticalPair, previter, Point(polygon_arbitrary_formation<Unit>::x_, currentY), counts_from_scanline, incoming);
Chris@16 2721 verticalCount = result.first;
Chris@16 2722 verticalTail = result.second;
Chris@16 2723 if(verticalPair.first != 0 && iter != polygon_arbitrary_formation<Unit>::scanData_.end() &&
Chris@16 2724 (currentIter == inputEnd || currentIter->pt.x() != polygon_arbitrary_formation<Unit>::x_ ||
Chris@16 2725 currentIter->pt.y() > (*iter).first.evalAtX(polygon_arbitrary_formation<Unit>::x_))) {
Chris@16 2726 //splice vertical pair into edge above
Chris@16 2727 active_tail_arbitrary* tailabove = (*iter).second;
Chris@16 2728 Point point(polygon_arbitrary_formation<Unit>::x_,
Chris@16 2729 convert_high_precision_type<Unit>((*iter).first.evalAtX(polygon_arbitrary_formation<Unit>::x_)));
Chris@16 2730 verticalPair.second->pushPoint(point);
Chris@16 2731 active_tail_arbitrary::joinChains(point, tailabove, verticalPair.first, true, output);
Chris@16 2732 (*iter).second = verticalPair.second;
Chris@16 2733 verticalPair.first = 0;
Chris@16 2734 verticalPair.second = 0;
Chris@16 2735 }
Chris@16 2736 }
Chris@16 2737 //std::cout << "erasing\n";
Chris@16 2738 //erase all elements from the tree
Chris@16 2739 for(typename std::vector<iterator>::iterator iter = elementIters.begin();
Chris@16 2740 iter != elementIters.end(); ++iter) {
Chris@16 2741 //std::cout << "erasing loop\n";
Chris@16 2742 polygon_arbitrary_formation<Unit>::scanData_.erase(*iter);
Chris@16 2743 }
Chris@16 2744 //switch comparison tie breaking policy
Chris@16 2745 polygon_arbitrary_formation<Unit>::justBefore_ = false;
Chris@16 2746 //add new elements into tree
Chris@16 2747 //std::cout << "inserting\n";
Chris@16 2748 for(typename std::vector<std::pair<vertex_half_edge, active_tail_arbitrary*> >::iterator iter = elements.begin();
Chris@16 2749 iter != elements.end(); ++iter) {
Chris@16 2750 //std::cout << "inserting loop\n";
Chris@16 2751 polygon_arbitrary_formation<Unit>::scanData_.insert(polygon_arbitrary_formation<Unit>::scanData_.end(), *iter);
Chris@16 2752 }
Chris@16 2753 //std::cout << "end processEvent\n";
Chris@16 2754 return currentIter;
Chris@16 2755 }
Chris@16 2756 public:
Chris@16 2757 template <typename stream_type>
Chris@16 2758 static inline bool testTrapezoidArbitraryFormationRect(stream_type& stdcout) {
Chris@16 2759 stdcout << "testing trapezoid formation\n";
Chris@16 2760 trapezoid_arbitrary_formation pf;
Chris@16 2761 std::vector<polygon_data<Unit> > polys;
Chris@16 2762 std::vector<vertex_half_edge> data;
Chris@16 2763 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1));
Chris@16 2764 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 2765 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 2766 data.push_back(vertex_half_edge(Point(0, 10), Point(10, 10), -1));
Chris@16 2767 data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1));
Chris@16 2768 data.push_back(vertex_half_edge(Point(10, 0), Point(10, 10), -1));
Chris@16 2769 data.push_back(vertex_half_edge(Point(10, 10), Point(10, 0), 1));
Chris@16 2770 data.push_back(vertex_half_edge(Point(10, 10), Point(0, 10), 1));
Chris@16 2771 polygon_sort(data.begin(), data.end());
Chris@16 2772 pf.scan(polys, data.begin(), data.end());
Chris@16 2773 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2774 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2775 stdcout << polys[i] << "\n";
Chris@16 2776 }
Chris@16 2777 stdcout << "done testing trapezoid formation\n";
Chris@16 2778 return true;
Chris@16 2779 }
Chris@16 2780 template <typename stream_type>
Chris@16 2781 static inline bool testTrapezoidArbitraryFormationP1(stream_type& stdcout) {
Chris@16 2782 stdcout << "testing trapezoid formation P1\n";
Chris@16 2783 trapezoid_arbitrary_formation pf;
Chris@16 2784 std::vector<polygon_data<Unit> > polys;
Chris@16 2785 std::vector<vertex_half_edge> data;
Chris@16 2786 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 10), 1));
Chris@16 2787 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 2788 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 2789 data.push_back(vertex_half_edge(Point(0, 10), Point(10, 20), -1));
Chris@16 2790 data.push_back(vertex_half_edge(Point(10, 10), Point(0, 0), -1));
Chris@16 2791 data.push_back(vertex_half_edge(Point(10, 10), Point(10, 20), -1));
Chris@16 2792 data.push_back(vertex_half_edge(Point(10, 20), Point(10, 10), 1));
Chris@16 2793 data.push_back(vertex_half_edge(Point(10, 20), Point(0, 10), 1));
Chris@16 2794 polygon_sort(data.begin(), data.end());
Chris@16 2795 pf.scan(polys, data.begin(), data.end());
Chris@16 2796 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2797 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2798 stdcout << polys[i] << "\n";
Chris@16 2799 }
Chris@16 2800 stdcout << "done testing trapezoid formation\n";
Chris@16 2801 return true;
Chris@16 2802 }
Chris@16 2803 template <typename stream_type>
Chris@16 2804 static inline bool testTrapezoidArbitraryFormationP2(stream_type& stdcout) {
Chris@16 2805 stdcout << "testing trapezoid formation P2\n";
Chris@16 2806 trapezoid_arbitrary_formation pf;
Chris@16 2807 std::vector<polygon_data<Unit> > polys;
Chris@16 2808 std::vector<vertex_half_edge> data;
Chris@16 2809 data.push_back(vertex_half_edge(Point(-3, 1), Point(2, -4), 1));
Chris@16 2810 data.push_back(vertex_half_edge(Point(-3, 1), Point(-2, 2), -1));
Chris@16 2811 data.push_back(vertex_half_edge(Point(-2, 2), Point(2, 4), -1));
Chris@16 2812 data.push_back(vertex_half_edge(Point(-2, 2), Point(-3, 1), 1));
Chris@16 2813 data.push_back(vertex_half_edge(Point(2, -4), Point(-3, 1), -1));
Chris@16 2814 data.push_back(vertex_half_edge(Point(2, -4), Point(2, 4), -1));
Chris@16 2815 data.push_back(vertex_half_edge(Point(2, 4), Point(-2, 2), 1));
Chris@16 2816 data.push_back(vertex_half_edge(Point(2, 4), Point(2, -4), 1));
Chris@16 2817 polygon_sort(data.begin(), data.end());
Chris@16 2818 pf.scan(polys, data.begin(), data.end());
Chris@16 2819 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2820 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2821 stdcout << polys[i] << "\n";
Chris@16 2822 }
Chris@16 2823 stdcout << "done testing trapezoid formation\n";
Chris@16 2824 return true;
Chris@16 2825 }
Chris@16 2826
Chris@16 2827 template <typename stream_type>
Chris@16 2828 static inline bool testTrapezoidArbitraryFormationPolys(stream_type& stdcout) {
Chris@16 2829 stdcout << "testing trapezoid formation polys\n";
Chris@16 2830 trapezoid_arbitrary_formation pf;
Chris@16 2831 std::vector<polygon_with_holes_data<Unit> > polys;
Chris@16 2832 //trapezoid_arbitrary_formation pf2(true);
Chris@16 2833 //std::vector<polygon_with_holes_data<Unit> > polys2;
Chris@16 2834 std::vector<vertex_half_edge> data;
Chris@16 2835 data.push_back(vertex_half_edge(Point(0, 0), Point(100, 1), 1));
Chris@16 2836 data.push_back(vertex_half_edge(Point(0, 0), Point(1, 100), -1));
Chris@16 2837 data.push_back(vertex_half_edge(Point(1, 100), Point(0, 0), 1));
Chris@16 2838 data.push_back(vertex_half_edge(Point(1, 100), Point(101, 101), -1));
Chris@16 2839 data.push_back(vertex_half_edge(Point(100, 1), Point(0, 0), -1));
Chris@16 2840 data.push_back(vertex_half_edge(Point(100, 1), Point(101, 101), 1));
Chris@16 2841 data.push_back(vertex_half_edge(Point(101, 101), Point(100, 1), -1));
Chris@16 2842 data.push_back(vertex_half_edge(Point(101, 101), Point(1, 100), 1));
Chris@16 2843
Chris@16 2844 data.push_back(vertex_half_edge(Point(2, 2), Point(10, 2), -1));
Chris@16 2845 data.push_back(vertex_half_edge(Point(2, 2), Point(2, 10), -1));
Chris@16 2846 data.push_back(vertex_half_edge(Point(2, 10), Point(2, 2), 1));
Chris@16 2847 data.push_back(vertex_half_edge(Point(2, 10), Point(10, 10), 1));
Chris@16 2848 data.push_back(vertex_half_edge(Point(10, 2), Point(2, 2), 1));
Chris@16 2849 data.push_back(vertex_half_edge(Point(10, 2), Point(10, 10), 1));
Chris@16 2850 data.push_back(vertex_half_edge(Point(10, 10), Point(10, 2), -1));
Chris@16 2851 data.push_back(vertex_half_edge(Point(10, 10), Point(2, 10), -1));
Chris@16 2852
Chris@16 2853 data.push_back(vertex_half_edge(Point(2, 12), Point(10, 12), -1));
Chris@16 2854 data.push_back(vertex_half_edge(Point(2, 12), Point(2, 22), -1));
Chris@16 2855 data.push_back(vertex_half_edge(Point(2, 22), Point(2, 12), 1));
Chris@16 2856 data.push_back(vertex_half_edge(Point(2, 22), Point(10, 22), 1));
Chris@16 2857 data.push_back(vertex_half_edge(Point(10, 12), Point(2, 12), 1));
Chris@16 2858 data.push_back(vertex_half_edge(Point(10, 12), Point(10, 22), 1));
Chris@16 2859 data.push_back(vertex_half_edge(Point(10, 22), Point(10, 12), -1));
Chris@16 2860 data.push_back(vertex_half_edge(Point(10, 22), Point(2, 22), -1));
Chris@16 2861
Chris@16 2862 polygon_sort(data.begin(), data.end());
Chris@16 2863 pf.scan(polys, data.begin(), data.end());
Chris@16 2864 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2865 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2866 stdcout << polys[i] << "\n";
Chris@16 2867 }
Chris@16 2868 //pf2.scan(polys2, data.begin(), data.end());
Chris@16 2869 //stdcout << "result size: " << polys2.size() << "\n";
Chris@16 2870 //for(std::size_t i = 0; i < polys2.size(); ++i) {
Chris@16 2871 // stdcout << polys2[i] << "\n";
Chris@16 2872 //}
Chris@16 2873 stdcout << "done testing trapezoid formation\n";
Chris@16 2874 return true;
Chris@16 2875 }
Chris@16 2876
Chris@16 2877 template <typename stream_type>
Chris@16 2878 static inline bool testTrapezoidArbitraryFormationSelfTouch1(stream_type& stdcout) {
Chris@16 2879 stdcout << "testing trapezoid formation self touch 1\n";
Chris@16 2880 trapezoid_arbitrary_formation pf;
Chris@16 2881 std::vector<polygon_data<Unit> > polys;
Chris@16 2882 std::vector<vertex_half_edge> data;
Chris@16 2883 data.push_back(vertex_half_edge(Point(0, 0), Point(10, 0), 1));
Chris@16 2884 data.push_back(vertex_half_edge(Point(0, 0), Point(0, 10), 1));
Chris@16 2885
Chris@16 2886 data.push_back(vertex_half_edge(Point(0, 10), Point(0, 0), -1));
Chris@16 2887 data.push_back(vertex_half_edge(Point(0, 10), Point(5, 10), -1));
Chris@16 2888
Chris@16 2889 data.push_back(vertex_half_edge(Point(10, 0), Point(0, 0), -1));
Chris@16 2890 data.push_back(vertex_half_edge(Point(10, 0), Point(10, 5), -1));
Chris@16 2891
Chris@16 2892 data.push_back(vertex_half_edge(Point(10, 5), Point(10, 0), 1));
Chris@16 2893 data.push_back(vertex_half_edge(Point(10, 5), Point(5, 5), 1));
Chris@16 2894
Chris@16 2895 data.push_back(vertex_half_edge(Point(5, 10), Point(5, 5), 1));
Chris@16 2896 data.push_back(vertex_half_edge(Point(5, 10), Point(0, 10), 1));
Chris@16 2897
Chris@16 2898 data.push_back(vertex_half_edge(Point(5, 2), Point(5, 5), -1));
Chris@16 2899 data.push_back(vertex_half_edge(Point(5, 2), Point(7, 2), -1));
Chris@16 2900
Chris@16 2901 data.push_back(vertex_half_edge(Point(5, 5), Point(5, 10), -1));
Chris@16 2902 data.push_back(vertex_half_edge(Point(5, 5), Point(5, 2), 1));
Chris@16 2903 data.push_back(vertex_half_edge(Point(5, 5), Point(10, 5), -1));
Chris@16 2904 data.push_back(vertex_half_edge(Point(5, 5), Point(7, 2), 1));
Chris@16 2905
Chris@16 2906 data.push_back(vertex_half_edge(Point(7, 2), Point(5, 5), -1));
Chris@16 2907 data.push_back(vertex_half_edge(Point(7, 2), Point(5, 2), 1));
Chris@16 2908
Chris@16 2909 polygon_sort(data.begin(), data.end());
Chris@16 2910 pf.scan(polys, data.begin(), data.end());
Chris@16 2911 stdcout << "result size: " << polys.size() << "\n";
Chris@16 2912 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 2913 stdcout << polys[i] << "\n";
Chris@16 2914 }
Chris@16 2915 stdcout << "done testing trapezoid formation\n";
Chris@16 2916 return true;
Chris@16 2917 }
Chris@16 2918 };
Chris@16 2919
Chris@16 2920 template <typename T>
Chris@16 2921 struct PolyLineArbitraryByConcept<T, polygon_with_holes_concept> { typedef poly_line_arbitrary_polygon_data<T> type; };
Chris@16 2922 template <typename T>
Chris@16 2923 struct PolyLineArbitraryByConcept<T, polygon_concept> { typedef poly_line_arbitrary_hole_data<T> type; };
Chris@16 2924
Chris@16 2925 template <typename T>
Chris@16 2926 struct geometry_concept<poly_line_arbitrary_polygon_data<T> > { typedef polygon_45_with_holes_concept type; };
Chris@16 2927 template <typename T>
Chris@16 2928 struct geometry_concept<poly_line_arbitrary_hole_data<T> > { typedef polygon_45_concept type; };
Chris@16 2929 }
Chris@16 2930 }
Chris@16 2931 #endif