1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
/*
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 <boost/polygon/polygon.hpp>
#include <list>
#include <time.h>
#include <cassert>
#include <deque>
#include <iostream>
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;
//once again we make our usage of the library generic
//and parameterize it on the polygon set type
template <typename PolygonSet>
void test_polygon_set() {
using namespace gtl;
PolygonSet ps;
ps += rectangle_data<int>(0, 0, 10, 10);
PolygonSet ps2;
ps2 += rectangle_data<int>(5, 5, 15, 15);
PolygonSet ps3;
assign(ps3, ps * ps2);
PolygonSet ps4;
ps4 += ps + ps2;
assert(area(ps4) == area(ps) + area(ps2) - area(ps3));
assert(equivalence((ps + ps2) - (ps * ps2), ps ^ ps2));
rectangle_data<int> rect;
assert(extents(rect, ps ^ ps2));
assert(area(rect) == 225);
assert(area(rect ^ (ps ^ ps2)) == area(rect) - area(ps ^ ps2));
}
//first thing is first, lets include all the code from previous examples
//the CPoint example
struct CPoint {
int x;
int y;
};
namespace boost { namespace polygon {
template <>
struct geometry_concept<CPoint> { typedef point_concept type; };
template <>
struct point_traits<CPoint> {
typedef int coordinate_type;
static inline coordinate_type get(const CPoint& point,
orientation_2d orient) {
if(orient == HORIZONTAL)
return point.x;
return point.y;
}
};
template <>
struct point_mutable_traits<CPoint> {
typedef int coordinate_type;
static inline void set(CPoint& point, orientation_2d orient, int value) {
if(orient == HORIZONTAL)
point.x = value;
else
point.y = value;
}
static inline CPoint construct(int x_value, int y_value) {
CPoint retval;
retval.x = x_value;
retval.y = y_value;
return retval;
}
};
} }
//the CPolygon example
typedef std::list<CPoint> CPolygon;
//we need to specialize our polygon concept mapping in boost polygon
namespace boost { namespace polygon {
//first register CPolygon as a polygon_concept type
template <>
struct geometry_concept<CPolygon>{ typedef polygon_concept type; };
template <>
struct polygon_traits<CPolygon> {
typedef int coordinate_type;
typedef CPolygon::const_iterator iterator_type;
typedef CPoint point_type;
// Get the begin iterator
static inline iterator_type begin_points(const CPolygon& t) {
return t.begin();
}
// Get the end iterator
static inline iterator_type end_points(const CPolygon& t) {
return t.end();
}
// Get the number of sides of the polygon
static inline std::size_t size(const CPolygon& t) {
return t.size();
}
// Get the winding direction of the polygon
static inline winding_direction winding(const CPolygon& t) {
return unknown_winding;
}
};
template <>
struct polygon_mutable_traits<CPolygon> {
//expects stl style iterators
template <typename iT>
static inline CPolygon& set_points(CPolygon& t,
iT input_begin, iT input_end) {
t.clear();
while(input_begin != input_end) {
t.push_back(CPoint());
gtl::assign(t.back(), *input_begin);
++input_begin;
}
return t;
}
};
} }
//OK, finally we get to declare our own polygon set type
typedef std::deque<CPolygon> CPolygonSet;
//deque isn't automatically a polygon set in the library
//because it is a standard container there is a shortcut
//for mapping it to polygon set concept, but I'll do it
//the long way that you would use in the general case.
namespace boost { namespace polygon {
//first we register CPolygonSet as a polygon set
template <>
struct geometry_concept<CPolygonSet> { typedef polygon_set_concept type; };
//next we map to the concept through traits
template <>
struct polygon_set_traits<CPolygonSet> {
typedef int coordinate_type;
typedef CPolygonSet::const_iterator iterator_type;
typedef CPolygonSet operator_arg_type;
static inline iterator_type begin(const CPolygonSet& polygon_set) {
return polygon_set.begin();
}
static inline iterator_type end(const CPolygonSet& polygon_set) {
return polygon_set.end();
}
//don't worry about these, just return false from them
static inline bool clean(const CPolygonSet& polygon_set) { return false; }
static inline bool sorted(const CPolygonSet& polygon_set) { return false; }
};
template <>
struct polygon_set_mutable_traits<CPolygonSet> {
template <typename input_iterator_type>
static inline void set(CPolygonSet& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) {
polygon_set.clear();
//this is kind of cheesy. I am copying the unknown input geometry
//into my own polygon set and then calling get to populate the
//deque
polygon_set_data<int> ps;
ps.insert(input_begin, input_end);
ps.get(polygon_set);
//if you had your own odd-ball polygon set you would probably have
//to iterate through each polygon at this point and do something
//extra
}
};
} }
int main() {
long long c1 = clock();
for(int i = 0; i < 1000; ++i)
test_polygon_set<CPolygonSet>();
long long c2 = clock();
for(int i = 0; i < 1000; ++i)
test_polygon_set<gtl::polygon_set_data<int> >();
long long c3 = clock();
long long diff1 = c2 - c1;
long long diff2 = c3 - c2;
if(diff1 > 0 && diff2)
std::cout << "library polygon_set_data is " << float(diff1)/float(diff2) << "X faster than custom polygon set deque of CPolygon" << std::endl;
else
std::cout << "operation was too fast" << std::endl;
return 0;
}
//Now you know how to map your own data type to polygon set concept
//Now you also know how to make your application code that operates on geometry
//data type agnostic from point through polygon set
|