boolean_op_45.hpp 56 KB

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