| // Boost.Geometry (aka GGL, Generic Geometry Library) |
| |
| // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. |
| // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. |
| // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. |
| |
| // 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) |
| // |
| // Polygon Example |
| |
| #include <algorithm> // for reverse, unique |
| #include <iostream> |
| #include <string> |
| |
| #include <boost/geometry/geometry.hpp> |
| #include <boost/geometry/geometries/point_xy.hpp> |
| #include <boost/geometry/geometries/polygon.hpp> |
| #include <boost/geometry/geometries/adapted/c_array.hpp> |
| #include <boost/geometry/geometries/multi_polygon.hpp> |
| |
| BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) |
| |
| |
| std::string boolstr(bool v) |
| { |
| return v ? "true" : "false"; |
| } |
| |
| int main(void) |
| { |
| using namespace boost::geometry; |
| |
| typedef model::d2::point_xy<double> point_2d; |
| typedef model::polygon<point_2d> polygon_2d; |
| typedef model::box<point_2d> box_2d; |
| |
| // Define a polygon and fill the outer ring. |
| // In most cases you will read it from a file or database |
| polygon_2d poly; |
| { |
| const double coor[][2] = { |
| {2.0, 1.3}, {2.4, 1.7}, {2.8, 1.8}, {3.4, 1.2}, {3.7, 1.6}, |
| {3.4, 2.0}, {4.1, 3.0}, {5.3, 2.6}, {5.4, 1.2}, {4.9, 0.8}, {2.9, 0.7}, |
| {2.0, 1.3} // closing point is opening point |
| }; |
| assign_points(poly, coor); |
| } |
| |
| // Polygons should be closed, and directed clockwise. If you're not sure if that is the case, |
| // call the correct algorithm |
| correct(poly); |
| |
| // Polygons can be streamed as text |
| // (or more precisely: as DSV (delimiter separated values)) |
| std::cout << dsv(poly) << std::endl; |
| |
| // As with lines, bounding box of polygons can be calculated |
| box_2d b; |
| envelope(poly, b); |
| std::cout << dsv(b) << std::endl; |
| |
| // The area of the polygon can be calulated |
| std::cout << "area: " << area(poly) << std::endl; |
| |
| // And the centroid, which is the center of gravity |
| point_2d cent; |
| centroid(poly, cent); |
| std::cout << "centroid: " << dsv(cent) << std::endl; |
| |
| |
| // The number of points can be requested per ring (using .size()) |
| // or per polygon (using num_points) |
| std::cout << "number of points in outer ring: " << poly.outer().size() << std::endl; |
| |
| // Polygons can have one or more inner rings, also called holes, islands, interior rings. |
| // Let's add one |
| { |
| poly.inners().resize(1); |
| model::ring<point_2d>& inner = poly.inners().back(); |
| |
| const double coor[][2] = { {4.0, 2.0}, {4.2, 1.4}, {4.8, 1.9}, {4.4, 2.2}, {4.0, 2.0} }; |
| assign_points(inner, coor); |
| } |
| |
| correct(poly); |
| |
| std::cout << "with inner ring:" << dsv(poly) << std::endl; |
| // The area of the polygon is changed of course |
| std::cout << "new area of polygon: " << area(poly) << std::endl; |
| centroid(poly, cent); |
| std::cout << "new centroid: " << dsv(cent) << std::endl; |
| |
| // You can test whether points are within a polygon |
| std::cout << "point in polygon:" |
| << " p1: " << boolstr(within(make<point_2d>(3.0, 2.0), poly)) |
| << " p2: " << boolstr(within(make<point_2d>(3.7, 2.0), poly)) |
| << " p3: " << boolstr(within(make<point_2d>(4.4, 2.0), poly)) |
| << std::endl; |
| |
| // As with linestrings and points, you can derive from polygon to add, for example, |
| // fill color and stroke color. Or SRID (spatial reference ID). Or Z-value. Or a property map. |
| // We don't show this here. |
| |
| // Clip the polygon using a box |
| box_2d cb(make<point_2d>(1.5, 1.5), make<point_2d>(4.5, 2.5)); |
| typedef std::vector<polygon_2d> polygon_list; |
| polygon_list v; |
| |
| intersection(cb, poly, v); |
| std::cout << "Clipped output polygons" << std::endl; |
| for (polygon_list::const_iterator it = v.begin(); it != v.end(); ++it) |
| { |
| std::cout << dsv(*it) << std::endl; |
| } |
| |
| typedef model::multi_polygon<polygon_2d> polygon_set; |
| polygon_set ps; |
| union_(cb, poly, ps); |
| |
| polygon_2d hull; |
| convex_hull(poly, hull); |
| std::cout << "Convex hull:" << dsv(hull) << std::endl; |
| |
| // If you really want: |
| // You don't have to use a vector, you can define a polygon with a deque |
| // You can specify the container for the points and for the inner rings independantly |
| |
| typedef model::polygon<point_2d, true, true, std::deque, std::deque> deque_polygon; |
| deque_polygon poly2; |
| ring_type<deque_polygon>::type& ring = exterior_ring(poly2); |
| append(ring, make<point_2d>(2.8, 1.9)); |
| append(ring, make<point_2d>(2.9, 2.4)); |
| append(ring, make<point_2d>(3.3, 2.2)); |
| append(ring, make<point_2d>(3.2, 1.8)); |
| append(ring, make<point_2d>(2.8, 1.9)); |
| std::cout << dsv(poly2) << std::endl; |
| |
| return 0; |
| } |