diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/polygon/test | |
parent | Initial commit. (diff) | |
download | ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/polygon/test')
17 files changed, 7733 insertions, 0 deletions
diff --git a/src/boost/libs/polygon/test/Jamfile.v2 b/src/boost/libs/polygon/test/Jamfile.v2 new file mode 100644 index 00000000..16787e3d --- /dev/null +++ b/src/boost/libs/polygon/test/Jamfile.v2 @@ -0,0 +1,26 @@ +# test/Jamfile.v2 controls building of Polygon Library unit tests +# +# Copyright (c) 2010 Intel Corporation +# +# Use, modification and distribution is subject to the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import testing ; + +run polygon_point_test.cpp ; +run polygon_segment_test.cpp ; +run polygon_interval_test.cpp ; +run polygon_rectangle_test.cpp ; +run polygon_rectangle_formation_test.cpp ; +run polygon_set_data_test.cpp ; +run polygon_90_data_test.cpp ; +run gtl_boost_unit_test.cpp ; + +run voronoi_builder_test.cpp ; +run voronoi_ctypes_test.cpp ; +run voronoi_diagram_test.cpp ; +run voronoi_geometry_type_test.cpp ; +run voronoi_predicates_test.cpp ; +run voronoi_robust_fpt_test.cpp ; +run voronoi_structures_test.cpp ; diff --git a/src/boost/libs/polygon/test/gtl_boost_unit_test.cpp b/src/boost/libs/polygon/test/gtl_boost_unit_test.cpp new file mode 100644 index 00000000..c85d5d66 --- /dev/null +++ b/src/boost/libs/polygon/test/gtl_boost_unit_test.cpp @@ -0,0 +1,3866 @@ +/* + Copyright 2008 Intel Corporation + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +*/ +#include <iostream> +#define BOOST_POLYGON_NO_DEPS +#include <boost/polygon/polygon.hpp> + +namespace gtl = boost::polygon; +using namespace boost::polygon::operators; +#include <time.h> +#include <stdlib.h> + +void assert_s(bool c, std::string msg) { + if(!c) { + std::cout << msg << std::endl; + exit( 1); + } +} + +namespace boost { namespace polygon{ + void addpoly(polygon_45_set_data<int>& pset, + int* pts, unsigned int numpts) { + std::vector<point_data<int> > mppts; + for(unsigned int i = 0; i < numpts*2; i += 2) { + point_data<int> pt(pts[i], pts[i+1]); + mppts.push_back(pt); + } + polygon_45_data<int> poly; + poly.set(mppts.begin(), mppts.end()); + pset += poly; + } + + template <class T> + std::ostream& operator << (std::ostream& o, const interval_data<T>& i) + { + return o << i.get(LOW) << ' ' << i.get(HIGH); + } + template <class T> + std::ostream& operator << (std::ostream& o, const point_data<T>& r) + { + return o << r.get(HORIZONTAL) << ' ' << r.get(VERTICAL); + } + template <typename T> + std::ostream& operator<<(std::ostream& o, const polygon_45_data<T>& poly) { + o << "Polygon { "; + for(typename polygon_45_data<T>::iterator_type itr = poly.begin(); + itr != poly.end(); ++itr) { + if(itr != poly.begin()) o << ", "; + o << (*itr).get(HORIZONTAL) << " " << (*itr).get(VERTICAL); + } + o << " } "; + return o; + } + template <typename Unit> + inline std::ostream& operator<< (std::ostream& o, const polygon_45_set_data<Unit>& p) { + o << "Polygon45Set "; + o << " " << !p.sorted() << " " << p.dirty() << " { "; + for(typename polygon_45_set_data<Unit>::iterator_type itr = p.begin(); + itr != p.end(); ++itr) { + o << (*itr).pt << ":"; + for(unsigned int i = 0; i < 4; ++i) { + o << (*itr).count[i] << ","; + } o << " "; + //o << (*itr).first << ":" << (*itr).second << "; "; + } + o << "} "; + return o; + } + + template <typename Unit> + inline std::istream& operator>> (std::istream& i, polygon_45_set_data<Unit>& p) { + //TODO + return i; + } + template <typename T> + std::ostream& operator << (std::ostream& o, const polygon_90_data<T>& r) + { + o << "Polygon { "; + for(typename polygon_90_data<T>::iterator_type itr = r.begin(); itr != r.end(); ++itr) { + o << *itr << ", "; + } + return o << "} "; + } + + template <typename T> + std::istream& operator >> (std::istream& i, polygon_90_data<T>& r) + { + std::size_t size; + i >> size; + std::vector<T> vec; + vec.reserve(size); + for(std::size_t ii = 0; ii < size; ++ii) { + T coord; + i >> coord; + vec.push_back(coord); + } + r.set_compact(vec.begin(), vec.end()); + return i; + } + + template <typename T> + std::ostream& operator << (std::ostream& o, const std::vector<polygon_90_data<T> >& r) { + o << r.size() << ' '; + for(std::size_t ii = 0; ii < r.size(); ++ii) { + o << (r[ii]); + } + return o; + } + template <typename T> + std::istream& operator >> (std::istream& i, std::vector<polygon_90_data<T> >& r) { + std::size_t size; + i >> size; + r.clear(); + r.reserve(size); + for(std::size_t ii = 0; ii < size; ++ii) { + polygon_90_data<T> tmp; + i >> tmp; + r.push_back(tmp); + } + return i; + } + template <typename T> + std::ostream& operator<<(std::ostream& o, const polygon_data<T>& poly) { + o << "Polygon { "; + for(typename polygon_data<T>::iterator_type itr = poly.begin(); + itr != poly.end(); ++itr) { + if(itr != poly.begin()) o << ", "; + o << (*itr).get(HORIZONTAL) << " " << (*itr).get(VERTICAL); + } + o << " } "; + return o; + } + template <typename T> + std::ostream& operator << (std::ostream& o, const polygon_set_data<T>& r) + { + o << "Polygon Set Data { "; + for(typename polygon_set_data<T>::iterator_type itr = r.begin(); itr != r.end(); ++itr) { + o << "<" << (*itr).first.first << ", " << (*itr).first.second << ">:" << (*itr).second << " "; + } + o << "} "; + return o; + } + template <typename T> + std::ostream& operator<<(std::ostream& o, const polygon_90_with_holes_data<T>& poly) { + o << "Polygon With Holes { "; + for(typename polygon_90_with_holes_data<T>::iterator_type itr = poly.begin(); + itr != poly.end(); ++itr) { + if(itr != poly.begin()) o << ", "; + o << (*itr).get(HORIZONTAL) << " " << (*itr).get(VERTICAL); + } o << " { "; + for(typename polygon_90_with_holes_data<T>::iterator_holes_type itr = poly.begin_holes(); + itr != poly.end_holes(); ++itr) { + o << (*itr); + } + o << " } } "; + return o; + } + template <typename T> + std::ostream& operator<<(std::ostream& o, const polygon_45_with_holes_data<T>& poly) { + o << "Polygon With Holes { "; + for(typename polygon_45_with_holes_data<T>::iterator_type itr = poly.begin(); + itr != poly.end(); ++itr) { + if(itr != poly.begin()) o << ", "; + o << (*itr).get(HORIZONTAL) << " " << (*itr).get(VERTICAL); + } o << " { "; + for(typename polygon_45_with_holes_data<T>::iterator_holes_type itr = poly.begin_holes(); + itr != poly.end_holes(); ++itr) { + o << (*itr); + } + o << " } } "; + return o; + } + template <typename T> + std::ostream& operator<<(std::ostream& o, const polygon_with_holes_data<T>& poly) { + o << "Polygon With Holes { "; + for(typename polygon_with_holes_data<T>::iterator_type itr = poly.begin(); + itr != poly.end(); ++itr) { + if(itr != poly.begin()) o << ", "; + o << (*itr).get(HORIZONTAL) << " " << (*itr).get(VERTICAL); + } o << " { "; + for(typename polygon_with_holes_data<T>::iterator_holes_type itr = poly.begin_holes(); + itr != poly.end_holes(); ++itr) { + o << (*itr); + } + o << " } } "; + return o; + } + template <class T> + std::ostream& operator << (std::ostream& o, const rectangle_data<T>& r) + { + return o << r.get(HORIZONTAL) << ' ' << r.get(VERTICAL); + } + template <class T> + std::ostream& operator << (std::ostream& o, const segment_data<T>& r) + { + return o << r.get(LOW) << ' ' << r.get(HIGH); + } + + + template <typename T> + typename enable_if<typename is_polygon_90_set_type<T>::type, void>::type + print_is_polygon_90_set_concept(const T& ) { std::cout << "is polygon 90 set concept\n"; } + template <typename T> + typename enable_if<typename is_mutable_polygon_90_set_type<T>::type, void>::type + print_is_mutable_polygon_90_set_concept(const T& ) { std::cout << "is mutable polygon 90 set concept\n"; } + namespace boolean_op { + //self contained unit test for BooleanOr algorithm + template <typename Unit> + inline bool testBooleanOr() { + BooleanOp<int, Unit> booleanOr; + //test one rectangle + std::vector<std::pair<interval_data<Unit>, int> > container; + booleanOr.processInterval(container, interval_data<Unit>(0, 10), 1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(0, 10), -1); + if(container.size() != 2) { + std::cout << "Test one rectangle, wrong output size\n"; + return false; + } + if(container[0] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 10), 1)) { + std::cout << "Test one rectangle, first output wrong: Interval(" << + container[0].first << "), " << container[0].second << std::endl; + } + if(container[1] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 10), -1)) { + std::cout << "Test one rectangle, second output wrong: Interval(" << + container[1].first << "), " << container[1].second << std::endl; + } + + //test two rectangles + container.clear(); + booleanOr = BooleanOp<int, Unit>(); + booleanOr.processInterval(container, interval_data<Unit>(0, 10), 1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(5, 15), 1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(0, 10), -1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(5, 15), -1); + if(container.size() != 4) { + std::cout << "Test two rectangles, wrong output size\n"; + for(std::size_t i = 0; i < container.size(); ++i){ + std::cout << container[i].first << "), " << container[i].second << std::endl; + } + return false; + } + if(container[0] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 10), 1)) { + std::cout << "Test two rectangles, first output wrong: Interval(" << + container[0].first << "), " << container[0].second << std::endl; + } + if(container[1] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(10, 15), 1)) { + std::cout << "Test two rectangles, second output wrong: Interval(" << + container[1].first << "), " << container[1].second << std::endl; + } + if(container[2] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 5), -1)) { + std::cout << "Test two rectangles, third output wrong: Interval(" << + container[2].first << "), " << container[2].second << std::endl; + } + if(container[3] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(5, 15), -1)) { + std::cout << "Test two rectangles, fourth output wrong: Interval(" << + container[3].first << "), " << container[3].second << std::endl; + } + + //test two rectangles + container.clear(); + booleanOr = BooleanOp<int, Unit>(); + booleanOr.processInterval(container, interval_data<Unit>(5, 15), 1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(0, 10), 1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(5, 15), -1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(0, 10), -1); + if(container.size() != 4) { + std::cout << "Test other two rectangles, wrong output size\n"; + for(std::size_t i = 0; i < container.size(); ++i){ + std::cout << container[i].first << "), " << container[i].second << std::endl; + } + return false; + } + if(container[0] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(5, 15), 1)) { + std::cout << "Test other two rectangles, first output wrong: Interval(" << + container[0].first << "), " << container[0].second << std::endl; + } + if(container[1] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 5), 1)) { + std::cout << "Test other two rectangles, second output wrong: Interval(" << + container[1].first << "), " << container[1].second << std::endl; + } + if(container[2] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(10, 15), -1)) { + std::cout << "Test other two rectangles, third output wrong: Interval(" << + container[2].first << "), " << container[2].second << std::endl; + } + if(container[3] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 10), -1)) { + std::cout << "Test other two rectangles, fourth output wrong: Interval(" << + container[3].first << "), " << container[3].second << std::endl; + } + + //test two nonoverlapping rectangles + container.clear(); + booleanOr = BooleanOp<int, Unit>(); + booleanOr.processInterval(container, interval_data<Unit>(0, 10), 1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(15, 25), 1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(0, 10), -1); + booleanOr.advanceScan(); + booleanOr.processInterval(container, interval_data<Unit>(15, 25), -1); + if(container.size() != 4) { + std::cout << "Test two nonoverlapping rectangles, wrong output size\n"; + return false; + } + if(container[0] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 10), 1)) { + std::cout << "Test two nonoverlapping rectangles, first output wrong: Interval(" << + container[0].first << "), " << container[0].second << std::endl; + } + if(container[1] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(15, 25), 1)) { + std::cout << "Test two nonoverlapping rectangles, second output wrong: Interval(" << + container[1].first << "), " << container[1].second << std::endl; + } + if(container[2] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(0, 10), -1)) { + std::cout << "Test two nonoverlapping rectangles, third output wrong: Interval(" << + container[2].first << "), " << container[2].second << std::endl; + } + if(container[3] != std::pair<interval_data<Unit>, int>(interval_data<Unit>(15, 25), -1)) { + std::cout << "Test two nonoverlapping rectangles, fourth output wrong: Interval(" << + container[3].first << "), " << container[3].second << std::endl; + } + return true; + } + } + + void test_assign() { + using namespace gtl; + std::vector<polygon_data<int> > ps; + polygon_90_set_data<int> ps90; + assign(ps, ps90); + } + + //this is a compile time test, if it compiles it passes + void test_view_as() { + using namespace gtl; + polygon_data<int> p; + polygon_45_data<int> p45; + polygon_90_data<int> p90; + polygon_with_holes_data<int> pwh; + polygon_45_with_holes_data<int> p45wh; + polygon_90_with_holes_data<int> p90wh; + rectangle_data<int> rect(0, 1, 10, 11); + polygon_90_set_data<int> ps90; + polygon_45_set_data<int> ps45; + polygon_set_data<int> ps; + + assign(p, rect); + assign(p90, view_as<polygon_90_concept>(p)); + if(!equivalence(p90, rect)) + std::cout << "fail 1\n"; + assign(p45, view_as<polygon_45_concept>(p)); + if(!equivalence(p45, rect)) + std::cout << "fail 2\n"; + assign(p90, view_as<polygon_90_concept>(p45)); + if(!equivalence(p90, rect)) + std::cout << "fail 3\n"; + if(!equivalence(rect, view_as<rectangle_concept>(p))) + std::cout << "fail 4\n"; + if(!equivalence(rect, view_as<rectangle_concept>(p45))) + std::cout << "fail 5\n"; + if(!equivalence(rect, view_as<rectangle_concept>(p90))) + std::cout << "fail 6\n"; + assign(pwh, rect); + assign(p90wh, rect); + assign(p45wh, rect); + if(!equivalence(rect, view_as<rectangle_concept>(pwh))) + std::cout << "fail 7\n"; + if(!equivalence(rect, view_as<rectangle_concept>(p45wh))) + std::cout << "fail 8\n"; + if(!equivalence(rect, view_as<rectangle_concept>(p90wh))) + std::cout << "fail 9\n"; + assign(p90wh, view_as<polygon_90_with_holes_concept>(pwh)); + if(!equivalence(p90wh, rect)) + std::cout << "fail 10\n"; + assign(p45wh, view_as<polygon_45_with_holes_concept>(pwh)); + if(!equivalence(p45wh, rect)) + std::cout << "fail 11\n"; + assign(p90wh, view_as<polygon_90_with_holes_concept>(p45wh)); + if(!equivalence(p90wh, rect)) + std::cout << "fail 12\n"; + assign(p90, view_as<polygon_90_concept>(pwh)); + if(!equivalence(p90, rect)) + std::cout << "fail 13\n"; + assign(p45, view_as<polygon_45_concept>(pwh)); + if(!equivalence(p45, rect)) + std::cout << "fail 14\n"; + assign(p90, view_as<polygon_90_concept>(p45wh)); + if(!equivalence(p90, rect)) + std::cout << "fail 15\n"; + assign(ps, rect); + assign(ps90, view_as<polygon_90_set_concept>(ps)); + if(!equivalence(ps90, rect)) + std::cout << "fail 16\n"; + assign(ps45, view_as<polygon_45_set_concept>(ps)); + if(!equivalence(ps45, rect)) + std::cout << "fail 17\n"; + assign(ps90, view_as<polygon_90_set_concept>(ps45)); + if(!equivalence(ps90, rect)) + std::cout << "fail 18\n"; + } + + inline bool testPolygon45SetRect() { + std::vector<point_data<int> > points; + points.push_back(point_data<int>(0,0)); + points.push_back(point_data<int>(0,10)); + points.push_back(point_data<int>(10,10)); + points.push_back(point_data<int>(10,0)); + polygon_45_data<int> poly; + poly.set(points.begin(), points.end()); + polygon_45_set_data<int> ps; + ps.insert(poly); + std::vector<polygon_45_data<int> > polys; + ps.get_polygons(polys); + std::cout << polys.size() << std::endl; + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + return true; + } + + inline bool testPolygon45Set() { + polygon_45_formation<int>::Polygon45Formation pf(true); + typedef boolean_op_45<int>::Vertex45 Vertex45; + std::vector<Vertex45> data; + // result == 0 8 -1 1 + data.push_back(Vertex45(point_data<int>(0, 8), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(point_data<int>(0, 8), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(point_data<int>(4, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(point_data<int>(4, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(point_data<int>(4, 4), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(point_data<int>(4, 4), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(point_data<int>(4, 12), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(point_data<int>(4, 12), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(point_data<int>(4, 16), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(point_data<int>(4, 16), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(point_data<int>(6, 2), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(point_data<int>(6, 14), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(point_data<int>(6, 2), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(point_data<int>(6, 14), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(point_data<int>(8, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(point_data<int>(8, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(point_data<int>(8, 4), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(point_data<int>(8, 4), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(point_data<int>(8, 12), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(point_data<int>(8, 12), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(point_data<int>(8, 16), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(point_data<int>(8, 16), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(point_data<int>(12, 8), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(point_data<int>(12, 8), -1, 1)); + + data.push_back(Vertex45(point_data<int>(6, 4), 1, -1)); + data.push_back(Vertex45(point_data<int>(6, 4), 2, -1)); + data.push_back(Vertex45(point_data<int>(6, 12), -1, 1)); + data.push_back(Vertex45(point_data<int>(6, 12), 2, 1)); + data.push_back(Vertex45(point_data<int>(10, 8), -1, -1)); + data.push_back(Vertex45(point_data<int>(10, 8), 1, 1)); + + std::sort(data.begin(), data.end()); + std::vector<polygon_45_data<int> > polys; + pf.scan(polys, data.begin(), data.end()); + polygon_45_set_data<int> ps; + std::cout << "inserting1\n"; + //std::vector<point_data<int> > points; + //points.push_back(point_data<int>(0,0)); + //points.push_back(point_data<int>(0,10)); + //points.push_back(point_data<int>(10,10)); + //points.push_back(point_data<int>(10,0)); + //Polygon45 poly; + //poly.set(points.begin(), points.end()); + //ps.insert(poly); + ps.insert(polys[0]); + + polygon_45_set_data<int> ps2; + std::cout << "inserting2\n"; + ps2.insert(polys[0]); + std::cout << "applying boolean\n"; + ps |= ps2; + std::vector<polygon_45_data<int> > polys2; + std::cout << "getting result\n"; + ps.get_polygons(polys2); + std::cout << ps2 << std::endl; + std::cout << ps << std::endl; + std::cout << polys[0] << std::endl; + std::cout << polys2[0] << std::endl; + if(polys != polys2) std::cout << "test Polygon45Set failed\n"; + return polys == polys2; + } + + inline bool testPolygon45SetPerterbation() { + polygon_45_formation<int>::Polygon45Formation pf(true); + typedef boolean_op_45<int>::Vertex45 Vertex45; + std::vector<Vertex45> data; + // result == 0 8 -1 1 + data.push_back(Vertex45(point_data<int>(0, 80), -1, 1)); + // result == 0 8 1 -1 + data.push_back(Vertex45(point_data<int>(0, 80), 1, -1)); + // result == 4 0 1 1 + data.push_back(Vertex45(point_data<int>(40, 0), 1, 1)); + // result == 4 0 2 1 + data.push_back(Vertex45(point_data<int>(40, 0), 2, 1)); + // result == 4 4 2 -1 + data.push_back(Vertex45(point_data<int>(40, 40), 2, -1)); + // result == 4 4 -1 -1 + data.push_back(Vertex45(point_data<int>(40, 40), -1, -1)); + // result == 4 12 1 1 + data.push_back(Vertex45(point_data<int>(40, 120), 1, 1)); + // result == 4 12 2 1 + data.push_back(Vertex45(point_data<int>(40, 120), 2, 1)); + // result == 4 16 2 -1 + data.push_back(Vertex45(point_data<int>(40, 160), 2, 1)); + // result == 4 16 -1 -1 + data.push_back(Vertex45(point_data<int>(40, 160), -1, -1)); + // result == 6 2 1 -1 + data.push_back(Vertex45(point_data<int>(60, 20), 1, -1)); + // result == 6 14 -1 1 + data.push_back(Vertex45(point_data<int>(60, 140), -1, 1)); + // result == 6 2 -1 1 + data.push_back(Vertex45(point_data<int>(60, 20), -1, 1)); + // result == 6 14 1 -1 + data.push_back(Vertex45(point_data<int>(60, 140), 1, -1)); + // result == 8 0 -1 -1 + data.push_back(Vertex45(point_data<int>(80, 0), -1, -1)); + // result == 8 0 2 -1 + data.push_back(Vertex45(point_data<int>(80, 0), 2, -1)); + // result == 8 4 2 1 + data.push_back(Vertex45(point_data<int>(80, 40), 2, 1)); + // result == 8 4 1 1 + data.push_back(Vertex45(point_data<int>(80, 40), 1, 1)); + // result == 8 12 -1 -1 + data.push_back(Vertex45(point_data<int>(80, 120), -1, -1)); + // result == 8 12 2 -1 + data.push_back(Vertex45(point_data<int>(80, 120), 2, -1)); + // result == 8 16 2 1 + data.push_back(Vertex45(point_data<int>(80, 160), 2, 1)); + // result == 8 16 1 1 + data.push_back(Vertex45(point_data<int>(80, 160), 1, 1)); + // result == 12 8 1 -1 + data.push_back(Vertex45(point_data<int>(120, 80), 1, -1)); + // result == 12 8 -1 1 + data.push_back(Vertex45(point_data<int>(120, 80), -1, 1)); + + data.push_back(Vertex45(point_data<int>(60, 40), 1, -1)); + data.push_back(Vertex45(point_data<int>(60, 40), 2, -1)); + data.push_back(Vertex45(point_data<int>(60, 120), -1, 1)); + data.push_back(Vertex45(point_data<int>(60, 120), 2, 1)); + data.push_back(Vertex45(point_data<int>(100, 80), -1, -1)); + data.push_back(Vertex45(point_data<int>(100, 80), 1, 1)); + + std::sort(data.begin(), data.end()); + std::vector<polygon_45_data<int> > polys; + pf.scan(polys, data.begin(), data.end()); + polygon_45_set_data<int> ps; + std::cout << "inserting1\n"; + //std::vector<point_data<int> > points; + //points.push_back(point_data<int>(0,0)); + //points.push_back(point_data<int>(0,10)); + //points.push_back(point_data<int>(10,10)); + //points.push_back(point_data<int>(10,0)); + //Polygon45 poly; + //poly.set(points.begin(), points.end()); + //ps.insert(poly); + polygon_45_set_data<int> preps(polys[0]); + + ps.insert(polys[0]); + convolve(polys[0], point_data<int>(0, 1) ); + + polygon_45_set_data<int> ps2; + std::cout << "inserting2\n"; + ps2.insert(polys[0]); + std::cout << "applying boolean\n"; + ps |= ps2; + std::vector<polygon_45_data<int> > polys2; + std::cout << "getting result\n"; + ps.get_polygons(polys2); + std::cout << preps << std::endl; + std::cout << ps2 << std::endl; + std::cout << ps << std::endl; + std::cout << polys[0] << std::endl; + std::cout << polys2[0] << std::endl; + if(polys != polys2) std::cout << "test Polygon45Set failed\n"; + return polys == polys2; + //return true; + } + + inline int testPolygon45SetDORA() { + std::cout << "testPolygon45SetDORA" << std::endl; + std::vector<point_data<int> > pts; + pts.push_back(point_data<int>(0, 0)); + pts.push_back(point_data<int>(10, 0)); + pts.push_back(point_data<int>(10, 10)); + pts.push_back(point_data<int>(0, 10)); + polygon_45_data<int> apoly; + apoly.set(pts.begin(), pts.end()); + polygon_45_set_data<int> ps(apoly); + polygon_45_set_data<int> ps2(ps); + ps2 = apoly; + std::vector<polygon_45_data<int> > apolys; + apolys.push_back(apoly); + ps2.insert(apolys.begin(), apolys.end()); + apolys.clear(); + ps2.get(apolys); + std::cout << apolys.size() << std::endl; + std::cout << (ps == ps2) << std::endl; + std::cout << !(ps != ps2) << std::endl; + ps2.clear(); + std::cout << (ps2.value().empty()) << std::endl; + ps2.set(apolys.begin(), apolys.end()); + ps2.set(ps.value()); + ps.clean(); + ps2.set_clean(ps.value()); + ps2.insert(ps.value().begin(), ps.value().end()); + ps2.clear(); + for(polygon_45_set_data<int>::iterator_type itr = ps.begin(); + itr != ps.end(); ++itr) { + ps2.insert(*itr); + } + std::vector<polygon_45_with_holes_data<int> > apolywhs; + ps2.get_polygons_with_holes(apolywhs); + std::cout << apolywhs.size() << std::endl; + ps2 += 1; + apolywhs.clear(); + ps2.get_polygons_with_holes(apolywhs); + if(apolywhs.size()) std::cout << apolywhs[0] << std::endl; + ps2 -= 1; + apolywhs.clear(); + ps2.get_polygons_with_holes(apolywhs); + if(apolywhs.size()) std::cout << apolywhs[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + rectangle_data<int> rect; + extents(rect, apolywhs[0]); + ps2.clear(); + ps2.insert(rect); + ps2.extents(rect); + ps2.clear(); + ps2.insert(rect); + ps2.clear(); + ps2.insert(apolywhs[0]); + apolywhs.clear(); + ps2.get_trapezoids(apolywhs); + if(apolywhs.size()) std::cout << apolywhs[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + ps2 *= ps; + std::cout << (ps2 == ps) << std::endl; + ps2 ^= ps; + std::cout << ps2.empty() << std::endl; + axis_transformation atr(axis_transformation::WEST_SOUTH); + ps2 = ps; + ps.transform(atr); + transformation<int> tr(atr); + tr.invert(); + ps.transform(tr); + ps.scale_up(2); + ps.scale_down(2); + std::cout << (ps2 == ps) << std::endl; + pts.clear(); + pts.push_back(point_data<int>(0,0)); + pts.push_back(point_data<int>(10,10)); + pts.push_back(point_data<int>(10,11)); + pts.push_back(point_data<int>(0,21)); + apoly.set(pts.begin(), pts.end()); + ps2.clear(); + ps2.insert(apoly); + ps2 -= 1; + apolywhs.clear(); + ps2.get_polygons_with_holes(apolywhs); + if(apolywhs.size()) std::cout << apolywhs[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + pts.clear(); + pts.push_back(point_data<int>(0, 0)); + pts.push_back(point_data<int>(10, 10)); + pts.push_back(point_data<int>(0, 20)); + apoly.set(pts.begin(), pts.end()); + ps2.clear(); + ps2.insert(apoly); + pts.clear(); + pts.push_back(point_data<int>(0, 5)); + pts.push_back(point_data<int>(10, 15)); + pts.push_back(point_data<int>(0, 25)); + apoly.set(pts.begin(), pts.end()); + ps2.insert(apoly); + apolywhs.clear(); + ps2.get_polygons_with_holes(apolywhs); + if(apolywhs.size()) std::cout << apolywhs[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + return 0; + + } +} +} +using namespace gtl; + +bool testRectangle() { + rectangle_data<int> rect, rect2; +#ifdef BOOST_POLYGON_MSVC + horizontal(rect, interval_data<int>(0, 10)); + vertical(rect, interval_data<int>(20, 30)); +#else + horizontal(rect, interval_data<polygon_long_long_type>(0, 10)); + vertical(rect, interval_data<polygon_long_long_type>(20, 30)); +#endif + xl(rect2, 0); + xh(rect2, 10); + yl(rect2, 20); + yh(rect2, 30); + if(euclidean_distance(rect, rect2) != 0) return false; + if(euclidean_distance(rect2, rect) != 0) return false; +#ifdef BOOST_POLYGON_MSVC + set(rect, HORIZONTAL, interval_data<int>(0, 10)); + if(!equivalence(horizontal(rect), interval_data<int>(0, 10))) return false; + if(!equivalence(vertical(rect2), interval_data<int>(20, 30))) return false; +#else + set(rect, HORIZONTAL, interval_data<polygon_long_long_type>(0, 10)); + if(!equivalence(horizontal(rect), interval_data<polygon_long_long_type>(0, 10))) return false; + if(!equivalence(vertical(rect2), interval_data<polygon_long_long_type>(20, 30))) return false; +#endif + if(xl(rect) != 0) return false; + if(xh(rect) != 10) return false; + if(yl(rect) != 20) return false; + if(yh(rect) != 30) return false; + move(rect, HORIZONTAL, 10); + if(xl(rect) != 10) return false; +#ifdef BOOST_POLYGON_MSVC + set_points(rect, point_data<int>(0, 20), point_data<int>(10, 30)); +#else + set_points(rect, point_data<int>(0, 20), point_data<polygon_long_long_type>(10, 30)); +#endif + if(xl(rect) != 0) return false; + convolve(rect, rect2); + if(xh(rect) != 20) return false; + deconvolve(rect, rect2); + if(xh(rect) != 10) return false; + reflected_convolve(rect, rect2); + reflected_deconvolve(rect, rect2); + if(!equivalence(rect, rect2)) return false; +#ifdef BOOST_POLYGON_MSVC + convolve(rect, point_data<int>(100, 200)); +#else + convolve(rect, point_data<polygon_long_long_type>(100, 200)); +#endif + if(xh(rect) != 110) return false; + deconvolve(rect, point_data<int>(100, 200)); + if(!equivalence(rect, rect2)) return false; + xh(rect, 100); + if(delta(rect, HORIZONTAL) != 100) return false; + if(area(rect) != 1000) return false; + if(half_perimeter(rect) != 110) return false; + if(perimeter(rect) != 220) return false; + if(guess_orientation(rect) != HORIZONTAL) return false; + return true; +} + + +bool testPolygon() { + int rect[4] = {0, 10, 20, 30}; + iterator_compact_to_points<int*, point_data<int> > itr(rect, rect+4); + iterator_compact_to_points<int*, point_data<int> > itr_end(rect, rect+4); + std::vector<point_data<int> > points; + points.insert(points.end(), itr, itr_end); + polygon_90_data<int> p90; + assign(p90, rectangle_data<int>(interval_data<int>(0, 10), interval_data<int>(20, 30))); + if(winding(p90) != COUNTERCLOCKWISE) return false; + polygon_45_data<int> p45; + assign(p45, rectangle_data<int>(interval_data<int>(0, 10), interval_data<int>(20, 30))); + if(winding(p45) != COUNTERCLOCKWISE) return false; + polygon_data<int> p; + assign(p, rectangle_data<int>(interval_data<int>(0, 10), interval_data<int>(20, 30))); + if(winding(p) != COUNTERCLOCKWISE) return false; + set_compact(p90, rect, rect+4); + if(winding(p90) != COUNTERCLOCKWISE) return false; + points.clear(); + points.push_back(point_data<int>(0, 0)); + points.push_back(point_data<int>(10, 10)); + points.push_back(point_data<int>(0, 20)); + points.push_back(point_data<int>(-10, 10)); + set_points(p45, points.begin(), points.end()); + if(winding(p45) != COUNTERCLOCKWISE) return false; + std::swap(points[1], points[3]); + set_points(p, points.begin(), points.end()); + if(winding(p) == COUNTERCLOCKWISE) return false; + point_data<int> cp; + center(cp, p); + if(cp != point_data<int>(0, 10)) return false; + move(p, HORIZONTAL, 3); + rectangle_data<int> bounding_box; + extents(bounding_box, p); + if(bounding_box != rectangle_data<int>(interval_data<int>(-7, 13), interval_data<int>(0, 20))) return false; + if(area(p90) != 400) return false; + if(area(p45) != 200) return false; + if(perimeter(p90) != 80) return false; + return true; +} + +bool testPolygonAssign() { + polygon_data<int> p; + polygon_data<int> p1; + polygon_45_data<int> p_45; + polygon_45_data<int> p_451; + polygon_90_data<int> p_90; + polygon_90_data<int> p_901; + polygon_with_holes_data<int> p_wh; + polygon_with_holes_data<int> p_wh1; + polygon_45_with_holes_data<int> p_45_wh; + polygon_45_with_holes_data<int> p_45_wh1; + polygon_90_with_holes_data<int> p_90_wh; + polygon_90_with_holes_data<int> p_90_wh1; + assign(p, p1); + assign(p, p_45); + assign(p, p_90); + //assign(p, p_wh); + //assign(p, p_45_wh); + //assign(p, p_90_wh); + //assign(p_45, p); + assign(p_451, p_45); + assign(p_45, p_90); + //assign(p_45, p_wh); + //assign(p_45, p_45_wh); + //assign(p_45, p_90_wh); + //assign(p_90, p); + //assign(p_90, p_45); + assign(p_901, p_90); + //assign(p_90, p_wh); + //assign(p_90, p_45_wh); + //assign(p_90, p_90_wh); + assign(p_wh, p); + assign(p_wh, p_45); + assign(p_wh, p_90); + assign(p_wh1, p_wh); + assign(p_wh, p_45_wh); + assign(p_wh, p_90_wh); + //assign(p_45_wh, p); + assign(p_45_wh, p_45); + assign(p_45_wh, p_90); + //assign(p_45_wh, p_wh); + assign(p_45_wh1, p_45_wh); + //assign(p_90_wh, p); + //assign(p_90_wh, p_45); + assign(p_90_wh, p_90); + assign(p_90_wh1, p_90_wh); + return true; +} + +int testPropertyMerge() { + rectangle_data<int> rect1 = construct<rectangle_data<int> >(0, 1, 10, 11); + rectangle_data<int> rect2 = construct<rectangle_data<int> >(5, 6, 17, 18); + property_merge_90<int, int> pm; + pm.insert(rect1, 0); + pm.insert(rect2, 1); + std::map<std::set<int>, polygon_90_set_data<int> > result; + pm.merge(result); + std::vector<rectangle_data<int> > rects; + std::set<int> key; + key.insert(0); + result[key].get(rects); + std::cout << rects.size() << std::endl; + std::vector<polygon_data<int> > polys; + result[key].get(polys); + std::cout << polys.size() << std::endl; + std::vector<polygon_90_with_holes_data<int> > polywhs; + result[key].get(polywhs); + std::cout << polys.size() << std::endl; + return result.size(); +} + +bool testPolygonWithHoles() { + int rect[4] = {0, 10, 20, 30}; + iterator_compact_to_points<int*, point_data<int> > itr(rect, rect+4); + iterator_compact_to_points<int*, point_data<int> > itr_end(rect, rect+4); + std::vector<point_data<int> > points; + points.insert(points.end(), itr, itr_end); + polygon_45_with_holes_data<int> p45wh; + assign(p45wh, rectangle_data<int>(interval_data<int>(0, 10), interval_data<int>(20, 30))); + if(winding(p45wh) != COUNTERCLOCKWISE) return false; + polygon_45_with_holes_data<int> p45; + assign(p45, rectangle_data<int>(interval_data<int>(0, 10), interval_data<int>(20, 30))); + if(winding(p45) != COUNTERCLOCKWISE) return false; + polygon_45_with_holes_data<int> p; + assign(p, rectangle_data<int>(interval_data<int>(0, 10), interval_data<int>(20, 30))); + if(winding(p) != COUNTERCLOCKWISE) return false; + set_compact(p45wh, rect, rect+4); + if(winding(p45wh) != COUNTERCLOCKWISE) return false; + points.clear(); + points.push_back(point_data<int>(0, 0)); + points.push_back(point_data<int>(10, 10)); + points.push_back(point_data<int>(0, 20)); + points.push_back(point_data<int>(-10, 10)); + set_points(p45, points.begin(), points.end()); + if(winding(p45) != COUNTERCLOCKWISE) return false; + std::swap(points[1], points[3]); + set_points(p, points.begin(), points.end()); + if(winding(p) == COUNTERCLOCKWISE) return false; + point_data<int> cp; + center(cp, p); + if(cp != point_data<int>(0, 10)) return false; + move(p, HORIZONTAL, 3); + rectangle_data<int> bounding_box; + extents(bounding_box, p); + if(bounding_box != rectangle_data<int>(interval_data<int>(-7, 13), interval_data<int>(0, 20))) return false; + if(area(p45wh) != 400) return false; + if(area(p45) != 200) return false; + if(perimeter(p45wh) != 80) return false; + return true; +} + +using namespace gtl; + +typedef int Unit; +typedef point_data<int> Point; +typedef interval_data<int> Interval; +typedef rectangle_data<int> Rectangle; +typedef polygon_90_data<int> Polygon; +typedef polygon_90_with_holes_data<int> PolygonWithHoles; +typedef polygon_45_data<int> Polygon45; +typedef polygon_45_with_holes_data<int> Polygon45WithHoles; +typedef polygon_90_set_data<int> PolygonSet; +typedef polygon_45_set_data<int> Polygon45Set; +typedef axis_transformation AxisTransform; +typedef transformation<int> Transform; + +bool getRandomBool() { + return rand()%2 != 0; +} +int getRandomInt() { + return rand()%6-2; +} +Point getRandomPoint() { + int x = rand()%8; + int y = rand()%8; + return Point(x, y); +} +Polygon45 getRandomTriangle() { + Point pts[3]; + pts[0] = getRandomPoint(); + pts[1] = pts[2] = pts[0]; + int disp = getRandomInt(); + bool dir = getRandomBool(); + x(pts[2], x(pts[2]) + disp); + x(pts[1], x(pts[1]) + disp); + if(dir) + y(pts[1], y(pts[1]) + disp); + else + y(pts[1], y(pts[1]) - disp); + return Polygon45(pts, pts+3); +} + +bool nonInteger45StessTest() { + for(unsigned int tests = 0; tests < 10; ++tests) { + Polygon45Set ps1, ps2; + std::vector<Polygon45> p45s; + for(unsigned int i = 0; i < 10; ++i) { + Polygon45 p45 = getRandomTriangle(); + p45s.push_back(p45); + ps1.insert(p45); + scale_up(p45, 2); + ps2.insert(p45); + } + std::vector<Polygon45> polys; + ps1.get(polys); + Polygon45Set ps3; + for(unsigned int i = 0; i < polys.size(); ++i) { + scale_up(polys[i], 2); + ps3.insert(polys[i]); + } + Polygon45Set ps4 = ps3 ^ ps2; + std::vector<Polygon45> polys_error; + ps4.get(polys_error); + for(unsigned int i = 0; i < polys_error.size(); ++i) { + //if(polys_error[i].size() > 3) return false; + if(area(polys_error[i]) != 1) { + if(area(polys_error[i]) == 2) { + //if two area 1 errors merge it will have area 2 + continue; + } + std::cout << "test failed\n"; + for(unsigned int j =0; j < p45s.size(); ++j) { + std::cout << p45s[j] << std::endl; + } + return false; + } + } + } + return true; +} + +bool validate_polygon_set_op(Polygon45Set& ps45_o, + const Polygon45Set& ps45_1, + const Polygon45Set& ps45_2, + int op_type) { + Polygon45Set s_ps_45_o(ps45_o); + Polygon45Set s_ps_45_1(ps45_1); + Polygon45Set s_ps_45_2(ps45_2); + s_ps_45_o.scale_up(2); + s_ps_45_1.scale_up(2); + s_ps_45_2.scale_up(2); + Polygon45Set s_ps_45_validate; + if(op_type == 0) { + s_ps_45_validate = s_ps_45_1 + s_ps_45_2; + s_ps_45_validate += Rectangle(4, 4, 6, 6); + } else if(op_type == 1) { + s_ps_45_validate = s_ps_45_1 * s_ps_45_2; + s_ps_45_validate -= Rectangle(4, 4, 6, 6); + } else if(op_type == 2) { + s_ps_45_validate = s_ps_45_1 ^ s_ps_45_2; + s_ps_45_validate -= Rectangle(4, 4, 6, 6); + } else { + s_ps_45_validate = s_ps_45_1 - s_ps_45_2; + s_ps_45_validate -= Rectangle(4, 4, 6, 6); + } + if(s_ps_45_validate != s_ps_45_o) { + std::cout << "TEST FAILED\n"; + std::vector<Polygon45> polys; + s_ps_45_o.get(polys); + std::cout << "Result:\n"; + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + polys.clear(); + s_ps_45_validate.get(polys); + std::cout << "Expected Result:\n"; + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + //redo the operation, set breakpoints here + switch (op_type) { + case 0: + ps45_o = ps45_1 + ps45_2; + ps45_o.get(polys);//needed to force clean + break; + case 1: + ps45_o = ps45_1 * ps45_2; + break; + case 2: + ps45_o = ps45_1 ^ ps45_2; + break; + default: + ps45_o = ps45_1 - ps45_2; + }; + //redo the check, set breakpoints here + if(op_type == 0) { + s_ps_45_validate = s_ps_45_1 + s_ps_45_2; + s_ps_45_validate += Rectangle(4, 4, 6, 6); + s_ps_45_validate.get(polys); + } else if(op_type == 1) { + s_ps_45_validate = s_ps_45_1 * s_ps_45_2; + s_ps_45_validate -= Rectangle(4, 4, 6, 6); + } else if(op_type == 2) { + s_ps_45_validate = s_ps_45_1 ^ s_ps_45_2; + s_ps_45_validate -= Rectangle(4, 4, 6, 6); + } else { + s_ps_45_validate = s_ps_45_1 - s_ps_45_2; + s_ps_45_validate -= Rectangle(4, 4, 6, 6); + } + return false; + } + return true; +} + +bool test_two_polygon_sets(const Polygon45Set& ps45_1, + const Polygon45Set& ps45_2) { + std::cout << "test two polygon sets \n"; + std::vector<Polygon45> polys; + ps45_1.get(polys); + std::cout << "LVALUE:\n"; + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + polys.clear(); + ps45_2.get(polys); + std::cout << "RVALUE:\n"; + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + Polygon45Set ps45_o; + std::cout << "OR\n"; + ps45_o = ps45_1 + ps45_2; + polys.clear(); + ps45_o.get(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + if(!validate_polygon_set_op(ps45_o, ps45_1, ps45_2, 0)) return false; + std::cout << "AND\n"; + ps45_o = ps45_1 * ps45_2; + polys.clear(); + ps45_o.get(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + if(!validate_polygon_set_op(ps45_o, ps45_1, ps45_2, 1)) return false; + std::cout << "XOR\n"; + ps45_o = ps45_1 ^ ps45_2; + polys.clear(); + ps45_o.get(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + if(!validate_polygon_set_op(ps45_o, ps45_1, ps45_2, 2)) return false; + std::cout << "SUBTRACT\n"; + ps45_o = ps45_1 - ps45_2; + polys.clear(); + ps45_o.get(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + if(!validate_polygon_set_op(ps45_o, ps45_1, ps45_2, 3)) return false; + return true; +} + +bool test_two_polygons(const Polygon45& p45_1, + const Polygon45& p45_2) { + Polygon45Set ps45_1, ps45_2; + ps45_1.insert(p45_1); + ps45_2.insert(p45_2); + ps45_1.insert(rectangle_data<int>(10, -100, 20, 100)); + ps45_2.insert(rectangle_data<int>(0, 10, 100, 20)); + if(!test_two_polygon_sets(ps45_1, ps45_2)) return false; + Polygon45Set ps45_1_c = ps45_1 - Rectangle(0, 0, 2, 5); + Polygon45Set ps45_2_c = ps45_2 - Rectangle(0, 0, 2, 5); + if(!test_two_polygon_sets(ps45_1_c, ps45_2_c)) return false; + if(!test_two_polygon_sets(ps45_1_c, ps45_2)) return false; + if(!test_two_polygon_sets(ps45_1, ps45_2_c)) return false; + return true; +} + +bool test_45_touch() { + using namespace gtl; + connectivity_extraction_45<int> ce; + rectangle_data<int> rect1(0, 0, 10, 10); + rectangle_data<int> rect2(5, 5, 15, 15); + rectangle_data<int> rect3(5, 20, 15, 25); + ce.insert(rect1); + ce.insert(rect2); + ce.insert(rect3); + std::vector<std::set<int> > graph(3); + ce.extract(graph); + if(graph[0].size() == 1 && graph[1].size() == 1 && graph[2].size() == 0) { + std::set<int>::iterator itr = graph[0].begin(); + std::cout << *itr << std::endl; + std::set<int>::iterator itr1 = graph[1].begin(); + std::cout << *itr1 << std::endl; + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_45_touch_ur() { + using namespace gtl; + connectivity_extraction_45<int> ce; + rectangle_data<int> rect1(0, 0, 5, 5); + rectangle_data<int> rect2(5, 5, 10, 10); + ce.insert(rect1); + ce.insert(rect2); + std::vector<std::set<int> > graph(2); + ce.extract(graph); + if(graph[0].size() == 1 && graph[1].size() == 1) { + std::set<int>::iterator itr = graph[0].begin(); + std::cout << *itr << std::endl; + std::set<int>::iterator itr1 = graph[1].begin(); + std::cout << *itr1 << std::endl; + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_45_touch_r() { + using namespace gtl; + connectivity_extraction_45<int> ce; + rectangle_data<int> rect1(0, 0, 5, 5); + rectangle_data<int> rect2(5, 0, 10, 5); + ce.insert(rect1); + ce.insert(rect2); + std::vector<std::set<int> > graph(2); + ce.extract(graph); + if(graph[0].size() == 1 && graph[1].size() == 1) { + std::set<int>::iterator itr = graph[0].begin(); + std::cout << *itr << std::endl; + std::set<int>::iterator itr1 = graph[1].begin(); + std::cout << *itr1 << std::endl; + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_45_touch_boundaries() { + using namespace gtl; + connectivity_extraction_45<int> ce; + rectangle_data<int> rect1(0, 0, 10, 10); + rectangle_data<int> rect2(10, 0, 20, 10); + rectangle_data<int> rect3(20, 0, 30, 10); + rectangle_data<int> rect4(0, 10, 10, 20); + rectangle_data<int> rect5(10, 10, 20, 20); + rectangle_data<int> rect6(20, 10, 30, 20); + rectangle_data<int> rect7(0, 20, 10, 30); + rectangle_data<int> rect8(10, 20, 20, 30); + rectangle_data<int> rect9(20, 20, 30, 30); + ce.insert(rect1); + ce.insert(rect2); + ce.insert(rect3); + ce.insert(rect4); + ce.insert(rect5); + ce.insert(rect6); + ce.insert(rect7); + ce.insert(rect8); + ce.insert(rect9); + std::vector<std::set<int> > graph(9); + ce.extract(graph); + for(unsigned int i = 0; i < 9; ++i) { + std::cout << i << ": "; + for(std::set<int>::iterator itr = graph[i].begin(); itr != graph[i].end(); ++itr) { + std::cout << *itr << " "; + } std::cout << std::endl; + } + if(graph[0].size() == 3 && graph[1].size() == 5 && graph[2].size() == 3 && + graph[3].size() == 5 && graph[4].size() == 8 && graph[5].size() == 5 && + graph[6].size() == 3 && graph[7].size() == 5 && graph[8].size() == 3) { + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_45_concept_interact() { + using namespace gtl; + std::vector<polygon_45_data<int> > polys; + polys += rectangle_data<int>(10, 10, 20, 20); + polys += rectangle_data<int>(15, 15, 25, 25); + polys += rectangle_data<int>(5, 25, 10, 35); + interact(polys, rectangle_data<int>(0, 0, 13, 13)); + if(polys.size() != 1) return false; + return true; +} + +bool test_aa_touch() { + using namespace gtl; + connectivity_extraction<int> ce; + rectangle_data<int> rect1(0, 0, 10, 10); + rectangle_data<int> rect2(5, 5, 15, 15); + rectangle_data<int> rect3(5, 20, 15, 25); + ce.insert(rect1); + ce.insert(rect2); + ce.insert(rect3); + std::vector<std::set<int> > graph(3); + ce.extract(graph); + if(graph[0].size() == 1 && graph[1].size() == 1 && graph[2].size() == 0) { + std::set<int>::iterator itr = graph[0].begin(); + std::cout << *itr << std::endl; + std::set<int>::iterator itr1 = graph[1].begin(); + std::cout << *itr1 << std::endl; + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_aa_touch_ur() { + using namespace gtl; + connectivity_extraction<int> ce; + rectangle_data<int> rect1(0, 0, 5, 5); + rectangle_data<int> rect2(5, 5, 10, 10); + ce.insert(rect1); + ce.insert(rect2); + std::vector<std::set<int> > graph(2); + ce.extract(graph); + if(graph[0].size() == 1 && graph[1].size() == 1) { + std::set<int>::iterator itr = graph[0].begin(); + std::cout << *itr << std::endl; + std::set<int>::iterator itr1 = graph[1].begin(); + std::cout << *itr1 << std::endl; + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_aa_touch_ur2() { + using namespace gtl; + connectivity_extraction<int> ce; + rectangle_data<int> rect2(5, 5, 10, 10); + point_data<int> pts[3] = { + point_data<int>(0, 0), + point_data<int>(5, 5), + point_data<int>(0, 5) + }; + polygon_data<int> poly; + poly.set(pts, pts+3); + ce.insert(poly); + ce.insert(rect2); + std::vector<std::set<int> > graph(2); + ce.extract(graph); + if(graph[0].size() == 1 && graph[1].size() == 1) { + std::set<int>::iterator itr = graph[0].begin(); + std::cout << *itr << std::endl; + std::set<int>::iterator itr1 = graph[1].begin(); + std::cout << *itr1 << std::endl; + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_aa_touch_r() { + using namespace gtl; + connectivity_extraction<int> ce; + rectangle_data<int> rect1(0, 0, 5, 5); + rectangle_data<int> rect2(5, 0, 10, 5); + ce.insert(rect1); + ce.insert(rect2); + std::vector<std::set<int> > graph(2); + ce.extract(graph); + if(graph[0].size() == 1 && graph[1].size() == 1) { + std::set<int>::iterator itr = graph[0].begin(); + std::cout << *itr << std::endl; + std::set<int>::iterator itr1 = graph[1].begin(); + std::cout << *itr1 << std::endl; + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_aa_touch_boundaries() { + using namespace gtl; + connectivity_extraction<int> ce; + rectangle_data<int> rect1(0, 0, 10, 10); + rectangle_data<int> rect2(10, 0, 20, 10); + rectangle_data<int> rect3(20, 0, 30, 10); + rectangle_data<int> rect4(0, 10, 10, 20); + rectangle_data<int> rect5(10, 10, 20, 20); + rectangle_data<int> rect6(20, 10, 30, 20); + rectangle_data<int> rect7(0, 20, 10, 30); + rectangle_data<int> rect8(10, 20, 20, 30); + rectangle_data<int> rect9(20, 20, 30, 30); + ce.insert(rect1); + ce.insert(rect2); + ce.insert(rect3); + ce.insert(rect4); + ce.insert(rect5); + ce.insert(rect6); + ce.insert(rect7); + ce.insert(rect8); + ce.insert(rect9); + std::vector<std::set<int> > graph(9); + ce.extract(graph); + for(unsigned int i = 0; i < 9; ++i) { + std::cout << i << ": "; + for(std::set<int>::iterator itr = graph[i].begin(); itr != graph[i].end(); ++itr) { + std::cout << *itr << " "; + } std::cout << std::endl; + } + if(graph[0].size() == 3 && graph[1].size() == 5 && graph[2].size() == 3 && + graph[3].size() == 5 && graph[4].size() == 8 && graph[5].size() == 5 && + graph[6].size() == 3 && graph[7].size() == 5 && graph[8].size() == 3) { + return true; + } + std::cout << "test failed\n"; + return false; +} + +bool test_aa_concept_interact() { + using namespace gtl; + std::vector<polygon_data<int> > polys; + polys += rectangle_data<int>(10, 10, 20, 20); + polys += rectangle_data<int>(15, 15, 25, 25); + polys += rectangle_data<int>(5, 25, 10, 35); + interact(polys, rectangle_data<int>(0, 0, 13, 13)); + if(polys.size() != 1) return false; + return true; +} + +bool test_get_rectangles() { + using namespace gtl; + polygon_90_set_data<int> ps(VERTICAL); + ps += rectangle_data<int>(0, 0, 10, 10); + ps += rectangle_data<int>(5, 5, 15, 15); + std::vector<polygon_90_data<int> > polys; + ps.get_rectangles(polys, HORIZONTAL); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + if(polys.size() != 3) return false; + std::vector<rectangle_data<int> > rects; + ps.get_rectangles(rects, HORIZONTAL); + for(unsigned int i = 0; i < rects.size(); ++i) { + std::cout << rects[i] << std::endl; + } + if(rects.size() != 3) return false; + if(!equivalence(rects[2], rectangle_data<int>(5,10,15,15))) return false; + + get_rectangles(polys, rects, VERTICAL); + get_rectangles(rects, polys, HORIZONTAL); + return equivalence(rects, polys); +} + +bool test_get_trapezoids() { + using namespace gtl; + polygon_45_set_data<int> ps; + ps += rectangle_data<int>(0, 0, 10, 10); + ps += rectangle_data<int>(5, 5, 15, 15); + std::vector<polygon_45_data<int> > polys; + ps.get_trapezoids(polys, HORIZONTAL); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + if(polys.size() != 3) return false; + std::vector<polygon_45_data<int> > rects; + ps.get_trapezoids(rects, HORIZONTAL); + for(unsigned int i = 0; i < rects.size(); ++i) { + std::cout << rects[i] << std::endl; + } + if(rects.size() != 3) return false; + if(!equivalence(rects[2], rectangle_data<int>(5,10,15,15))) return false; + get_trapezoids(polys, rects, VERTICAL); + get_trapezoids(rects, polys, HORIZONTAL); + return equivalence(rects, polys); +} + +bool test_SQRT1OVER2() { + Point pts[] = { + Point(100, 100), + Point(0, 100), + Point(100, 200), + Point(0, 300), + Point(100, 400), + Point(0, 500), + Point(100, 500), + Point(100, 600), + Point(200, 500), + Point(300, 600), + Point(400, 500), + Point(500, 600), + Point(500, 500), + Point(600, 500), + Point(500, 400), + Point(600, 300), + Point(500, 200), + Point(600, 100), + Point(500, 100), + Point(500, 0), + Point(400, 100), + Point(300, 0), + Point(200, 100), + Point(100, 0), + Point(100, 100) + }; + Polygon45 p45(pts, pts+25); + std::cout << is_45(p45) << std::endl; + std::cout << p45 << std::endl; + Polygon45Set ps45; + ps45 += p45; + ps45.resize(10, SQRT1OVER2, ORTHOGONAL); + std::vector<Polygon45> polys; + ps45.get(polys); + if(polys.size() != 1) return false; + Point pts2[] = { + Point(90, 90), + Point(-10, 90), + Point(-10, 100), + Point(90, 200), + Point(-10, 300), + Point(90, 400), + Point(-10, 500), + Point(-10, 510), + Point(90, 510), + Point(90, 610), + Point(100, 610), + Point(200, 510), + Point(300, 610), + Point(400, 510), + Point(500, 610), + Point(510, 610), + Point(510, 510), + Point(610, 510), + Point(610, 500), + Point(510, 400), + Point(610, 300), + Point(510, 200), + Point(610, 100), + Point(610, 90), + Point(510, 90), + Point(510, -10), + Point(500, -10), + Point(400, 90), + Point(300, -10), + Point(200, 90), + Point(100, -10), + Point(90, -10), + Point(90, 90) + }; + Polygon45 p45reference(pts2, pts2+33); + std::cout << is_45(polys[0]) << std::endl; + std::cout << polys[0] << std::endl; + std::cout << p45reference << std::endl; + std::cout << is_45(p45reference) << std::endl; + if(!equivalence(polys[0], p45reference)) { + std::cout << "polys don't match\n"; + return false; + } + ps45.resize(-10, SQRT1OVER2, ORTHOGONAL); + polys.clear(); + ps45.get(polys); + if(polys.size() != 1) return false; + std::cout << is_45(polys[0]) << std::endl; + std::cout << polys[0] << std::endl; + if(!equivalence(polys[0], p45)) { + std::cout << "polys don't match\n"; + return false; + } + ps45.resize(11, SQRT1OVER2, UNFILLED); + polys.clear(); + ps45.get(polys); + if(polys.size() != 1) return false; + std::cout << is_45(polys[0]) << std::endl; + std::cout << polys[0] << std::endl; + return true; +} + +bool test_scaling_by_floating(){ + Point pts[] = { + Point(1, 1), + Point(10, 1), + Point(1, 10) + }; + Polygon45 poly(pts, pts+3); + Polygon45Set ps45; + ps45 += poly; + ps45.scale(double(2.5)); + std::vector<Polygon45> polys; + ps45.get(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + std::cout << area(polys[i]) << std::endl; + } + if(polys.size() != 1) return false; + if(area(polys[0]) != 242) return false; + scale(ps45, double(1)/double(2.5)); + polys.clear(); + ps45.get(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + return equivalence(polys, poly); +} + +bool test_directional_resize() { + std::vector<Rectangle> rects; + rects.push_back(Rectangle(0, 0, 100, 100)); + resize(rects, -10, 10, -10, 10); + for(unsigned int i = 0; i < rects.size(); ++i) { + std::cout << rects[i] << std::endl; + } + if(rects.size() != 1) return false; + if(rects[0] != Rectangle(10, 10, 110, 110)) return false; + + return true; +} + +bool test_self_xor() { + std::vector<Rectangle> rects; + rects.push_back(Rectangle(0, 0, 10, 10)); + rects.push_back(Rectangle(5, 5, 15, 15)); + self_xor(rects); + for(unsigned int i = 0; i < rects.size(); ++i) { + std::cout << rects[i] << std::endl; + } + if(rects.size() == 4) return true; + else return false; +} + +bool test_grow_and_45() { + polygon_45_set_data<int> ps; + ps.insert(Rectangle(0, 0, 5, 5)); + ps.insert(Rectangle(5, 5, 15, 15)); + grow_and(ps, 2); + std::vector<polygon_45_data<int> > rects; + ps.get_trapezoids(rects); + for(unsigned int i = 0; i < rects.size(); ++i) { + std::cout << rects[i] << std::endl; + } + if(rects.size() != 1) return false; + return equivalence(rects, Rectangle(3, 3, 7, 7)); +} + +bool test_self_xor_45() { + polygon_45_set_data<int> ps; + ps.insert(Rectangle(0, 0, 10, 10)); + ps.insert(Rectangle(5, 5, 15, 15)); + self_xor(ps); + std::vector<polygon_45_data<int> > rects; + ps.get_trapezoids(rects); + for(unsigned int i = 0; i < rects.size(); ++i) { + std::cout << rects[i] << std::endl; + } + if(rects.size() == 4) return true; + else return false; +} + +bool testViewCopyConstruct() { + PolygonSet ps1, ps2; + ps1.insert(Rectangle(0, 0, 10, 10)); + ps2.insert(Rectangle(5, 5, 15, 15)); + PolygonSet psr = ps1 - ps2; + std::vector<Rectangle> rects; + rects += psr; + for(unsigned int i = 0; i < rects.size(); ++i) + std::cout << rects[i] << std::endl; + if( rects.size() != 2) return false; + Polygon45Set ps45_1, ps45_2; + ps45_1.insert(Rectangle(0, 0, 10, 10)); + ps45_2.insert(Rectangle(5, 5, 15, 15)); + Polygon45Set ps45_r = ps45_1 - ps45_2; + std::vector<Polygon45> polys; + ps45_r.get_trapezoids(polys); + for(unsigned int i = 0; i < polys.size(); ++i) + std::cout << polys[i] << std::endl; + if( polys.size() != 2) return false; + return true; +} + +bool testpip() { + std::vector<Point> pts; + pts.push_back(Point(0, 0)); + pts.push_back(Point(10, 0)); + pts.push_back(Point(20, 10)); + pts.push_back(Point(0, 20)); + pts.push_back(Point(30, 40)); + pts.push_back(Point(-10, 50)); + pts.push_back(Point(-20, -20)); + pts.push_back(Point(0, 0)); + polygon_data<int> poly; + polygon_with_holes_data<int> poly2; + polygon_45_data<int> poly45; + polygon_45_with_holes_data<int> poly245; + polygon_90_data<int> poly90; + polygon_90_with_holes_data<int> poly290; + poly.set(pts.begin(), pts.end()); + poly2.set(pts.begin(), pts.end()); + assign(poly45, Rectangle(0, 0, 100, 100)); + assign(poly245, Rectangle(0, 0, 100, 100)); + assign(poly90, Rectangle(0, 0, 100, 100)); + assign(poly290, Rectangle(0, 0, 100, 100)); + for(unsigned int i = 0; i < pts.size(); ++i) { + if(!contains(poly, pts[i], true)) return false; + if(contains(poly, pts[i], false)) return false; + if(!contains(poly2, pts[i], true)) return false; + if(contains(poly2, pts[i], false)) return false; + } + if(!contains(poly45, pts[0], true)) return false; + if(contains(poly245, pts[0], false)) return false; + if(!contains(poly90, pts[0], true)) return false; + if(contains(poly290, pts[0], false)) return false; + Point pt(0, -10); + if(contains(poly, pt)) return false; + Point p2(0, 1); + if(!contains(poly, p2)) return false; + return true; +} + +void testHand() { + using namespace gtl; + int handcoords[] = { +12375, 11050, 13175, 10200, 15825, 9275, 18750, 8525, 24150, 8300, 27575, 8400, 31775, 7800, +35975, 7200, 41375, 4800, 42575, 4200, 43175, 4200, 47375, 2400, 49175, 1800, 51150, 2200, +52275, 2825, 52625, 4150, 52375, 4975, 51575, 6000, 49275, 6850, 45700, 7950, 43175, 9600, +39575, 10800, 37775, 12000, 37775, 12600, 37775, 13800, 38975, 14400, 41375, 14400, 45575, 13200, +48600, 13000, 51575, 13200, 55175, 12600, 58775, 12600, 61175, 13200, 62375, 14400, 62550, 15700, +61975, 16875, 60775, 17600, 60100, 17675, 58525, 17675, 56150, 17575, 52175, 18000, 47975, 18600, +45575, 19200, 44375, 19200, 42675, 19325, 41600, 19775, 41600, 20500, 42100, 20825, 44975, 20400, +48575, 20400, 52775, 21000, 53975, 21000, 57575, 21000, 62375, 21000, 65450, 22000, 66300, 23100, +66100, 24550, 64750, 25925, 62975, 26400, 61175, 26400, 58775, 26400, 56025, 26050, 53450, 26025, +50975, 26400, 48575, 26400, 46775, 26400, 43650, 26075, 41375, 26400, 40775, 27000, 40775, 27600, +42225, 28650, 44375, 29400, 48575, 30000, 50975, 31200, 53975, 31800, 58775, 33000, 61200, 34300, +62375, 35400, 62375, 37200, 61175, 38400, 60000, 38700, 57575, 38400, 54550, 37575, 50975, 36600, +49075, 36125, 47750, 36125, 45700, 35425, 42350, 34350, 38900, 33775, 30575, 33000, 26975, 33600, +25975, 34900, 26375, 36600, 28175, 38400, 30575, 40800, 32375, 43800, 33200, 46200, 33200, 48000, +32650, 49300, 31425, 50000, 29950, 50125, 28825, 49375, 27575, 48000, 25825, 46000, 23975, 44100, +22175, 42600, 19775, 39600, 17325, 37300, 14975, 34800, 13175, 31800, 10775, 29400, 9600, 27400, +10175, 27000, 11375, 27600, 12575, 28800, 14375, 31800, 16175, 34800, 18575, 37200, 21575, 39000, +22775, 40200, 23975, 41400, 24575, 42600, 26375, 44400, 28325, 46000, 29850, 46775, 31175, 46200, +31550, 44575, 30575, 43200, 28775, 40800, 25775, 38400, 24575, 34800, 24750, 33175, 26975, 31800, +29975, 31800, 33575, 31800, 37775, 32400, 39575, 33000, 41975, 33600, 45150, 34175, 46975, 34750, +48575, 35400, 50975, 35400, 51575, 34800, 51875, 33725, 50775, 32575, 48575, 31800, 45750, 30875, +43775, 30600, 41375, 29400, 38975, 28800, 35975, 28200, 34775, 27600, 34175, 27000, 34775, 25800, +37175, 25200, 40175, 25200, 43175, 25200, 46775, 25200, 50975, 25425, 53375, 25200, 55175, 24600, +55525, 23450, 53975, 22200, 52775, 22200, 49075, 21850, 45950, 21925, 40775, 21600, 37775, 21600, +35150, 21350, 34325, 20950, 34175, 19800, 35975, 19200, 38375, 19200, 40750, 18900, 42575, 18600, +44375, 18000, 47975, 17400, 50375, 17125, 52025, 16625, 52775, 15600, 52100, 14625, 49675, 14125, +48625, 14125, 46775, 14400, 44375, 15000, 41375, 15150, 37700, 15275, 34775, 15600, 32850, 15925, +31775, 15600, 31425, 14875, 32375, 13800, 36575, 11400, 38975, 10200, 41375, 9000, 43075, 8150, +43650, 7200, 43325, 6250, 42225, 5825, 40800, 6275, 38900, 6925, 35375, 8400, 32375, 10200, +27575, 11400, 22775, 12600, 19775, 13225, 16775, 13800, 14975, 14400, 13050, 14000, 11975, 12600, + 0, 0 }; + std::vector<Point> handpoints; + for(unsigned int i = 0; i < 100000; i += 2) { + Point pt(handcoords[i], handcoords[i+1]); + if(pt == Point(0, 0)) break; + handpoints.push_back(pt); + } + polygon_data<int> handpoly; + handpoly.set(handpoints.begin(), handpoints.end()); + int spiralcoords [] = { +37200, 3600, 42075, 4025, 47475, 5875, 51000, 7800, 55800, 12300, 59000, 17075, 60000, 20400, +61200, 25800, 61200, 29400, 60600, 33600, 58800, 38400, 55800, 42600, 53200, 45625, +49200, 48600, 43200, 51000, 35400, 51600, 29400, 50400, 23400, 47400, 19200, 43800, +16200, 39600, 14400, 35400, 13200, 29400, 13200, 24000, 15000, 18600, 17400, 13800, +20525, 10300, 24600, 7200, 29400, 4800, 32450, 4000, 34825, 3675, 35625, 3625, +35825, 7275, 39600, 7200, 43800, 8400, 46800, 9600, 50400, 12000, 53400, 15000, +55800, 18600, 57000, 23400, 57600, 27000, 57000, 32400, 55200, 37200, 52200, 41400, +48000, 45000, 42000, 47400, 35400, 48000, 30000, 46800, 24600, 43800, 20325, 39100, +17850, 34275, 16800, 27600, 17400, 22200, 20400, 16200, 24600, 11400, 28800, 9000, +32400, 7800, 33200, 7575, 33925, 11050, 35400, 10800, 37200, 10800, 41400, 11400, +46200, 13200, 49800, 16200, 51600, 19200, 53400, 23400, 54000, 29400, 52800, 33600, +49800, 39000, 45000, 42600, 39000, 44400, 33600, 43800, 28200, 42000, 24000, 37800, +21000, 33000, 20400, 26400, 21600, 21000, 24600, 16200, 28200, 13200, 31875, 11625, +33200, 15625, 36000, 15000, 39000, 15000, 43800, 16800, 46800, 19200, 49200, 23400, +49800, 27600, 48750, 32700, 46350, 36275, 42600, 39000, 38400, 40200, 31800, 39000, +28200, 36600, 25200, 31200, 24600, 26400, 26025, 21800, 28200, 18600, 30600, 16800, +32575, 19875, 34200, 19200, 36000, 18600, 37200, 18600, 40375, 19125, 43200, 21000, +45600, 24000, 46200, 27600, 45600, 30600, 43800, 33600, 41475, 35625, 37800, 36600, +33600, 36000, 30000, 33600, 28200, 28800, 28800, 24600, 30000, 22200, 31200, 23400, +30600, 25200, 30000, 27000, 30600, 30000, 31800, 32400, 34200, 34200, 38400, 34800, +41400, 33000, 44025, 30225, 44400, 26400, 43200, 23400, 40900, 21200, 37800, 20400, +34950, 20675, 32400, 22200, 30175, 19475, 28425, 21300, 27000, 24000, 26400, 27600, +27000, 31800, 31200, 36600, 36600, 38400, 42600, 37200, 46200, 33600, 48000, 30000, +47650, 24425, 45600, 20400, 42650, 18200, 39000, 16800, 35400, 16800, 33600, 17400, +32875, 17675, 31100, 13850, 28200, 15600, 25200, 18600, 22800, 22800, 22200, 27000, +23400, 33600, 26400, 38400, 31675, 41575, 37800, 42600, 40850, 42150, 42800, 41550, +47050, 39025, 50100, 35375, 52200, 29400, 51675, 23950, 49800, 19200, 46200, 15600, +41400, 13200, 37800, 12600, 35025, 12750, 33350, 13050, 32400, 9600, 30025, 10325, +25925, 12725, 22200, 16800, 19800, 21000, 18600, 25800, 18600, 30000, 20400, 35400, +22575, 39250, 25225, 41825, 28200, 43800, 33600, 46200, 39000, 46200, 44400, 45000, +48650, 42350, 52800, 37800, 55200, 32400, 55800, 26400, 54600, 21000, 53400, 18000, +50400, 14400, 47400, 12000, 42600, 9600, 39000, 9000, 36000, 9000, 34775, 9125, +34300, 5600, 30000, 6600, 25800, 8400, 22025, 11350, 18725, 15125, 16200, 20400, +15000, 24600, 15000, 30600, 16800, 36600, 20400, 42600, 25800, 46800, 31200, 49200, +38400, 49800, 45000, 48600, 51000, 45000, 55475, 40225, 58200, 34800, 59400, 30000, +59400, 25200, 58200, 19800, 55200, 14400, 52225, 11150, 47400, 7800, 44175, 6500, +40200, 5400, 38400, 5400, 37200, 5400, 0, 0 }; + std::vector<Point> spiralpoints; + for(unsigned int i = 0; i < 100000; i += 2) { + Point pt(spiralcoords[i], spiralcoords[i+1]); + if(pt == Point(0, 0)) break; + spiralpoints.push_back(pt); + } + polygon_data<int> spiralpoly; + spiralpoly.set(spiralpoints.begin(), spiralpoints.end()); + polygon_set_data<int> handset; + handset += handpoly; + polygon_set_data<int> spiralset; + spiralset += spiralpoly; + polygon_set_data<int> xorset = handset ^ spiralset; + std::vector<polygon_data<int> > polys; + polys += xorset; + std::cout << polys.size() << std::endl; + for(unsigned int i = 0; i < polys.size(); ++i) + std::cout << polys[i] << std::endl; +} + +//void testHandFloat() { +// using namespace gtl; +// double handcoords[] = { +//12375, 11050, 13175, 10200, 15825, 9275, 18750, 8525, 24150, 8300, 27575, 8400, 31775, 7800, +//35975, 7200, 41375, 4800, 42575, 4200, 43175, 4200, 47375, 2400, 49175, 1800, 51150, 2200, +//52275, 2825, 52625, 4150, 52375, 4975, 51575, 6000, 49275, 6850, 45700, 7950, 43175, 9600, +//39575, 10800, 37775, 12000, 37775, 12600, 37775, 13800, 38975, 14400, 41375, 14400, 45575, 13200, +//48600, 13000, 51575, 13200, 55175, 12600, 58775, 12600, 61175, 13200, 62375, 14400, 62550, 15700, +//61975, 16875, 60775, 17600, 60100, 17675, 58525, 17675, 56150, 17575, 52175, 18000, 47975, 18600, +//45575, 19200, 44375, 19200, 42675, 19325, 41600, 19775, 41600, 20500, 42100, 20825, 44975, 20400, +//48575, 20400, 52775, 21000, 53975, 21000, 57575, 21000, 62375, 21000, 65450, 22000, 66300, 23100, +//66100, 24550, 64750, 25925, 62975, 26400, 61175, 26400, 58775, 26400, 56025, 26050, 53450, 26025, +//50975, 26400, 48575, 26400, 46775, 26400, 43650, 26075, 41375, 26400, 40775, 27000, 40775, 27600, +//42225, 28650, 44375, 29400, 48575, 30000, 50975, 31200, 53975, 31800, 58775, 33000, 61200, 34300, +//62375, 35400, 62375, 37200, 61175, 38400, 60000, 38700, 57575, 38400, 54550, 37575, 50975, 36600, +//49075, 36125, 47750, 36125, 45700, 35425, 42350, 34350, 38900, 33775, 30575, 33000, 26975, 33600, +//25975, 34900, 26375, 36600, 28175, 38400, 30575, 40800, 32375, 43800, 33200, 46200, 33200, 48000, +//32650, 49300, 31425, 50000, 29950, 50125, 28825, 49375, 27575, 48000, 25825, 46000, 23975, 44100, +//22175, 42600, 19775, 39600, 17325, 37300, 14975, 34800, 13175, 31800, 10775, 29400, 9600, 27400, +//10175, 27000, 11375, 27600, 12575, 28800, 14375, 31800, 16175, 34800, 18575, 37200, 21575, 39000, +//22775, 40200, 23975, 41400, 24575, 42600, 26375, 44400, 28325, 46000, 29850, 46775, 31175, 46200, +//31550, 44575, 30575, 43200, 28775, 40800, 25775, 38400, 24575, 34800, 24750, 33175, 26975, 31800, +//29975, 31800, 33575, 31800, 37775, 32400, 39575, 33000, 41975, 33600, 45150, 34175, 46975, 34750, +//48575, 35400, 50975, 35400, 51575, 34800, 51875, 33725, 50775, 32575, 48575, 31800, 45750, 30875, +//43775, 30600, 41375, 29400, 38975, 28800, 35975, 28200, 34775, 27600, 34175, 27000, 34775, 25800, +//37175, 25200, 40175, 25200, 43175, 25200, 46775, 25200, 50975, 25425, 53375, 25200, 55175, 24600, +//55525, 23450, 53975, 22200, 52775, 22200, 49075, 21850, 45950, 21925, 40775, 21600, 37775, 21600, +//35150, 21350, 34325, 20950, 34175, 19800, 35975, 19200, 38375, 19200, 40750, 18900, 42575, 18600, +//44375, 18000, 47975, 17400, 50375, 17125, 52025, 16625, 52775, 15600, 52100, 14625, 49675, 14125, +//48625, 14125, 46775, 14400, 44375, 15000, 41375, 15150, 37700, 15275, 34775, 15600, 32850, 15925, +//31775, 15600, 31425, 14875, 32375, 13800, 36575, 11400, 38975, 10200, 41375, 9000, 43075, 8150, +//43650, 7200, 43325, 6250, 42225, 5825, 40800, 6275, 38900, 6925, 35375, 8400, 32375, 10200, +//27575, 11400, 22775, 12600, 19775, 13225, 16775, 13800, 14975, 14400, 13050, 14000, 11975, 12600, +// 0, 0 }; +// std::vector<point_data<double> > handpoints; +// for(unsigned int i = 0; i < 100000; i += 2) { +// point_data<double> pt(handcoords[i], handcoords[i+1]); +// if(pt == point_data<double> (0, 0)) break; +// handpoints.push_back(pt); +// } +// polygon_data<double> handpoly; +// handpoly.set(handpoints.begin(), handpoints.end()); +// double spiralcoords [] = { +//37200, 3600, 42075, 4025, 47475, 5875, 51000, 7800, 55800, 12300, 59000, 17075, 60000, 20400, +//61200, 25800, 61200, 29400, 60600, 33600, 58800, 38400, 55800, 42600, 53200, 45625, +//49200, 48600, 43200, 51000, 35400, 51600, 29400, 50400, 23400, 47400, 19200, 43800, +//16200, 39600, 14400, 35400, 13200, 29400, 13200, 24000, 15000, 18600, 17400, 13800, +//20525, 10300, 24600, 7200, 29400, 4800, 32450, 4000, 34825, 3675, 35625, 3625, +//35825, 7275, 39600, 7200, 43800, 8400, 46800, 9600, 50400, 12000, 53400, 15000, +//55800, 18600, 57000, 23400, 57600, 27000, 57000, 32400, 55200, 37200, 52200, 41400, +//48000, 45000, 42000, 47400, 35400, 48000, 30000, 46800, 24600, 43800, 20325, 39100, +//17850, 34275, 16800, 27600, 17400, 22200, 20400, 16200, 24600, 11400, 28800, 9000, +//32400, 7800, 33200, 7575, 33925, 11050, 35400, 10800, 37200, 10800, 41400, 11400, +//46200, 13200, 49800, 16200, 51600, 19200, 53400, 23400, 54000, 29400, 52800, 33600, +//49800, 39000, 45000, 42600, 39000, 44400, 33600, 43800, 28200, 42000, 24000, 37800, +//21000, 33000, 20400, 26400, 21600, 21000, 24600, 16200, 28200, 13200, 31875, 11625, +//33200, 15625, 36000, 15000, 39000, 15000, 43800, 16800, 46800, 19200, 49200, 23400, +//49800, 27600, 48750, 32700, 46350, 36275, 42600, 39000, 38400, 40200, 31800, 39000, +//28200, 36600, 25200, 31200, 24600, 26400, 26025, 21800, 28200, 18600, 30600, 16800, +//32575, 19875, 34200, 19200, 36000, 18600, 37200, 18600, 40375, 19125, 43200, 21000, +//45600, 24000, 46200, 27600, 45600, 30600, 43800, 33600, 41475, 35625, 37800, 36600, +//33600, 36000, 30000, 33600, 28200, 28800, 28800, 24600, 30000, 22200, 31200, 23400, +//30600, 25200, 30000, 27000, 30600, 30000, 31800, 32400, 34200, 34200, 38400, 34800, +//41400, 33000, 44025, 30225, 44400, 26400, 43200, 23400, 40900, 21200, 37800, 20400, +//34950, 20675, 32400, 22200, 30175, 19475, 28425, 21300, 27000, 24000, 26400, 27600, +//27000, 31800, 31200, 36600, 36600, 38400, 42600, 37200, 46200, 33600, 48000, 30000, +//47650, 24425, 45600, 20400, 42650, 18200, 39000, 16800, 35400, 16800, 33600, 17400, +//32875, 17675, 31100, 13850, 28200, 15600, 25200, 18600, 22800, 22800, 22200, 27000, +//23400, 33600, 26400, 38400, 31675, 41575, 37800, 42600, 40850, 42150, 42800, 41550, +//47050, 39025, 50100, 35375, 52200, 29400, 51675, 23950, 49800, 19200, 46200, 15600, +//41400, 13200, 37800, 12600, 35025, 12750, 33350, 13050, 32400, 9600, 30025, 10325, +//25925, 12725, 22200, 16800, 19800, 21000, 18600, 25800, 18600, 30000, 20400, 35400, +//22575, 39250, 25225, 41825, 28200, 43800, 33600, 46200, 39000, 46200, 44400, 45000, +//48650, 42350, 52800, 37800, 55200, 32400, 55800, 26400, 54600, 21000, 53400, 18000, +//50400, 14400, 47400, 12000, 42600, 9600, 39000, 9000, 36000, 9000, 34775, 9125, +//34300, 5600, 30000, 6600, 25800, 8400, 22025, 11350, 18725, 15125, 16200, 20400, +//15000, 24600, 15000, 30600, 16800, 36600, 20400, 42600, 25800, 46800, 31200, 49200, +//38400, 49800, 45000, 48600, 51000, 45000, 55475, 40225, 58200, 34800, 59400, 30000, +//59400, 25200, 58200, 19800, 55200, 14400, 52225, 11150, 47400, 7800, 44175, 6500, +//40200, 5400, 38400, 5400, 37200, 5400, 0, 0 }; +// std::vector<point_data<double> > spiralpoints; +// for(unsigned int i = 0; i < 100000; i += 2) { +// point_data<double> pt(spiralcoords[i], spiralcoords[i+1]); +// if(pt == point_data<double> (0, 0)) break; +// spiralpoints.push_back(pt); +// } +// polygon_data<double> spiralpoly; +// spiralpoly.set(spiralpoints.begin(), spiralpoints.end()); +// polygon_set_data<double> handset; +// handset += handpoly; +// polygon_set_data<double> spiralset; +// spiralset += spiralpoly; +// polygon_set_data<double> xorset = handset ^ spiralset; +// std::vector<polygon_data<double> > polys; +// polys += xorset; +// std::cout << polys.size() << std::endl; +// for(unsigned int i = 0; i < polys.size(); ++i) +// std::cout << polys[i] << std::endl; +//} + +bool testDirectionalSize() { + { + PolygonSet ps(VERTICAL); + ps += Rectangle(0, 0, 100, 100); + ps.resize(0, -10, 0, -10); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(0, 0, 90, 90) << std::endl; + if(rects[0] != Rectangle(0, 0, 90, 90)) return false; + } + { + PolygonSet ps(VERTICAL); + ps += Rectangle(0, 0, 100, 100); + ps.resize(0, 0, 0, -10); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(0, 0, 100, 90) << std::endl; + if(rects[0] != Rectangle(0, 0, 100, 90)) return false; + } + { + PolygonSet ps; + ps += Rectangle(0, 0, 100, 100); + ps.resize(0, -10, 0, 0); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(0, 0, 90, 100) << std::endl; + if(rects[0] != Rectangle(0, 0, 90, 100)) return false; + } + { + PolygonSet ps; + ps += Rectangle(0, 0, 100, 100); + ps.resize(0, 0, -10, 0); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(0, 10, 100, 100) << std::endl; + if(rects[0] != Rectangle(0, 10, 100, 100)) return false; + } + { + PolygonSet ps; + ps += Rectangle(0, 0, 100, 100); + ps.resize(-10, 0, 0, 0); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(10, 0, 100, 100) << std::endl; + if(rects[0] != Rectangle(10, 0, 100, 100)) return false; + } + { + PolygonSet ps; + ps += Rectangle(0, 0, 100, 100); + ps.resize(-10, 10, 0, 0); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(10, 0, 110, 100) << std::endl; + if(rects[0] != Rectangle(10, 0, 110, 100)) return false; + } + { + PolygonSet ps; + ps += Rectangle(0, 0, 100, 100); + ps.resize(-10, 10, 10, -10); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(10, -10, 110, 90) << std::endl; + if(rects[0] != Rectangle(10, -10, 110, 90)) return false; + } + { + PolygonSet ps; + ps += Rectangle(0, 0, 100, 100); + ps.resize(10, 10, -10, -10); + std::vector<Rectangle> rects; + ps.get(rects); + if(rects.size() != 1) return false; + std::cout << rects[0] << std::endl; + std::cout << Rectangle(-10, 10, 110, 90) << std::endl; + if(rects[0] != Rectangle(-10, 10, 110, 90)) return false; + } + return true; +} + +bool testMaxCover() { + std::vector<Rectangle> rects; + rects.push_back(Rectangle(Interval(60, 124), Interval( 1, 3))); + rects.push_back(Rectangle(Interval(59, 83), Interval( 9, 28))); + rects.push_back(Rectangle(Interval(90, 124), Interval( 3, 29))); + rects.push_back(Rectangle(Interval(64, 124), Interval( 29, 35))); + rects.push_back(Rectangle(Interval(64, 102), Interval( 35, 49))); + rects.push_back(Rectangle(Interval(1, 20), Interval( 44, 60))); + rects.push_back(Rectangle(Interval(50, 102), Interval( 49, 71))); + rects.push_back(Rectangle(Interval(49, 102), Interval( 71, 72))); + rects.push_back(Rectangle(Interval(49, 94), Interval( 72, 75))); + rects.push_back(Rectangle(Interval(50, 74), Interval( 75, 81))); + rects.push_back(Rectangle(Interval(90, 127), Interval( 75, 81))); + rects.push_back(Rectangle(Interval(50, 127), Interval( 81, 82))); + rects.push_back(Rectangle(Interval(3, 7), Interval( 60, 88))); + rects.push_back(Rectangle(Interval(50, 92), Interval( 82, 94))); + rects.push_back(Rectangle(Interval(58, 92), Interval( 94, 111))); + std::vector<Rectangle> expected_result; + expected_result.push_back(Rectangle(Interval(60, 124), Interval( 1, 3))); + expected_result.push_back(Rectangle(Interval(90, 124), Interval( 1, 35))); + expected_result.push_back(Rectangle(Interval(90, 102), Interval( 1, 72))); + expected_result.push_back(Rectangle(Interval(90, 94 ), Interval(1 ,82))); + expected_result.push_back(Rectangle(Interval(90, 92), Interval( 1, 111))); + expected_result.push_back(Rectangle(Interval(59, 83 ), Interval(9, 28))); + expected_result.push_back(Rectangle(Interval(64, 124), Interval( 29, 35))); + expected_result.push_back(Rectangle(Interval(64, 102), Interval( 29, 72))); + expected_result.push_back(Rectangle(Interval(64, 94), Interval( 29, 75))); + expected_result.push_back(Rectangle(Interval(64, 74), Interval( 29, 111))); + expected_result.push_back(Rectangle(Interval(1, 20), Interval( 44, 60))); + expected_result.push_back(Rectangle(Interval(3, 7), Interval( 44, 88))); + expected_result.push_back(Rectangle(Interval(50, 102 ), Interval(49, 72))); + expected_result.push_back(Rectangle(Interval(50, 94), Interval( 49, 75))); + expected_result.push_back(Rectangle(Interval(50, 74), Interval( 49, 94))); + expected_result.push_back(Rectangle(Interval(58, 74), Interval( 49, 111))); + expected_result.push_back(Rectangle(Interval(49, 102 ), Interval(71, 72))); + expected_result.push_back(Rectangle(Interval(49, 94 ), Interval(71, 75))); + expected_result.push_back(Rectangle(Interval(90, 127), Interval( 75, 82))); + expected_result.push_back(Rectangle(Interval(50, 127), Interval( 81, 82))); + expected_result.push_back(Rectangle(Interval(50, 92), Interval( 81, 94))); + expected_result.push_back(Rectangle(Interval(58, 92), Interval( 81, 111))); + std::vector<Rectangle> result; + get_max_rectangles(result, rects); + std::cout << "result XOR clean: " << equivalence(result, rects) << std::endl; + std::cout << "expected result XOR clean: " << equivalence(expected_result, rects) << std::endl; + std::vector<Rectangle>& output = result; + std::vector<Rectangle>& voutput = expected_result; + std::sort(output.begin(), output.end(), less_rectangle_concept< Rectangle, Rectangle>()); + std::sort(voutput.begin(), voutput.end(), less_rectangle_concept< Rectangle, Rectangle>()); + if(output != voutput) { + std::cerr << "Max Rectangle TEST failed\n"; + for(unsigned int i = 0; i < output.size(); ++i) { + std::cerr << output[i] << std::endl; + } + std::cerr << "Incorrect result\n"; + for(unsigned int i = 0; i < voutput.size(); ++i) { + std::cerr << voutput[i] << std::endl; + } + std::cerr << "Max Rectangle TEST failed\n"; + for(unsigned int i = 0; i < rects.size(); ++i) { + std::cout << rects[i] << std::endl; + } + return false; + } + return true; +} + +void max_cover_stress_test() { + for(unsigned int k = 3; k < 20; k++) { + for(unsigned int i = 0; i < k * k; ++i) { + std::vector<Rectangle> rects, result; + //std::cout << "test " << i << std::endl; + for(unsigned int j = 0; j < k; ++j) { + int x1 = rand() % 100; + int x2 = rand() % 50; + int y1 = rand() % 100; + int y2 = rand() % 50; + rects.push_back(Rectangle(x1, y1, x1+x2, y1+y2)); + //std::cout << rects.back() << std::endl; + } + get_max_rectangles(result, rects); + } + } +} + +// namespace boost { namespace polygon{ +// template <typename GCT, typename T> +// struct view_of {}; + +// template <typename T> +// struct view_of<polygon_45_concept, T> { +// const T* t; +// view_of(const T& obj) : t(&obj) {} +// typedef typename polygon_traits<T>::coordinate_type coordinate_type; +// typedef typename polygon_traits<T>::iterator_type iterator_type; +// typedef typename polygon_traits<T>::point_type point_type; + +// /// Get the begin iterator +// inline iterator_type begin() const { +// return polygon_traits<T>::begin_points(*t); +// } + +// /// Get the end iterator +// inline iterator_type end() const { +// return polygon_traits<T>::end_points(*t); +// } + +// /// Get the number of sides of the polygon +// inline unsigned int size() const { +// return polygon_traits<T>::size(*t); +// } + +// /// Get the winding direction of the polygon +// inline winding_direction winding() const { +// return polygon_traits<T>::winding(*t); +// } +// }; + +// template <typename T1, typename T2> +// view_of<T1, T2> view_as(const T2& obj) { return view_of<T1, T2>(obj); } + +// template <typename T> +// struct geometry_concept<view_of<polygon_45_concept, T> > { +// typedef polygon_45_concept type; +// }; + +// template <typename T> +// struct view_of<polygon_90_concept, T> { +// const T* t; +// view_of(const T& obj) : t(&obj) {} +// typedef typename polygon_traits<T>::coordinate_type coordinate_type; +// typedef typename polygon_traits<T>::iterator_type iterator_type; +// typedef typename polygon_traits<T>::point_type point_type; +// typedef iterator_points_to_compact<iterator_type, point_type> compact_iterator_type; + +// /// Get the begin iterator +// inline compact_iterator_type begin_compact() const { +// return compact_iterator_type(polygon_traits<T>::begin_points(*t), +// polygon_traits<T>::end_points(*t)); +// } + +// /// Get the end iterator +// inline compact_iterator_type end_compact() const { +// return compact_iterator_type(polygon_traits<T>::end_points(*t), +// polygon_traits<T>::end_points(*t)); +// } + +// /// Get the number of sides of the polygon +// inline unsigned int size() const { +// return polygon_traits<T>::size(*t); +// } + +// /// Get the winding direction of the polygon +// inline winding_direction winding() const { +// return polygon_traits<T>::winding(*t); +// } +// }; + +// template <typename T> +// struct geometry_concept<view_of<polygon_90_concept, T> > { +// typedef polygon_90_concept type; +// }; +// }} +using namespace gtl; + +//this test fails and I'd like to get it to pass +bool test_colinear_duplicate_points() { + Point pts[6] = { Point(0, 10), Point(0, 0), Point(100, 0), Point(100, 100), Point(0, 100), Point(0, 10)}; + Polygon45 p1; + p1.set(pts, pts+5); + Polygon45 pg; + pg.set(pts, pts+6); + Polygon45 p2; + p2.set(pts+1, pts+6); + std::cout << p2 << std::endl; + if(!equivalence(view_as<polygon_90_concept>(p2), view_as<polygon_90_concept>(pg))) return false; + std::cout << p1 << std::endl; + if(!equivalence(view_as<polygon_90_concept>(p1), view_as<polygon_90_concept>(pg))) return false; + return true; +} + +bool test_extents() { + PolygonSet psT(gtl::VERTICAL); + //int xy[] = { 126, 69, 54, 69, 54, 81, 126, 81 }; + //CPolygonQuery polygon(0, 4, xy); + //Rectangle rectIn(54, 69, 126, 81); + polygon_data<int> polygon; + std::vector<Point> pts; + pts.push_back(Point(126, 69)); + pts.push_back(Point(54, 69)); + pts.push_back(Point(54, 81)); + pts.push_back(Point(126, 81)); + set_points(polygon, pts.begin(), pts.end()); + psT.insert(view_as<polygon_90_concept>(polygon)); + + Rectangle rect, rect2; + psT.extents(rect2); + gtl::extents(rect, psT); + + if (rect != rect2) { + std::cout << "gtl::Rectangles differ: " << gtl::xl(rect) << " " << gtl::xh(rect) << " " << gtl::yl(rect) << " " << gtl::yh(rect) << std::endl; + std::cout << " " << gtl::xl(rect2) << " " << gtl::xh(rect2) << " " << gtl::yl(rect2) << " " << gtl::yh(rect2) << std::endl; + return false; + } + return true; +} + +bool test_extents2() { + Polygon45Set psT; + Point xy[] = { Point(130, 50), Point(50, 50), Point(50, 100), Point(119, 100), + Point(119, 59), Point(89, 89), Point(59, 59), Point(119, 59), Point(119, 100), Point(130, 100) }; + Polygon45 polygon(xy, xy+10); + + psT.insert(polygon); + psT += 2; + + Rectangle rect, rect2; + psT.extents(rect2); + gtl::extents(rect, psT); + std::cout << "Extents: " << gtl::xl(rect) << " " << gtl::xh(rect) << " " << gtl::yl(rect) << " " << gtl::yh(rect) << std::endl; + std::cout << "Extents: " << gtl::xl(rect2) << " " << gtl::xh(rect2) << " " << gtl::yl(rect2) << " " << gtl::yh(rect2) << std::endl; + std::vector<Polygon45WithHoles> pwhs; + psT.get(pwhs); + for(unsigned int i = 0; i < pwhs.size(); ++i) { + std::cout << pwhs[i] << std::endl; + } + return gtl::equivalence(rect, rect2); +} + +/*************New Polygon Formation Tests********************/ +/* + * + * Test Input: + * +--------------------+ + * | +-------+ | + * | | | | + * | | | | + * +-----+ | | | + * | | | | + * | | | | + * +-----+ | | | + * | | | | + * | | | | + * | +-------+ | + * +--------+ | + * | | + * | | + * +--------+ | + * | | + * | | + * +--------+ | + * | | + * | | + * +--------+ | + * | | + * | | + * +--------------------+ + * + * Test Plan: + * a. call 'get(out, param)' , param >=4 + * b. check if each polygon in the container is <= param + * c. check the area of all the pieces sum up to original piece + */ +typedef int intDC; +typedef boost::polygon::polygon_90_with_holes_data<intDC> GTLPolygon; +typedef boost::polygon::polygon_90_set_data<intDC> GTLPolygonSet; +typedef boost::polygon::polygon_90_concept GTLPolygonConcept; +typedef boost::polygon::point_data<intDC> GTLPoint; +inline void PrintPolygon(const GTLPolygon&); +inline GTLPolygon CreateGTLPolygon(const int*, size_t); +int test_new_polygon_formation(int argc, char** argv){ + // // + // Sub-Test-1: do a Boolean and call the new get // + // // + int coordinates[] = {0,0, 10,0, 10,10, 0,10}; + int coordinates1[] = {9,1, 20,1, 20,10, 9,10}; + std::vector<GTLPoint> pts; + size_t count = sizeof(coordinates)/(2*sizeof(intDC)); + size_t count1 = sizeof(coordinates1)/(2*sizeof(intDC)); + GTLPolygon poly, poly1; + GTLPolygonSet polySet; + + poly = CreateGTLPolygon(coordinates, count); + poly1 = CreateGTLPolygon(coordinates1, count1); + + polySet.insert(poly); + polySet.insert(poly1); + + std::vector<GTLPolygon> result; + polySet.get(result, 100); + + if(result.size() > 1){ + std::cerr << "FAILED: expecting only one polygon because the" + " threshold is 100" << std::endl; + return 1; + } + + if(result[0].size() != 6){ + std::cerr << "FAILED: expecting only 6 vertices" << std::endl; + return 1; + } + + if(area(result[0]) != 190){ + std::cerr <<"FAILED: expecting only 6 vertices" << std::endl; + return 1; + } + + //expect no more than 1 polygon + std::cout << "Found " << result.size() << "polygons after union" + << std::endl; + for(size_t i=0; i<result.size(); i++){ + PrintPolygon(result[i]); + } + + intDC shell_coords[] = {0,0, 10,0, 10,21, 0,21, 0,15, 3,15, 3,13, + 0,13, 0,10, 5,10, 5,8, 0,8, 0,5, 5,5, 5,3, 0,3}; + intDC hole_coords[] = {4,11, 7,11, 7,19, 4,19}; + GTLPolygon slice_polygon, slice_hole; + count = sizeof(shell_coords)/(2*sizeof(intDC)); + count1 = sizeof(hole_coords)/(2*sizeof(intDC)); + + slice_polygon = CreateGTLPolygon(shell_coords, count); + slice_hole = CreateGTLPolygon(hole_coords, count1); + + result.clear(); + polySet.clear(); + polySet.insert(slice_polygon); + polySet.insert(slice_hole, true); + + polySet.get(result); + double gold_area = 0; + std::cout << "Found " << result.size() << " slices" << std::endl; + for(size_t i=0; i<result.size(); i++){ + PrintPolygon(result[i]); + gold_area += area(result[i]); + } + + result.clear(); + polySet.get(result, 6); + double platinum_area = 0; + std::cout << "Found " << result.size() << " slices" << std::endl; + for(size_t i=0; i<result.size(); i++){ + PrintPolygon(result[i]); + platinum_area += area(result[i]); + if(result[i].size() > 6){ + std::cerr << "FAILED: expecting size to be less than 6" << std::endl; + return 1; + } + } + + std::cout << "platinum_area = " << platinum_area << " , gold_area=" + << gold_area << std::endl; + if( platinum_area != gold_area){ + std::cerr << "FAILED: Area mismatch" << std::endl; + return 1; + } + std::cout << "[SUB-TEST-1] PASSED\n"; + + result.clear(); + polySet.get(result, 4); + platinum_area = 0; + std::cout << "Found " << result.size() << " slices" << std::endl; + for(size_t i=0; i<result.size(); i++){ + PrintPolygon(result[i]); + platinum_area += area(result[i]); + if(result[i].size() > 4){ + std::cerr << "FAILED: expecting size to be < 4" << std::endl; + return 1; + } + } + + std::cout << "platinum_area=" << platinum_area << ", gold_area=" + << gold_area << std::endl; + + if( platinum_area != gold_area){ + std::cerr << "FAILED: Area mismatch" << std::endl; + return 1; + } + + std::cout << "[SUB-TEST-1] PASSED" << std::endl; + return 0; +} + +/* + * INPUT: + * +--------+ + * | | + * | | + * | +---+ + * | | + * | +---+ + * | | + * +--------+ + * X + * + * TEST PLAN: as the sweepline moves and reaches + * X the number of vertices in the solid jumps by 4 + * instead of 2. So make sure we don't get a 6 vertex + * polygon when the threshold is 4 and 6. + */ +int test_new_polygon_formation_marginal_threshold(int argc, char**){ + std::vector<GTLPoint> pts; + GTLPolygon polygon; + GTLPolygonSet pset; + std::vector<GTLPolygon> result; + intDC coords[] = {0,0, 15,0, 15,10, 10,10, 10,15, 5,15, 5,10, 0,10}; + size_t count = sizeof(coords)/(2*sizeof(intDC)); + + polygon = CreateGTLPolygon(coords, count); + pset.insert(polygon); + + for(size_t i=0; i<1; i++){ + pset.get(result, i ? 4 : 6); + double gold_area = 175, plat_area = 0; + for(size_t i=0; i<result.size(); i++){ + if(result[i].size() > (i ? 4 : 6) ){ + size_t expected = i ? 4 : 6; + std::cerr << "FAILED: Expecting no more than " << + expected << " vertices" << std::endl; + return 1; + } + PrintPolygon(result[i]); + plat_area += area(result[i]); + } + + if(plat_area != gold_area){ + std::cerr << "FAILED area mismatch gold=" << gold_area << + " plat=" << plat_area << std::endl; + return 1; + } + } + std::cout << "Test Passed" << std::endl; + return 0; +} + +inline void PrintPolygon(const GTLPolygon& p){ + //get an iterator of the point_data<int> + boost::polygon::point_data<int> pt; + boost::polygon::polygon_90_data<int>::iterator_type itr; + + size_t vertex_id = 0; + for(itr = p.begin(); itr != p.end(); ++itr){ + pt = *itr; + std::cout << "Vertex-" << ++vertex_id << "(" << pt.x() << + "," << pt.y() << ")" << std::endl; + } +} + +// size: is the number of vertices // +inline GTLPolygon CreateGTLPolygon(const int *coords, size_t size){ + GTLPolygon r; + std::vector<GTLPoint> pts; + + for(size_t i=0; i<size; i++){ + pts.push_back( GTLPoint(coords[2*i], coords[2*i+1]) ); + } + boost::polygon::set_points(r, pts.begin(), pts.end()); + return r; +} + +/************************************************************/ + +int main() { + test_view_as(); + //this test fails and I'd like to get it to pass + //if(!test_colinear_duplicate_points()) return 1; + if(!test_extents2()) return 1; + if(!test_extents()) return 1; + if(!testMaxCover()) return 1; + //max_cover_stress_test(); //does not include functional testing + if(!testDirectionalSize()) return 1; + testHand(); + //testHandFloat(); + if(!testpip()) return 1; + { + PolygonSet ps; + Polygon p; + assign(ps, p); + } + if(!testViewCopyConstruct()) return 1; + if(!test_grow_and_45()) return 1; + if(!test_self_xor_45()) return 1; + if(!test_self_xor()) return 1; + if(!test_directional_resize()) return 1; + if(!test_scaling_by_floating()) return 1; + if(!test_SQRT1OVER2()) return 1; + if(!test_get_trapezoids()) return 1; + if(!test_get_rectangles()) return 1; + if(!test_45_concept_interact()) return 1; + if(!test_45_touch_r()) return 1; + if(!test_45_touch_ur()) return 1; + if(!test_45_touch()) return 1; + if(!test_45_touch_boundaries()) return 1; + { + Point pts[] = {Point(0,0), Point(5, 5), Point(5, 0)}; + Polygon45 p45(pts, pts+3); + pts[1] = Point(0, 5); + Polygon45 p452(pts, pts+3); + if(!test_two_polygons(p45,p452)) return 1; + pts[2] = Point(5,5); + p45.set(pts, pts+3); + if(!test_two_polygons(p45,p452)) return 1; + pts[0] = Point(5,0); + p452.set(pts, pts+3); + if(!test_two_polygons(p45, p452)) return 1; + Point pts2[] = {Point(0,5), Point(5, 5), Point(5, 0)}; + Point pts3[] = {Point(0,0), Point(5, 5), Point(5, 0)}; + p45.set(pts2, pts2 + 3); + p452.set(pts3, pts3+3); + if(!test_two_polygons(p45, p452)) return 1; + Point pts4[] = {Point(0, 5), Point(3, 2), Point(3,5)}; + Point pts5[] = {Point(0,0), Point(5, 5), Point(5, 0)}; + p45.set(pts4, pts4+3); + p452.set(pts5, pts5+3); + if(!test_two_polygons(p45, p452)) return 1; + } + { + std::vector<point_data<int> > pts; + pts.push_back(point_data<int>(0, 0)); + pts.push_back(point_data<int>(10, 0)); + pts.push_back(point_data<int>(10, 10)); + pts.push_back(point_data<int>(0, 10)); + std::vector<point_data<int> > pts2; + pts2.push_back(point_data<int>(0, 0)); + pts2.push_back(point_data<int>(10, 10)); + pts2.push_back(point_data<int>(0, 20)); + pts2.push_back(point_data<int>(-10, 10)); + std::vector<point_data<int> > pts3; + pts3.push_back(point_data<int>(0, 0)); + pts3.push_back(point_data<int>(10, 11)); + pts3.push_back(point_data<int>(0, 20)); + pts3.push_back(point_data<int>(-100, 8)); + polygon_data<int> p, p1; p.set(pts3.begin(), pts3.end()); + polygon_45_data<int> p45, p451; p45.set(pts2.begin(), pts2.end()); + polygon_90_data<int> p90, p901; p90.set(pts.begin(), pts.end()); + polygon_with_holes_data<int> pwh, pwh1; pwh.set(pts3.begin(), pts3.end()); + polygon_45_with_holes_data<int> p45wh, p45wh1; p45wh.set(pts2.begin(), pts2.end()); + polygon_90_with_holes_data<int> p90wh, p90wh1; p90wh.set(pts.begin(), pts.end()); + assign(p, p90); + assign(p, p45); + assign(p1, p); + //illegal: assign(p, p90wh); + //illegal: assign(p, p45wh); + //illegal: assign(p, pwh); + + assign(p45, p90); + assign(p451, p45); + //illegal: assign(p45, p); + //illegal: assign(p45, p90wh); + //illegal: assign(p45, p45wh); + //illegal: assign(p45, pwh); + + assign(p901, p90); + //illegal: assign(p90, p45); + //illegal: assign(p90, p); + //illegal: assign(p90, p90wh); + //illegal: assign(p90, p45wh); + //illegal: assign(p90, pwh); + + assign(pwh, p90); + assign(pwh, p45); + assign(pwh, p); + assign(pwh, p90wh); + assign(pwh, p45wh); + assign(pwh1, pwh); + + assign(p45wh, p90); + assign(p45wh, p45); + //illegal: assign(p45wh, p); + assign(p45wh, p90wh); + assign(p45wh1, p45wh); + //illegal: assign(p45wh, pwh); + + assign(p90wh, p90); + //illegal: assign(p90wh, p45); + //illegal: assign(p90wh, p); + assign(p90wh1, p90wh); + //illegal: assign(p90wh, p45wh); + //illegal: assign(p90wh, pwh); + pts.clear(); + pts.push_back(point_data<int>(0, 0)); + pts.push_back(point_data<int>(3, 0)); + pts.push_back(point_data<int>(0, 1)); + p.set(pts.begin(), pts.end()); + std::cout << std::endl; std::cout << (area(p90)); + std::cout << std::endl; std::cout << (area(p45)); + std::cout << std::endl; std::cout << (area(p)); + std::cout << std::endl; std::cout << (area(p90wh)); + std::cout << std::endl; std::cout << (area(p45wh)); + std::cout << std::endl; std::cout << (area(pwh)); + std::cout << std::endl; + point_data<int> pt(1, 1); + std::cout << contains(p, pt) << std::endl; + std::cout << contains(p90, pt) << std::endl; + + interval_data<int> ivl = construct<interval_data<int> >(0, 10); + std::cout << get(ivl, LOW) << std::endl; + set(ivl, HIGH, 20); + + std::cout << perimeter(p) << std::endl; + if(winding(p) == LOW) std::cout << "LOW" << std::endl; + if(winding(p) == HIGH) std::cout << "HIGH" << std::endl; + rectangle_data<polygon_long_long_type> rd; + std::cout << extents(rd, p) << std::endl; + std::cout << rd << std::endl; + + boolean_op::testBooleanOr<int>(); + + std::vector<rectangle_data<int> > rects1, rects2; + rects2.push_back(rectangle_data<int>(0, 0, 10, 10)); + print_is_polygon_90_set_concept((polygon_90_set_data<int>())); + print_is_mutable_polygon_90_set_concept((polygon_90_set_data<int>())); + print_is_polygon_90_set_concept((polygon_90_data<int>())); + print_is_polygon_90_set_concept((std::vector<polygon_90_data<int> >())); + assign(rects1, rects2); + polygon_90_set_data<int> ps90; + assign(ps90, rects2); + assign(rects2, ps90); + assign(ps90, p90); + assign(rects2, p90); + std::cout << p90 << std::endl; + for(unsigned int i = 0; i < rects2.size(); ++i) { + std::cout << rects2[i] << std::endl; + } + bloat(rects2, 10); + shrink(rects2[0], 10); + for(unsigned int i = 0; i < rects2.size(); ++i) { + std::cout << rects2[i] << std::endl; + } + move(rects2[0], HORIZONTAL, 30); + assign(rects1, rects2 + p90); + std::cout << "result of boolean or\n"; + for(unsigned int i = 0; i < rects1.size(); ++i) { + std::cout << rects1[i] << std::endl; + } + rects1 -= p90; + std::cout << "result of boolean not\n"; + for(unsigned int i = 0; i < rects1.size(); ++i) { + std::cout << rects1[i] << std::endl; + } + rects1 += p90; + std::cout << "result of boolean OR\n"; + for(unsigned int i = 0; i < rects1.size(); ++i) { + std::cout << rects1[i] << std::endl; + } + rects1 *= p90; + std::cout << "result of boolean AND\n"; + for(unsigned int i = 0; i < rects1.size(); ++i) { + std::cout << rects1[i] << std::endl; + } + rects1 ^= rects2; + std::cout << "result of boolean XOR\n"; + for(unsigned int i = 0; i < rects1.size(); ++i) { + std::cout << rects1[i] << std::endl; + } + rects2.clear(); + get_max_rectangles(rects2, p90); + std::cout << "result of max rectangles\n"; + for(unsigned int i = 0; i < rects2.size(); ++i) { + std::cout << rects2[i] << std::endl; + } + rects2.clear(); + //operator += and -= don't support polygons, so + and - should not exist +// rects2 += p90 + 6; +// std::cout << "result of resize\n"; +// for(unsigned int i = 0; i < rects2.size(); ++i) { +// std::cout << rects2[i] << std::endl; +// } +// std::cout << "result of resize\n"; + std::vector<polygon_90_with_holes_data<int> > polyswh1, polyswh2; +// polyswh1 += p90 -2; +// for(unsigned int i = 0; i < polyswh1.size(); ++i) { +// std::cout << polyswh1[i] << std::endl; +// } +// std::cout << "result of resize\n"; + std::vector<polygon_90_data<int> > polys1, polys2; + polys1 += p90; + polys1 -= 2; +// polys1 += p90 -2; + for(unsigned int i = 0; i < polys1.size(); ++i) { + std::cout << polys1[i] << std::endl; + } + + boolean_op_45<int>::testScan45(std::cout); + polygon_45_formation<int>::testPolygon45Formation(std::cout); + polygon_45_formation<int>::testPolygon45Tiling(std::cout); + + axis_transformation atr; + transform(p, atr); + transform(p45, atr); + transform(p90, atr); + transform(pwh, atr); + transform(p45wh, atr); + transform(p90wh, atr); + scale_up(p, 2); + scale_up(p45, 2); + scale_up(p90, 2); + scale_up(pwh, 2); + scale_up(p45wh, 2); + scale_up(p90wh, 2); + scale_down(p, 2); + scale_down(p45, 2); + scale_down(p90, 2); + scale_down(pwh, 2); + scale_down(p45wh, 2); + scale_down(p90wh, 2); + std::vector<polygon_45_data<int> > p45s1, p45s2; + std::cout << equivalence(p45s1, p45s2) << std::endl; + std::cout << equivalence(p45, p45wh) << std::endl; + std::cout << equivalence(p90, p45wh) << std::endl; + gtl::assign(p45s1, p90); + p90 = polys1[0]; + move(p90, orientation_2d(HORIZONTAL), 8); + std::cout << p90 << std::endl << p45wh << std::endl; + polygon_45_set_data<int> ps45 = p90 + p45wh; + assign(p45s1, ps45); + std::cout << "result\n"; + for(unsigned int i = 0; i < p45s1.size(); ++i) { + std::cout << p45s1[i] << std::endl; + } + std::cout << equivalence(p, pwh) << std::endl; + std::cout << equivalence(p90, pwh) << std::endl; + std::cout << equivalence(p45, pwh) << std::endl; + std::cout << equivalence(pwh, pwh) << std::endl; + p + pwh; + p90 + pwh; + p45 + pwh; + std::cout << testRectangle() << std::endl; + std::cout << testPolygon() << std::endl; + std::cout << testPropertyMerge() << std::endl; + std::cout << testPolygonAssign() << std::endl; + std::cout << testPolygonWithHoles() << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationRect(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationP1(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationP2(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationPolys(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationSelfTouch1(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationSelfTouch2(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationSelfTouch3(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testSegmentIntersection(std::cout)) << std::endl; + std::cout << (property_merge<int, int>::test_insertion(std::cout)) << std::endl; + std::cout << (line_intersection<int>::test_verify_scan(std::cout)) << std::endl; + std::cout << (line_intersection<int>::test_validate_scan(std::cout)) << std::endl; + std::cout << (scanline<int, int>::test_scanline(std::cout)) << std::endl; + std::cout << (property_merge<int, int>::test_merge(std::cout)) << std::endl; + std::cout << (property_merge<int, int>::test_intersection(std::cout)) << std::endl; + std::cout << (polygon_arbitrary_formation<int>::testPolygonArbitraryFormationColinear(std::cout)) << std::endl; + std::cout << (property_merge<int, int>::test_manhattan_intersection(std::cout)) << std::endl; + std::cout << (test_arbitrary_boolean_op<int>(std::cout)) << std::endl; + } + { + polygon_set_data<int> psd; + rectangle_data<int> rect; + set_points(rect, point_data<int>(0, 0), point_data<int>(10, 10)); + psd.insert(rect); + polygon_set_data<int> psd2; + set_points(rect, point_data<int>(5, 5), point_data<int>(15, 15)); + psd2.insert(rect); + std::vector<polygon_data<int> > pv; + polygon_set_data<int> psd3; + psd3 = psd + psd2; + psd3.get(pv); + for(unsigned int i = 0; i < pv.size(); ++i) { + std::cout << pv[i] << std::endl; + } + psd += psd2; + pv.clear(); + psd3.get(pv); + for(unsigned int i = 0; i < pv.size(); ++i) { + std::cout << pv[i] << std::endl; + } + } + { + polygon_90_set_data<int> psd; + rectangle_data<int> rect; + set_points(rect, point_data<int>(0, 0), point_data<int>(10, 10)); + psd.insert(rect); + polygon_90_set_data<int> psd2; + set_points(rect, point_data<int>(5, 5), point_data<int>(15, 15)); + psd2.insert(rect); + std::vector<polygon_90_data<int> > pv; + interact(psd, psd2); + assign(pv, psd); + for(unsigned int i = 0; i < pv.size(); ++i) { + std::cout << pv[i] << std::endl; + } + + connectivity_extraction_90<int> ce; + ce.insert(pv[0]); + ce.insert(psd2); + std::vector<std::set<int> > graph(2); + ce.extract(graph); + if(graph[0].size() == 1) std::cout << "connectivity extraction is alive\n"; + + //std::vector<rectangle_data<polygon_long_long_type> > lobs; + //get_max_rectangles(lobs, psd); + //if(lobs.size() == 1) std::cout << "max rectangles is alive\n"; + + std::vector<rectangle_data<int> > rv; + rv.push_back(rect); + set_points(rect, point_data<int>(0, 0), point_data<int>(10, 10)); + rv.push_back(rect); + self_intersect(rv); + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + + assign(rv, rv + 1); + std::cout << rv.size() << std::endl; + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + assign(rv, rv - 1); + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + rv += 1; + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + rv -= 1; + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + rv.clear(); + set_points(rect, point_data<int>(0, 0), point_data<int>(10, 10)); + rv.push_back(rect); + set_points(rect, point_data<int>(12, 12), point_data<int>(20, 20)); + rv.push_back(rect); + grow_and(rv, 7); + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + std::cout << area(rv) << std::endl; + std::cout << area(rv) << std::endl; + + scale_up(rv, 10); + std::cout << area(rv) << std::endl; + scale_down(rv, 7); + std::cout << area(rv) << std::endl; + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + keep(rv, 290, 300, 7, 24, 7, 24); + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + keep(rv, 300, 310, 7, 24, 7, 24); + if(rv.empty()) std::cout << "keep is alive\n"; + } + { +// typedef int Unit; +// typedef point_data<int> Point; +// typedef interval_data<int> Interval; +// typedef rectangle_data<int> Rectangle; +// typedef polygon_90_data<int> Polygon; +// typedef polygon_90_with_holes_data<int> PolygonWithHoles; +// typedef polygon_45_data<int> Polygon45; +// typedef polygon_45_with_holes_data<int> Polygon45WithHoles; +// typedef polygon_90_set_data<int> PolygonSet; +// //typedef polygon_45_set_data<int> Polygon45Set; +// typedef axis_transformation AxisTransform; +// typedef transformation<int> Transform; + //test polygon45 area, polygon45 with holes area + std::vector<Point> pts; + pts.clear(); + pts.push_back(Point(10, 10)); + pts.push_back(Point(15, 10)); + pts.push_back(Point(10, 15)); + Polygon45 polyHole; + polyHole.set(pts.begin(), pts.end()); + pts.clear(); + pts.push_back(Point(10, 0)); + pts.push_back(Point(20, 10)); + pts.push_back(Point(20, 30)); + pts.push_back(Point(0, 50)); + pts.push_back(Point(0, 10)); + Polygon45WithHoles polyWHoles; + polyWHoles.set(pts.begin(), pts.end()); + polyWHoles.set_holes(&polyHole, (&polyHole)+1); + std::cout << polyWHoles << std::endl; + std::cout << area(polyWHoles) << std::endl; + std::cout << area(polyWHoles) << std::endl; + //test polygon45, polygon45with holes transform + AxisTransform atr(AxisTransform::EAST_SOUTH); + Polygon45WithHoles p45wh(polyWHoles); + transform(polyWHoles, atr); + std::cout << polyWHoles << std::endl; + Transform tr(atr); + tr.invert(); + transform(polyWHoles, tr); + std::cout << polyWHoles << std::endl; + if(area(polyWHoles) != 687.5) return 1; + //test polygon, polygon with holes transform + Polygon ph; + assign(ph, Rectangle(10, 10, 20, 20)); + PolygonWithHoles pwh; + assign(pwh, Rectangle(0, 0, 100, 100)); + pwh.set_holes(&ph, (&ph)+1); + std::cout << area(pwh) << std::endl; + transform(pwh, atr); + std::cout << pwh << std::endl; + std::cout << area(pwh) << std::endl; + transform(pwh, tr); + std::cout << pwh << std::endl; + std::cout << area(pwh) << std::endl; + if(area(pwh) != 9900) return 1; + + //test point scale up / down + Point pt(10, 10); + scale_up(pt, 25); + if(pt != Point(250, 250)) return 1; + std::cout << pt << std::endl; + scale_down(pt, 25); + if(pt != Point(10, 10)) return 1; + std::cout << pt << std::endl; + scale_down(pt, 25); + if(pt != Point(0, 0)) return 1; + std::cout << pt << std::endl; + + //test polygon, polygon with holes scale up down + PolygonWithHoles tmpPwh(pwh); + scale_up(pwh, 25); + std::cout << pwh << std::endl; + scale_down(pwh, 25); + if(area(pwh) != area(tmpPwh)) return 1; + std::cout << pwh << std::endl; + scale_down(pwh, 25); + std::cout << pwh << std::endl; + //test polygon45, polygon45 with holes is45 + std::cout << is_45(polyHole) << std::endl; + if(is_45(polyHole) != true) return 1; + pts.clear(); + pts.push_back(Point(10, 10)); + pts.push_back(Point(15, 10)); + pts.push_back(Point(10, 16)); + polyHole.set(pts.begin(), pts.end()); + std::cout << is_45(polyHole) << std::endl; + if(is_45(polyHole) != false) return 1; + //test polygon45, polygon45 with holes snap 45 + snap_to_45(polyHole); + std::cout << is_45(polyHole) << std::endl; + if(is_45(polyHole) != true) return 1; + std::cout << polyHole << std::endl; + //test polygon45, polygon45 with holes scalue up down + scale_up(polyHole, 10000); + std::cout << polyHole << std::endl; + scale_down(polyHole, 3); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 5); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 7); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 13); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_up(polyHole, 3); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + pts.clear(); + pts.push_back(Point(11, 1)); + pts.push_back(Point(21, 11)); + pts.push_back(Point(11, 21)); + pts.push_back(Point(1, 11)); + polyHole.set(pts.begin(), pts.end()); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 3); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_up(polyHole, 10000); + std::cout << polyHole << std::endl; + scale_down(polyHole, 3); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 5); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 7); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 13); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_up(polyHole, 3); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + scale_down(polyHole, 2); + std::cout << is_45(polyHole) << " " << polyHole << std::endl; + if(is_45(polyHole) != true) return 1; + + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_up(polyWHoles, 100013); + std::cout << polyWHoles << std::endl; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 3); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + scale_down(polyWHoles, 2); + std::cout << is_45(polyWHoles) << " " << polyWHoles << std::endl; + if(is_45(polyWHoles) != true) return 1; + + std::cout << (boolean_op_45<Unit>::testScan45(std::cout)) << std::endl; + std::cout << (polygon_45_formation<Unit>::testPolygon45Formation(std::cout)) << std::endl; + std::cout << (polygon_45_formation<Unit>::testPolygon45Tiling(std::cout)) << std::endl; + + + { + PolygonSet ps; + Rectangle rect; + ps.insert(Rectangle(0, 0, 10, 10)); + std::cout << area(ps) << std::endl; + if(area(ps) != 100) return 1; + scale_up(ps, 3); + std::cout << area(ps) << std::endl; + if(area(ps) != 900) return 1; + scale_down(ps, 2); + std::cout << area(ps) << std::endl; + if(area(ps) != 225) return 1; + transform(ps, atr); + std::vector<Rectangle> rv; + rv.clear(); + ps.get(rv); + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + transform(ps, tr); + rv.clear(); + ps.get(rv); + if(rv.size() == 1) { + assign(rect, rv.back()); + std::cout << rect << std::endl; + } + } + //test polygon45set transform + pts.clear(); + pts.push_back(Point(10, 10)); + pts.push_back(Point(15, 10)); + pts.push_back(Point(10, 15)); + polyHole.set(pts.begin(), pts.end()); + Polygon45Set ps451, ps452; + ps451.insert(polyHole); + ps452 = ps451; + std::cout << (ps451 == ps452) << std::endl; + if(ps451 != ps452) return 1; + ps451.transform(atr); + std::cout << (ps451 == ps452) << std::endl; + if(ps451 == ps452) return 1; + ps451.transform(tr); + std::cout << (ps451 == ps452) << std::endl; + if(ps451 != ps452) return 1; + + //test polygon45set area + std::cout << area(ps451) << std::endl; + if(area(ps451) != 12.5) return 1; + //test polygon45set scale up down + ps451.scale_up(3); + std::cout << area(ps451) << std::endl; + if(area(ps451) != 112.5) return 1; + ps451.scale_down(2); + std::cout << area(ps451) << std::endl; + if(area(ps451) != 32) return 1; + //test polygonset scalue up down + } + { + std::cout << (testPolygon45SetRect()) << std::endl; + testPolygon45SetPerterbation(); //re-enable after non-intersection fix + testPolygon45Set(); + testPolygon45SetDORA(); //re-enable after non-intersection fix + polygon_45_set_data<int> ps45_1, ps45_2, ps45_3; + ps45_1.insert(rectangle_data<int>(0, 0, 10, 10)); + ps45_2.insert(rectangle_data<int>(5, 5, 15, 15)); + std::vector<polygon_45_data<int> > p45s; + ps45_3 = ps45_1 | ps45_2; + ps45_3.get(p45s); + if(p45s.size()) std::cout << p45s[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + p45s.clear(); + ps45_3 = ps45_1 + ps45_2; + ps45_3.get(p45s); + if(p45s.size()) std::cout << p45s[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + p45s.clear(); + ps45_3 = ps45_1 * ps45_2; + ps45_3.get(p45s); + if(p45s.size()) std::cout << p45s[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + p45s.clear(); + ps45_3 = ps45_1 - ps45_2; + ps45_3.get(p45s); + if(p45s.size()) std::cout << p45s[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + p45s.clear(); + ps45_3 = ps45_1 ^ ps45_2; + ps45_3.get(p45s); + if(p45s.size() == 2) std::cout << p45s[0] << " " << p45s[1] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + std::vector<point_data<int> > pts; + pts.clear(); + pts.push_back(point_data<int>(7, 0)); + pts.push_back(point_data<int>(20, 13)); + pts.push_back(point_data<int>(0, 13)); + pts.push_back(point_data<int>(0, 0)); + polygon_45_data<int> p45_1(pts.begin(), pts.end()); + ps45_3.clear(); + ps45_3.insert(p45_1); + p45s.clear(); + ps45_3.get(p45s); + if(p45s.size()) std::cout << p45s[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + ps45_3 += 1; + p45s.clear(); + ps45_3.get(p45s); + if(p45s.size()) std::cout << p45s[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + ps45_3 -= 1; + p45s.clear(); + ps45_3.get(p45s); + if(p45s.size()) std::cout << p45s[0] << std::endl; + else { + std::cout << "test failed\n"; + return 1; + } + } + { + polygon_90_set_data<int> p90sd; + p90sd.insert(rectangle_data<int>(0, 0, 10, 10)); + std::vector<rectangle_data<int> > rects; + std::vector<polygon_90_data<int> > polys90; + std::vector<polygon_90_with_holes_data<int> > pwhs90; + assign(rects, p90sd); + assign(polys90, p90sd); + assign(pwhs90, p90sd); + std::cout << equivalence(rects, polys90) << std::endl; + std::cout << equivalence(pwhs90, polys90) << std::endl; + pwhs90.clear(); + assign(pwhs90, polys90); + std::cout << equivalence(pwhs90, polys90) << std::endl; + } + { + polygon_45_set_data<int> p45sd; + p45sd.insert(rectangle_data<int>(0, 0, 10, 10)); + std::vector<rectangle_data<int> > rects; + std::vector<polygon_45_data<int> > polys45; + std::vector<polygon_45_with_holes_data<int> > pwhs45; + get_trapezoids(polys45, p45sd); + assign(polys45, p45sd); + assign(pwhs45, p45sd); + std::cout << equivalence(pwhs45, polys45) << std::endl; + pwhs45.clear(); + assign(pwhs45, polys45); + std::cout << equivalence(pwhs45, polys45) << std::endl; + } + { + polygon_set_data<int> psd; + psd.insert(rectangle_data<int>(0, 0, 10, 10)); + std::vector<polygon_data<int> > polys; + std::vector<polygon_with_holes_data<int> > pwhs; + assign(polys, psd); + assign(pwhs, psd); + std::cout << equivalence(pwhs, polys) << std::endl; + pwhs.clear(); + assign(pwhs, polys); + std::cout << equivalence(pwhs, polys) << std::endl; + } + { + polygon_90_set_data<int> ps1(HORIZONTAL), ps2(VERTICAL); + ps1 += rectangle_data<int>(0, 0, 10, 120); + assign(ps1, ps2); + std::cout << equivalence(ps1, ps2) << std::endl; + } + { + std::vector<rectangle_data<polygon_long_long_type> > lobs, input; + input.push_back(rectangle_data<polygon_long_long_type>(0, 0, 10, 10)); + input.push_back(rectangle_data<polygon_long_long_type>(10, 5, 15, 15)); + get_max_rectangles(lobs, input); + if(lobs.size() == 3) std::cout << "max rectangles is correct\n"; + } + { + polygon_set_data<int> ps1, ps2, ps3; + ps1.insert(rectangle_data<int>(0, 0, 10, 10)); + ps2.insert(rectangle_data<int>(0, 0, 15, 5)); + ps3.insert(rectangle_data<int>(0, 0, 20, 2)); + std::cout << area(ps1 + ps2) << std::endl; + keep(ps1, 0, 100, 0, 100, 0, 100); + if(empty(ps1)) return 1; + rectangle_data<int> bbox; + extents(bbox, ps1); + std::cout << bbox << std::endl; + //resize(ps1, 1); + //shrink(ps1, 1); + //bloat(ps1, 1); + scale_up(ps1, 2); + scale_down(ps1, 2); + axis_transformation atr; + transform(ps1, atr); + std::cout << area(ps1) << std::endl; + if(area(ps1) != 100) return 1; + clear(ps1); + if(!empty(ps1)) return 1; + ps1 = ps2 * ps3; + ps1 *= ps2; + ps1 - ps2; + ps1 -= ps2; + ps1 ^ ps2; + ps1 ^= ps2; + ps1 | ps2; + ps1 |= ps2; + } + { + polygon_45_set_data<int> ps45_1, ps45_2; + ps45_1.insert(rectangle_data<int>(0, 0, 10, 10)); + keep(ps45_1, 0, 1000, 0, 1000, 0, 1000); + std::cout << area(ps45_1) << std::endl; + std::cout << empty(ps45_1) << std::endl; + rectangle_data<int> bbox; + extents(bbox, ps45_1); + std::cout << bbox << std::endl; + resize(ps45_1, 1); + shrink(ps45_1, 1); + bloat(ps45_1, 1); + scale_up(ps45_1, 2); + scale_down(ps45_1, 2); + axis_transformation atr; + transform(ps45_1, atr); + std::cout << area(ps45_1) << std::endl; + if(area(ps45_1) != 144) return 1; + clear(ps45_1); + if(!empty(ps45_1)) return 1; + } + { + std::vector<polygon_45_data<int> > p45v; + p45v + p45v; + p45v *= p45v; + p45v += p45v; + p45v - p45v; + p45v -= p45v; + p45v ^ p45v; + p45v ^= p45v; + p45v | p45v; + p45v |= p45v; + p45v + 1; + p45v += 1; + p45v - 1; + p45v -= 1; + p45v + (p45v + p45v); + } + { + polygon_45_set_data<int> ps45; + polygon_90_set_data<int> ps90; + std::vector<polygon_90_with_holes_data<int> > p90whv; + ps45.insert(ps90); + ps45.insert(p90whv); + ps45.insert(p90whv + p90whv); + + ps45.insert(polygon_90_with_holes_data<int>()); + polygon_with_holes_data<int> pwh; + snap_to_45(pwh); + } + { + polygon_90_set_data<int> ps90_1, ps90_2; + ps90_1.insert(rectangle_data<int>(0, 0, 10, 10)); + keep(ps90_1, 0, 1000, 0, 1000, 0, 1000); + std::cout << area(ps90_1) << std::endl; + std::cout << empty(ps90_1) << std::endl; + rectangle_data<int> bbox; + extents(bbox, ps90_1); + std::cout << bbox << std::endl; + resize(ps90_1, 1); + shrink(ps90_1, 1); + bloat(ps90_1, 1); + scale_up(ps90_1, 2); + scale_down(ps90_1, 2); + scale(ps90_1, anisotropic_scale_factor<double>(2, 2)); + scale(ps90_1, anisotropic_scale_factor<double>(0.5, 0.5)); + axis_transformation atr; + transform(ps90_1, atr); + std::cout << area(ps90_1) << std::endl; + if(area(ps90_1) != 144) return 1; + clear(ps90_1); + if(!empty(ps90_1)) return 1; + } + if(!nonInteger45StessTest()) return 1; + { + using namespace gtl; + typedef polygon_45_property_merge<int, int> p45pm; + p45pm::MergeSetData msd; + polygon_45_set_data<int> ps; + ps += rectangle_data<int>(0, 0, 10, 10); + p45pm::populateMergeSetData(msd, ps.begin(), ps.end(), 444); + ps.clear(); + ps += rectangle_data<int>(5, 5, 15, 15); + p45pm::populateMergeSetData(msd, ps.begin(), ps.end(), 333); + std::map<std::set<int>, polygon_45_set_data<int> > result; + p45pm::performMerge(result, msd); + int i = 0; + for(std::map<std::set<int>, polygon_45_set_data<int> >::iterator itr = result.begin(); + itr != result.end(); ++itr) { + for(std::set<int>::const_iterator itr2 = (*itr).first.begin(); + itr2 != (*itr).first.end(); ++itr2) { + std::cout << *itr2 << " "; + } std::cout << " : "; + std::cout << area((*itr).second) << std::endl; + if(i == 1) { + if(area((*itr).second) != 100) return 1; + } else + if(area((*itr).second) != 300) return 1; + ++i; + } + + + property_merge_45<int, int> pm; + pm.insert(rectangle_data<int>(0, 0, 10, 10), 444); + pm.insert(rectangle_data<int>(5, 5, 15, 15), 333); + std::map<std::set<int>, polygon_45_set_data<int> > mp; + pm.merge(mp); + i = 0; + for(std::map<std::set<int>, polygon_45_set_data<int> >::iterator itr = mp.begin(); + itr != mp.end(); ++itr) { + for(std::set<int>::const_iterator itr2 = (*itr).first.begin(); + itr2 != (*itr).first.end(); ++itr2) { + std::cout << *itr2 << " "; + } std::cout << " : "; + std::cout << area((*itr).second) << std::endl; + if(i == 1) { + if(area((*itr).second) != 25) return 1; + } else + if(area((*itr).second) != 75) return 1; + ++i; + } + std::map<std::vector<int>, polygon_45_set_data<int> > mp2; + pm.merge(mp2); + i = 0; + for(std::map<std::vector<int>, polygon_45_set_data<int> >::iterator itr = mp2.begin(); + itr != mp2.end(); ++itr) { + for(std::vector<int>::const_iterator itr2 = (*itr).first.begin(); + itr2 != (*itr).first.end(); ++itr2) { + std::cout << *itr2 << " "; + } std::cout << " : "; + std::cout << area((*itr).second) << std::endl; + if(i == 1) { + if(area((*itr).second) != 25) return 1; + } else + if(area((*itr).second) != 75) return 1; + ++i; + } + } + { + std::cout << trapezoid_arbitrary_formation<int>::testTrapezoidArbitraryFormationRect(std::cout) << std::endl; + std::cout << trapezoid_arbitrary_formation<int>::testTrapezoidArbitraryFormationP1(std::cout) << std::endl; + std::cout << trapezoid_arbitrary_formation<int>::testTrapezoidArbitraryFormationP2(std::cout) << std::endl; + std::cout << trapezoid_arbitrary_formation<int>::testTrapezoidArbitraryFormationPolys(std::cout) << std::endl; + std::cout << polygon_arbitrary_formation<int>::testPolygonArbitraryFormationSelfTouch1(std::cout) << std::endl; + std::cout << trapezoid_arbitrary_formation<int>::testTrapezoidArbitraryFormationSelfTouch1(std::cout) << std::endl; + typedef rectangle_data<int> Rectangle; + polygon_set_data<int> ps; + ps += Rectangle(0, 1, 10, 11); + ps += Rectangle(5, 6, 15, 16); + std::vector<polygon_data<int> > polys; + ps.get_trapezoids(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + ps.transform(axis_transformation(axis_transformation::FLIP_X)); + polys.clear(); + ps.get_trapezoids(polys); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + polys.clear(); + ps.get_trapezoids(polys, HORIZONTAL); + for(unsigned int i = 0; i < polys.size(); ++i) { + std::cout << polys[i] << std::endl; + } + } + + if(!test_aa_touch()) { + std::cout << "test_aa_touch failed\n"; + return 1; + } + if(!test_aa_touch_ur()) { + std::cout << "test_aa_touch_ur failed\n"; + return 1; + } + if(!test_aa_touch_ur()) { + std::cout << "test_aa_touch_ur failed\n"; + return 1; + } + if(!test_aa_touch_r()) { + std::cout << "test_aa_touch_r failed\n"; + return 1; + } + if(!test_aa_touch_boundaries()) { + std::cout << "test_aa_touch_boundaries failed\n"; + return 1; + } + if(!test_aa_concept_interact()) { + std::cout << "test_aa_concept_interact failed\n"; + return 1; + } + + { + polygon_set_data<int> ps; + polygon_90_set_data<int> ps90; + rectangle_data<int> rect(0, 1, 10, 100); + std::vector<polygon_data<int> > rupolys, rupolys45; + ps.insert(rect); + ps90.insert(rect); + ps.bloat(10); + ps90.bloat(10, 10, 10, 10); + rupolys.clear(); + rupolys45.clear(); + ps.get(rupolys); + ps90.get(rupolys45); + std::cout << rupolys[0] << std::endl; + std::cout << rupolys45[0] << std::endl; + if(!equivalence(ps, ps90)) { + std::cout << "test manhattan vs general resize up failed\n"; + return 1; + } + ps.shrink(10); + ps90.shrink(10, 10, 10, 10); + if(!equivalence(ps, rect)) { + std::cout << "test manhattan vs general resize down failed\n"; + return 1; + } + rectangle_data<int> rect2(3, 4, 6, 80); + ps -= rect2; + ps90 -= rect2; + ps.bloat(1); + ps90.bloat(1, 1, 1, 1); + if(!equivalence(ps, ps90)) { + std::cout << "test manhattan vs general with hole resize up failed\n"; + return 1; + } + ps.shrink(1); + ps90.shrink(1, 1, 1, 1); + if(!equivalence(ps, ps90)) { + std::cout << "test manhattan vs general with hole resize down failed\n"; + return 1; + } + ps.clear(); + polygon_45_data<int> poly; + std::vector<point_data<int> > pts; + pts.push_back(point_data<int>(0, 0)); + pts.push_back(point_data<int>(10, 0)); + pts.push_back(point_data<int>(0, 10)); + polygon_45_set_data<int> ps45; + set_points(poly, pts.begin(), pts.end()); + ps.insert(poly); + ps45.insert(poly); + ps.bloat(9); + ps45.resize(9); + rupolys.clear(); + rupolys45.clear(); + ps.get(rupolys); + ps45.get(rupolys45); + std::cout << rupolys[0] << std::endl; + std::cout << rupolys45[0] << std::endl; + pts.clear(); + pts.push_back(point_data<int>(32, -9)); + pts.push_back(point_data<int>(-9, 32)); + pts.push_back(point_data<int>(-9, -9)); + set_points(poly, pts.begin(), pts.end()); + if(!equivalence(ps, poly)) { + std::cout << "test general resize up failed\n"; + return 1; + } + // this test is waived due to rounding differences between 45 and general resizing + // general resizing is computing floating point coordinates for the intersection + // and rounding those to closest while 45 is computing the normal point and rounding + // that to closest, it turns out to result in different intersection point + // we want the general to be more accurate to avoid artifacts + //if(!equivalence(ps, ps45)) { + // std::cout << "test 45 vs general resize up failed\n"; + // return 1; + //} + ps.shrink(9); + ps45.resize(-9); + if(!equivalence(ps, ps45)) { + std::cout << "test 45 vs general resize down failed\n"; + return 1; + } + pts.clear(); + pts.push_back(point_data<int>(1, 1)); + pts.push_back(point_data<int>(7, 1)); + pts.push_back(point_data<int>(1, 7)); + set_points(poly, pts.begin(), pts.end()); + ps.insert(poly, true); + ps45.insert(poly, true); + ps.bloat(1); + ps45.resize(1); + rupolys.clear(); + rupolys45.clear(); + ps.get(rupolys); + ps45.get(rupolys45); + std::cout << rupolys[0] << std::endl; + std::cout << rupolys45[0] << std::endl; + pts.clear(); + pts.push_back(point_data<int>(12, -1)); + pts.push_back(point_data<int>(5, 6)); + pts.push_back(point_data<int>(5, 2)); + pts.push_back(point_data<int>(2, 2)); + pts.push_back(point_data<int>(2, 5)); + pts.push_back(point_data<int>(5, 2)); + pts.push_back(point_data<int>(5, 6)); + pts.push_back(point_data<int>(-1, 12)); + pts.push_back(point_data<int>(-1, -1)); + pts.push_back(point_data<int>(12, -1)); + set_points(poly, pts.begin(), pts.end()); + //waived + //if(!equivalence(ps, poly)) { + // std::cout << "test general resize up with holes failed\n"; + // return 1; + //} + //waived + //if(!equivalence(ps, ps45)) { + // std::cout << "test 45 vs general resize up with holes failed\n"; + // return 1; + //} + ps.shrink(1); + ps45.resize(-1); + if(!equivalence(ps, ps45)) { + std::cout << "test 45 vs general resize down with holes failed\n"; + return 1; + } + ps.shrink(10); + ps45.resize(-10); + if(!equivalence(ps, ps45)) { + std::cout << "test 45 vs general resize down 2 with holes failed\n"; + return 1; + } + } + + { + + Point pts[] = {construct<Point>(1565, 5735), + construct<Point>(915, 5735), + construct<Point>(915, 7085), + construct<Point>(1565, 7085) }; + Polygon poly; + set_points(poly, pts, pts+4); + bool ret=gtl::contains(poly,gtl::construct<Point>(920, 7080)); + if(!ret) { + std::cout << "contains failed!" << std::endl; + return 1; + } + polygon_data<int> poly_aa; + set_points(poly_aa, pts, pts+4); + ret=gtl::contains(poly,gtl::construct<Point>(920, 7080)); + if(!ret) { + std::cout << "contains 90 failed!" << std::endl; + return 1; + } + polygon_with_holes_data<int> pwh; + polygon_90_with_holes_data<int> p90wh; + Point pts2[] = {construct<Point>(565, 15735), + construct<Point>(15, 15735), + construct<Point>(15, 17085), + construct<Point>(565, 17085) }; + set_points(pwh, pts2, pts2+4); + set_points(p90wh, pts2, pts2+4); + pwh.set_holes(&poly_aa, (&poly_aa)+1); + p90wh.set_holes(&poly, (&poly)+1); + ret=gtl::contains(pwh,gtl::construct<Point>(920, 7080)); + if(ret) { + std::cout << "contains wh failed!" << std::endl; + return 1; + } + ret=gtl::contains(p90wh,gtl::construct<Point>(920, 7080)); + if(ret) { + std::cout << "contains 90wh failed!" << std::endl; + return 1; + } + std::reverse(pts, pts+4); + set_points(poly, pts, pts+4); + ret=gtl::contains(poly,gtl::construct<Point>(920, 7080)); + if(!ret) { + std::cout << "reverse contains failed!" << std::endl; + return 1; + } + } + { +// //MULTIPOLYGON +// ( +// ((200 400,100 400,100 300,200 400)), +// ((300 100,200 100,200 0,300 0,300 100)), +// ((600 700,500 700,500 600,600 700)), +// ((700 300,600 300,600 200,700 300)), +// ((800 500,700 600,700 500,800 500)), +// ((900 800,800 700,900 700,900 800)), +// ((1000 200,900 100,1000 100,1000 200)), +// ((1000 800,900 900,900 800,1000 800))), + int mp1 [7][2*4] = { + {200,400,100,400,100,300,200,400}, + {600,700,500,700,500,600,600,700}, + {700,300,600,300,600,200,700,300}, + {800,500,700,600,700,500,800,500}, + {900,800,800,700,900,700,900,800}, + {1000,200,900,100,1000,100,1000,200}, + {1000,800,900,900,900,800,1000,800} + }; + int mp11 [2*5] = {300,100,200,100,200,0,300,0,300,100}; + polygon_45_set_data<int> pset1; + polygon_45_set_data<int> pset2; + for(int i = 0; i < 7; ++i) { + addpoly(pset1, mp1[i], 4); + } + addpoly(pset1, mp11, 5); +// //MULTIPOLYGON +// ( +// ((200 800,100 800,100 700,200 700,200 800)), +// ((400 200,300 100,400 100,400 200)), +// ((400 800,300 700,400 700,400 800)), +// ((700 100,600 0,700 0,700 100)), +// ((700 200,600 200,600 100,700 200)), +// ((900 200,800 200,800 0,900 0,900 200)), +// ((1000 300,900 200,1000 200,1000 300))) + int mp2 [5][2*4] = { + {400,200,300,100,400,100,400,200}, + {400,800,300,700,400,700,400,800}, + {700,100,600,0,700,0,700,100}, + {700,200,600,200,600,100,700,200}, + {1000,300,900,200,1000,200,1000,300}, + }; + int mp21 [2*5] = {200,800,100,800,100,700,200,700,200,800}; + int mp22 [2*5] = {900,200,800,200,800,0,900,0,900,200}; + for(int i = 0; i < 5; ++i) { + addpoly(pset2, mp2[i], 4); + } + addpoly(pset2, mp21, 5); + addpoly(pset2, mp22, 5); + polygon_45_set_data<int> orr = pset1 + pset2; + polygon_45_set_data<int> inr = pset1 & pset2; + std::cout << area(orr)<<std::endl;; + std::cout << area(inr)<<std::endl;; + std::vector<polygon_45_with_holes_data<int> > polys; + assign(polys, orr); + std::cout << area(polys) << std::endl; + polygon_set_data<int> testbug; + testbug.insert(orr); + std::cout << area(testbug) << std::endl; + polygon_set_data<int> testbug2; + for(size_t i = 0; i < polys.size(); ++i) { + for(size_t j = 0; j < polys.size(); ++j) { + testbug2.clear(); + testbug2.insert(polys[i]); + testbug2.insert(polys[j]); + std::cout << i << " " << j << std::endl; + std::cout << polys[i] << std::endl; + std::cout << polys[j] << std::endl; + if(area(testbug2) == 0.0) { + std::cout << area(testbug2) << std::endl; + std::cout << "Self touch 45 through general interface failed!\n"; + return 1; + } + } + } + } + + { + polygon_set_data<int> t_eq; + t_eq.insert(rectangle_data<int>(0, 0, 5, 10)); + t_eq.insert(rectangle_data<int>(0, 5, 5, 10)); + std::cout << t_eq <<std::endl; + polygon_set_data<int> t_eq2; + t_eq2 += rectangle_data<int>(0, 0, 5, 10); + std::cout << area(t_eq) <<std::endl; + std::cout << area(t_eq2) <<std::endl; + std::cout << t_eq <<std::endl; + std::cout << t_eq2 <<std::endl; + if(t_eq != t_eq2) { + std::cout << "equivalence failed" << std::endl; + return 1; + } + } + + { + using namespace boost::polygon; + typedef point_data<int> Point; + typedef segment_data<int> Dls; + Point pt1(0, 0); + Point pt2(10, 10); + Point pt3(20, 20); + Point pt4(20, 0); + Dls dls1(pt1, pt2); + Dls dls2(pt1, pt3); + Dls dls3(pt1, pt4); + Dls dls4(pt2, pt1); + typedef std::vector<segment_data<int> > Dlss; + Dlss dlss, result; + dlss.push_back(dls1); + dlss.push_back(dls2); + dlss.push_back(dls3); + dlss.push_back(dls4); + rectangle_data<int> rect; + envelope_segments(rect, dlss.begin(), dlss.end()); + assert_s(area(rect) == 400.0, "envelope"); + intersect_segments(result, dlss.begin(), dlss.end()); + dlss.swap(result); + for (Dlss::iterator itr = dlss.begin(); itr != dlss.end(); ++itr) { + std::cout << *itr << std::endl; + } + assert_s(dlss.size() == 5, "intersection"); + Dls dls5(Point(0,5), Point(5,0)); + dlss.push_back(dls5); + std::cout << std::endl; + result.clear(); + intersect_segments(result, dlss.begin(), dlss.end()); + dlss.swap(result); + for (Dlss::iterator itr = dlss.begin(); itr != dlss.end(); ++itr) { + std::cout << *itr << std::endl; + } + assert_s(dlss.size() == 11, "intersection2"); + } + + { + using namespace boost::polygon; + std::vector<std::pair<std::size_t, segment_data<int> > > segs; + segment_data<int> sarray[2]; + sarray[0] = segment_data<int>(point_data<int>(0,0), point_data<int>(10,10)); + sarray[1] = segment_data<int>(point_data<int>(10,0), point_data<int>(0,10)); + intersect_segments(segs, sarray, sarray+2); + std::cout << segs.size() << std::endl; + assert_s(segs.size() == 4, "intersection3"); + } + + + /*New polygon_formation tests*/ + if(test_new_polygon_formation(0,NULL)){ + std::cerr << "[test_new_polygon_formation] failed" << std::endl; + return 1; + } + + if(test_new_polygon_formation_marginal_threshold(0,NULL)){ + std::cerr << "[test_new_polygon_formation_marginal_threshold] failed" + << std::endl; + return 1; + } + + std::cout << "ALL TESTS COMPLETE\n"; + return 0; +} diff --git a/src/boost/libs/polygon/test/polygon_90_data_test.cpp b/src/boost/libs/polygon/test/polygon_90_data_test.cpp new file mode 100644 index 00000000..2b61d41e --- /dev/null +++ b/src/boost/libs/polygon/test/polygon_90_data_test.cpp @@ -0,0 +1,52 @@ +// Boost.Polygon library polygon_90_data_test.cpp file + +// Copyright Andrii Sydorchuk 2015. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/polygon.hpp> +#include <iostream> +#include <vector> + +using namespace boost::polygon; + +void polygon_90_data_test() +{ + typedef polygon_90_data<int> polygon_type; + typedef polygon_traits_90<polygon_type>::point_type point_type; + typedef polygon_type::iterator_type iterator_type; + + std::vector<point_type> data; + data.push_back(point_type(0, 0)); // 1 + data.push_back(point_type(10, 0)); // 2 + data.push_back(point_type(10, 10)); // 3 + data.push_back(point_type(0, 10)); // 4 + + polygon_type polygon; + polygon.set(data.begin(), data.end()); + + std::cout << "Interesting: " << std::endl; + for (polygon_type::compact_iterator_type it = polygon.begin_compact(); it != polygon.end_compact(); ++it) { + std::cout << *it << " "; + } + std::cout << std::endl; + + iterator_type it = polygon.begin(); + for (int i = 0; i < 2; i++) { + it++; + } + + iterator_type it_3rd = it; + it++; + BOOST_TEST(it != it_3rd); +} + +int main() +{ + polygon_90_data_test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/polygon_interval_test.cpp b/src/boost/libs/polygon/test/polygon_interval_test.cpp new file mode 100644 index 00000000..070d34f7 --- /dev/null +++ b/src/boost/libs/polygon/test/polygon_interval_test.cpp @@ -0,0 +1,271 @@ +// Boost.Polygon library polygon_interval_test.cpp file + +// Copyright Andrii Sydorchuk 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/interval_concept.hpp> +#include <boost/polygon/interval_data.hpp> +#include <boost/polygon/interval_traits.hpp> + +using namespace boost::polygon; + +void interval_data_test() +{ + typedef interval_data<int> interval_type; + interval_type interval1(1, 2); + interval_type interval2; + interval2 = interval1; + + BOOST_TEST_EQ(interval1.low(), 1); + BOOST_TEST_EQ(interval1.high(), 2); + BOOST_TEST_EQ(interval1.get(LOW), 1); + BOOST_TEST_EQ(interval1.get(HIGH), 2); + BOOST_TEST(interval1 == interval2); + BOOST_TEST(!(interval1 != interval2)); + BOOST_TEST(!(interval1 < interval2)); + BOOST_TEST(!(interval1 > interval2)); + BOOST_TEST(interval1 <= interval2); + BOOST_TEST(interval1 >= interval2); + + interval1.low(2); + interval1.high(1); + BOOST_TEST_EQ(interval1.low(), 2); + BOOST_TEST_EQ(interval1.high(), 1); + BOOST_TEST(!(interval1 == interval2)); + BOOST_TEST(interval1 != interval2); + + interval2.set(LOW, 2); + interval2.set(HIGH, 1); + BOOST_TEST(interval1 == interval2); +} + +void interval_traits_test() +{ + typedef interval_data<int> interval_type; + + interval_type interval = interval_mutable_traits<interval_type>::construct(1, 2); + BOOST_TEST_EQ(interval_traits<interval_type>::get(interval, LOW), 1); + BOOST_TEST_EQ(interval_traits<interval_type>::get(interval, HIGH), 2); + + interval_mutable_traits<interval_type>::set(interval, LOW, 3); + interval_mutable_traits<interval_type>::set(interval, HIGH, 4); + BOOST_TEST_EQ(interval_traits<interval_type>::get(interval, LOW), 3); + BOOST_TEST_EQ(interval_traits<interval_type>::get(interval, HIGH), 4); +} + +template <typename T> +struct Interval { + T left; + T right; +}; + +namespace boost { +namespace polygon { + template <typename T> + struct geometry_concept< Interval<T> > { + typedef interval_concept type; + }; + + template <typename T> + struct interval_traits< Interval<T> > { + typedef T coordinate_type; + + static coordinate_type get(const Interval<T>& interval, direction_1d dir) { + return (dir == LOW) ? interval.left : interval.right; + } + }; + + template <typename T> + struct interval_mutable_traits< Interval<T> > { + typedef T coordinate_type; + + static void set(Interval<T>& interval, direction_1d dir, T value) { + (dir == LOW) ? interval.left = value : interval.right = value; + } + + static Interval<T> construct(coordinate_type left, coordinate_type right) { + Interval<T> interval; + interval.left = left; + interval.right = right; + return interval; + } + }; +} // polygon +} // boost + +void interval_concept_test1() +{ + typedef Interval<int> interval_type; + + interval_type interval1 = construct<interval_type>(2, 1); + BOOST_TEST_EQ(interval1.left, 1); + BOOST_TEST_EQ(interval1.right, 2); + + set(interval1, LOW, 3); + set(interval1, HIGH, 4); + BOOST_TEST_EQ(get(interval1, LOW), 3); + BOOST_TEST_EQ(get(interval1, HIGH), 4); + + interval_type interval2 = copy_construct<interval_type>(interval1); + BOOST_TEST(equivalence(interval1, interval2)); + + low(interval2, 1); + high(interval2, 2); + BOOST_TEST_EQ(low(interval2), 1); + BOOST_TEST_EQ(high(interval2), 2); + + assign(interval1, interval2); + BOOST_TEST(equivalence(interval1, interval2)); +} + +void interval_concept_test2() +{ + typedef Interval<int> interval_type; + + interval_type interval1 = construct<interval_type>(1, 3); + BOOST_TEST_EQ(center(interval1), 2); + BOOST_TEST_EQ(delta(interval1), 2); + + flip(interval1, -1); + BOOST_TEST_EQ(low(interval1), -5); + BOOST_TEST_EQ(high(interval1), -3); + + scale_up(interval1, 2); + BOOST_TEST_EQ(low(interval1), -10); + BOOST_TEST_EQ(high(interval1), -6); + + scale_down(interval1, 2); + BOOST_TEST_EQ(low(interval1), -5); + BOOST_TEST_EQ(high(interval1), -3); + + move(interval1, 5); + BOOST_TEST_EQ(low(interval1), 0); + BOOST_TEST_EQ(high(interval1), 2); + + convolve(interval1, 1); + BOOST_TEST_EQ(low(interval1), 1); + BOOST_TEST_EQ(high(interval1), 3); + + deconvolve(interval1, 2); + BOOST_TEST_EQ(low(interval1), -1); + BOOST_TEST_EQ(high(interval1), 1); + + interval_type interval2 = construct<interval_type>(-1, 2); + convolve(interval1, interval2); + BOOST_TEST_EQ(low(interval1), -2); + BOOST_TEST_EQ(high(interval1), 3); + + deconvolve(interval1, interval2); + BOOST_TEST_EQ(low(interval1), -1); + BOOST_TEST_EQ(high(interval1), 1); + + reflected_convolve(interval1, interval2); + BOOST_TEST_EQ(low(interval1), -3); + BOOST_TEST_EQ(high(interval1), 2); + + reflected_deconvolve(interval1, interval2); + BOOST_TEST_EQ(low(interval1), -1); + BOOST_TEST_EQ(high(interval1), 1); +} + +void interval_concept_test3() +{ + typedef Interval<int> interval_type; + + interval_type interval1 = construct<interval_type>(1, 3); + BOOST_TEST_EQ(euclidean_distance(interval1, -2), 3); + BOOST_TEST_EQ(euclidean_distance(interval1, 2), 0); + BOOST_TEST_EQ(euclidean_distance(interval1, 4), 1); + + interval_type interval2 = construct<interval_type>(-1, 0); + BOOST_TEST_EQ(euclidean_distance(interval1, interval2), 1); + BOOST_TEST(!intersects(interval1, interval2)); + BOOST_TEST(!boundaries_intersect(interval1, interval2)); + BOOST_TEST(!intersect(interval2, interval1)); + BOOST_TEST_EQ(low(interval2), -1); + BOOST_TEST_EQ(high(interval2), 0); + + interval_type interval3 = construct<interval_type>(-1, 6); + BOOST_TEST_EQ(euclidean_distance(interval1, interval3), 0); + BOOST_TEST(intersects(interval1, interval3)); + BOOST_TEST(!boundaries_intersect(interval1, interval3)); + BOOST_TEST(intersect(interval3, interval1)); + BOOST_TEST_EQ(low(interval3), 1); + BOOST_TEST_EQ(high(interval3), 3); + + interval_type interval4 = construct<interval_type>(5, 6); + BOOST_TEST_EQ(euclidean_distance(interval1, interval4), 2); + BOOST_TEST(!intersects(interval1, interval4)); + BOOST_TEST(!boundaries_intersect(interval1, interval4)); + BOOST_TEST(!intersect(interval4, interval1)); + BOOST_TEST_EQ(low(interval4), 5); + BOOST_TEST_EQ(high(interval4), 6); + + interval_type interval5 = construct<interval_type>(3, 5); + BOOST_TEST_EQ(euclidean_distance(interval1, interval5), 0); + BOOST_TEST(!intersects(interval1, interval5, false)); + BOOST_TEST(boundaries_intersect(interval1, interval5)); + BOOST_TEST(intersect(interval5, interval1)); + BOOST_TEST_EQ(low(interval5), 3); + BOOST_TEST_EQ(high(interval5), 3); +} + +void interval_concept_test4() +{ + typedef Interval<int> interval_type; + + interval_type interval1 = construct<interval_type>(1, 3); + interval_type interval2 = construct<interval_type>(3, 5); + BOOST_TEST(!abuts(interval1, interval2, LOW)); + BOOST_TEST(abuts(interval1, interval2, HIGH)); + BOOST_TEST(abuts(interval1, interval2)); + + bloat(interval1, 1); + BOOST_TEST_EQ(low(interval1), 0); + BOOST_TEST_EQ(high(interval1), 4); + BOOST_TEST(!abuts(interval1, interval2)); + + bloat(interval1, LOW, 1); + BOOST_TEST_EQ(low(interval1), -1); + BOOST_TEST_EQ(high(interval1), 4); + + shrink(interval1, LOW, 1); + BOOST_TEST_EQ(low(interval1), 0); + BOOST_TEST_EQ(high(interval1), 4); + + shrink(interval1, 1); + BOOST_TEST_EQ(low(interval1), 1); + BOOST_TEST_EQ(high(interval1), 3); + + BOOST_TEST(encompass(interval1, 4)); + BOOST_TEST_EQ(low(interval1), 1); + BOOST_TEST_EQ(high(interval1), 4); + + BOOST_TEST(encompass(interval1, interval2)); + BOOST_TEST_EQ(low(interval1), 1); + BOOST_TEST_EQ(high(interval1), 5); + + interval1 = get_half(interval1, LOW); + BOOST_TEST_EQ(low(interval1), 1); + BOOST_TEST_EQ(high(interval1), 3); + + BOOST_TEST(join_with(interval1, interval2)); + BOOST_TEST_EQ(low(interval1), 1); + BOOST_TEST_EQ(high(interval1), 5); +} + +int main() +{ + interval_data_test(); + interval_traits_test(); + interval_concept_test1(); + interval_concept_test2(); + interval_concept_test3(); + interval_concept_test4(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/polygon_point_test.cpp b/src/boost/libs/polygon/test/polygon_point_test.cpp new file mode 100644 index 00000000..ce57f5b1 --- /dev/null +++ b/src/boost/libs/polygon/test/polygon_point_test.cpp @@ -0,0 +1,205 @@ +// Boost.Polygon library polygon_point_test.cpp file + +// Copyright Andrii Sydorchuk 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/point_concept.hpp> +#include <boost/polygon/point_data.hpp> +#include <boost/polygon/point_traits.hpp> + +using namespace boost::polygon; + +void point_data_test() +{ + typedef point_data<int> point_type; + + point_type point1(1, 2); + point_type point2; + point2 = point1; + BOOST_TEST_EQ(point1.x(), 1); + BOOST_TEST_EQ(point1.y(), 2); + BOOST_TEST_EQ(point2.x(), 1); + BOOST_TEST_EQ(point2.y(), 2); + BOOST_TEST(point1 == point2); + BOOST_TEST(!(point1 != point2)); + BOOST_TEST(!(point1 < point2)); + BOOST_TEST(!(point1 > point2)); + BOOST_TEST(point1 <= point2); + BOOST_TEST(point1 >= point2); + + point2.x(2); + point2.y(1); + BOOST_TEST_EQ(point2.x(), 2); + BOOST_TEST_EQ(point2.y(), 1); + BOOST_TEST(!(point1 == point2)); + BOOST_TEST(point1 != point2); + BOOST_TEST(point1 < point2); + BOOST_TEST(!(point1 > point2)); + BOOST_TEST(point1 <= point2); + BOOST_TEST(!(point1 >= point2)); + + point2.set(HORIZONTAL, 1); + point2.set(VERTICAL, 2); + BOOST_TEST(point1 == point2); +} + +void point_traits_test() +{ + typedef point_data<int> point_type; + + point_type point = point_mutable_traits<point_type>::construct(1, 2); + BOOST_TEST_EQ(point_traits<point_type>::get(point, HORIZONTAL), 1); + BOOST_TEST_EQ(point_traits<point_type>::get(point, VERTICAL), 2); + + point_mutable_traits<point_type>::set(point, HORIZONTAL, 3); + point_mutable_traits<point_type>::set(point, VERTICAL, 4); + BOOST_TEST_EQ(point_traits<point_type>::get(point, HORIZONTAL), 3); + BOOST_TEST_EQ(point_traits<point_type>::get(point, VERTICAL), 4); +} + +template <typename T> +struct Point { + T x; + T y; +}; + +namespace boost { +namespace polygon { + template <typename T> + struct geometry_concept< Point<T> > { + typedef point_concept type; + }; + + template <typename T> + struct point_traits< Point<T> > { + typedef T coordinate_type; + + static coordinate_type get(const Point<T>& point, orientation_2d orient) { + return (orient == HORIZONTAL) ? point.x : point.y; + } + }; + + template <typename T> + struct point_mutable_traits< Point<T> > { + typedef T coordinate_type; + + static void set(Point<T>& point, orientation_2d orient, T value) { + (orient == HORIZONTAL) ? point.x = value : point.y = value; + } + + static Point<T> construct(coordinate_type x, coordinate_type y) { + Point<T> point; + point.x = x; + point.y = y; + return point; + } + }; +} // polygon +} // boost + +void point_concept_test1() +{ + typedef Point<int> point_type; + + point_type point1 = construct<point_type>(1, 2); + BOOST_TEST_EQ(point1.x, 1); + BOOST_TEST_EQ(point1.y, 2); + + set(point1, HORIZONTAL, 3); + set(point1, VERTICAL, 4); + BOOST_TEST_EQ(get(point1, HORIZONTAL), 3); + BOOST_TEST_EQ(get(point1, VERTICAL), 4); + + point_type point2; + assign(point2, point1); + BOOST_TEST(equivalence(point1, point2)); + + x(point2, 1); + y(point2, 2); + BOOST_TEST_EQ(x(point2), 1); + BOOST_TEST_EQ(y(point2), 2); +} + +void point_concept_test2() +{ + typedef Point<int> point_type; + + point_type point1 = construct<point_type>(1, 2); + point_type point2 = construct<point_type>(5, 5); + BOOST_TEST_EQ(euclidean_distance(point1, point2, HORIZONTAL), 4); + BOOST_TEST_EQ(euclidean_distance(point1, point2, VERTICAL), 3); + BOOST_TEST_EQ(manhattan_distance(point1, point2), 7); + BOOST_TEST_EQ(euclidean_distance(point1, point2), 5.0); +} + +void point_concept_test3() +{ + typedef Point<int> point_type; + + point_type point = construct<point_type>(1, 2); + point_type shift = construct<point_type>(4, 3); + convolve(point, shift); + BOOST_TEST_EQ(x(point), 5); + BOOST_TEST_EQ(y(point), 5); + + deconvolve(point, shift); + BOOST_TEST_EQ(x(point), 1); + BOOST_TEST_EQ(y(point), 2); + + scale_up(point, 5); + BOOST_TEST_EQ(x(point), 5); + BOOST_TEST_EQ(y(point), 10); + + scale_down(point, 5); + BOOST_TEST_EQ(x(point), 1); + BOOST_TEST_EQ(y(point), 2); + + move(point, HORIZONTAL, 2); + move(point, VERTICAL, 3); + BOOST_TEST_EQ(x(point), 3); + BOOST_TEST_EQ(y(point), 5); +} + +template<typename T> +struct Transformer { + void scale(T& x, T& y) const { + x *= 2; + y *= 2; + } + + void transform(T& x, T& y) const { + T tmp = x; + x = y; + y = tmp; + } +}; + +void point_concept_test4() +{ + typedef Point<int> point_type; + + point_type point = construct<point_type>(1, 2); + scale(point, Transformer<int>()); + BOOST_TEST_EQ(x(point), 2); + BOOST_TEST_EQ(y(point), 4); + + transform(point, Transformer<int>()); + BOOST_TEST_EQ(x(point), 4); + BOOST_TEST_EQ(y(point), 2); +} + +int main() +{ + point_data_test(); + point_traits_test(); + point_concept_test1(); + point_concept_test2(); + point_concept_test3(); + point_concept_test4(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/polygon_rectangle_formation_test.cpp b/src/boost/libs/polygon/test/polygon_rectangle_formation_test.cpp new file mode 100644 index 00000000..82640640 --- /dev/null +++ b/src/boost/libs/polygon/test/polygon_rectangle_formation_test.cpp @@ -0,0 +1,44 @@ +// Boost.Polygon library polygon_rectangle_formation_test.cpp file + +// Copyright Andrii Sydorchuk 2015. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/polygon.hpp> + +using namespace boost::polygon; + +void rectangle_formation_test1() +{ + typedef polygon_90_with_holes_data<int> polygon_type; + typedef polygon_traits<polygon_type>::point_type point_type; + + polygon_type poly; + point_type points[] = { + boost::polygon::construct<point_type>(0, 0), + boost::polygon::construct<point_type>(0, 10), + boost::polygon::construct<point_type>(10, 10), + boost::polygon::construct<point_type>(10, 0), + }; + boost::polygon::set_points(poly, points, points + 4); + + std::vector< rectangle_data<int> > rects; + boost::polygon::get_rectangles(rects, poly); + + BOOST_TEST_EQ(1, rects.size()); + const rectangle_data<int>& rect = rects[0]; + BOOST_TEST_EQ(0, rect.get(WEST)); + BOOST_TEST_EQ(10, rect.get(EAST)); + BOOST_TEST_EQ(10, rect.get(NORTH)); + BOOST_TEST_EQ(0, rect.get(SOUTH)); +} + +int main() +{ + rectangle_formation_test1(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/polygon_rectangle_test.cpp b/src/boost/libs/polygon/test/polygon_rectangle_test.cpp new file mode 100644 index 00000000..66a586df --- /dev/null +++ b/src/boost/libs/polygon/test/polygon_rectangle_test.cpp @@ -0,0 +1,45 @@ +// Boost.Polygon library polygon_rectangle_test.cpp file + +// Copyright Andrii Sydorchuk 2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/rectangle_concept.hpp> +#include <boost/polygon/rectangle_data.hpp> +#include <boost/polygon/rectangle_traits.hpp> + +using namespace boost::polygon; + +template <typename interval_type> +void CHECK_INTERVAL_EQUAL(const interval_type& i1, const interval_type& i2) { + BOOST_TEST_EQ(get(i1, LOW), get(i2, LOW)); + BOOST_TEST_EQ(get(i1, HIGH), get(i2, HIGH)); +} + +template <typename rectangle_type> +void CHECK_RECT_EQUAL(const rectangle_type& r1, const rectangle_type& r2) { + CHECK_INTERVAL_EQUAL(horizontal(r1), horizontal(r2)); + CHECK_INTERVAL_EQUAL(vertical(r1), vertical(r2)); +} + +void rectangle_concept_test1() +{ + typedef rectangle_data<int> rectangle_type; + + rectangle_type rectangle1 = construct<rectangle_type>(-1, -1, 1, 1); + scale_up(rectangle1, 2); + CHECK_RECT_EQUAL(construct<rectangle_type>(-2, -2, 2, 2), rectangle1); + + scale_down(rectangle1, 2); + CHECK_RECT_EQUAL(construct<rectangle_type>(-1, -1, 1, 1), rectangle1); +} + +int main() +{ + rectangle_concept_test1(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/polygon_segment_test.cpp b/src/boost/libs/polygon/test/polygon_segment_test.cpp new file mode 100644 index 00000000..a9042f5e --- /dev/null +++ b/src/boost/libs/polygon/test/polygon_segment_test.cpp @@ -0,0 +1,485 @@ +// Boost.Polygon library polygon_segment_test.cpp file + +// Copyright Andrii Sydorchuk 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/segment_concept.hpp> +#include <boost/polygon/segment_data.hpp> +#include <boost/polygon/segment_traits.hpp> + +using namespace boost::polygon; + +void segment_data_test() +{ + typedef point_data<int> point_type; + typedef segment_data<int> segment_type; + point_type point1(1, 2); + point_type point2(3, 4); + segment_type segment1(point1, point2); + segment_type segment2; + segment2 = segment1; + + BOOST_TEST(segment1.low() == point1); + BOOST_TEST(segment1.high() == point2); + BOOST_TEST(segment1.get(LOW) == point1); + BOOST_TEST(segment1.get(HIGH) == point2); + BOOST_TEST(segment1 == segment2); + BOOST_TEST(!(segment1 != segment2)); + BOOST_TEST(!(segment1 < segment2)); + BOOST_TEST(!(segment1 > segment1)); + BOOST_TEST(segment1 <= segment2); + BOOST_TEST(segment1 >= segment2); + + segment1.low(point2); + segment1.high(point1); + BOOST_TEST(segment1.low() == point2); + BOOST_TEST(segment1.high() == point1); + BOOST_TEST(!(segment1 == segment2)); + BOOST_TEST(segment1 != segment2); + + segment2.set(LOW, point2); + segment2.set(HIGH, point1); + BOOST_TEST(segment1 == segment2); +} + +void segment_traits_test() +{ + typedef point_data<int> point_type; + typedef segment_data<int> segment_type; + + point_type point1(1, 2); + point_type point2(3, 4); + segment_type segment = + segment_mutable_traits<segment_type>::construct(point1, point2); + + BOOST_TEST(segment_traits<segment_type>::get(segment, LOW) == point1); + BOOST_TEST(segment_traits<segment_type>::get(segment, HIGH) == point2); + + segment_mutable_traits<segment_type>::set(segment, LOW, point2); + segment_mutable_traits<segment_type>::set(segment, HIGH, point1); + BOOST_TEST(segment_traits<segment_type>::get(segment, LOW) == point2); + BOOST_TEST(segment_traits<segment_type>::get(segment, HIGH) == point1); +} + +template <typename T> +struct Segment { + typedef T coordinate_type; + typedef point_data<int> point_type; + point_type p0; + point_type p1; +}; + +namespace boost { +namespace polygon { + template <typename T> + struct geometry_concept< Segment<T> > { + typedef segment_concept type; + }; + + template <typename T> + struct segment_traits< Segment<T> > { + typedef T coordinate_type; + typedef point_data<int> point_type; + + static point_type get(const Segment<T>& segment, direction_1d dir) { + return dir.to_int() ? segment.p1 : segment.p0; + } + }; + + template <typename T> + struct segment_mutable_traits< Segment<T> > { + typedef T coordinate_type; + typedef point_data<int> point_type; + + static void set( + Segment<T>& segment, direction_1d dir, const point_type& point) { + dir.to_int() ? segment.p1 = point : segment.p0 = point;; + } + + static Segment<T> construct( + const point_type& point1, const point_type& point2) { + Segment<T> segment; + segment.p0 = point1; + segment.p1 = point2; + return segment; + } + }; +} +} + +void segment_concept_test1() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + point_type point1(1, 2); + point_type point2(3, 4); + point_type point3(2, 3); + segment_type segment1 = construct<segment_type>(point1, point2); + BOOST_TEST(segment1.p0 == point1); + BOOST_TEST(segment1.p1 == point2); + BOOST_TEST(get(segment1, LOW) == point1); + BOOST_TEST(low(segment1) == point1); + BOOST_TEST(get(segment1, HIGH) == point2); + BOOST_TEST(high(segment1) == point2); + BOOST_TEST(center(segment1) == point3); + + set(segment1, LOW, point2); + set(segment1, HIGH, point1); + BOOST_TEST(segment1.p0 == point2); + BOOST_TEST(segment1.p1 == point1); + BOOST_TEST(get(segment1, LOW) == point2); + BOOST_TEST(get(segment1, HIGH) == point1); + low(segment1, point1); + high(segment1, point2); + BOOST_TEST(segment1.p0 == point1); + BOOST_TEST(segment1.p1 == point2); + + segment_data<int> segment2 = copy_construct< segment_data<int> >(segment1); + BOOST_TEST(segment1.p0 == segment2.low()); + BOOST_TEST(segment1.p1 == segment2.high()); + BOOST_TEST(equivalence(segment1, segment2)); + + segment_data<int> segment3 = construct< segment_data<int> >(point2, point1); + assign(segment1, segment3); + BOOST_TEST(segment1.p0 == point2); + BOOST_TEST(segment1.p1 == point1); + BOOST_TEST(!equivalence(segment1, segment2)); +} + +void segment_concept_test2() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + point_type point1(1, 2); + point_type point2(2, 4); + point_type point3(0, 0); + point_type point4(5, 10); + point_type point5(1, 3); + point_type point6(2, 3); + point_type point7(100, 201); + point_type point8(100, 200); + point_type point9(100, 199); + segment_type segment1 = construct<segment_type>(point1, point2); + segment_type segment2 = construct<segment_type>(point2, point1); + segment_type segment3 = construct<segment_type>(point1, point5); + + BOOST_TEST(orientation(segment1, point1) == 0); + BOOST_TEST(orientation(segment1, point2) == 0); + BOOST_TEST(orientation(segment1, point3) == 0); + BOOST_TEST(orientation(segment1, point4) == 0); + BOOST_TEST(orientation(segment1, point5) == 1); + BOOST_TEST(orientation(segment2, point5) == -1); + BOOST_TEST(orientation(segment1, point6) == -1); + BOOST_TEST(orientation(segment2, point6) == 1); + BOOST_TEST(orientation(segment1, point7) == 1); + BOOST_TEST(orientation(segment2, point7) == -1); + BOOST_TEST(orientation(segment1, point8) == 0); + BOOST_TEST(orientation(segment1, point9) == -1); + BOOST_TEST(orientation(segment2, point9) == 1); + BOOST_TEST(orientation(segment3, point6) == -1); + BOOST_TEST(orientation(segment3, point3) == 1); +} + +void segment_concept_test3() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + segment_type segment1 = construct<segment_type>( + point_type(0, 0), point_type(1, 2)); + segment_type segment2 = construct<segment_type>( + point_type(0, 0), point_type(2, 4)); + segment_type segment3 = construct<segment_type>( + point_type(0, 0), point_type(2, 3)); + segment_type segment4 = construct<segment_type>( + point_type(0, 0), point_type(2, 5)); + segment_type segment5 = construct<segment_type>( + point_type(0, 2), point_type(2, 0)); + + BOOST_TEST(orientation(segment1, segment2) == 0); + BOOST_TEST(orientation(segment1, segment3) == -1); + BOOST_TEST(orientation(segment3, segment1) == 1); + BOOST_TEST(orientation(segment1, segment4) == 1); + BOOST_TEST(orientation(segment4, segment1) == -1); + BOOST_TEST(orientation(segment1, segment5) == -1); + BOOST_TEST(orientation(segment5, segment1) == 1); +} + +void segment_concept_test4() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + point_type point1(1, 2); + point_type point2(3, 6); + point_type point3(2, 4); + point_type point4(4, 8); + point_type point5(0, 0); + segment_type segment = construct<segment_type>(point1, point2); + + BOOST_TEST(contains(segment, point1, true)); + BOOST_TEST(contains(segment, point2, true)); + BOOST_TEST(!contains(segment, point1, false)); + BOOST_TEST(!contains(segment, point2, false)); + BOOST_TEST(contains(segment, point3, false)); + BOOST_TEST(!contains(segment, point4, true)); + BOOST_TEST(!contains(segment, point5, true)); +} + +void segment_concept_test5() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + point_type point1(0, 0); + point_type point2(10, 0); + point_type point3(5, 0); + point_type point4(-1, 0); + point_type point5(11, 0); + segment_type segment = construct<segment_type>(point1, point2); + + BOOST_TEST(contains(segment, point1, true)); + BOOST_TEST(contains(segment, point2, true)); + BOOST_TEST(!contains(segment, point1, false)); + BOOST_TEST(!contains(segment, point2, false)); + BOOST_TEST(contains(segment, point3, false)); + BOOST_TEST(!contains(segment, point4, true)); + BOOST_TEST(!contains(segment, point5, true)); +} + +void segment_concept_test6() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + point_type point1(0, 0); + point_type point2(1, 2); + point_type point3(2, 4); + point_type point4(3, 6); + point_type point5(4, 8); + point_type point6(5, 10); + segment_type segment1 = construct<segment_type>(point2, point5); + segment_type segment2 = construct<segment_type>(point3, point4); + segment_type segment3 = construct<segment_type>(point1, point3); + segment_type segment4 = construct<segment_type>(point4, point6); + + BOOST_TEST(contains(segment1, segment2, false)); + BOOST_TEST(!contains(segment2, segment1, true)); + BOOST_TEST(!contains(segment1, segment3, true)); + BOOST_TEST(!contains(segment1, segment4, true)); + BOOST_TEST(contains(segment1, segment1, true)); + BOOST_TEST(!contains(segment1, segment1, false)); +} + +template<typename T> +struct Transformer { + void scale(T& x, T& y) const { + x *= 2; + y *= 2; + } + + void transform(T& x, T& y) const { + T tmp = x; + x = y; + y = tmp; + } +}; + +void segment_concept_test7() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + point_type point1(1, 2); + point_type point2(4, 6); + segment_type segment1 = construct<segment_type>(point1, point2); + + scale_up(segment1, 3); + BOOST_TEST(low(segment1) == point_type(3, 6)); + BOOST_TEST(high(segment1) == point_type(12, 18)); + + scale_down(segment1, 3); + BOOST_TEST(low(segment1) == point1); + BOOST_TEST(high(segment1) == point2); + BOOST_TEST(length(segment1) == 5); + + move(segment1, HORIZONTAL, 1); + move(segment1, VERTICAL, 2); + BOOST_TEST(low(segment1) == point_type(2, 4)); + BOOST_TEST(high(segment1) == point_type(5, 8)); + BOOST_TEST(length(segment1) == 5); + + convolve(segment1, point_type(1, 2)); + BOOST_TEST(low(segment1) == point_type(3, 6)); + BOOST_TEST(high(segment1) == point_type(6, 10)); + + deconvolve(segment1, point_type(2, 4)); + BOOST_TEST(low(segment1) == point1); + BOOST_TEST(high(segment1) == point2); + + scale(segment1, Transformer<int>()); + BOOST_TEST(low(segment1) == point_type(2, 4)); + BOOST_TEST(high(segment1) == point_type(8, 12)); + transform(segment1, Transformer<int>()); + BOOST_TEST(low(segment1) == point_type(4, 2)); + BOOST_TEST(high(segment1) == point_type(12, 8)); +} + +void segment_concept_test8() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + segment_type segment1 = construct<segment_type>( + point_type(0, 0), point_type(1, 2)); + segment_type segment2 = construct<segment_type>( + point_type(1, 2), point_type(2, 4)); + segment_type segment3 = construct<segment_type>( + point_type(2, 4), point_type(0, 4)); + segment_type segment4 = construct<segment_type>( + point_type(0, 4), point_type(0, 0)); + + BOOST_TEST(abuts(segment1, segment2, HIGH)); + BOOST_TEST(abuts(segment2, segment3, HIGH)); + BOOST_TEST(abuts(segment3, segment4, HIGH)); + BOOST_TEST(abuts(segment4, segment1, HIGH)); + + BOOST_TEST(!abuts(segment1, segment2, LOW)); + BOOST_TEST(!abuts(segment2, segment3, LOW)); + BOOST_TEST(!abuts(segment3, segment4, LOW)); + BOOST_TEST(!abuts(segment4, segment1, LOW)); + + BOOST_TEST(abuts(segment2, segment1)); + BOOST_TEST(abuts(segment3, segment2)); + BOOST_TEST(abuts(segment4, segment3)); + BOOST_TEST(abuts(segment1, segment4)); + + BOOST_TEST(!abuts(segment1, segment3)); + BOOST_TEST(!abuts(segment2, segment4)); +} + +void segment_concept_test9() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + segment_type segment1 = construct<segment_type>( + point_type(0, 0), point_type(2, 2)); + segment_type segment2 = construct<segment_type>( + point_type(1, 1), point_type(3, 3)); + segment_type segment3 = construct<segment_type>( + point_type(2, 2), point_type(-1, -1)); + segment_type segment4 = construct<segment_type>( + point_type(1, 3), point_type(3, 1)); + segment_type segment5 = construct<segment_type>( + point_type(2, 2), point_type(1, 3)); + + BOOST_TEST(intersects(segment1, segment2, false)); + BOOST_TEST(intersects(segment1, segment2, true)); + BOOST_TEST(intersects(segment1, segment3, false)); + BOOST_TEST(intersects(segment1, segment3, true)); + BOOST_TEST(intersects(segment2, segment3, false)); + BOOST_TEST(intersects(segment2, segment3, true)); + BOOST_TEST(intersects(segment4, segment3, false)); + BOOST_TEST(intersects(segment4, segment3, true)); + BOOST_TEST(intersects(segment4, segment2, false)); + BOOST_TEST(intersects(segment4, segment2, true)); + BOOST_TEST(!intersects(segment3, segment5, false)); + BOOST_TEST(intersects(segment3, segment5, true)); +} + +void segment_concept_test10() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + segment_type segment1 = construct<segment_type>( + point_type(0, 0), point_type(0, 2)); + segment_type segment2 = construct<segment_type>( + point_type(0, 1), point_type(0, 3)); + segment_type segment3 = construct<segment_type>( + point_type(0, 1), point_type(0, 2)); + segment_type segment4 = construct<segment_type>( + point_type(0, 2), point_type(0, 3)); + segment_type segment5 = construct<segment_type>( + point_type(0, 2), point_type(2, 2)); + segment_type segment6 = construct<segment_type>( + point_type(0, 1), point_type(1, 1)); + + BOOST_TEST(intersects(segment1, segment1, false)); + BOOST_TEST(intersects(segment1, segment1, true)); + BOOST_TEST(intersects(segment1, segment2, false)); + BOOST_TEST(intersects(segment1, segment2, true)); + BOOST_TEST(intersects(segment1, segment3, false)); + BOOST_TEST(intersects(segment1, segment3, true)); + BOOST_TEST(intersects(segment2, segment3, false)); + BOOST_TEST(intersects(segment2, segment3, true)); + BOOST_TEST(!intersects(segment1, segment4, false)); + BOOST_TEST(intersects(segment1, segment4, true)); + BOOST_TEST(!intersects(segment1, segment5, false)); + BOOST_TEST(intersects(segment1, segment5, true)); + BOOST_TEST(intersects(segment1, segment6, false)); + BOOST_TEST(intersects(segment1, segment6, true)); +} + +void segment_concept_test11() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + point_type point1(1, 2); + point_type point2(7, 10); + segment_type segment1 = construct<segment_type>(point1, point2); + + BOOST_TEST(euclidean_distance(segment1, point1) == 0.0); + BOOST_TEST(euclidean_distance(segment1, point2) == 0.0); + BOOST_TEST(euclidean_distance(segment1, point_type(10, 14)) == 5.0); + BOOST_TEST(euclidean_distance(segment1, point_type(-3, -1)) == 5.0); + BOOST_TEST(euclidean_distance(segment1, point_type(0, 9)) == 5.0); + BOOST_TEST(euclidean_distance(segment1, point_type(8, 3)) == 5.0); +} + +void segment_concept_test12() +{ + typedef point_data<int> point_type; + typedef Segment<int> segment_type; + + segment_type segment1 = construct<segment_type>( + point_type(0, 0), point_type(3, 4)); + segment_type segment2 = construct<segment_type>( + point_type(2, 0), point_type(0, 2)); + segment_type segment3 = construct<segment_type>( + point_type(1, -7), point_type(10, 5)); + segment_type segment4 = construct<segment_type>( + point_type(7, 7), point_type(10, 11)); + + BOOST_TEST(euclidean_distance(segment1, segment2) == 0.0); + BOOST_TEST(euclidean_distance(segment1, segment3) == 5.0); + BOOST_TEST(euclidean_distance(segment1, segment4) == 5.0); +} + +int main() +{ + segment_data_test(); + segment_traits_test(); + segment_concept_test1(); + segment_concept_test2(); + segment_concept_test3(); + segment_concept_test4(); + segment_concept_test5(); + segment_concept_test6(); + segment_concept_test7(); + segment_concept_test8(); + segment_concept_test9(); + segment_concept_test10(); + segment_concept_test11(); + segment_concept_test12(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/polygon_set_data_test.cpp b/src/boost/libs/polygon/test/polygon_set_data_test.cpp new file mode 100644 index 00000000..df4fa4ac --- /dev/null +++ b/src/boost/libs/polygon/test/polygon_set_data_test.cpp @@ -0,0 +1,114 @@ +// Boost.Polygon library polygon_set_data_test.cpp file + +// Copyright Andrii Sydorchuk 2015. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/polygon.hpp> +#include <vector> + +using namespace boost::polygon; +using namespace boost::polygon::operators; + +void polygon_set_data_test1() +{ + typedef point_data<int> point_type; + typedef polygon_with_holes_data<int> polygon_with_holes_type; + typedef polygon_set_data<int> polygon_set_type; + + polygon_set_type pset; + std::vector<point_type> outbox; + outbox.push_back(point_type(0, 0)); + outbox.push_back(point_type(100, 0)); + outbox.push_back(point_type(100, 100)); + outbox.push_back(point_type(0, 100)); + pset.insert_vertex_sequence(outbox.begin(), outbox.end(), COUNTERCLOCKWISE, false); + std::vector<point_type> inbox; + inbox.push_back(point_type(20, 20)); + inbox.push_back(point_type(80, 20)); + inbox.push_back(point_type(80, 80)); + inbox.push_back(point_type(20, 80)); + pset.insert_vertex_sequence(inbox.begin(), inbox.end(), COUNTERCLOCKWISE, true); + + BOOST_TEST(!pset.empty()); + BOOST_TEST(!pset.sorted()); + BOOST_TEST(pset.dirty()); + BOOST_TEST_EQ(8, pset.size()); + + std::vector<polygon_with_holes_type> vpoly; + pset.get(vpoly); + BOOST_TEST_EQ(1, vpoly.size()); + + polygon_with_holes_type poly = vpoly[0]; + BOOST_TEST_EQ(5, poly.size()); + BOOST_TEST_EQ(1, poly.size_holes()); +} + +void polygon_set_data_test2() +{ + typedef point_data<int> point_type; + typedef polygon_data<int> polygon_type; + typedef polygon_set_data<int> polygon_set_type; + + std::vector<point_type> data; + data.push_back(point_type(2,0)); + data.push_back(point_type(4,0)); + data.push_back(point_type(4,3)); + data.push_back(point_type(0,3)); + data.push_back(point_type(0,0)); + data.push_back(point_type(2,0)); + data.push_back(point_type(2,1)); + data.push_back(point_type(1,1)); + data.push_back(point_type(1,2)); + data.push_back(point_type(3,2)); + data.push_back(point_type(3,1)); + data.push_back(point_type(2,1)); + data.push_back(point_type(2,0)); + + polygon_type polygon; + set_points(polygon, data.begin(), data.end()); + + polygon_set_type pset; + pset.insert(polygon); + + std::vector<polygon_type> traps; + get_trapezoids(traps, pset, HORIZONTAL); + + BOOST_TEST_EQ(4, traps.size()); +} + +void polygon_set_data_test3() +{ + typedef point_data<int> point_type; + typedef polygon_data<int> polygon_type; + typedef polygon_set_data<int> polygon_set_type; + + std::vector<point_type> data; + data.push_back(point_type(0,0)); + data.push_back(point_type(6,0)); + data.push_back(point_type(6,4)); + data.push_back(point_type(4,6)); + data.push_back(point_type(0,6)); + data.push_back(point_type(0,0)); + data.push_back(point_type(4,4)); + data.push_back(point_type(5,4)); + + polygon_type polygon(data.begin(), data.end()); + polygon_set_type pset; + pset += polygon; + + BOOST_TEST_EQ(32.0, area(polygon)); + BOOST_TEST_EQ(32.0, area(polygon)); +} + +int main() +{ + polygon_set_data_test1(); + polygon_set_data_test2(); + polygon_set_data_test3(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_builder_test.cpp b/src/boost/libs/polygon/test/voronoi_builder_test.cpp new file mode 100644 index 00000000..192c2171 --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_builder_test.cpp @@ -0,0 +1,681 @@ +// Boost.Polygon library voronoi_builder_test.cpp file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include "voronoi_test_helper.hpp" +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/polygon.hpp> +#include <boost/polygon/voronoi.hpp> +#include <boost/random/mersenne_twister.hpp> +#include <limits> +#include <list> +#include <vector> +#include <ctime> + +using boost::polygon::voronoi_builder; +using boost::polygon::voronoi_diagram; + +typedef voronoi_diagram<double> vd_type; +typedef vd_type::coordinate_type coordinate_type; +typedef vd_type::edge_type voronoi_edge_type; +typedef vd_type::const_cell_iterator const_cell_iterator; +typedef vd_type::const_vertex_iterator const_vertex_iterator; + +#define CHECK_OUTPUT_SIZE(output, cells, vertices, edges) \ + BOOST_TEST_EQ(output.num_cells(), (std::size_t)cells); \ + BOOST_TEST_EQ(output.num_vertices(), (std::size_t)vertices); \ + BOOST_TEST_EQ(output.num_edges(), (std::size_t)edges) + +#define VERIFY_OUTPUT(output) \ + BOOST_TEST(voronoi_test_helper::verify_output(output, \ + voronoi_test_helper::CELL_CONVEXITY)); \ + BOOST_TEST(voronoi_test_helper::verify_output(output, \ + voronoi_test_helper::INCIDENT_EDGES_CCW_ORDER)); \ + BOOST_TEST(voronoi_test_helper::verify_output(output, \ + voronoi_test_helper::NO_HALF_EDGE_INTERSECTIONS)) + +#define VERIFY_NO_HALF_EDGE_INTERSECTIONS(output) \ + BOOST_TEST(voronoi_test_helper::verify_output(output, \ + voronoi_test_helper::NO_HALF_EDGE_INTERSECTIONS)) + +// Sites: (0, 0). +void single_site_test() +{ + std::vector< point_data<int> > points; + points.push_back(point_data<int>(0, 0)); + vd_type test_output; + construct_voronoi(points.begin(), points.end(), &test_output); + VERIFY_OUTPUT(test_output); + + BOOST_TEST(test_output.cells().size() == 1); + CHECK_OUTPUT_SIZE(test_output, 1, 0, 0); + + const_cell_iterator it = test_output.cells().begin(); + BOOST_TEST(it->incident_edge() == NULL); +} + +// Sites: (0, 0), (0, 1). +void collinear_sites_test1() +{ + std::vector< point_data<int> > points; + points.push_back(point_data<int>(0, 0)); + points.push_back(point_data<int>(0, 1)); + vd_type test_output; + construct_voronoi(points.begin(), points.end(), &test_output); + VERIFY_OUTPUT(test_output); + CHECK_OUTPUT_SIZE(test_output, 2, 0, 2); + + const_cell_iterator cell_it = test_output.cells().begin(); + cell_it++; + + const voronoi_edge_type* edge1_1 = cell_it->incident_edge(); + const voronoi_edge_type* edge1_2 = edge1_1->twin(); + + BOOST_TEST(edge1_1->twin() == edge1_2); + BOOST_TEST(edge1_2->twin() == edge1_1); + + BOOST_TEST(edge1_1->next() == edge1_1); + BOOST_TEST(edge1_1->prev() == edge1_1); + BOOST_TEST(edge1_1->rot_next() == edge1_2); + BOOST_TEST(edge1_1->rot_prev() == edge1_2); + + BOOST_TEST(edge1_2->next() == edge1_2); + BOOST_TEST(edge1_2->prev() == edge1_2); + BOOST_TEST(edge1_2->rot_next() == edge1_1); + BOOST_TEST(edge1_2->rot_prev() == edge1_1); +} + +// Sites: (0, 0), (1, 1), (2, 2). +void collinear_sites_test2() +{ + std::vector< point_data<int> > points; + points.push_back(point_data<int>(0, 0)); + points.push_back(point_data<int>(1, 1)); + points.push_back(point_data<int>(2, 2)); + vd_type test_output; + construct_voronoi(points.begin(), points.end(), &test_output); + VERIFY_OUTPUT(test_output); + CHECK_OUTPUT_SIZE(test_output, 3, 0, 4); + + const_cell_iterator cell_it = test_output.cells().begin(); + const voronoi_edge_type* edge1_1 = cell_it->incident_edge(); + const voronoi_edge_type* edge1_2 = edge1_1->twin(); + cell_it++; + cell_it++; + const voronoi_edge_type* edge2_2 = cell_it->incident_edge(); + const voronoi_edge_type* edge2_1 = edge2_2->twin(); + + BOOST_TEST(edge1_1->twin() == edge1_2 && edge1_2->twin() == edge1_1); + BOOST_TEST(edge2_1->twin() == edge2_2 && edge2_2->twin() == edge2_1); + + BOOST_TEST(edge1_1->next() == edge1_1 && edge1_1->prev() == edge1_1); + BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1); + BOOST_TEST(edge2_1->next() == edge1_2 && edge2_1->prev() == edge1_2); + BOOST_TEST(edge2_2->next() == edge2_2 && edge2_2->prev() == edge2_2); + + BOOST_TEST(edge1_1->rot_next() == edge1_2 && edge1_1->rot_prev() == edge2_1); + BOOST_TEST(edge1_2->rot_next() == edge2_2 && edge1_2->rot_prev() == edge1_1); + BOOST_TEST(edge2_1->rot_next() == edge1_1 && edge2_1->rot_prev() == edge2_2); + BOOST_TEST(edge2_2->rot_next() == edge2_1 && edge2_2->rot_prev() == edge1_2); + + BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1); + BOOST_TEST(edge2_1->next() == edge1_2 && edge2_1->prev() == edge1_2); +} + +// Sites: (0, 0), (0, 4), (2, 1). +void triangle_test1() +{ + point_data<int> point1(0, 0); + point_data<int> point2(0, 4); + point_data<int> point3(2, 1); + std::vector< point_data<int> > points; + points.push_back(point1); + points.push_back(point2); + points.push_back(point3); + vd_type test_output; + construct_voronoi(points.begin(), points.end(), &test_output); + VERIFY_OUTPUT(test_output); + CHECK_OUTPUT_SIZE(test_output, 3, 1, 6); + + const_vertex_iterator it = test_output.vertices().begin(); + BOOST_TEST_EQ(it->x(), 0.25); + BOOST_TEST_EQ(it->y(), 2.0); + + const voronoi_edge_type* edge1_1 = it->incident_edge(); + const voronoi_edge_type* edge1_2 = edge1_1->twin(); + BOOST_TEST(edge1_1->cell()->source_index() == 1); + BOOST_TEST(edge1_2->cell()->source_index() == 2); + + const voronoi_edge_type* edge2_1 = edge1_1->rot_prev(); + const voronoi_edge_type* edge2_2 = edge2_1->twin(); + BOOST_TEST(edge2_1->cell()->source_index() == 2); + BOOST_TEST(edge2_2->cell()->source_index() == 0); + + const voronoi_edge_type* edge3_1 = edge2_1->rot_prev(); + const voronoi_edge_type* edge3_2 = edge3_1->twin(); + BOOST_TEST(edge3_1->cell()->source_index() == 0); + BOOST_TEST(edge3_2->cell()->source_index() == 1); + + BOOST_TEST(edge1_2->twin() == edge1_1); + BOOST_TEST(edge2_2->twin() == edge2_1); + BOOST_TEST(edge3_2->twin() == edge3_1); + + BOOST_TEST(edge1_1->prev() == edge3_2 && edge1_1->next() == edge3_2); + BOOST_TEST(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2); + BOOST_TEST(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2); + + BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1); + BOOST_TEST(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1); + BOOST_TEST(edge3_2->next() == edge1_1 && edge3_2->prev() == edge1_1); + + BOOST_TEST(edge1_1->rot_next() == edge3_1); + BOOST_TEST(edge3_1->rot_next() == edge2_1); + BOOST_TEST(edge2_1->rot_next() == edge1_1); + + BOOST_TEST(edge1_2->rot_next() == edge2_2); + BOOST_TEST(edge2_2->rot_next() == edge3_2); + BOOST_TEST(edge3_2->rot_next() == edge1_2); +} + +// Sites: (0, 1), (2, 0), (2, 4). +void triangle_test2() +{ + point_data<int> point1(0, 1); + point_data<int> point2(2, 0); + point_data<int> point3(2, 4); + std::vector< point_data<int> > points; + points.push_back(point1); + points.push_back(point2); + points.push_back(point3); + vd_type test_output; + construct_voronoi(points.begin(), points.end(), &test_output); + VERIFY_OUTPUT(test_output); + CHECK_OUTPUT_SIZE(test_output, 3, 1, 6); + + const_vertex_iterator it = test_output.vertices().begin(); + BOOST_TEST_EQ(it->x(), 1.75); + BOOST_TEST_EQ(it->y(), 2.0); + + const voronoi_edge_type* edge1_1 = it->incident_edge(); + const voronoi_edge_type* edge1_2 = edge1_1->twin(); + BOOST_TEST(edge1_1->cell()->source_index() == 2); + BOOST_TEST(edge1_2->cell()->source_index() == 1); + + const voronoi_edge_type* edge2_1 = edge1_1->rot_prev(); + const voronoi_edge_type* edge2_2 = edge2_1->twin(); + BOOST_TEST(edge2_1->cell()->source_index() == 1); + BOOST_TEST(edge2_2->cell()->source_index() == 0); + + const voronoi_edge_type* edge3_1 = edge2_1->rot_prev(); + const voronoi_edge_type* edge3_2 = edge3_1->twin(); + BOOST_TEST(edge3_1->cell()->source_index() == 0); + BOOST_TEST(edge3_2->cell()->source_index() == 2); + + BOOST_TEST(edge1_2->twin() == edge1_1); + BOOST_TEST(edge2_2->twin() == edge2_1); + BOOST_TEST(edge3_2->twin() == edge3_1); + + BOOST_TEST(edge1_1->prev() == edge3_2 && edge1_1->next() == edge3_2); + BOOST_TEST(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2); + BOOST_TEST(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2); + + BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1); + BOOST_TEST(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1); + BOOST_TEST(edge3_2->next() == edge1_1 && edge3_2->prev() == edge1_1); + + BOOST_TEST(edge1_1->rot_next() == edge3_1); + BOOST_TEST(edge3_1->rot_next() == edge2_1); + BOOST_TEST(edge2_1->rot_next() == edge1_1); + + BOOST_TEST(edge1_2->rot_next() == edge2_2); + BOOST_TEST(edge2_2->rot_next() == edge3_2); + BOOST_TEST(edge3_2->rot_next() == edge1_2); +} + +// Sites: (0, 0), (0, 1), (1, 0), (1, 1). +void square_test1() +{ + point_data<int> point1(0, 0); + point_data<int> point2(0, 1); + point_data<int> point3(1, 0); + point_data<int> point4(1, 1); + std::vector< point_data<int> > points; + points.push_back(point1); + points.push_back(point2); + points.push_back(point3); + points.push_back(point4); + vd_type test_output; + construct_voronoi(points.begin(), points.end(), &test_output); + VERIFY_OUTPUT(test_output); + CHECK_OUTPUT_SIZE(test_output, 4, 1, 8); + + // Check voronoi vertex. + const_vertex_iterator it = test_output.vertices().begin(); + BOOST_TEST_EQ(it->x(), 0.5); + BOOST_TEST_EQ(it->y(), 0.5); + + // Check voronoi edges. + const voronoi_edge_type* edge1_1 = it->incident_edge(); + const voronoi_edge_type* edge1_2 = edge1_1->twin(); + BOOST_TEST(edge1_1->cell()->source_index() == 3); + BOOST_TEST(edge1_2->cell()->source_index() == 2); + + const voronoi_edge_type* edge2_1 = edge1_1->rot_prev(); + const voronoi_edge_type* edge2_2 = edge2_1->twin(); + BOOST_TEST(edge2_1->cell()->source_index() == 2); + BOOST_TEST(edge2_2->cell()->source_index() == 0); + + const voronoi_edge_type* edge3_1 = edge2_1->rot_prev(); + const voronoi_edge_type* edge3_2 = edge3_1->twin(); + BOOST_TEST(edge3_1->cell()->source_index() == 0); + BOOST_TEST(edge3_2->cell()->source_index() == 1); + + const voronoi_edge_type* edge4_1 = edge3_1->rot_prev(); + const voronoi_edge_type* edge4_2 = edge4_1->twin(); + BOOST_TEST(edge4_1->cell()->source_index() == 1); + BOOST_TEST(edge4_2->cell()->source_index() == 3); + + BOOST_TEST(edge1_2->twin() == edge1_1); + BOOST_TEST(edge2_2->twin() == edge2_1); + BOOST_TEST(edge3_2->twin() == edge3_1); + BOOST_TEST(edge4_2->twin() == edge4_1); + + BOOST_TEST(edge1_1->prev() == edge4_2 && edge1_1->next() == edge4_2); + BOOST_TEST(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2); + BOOST_TEST(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2); + BOOST_TEST(edge4_1->prev() == edge3_2 && edge4_1->next() == edge3_2); + + BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1); + BOOST_TEST(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1); + BOOST_TEST(edge3_2->next() == edge4_1 && edge3_2->prev() == edge4_1); + BOOST_TEST(edge4_2->next() == edge1_1 && edge4_2->prev() == edge1_1); + + BOOST_TEST(edge1_1->rot_next() == edge4_1); + BOOST_TEST(edge4_1->rot_next() == edge3_1); + BOOST_TEST(edge3_1->rot_next() == edge2_1); + BOOST_TEST(edge2_1->rot_next() == edge1_1); + + BOOST_TEST(edge1_2->rot_next() == edge2_2); + BOOST_TEST(edge2_2->rot_next() == edge3_2); + BOOST_TEST(edge3_2->rot_next() == edge4_2); + BOOST_TEST(edge4_2->rot_next() == edge1_2); +} + +#ifdef NDEBUG +void grid_test() +{ + vd_type test_output_small, test_output_large; + std::vector< point_data<int> > point_vec_small, point_vec_large; + int grid_size[] = {10, 33, 101}; + int max_value[] = {10, 33, 101}; + int array_length = sizeof(grid_size) / sizeof(int); + for (int k = 0; k < array_length; k++) { + test_output_small.clear(); + test_output_large.clear(); + point_vec_small.clear(); + point_vec_large.clear(); + int koef = (std::numeric_limits<int>::max)() / max_value[k]; + for (int i = 0; i < grid_size[k]; i++) { + for (int j = 0; j < grid_size[k]; j++) { + point_vec_small.push_back(point_data<int>(i, j)); + point_vec_large.push_back(point_data<int>(koef * i, koef * j)); + } + } + construct_voronoi(point_vec_small.begin(), point_vec_small.end(), &test_output_small); + construct_voronoi(point_vec_large.begin(), point_vec_large.end(), &test_output_large); + VERIFY_OUTPUT(test_output_small); + VERIFY_OUTPUT(test_output_large); + unsigned int num_cells = grid_size[k] * grid_size[k]; + unsigned int num_vertices = num_cells - 2 * grid_size[k] + 1; + unsigned int num_edges = 4 * num_cells - 4 * grid_size[k]; + CHECK_OUTPUT_SIZE(test_output_small, num_cells, num_vertices, num_edges); + CHECK_OUTPUT_SIZE(test_output_large, num_cells, num_vertices, num_edges); + } +} +#endif + +#ifdef NDEBUG +void random_test() +{ + boost::mt19937 gen(static_cast<unsigned int>(time(NULL))); + vd_type test_output_small, test_output_large; + std::vector< point_data<int> > point_vec_small, point_vec_large; + int num_points[] = {10, 100, 1000, 10000}; + int num_runs[] = {1000, 100, 10, 1}; + int mod_koef[] = {10, 100, 100, 1000}; + int max_value[] = {5, 50, 50, 5000}; + int array_length = sizeof(num_points) / sizeof(int); + for (int k = 0; k < array_length; k++) { + int koef = (std::numeric_limits<int>::max)() / max_value[k]; + for (int i = 0; i < num_runs[k]; i++) { + test_output_small.clear(); + test_output_large.clear(); + point_vec_small.clear(); + point_vec_large.clear(); + for (int j = 0; j < num_points[k]; j++) { + int x = gen() % mod_koef[k] - mod_koef[k] / 2; + int y = gen() % mod_koef[k] - mod_koef[k] / 2; + point_vec_small.push_back(point_data<int>(x, y)); + point_vec_large.push_back(point_data<int>(koef * x, koef * y)); + } + construct_voronoi(point_vec_small.begin(), point_vec_small.end(), &test_output_small); + construct_voronoi(point_vec_large.begin(), point_vec_large.end(), &test_output_large); + VERIFY_OUTPUT(test_output_small); + VERIFY_OUTPUT(test_output_large); + BOOST_TEST_EQ(test_output_small.num_cells(), test_output_large.num_cells()); + BOOST_TEST_EQ(test_output_small.num_vertices(), test_output_large.num_vertices()); + BOOST_TEST_EQ(test_output_small.num_edges(), test_output_large.num_edges()); + } + } +} +#endif + +void segment_sites_test1() +{ + vd_type test_output; + std::vector< segment_data<int> > segments; + point_data<int> point1(0, 0); + point_data<int> point2(1, 1); + segments.push_back(segment_data<int>(point1, point2)); + construct_voronoi(segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 3, 0, 4); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_sites_test2() +{ + vd_type test_output; + std::vector< point_data<int> > points; + std::vector< segment_data<int> > segments; + point_data<int> point1(0, 0); + point_data<int> point2(4, 4); + point_data<int> point3(3, 1); + point_data<int> point4(1, 3); + segments.push_back(segment_data<int>(point1, point2)); + points.push_back(point3); + points.push_back(point4); + construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 5, 4, 16); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_sites_test3() +{ + vd_type test_output; + std::vector< point_data<int> > points; + std::vector< segment_data<int> > segments; + point_data<int> point1(4, 0); + point_data<int> point2(0, 4); + point_data<int> point3(3, 3); + point_data<int> point4(1, 1); + segments.push_back(segment_data<int>(point1, point2)); + points.push_back(point3); + points.push_back(point4); + construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 5, 4, 16); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_sites_test4() +{ + vd_type test_output; + std::vector< point_data<int> > points; + std::vector< segment_data<int> > segments; + point_data<int> point1(4, 0); + point_data<int> point2(0, 4); + point_data<int> point3(3, 2); + point_data<int> point4(2, 3); + segments.push_back(segment_data<int>(point1, point2)); + points.push_back(point3); + points.push_back(point4); + construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 5, 3, 14); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_site_test5() +{ + vd_type test_output; + std::vector< point_data<int> > points; + std::vector< segment_data<int> > segments; + point_data<int> point1(0, 0); + point_data<int> point2(0, 8); + point_data<int> point3(-2, -2); + point_data<int> point4(-2, 4); + point_data<int> point5(-2, 10); + segments.push_back(segment_data<int>(point1, point2)); + points.push_back(point3); + points.push_back(point4); + points.push_back(point5); + construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 6, 4, 18); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_site_test6() +{ + vd_type test_output; + std::vector< point_data<int> > points; + std::vector< segment_data<int> > segments; + point_data<int> point1(-1, 1); + point_data<int> point2(1, 0); + point_data<int> point3(1, 2); + segments.push_back(segment_data<int>(point2, point3)); + points.push_back(point1); + construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 4, 2, 10); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_site_test7() +{ + vd_type test_output; + std::vector< segment_data<int> > segments; + point_data<int> point1(0, 0); + point_data<int> point2(4, 0); + point_data<int> point3(0, 4); + point_data<int> point4(4, 4); + segments.push_back(segment_data<int>(point1, point2)); + segments.push_back(segment_data<int>(point2, point3)); + segments.push_back(segment_data<int>(point3, point4)); + construct_voronoi(segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 7, 6, 24); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_site_test8() +{ + vd_type test_output; + std::vector< segment_data<int> > segments; + point_data<int> point1(0, 0); + point_data<int> point2(4, 0); + point_data<int> point3(4, 4); + point_data<int> point4(0, 4); + segments.push_back(segment_data<int>(point1, point2)); + segments.push_back(segment_data<int>(point2, point3)); + segments.push_back(segment_data<int>(point3, point4)); + segments.push_back(segment_data<int>(point4, point1)); + construct_voronoi(segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 8, 5, 24); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +void segment_site_test9() +{ + vd_type test_output; + std::vector< segment_data<int> > segments; + point_data<int> point1(0, 0); + point_data<int> point2(2, 0); + point_data<int> point3(4, 0); + segments.push_back(segment_data<int>(point1, point2)); + segments.push_back(segment_data<int>(point2, point3)); + construct_voronoi(segments.begin(), segments.end(), &test_output); + CHECK_OUTPUT_SIZE(test_output, 5, 0, 8); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); +} + +#ifdef NDEBUG +void segment_grid_test() +{ + vd_type test_output_small, test_output_large; + std::vector< segment_data<int> > segments_small, segments_large; + int grid_size[] = {10, 27, 53}; + int max_value[] = {100, 330, 1000}; + int array_length = sizeof(grid_size) / sizeof(int); + for (int k = 0; k < array_length; k++) { + test_output_small.clear(); + test_output_large.clear(); + segments_small.clear(); + segments_large.clear(); + int cur_sz = grid_size[k]; + int koef = (std::numeric_limits<int>::max)() / max_value[k]; + for (int i = 0; i < cur_sz + 1; i++) + for (int j = 0; j < cur_sz; j++) { + point_data<int> point1_1(10 * i, 10 * j); + point_data<int> point1_2(koef * 10 * i, koef * 10 * j); + point_data<int> point2_1(10 * i, 10 * j + 10); + point_data<int> point2_2(koef * 10 * i, koef * (10 * j + 10)); + segments_small.push_back(segment_data<int>(point1_1, point2_1)); + segments_large.push_back(segment_data<int>(point1_2, point2_2)); + point_data<int> point3_1(10 * j, 10 * i); + point_data<int> point3_2(koef * 10 * j, koef * 10 * i); + point_data<int> point4_1(10 * j + 10, 10 * i); + point_data<int> point4_2(koef * (10 * j + 10), koef * 10 * i); + segments_small.push_back(segment_data<int>(point3_1, point4_1)); + segments_large.push_back(segment_data<int>(point3_2, point4_2)); + } + construct_voronoi(segments_small.begin(), segments_small.end(), &test_output_small); + construct_voronoi(segments_large.begin(), segments_large.end(), &test_output_large); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_small); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_large); + BOOST_TEST_EQ(test_output_small.num_cells(), test_output_large.num_cells()); + BOOST_TEST_EQ(test_output_small.num_vertices(), test_output_large.num_vertices()); + BOOST_TEST_EQ(test_output_small.num_edges(), test_output_large.num_edges()); + } +} +#endif + +#ifdef NDEBUG +void segment_random_test1() +{ + boost::mt19937 gen(static_cast<unsigned int>(time(NULL))); + vd_type test_output; + std::vector< point_data<int> > points; + std::vector< segment_data<int> > segments; + int num_runs = 1000; + int num_segments = 10; + points.push_back(point_data<int>(-100, -100)); + points.push_back(point_data<int>(-100, 100)); + points.push_back(point_data<int>(100, -100)); + points.push_back(point_data<int>(100, 100)); + for (int i = 0; i < num_runs; i++) { + test_output.clear(); + segments.clear(); + for (int j = 0; j < num_segments; j++) { + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + while (x1 == x2 && y1 == y2) { + x1 = (gen() % 100) - 50; + y1 = (gen() % 100) - 50; + x2 = (gen() % 100) - 50; + y2 = (gen() % 100) - 50; + } + point_data<int> point1(x1, y1); + point_data<int> point2(x2, y2); + segments.push_back(segment_data<int>(point1, point2)); + } + voronoi_test_helper::clean_segment_set(segments); + construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output); + } +} +#endif + +#ifdef NDEBUG +void segment_random_test2() +{ + boost::mt19937 gen(static_cast<unsigned int>(time(NULL))); + vd_type test_output_small, test_output_large; + std::vector< segment_data<int> > segments_small, segments_large; + int num_segments[] = {5, 25, 125, 625}; + int num_runs[] = {1000, 100, 10, 1}; + int mod_koef1[] = {10, 100, 200, 300}; + int mod_koef2[] = {10, 20, 50, 100}; + int max_value[] = {10, 60, 125, 200}; + int array_length = sizeof(num_segments) / sizeof(int); + for (int k = 0; k < array_length; k++) { + int koef = (std::numeric_limits<int>::max)() / max_value[k]; + for (int i = 0; i < num_runs[k]; i++) { + test_output_small.clear(); + test_output_large.clear(); + segments_small.clear(); + segments_large.clear(); + for (int j = 0; j < num_segments[k]; j++) { + int x1 = (gen() % mod_koef1[k]) - mod_koef1[k] / 2; + int y1 = (gen() % mod_koef1[k]) - mod_koef1[k] / 2; + int dx = 0, dy = 0; + while (dx == 0 && dy == 0) { + dx = (gen() % mod_koef2[k]) - mod_koef2[k] / 2; + dy = (gen() % mod_koef2[k]) - mod_koef2[k] / 2; + } + int x2 = x1 + dx; + int y2 = y1 + dy; + point_data<int> point1_small(x1, y1); + point_data<int> point2_small(x2, y2); + segments_small.push_back(segment_data<int>(point1_small, point2_small)); + } + voronoi_test_helper::clean_segment_set(segments_small); + for (std::vector< segment_data<int> >::iterator it = segments_small.begin(); + it != segments_small.end(); ++it) { + int x1 = it->low().x() * koef; + int y1 = it->low().y() * koef; + int x2 = it->high().x() * koef; + int y2 = it->high().y() * koef; + point_data<int> point1_large(x1, y1); + point_data<int> point2_large(x2, y2); + segments_large.push_back(segment_data<int>(point1_large, point2_large)); + } + construct_voronoi(segments_small.begin(), segments_small.end(), &test_output_small); + construct_voronoi(segments_large.begin(), segments_large.end(), &test_output_large); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_small); + VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_large); + BOOST_TEST_EQ(test_output_small.num_cells(), test_output_large.num_cells()); + BOOST_TEST_EQ(test_output_small.num_vertices(), test_output_large.num_vertices()); + BOOST_TEST_EQ(test_output_small.num_edges(), test_output_large.num_edges()); + } + } +} +#endif + +int main() +{ + single_site_test(); + collinear_sites_test1(); + collinear_sites_test2(); + triangle_test1(); + triangle_test2(); + square_test1(); +#ifdef NDEBUG + grid_test(); + random_test(); +#endif + segment_sites_test1(); + segment_sites_test2(); + segment_sites_test3(); + segment_sites_test4(); + segment_site_test5(); + segment_site_test6(); + segment_site_test7(); + segment_site_test8(); + segment_site_test9(); +#ifdef NDEBUG + segment_grid_test(); + segment_random_test1(); + segment_random_test2(); +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_ctypes_test.cpp b/src/boost/libs/polygon/test/voronoi_ctypes_test.cpp new file mode 100644 index 00000000..6087e724 --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_ctypes_test.cpp @@ -0,0 +1,334 @@ +// Boost.Polygon library voronoi_ctypes_test.cpp file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/detail/voronoi_ctypes.hpp> +#include <boost/random/mersenne_twister.hpp> +#include <vector> +#include <ctime> + +using namespace boost::polygon::detail; + +type_converter_fpt to_fpt; + +void ulp_comparison_test1() +{ + ulp_comparison<double> ulp_cmp; + uint64 a = 22; + uint64 b = 27; + fpt64 da, db; + std::memcpy(&da, &a, sizeof(uint64)); + std::memcpy(&db, &b, sizeof(uint64)); + BOOST_TEST_EQ(ulp_cmp(da, db, 1), ulp_cmp.LESS); + BOOST_TEST_EQ(ulp_cmp(db, da, 1), ulp_cmp.MORE); + BOOST_TEST_EQ(ulp_cmp(da, db, 4), ulp_cmp.LESS); + BOOST_TEST_EQ(ulp_cmp(da, db, 5), ulp_cmp.EQUAL); + BOOST_TEST_EQ(ulp_cmp(da, db, 6), ulp_cmp.EQUAL); +} + +void ulp_comparison_test2() +{ + ulp_comparison<fpt64> ulp_cmp; + uint64 a = 0ULL; + uint64 b = 0x8000000000000002ULL; + fpt64 da, db; + std::memcpy(&da, &a, sizeof(uint64)); + std::memcpy(&db, &b, sizeof(uint64)); + BOOST_TEST_EQ(ulp_cmp(da, db, 1), ulp_cmp.MORE); + BOOST_TEST_EQ(ulp_cmp(db, da, 1), ulp_cmp.LESS); + BOOST_TEST_EQ(ulp_cmp(da, db, 2), ulp_cmp.EQUAL); + BOOST_TEST_EQ(ulp_cmp(da, db, 3), ulp_cmp.EQUAL); +} + +void extended_exponent_fpt_test1() +{ + boost::mt19937_64 gen(static_cast<uint32>(time(NULL))); + fpt64 b = 0.0; + efpt64 eeb(b); + for (int i = 0; i < 1000; ++i) { + fpt64 a = to_fpt(static_cast<int64>(gen())); + efpt64 eea(a); + efpt64 neg = -eea; + efpt64 sum = eea + eeb; + efpt64 dif = eea - eeb; + efpt64 mul = eea * eeb; + BOOST_TEST_EQ(to_fpt(neg), -a); + BOOST_TEST_EQ(to_fpt(sum), a + b); + BOOST_TEST_EQ(to_fpt(dif), a - b); + BOOST_TEST_EQ(to_fpt(mul), a * b); + } +} + +void extended_exponent_fpt_test2() +{ + boost::mt19937_64 gen(static_cast<uint32>(time(NULL))); + fpt64 a = 0.0; + efpt64 eea(a); + for (int i = 0; i < 1000; ++i) { + fpt64 b = to_fpt(static_cast<int64>(gen())); + if (b == 0.0) + continue; + efpt64 eeb(b); + efpt64 neg = -eea; + efpt64 sum = eea + eeb; + efpt64 dif = eea - eeb; + efpt64 mul = eea * eeb; + efpt64 div = eea / eeb; + BOOST_TEST_EQ(to_fpt(neg), -a); + BOOST_TEST_EQ(to_fpt(sum), a + b); + BOOST_TEST_EQ(to_fpt(dif), a - b); + BOOST_TEST_EQ(to_fpt(mul), a * b); + BOOST_TEST_EQ(to_fpt(div), a / b); + } +} + +void extended_exponent_fpt_test3() +{ + boost::mt19937_64 gen(static_cast<uint32>(time(NULL))); + for (int i = 0; i < 1000; ++i) { + fpt64 a = to_fpt(static_cast<int64>(gen())); + fpt64 b = to_fpt(static_cast<int64>(gen())); + if (b == 0.0) + continue; + efpt64 eea(a); + efpt64 eeb(b); + efpt64 neg = -eea; + efpt64 sum = eea + eeb; + efpt64 dif = eea - eeb; + efpt64 mul = eea * eeb; + efpt64 div = eea / eeb; + BOOST_TEST_EQ(to_fpt(neg), -a); + BOOST_TEST_EQ(to_fpt(sum), a + b); + BOOST_TEST_EQ(to_fpt(dif), a - b); + BOOST_TEST_EQ(to_fpt(mul), a * b); + BOOST_TEST_EQ(to_fpt(div), a / b); + } +} + +void extended_exponent_fpt_test4() +{ + for (int exp = 0; exp < 64; ++exp) + for (int i = 1; i < 100; ++i) { + fpt64 a = i; + fpt64 b = to_fpt(1LL << exp); + efpt64 eea(a); + efpt64 eeb(b); + efpt64 neg = -eea; + efpt64 sum = eea + eeb; + efpt64 dif = eea - eeb; + efpt64 mul = eea * eeb; + efpt64 div = eea / eeb; + BOOST_TEST_EQ(to_fpt(neg), -a); + BOOST_TEST_EQ(to_fpt(sum), a + b); + BOOST_TEST_EQ(to_fpt(dif), a - b); + BOOST_TEST_EQ(to_fpt(mul), a * b); + BOOST_TEST_EQ(to_fpt(div), a / b); + } +} + +void extended_exponent_fpt_test5() +{ + for (int i = 0; i < 100; ++i) { + efpt64 a(to_fpt(i * i)); + efpt64 b = a.sqrt(); + BOOST_TEST_EQ(to_fpt(b), to_fpt(i)); + } +} + +void extended_exponent_fpt_test6() +{ + for (int i = -10; i <= 10; ++i) { + efpt64 a(to_fpt(i)); + BOOST_TEST_EQ(is_pos(a), i > 0); + BOOST_TEST_EQ(is_neg(a), i < 0); + BOOST_TEST_EQ(is_zero(a), !i); + } +} + +void extended_int_test1() +{ + typedef extended_int<1> eint32; + eint32 e1(0), e2(32), e3(-32); + BOOST_TEST_EQ(e1.count(), 0); + BOOST_TEST_EQ(e1.size(), 0U); + BOOST_TEST_EQ(e2.count(), 1); + BOOST_TEST_EQ(e2.chunks()[0], 32U); + BOOST_TEST_EQ(e2.size(), 1U); + BOOST_TEST_EQ(e3.count(), -1); + BOOST_TEST_EQ(e3.chunks()[0], 32U); + BOOST_TEST_EQ(e3.size(), 1U); +} + +void extended_int_test2() +{ + typedef extended_int<2> eint64; + int64 val64 = 0x7fffffffffffffffLL; + eint64 e1(0), e2(32), e3(-32), e4(val64), e5(-val64); + BOOST_TEST_EQ(e1.count(), 0); + BOOST_TEST_EQ(e2.count(), 1); + BOOST_TEST_EQ(e2.chunks()[0], 32U); + BOOST_TEST_EQ(e3.count(), -1); + BOOST_TEST_EQ(e3.chunks()[0], 32U); + BOOST_TEST_EQ(e4.count(), 2); + BOOST_TEST_EQ(e4.chunks()[0], 0xffffffff); + BOOST_TEST_EQ(e4.chunks()[1], val64 >> 32); + BOOST_TEST_EQ(e5.count(), -2); + BOOST_TEST_EQ(e5.chunks()[0], 0xffffffff); + BOOST_TEST_EQ(e5.chunks()[1], val64 >> 32); +} + +void extended_int_test3() +{ + typedef extended_int<2> eint64; + std::vector<uint32> chunks; + chunks.push_back(1); + chunks.push_back(2); + eint64 e1(chunks, true), e2(chunks, false); + BOOST_TEST_EQ(e1.count(), 2); + BOOST_TEST_EQ(e1.chunks()[0], 2U); + BOOST_TEST_EQ(e1.chunks()[1], 1U); + BOOST_TEST_EQ(e2.count(), -2); + BOOST_TEST_EQ(e2.chunks()[0], 2U); + BOOST_TEST_EQ(e2.chunks()[1], 1U); +} + +void extended_int_test4() +{ + typedef extended_int<2> eint64; + std::vector<uint32> chunks; + chunks.push_back(1); + chunks.push_back(2); + eint64 e1(chunks, true), e2(chunks, false); + BOOST_TEST_EQ(e1 == e2, false); + BOOST_TEST_EQ(e1 == -e2, true); + BOOST_TEST_EQ(e1 != e2, true); + BOOST_TEST_EQ(e1 != -e2, false); + BOOST_TEST_EQ(e1 < e2, false); + BOOST_TEST_EQ(e1 < -e2, false); + BOOST_TEST_EQ(e1 <= e2, false); + BOOST_TEST_EQ(e1 <= -e2, true); + BOOST_TEST_EQ(e1 > e2, true); + BOOST_TEST_EQ(e1 > -e2, false); + BOOST_TEST_EQ(e1 >= e2, true); + BOOST_TEST_EQ(e1 >= -e2, true); +} + +void extended_int_test5() +{ + typedef extended_int<2> eint64; + boost::mt19937_64 gen(static_cast<uint32>(time(NULL))); + for (int i = 0; i < 1000; ++i) { + int64 i1 = static_cast<int64>(gen()); + int64 i2 = static_cast<int64>(gen()); + eint64 e1(i1), e2(i2); + BOOST_TEST_EQ(e1 == e2, i1 == i2); + BOOST_TEST_EQ(e1 != e2, i1 != i2); + BOOST_TEST_EQ(e1 > e2, i1 > i2); + BOOST_TEST_EQ(e1 >= e2, i1 >= i2); + BOOST_TEST_EQ(e1 < e2, i1 < i2); + BOOST_TEST_EQ(e1 <= e2, i1 <= i2); + } +} + +void extended_int_test6() +{ + typedef extended_int<1> eint32; + eint32 e1(32); + eint32 e2 = -e1; + BOOST_TEST_EQ(e2.count(), -1); + BOOST_TEST_EQ(e2.size(), 1U); + BOOST_TEST_EQ(e2.chunks()[0], 32U); +} + +void extended_int_test7() +{ + typedef extended_int<2> eint64; + boost::mt19937_64 gen(static_cast<uint32>(time(NULL))); + for (int i = 0; i < 1000; ++i) { + int64 i1 = static_cast<int64>(gen()) >> 2; + int64 i2 = static_cast<int64>(gen()) >> 2; + eint64 e1(i1), e2(i2), e3(i1 + i2), e4(i1 - i2); + BOOST_TEST(e1 + e2 == e3); + BOOST_TEST(e1 - e2 == e4); + } +} + +void extended_int_test8() +{ + typedef extended_int<2> eint64; + boost::mt19937 gen(static_cast<uint32>(time(NULL))); + for (int i = 0; i < 1000; ++i) { + int64 i1 = static_cast<int32>(gen()); + int64 i2 = static_cast<int32>(gen()); + eint64 e1(i1), e2(i2), e3(i1 * i2); + BOOST_TEST(e1 * e2 == e3); + } +} + +void extended_int_test9() +{ + typedef extended_int<1> eint32; + for (int i = -10; i <= 10; ++i) { + for (int j = -10; j <= 10; ++j) { + eint32 e1(i), e2(j), e3(i+j), e4(i-j), e5(i*j); + BOOST_TEST(e1 + e2 == e3); + BOOST_TEST(e1 - e2 == e4); + BOOST_TEST(e1 * e2 == e5); + } + } +} + +void extended_int_test10() +{ + typedef extended_int<2> eint64; + boost::mt19937_64 gen(static_cast<uint32>(time(NULL))); + for (int i = 0; i < 100; ++i) { + int64 i1 = static_cast<int64>(gen()) >> 20; + int64 i2 = i1 >> 32; + eint64 e1(i1), e2(i2); + BOOST_TEST(to_fpt(e1) == static_cast<fpt64>(i1)); + BOOST_TEST(to_fpt(e2) == static_cast<fpt64>(i2)); + } +} + +void extened_int_test11() +{ + typedef extended_int<64> eint2048; + eint2048 two(2), value(1); + for (int i = 0; i < 1024; ++i) + value = value * two; + BOOST_TEST_EQ(value.count(), 33); + for (std::size_t i = 1; i < value.size(); ++i) + BOOST_TEST_EQ(value.chunks()[i-1], 0U); + BOOST_TEST_EQ(value.chunks()[32], 1U); +} + +int main() +{ + ulp_comparison_test1(); + ulp_comparison_test2(); + extended_exponent_fpt_test1(); + extended_exponent_fpt_test2(); + extended_exponent_fpt_test3(); + extended_exponent_fpt_test4(); + extended_exponent_fpt_test5(); + extended_exponent_fpt_test6(); + extended_int_test1(); + extended_int_test2(); + extended_int_test3(); + extended_int_test4(); + extended_int_test5(); + extended_int_test6(); + extended_int_test7(); + extended_int_test8(); + extended_int_test9(); + extended_int_test10(); + extened_int_test11(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_diagram_test.cpp b/src/boost/libs/polygon/test/voronoi_diagram_test.cpp new file mode 100644 index 00000000..6646a175 --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_diagram_test.cpp @@ -0,0 +1,125 @@ +// Boost.Polygon library voronoi_diagram_test.cpp file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/voronoi_diagram.hpp> +#include <boost/polygon/voronoi_geometry_type.hpp> + +using namespace boost::polygon; + +typedef voronoi_cell<double> voronoi_cell_type; +typedef voronoi_vertex<double> voronoi_vertex_type; +typedef voronoi_edge<double> voronoi_edge_type; +typedef voronoi_diagram<double> voronoi_diagram_type; + +void voronoi_cell_test() +{ + voronoi_cell_type cell(1, SOURCE_CATEGORY_INITIAL_SEGMENT); + cell.color(27); + BOOST_TEST(!cell.contains_point()); + BOOST_TEST(cell.contains_segment()); + BOOST_TEST(cell.is_degenerate()); + BOOST_TEST(cell.source_index() == 1); + BOOST_TEST(cell.source_category() == SOURCE_CATEGORY_INITIAL_SEGMENT); + BOOST_TEST(cell.incident_edge() == NULL); + BOOST_TEST(cell.color() == 27); + + voronoi_edge_type edge(true, true); + cell.incident_edge(&edge); + BOOST_TEST(!cell.is_degenerate()); + BOOST_TEST(cell.incident_edge() == &edge); +} + +void voronoi_vertex_test() +{ + voronoi_vertex_type vertex(1, 2); + vertex.color(27); + BOOST_TEST(vertex.is_degenerate()); + BOOST_TEST(vertex.x() == 1); + BOOST_TEST(vertex.y() == 2); + BOOST_TEST(vertex.incident_edge() == NULL); + BOOST_TEST(vertex.color() == 27); + + voronoi_edge_type edge(true, true); + vertex.incident_edge(&edge); + BOOST_TEST(!vertex.is_degenerate()); + BOOST_TEST(vertex.incident_edge() == &edge); +} + +void voronoi_edge_test() +{ + voronoi_edge_type edge1(false, false); + edge1.color(13); + BOOST_TEST(!edge1.is_primary()); + BOOST_TEST(edge1.is_secondary()); + BOOST_TEST(!edge1.is_linear()); + BOOST_TEST(edge1.is_curved()); + BOOST_TEST(!edge1.is_finite()); + BOOST_TEST(edge1.is_infinite()); + BOOST_TEST(edge1.color() == 13); + + voronoi_edge_type edge2(true, true); + edge2.color(14); + BOOST_TEST(edge2.is_primary()); + BOOST_TEST(!edge2.is_secondary()); + BOOST_TEST(edge2.is_linear()); + BOOST_TEST(!edge2.is_curved()); + BOOST_TEST(!edge2.is_finite()); + BOOST_TEST(edge2.is_infinite()); + BOOST_TEST(edge2.color() == 14); + + edge1.twin(&edge2); + edge2.twin(&edge1); + BOOST_TEST(edge1.twin() == &edge2); + BOOST_TEST(edge2.twin() == &edge1); + + edge1.next(&edge2); + edge1.prev(&edge2); + edge2.next(&edge1); + edge2.prev(&edge1); + BOOST_TEST(edge1.next() == &edge2); + BOOST_TEST(edge1.prev() == &edge2); + BOOST_TEST(edge1.rot_next() == &edge1); + BOOST_TEST(edge1.rot_prev() == &edge1); + + voronoi_cell_type cell(1, SOURCE_CATEGORY_INITIAL_SEGMENT); + edge1.cell(&cell); + BOOST_TEST(edge1.cell() == &cell); + + voronoi_vertex_type vertex0(1, 2); + edge1.vertex0(&vertex0); + BOOST_TEST(edge1.vertex0() == &vertex0); + BOOST_TEST(edge2.vertex1() == &vertex0); + + voronoi_vertex_type vertex1(2, 1); + edge2.vertex0(&vertex1); + BOOST_TEST(edge1.vertex1() == &vertex1); + BOOST_TEST(edge2.vertex0() == &vertex1); + + BOOST_TEST(edge1.is_finite()); + BOOST_TEST(edge2.is_finite()); +} + +void voronoi_diagram_test() +{ + voronoi_diagram_type vd; + BOOST_TEST(vd.num_cells() == 0); + BOOST_TEST(vd.num_vertices() == 0); + BOOST_TEST(vd.num_edges() == 0); + vd.clear(); +} + +int main() +{ + voronoi_cell_test(); + voronoi_vertex_test(); + voronoi_edge_test(); + voronoi_diagram_test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_geometry_type_test.cpp b/src/boost/libs/polygon/test/voronoi_geometry_type_test.cpp new file mode 100644 index 00000000..82dd9fe4 --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_geometry_type_test.cpp @@ -0,0 +1,34 @@ +// Boost.Polygon library voronoi_geometry_type_test.cpp file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/voronoi_geometry_type.hpp> + +using namespace boost::polygon; + +void source_category_test1() +{ + BOOST_TEST(belongs(SOURCE_CATEGORY_SINGLE_POINT, GEOMETRY_CATEGORY_POINT)); + BOOST_TEST(belongs(SOURCE_CATEGORY_SEGMENT_START_POINT, GEOMETRY_CATEGORY_POINT)); + BOOST_TEST(belongs(SOURCE_CATEGORY_SEGMENT_END_POINT, GEOMETRY_CATEGORY_POINT)); + BOOST_TEST(!belongs(SOURCE_CATEGORY_INITIAL_SEGMENT, GEOMETRY_CATEGORY_POINT)); + BOOST_TEST(!belongs(SOURCE_CATEGORY_REVERSE_SEGMENT, GEOMETRY_CATEGORY_POINT)); + + BOOST_TEST(!belongs(SOURCE_CATEGORY_SINGLE_POINT, GEOMETRY_CATEGORY_SEGMENT)); + BOOST_TEST(!belongs(SOURCE_CATEGORY_SEGMENT_START_POINT, GEOMETRY_CATEGORY_SEGMENT)); + BOOST_TEST(!belongs(SOURCE_CATEGORY_SEGMENT_END_POINT, GEOMETRY_CATEGORY_SEGMENT)); + BOOST_TEST(belongs(SOURCE_CATEGORY_INITIAL_SEGMENT, GEOMETRY_CATEGORY_SEGMENT)); + BOOST_TEST(belongs(SOURCE_CATEGORY_REVERSE_SEGMENT, GEOMETRY_CATEGORY_SEGMENT)); +} + +int main() +{ + source_category_test1(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_predicates_test.cpp b/src/boost/libs/polygon/test/voronoi_predicates_test.cpp new file mode 100644 index 00000000..1f5b3fb3 --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_predicates_test.cpp @@ -0,0 +1,636 @@ +// Boost.Polygon library voronoi_predicates_test.cpp file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/detail/voronoi_ctypes.hpp> +#include <boost/polygon/detail/voronoi_predicates.hpp> +#include <boost/polygon/detail/voronoi_structures.hpp> +#include <boost/polygon/voronoi_geometry_type.hpp> +#include <limits> +#include <map> + +using namespace boost::polygon::detail; +using namespace boost::polygon; + +ulp_comparison<double> ulp_cmp; + +typedef voronoi_predicates< voronoi_ctype_traits<int> > VP; +typedef point_2d<int> point_type; +typedef site_event<int> site_type; +typedef circle_event<double> circle_type; +VP::event_comparison_predicate<site_type, circle_type> event_comparison; + +typedef beach_line_node_key<site_type> key_type; +typedef VP::distance_predicate<site_type> distance_predicate_type; +typedef VP::node_comparison_predicate<key_type> node_comparison_type; +typedef std::map<key_type, int, node_comparison_type> beach_line_type; +typedef beach_line_type::iterator bieach_line_iterator; +distance_predicate_type distance_predicate; +node_comparison_type node_comparison; + +typedef VP::circle_existence_predicate<site_type> CEP_type; +typedef VP::mp_circle_formation_functor<site_type, circle_type> MP_CFF_type; +typedef VP::lazy_circle_formation_functor<site_type, circle_type> lazy_CFF_type; +VP::circle_formation_predicate<site_type, circle_type, CEP_type, MP_CFF_type> mp_predicate; +VP::circle_formation_predicate<site_type, circle_type, CEP_type, lazy_CFF_type> lazy_predicate; + +#define CHECK_ORIENTATION(P1, P2, P3, R1, R2) \ + BOOST_TEST_EQ(VP::ot::eval(P1, P2, P3) == R1, true); \ + BOOST_TEST_EQ(VP::ot::eval(P1, P3, P2) == R2, true); \ + BOOST_TEST_EQ(VP::ot::eval(P2, P1, P3) == R2, true); \ + BOOST_TEST_EQ(VP::ot::eval(P2, P3, P1) == R1, true); \ + BOOST_TEST_EQ(VP::ot::eval(P3, P1, P2) == R1, true); \ + BOOST_TEST_EQ(VP::ot::eval(P3, P2, P1) == R2, true) + +#define CHECK_EVENT_COMPARISON(A, B, R1, R2) \ + BOOST_TEST_EQ(event_comparison(A, B), R1); \ + BOOST_TEST_EQ(event_comparison(B, A), R2) + +#define CHECK_DISTANCE_PREDICATE(S1, S2, P3, RES) \ + BOOST_TEST_EQ(distance_predicate(S1, S2, P3), RES) + +#define CHECK_NODE_COMPARISON(node, nodes, res, sz) \ + for (int i = 0; i < sz; ++i) { \ + BOOST_TEST_EQ(node_comparison(node, nodes[i]), res[i]); \ + BOOST_TEST_EQ(node_comparison(nodes[i], node), !res[i]); \ + } + +#define CHECK_CIRCLE(circle, c_x, c_y, l_x) \ + BOOST_TEST_EQ(ulp_cmp(c1.x(), c_x, 10), ulp_comparison<double>::EQUAL); \ + BOOST_TEST_EQ(ulp_cmp(c1.y(), c_y, 10), ulp_comparison<double>::EQUAL); \ + BOOST_TEST_EQ(ulp_cmp(c1.lower_x(), l_x, 10), ulp_comparison<double>::EQUAL) + +#define CHECK_CIRCLE_EXISTENCE(s1, s2, s3, RES) \ + { circle_type c1; \ + BOOST_TEST_EQ(lazy_predicate(s1, s2, s3, c1), RES); } + +#define CHECK_CIRCLE_FORMATION_PREDICATE(s1, s2, s3, c_x, c_y, l_x) \ + { circle_type c1, c2; \ + BOOST_TEST_EQ(mp_predicate(s1, s2, s3, c1), true); \ + BOOST_TEST_EQ(lazy_predicate(s1, s2, s3, c2), true); \ + CHECK_CIRCLE(c1, c_x, c_y, l_x); \ + CHECK_CIRCLE(c2, c_x, c_y, l_x); } + +void orientation_test() +{ + int min_int = (std::numeric_limits<int>::min)(); + int max_int = (std::numeric_limits<int>::max)(); + point_type point1(min_int, min_int); + point_type point2(0, 0); + point_type point3(max_int, max_int); + point_type point4(min_int, max_int); + point_type point5(max_int-1, max_int); + CHECK_ORIENTATION(point1, point2, point3, VP::ot::COLLINEAR, VP::ot::COLLINEAR); + CHECK_ORIENTATION(point1, point4, point3, VP::ot::RIGHT, VP::ot::LEFT); + CHECK_ORIENTATION(point1, point5, point3, VP::ot::RIGHT, VP::ot::LEFT); +} + +void event_comparison_test1() +{ + site_type site(1, 2); + CHECK_EVENT_COMPARISON(site, site_type(0, 2), false, true); + CHECK_EVENT_COMPARISON(site, site_type(1, 3), true, false); + CHECK_EVENT_COMPARISON(site, site_type(1, 2), false, false); +} + +void event_comparison_test2() +{ + site_type site(0, 0, 0, 2); + CHECK_EVENT_COMPARISON(site, site_type(0, 2), true, false); + CHECK_EVENT_COMPARISON(site, site_type(0, 0), false, true); + CHECK_EVENT_COMPARISON(site, site_type(0, -2, 0, -1), false, true); + CHECK_EVENT_COMPARISON(site, site_type(0, -2, 1, 1), true, false); + CHECK_EVENT_COMPARISON(site, site_type(0, 0, 1, 1), true, false); +} + +void event_comparison_test3() +{ + site_type site(0, 0, 10, 10); + CHECK_EVENT_COMPARISON(site, site_type(0, 0), false, true); + CHECK_EVENT_COMPARISON(site, site_type(0, -1), false, true); + CHECK_EVENT_COMPARISON(site, site_type(0, 1), false, true); + CHECK_EVENT_COMPARISON(site, site_type(0, 1, 0, 10), false, true); + CHECK_EVENT_COMPARISON(site, site_type(0, -10, 0, -1), false, true); + CHECK_EVENT_COMPARISON(site, site_type(0, 0, 10, 9), true, false); + CHECK_EVENT_COMPARISON(site, site_type(0, 0, 9, 10), false, true); +} + +void event_comparison_test4() +{ + circle_type circle(1, 2, 3); + CHECK_EVENT_COMPARISON(circle, circle_type(1, 2, 3), false, false); + CHECK_EVENT_COMPARISON(circle, circle_type(1, 3, 3), true, false); + CHECK_EVENT_COMPARISON(circle, circle_type(1, 2, 4), true, false); + CHECK_EVENT_COMPARISON(circle, circle_type(0, 2, 2), false, true); + CHECK_EVENT_COMPARISON(circle, circle_type(-1, 2, 3), false, false); +} + +void event_comparison_test5() +{ + circle_type circle(1, 2, 3); + CHECK_EVENT_COMPARISON(circle, site_type(0, 100), false, true); + CHECK_EVENT_COMPARISON(circle, site_type(3, 0), false, false); + CHECK_EVENT_COMPARISON(circle, site_type(3, 2), false, false); + CHECK_EVENT_COMPARISON(circle, site_type(3, 3), false, false); + CHECK_EVENT_COMPARISON(circle, site_type(4, 2), true, false); +} + +void distance_predicate_test1() +{ + site_type site1(-5, 0); + site1.sorted_index(1); + site_type site2(-8, 9); + site2.sorted_index(0); + site_type site3(-2, 1); + site3.sorted_index(2); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 5), false); + CHECK_DISTANCE_PREDICATE(site3, site1, point_type(0, 5), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 4), false); + CHECK_DISTANCE_PREDICATE(site3, site1, point_type(0, 4), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 6), true); + CHECK_DISTANCE_PREDICATE(site3, site1, point_type(0, 6), true); +} + +void distance_predicate_test2() +{ + site_type site1(-4, 0, -4, 20); + site1.sorted_index(0); + site_type site2(-2, 10); + site2.sorted_index(1); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, 11), false); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, 9), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 11), true); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 9), true); +} + +void distance_predicate_test3() +{ + site_type site1(-5, 5, 2, -2); + site1.sorted_index(0); + site1.inverse(); + site_type site2(-2, 4); + site2.sorted_index(1); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, -1), false); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, -1), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 1), false); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, 1), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 4), true); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, 4), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 5), true); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, 5), false); +} + +void distance_predicate_test4() +{ + site_type site1(-5, 5, 2, -2); + site1.sorted_index(0); + site_type site2(-2, -4); + site2.sorted_index(2); + site_type site3(-4, 1); + site3.sorted_index(1); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, 1), true); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, 1), true); + CHECK_DISTANCE_PREDICATE(site1, site3, point_type(0, 1), true); + CHECK_DISTANCE_PREDICATE(site3, site1, point_type(0, 1), true); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, -2), true); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, -2), false); + CHECK_DISTANCE_PREDICATE(site1, site3, point_type(0, -2), true); + CHECK_DISTANCE_PREDICATE(site3, site1, point_type(0, -2), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, -8), true); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, -8), false); + CHECK_DISTANCE_PREDICATE(site1, site3, point_type(0, -8), true); + CHECK_DISTANCE_PREDICATE(site3, site1, point_type(0, -8), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(0, -9), true); + CHECK_DISTANCE_PREDICATE(site2, site1, point_type(0, -9), false); + CHECK_DISTANCE_PREDICATE(site1, site3, point_type(0, -9), true); + CHECK_DISTANCE_PREDICATE(site3, site1, point_type(0, -9), false); +} + +void distance_predicate_test5() +{ + site_type site1(-5, 5, 2, -2); + site1.sorted_index(0); + site_type site2 = site1; + site2.inverse(); + site_type site3(-2, 4); + site3.sorted_index(3); + site_type site4(-2, -4); + site4.sorted_index(2); + site_type site5(-4, 1); + site5.sorted_index(1); + CHECK_DISTANCE_PREDICATE(site3, site2, point_type(0, 1), false); + CHECK_DISTANCE_PREDICATE(site3, site2, point_type(0, 4), false); + CHECK_DISTANCE_PREDICATE(site3, site2, point_type(0, 5), false); + CHECK_DISTANCE_PREDICATE(site3, site2, point_type(0, 7), true); + CHECK_DISTANCE_PREDICATE(site4, site1, point_type(0, -2), false); + CHECK_DISTANCE_PREDICATE(site5, site1, point_type(0, -2), false); + CHECK_DISTANCE_PREDICATE(site4, site1, point_type(0, -8), false); + CHECK_DISTANCE_PREDICATE(site5, site1, point_type(0, -8), false); + CHECK_DISTANCE_PREDICATE(site4, site1, point_type(0, -9), false); + CHECK_DISTANCE_PREDICATE(site5, site1, point_type(0, -9), false); + CHECK_DISTANCE_PREDICATE(site4, site1, point_type(0, -18), false); + CHECK_DISTANCE_PREDICATE(site5, site1, point_type(0, -18), false); + CHECK_DISTANCE_PREDICATE(site4, site1, point_type(0, -1), true); + CHECK_DISTANCE_PREDICATE(site5, site1, point_type(0, -1), true); +} + +void distance_predicate_test6() +{ + site_type site1(-5, 0, 2, 7); + site_type site2 = site1; + site2.inverse(); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(2, 7), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(1, 5), false); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(-1, 5), true); +} + +void distance_predicate_test7() +{ + site_type site1(-5, 5, 2, -2); + site1.sorted_index(1); + site1.inverse(); + site_type site2(-5, 5, 0, 6); + site2.sorted_index(0); + site_type site3(-2, 4, 0, 4); + site3.sorted_index(2); + point_type site4(0, 2); + point_type site5(0, 5); + point_type site6(0, 6); + point_type site7(0, 8); + CHECK_DISTANCE_PREDICATE(site1, site2, site4, false); + CHECK_DISTANCE_PREDICATE(site1, site2, site5, true); + CHECK_DISTANCE_PREDICATE(site1, site2, site6, true); + CHECK_DISTANCE_PREDICATE(site1, site2, site7, true); + CHECK_DISTANCE_PREDICATE(site1, site3, site4, false); + CHECK_DISTANCE_PREDICATE(site1, site3, site5, true); + CHECK_DISTANCE_PREDICATE(site1, site3, site6, true); + CHECK_DISTANCE_PREDICATE(site1, site3, site7, true); + site3.inverse(); + CHECK_DISTANCE_PREDICATE(site3, site1, site4, false); + CHECK_DISTANCE_PREDICATE(site3, site1, site5, false); + CHECK_DISTANCE_PREDICATE(site3, site1, site6, false); + CHECK_DISTANCE_PREDICATE(site3, site1, site7, true); +} + +void distance_predicate_test8() +{ + site_type site1(-5, 3, -2, 2); + site1.sorted_index(0); + site1.inverse(); + site_type site2(-5, 5, -2, 2); + site2.sorted_index(1); + CHECK_DISTANCE_PREDICATE(site1, site2, point_type(-4, 2), false); +} + +void node_comparison_test1() +{ + beach_line_type beach_line; + site_type site1(0, 0); + site1.sorted_index(0); + site_type site2(0, 2); + site2.sorted_index(1); + site_type site3(1, 0); + site3.sorted_index(2); + beach_line[key_type(site1, site2)] = 2; + beach_line[key_type(site1, site3)] = 0; + beach_line[key_type(site3, site1)] = 1; + int cur_index = 0; + for (bieach_line_iterator it = beach_line.begin(); + it != beach_line.end(); ++it, ++cur_index) { + BOOST_TEST_EQ(it->second, cur_index); + } +} + +void node_comparison_test2() +{ + beach_line_type beach_line; + site_type site1(0, 1); + site1.sorted_index(0); + site_type site2(2, 0); + site2.sorted_index(1); + site_type site3(2, 4); + site3.sorted_index(2); + beach_line[key_type(site1, site2)] = 0; + beach_line[key_type(site2, site1)] = 1; + beach_line[key_type(site1, site3)] = 2; + beach_line[key_type(site3, site1)] = 3; + int cur_index = 0; + for (bieach_line_iterator it = beach_line.begin(); + it != beach_line.end(); ++it, ++cur_index) { + BOOST_TEST_EQ(it->second, cur_index); + } +} + +void node_comparison_test3() +{ + key_type node(site_type(1, 0).sorted_index(1), site_type(0, 2).sorted_index(0)); + key_type nodes[] = { + key_type(site_type(2, -10).sorted_index(2)), + key_type(site_type(2, -1).sorted_index(2)), + key_type(site_type(2, 0).sorted_index(2)), + key_type(site_type(2, 1).sorted_index(2)), + key_type(site_type(2, 2).sorted_index(2)), + key_type(site_type(2, 3).sorted_index(2)), + }; + bool res[] = {false, false, false, false, true, true}; + CHECK_NODE_COMPARISON(node, nodes, res, 6); +} + +void node_comparison_test4() +{ + key_type node(site_type(0, 1).sorted_index(0), site_type(1, 0).sorted_index(1)); + key_type nodes[] = { + key_type(site_type(2, -3).sorted_index(2)), + key_type(site_type(2, -2).sorted_index(2)), + key_type(site_type(2, -1).sorted_index(2)), + key_type(site_type(2, 0).sorted_index(2)), + key_type(site_type(2, 1).sorted_index(2)), + key_type(site_type(2, 3).sorted_index(2)), + }; + bool res[] = {false, true, true, true, true, true}; + CHECK_NODE_COMPARISON(node, nodes, res, 6); +} + +void node_comparison_test5() +{ + key_type node(site_type(0, 0).sorted_index(0), site_type(1, 2).sorted_index(1)); + key_type nodes[] = { + key_type(site_type(2, -10).sorted_index(2)), + key_type(site_type(2, 0).sorted_index(2)), + key_type(site_type(2, 1).sorted_index(2)), + key_type(site_type(2, 2).sorted_index(2)), + key_type(site_type(2, 5).sorted_index(2)), + key_type(site_type(2, 20).sorted_index(2)), + }; + bool res[] = {false, false, true, true, true, true}; + CHECK_NODE_COMPARISON(node, nodes, res, 6); +} + +void node_comparison_test6() +{ + key_type node(site_type(1, 1).sorted_index(1), site_type(0, 0).sorted_index(0)); + key_type nodes[] = { + key_type(site_type(2, -3).sorted_index(2)), + key_type(site_type(2, -2).sorted_index(2)), + key_type(site_type(2, 0).sorted_index(2)), + key_type(site_type(2, 1).sorted_index(2)), + key_type(site_type(2, 2).sorted_index(2)), + key_type(site_type(2, 3).sorted_index(2)), + key_type(site_type(2, 5).sorted_index(2)), + }; + bool res[] = {false, false, false, false, false, false, true}; + CHECK_NODE_COMPARISON(node, nodes, res, 7); +} + +void node_comparison_test7() +{ + key_type node(site_type(0, 0).sorted_index(0), site_type(0, 2).sorted_index(1)); + key_type nodes[] = { + key_type(site_type(1, 0).sorted_index(2)), + key_type(site_type(1, 1).sorted_index(2)), + key_type(site_type(1, 2).sorted_index(2)), + }; + bool res[] = {false, false, true}; + CHECK_NODE_COMPARISON(node, nodes, res, 3); +} + +void node_comparison_test8() +{ + key_type node(site_type(0, 0).sorted_index(0), site_type(1, 1).sorted_index(2)); + key_type nodes[] = { + key_type(site_type(1, 0).sorted_index(1)), + key_type(site_type(1, 1).sorted_index(2)), + key_type(site_type(1, 2).sorted_index(3)), + key_type(site_type(1, 1).sorted_index(2), site_type(0, 0).sorted_index(0)), + }; + bool res[] = {false, true, true, true}; + CHECK_NODE_COMPARISON(node, nodes, res, 4); +} + +void circle_formation_predicate_test1() +{ + site_type site1(0, 0); + site1.sorted_index(1); + site_type site2(-8, 0); + site2.sorted_index(0); + site_type site3(0, 6); + site3.sorted_index(2); + CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, -4.0, 3.0, 1.0); +} + +void circle_formation_predicate_test2() +{ + int min_int = (std::numeric_limits<int>::min)(); + int max_int = (std::numeric_limits<int>::max)(); + site_type site1(min_int, min_int); + site1.sorted_index(0); + site_type site2(min_int, max_int); + site2.sorted_index(1); + site_type site3(max_int-1, max_int-1); + site3.sorted_index(2); + site_type site4(max_int, max_int); + site4.sorted_index(3); + CHECK_CIRCLE_EXISTENCE(site1, site2, site4, true); + CHECK_CIRCLE_EXISTENCE(site1, site3, site4, false); +} + +void circle_formation_predicate_test3() +{ + site_type site1(-4, 0); + site1.sorted_index(0); + site_type site2(0, 4); + site2.sorted_index(4); + site_type site3(site1.point0(), site2.point0()); + site3.sorted_index(1); + CHECK_CIRCLE_EXISTENCE(site1, site3, site2, false); + site_type site4(-2, 0); + site4.sorted_index(2); + site_type site5(0, 2); + site5.sorted_index(3); + CHECK_CIRCLE_EXISTENCE(site3, site4, site5, false); + CHECK_CIRCLE_EXISTENCE(site4, site5, site3, false); +} + +void circle_formation_predicate_test4() +{ + site_type site1(-4, 0, -4, 20); + site1.sorted_index(0); + site_type site2(-2, 10); + site2.sorted_index(1); + site_type site3(4, 10); + site3.sorted_index(2); + CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, 1.0, 6.0, 6.0); + CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 1.0, 14.0, 6.0); +} + +void circle_formation_predicate_test5() +{ + site_type site1(1, 0, 7, 0); + site1.sorted_index(2); + site1.inverse(); + site_type site2(-2, 4, 10, 4); + site2.sorted_index(0); + site_type site3(6, 2); + site3.sorted_index(3); + site_type site4(1, 0); + site4.sorted_index(1); + CHECK_CIRCLE_FORMATION_PREDICATE(site3, site1, site2, 4.0, 2.0, 6.0); + CHECK_CIRCLE_FORMATION_PREDICATE(site4, site2, site1, 1.0, 2.0, 3.0); +} + +void circle_formation_predicate_test6() +{ + site_type site1(-1, 2, 8, -10); + site1.sorted_index(1); + site1.inverse(); + site_type site2(-1, 0, 8, 12); + site2.sorted_index(0); + site_type site3(1, 1); + site3.sorted_index(2); + CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 6.0, 1.0, 11.0); +} + +void circle_formation_predicate_test7() +{ + site_type site1(1, 0, 6, 0); + site1.sorted_index(2); + site1.inverse(); + site_type site2(-6, 4, 0, 12); + site2.sorted_index(0); + site_type site3(1, 0); + site3.sorted_index(1); + CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 1.0, 5.0, 6.0); +} + +void circle_formation_predicate_test8() +{ + site_type site1(1, 0, 5, 0); + site1.sorted_index(2); + site1.inverse(); + site_type site2(0, 12, 8, 6); + site2.sorted_index(0); + site_type site3(1, 0); + site3.sorted_index(1); + CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 1.0, 5.0, 6.0); +} + +void circle_formation_predicate_test9() +{ + site_type site1(0, 0, 4, 0); + site1.sorted_index(1); + site_type site2(0, 0, 0, 4); + site2.sorted_index(0); + site_type site3(0, 4, 4, 4); + site3.sorted_index(2); + site1.inverse(); + CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, 2.0, 2.0, 4.0); +} + +void circle_formation_predicate_test10() +{ + site_type site1(1, 0, 41, 30); + site1.sorted_index(1); + site_type site2(-39, 30, 1, 60); + site2.sorted_index(0); + site_type site3(1, 60, 41, 30); + site3.sorted_index(2); + site1.inverse(); + CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, 1.0, 30.0, 25.0); +} + +void circle_formation_predicate_test11() +{ + site_type site1(0, 0, 0, 10); + site1.sorted_index(2); + site1.inverse(); + site_type site2(-8, 10); + site2.sorted_index(0); + site_type site3(-7, 14, -1, 14); + site3.sorted_index(1); + CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, -4.0, 10.0, 0.0); +} + +void circle_formation_predicate_test12() +{ + site_type site1(0, 0, 0, 10); + site1.sorted_index(2); + site1.inverse(); + site_type site2(-8, 10); + site2.sorted_index(0); + site_type site3(-7, 15, -1, 15); + site3.sorted_index(1); + CHECK_CIRCLE_EXISTENCE(site1, site2, site3, false); +} + +void circle_formation_predicate_test13() +{ + site_type site1(0, 0, 0, 10); + site1.sorted_index(2); + site1.inverse(); + site_type site2(-7, -4, -1, -4); + site2.sorted_index(1); + site2.inverse(); + site_type site3(-8, 0); + site3.sorted_index(0); + CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, -4.0, 0.0, 0.0); +} + +void circle_formation_predicate_test14() +{ + site_type site1(0, 0, 0, 10); + site1.sorted_index(2); + site1.inverse(); + site_type site2(-7, -5, -1, -5); + site2.sorted_index(1); + site2.inverse(); + site_type site3(-8, 0); + site3.sorted_index(0); + CHECK_CIRCLE_EXISTENCE(site1, site2, site3, false); +} + +int main() +{ + orientation_test(); + event_comparison_test1(); + event_comparison_test2(); + event_comparison_test3(); + event_comparison_test4(); + event_comparison_test5(); + distance_predicate_test1(); + distance_predicate_test2(); + distance_predicate_test3(); + distance_predicate_test4(); + distance_predicate_test5(); + distance_predicate_test6(); + distance_predicate_test7(); + distance_predicate_test8(); + node_comparison_test1(); + node_comparison_test2(); + node_comparison_test3(); + node_comparison_test4(); + node_comparison_test5(); + node_comparison_test6(); + node_comparison_test7(); + node_comparison_test8(); + circle_formation_predicate_test1(); + circle_formation_predicate_test2(); + circle_formation_predicate_test3(); + circle_formation_predicate_test4(); + circle_formation_predicate_test5(); + circle_formation_predicate_test6(); + circle_formation_predicate_test7(); + circle_formation_predicate_test8(); + circle_formation_predicate_test9(); + circle_formation_predicate_test10(); + circle_formation_predicate_test11(); + circle_formation_predicate_test12(); + circle_formation_predicate_test13(); + circle_formation_predicate_test14(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_robust_fpt_test.cpp b/src/boost/libs/polygon/test/voronoi_robust_fpt_test.cpp new file mode 100644 index 00000000..91853069 --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_robust_fpt_test.cpp @@ -0,0 +1,405 @@ +// Boost.Polygon library voronoi_robust_fpt_test.cpp file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/detail/voronoi_ctypes.hpp> +#include <boost/polygon/detail/voronoi_robust_fpt.hpp> +#include <boost/random/mersenne_twister.hpp> +#include <vector> +#include <cmath> +#include <ctime> + +using boost::polygon::detail::int32; +using boost::polygon::detail::uint32; +using boost::polygon::detail::int64; +using boost::polygon::detail::fpt64; +using boost::polygon::detail::efpt64; +using boost::polygon::detail::extended_int; +using boost::polygon::detail::extended_exponent_fpt; +using boost::polygon::detail::robust_fpt; +using boost::polygon::detail::robust_dif; +using boost::polygon::detail::robust_sqrt_expr; +using boost::polygon::detail::type_converter_fpt; +using boost::polygon::detail::type_converter_efpt; +using boost::polygon::detail::ulp_comparison; + +typedef robust_fpt<double> rfpt_type; +typedef type_converter_fpt to_fpt_type; +typedef type_converter_efpt to_efpt_type; +type_converter_fpt to_fpt; + +void robust_fpt_constructors_test1() +{ + rfpt_type a = rfpt_type(); + BOOST_TEST_EQ(a.fpv(), 0.0); + BOOST_TEST_EQ(a.re(), 0.0); + BOOST_TEST_EQ(a.ulp(), 0); +} + +void robust_fpt_constructors_test2() +{ + rfpt_type a(10.0, 1.0); + BOOST_TEST_EQ(a.fpv(), 10.0); + BOOST_TEST_EQ(a.re(), 1.0); + BOOST_TEST_EQ(a.ulp(), 1.0); +} + +void robust_fpt_constructors_test3() +{ + rfpt_type a(10.0); + BOOST_TEST_EQ(a.fpv(), 10.0); + BOOST_TEST_EQ(a.re(), 0.0); + BOOST_TEST_EQ(a.ulp(), 0.0); +} + +void robust_fpt_constructors_test4() +{ + rfpt_type a(10.0, 3.0); + BOOST_TEST_EQ(a.fpv(), 10.0); + BOOST_TEST_EQ(a.re(), 3.0); + BOOST_TEST_EQ(a.ulp(), 3.0); + + rfpt_type b(10.0, 2.75); + BOOST_TEST_EQ(b.fpv(), 10.0); + BOOST_TEST_EQ(b.re(), 2.75); + BOOST_TEST_EQ(b.ulp(), 2.75); +} + +void robust_fpt_sum_test1() +{ + rfpt_type a(2.0, 5.0); + rfpt_type b(3.0, 4.0); + rfpt_type c = a + b; + BOOST_TEST_EQ(c.fpv(), 5.0); + BOOST_TEST_EQ(c.re(), 6.0); + BOOST_TEST_EQ(c.ulp(), 6.0); + + c += b; + BOOST_TEST_EQ(c.fpv(), 8.0); + BOOST_TEST_EQ(c.re(), 7.0); + BOOST_TEST_EQ(c.ulp(), 7.0); +} + +void robust_fpt_sum_test2() +{ + rfpt_type a(3.0, 2.0); + rfpt_type b(-2.0, 3.0); + rfpt_type c = a + b; + BOOST_TEST_EQ(c.fpv(), 1.0); + BOOST_TEST_EQ(c.re(), 13.0); + BOOST_TEST_EQ(c.ulp(), 13.0); + + c += b; + BOOST_TEST_EQ(c.fpv(), -1.0); + BOOST_TEST_EQ(c.re(), 20.0); + BOOST_TEST_EQ(c.ulp(), 20.0); +} + +void robust_fpt_dif_test1() +{ + rfpt_type a(2.0, 5.0); + rfpt_type b(-3.0, 4.0); + rfpt_type c = a - b; + BOOST_TEST_EQ(c.fpv(), 5.0); + BOOST_TEST_EQ(c.re(), 6.0); + BOOST_TEST_EQ(c.ulp(), 6.0); + + c -= b; + BOOST_TEST_EQ(c.fpv(), 8.0); + BOOST_TEST_EQ(c.re(), 7.0); + BOOST_TEST_EQ(c.ulp(), 7.0); +} + +void robust_fpt_dif_test2() +{ + rfpt_type a(3.0, 2.0); + rfpt_type b(2.0, 3.0); + rfpt_type c = a - b; + BOOST_TEST_EQ(c.fpv(), 1.0); + BOOST_TEST_EQ(c.re(), 13.0); + BOOST_TEST_EQ(c.ulp(), 13.0); + + c -= b; + BOOST_TEST_EQ(c.fpv(), -1.0); + BOOST_TEST_EQ(c.re(), 20.0); + BOOST_TEST_EQ(c.ulp(), 20.0); +} + +void robust_fpt_mult_test3() +{ + rfpt_type a(2.0, 3.0); + rfpt_type b(4.0, 1.0); + rfpt_type c = a * b; + BOOST_TEST_EQ(c.fpv(), 8.0); + BOOST_TEST_EQ(c.re(), 5.0); + BOOST_TEST_EQ(c.ulp(), 5.0); + + c *= b; + BOOST_TEST_EQ(c.fpv(), 32.0); + BOOST_TEST_EQ(c.re(), 7.0); + BOOST_TEST_EQ(c.ulp(), 7.0); +} + +void robust_fpt_div_test1() +{ + rfpt_type a(2.0, 3.0); + rfpt_type b(4.0, 1.0); + rfpt_type c = a / b; + BOOST_TEST_EQ(c.fpv(), 0.5); + BOOST_TEST_EQ(c.re(), 5.0); + BOOST_TEST_EQ(c.ulp(), 5.0); + + c /= b; + BOOST_TEST_EQ(c.fpv(), 0.125); + BOOST_TEST_EQ(c.re(), 7.0); + BOOST_TEST_EQ(c.ulp(), 7.0); +} + +void robust_dif_constructors_test() +{ + robust_dif<int> rd1; + BOOST_TEST_EQ(rd1.pos(), 0); + BOOST_TEST_EQ(rd1.neg(), 0); + BOOST_TEST_EQ(rd1.dif(), 0); + + robust_dif<int> rd2(1); + BOOST_TEST_EQ(rd2.pos(), 1); + BOOST_TEST_EQ(rd2.neg(), 0); + BOOST_TEST_EQ(rd2.dif(), 1); + + robust_dif<int> rd3(-1); + BOOST_TEST_EQ(rd3.pos(), 0); + BOOST_TEST_EQ(rd3.neg(), 1); + BOOST_TEST_EQ(rd3.dif(), -1); + + robust_dif<int> rd4(1, 2); + BOOST_TEST_EQ(rd4.pos(), 1); + BOOST_TEST_EQ(rd4.neg(), 2); + BOOST_TEST_EQ(rd4.dif(), -1); +} + +void robust_dif_operators_test1() +{ + robust_dif<int> a(5, 2), b(1, 10); + int dif_a = a.dif(); + int dif_b = b.dif(); + robust_dif<int> sum = a + b; + robust_dif<int> dif = a - b; + robust_dif<int> mult = a * b; + robust_dif<int> umin = -a; + BOOST_TEST_EQ(sum.dif(), dif_a + dif_b); + BOOST_TEST_EQ(dif.dif(), dif_a - dif_b); + BOOST_TEST_EQ(mult.dif(), dif_a * dif_b); + BOOST_TEST_EQ(umin.dif(), -dif_a); +} + +void robust_dif_operators_test2() +{ + robust_dif<int> a(5, 2); + for (int b = -3; b <= 3; b += 6) { + int dif_a = a.dif(); + int dif_b = b; + robust_dif<int> sum = a + b; + robust_dif<int> dif = a - b; + robust_dif<int> mult = a * b; + robust_dif<int> div = a / b; + BOOST_TEST_EQ(sum.dif(), dif_a + dif_b); + BOOST_TEST_EQ(dif.dif(), dif_a - dif_b); + BOOST_TEST_EQ(mult.dif(), dif_a * dif_b); + BOOST_TEST_EQ(div.dif(), dif_a / dif_b); + } +} + +void robust_dif_operators_test3() +{ + robust_dif<int> b(5, 2); + for (int a = -3; a <= 3; a += 6) { + int dif_a = a; + int dif_b = b.dif(); + robust_dif<int> sum = a + b; + robust_dif<int> dif = a - b; + robust_dif<int> mult = a * b; + BOOST_TEST_EQ(sum.dif(), dif_a + dif_b); + BOOST_TEST_EQ(dif.dif(), dif_a - dif_b); + BOOST_TEST_EQ(mult.dif(), dif_a * dif_b); + } +} + +void robust_dif_operators_test4() +{ + std::vector< robust_dif<int> > a4(4, robust_dif<int>(5, 2)); + std::vector< robust_dif<int> > b4(4, robust_dif<int>(1, 2)); + std::vector< robust_dif<int> > c4 = a4; + c4[0] += b4[0]; + c4[1] -= b4[1]; + c4[2] *= b4[2]; + BOOST_TEST_EQ(c4[0].dif(), a4[0].dif() + b4[0].dif()); + BOOST_TEST_EQ(c4[1].dif(), a4[1].dif() - b4[1].dif()); + BOOST_TEST_EQ(c4[2].dif(), a4[2].dif() * b4[2].dif()); + a4[0] += b4[0].dif(); + a4[1] -= b4[1].dif(); + a4[2] *= b4[2].dif(); + a4[3] /= b4[3].dif(); + BOOST_TEST_EQ(c4[0].dif(), a4[0].dif()); + BOOST_TEST_EQ(c4[1].dif(), a4[1].dif()); + BOOST_TEST_EQ(c4[2].dif(), a4[2].dif()); + BOOST_TEST_EQ(c4[3].dif() / b4[3].dif(), a4[3].dif()); +} + +void robust_sqrt_expr_test1() +{ + robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr; + int32 A[1] = {10}; + int32 B[1] = {100}; + BOOST_TEST_EQ(sqrt_expr.eval1(A, B), 100.0); +} + +void robust_sqrt_expr_test2() +{ + robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr; + int32 A[2] = {10, 30}; + int32 B[2] = {400, 100}; + BOOST_TEST_EQ(sqrt_expr.eval2(A, B), 500.0); +} + +void robust_sqrt_expr_test3() +{ + robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr; + int32 A[2] = {10, -30}; + int32 B[2] = {400, 100}; + BOOST_TEST_EQ(sqrt_expr.eval2(A, B), -100.0); +} + +void robust_sqrt_expr_test4() +{ + robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr; + int32 A[3] = {10, 30, 20}; + int32 B[3] = {4, 1, 9}; + BOOST_TEST_EQ(sqrt_expr.eval3(A, B), 110.0); +} + +void robust_sqrt_expr_test5() +{ + robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr; + int32 A[3] = {10, 30, -20}; + int32 B[3] = {4, 1, 9}; + BOOST_TEST_EQ(sqrt_expr.eval3(A, B), -10.0); +} + +void robust_sqrt_expr_test6() +{ + robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr; + int32 A[4] = {10, 30, 20, 5}; + int32 B[4] = {4, 1, 9, 16}; + BOOST_TEST_EQ(sqrt_expr.eval4(A, B), 130.0); +} + +void robust_sqrt_expr_test7() +{ + robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr; + int32 A[4] = {10, 30, -20, -5}; + int32 B[4] = {4, 1, 9, 16}; + BOOST_TEST_EQ(sqrt_expr.eval4(A, B), -30.0); +} + +void robust_sqrt_expr_test8() +{ + typedef extended_int<16> eint512; + robust_sqrt_expr<eint512, efpt64, to_efpt_type> sqrt_expr; + int32 A[4] = {1000, 3000, -2000, -500}; + int32 B[4] = {400, 100, 900, 1600}; + eint512 AA[4], BB[4]; + for (std::size_t i = 0; i < 4; ++i) { + AA[i] = A[i]; + BB[i] = B[i]; + } + BOOST_TEST_EQ(to_fpt(sqrt_expr.eval4(AA, BB)), -30000.0); +} + +template <typename _int, typename _fpt> +class sqrt_expr_tester { + public: + static const std::size_t MX_SQRTS = 4; + + bool run() { + static boost::mt19937 gen(static_cast<uint32>(time(NULL))); + bool ret_val = true; + for (std::size_t i = 0; i < MX_SQRTS; ++i) { + a[i] = gen() & 1048575; + int64 temp = gen() & 1048575; + b[i] = temp * temp; + } + uint32 mask = (1 << MX_SQRTS); + for (std::size_t i = 0; i < mask; i++) { + fpt64 expected_val = 0.0; + for (std::size_t j = 0; j < MX_SQRTS; j++) { + if (i & (1 << j)) { + A[j] = a[j]; + B[j] = b[j]; + expected_val += static_cast<fpt64>(a[j]) * + std::sqrt(static_cast<fpt64>(b[j])); + } else { + A[j] = -a[j]; + B[j] = b[j]; + expected_val -= static_cast<fpt64>(a[j]) * + std::sqrt(static_cast<fpt64>(b[j])); + } + } + fpt64 received_val = to_fpt(sqrt_expr_.eval4(A, B)); + ret_val &= ulp_cmp(expected_val, received_val, 25) == + ulp_comparison<fpt64>::EQUAL; + } + return ret_val; + } + + private: + robust_sqrt_expr<_int, _fpt, to_efpt_type> sqrt_expr_; + ulp_comparison<fpt64> ulp_cmp; + _int A[MX_SQRTS]; + _int B[MX_SQRTS]; + int64 a[MX_SQRTS]; + int64 b[MX_SQRTS]; +}; + +void mpz_sqrt_evaluator_test() +{ + typedef extended_int<16> eint512; + sqrt_expr_tester<eint512, efpt64> tester; + for (int i = 0; i < 2000; ++i) + BOOST_TEST(tester.run()); +} + +int main() +{ + robust_fpt_constructors_test1(); + robust_fpt_constructors_test2(); + robust_fpt_constructors_test3(); + robust_fpt_constructors_test4(); + robust_fpt_sum_test1(); + robust_fpt_sum_test2(); + robust_fpt_dif_test1(); + robust_fpt_dif_test2(); + robust_fpt_mult_test3(); + robust_fpt_div_test1(); + robust_dif_constructors_test(); + robust_dif_operators_test1(); + robust_dif_operators_test2(); + robust_dif_operators_test3(); + robust_dif_operators_test4(); + robust_sqrt_expr_test1(); + robust_sqrt_expr_test2(); + robust_sqrt_expr_test3(); + robust_sqrt_expr_test4(); + robust_sqrt_expr_test5(); + robust_sqrt_expr_test6(); + robust_sqrt_expr_test7(); + robust_sqrt_expr_test8(); + mpz_sqrt_evaluator_test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_structures_test.cpp b/src/boost/libs/polygon/test/voronoi_structures_test.cpp new file mode 100644 index 00000000..1693c317 --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_structures_test.cpp @@ -0,0 +1,150 @@ +// Boost.Polygon library voronoi_structures_test.cpp file + +// Copyright Andrii Sydorchuk 2010-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/core/lightweight_test.hpp> +#include <boost/polygon/detail/voronoi_structures.hpp> +#include <boost/polygon/voronoi_geometry_type.hpp> +#include <functional> +#include <vector> + +using namespace boost::polygon::detail; +using namespace boost::polygon; + +typedef point_2d<int> point_type; +typedef site_event<int> site_type; +typedef circle_event<int> circle_type; +typedef ordered_queue<int, std::greater<int> > ordered_queue_type; +typedef beach_line_node_key<int> node_key_type; +typedef beach_line_node_data<int, int> node_data_type; + +void point_2d_test1() +{ + point_type p(1, 2); + BOOST_TEST_EQ(1, p.x()); + BOOST_TEST_EQ(2, p.y()); + p.x(3); + BOOST_TEST_EQ(3, p.x()); + p.y(4); + BOOST_TEST_EQ(4, p.y()); +} + +void site_event_test1() +{ + site_type s(1, 2); + s.sorted_index(1); + s.initial_index(2); + s.source_category(SOURCE_CATEGORY_SEGMENT_START_POINT); + BOOST_TEST_EQ(1, s.x0()); + BOOST_TEST_EQ(1, s.x1()); + BOOST_TEST_EQ(2, s.y0()); + BOOST_TEST_EQ(2, s.y1()); + BOOST_TEST(s.is_point()); + BOOST_TEST(!s.is_segment()); + BOOST_TEST(!s.is_inverse()); + BOOST_TEST_EQ(1, s.sorted_index()); + BOOST_TEST_EQ(2, s.initial_index()); + BOOST_TEST_EQ(SOURCE_CATEGORY_SEGMENT_START_POINT, s.source_category()); +} + +void site_event_test2() +{ + site_type s(1, 2, 3, 4); + s.sorted_index(1); + s.initial_index(2); + s.source_category(SOURCE_CATEGORY_INITIAL_SEGMENT); + BOOST_TEST_EQ(1, s.x0()); + BOOST_TEST_EQ(2, s.y0()); + BOOST_TEST_EQ(3, s.x1()); + BOOST_TEST_EQ(4, s.y1()); + BOOST_TEST(!s.is_point()); + BOOST_TEST(s.is_segment()); + BOOST_TEST(!s.is_inverse()); + BOOST_TEST_EQ(SOURCE_CATEGORY_INITIAL_SEGMENT, s.source_category()); + + s.inverse(); + BOOST_TEST_EQ(3, s.x0()); + BOOST_TEST_EQ(4, s.y0()); + BOOST_TEST_EQ(1, s.x1()); + BOOST_TEST_EQ(2, s.y1()); + BOOST_TEST(s.is_inverse()); + BOOST_TEST_EQ(SOURCE_CATEGORY_INITIAL_SEGMENT, s.source_category()); +} + +void circle_event_test() +{ + circle_type c(0, 1, 2); + BOOST_TEST_EQ(0, c.x()); + BOOST_TEST_EQ(1, c.y()); + BOOST_TEST_EQ(2, c.lower_x()); + BOOST_TEST_EQ(1, c.lower_y()); + BOOST_TEST(c.is_active()); + c.x(3); + c.y(4); + c.lower_x(5); + BOOST_TEST_EQ(3, c.x()); + BOOST_TEST_EQ(4, c.y()); + BOOST_TEST_EQ(5, c.lower_x()); + BOOST_TEST_EQ(4, c.lower_y()); + c.deactivate(); + BOOST_TEST(!c.is_active()); +} + +void ordered_queue_test() +{ + ordered_queue_type q; + BOOST_TEST(q.empty()); + std::vector<int*> vi; + for (int i = 0; i < 20; ++i) + vi.push_back(&q.push(i)); + for (int i = 0; i < 20; ++i) + *vi[i] <<= 1; + BOOST_TEST(!q.empty()); + for (int i = 0; i < 20; ++i, q.pop()) + BOOST_TEST_EQ(i << 1, q.top()); + BOOST_TEST(q.empty()); +} + +void beach_line_node_key_test() +{ + node_key_type key(1); + BOOST_TEST_EQ(1, key.left_site()); + BOOST_TEST_EQ(1, key.right_site()); + key.left_site(2); + BOOST_TEST_EQ(2, key.left_site()); + BOOST_TEST_EQ(1, key.right_site()); + key.right_site(3); + BOOST_TEST_EQ(2, key.left_site()); + BOOST_TEST_EQ(3, key.right_site()); +} + +void beach_line_node_data_test() +{ + node_data_type node_data(NULL); + BOOST_TEST(node_data.edge() == NULL); + BOOST_TEST(node_data.circle_event() == NULL); + int data = 4; + node_data.circle_event(&data); + BOOST_TEST(node_data.edge() == NULL); + BOOST_TEST(node_data.circle_event() == &data); + node_data.edge(&data); + BOOST_TEST(node_data.edge() == &data); + BOOST_TEST(node_data.circle_event() == &data); +} + +int main() +{ + point_2d_test1(); + site_event_test1(); + site_event_test2(); + circle_event_test(); + ordered_queue_test(); + beach_line_node_key_test(); + beach_line_node_data_test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/polygon/test/voronoi_test_helper.hpp b/src/boost/libs/polygon/test/voronoi_test_helper.hpp new file mode 100644 index 00000000..61c4630a --- /dev/null +++ b/src/boost/libs/polygon/test/voronoi_test_helper.hpp @@ -0,0 +1,260 @@ +// Boost.Polygon library voronoi_test_helper.hpp file + +// Copyright Andrii Sydorchuk 2010-2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef VORONOI_TEST_HELPER +#define VORONOI_TEST_HELPER + +#include <boost/polygon/polygon.hpp> +#include <algorithm> +#include <iostream> +#include <iterator> +#include <fstream> +#include <map> +#include <vector> +#include <utility> + +using namespace boost::polygon; + +namespace voronoi_test_helper { + +enum kOrientation { + RIGHT = -1, + COLLINEAR = 0, + LEFT = 1 +}; + +template <typename VERTEX> +kOrientation get_orientation( + const VERTEX& v1, const VERTEX& v2, const VERTEX& v3) { + typename VERTEX::coordinate_type lhs = (v2.x() - v1.x()) * (v3.y() - v2.y()); + typename VERTEX::coordinate_type rhs = (v2.y() - v1.y()) * (v3.x() - v2.x()); + if (lhs == rhs) { + return COLLINEAR; + } + return (lhs < rhs) ? RIGHT : LEFT; +} + +template <typename OUTPUT> +bool verify_cell_convexity(const OUTPUT& output) { + typename OUTPUT::const_cell_iterator cell_it; + for (cell_it = output.cells().begin(); + cell_it != output.cells().end(); cell_it++) { + const typename OUTPUT::edge_type* edge = cell_it->incident_edge(); + if (edge) + do { + if (edge->next()->prev() != edge) { + return false; + } + if (edge->cell() != &(*cell_it)) { + return false; + } + if (edge->vertex1() != edge->next()->vertex0()) { + return false; + } + if (edge->vertex0() != NULL && + edge->vertex1() != NULL && + edge->next()->vertex1() != NULL) { + if (get_orientation(*edge->vertex0(), + *edge->vertex1(), + *edge->next()->vertex1()) != LEFT) { + return false; + } + } + edge = edge->next(); + } while (edge != cell_it->incident_edge()); + } + return true; +} + +template <typename OUTPUT> +bool verify_incident_edges_ccw_order(const OUTPUT& output) { + typedef typename OUTPUT::edge_type voronoi_edge_type; + typename OUTPUT::const_vertex_iterator vertex_it; + for (vertex_it = output.vertices().begin(); + vertex_it != output.vertices().end(); vertex_it++) { + if (vertex_it->is_degenerate()) + continue; + const voronoi_edge_type* edge = vertex_it->incident_edge(); + do { + const voronoi_edge_type* next_edge = edge->rot_next(); + if (edge->vertex0() != next_edge->vertex0()) { + return false; + } + if (edge->vertex1() != NULL && next_edge->vertex1() != NULL && + get_orientation(*edge->vertex1(), + *edge->vertex0(), + *next_edge->vertex1()) == LEFT) { + return false; + } + edge = edge->rot_next(); + } while (edge != vertex_it->incident_edge()); + } + return true; +} + +template <typename VERTEX> +struct cmp { + bool operator()(const VERTEX& v1, const VERTEX& v2) const { + if (v1.x() != v2.x()) + return v1.x() < v2.x(); + return v1.y() < v2.y(); + } +}; + +template <typename Output> +bool verfiy_no_line_edge_intersections(const Output &output) { + // Create map from edges with first point less than the second one. + // Key is the first point of the edge, value is a vector of second points + // with the same first point. + typedef typename Output::vertex_type vertex_type; + cmp<vertex_type> comparator; + std::map< vertex_type, std::vector<vertex_type>, cmp<vertex_type> > edge_map; + typename Output::const_edge_iterator edge_it; + for (edge_it = output.edges().begin(); + edge_it != output.edges().end(); edge_it++) { + if (edge_it->is_finite()) { + if (comparator(*edge_it->vertex0(), *edge_it->vertex1())) { + edge_map[*edge_it->vertex0()].push_back(*edge_it->vertex1()); + } + } + } + return !intersection_check(edge_map); +} + +template <typename Point2D> +bool intersection_check( + const std::map< Point2D, std::vector<Point2D>, cmp<Point2D> > &edge_map) { + // Iterate over map of edges and check if there are any intersections. + // All the edges are stored by the low x value. That's why we iterate + // left to right checking for intersections between all pairs of edges + // that overlap in the x dimension. + // Complexity. Approximately N*sqrt(N). Worst case N^2. + typedef Point2D point_type; + typedef typename point_type::coordinate_type coordinate_type; + typedef typename std::map<point_type, std::vector<point_type>, cmp<Point2D> >::const_iterator + edge_map_iterator; + typedef typename std::vector<point_type>::size_type size_type; + edge_map_iterator edge_map_it1, edge_map_it2, edge_map_it_bound; + for (edge_map_it1 = edge_map.begin(); + edge_map_it1 != edge_map.end(); edge_map_it1++) { + const point_type &point1 = edge_map_it1->first; + for (size_type i = 0; i < edge_map_it1->second.size(); i++) { + const point_type &point2 = edge_map_it1->second[i]; + coordinate_type min_y1 = (std::min)(point1.y(), point2.y()); + coordinate_type max_y1 = (std::max)(point1.y(), point2.y()); + + // Find the first edge with greater or equal first point. + edge_map_it_bound = edge_map.lower_bound(point2); + + edge_map_it2 = edge_map_it1; + edge_map_it2++; + for (; edge_map_it2 != edge_map_it_bound; edge_map_it2++) { + const point_type &point3 = edge_map_it2->first; + for (size_type j = 0; j < edge_map_it2->second.size(); j++) { + const point_type &point4 = edge_map_it2->second[j]; + coordinate_type min_y2 = (std::min)(point3.y(), point4.y()); + coordinate_type max_y2 = (std::max)(point3.y(), point4.y()); + + // In most cases it is enought to make + // simple intersection check in the y dimension. + if (!(max_y1 > min_y2 && max_y2 > min_y1)) + continue; + + // Intersection check. + if (get_orientation(point1, point2, point3) * + get_orientation(point1, point2, point4) == RIGHT && + get_orientation(point3, point4, point1) * + get_orientation(point3, point4, point2) == RIGHT) + return true; + } + } + } + } + return false; +} + +enum kVerification { + CELL_CONVEXITY = 1, + INCIDENT_EDGES_CCW_ORDER = 2, + NO_HALF_EDGE_INTERSECTIONS = 4, + FAST_VERIFICATION = 3, + COMPLETE_VERIFICATION = 7 +}; + +template <typename Output> +bool verify_output(const Output &output, kVerification mask) { + bool result = true; + if (mask & CELL_CONVEXITY) + result &= verify_cell_convexity(output); + if (mask & INCIDENT_EDGES_CCW_ORDER) + result &= verify_incident_edges_ccw_order(output); + if (mask & NO_HALF_EDGE_INTERSECTIONS) + result &= verfiy_no_line_edge_intersections(output); + return result; +} + +template <typename PointIterator> +void save_points( + PointIterator first, PointIterator last, const char* file_name) { + std::ofstream ofs(file_name); + ofs << std::distance(first, last) << std::endl; + for (PointIterator it = first; it != last; ++it) { + ofs << it->x() << " " << it->y() << std::endl; + } + ofs.close(); +} + +template <typename SegmentIterator> +void save_segments( + SegmentIterator first, SegmentIterator last, const char* file_name) { + std::ofstream ofs(file_name); + ofs << std::distance(first, last) << std::endl; + for (SegmentIterator it = first; it != last; ++it) { + ofs << it->low().x() << " " << it->low().y() << " "; + ofs << it->high().x() << " " << it->high().y() << std::endl; + } + ofs.close(); +} + +template <typename T> +void clean_segment_set(std::vector< segment_data<T> >& data) { + typedef T Unit; + typedef typename scanline_base<Unit>::Point Point; + typedef typename scanline_base<Unit>::half_edge half_edge; + typedef int segment_id; + std::vector<std::pair<half_edge, segment_id> > half_edges; + std::vector<std::pair<half_edge, segment_id> > half_edges_out; + segment_id id = 0; + half_edges.reserve(data.size()); + for (typename std::vector< segment_data<T> >::iterator it = data.begin(); + it != data.end(); ++it) { + Point l = it->low(); + Point h = it->high(); + half_edges.push_back(std::make_pair(half_edge(l, h), id++)); + } + half_edges_out.reserve(half_edges.size()); + // Apparently no need to pre-sort data when calling validate_scan. + line_intersection<Unit>::validate_scan( + half_edges_out, half_edges.begin(), half_edges.end()); + std::vector< segment_data<T> > result; + result.reserve(half_edges_out.size()); + for (std::size_t i = 0; i < half_edges_out.size(); ++i) { + id = half_edges_out[i].second; + Point l = half_edges_out[i].first.first; + Point h = half_edges_out[i].first.second; + segment_data<T> orig_seg = data[id]; + if (orig_seg.high() < orig_seg.low()) + std::swap(l, h); + result.push_back(segment_data<T>(l, h)); + } + std::swap(result, data); +} +} // voronoi_test_helper + +#endif |