boolean_op_45.hpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396
  1. /*
  2. Copyright 2008 Intel Corporation
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. #ifndef BOOST_POLYGON_BOOLEAN_OP_45_HPP
  8. #define BOOST_POLYGON_BOOLEAN_OP_45_HPP
  9. namespace boost { namespace polygon{
  10. template <typename Unit>
  11. struct boolean_op_45 {
  12. typedef point_data<Unit> Point;
  13. typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit;
  14. class Count2 {
  15. public:
  16. inline Count2()
  17. #ifndef BOOST_POLYGON_MSVC
  18. : counts()
  19. #endif
  20. { counts[0] = counts[1] = 0; }
  21. //inline Count2(int count) { counts[0] = counts[1] = count; }
  22. inline Count2(int count1, int count2)
  23. #ifndef BOOST_POLYGON_MSVC
  24. : counts()
  25. #endif
  26. { counts[0] = count1; counts[1] = count2; }
  27. inline Count2(const Count2& count)
  28. #ifndef BOOST_POLYGON_MSVC
  29. : counts()
  30. #endif
  31. { counts[0] = count.counts[0]; counts[1] = count.counts[1]; }
  32. inline bool operator==(const Count2& count) const { return counts[0] == count.counts[0] && counts[1] == count.counts[1]; }
  33. inline bool operator!=(const Count2& count) const { return !((*this) == count); }
  34. inline Count2& operator=(int count) { counts[0] = counts[1] = count; return *this; }
  35. inline Count2& operator=(const Count2& count) { counts[0] = count.counts[0]; counts[1] = count.counts[1]; return *this; }
  36. inline int& operator[](bool index) { return counts[index]; }
  37. inline int operator[](bool index) const {return counts[index]; }
  38. inline Count2& operator+=(const Count2& count){
  39. counts[0] += count[0];
  40. counts[1] += count[1];
  41. return *this;
  42. }
  43. inline Count2& operator-=(const Count2& count){
  44. counts[0] -= count[0];
  45. counts[1] -= count[1];
  46. return *this;
  47. }
  48. inline Count2 operator+(const Count2& count) const {
  49. return Count2(*this)+=count;
  50. }
  51. inline Count2 operator-(const Count2& count) const {
  52. return Count2(*this)-=count;
  53. }
  54. inline Count2 invert() const {
  55. return Count2(-counts[0], -counts[1]);
  56. }
  57. private:
  58. int counts[2];
  59. };
  60. class Count1 {
  61. public:
  62. inline Count1() : count_(0) { }
  63. inline Count1(int count) : count_(count) { }
  64. inline Count1(const Count1& count) : count_(count.count_) { }
  65. inline bool operator==(const Count1& count) const { return count_ == count.count_; }
  66. inline bool operator!=(const Count1& count) const { return !((*this) == count); }
  67. inline Count1& operator=(int count) { count_ = count; return *this; }
  68. inline Count1& operator=(const Count1& count) { count_ = count.count_; return *this; }
  69. inline Count1& operator+=(const Count1& count){
  70. count_ += count.count_;
  71. return *this;
  72. }
  73. inline Count1& operator-=(const Count1& count){
  74. count_ -= count.count_;
  75. return *this;
  76. }
  77. inline Count1 operator+(const Count1& count) const {
  78. return Count1(*this)+=count;
  79. }
  80. inline Count1 operator-(const Count1& count) const {
  81. return Count1(*this)-=count;
  82. }
  83. inline Count1 invert() const {
  84. return Count1(-count_);
  85. }
  86. int count_;
  87. };
  88. // inline std::ostream& operator<< (std::ostream& o, const Count2& c) {
  89. // o << c[0] << " " << c[1];
  90. // return o;
  91. // }
  92. template <typename CountType>
  93. class Scan45ElementT {
  94. public:
  95. Unit x;
  96. Unit y;
  97. int rise; //-1, 0, +1
  98. mutable CountType count;
  99. inline Scan45ElementT() : x(), y(), rise(), count() {}
  100. inline Scan45ElementT(Unit xIn, Unit yIn, int riseIn, CountType countIn = CountType()) :
  101. x(xIn), y(yIn), rise(riseIn), count(countIn) {}
  102. inline Scan45ElementT(const Scan45ElementT& that) :
  103. x(that.x), y(that.y), rise(that.rise), count(that.count) {}
  104. inline Scan45ElementT& operator=(const Scan45ElementT& that) {
  105. x = that.x; y = that.y; rise = that.rise; count = that.count;
  106. return *this;
  107. }
  108. inline Unit evalAtX(Unit xIn) const {
  109. return y + rise * (xIn - x);
  110. }
  111. inline bool cross(Point& crossPoint, const Scan45ElementT& edge, Unit currentX) const {
  112. Unit y1 = evalAtX(currentX);
  113. Unit y2 = edge.evalAtX(currentX);
  114. int rise1 = rise;
  115. int rise2 = edge.rise;
  116. if(rise > edge.rise){
  117. if(y1 > y2) return false;
  118. } else if(rise < edge.rise){
  119. if(y2 > y1) return false;
  120. std::swap(y1, y2);
  121. std::swap(rise1, rise2);
  122. } else { return false; }
  123. if(rise1 == 1) {
  124. if(rise2 == 0) {
  125. crossPoint = Point(currentX + y2 - y1, y2);
  126. } else {
  127. //rise2 == -1
  128. Unit delta = (y2 - y1)/2;
  129. crossPoint = Point(currentX + delta, y1 + delta);
  130. }
  131. } else {
  132. //rise1 == 0 and rise2 == -1
  133. crossPoint = Point(currentX + y2 - y1, y1);
  134. }
  135. return true;
  136. }
  137. };
  138. typedef Scan45ElementT<Count2> Scan45Element;
  139. // inline std::ostream& operator<< (std::ostream& o, const Scan45Element& c) {
  140. // o << c.x << " " << c.y << " " << c.rise << " " << c.count;
  141. // return o;
  142. // }
  143. class lessScan45ElementRise : public std::binary_function<Scan45Element, Scan45Element, bool> {
  144. public:
  145. inline lessScan45ElementRise() {} //default constructor is only constructor
  146. inline bool operator () (Scan45Element elm1, Scan45Element elm2) const {
  147. return elm1.rise < elm2.rise;
  148. }
  149. };
  150. template <typename CountType>
  151. class lessScan45Element {
  152. private:
  153. Unit *x_; //x value at which to apply comparison
  154. int *justBefore_;
  155. public:
  156. inline lessScan45Element() : x_(0), justBefore_(0) {}
  157. inline lessScan45Element(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {}
  158. inline lessScan45Element(const lessScan45Element& that) : x_(that.x_), justBefore_(that.justBefore_) {}
  159. inline lessScan45Element& operator=(const lessScan45Element& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; }
  160. inline bool operator () (const Scan45ElementT<CountType>& elm1,
  161. const Scan45ElementT<CountType>& elm2) const {
  162. Unit y1 = elm1.evalAtX(*x_);
  163. Unit y2 = elm2.evalAtX(*x_);
  164. if(y1 < y2) return true;
  165. if(y1 == y2) {
  166. //if justBefore is true we invert the result of the comparison of slopes
  167. if(*justBefore_) {
  168. return elm1.rise > elm2.rise;
  169. } else {
  170. return elm1.rise < elm2.rise;
  171. }
  172. }
  173. return false;
  174. }
  175. };
  176. template <typename CountType>
  177. class Scan45CountT {
  178. public:
  179. inline Scan45CountT() : counts() {} //counts[0] = counts[1] = counts[2] = counts[3] = 0; }
  180. inline Scan45CountT(CountType count) : counts() { counts[0] = counts[1] = counts[2] = counts[3] = count; }
  181. inline Scan45CountT(const CountType& count1, const CountType& count2, const CountType& count3,
  182. const CountType& count4) : counts() {
  183. counts[0] = count1;
  184. counts[1] = count2;
  185. counts[2] = count3;
  186. counts[3] = count4;
  187. }
  188. inline Scan45CountT(const Scan45CountT& count) : counts() {
  189. (*this) = count;
  190. }
  191. inline bool operator==(const Scan45CountT& count) const {
  192. for(unsigned int i = 0; i < 4; ++i) {
  193. if(counts[i] != count.counts[i]) return false;
  194. }
  195. return true;
  196. }
  197. inline bool operator!=(const Scan45CountT& count) const { return !((*this) == count); }
  198. inline Scan45CountT& operator=(CountType count) {
  199. counts[0] = counts[1] = counts[2] = counts[3] = count; return *this; }
  200. inline Scan45CountT& operator=(const Scan45CountT& count) {
  201. for(unsigned int i = 0; i < 4; ++i) {
  202. counts[i] = count.counts[i];
  203. }
  204. return *this;
  205. }
  206. inline CountType& operator[](int index) { return counts[index]; }
  207. inline CountType operator[](int index) const {return counts[index]; }
  208. inline Scan45CountT& operator+=(const Scan45CountT& count){
  209. for(unsigned int i = 0; i < 4; ++i) {
  210. counts[i] += count.counts[i];
  211. }
  212. return *this;
  213. }
  214. inline Scan45CountT& operator-=(const Scan45CountT& count){
  215. for(unsigned int i = 0; i < 4; ++i) {
  216. counts[i] -= count.counts[i];
  217. }
  218. return *this;
  219. }
  220. inline Scan45CountT operator+(const Scan45CountT& count) const {
  221. return Scan45CountT(*this)+=count;
  222. }
  223. inline Scan45CountT operator-(const Scan45CountT& count) const {
  224. return Scan45CountT(*this)-=count;
  225. }
  226. inline Scan45CountT invert() const {
  227. return Scan45CountT(CountType())-=(*this);
  228. }
  229. inline Scan45CountT& operator+=(const Scan45ElementT<CountType>& element){
  230. counts[element.rise+1] += element.count; return *this;
  231. }
  232. private:
  233. CountType counts[4];
  234. };
  235. typedef Scan45CountT<Count2> Scan45Count;
  236. // inline std::ostream& operator<< (std::ostream& o, const Scan45Count& c) {
  237. // o << c[0] << ", " << c[1] << ", ";
  238. // o << c[2] << ", " << c[3];
  239. // return o;
  240. // }
  241. // inline std::ostream& operator<< (std::ostream& o, const Scan45Vertex& c) {
  242. // o << c.first << ": " << c.second;
  243. // return o;
  244. // }
  245. //vetex45 is sortable
  246. template <typename ct>
  247. class Vertex45T {
  248. public:
  249. Point pt;
  250. int rise; // 1, 0 or -1
  251. ct count; //dxdydTheta
  252. inline Vertex45T() : pt(), rise(), count() {}
  253. inline Vertex45T(const Point& point, int riseIn, ct countIn) : pt(point), rise(riseIn), count(countIn) {}
  254. inline Vertex45T(const Vertex45T& vertex) : pt(vertex.pt), rise(vertex.rise), count(vertex.count) {}
  255. inline Vertex45T& operator=(const Vertex45T& vertex){
  256. pt = vertex.pt; rise = vertex.rise; count = vertex.count; return *this; }
  257. inline Vertex45T(const std::pair<Point, Point>& vertex) : pt(), rise(), count() {}
  258. inline Vertex45T& operator=(const std::pair<Point, Point>& vertex){ return *this; }
  259. inline bool operator==(const Vertex45T& vertex) const {
  260. return pt == vertex.pt && rise == vertex.rise && count == vertex.count; }
  261. inline bool operator!=(const Vertex45T& vertex) const { return !((*this) == vertex); }
  262. inline bool operator==(const std::pair<Point, Point>& vertex) const { return false; }
  263. inline bool operator!=(const std::pair<Point, Point>& vertex) const { return !((*this) == vertex); }
  264. inline bool operator<(const Vertex45T& vertex) const {
  265. if(pt.x() < vertex.pt.x()) return true;
  266. if(pt.x() == vertex.pt.x()) {
  267. if(pt.y() < vertex.pt.y()) return true;
  268. if(pt.y() == vertex.pt.y()) { return rise < vertex.rise; }
  269. }
  270. return false;
  271. }
  272. inline bool operator>(const Vertex45T& vertex) const { return vertex < (*this); }
  273. inline bool operator<=(const Vertex45T& vertex) const { return !((*this) > vertex); }
  274. inline bool operator>=(const Vertex45T& vertex) const { return !((*this) < vertex); }
  275. inline Unit evalAtX(Unit xIn) const { return pt.y() + rise * (xIn - pt.x()); }
  276. };
  277. typedef Vertex45T<int> Vertex45;
  278. // inline std::ostream& operator<< (std::ostream& o, const Vertex45& c) {
  279. // o << c.pt << " " << c.rise << " " << c.count;
  280. // return o;
  281. // }
  282. //when scanning Vertex45 for polygon formation we need a scanline comparator functor
  283. class lessVertex45 {
  284. private:
  285. Unit *x_; //x value at which to apply comparison
  286. int *justBefore_;
  287. public:
  288. inline lessVertex45() : x_(0), justBefore_() {}
  289. inline lessVertex45(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {}
  290. inline lessVertex45(const lessVertex45& that) : x_(that.x_), justBefore_(that.justBefore_) {}
  291. inline lessVertex45& operator=(const lessVertex45& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; }
  292. template <typename ct>
  293. inline bool operator () (const Vertex45T<ct>& elm1, const Vertex45T<ct>& elm2) const {
  294. Unit y1 = elm1.evalAtX(*x_);
  295. Unit y2 = elm2.evalAtX(*x_);
  296. if(y1 < y2) return true;
  297. if(y1 == y2) {
  298. //if justBefore is true we invert the result of the comparison of slopes
  299. if(*justBefore_) {
  300. return elm1.rise > elm2.rise;
  301. } else {
  302. return elm1.rise < elm2.rise;
  303. }
  304. }
  305. return false;
  306. }
  307. };
  308. // 0 right to left
  309. // 1 upper right to lower left
  310. // 2 high to low
  311. // 3 upper left to lower right
  312. // 4 left to right
  313. // 5 lower left to upper right
  314. // 6 low to high
  315. // 7 lower right to upper left
  316. static inline int classifyEdge45(const Point& prevPt, const Point& nextPt) {
  317. if(prevPt.x() == nextPt.x()) {
  318. //2 or 6
  319. return predicated_value(prevPt.y() < nextPt.y(), 6, 2);
  320. }
  321. if(prevPt.y() == nextPt.y()) {
  322. //0 or 4
  323. return predicated_value(prevPt.x() < nextPt.x(), 4, 0);
  324. }
  325. if(prevPt.x() < nextPt.x()) {
  326. //3 or 5
  327. return predicated_value(prevPt.y() < nextPt.y(), 5, 3);
  328. }
  329. //prevPt.x() > nextPt.y()
  330. //1 or 7
  331. return predicated_value(prevPt.y() < nextPt.y(), 7, 1);
  332. }
  333. template <int op, typename CountType>
  334. static int applyLogic(CountType count1, CountType count2){
  335. bool l1 = applyLogic<op>(count1);
  336. bool l2 = applyLogic<op>(count2);
  337. if(l1 && !l2)
  338. return -1; //was true before and became false like a trailing edge
  339. if(!l1 && l2)
  340. return 1; //was false before and became true like a leading edge
  341. return 0; //no change in logic between the two counts
  342. }
  343. template <int op>
  344. static bool applyLogic(Count2 count) {
  345. #ifdef BOOST_POLYGON_MSVC
  346. #pragma warning (push)
  347. #pragma warning (disable: 4127)
  348. #endif
  349. if(op == 0) { //apply or
  350. return count[0] > 0 || count[1] > 0;
  351. } else if(op == 1) { //apply and
  352. return count[0] > 0 && count[1] > 0;
  353. } else if(op == 2) { //apply not
  354. return count[0] > 0 && !(count[1] > 0);
  355. } else if(op == 3) { //apply xor
  356. return (count[0] > 0) ^ (count[1] > 0);
  357. } else
  358. return false;
  359. #ifdef BOOST_POLYGON_MSVC
  360. #pragma warning (pop)
  361. #endif
  362. }
  363. template <int op>
  364. struct boolean_op_45_output_functor {
  365. template <typename cT>
  366. void operator()(cT& output, const Count2& count1, const Count2& count2,
  367. const Point& pt, int rise, direction_1d end) {
  368. int edgeType = applyLogic<op>(count1, count2);
  369. if(edgeType) {
  370. int multiplier = end == LOW ? -1 : 1;
  371. //std::cout << "cross logic: " << edgeType << "\n";
  372. output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier));
  373. //std::cout << "write out: " << crossPoint << " " << Point(eraseItrs[i]->x, eraseItrs[i]->y) << "\n";
  374. }
  375. }
  376. };
  377. template <int op>
  378. static bool applyLogic(Count1 count) {
  379. #ifdef BOOST_POLYGON_MSVC
  380. #pragma warning (push)
  381. #pragma warning (disable: 4127)
  382. #endif
  383. if(op == 0) { //apply or
  384. return count.count_ > 0;
  385. } else if(op == 1) { //apply and
  386. return count.count_ > 1;
  387. } else if(op == 3) { //apply xor
  388. return (count.count_ % 2) != 0;
  389. } else
  390. return false;
  391. #ifdef BOOST_POLYGON_MSVC
  392. #pragma warning (pop)
  393. #endif
  394. }
  395. template <int op>
  396. struct unary_op_45_output_functor {
  397. template <typename cT>
  398. void operator()(cT& output, const Count1& count1, const Count1& count2,
  399. const Point& pt, int rise, direction_1d end) {
  400. int edgeType = applyLogic<op>(count1, count2);
  401. if(edgeType) {
  402. int multiplier = end == LOW ? -1 : 1;
  403. //std::cout << "cross logic: " << edgeType << "\n";
  404. output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier));
  405. //std::cout << "write out: " << crossPoint << " " << Point(eraseItrs[i]->x, eraseItrs[i]->y) << "\n";
  406. }
  407. }
  408. };
  409. class lessScan45Vertex {
  410. public:
  411. inline lessScan45Vertex() {} //default constructor is only constructor
  412. template <typename Scan45Vertex>
  413. inline bool operator () (const Scan45Vertex& v1, const Scan45Vertex& v2) const {
  414. return (v1.first.x() < v2.first.x()) || (v1.first.x() == v2.first.x() && v1.first.y() < v2.first.y());
  415. }
  416. };
  417. template <typename S45V>
  418. static inline void sortScan45Vector(S45V& vec) {
  419. polygon_sort(vec.begin(), vec.end(), lessScan45Vertex());
  420. }
  421. template <typename CountType, typename output_functor>
  422. class Scan45 {
  423. public:
  424. typedef Scan45CountT<CountType> Scan45Count;
  425. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  426. //index is the index into the vertex
  427. static inline Scan45Element getElement(const Scan45Vertex& vertex, int index) {
  428. return Scan45Element(vertex.first.x(), vertex.first.y(), index - 1, vertex.second[index]);
  429. }
  430. class lessScan45Point : public std::binary_function<Point, Point, bool> {
  431. public:
  432. inline lessScan45Point() {} //default constructor is only constructor
  433. inline bool operator () (const Point& v1, const Point& v2) const {
  434. return (v1.x() < v2.x()) || (v1.x() == v2.x() && v1.y() < v2.y());
  435. }
  436. };
  437. typedef std::vector<Scan45Vertex> Scan45Vector;
  438. //definitions
  439. typedef std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> > Scan45Data;
  440. typedef typename Scan45Data::iterator iterator;
  441. typedef typename Scan45Data::const_iterator const_iterator;
  442. typedef std::set<Point, lessScan45Point> CrossQueue;
  443. //data
  444. Scan45Data scanData_;
  445. CrossQueue crossQueue_;
  446. Scan45Vector crossVector_;
  447. Unit x_;
  448. int justBefore_;
  449. public:
  450. inline Scan45() : scanData_(), crossQueue_(), crossVector_(),
  451. x_((std::numeric_limits<Unit>::min)()), justBefore_(false) {
  452. lessScan45Element<CountType> lessElm(&x_, &justBefore_);
  453. scanData_ = std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >(lessElm);
  454. }
  455. inline Scan45(const Scan45& that) : scanData_(), crossQueue_(), crossVector_(),
  456. x_((std::numeric_limits<Unit>::min)()), justBefore_(false) {
  457. (*this) = that; }
  458. inline Scan45& operator=(const Scan45& that) {
  459. x_ = that.x_;
  460. justBefore_ = that.justBefore_;
  461. crossQueue_ = that.crossQueue_;
  462. crossVector_ = that.crossVector_;
  463. lessScan45Element<CountType> lessElm(&x_, &justBefore_);
  464. scanData_ = std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >(lessElm);
  465. for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){
  466. scanData_.insert(scanData_.end(), *itr);
  467. }
  468. return *this;
  469. }
  470. //cT is an output container of Vertex45
  471. //iT is an iterator over Scan45Vertex elements
  472. template <class cT, class iT>
  473. void scan(cT& output, iT inputBegin, iT inputEnd) {
  474. //std::cout << "1\n";
  475. while(inputBegin != inputEnd) {
  476. //std::cout << "2\n";
  477. //std::cout << "x_ = " << x_ << "\n";
  478. //std::cout << "scan line size: " << scanData_.size() << "\n";
  479. //for(iterator iter = scanData_.begin();
  480. // iter != scanData_.end(); ++iter) {
  481. // std::cout << "scan element\n";
  482. // std::cout << *iter << " " << iter->evalAtX(x_) << "\n";
  483. // }
  484. // std::cout << "cross queue size: " << crossQueue_.size() << "\n";
  485. // std::cout << "cross vector size: " << crossVector_.size() << "\n";
  486. //for(CrossQueue::iterator cqitr = crossQueue_.begin(); cqitr != crossQueue_.end(); ++cqitr) {
  487. // std::cout << *cqitr << " ";
  488. //} std::cout << "\n";
  489. Unit nextX = (*inputBegin).first.x();
  490. if(!crossVector_.empty() && crossVector_[0].first.x() < nextX) nextX = crossVector_[0].first.x();
  491. if(nextX != x_) {
  492. //std::cout << "3\n";
  493. //we need to move to the next scanline stop
  494. //we need to process end events then cross events
  495. //process end events
  496. if(!crossQueue_.empty() &&
  497. (*crossQueue_.begin()).x() < nextX) {
  498. //std::cout << "4\n";
  499. nextX = (std::min)(nextX, (*crossQueue_.begin()).x());
  500. }
  501. //std::cout << "6\n";
  502. justBefore_ = true;
  503. x_ = nextX;
  504. advance_(output);
  505. justBefore_ = false;
  506. if(!crossVector_.empty() &&
  507. nextX == (*inputBegin).first.x()) {
  508. inputBegin = mergeCross_(inputBegin, inputEnd);
  509. }
  510. processEvent_(output, crossVector_.begin(), crossVector_.end());
  511. crossVector_.clear();
  512. } else {
  513. //std::cout << "7\n";
  514. //our scanline has progressed to the event that is next in the queue
  515. inputBegin = processEvent_(output, inputBegin, inputEnd);
  516. }
  517. }
  518. //std::cout << "done scanning\n";
  519. }
  520. private:
  521. //functions
  522. template <class cT>
  523. inline void advance_(cT& output) {
  524. //process all cross points on the cross queue at the current x_
  525. //std::cout << "advance_\n";
  526. std::vector<iterator> eraseVec;
  527. while(!crossQueue_.empty() &&
  528. (*crossQueue_.begin()).x() == x_){
  529. //std::cout << "loop\n";
  530. //pop point off the cross queue
  531. Point crossPoint = *(crossQueue_.begin());
  532. //std::cout << crossPoint << "\n";
  533. //for(iterator iter = scanData_.begin();
  534. // iter != scanData_.end(); ++iter) {
  535. // std::cout << "scan element\n";
  536. // std::cout << *iter << " " << iter->evalAtX(x_) << "\n";
  537. //}
  538. crossQueue_.erase(crossQueue_.begin());
  539. Scan45Vertex vertex(crossPoint, Scan45Count());
  540. iterator lowIter = lookUp_(vertex.first.y());
  541. //std::cout << "searching at: " << vertex.first.y() << "\n";
  542. //if(lowIter == scanData_.end()) std::cout << "could not find\n";
  543. //else std::cout << "found: " << *lowIter << "\n";
  544. if(lowIter == scanData_.end() ||
  545. lowIter->evalAtX(x_) != vertex.first.y()) {
  546. // std::cout << "skipping\n";
  547. //there weren't any edges at this potential cross point
  548. continue;
  549. }
  550. CountType countBelow;
  551. iterator searchDownItr = lowIter;
  552. while(searchDownItr != scanData_.begin()
  553. && searchDownItr->evalAtX(x_) == vertex.first.y()) {
  554. //get count from below
  555. --searchDownItr;
  556. countBelow = searchDownItr->count;
  557. }
  558. //std::cout << "Below Count: " << countBelow << "\n";
  559. Scan45Count count(countBelow);
  560. std::size_t numEdges = 0;
  561. iterator eraseItrs[3];
  562. while(lowIter != scanData_.end() &&
  563. lowIter->evalAtX(x_) == vertex.first.y()) {
  564. for(int index = lowIter->rise +1; index >= 0; --index)
  565. count[index] = lowIter->count;
  566. //std::cout << count << "\n";
  567. eraseItrs[numEdges] = lowIter;
  568. ++numEdges;
  569. ++lowIter;
  570. }
  571. if(numEdges == 1) {
  572. //look for the next crossing point and continue
  573. //std::cout << "found only one edge\n";
  574. findCross_(eraseItrs[0]);
  575. continue;
  576. }
  577. //before we erase the elements we need to decide if they should be written out
  578. CountType currentCount = countBelow;
  579. for(std::size_t i = 0; i < numEdges; ++i) {
  580. output_functor f;
  581. f(output, currentCount, eraseItrs[i]->count, crossPoint, eraseItrs[i]->rise, LOW);
  582. currentCount = eraseItrs[i]->count;
  583. }
  584. //schedule erase of the elements
  585. for(std::size_t i = 0; i < numEdges; ++i) {
  586. eraseVec.push_back(eraseItrs[i]);
  587. }
  588. //take the derivative wrt theta of the count at the crossing point
  589. vertex.second[2] = count[2] - countBelow;
  590. vertex.second[1] = count[1] - count[2];
  591. vertex.second[0] = count[0] - count[1];
  592. //add the point, deriviative pair into the cross vector
  593. //std::cout << "LOOK HERE!\n";
  594. //std::cout << count << "\n";
  595. //std::cout << vertex << "\n";
  596. crossVector_.push_back(vertex);
  597. }
  598. //erase crossing elements
  599. std::vector<iterator> searchVec;
  600. for(std::size_t i = 0; i < eraseVec.size(); ++i) {
  601. if(eraseVec[i] != scanData_.begin()) {
  602. iterator searchItr = eraseVec[i];
  603. --searchItr;
  604. if(searchVec.empty() ||
  605. searchVec.back() != searchItr)
  606. searchVec.push_back(searchItr);
  607. }
  608. scanData_.erase(eraseVec[i]);
  609. }
  610. for(std::size_t i = 0; i < searchVec.size(); ++i) {
  611. findCross_(searchVec[i]);
  612. }
  613. }
  614. template <class iT>
  615. inline iT mergeCross_(iT inputBegin, iT inputEnd) {
  616. Scan45Vector vec;
  617. swap(vec, crossVector_);
  618. iT mergeEnd = inputBegin;
  619. std::size_t mergeCount = 0;
  620. while(mergeEnd != inputEnd &&
  621. (*mergeEnd).first.x() == x_) {
  622. ++mergeCount;
  623. ++mergeEnd;
  624. }
  625. crossVector_.reserve((std::max)(vec.capacity(), vec.size() + mergeCount));
  626. for(std::size_t i = 0; i < vec.size(); ++i){
  627. while(inputBegin != mergeEnd &&
  628. (*inputBegin).first.y() < vec[i].first.y()) {
  629. crossVector_.push_back(*inputBegin);
  630. ++inputBegin;
  631. }
  632. crossVector_.push_back(vec[i]);
  633. }
  634. while(inputBegin != mergeEnd){
  635. crossVector_.push_back(*inputBegin);
  636. ++inputBegin;
  637. }
  638. return inputBegin;
  639. }
  640. template <class cT, class iT>
  641. inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) {
  642. //std::cout << "processEvent_\n";
  643. CountType verticalCount = CountType();
  644. Point prevPoint;
  645. iterator prevIter = scanData_.end();
  646. while(inputBegin != inputEnd &&
  647. (*inputBegin).first.x() == x_) {
  648. //std::cout << (*inputBegin) << "\n";
  649. //std::cout << "loop\n";
  650. Scan45Vertex vertex = *inputBegin;
  651. //std::cout << vertex.first << "\n";
  652. //if vertical count propigating up fake a null event at the next element
  653. if(verticalCount != CountType() && (prevIter != scanData_.end() &&
  654. prevIter->evalAtX(x_) < vertex.first.y())) {
  655. //std::cout << "faking null event\n";
  656. vertex = Scan45Vertex(Point(x_, prevIter->evalAtX(x_)), Scan45Count());
  657. } else {
  658. ++inputBegin;
  659. //std::cout << "after increment\n";
  660. //accumulate overlapping changes in Scan45Count
  661. while(inputBegin != inputEnd &&
  662. (*inputBegin).first.x() == x_ &&
  663. (*inputBegin).first.y() == vertex.first.y()) {
  664. //std::cout << "accumulate\n";
  665. vertex.second += (*inputBegin).second;
  666. ++inputBegin;
  667. }
  668. }
  669. //std::cout << vertex.second << "\n";
  670. //integrate vertex
  671. CountType currentCount = verticalCount;// + vertex.second[0];
  672. for(unsigned int i = 0; i < 3; ++i) {
  673. vertex.second[i] = currentCount += vertex.second[i];
  674. }
  675. //std::cout << vertex.second << "\n";
  676. //vertex represents the change in state at this point
  677. //get counts at current vertex
  678. CountType countBelow;
  679. iterator lowIter = lookUp_(vertex.first.y());
  680. if(lowIter != scanData_.begin()) {
  681. //get count from below
  682. --lowIter;
  683. countBelow = lowIter->count;
  684. ++lowIter;
  685. }
  686. //std::cout << "Count Below: " << countBelow[0] << " " << countBelow[1] << "\n";
  687. //std::cout << "vertical count: " << verticalCount[0] << " " << verticalCount[1] << "\n";
  688. Scan45Count countAt(countBelow - verticalCount);
  689. //check if the vertical edge should be written out
  690. if(verticalCount != CountType()) {
  691. output_functor f;
  692. f(output, countBelow - verticalCount, countBelow, prevPoint, 2, HIGH);
  693. f(output, countBelow - verticalCount, countBelow, vertex.first, 2, LOW);
  694. }
  695. currentCount = countBelow - verticalCount;
  696. while(lowIter != scanData_.end() &&
  697. lowIter->evalAtX(x_) == vertex.first.y()) {
  698. for(unsigned int i = lowIter->rise + 1; i < 3; ++i) {
  699. countAt[i] = lowIter->count;
  700. }
  701. Point lp(lowIter->x, lowIter->y);
  702. if(lp != vertex.first) {
  703. output_functor f;
  704. f(output, currentCount, lowIter->count, vertex.first, lowIter->rise, LOW);
  705. }
  706. currentCount = lowIter->count;
  707. iterator nextIter = lowIter;
  708. ++nextIter;
  709. //std::cout << "erase\n";
  710. scanData_.erase(lowIter);
  711. if(nextIter != scanData_.end())
  712. findCross_(nextIter);
  713. lowIter = nextIter;
  714. }
  715. verticalCount += vertex.second[3];
  716. prevPoint = vertex.first;
  717. //std::cout << "new vertical count: " << verticalCount[0] << " " << verticalCount[1] << "\n";
  718. prevIter = lowIter;
  719. //count represents the current state at this point
  720. //std::cout << vertex.second << "\n";
  721. //std::cout << countAt << "\n";
  722. //std::cout << "ADD\n";
  723. vertex.second += countAt;
  724. //std::cout << vertex.second << "\n";
  725. //add elements to the scanline
  726. for(int i = 0; i < 3; ++i) {
  727. if(vertex.second[i] != countBelow) {
  728. //std::cout << "insert: " << vertex.first.x() << " " << vertex.first.y() << " " << i-1 <<
  729. // " " << vertex.second[i][0] << " " << vertex.second[i][1] << "\n";
  730. iterator insertIter = scanData_.insert(scanData_.end(),
  731. Scan45ElementT<CountType>(vertex.first.x(),
  732. vertex.first.y(),
  733. i - 1, vertex.second[i]));
  734. findCross_(insertIter);
  735. output_functor f;
  736. f(output, countBelow, vertex.second[i], vertex.first, i - 1, HIGH);
  737. }
  738. countBelow = vertex.second[i];
  739. }
  740. }
  741. //std::cout << "end processEvent\n";
  742. return inputBegin;
  743. }
  744. //iter1 is horizontal
  745. inline void scheduleCross0_(iterator iter1, iterator iter2) {
  746. //std::cout << "0, ";
  747. Unit y1 = iter1->evalAtX(x_);
  748. Unit y2 = iter2->evalAtX(x_);
  749. LongUnit delta = local_abs(LongUnit(y1) - LongUnit(y2));
  750. if(delta + static_cast<LongUnit>(x_) <= (std::numeric_limits<Unit>::max)())
  751. crossQueue_.insert(crossQueue_.end(), Point(x_ + static_cast<Unit>(delta), y1));
  752. //std::cout << Point(x_ + delta, y1);
  753. }
  754. //neither iter is horizontal
  755. inline void scheduleCross1_(iterator iter1, iterator iter2) {
  756. //std::cout << "1, ";
  757. Unit y1 = iter1->evalAtX(x_);
  758. Unit y2 = iter2->evalAtX(x_);
  759. //std::cout << y1 << " " << y2 << ": ";
  760. //note that half the delta cannot exceed the positive inter range
  761. LongUnit delta = y1;
  762. delta -= y2;
  763. Unit UnitMax = (std::numeric_limits<Unit>::max)();
  764. if((delta & 1) == 1) {
  765. //delta is odd, division by 2 will result in integer trunctaion
  766. if(delta == 1) {
  767. //the cross point is not on the integer grid and cannot be represented
  768. //we must throw an exception
  769. std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value.";
  770. throw(msg);
  771. } else {
  772. //note that result of this subtraction is always positive because itr1 is above itr2 in scanline
  773. LongUnit halfDelta2 = (LongUnit)((((LongUnit)y1) - y2)/2);
  774. //note that halfDelta2 has been truncated
  775. if(halfDelta2 + x_ <= UnitMax && halfDelta2 + y2 <= UnitMax) {
  776. crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta2), y2+static_cast<Unit>(halfDelta2)));
  777. crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta2), y2+static_cast<Unit>(halfDelta2)+1));
  778. }
  779. }
  780. } else {
  781. LongUnit halfDelta = (LongUnit)((((LongUnit)y1) - y2)/2);
  782. if(halfDelta + x_ <= UnitMax && halfDelta + y2 <= UnitMax)
  783. crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta), y2+static_cast<Unit>(halfDelta)));
  784. //std::cout << Point(x_+halfDelta, y2+halfDelta);
  785. }
  786. }
  787. inline void findCross_(iterator iter) {
  788. //std::cout << "find cross ";
  789. iterator iteratorBelow = iter;
  790. iterator iteratorAbove = iter;
  791. if(iter != scanData_.begin() && iter->rise < 1) {
  792. --iteratorBelow;
  793. if(iter->rise == 0){
  794. if(iteratorBelow->rise == 1) {
  795. scheduleCross0_(iter, iteratorBelow);
  796. }
  797. } else {
  798. //iter->rise == -1
  799. if(iteratorBelow->rise == 1) {
  800. scheduleCross1_(iter, iteratorBelow);
  801. } else if(iteratorBelow->rise == 0) {
  802. scheduleCross0_(iteratorBelow, iter);
  803. }
  804. }
  805. }
  806. ++iteratorAbove;
  807. if(iteratorAbove != scanData_.end() && iter->rise > -1) {
  808. if(iter->rise == 0) {
  809. if(iteratorAbove->rise == -1) {
  810. scheduleCross0_(iter, iteratorAbove);
  811. }
  812. } else {
  813. //iter->rise == 1
  814. if(iteratorAbove->rise == -1) {
  815. scheduleCross1_(iteratorAbove, iter);
  816. } else if(iteratorAbove->rise == 0) {
  817. scheduleCross0_(iteratorAbove, iter);
  818. }
  819. }
  820. }
  821. //std::cout << "\n";
  822. }
  823. inline iterator lookUp_(Unit y){
  824. //if just before then we need to look from 1 not -1
  825. return scanData_.lower_bound(Scan45ElementT<CountType>(x_, y, -1+2*justBefore_));
  826. }
  827. };
  828. //template <typename CountType>
  829. //static inline void print45Data(const std::set<Scan45ElementT<CountType>,
  830. // lessScan45Element<CountType> >& data) {
  831. // typename std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >::const_iterator iter;
  832. // for(iter = data.begin(); iter != data.end(); ++iter) {
  833. // std::cout << iter->x << " " << iter->y << " " << iter->rise << "\n";
  834. // }
  835. //}
  836. template <typename streamtype>
  837. static inline bool testScan45Data(streamtype& stdcout) {
  838. Unit x = 0;
  839. int justBefore = false;
  840. lessScan45Element<Count2> lessElm(&x, &justBefore);
  841. std::set<Scan45ElementT<Count2>, lessScan45Element<Count2> > testData(lessElm);
  842. //Unit size = testData.size();
  843. typedef std::set<Scan45ElementT<Count2>, lessScan45Element<Count2> > Scan45Data;
  844. typename Scan45Data::iterator itr10 = testData.insert(testData.end(), Scan45Element(0, 10, 1));
  845. typename Scan45Data::iterator itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1));
  846. typename Scan45Data::iterator itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1));
  847. typename Scan45Data::iterator itr40 = testData.insert(testData.end(), Scan45Element(0, 40, -1));
  848. typename Scan45Data::iterator itrA = testData.lower_bound(Scan45Element(0, 29, -1));
  849. typename Scan45Data::iterator itr1 = testData.lower_bound(Scan45Element(0, 10, -1));
  850. x = 4;
  851. //now at 14 24 26 36
  852. typename Scan45Data::iterator itrB = testData.lower_bound(Scan45Element(4, 29, -1));
  853. typename Scan45Data::iterator itr2 = testData.lower_bound(Scan45Element(4, 14, -1));
  854. if(itr1 != itr2) stdcout << "test1 failed\n";
  855. if(itrA == itrB) stdcout << "test2 failed\n";
  856. //remove crossing elements
  857. testData.erase(itr20);
  858. testData.erase(itr30);
  859. x = 5;
  860. itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1));
  861. itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1));
  862. //now at 15 25 25 35
  863. typename Scan45Data::iterator itr = testData.begin();
  864. if(itr != itr10) stdcout << "test3 failed\n";
  865. ++itr;
  866. if(itr != itr30) stdcout << "test4 failed\n";
  867. ++itr;
  868. if(itr != itr20) stdcout << "test5 failed\n";
  869. ++itr;
  870. if(itr != itr40) stdcout << "test6 failed\n";
  871. stdcout << "done testing Scan45Data\n";
  872. return true;
  873. }
  874. template <typename stream_type>
  875. static inline bool testScan45Rect(stream_type& stdcout) {
  876. stdcout << "testing Scan45Rect\n";
  877. Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
  878. std::vector<Vertex45 > result;
  879. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  880. std::vector<Scan45Vertex> vertices;
  881. //is a Rectnagle(0, 0, 10, 10);
  882. Count2 count(1, 0);
  883. Count2 ncount(-1, 0);
  884. vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  885. vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  886. vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  887. vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  888. stdcout << "scanning\n";
  889. scan45.scan(result, vertices.begin(), vertices.end());
  890. stdcout << "done scanning\n";
  891. // result size == 8
  892. // result == 0 0 0 1
  893. // result == 0 0 2 1
  894. // result == 0 10 2 -1
  895. // result == 0 10 0 -1
  896. // result == 10 0 0 -1
  897. // result == 10 0 2 -1
  898. // result == 10 10 2 1
  899. // result == 10 10 0 1
  900. std::vector<Vertex45> reference;
  901. reference.push_back(Vertex45(Point(0, 0), 0, 1));
  902. reference.push_back(Vertex45(Point(0, 0), 2, 1));
  903. reference.push_back(Vertex45(Point(0, 10), 2, -1));
  904. reference.push_back(Vertex45(Point(0, 10), 0, -1));
  905. reference.push_back(Vertex45(Point(10, 0), 0, -1));
  906. reference.push_back(Vertex45(Point(10, 0), 2, -1));
  907. reference.push_back(Vertex45(Point(10, 10), 2, 1));
  908. reference.push_back(Vertex45(Point(10, 10), 0, 1));
  909. if(result != reference) {
  910. stdcout << "result size == " << result.size() << "\n";
  911. for(std::size_t i = 0; i < result.size(); ++i) {
  912. //std::cout << "result == " << result[i]<< "\n";
  913. }
  914. stdcout << "reference size == " << reference.size() << "\n";
  915. for(std::size_t i = 0; i < reference.size(); ++i) {
  916. //std::cout << "reference == " << reference[i]<< "\n";
  917. }
  918. return false;
  919. }
  920. stdcout << "done testing Scan45Rect\n";
  921. return true;
  922. }
  923. template <typename stream_type>
  924. static inline bool testScan45P1(stream_type& stdcout) {
  925. stdcout << "testing Scan45P1\n";
  926. Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
  927. std::vector<Vertex45 > result;
  928. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  929. std::vector<Scan45Vertex> vertices;
  930. //is a Rectnagle(0, 0, 10, 10);
  931. Count2 count(1, 0);
  932. Count2 ncount(-1, 0);
  933. vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
  934. vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount)));
  935. vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount)));
  936. vertices.push_back(Scan45Vertex(Point(10,20), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
  937. stdcout << "scanning\n";
  938. scan45.scan(result, vertices.begin(), vertices.end());
  939. stdcout << "done scanning\n";
  940. // result size == 8
  941. // result == 0 0 1 1
  942. // result == 0 0 2 1
  943. // result == 0 10 2 -1
  944. // result == 0 10 1 -1
  945. // result == 10 10 1 -1
  946. // result == 10 10 2 -1
  947. // result == 10 20 2 1
  948. // result == 10 20 1 1
  949. std::vector<Vertex45> reference;
  950. reference.push_back(Vertex45(Point(0, 0), 1, 1));
  951. reference.push_back(Vertex45(Point(0, 0), 2, 1));
  952. reference.push_back(Vertex45(Point(0, 10), 2, -1));
  953. reference.push_back(Vertex45(Point(0, 10), 1, -1));
  954. reference.push_back(Vertex45(Point(10, 10), 1, -1));
  955. reference.push_back(Vertex45(Point(10, 10), 2, -1));
  956. reference.push_back(Vertex45(Point(10, 20), 2, 1));
  957. reference.push_back(Vertex45(Point(10, 20), 1, 1));
  958. if(result != reference) {
  959. stdcout << "result size == " << result.size() << "\n";
  960. for(std::size_t i = 0; i < result.size(); ++i) {
  961. //std::cout << "result == " << result[i]<< "\n";
  962. }
  963. stdcout << "reference size == " << reference.size() << "\n";
  964. for(std::size_t i = 0; i < reference.size(); ++i) {
  965. //std::cout << "reference == " << reference[i]<< "\n";
  966. }
  967. return false;
  968. }
  969. stdcout << "done testing Scan45P1\n";
  970. return true;
  971. }
  972. template <typename stream_type>
  973. static inline bool testScan45P2(stream_type& stdcout) {
  974. stdcout << "testing Scan45P2\n";
  975. Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
  976. std::vector<Vertex45 > result;
  977. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  978. std::vector<Scan45Vertex> vertices;
  979. //is a Rectnagle(0, 0, 10, 10);
  980. Count2 count(1, 0);
  981. Count2 ncount(-1, 0);
  982. vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
  983. vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0))));
  984. vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0))));
  985. vertices.push_back(Scan45Vertex(Point(20,10), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
  986. stdcout << "scanning\n";
  987. scan45.scan(result, vertices.begin(), vertices.end());
  988. stdcout << "done scanning\n";
  989. // result size == 8
  990. // result == 0 0 0 1
  991. // result == 0 0 1 -1
  992. // result == 10 0 0 -1
  993. // result == 10 0 1 1
  994. // result == 10 10 1 1
  995. // result == 10 10 0 -1
  996. // result == 20 10 1 -1
  997. // result == 20 10 0 1
  998. std::vector<Vertex45> reference;
  999. reference.push_back(Vertex45(Point(0, 0), 0, 1));
  1000. reference.push_back(Vertex45(Point(0, 0), 1, -1));
  1001. reference.push_back(Vertex45(Point(10, 0), 0, -1));
  1002. reference.push_back(Vertex45(Point(10, 0), 1, 1));
  1003. reference.push_back(Vertex45(Point(10, 10), 1, 1));
  1004. reference.push_back(Vertex45(Point(10, 10), 0, -1));
  1005. reference.push_back(Vertex45(Point(20, 10), 1, -1));
  1006. reference.push_back(Vertex45(Point(20, 10), 0, 1));
  1007. if(result != reference) {
  1008. stdcout << "result size == " << result.size() << "\n";
  1009. for(std::size_t i = 0; i < result.size(); ++i) {
  1010. //stdcout << "result == " << result[i]<< "\n";
  1011. }
  1012. stdcout << "reference size == " << reference.size() << "\n";
  1013. for(std::size_t i = 0; i < reference.size(); ++i) {
  1014. //stdcout << "reference == " << reference[i]<< "\n";
  1015. }
  1016. return false;
  1017. }
  1018. stdcout << "done testing Scan45P2\n";
  1019. return true;
  1020. }
  1021. template <typename streamtype>
  1022. static inline bool testScan45And(streamtype& stdcout) {
  1023. stdcout << "testing Scan45And\n";
  1024. Scan45<Count2, boolean_op_45_output_functor<1> > scan45;
  1025. std::vector<Vertex45 > result;
  1026. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  1027. std::vector<Scan45Vertex> vertices;
  1028. //is a Rectnagle(0, 0, 10, 10);
  1029. Count2 count(1, 0);
  1030. Count2 ncount(-1, 0);
  1031. vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1032. vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1033. vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1034. vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1035. count = Count2(0, 1);
  1036. ncount = count.invert();
  1037. vertices.push_back(Scan45Vertex(Point(2,2), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1038. vertices.push_back(Scan45Vertex(Point(2,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1039. vertices.push_back(Scan45Vertex(Point(12,2), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1040. vertices.push_back(Scan45Vertex(Point(12,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1041. sortScan45Vector(vertices);
  1042. stdcout << "scanning\n";
  1043. scan45.scan(result, vertices.begin(), vertices.end());
  1044. stdcout << "done scanning\n";
  1045. //result size == 8
  1046. //result == 2 2 0 1
  1047. //result == 2 2 2 1
  1048. //result == 2 10 2 -1
  1049. //result == 2 10 0 -1
  1050. //result == 10 2 0 -1
  1051. //result == 10 2 2 -1
  1052. //result == 10 10 2 1
  1053. //result == 10 10 0 1
  1054. std::vector<Vertex45> reference;
  1055. reference.push_back(Vertex45(Point(2, 2), 0, 1));
  1056. reference.push_back(Vertex45(Point(2, 2), 2, 1));
  1057. reference.push_back(Vertex45(Point(2, 10), 2, -1));
  1058. reference.push_back(Vertex45(Point(2, 10), 0, -1));
  1059. reference.push_back(Vertex45(Point(10, 2), 0, -1));
  1060. reference.push_back(Vertex45(Point(10, 2), 2, -1));
  1061. reference.push_back(Vertex45(Point(10, 10), 2, 1));
  1062. reference.push_back(Vertex45(Point(10, 10), 0, 1));
  1063. if(result != reference) {
  1064. stdcout << "result size == " << result.size() << "\n";
  1065. for(std::size_t i = 0; i < result.size(); ++i) {
  1066. //stdcout << "result == " << result[i]<< "\n";
  1067. }
  1068. stdcout << "reference size == " << reference.size() << "\n";
  1069. for(std::size_t i = 0; i < reference.size(); ++i) {
  1070. //stdcout << "reference == " << reference[i]<< "\n";
  1071. }
  1072. return false;
  1073. }
  1074. stdcout << "done testing Scan45And\n";
  1075. return true;
  1076. }
  1077. template <typename stream_type>
  1078. static inline bool testScan45Star1(stream_type& stdcout) {
  1079. stdcout << "testing Scan45Star1\n";
  1080. Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
  1081. std::vector<Vertex45 > result;
  1082. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  1083. std::vector<Scan45Vertex> vertices;
  1084. //is a Rectnagle(0, 0, 10, 10);
  1085. Count2 count(1, 0);
  1086. Count2 ncount(-1, 0);
  1087. vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
  1088. vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
  1089. vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
  1090. count = Count2(0, 1);
  1091. ncount = count.invert();
  1092. vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
  1093. vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
  1094. vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
  1095. sortScan45Vector(vertices);
  1096. stdcout << "scanning\n";
  1097. scan45.scan(result, vertices.begin(), vertices.end());
  1098. stdcout << "done scanning\n";
  1099. // result size == 24
  1100. // result == 0 8 -1 1
  1101. // result == 0 8 1 -1
  1102. // result == 4 0 1 1
  1103. // result == 4 0 2 1
  1104. // result == 4 4 2 -1
  1105. // result == 4 4 -1 -1
  1106. // result == 4 12 1 1
  1107. // result == 4 12 2 1
  1108. // result == 4 16 2 -1
  1109. // result == 4 16 -1 -1
  1110. // result == 6 2 1 -1
  1111. // result == 6 14 -1 1
  1112. // result == 6 2 -1 1
  1113. // result == 6 14 1 -1
  1114. // result == 8 0 -1 -1
  1115. // result == 8 0 2 -1
  1116. // result == 8 4 2 1
  1117. // result == 8 4 1 1
  1118. // result == 8 12 -1 -1
  1119. // result == 8 12 2 -1
  1120. // result == 8 16 2 1
  1121. // result == 8 16 1 1
  1122. // result == 12 8 1 -1
  1123. // result == 12 8 -1 1
  1124. if(result.size() != 24) {
  1125. //stdcout << "result size == " << result.size() << "\n";
  1126. //stdcout << "reference size == " << 24 << "\n";
  1127. return false;
  1128. }
  1129. stdcout << "done testing Scan45Star1\n";
  1130. return true;
  1131. }
  1132. template <typename stream_type>
  1133. static inline bool testScan45Star2(stream_type& stdcout) {
  1134. stdcout << "testing Scan45Star2\n";
  1135. Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
  1136. std::vector<Vertex45 > result;
  1137. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  1138. std::vector<Scan45Vertex> vertices;
  1139. //is a Rectnagle(0, 0, 10, 10);
  1140. Count2 count(1, 0);
  1141. Count2 ncount(-1, 0);
  1142. vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
  1143. vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
  1144. vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
  1145. count = Count2(0, 1);
  1146. ncount = count.invert();
  1147. vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
  1148. vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
  1149. vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
  1150. sortScan45Vector(vertices);
  1151. stdcout << "scanning\n";
  1152. scan45.scan(result, vertices.begin(), vertices.end());
  1153. stdcout << "done scanning\n";
  1154. // result size == 24
  1155. // result == 0 4 0 1
  1156. // result == 0 4 1 -1
  1157. // result == 0 8 -1 1
  1158. // result == 0 8 0 -1
  1159. // result == 2 6 1 1
  1160. // result == 2 6 -1 -1
  1161. // result == 4 4 0 -1
  1162. // result == 4 8 0 1
  1163. // result == 4 4 -1 1
  1164. // result == 4 8 1 -1
  1165. // result == 8 0 -1 -1
  1166. // result == 8 0 1 1
  1167. // result == 8 12 1 1
  1168. // result == 8 12 -1 -1
  1169. // result == 12 4 1 -1
  1170. // result == 12 8 -1 1
  1171. // result == 12 4 0 1
  1172. // result == 12 8 0 -1
  1173. // result == 14 6 -1 -1
  1174. // result == 14 6 1 1
  1175. // result == 16 4 0 -1
  1176. // result == 16 4 -1 1
  1177. // result == 16 8 1 -1
  1178. // result == 16 8 0 1
  1179. if(result.size() != 24) {
  1180. //std::cout << "result size == " << result.size() << "\n";
  1181. //std::cout << "reference size == " << 24 << "\n";
  1182. return false;
  1183. }
  1184. stdcout << "done testing Scan45Star2\n";
  1185. return true;
  1186. }
  1187. template <typename stream_type>
  1188. static inline bool testScan45Star3(stream_type& stdcout) {
  1189. stdcout << "testing Scan45Star3\n";
  1190. Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
  1191. std::vector<Vertex45 > result;
  1192. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  1193. std::vector<Scan45Vertex> vertices;
  1194. //is a Rectnagle(0, 0, 10, 10);
  1195. Count2 count(1, 0);
  1196. Count2 ncount(-1, 0);
  1197. vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
  1198. vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
  1199. vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
  1200. vertices.push_back(Scan45Vertex(Point(6,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1201. vertices.push_back(Scan45Vertex(Point(6,14), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1202. vertices.push_back(Scan45Vertex(Point(12,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1203. vertices.push_back(Scan45Vertex(Point(12,14), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1204. count = Count2(0, 1);
  1205. ncount = count.invert();
  1206. vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
  1207. vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
  1208. vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
  1209. sortScan45Vector(vertices);
  1210. stdcout << "scanning\n";
  1211. scan45.scan(result, vertices.begin(), vertices.end());
  1212. stdcout << "done scanning\n";
  1213. // result size == 28
  1214. // result == 0 8 -1 1
  1215. // result == 0 8 1 -1
  1216. // result == 4 0 1 1
  1217. // result == 4 0 2 1
  1218. // result == 4 4 2 -1
  1219. // result == 4 4 -1 -1
  1220. // result == 4 12 1 1
  1221. // result == 4 12 2 1
  1222. // result == 4 16 2 -1
  1223. // result == 4 16 -1 -1
  1224. // result == 6 2 1 -1
  1225. // result == 6 14 -1 1
  1226. // result == 6 0 0 1
  1227. // result == 6 0 2 1
  1228. // result == 6 2 2 -1
  1229. // result == 6 14 1 -1
  1230. // result == 8 0 0 -1
  1231. // result == 8 0 0 1
  1232. // result == 8 14 0 -1
  1233. // result == 8 14 2 -1
  1234. // result == 8 16 2 1
  1235. // result == 8 16 1 1
  1236. // result == 12 0 0 -1
  1237. // result == 12 0 2 -1
  1238. // result == 12 8 2 1
  1239. // result == 12 8 2 -1
  1240. // result == 12 14 2 1
  1241. // result == 12 14 0 1
  1242. if(result.size() != 28) {
  1243. //std::cout << "result size == " << result.size() << "\n";
  1244. //std::cout << "reference size == " << 28 << "\n";
  1245. return false;
  1246. }
  1247. stdcout << "done testing Scan45Star3\n";
  1248. return true;
  1249. }
  1250. template <typename stream_type>
  1251. static inline bool testScan45Star4(stream_type& stdcout) {
  1252. stdcout << "testing Scan45Star4\n";
  1253. Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
  1254. std::vector<Vertex45 > result;
  1255. typedef std::pair<Point, Scan45Count> Scan45Vertex;
  1256. std::vector<Scan45Vertex> vertices;
  1257. //is a Rectnagle(0, 0, 10, 10);
  1258. Count2 count(1, 0);
  1259. Count2 ncount(-1, 0);
  1260. vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
  1261. vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
  1262. vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
  1263. vertices.push_back(Scan45Vertex(Point(0,6), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1264. vertices.push_back(Scan45Vertex(Point(0,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1265. vertices.push_back(Scan45Vertex(Point(16,6), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
  1266. vertices.push_back(Scan45Vertex(Point(16,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
  1267. count = Count2(0, 1);
  1268. ncount = count.invert();
  1269. vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
  1270. vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
  1271. vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
  1272. sortScan45Vector(vertices);
  1273. stdcout << "scanning\n";
  1274. scan45.scan(result, vertices.begin(), vertices.end());
  1275. stdcout << "done scanning\n";
  1276. // result size == 28
  1277. // result == 0 4 0 1
  1278. // result == 0 4 1 -1
  1279. // result == 0 6 0 1
  1280. // result == 0 6 2 1
  1281. // result == 0 8 2 -1
  1282. // result == 0 8 2 1
  1283. // result == 0 12 2 -1
  1284. // result == 0 12 0 -1
  1285. // result == 2 6 1 1
  1286. // result == 2 6 0 -1
  1287. // result == 4 4 0 -1
  1288. // result == 4 4 -1 1
  1289. // result == 8 12 0 1
  1290. // result == 8 0 -1 -1
  1291. // result == 8 0 1 1
  1292. // result == 8 12 0 -1
  1293. // result == 12 4 1 -1
  1294. // result == 12 4 0 1
  1295. // result == 14 6 -1 -1
  1296. // result == 14 6 0 1
  1297. // result == 16 4 0 -1
  1298. // result == 16 4 -1 1
  1299. // result == 16 6 0 -1
  1300. // result == 16 6 2 -1
  1301. // result == 16 8 2 1
  1302. // result == 16 8 2 -1
  1303. // result == 16 12 2 1
  1304. // result == 16 12 0 1
  1305. if(result.size() != 28) {
  1306. //stdcout << "result size == " << result.size() << "\n";
  1307. //stdcout << "reference size == " << 28 << "\n";
  1308. return false;
  1309. }
  1310. stdcout << "done testing Scan45Star4\n";
  1311. return true;
  1312. }
  1313. template <typename stream_type>
  1314. static inline bool testScan45(stream_type& stdcout) {
  1315. if(!testScan45Rect(stdcout)) return false;
  1316. if(!testScan45P1(stdcout)) return false;
  1317. if(!testScan45P2(stdcout)) return false;
  1318. if(!testScan45And(stdcout)) return false;
  1319. if(!testScan45Star1(stdcout)) return false;
  1320. if(!testScan45Star2(stdcout)) return false;
  1321. if(!testScan45Star3(stdcout)) return false;
  1322. if(!testScan45Star4(stdcout)) return false;
  1323. return true;
  1324. }
  1325. };
  1326. }
  1327. }
  1328. #endif