Calculating distance from point to voronoi cell with boost - c++

Good night. Has anyone encountered a similar problem?
Constructing Voronoi diagram has not caused problems. Voronoi cell is a polygon, at least for me. The library also allows you to find the distance from a point to a polygon. But the library function does not want to work with the cell. The compiler produces something in Elvish. Joke. In short, the compiler output can not help me.
Is there a way to make a polygon from the cell?
Voronoi diagram is constructed on vpoints. The program should calculate the distance from the qpoints element to the corresponding cell.
Here is my code:
#include <iostream>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/polygon/voronoi.hpp>
namespace bg = boost::geometry;
using boost::polygon::voronoi_diagram;
typedef voronoi_diagram<double>::cell_type cell_type;
typedef voronoi_diagram<double>::edge_type edge_type;
typedef voronoi_diagram<double>::vertex_type vertex_type;
typedef boost::polygon::point_data<double> point_type;
using namespace std;
int main() {
vector< point_type > vpoints;
vpoints.push_back(point_type(0.0, 0.0));
vpoints.push_back(point_type(0.0, 4.0));
vpoints.push_back(point_type(4.0, 4.0));
vpoints.push_back(point_type(4.0, 0.0));
vpoints.push_back(point_type(2.0, 2.0));
vector< point_type > qpoints;
qpoints.push_back(point_type(0.0, 0.0));
qpoints.push_back(point_type(0.0, 2.0));
qpoints.push_back(point_type(3.0, 3.0));
qpoints.push_back(point_type(5.0, 5.0));
qpoints.push_back(point_type(5.0, 5.0));
voronoi_diagram<double> vd;
construct_voronoi(vpoints.begin(), vpoints.end(), &vd);
for (int i = 0; i < qpoints.size(); i++) {
for (voronoi_diagram<double>::const_cell_iterator it = vd.cells().begin();
it != vd.cells().end(); ++it) {
if (i == it->source_index()) {
cout << "v[i]=(" << vpoints[i].x() << "," << vpoints[i].y() << ")\t";
cout << "q[i]=(" << qpoints[i].x() << "," << qpoints[i].y() << ")\t";
cout << "Distance=";
cout << bg::distance(qpoints[i], *it) << endl;
cout << endl;
break;
}
}
}
return 0;
}

The message is
boost_1_57_0/boost/geometry/core/geometry_id.hpp|37 col 5| error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::geometry::core_dispatch::geometry_id<void>::NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE::************)(mpl_::assert_::types<void, mpl_::na, mpl_::na, mpl_::na>))’
Which is the NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE assert. It happens doing geometry_id for reverse_dispatch:
/*!
\brief Meta-function returning the id of a geometry type
\details The meta-function geometry_id defines a numerical ID (based on
boost::mpl::int_<...> ) for each geometry concept. A numerical ID is
sometimes useful, and within Boost.Geometry it is used for the
reverse_dispatch metafuntion.
\note Used for e.g. reverse meta-function
\ingroup core
*/
template <typename Geometry>
struct geometry_id : core_dispatch::geometry_id<typename tag<Geometry>::type>
{};
The same warning is triggered when you do
cout << distance(qpoints[i], qpoints[i]) << endl;
So the problem is that your point type is not a reqistered geometry. Including
#include <boost/geometry/geometries/adapted/boost_polygon.hpp>
makes that compile, but of course
cout << distance(qpoints[i], *it) << endl;
still fails, this time because const boost::polygon::voronoi_cell<double> isn't a known geometry type to Boost Geometry.
I'd suggest not mixing the libraries unless you know why you want to.
It looks to me that a voronoi cell can be more than just a single thing (contains_segment() and contains_point() are indications). You may have to write some switching logic to handle the possible cases separately, and perhaps use euclidean_distance from Boost Polygon in the process (as opposed to boost::geometry::distance`)

Related

Cgal - Point_set_3 object, functions fails to process?

Currently trying to build upon the surface reconstruction tutorial and noticed a potential major issue in the tutorial which, in my experience do generalised outside of it:
In the following tutorial: https://doc.cgal.org/latest/Manual/tuto_reconstruction.html (cgal 5.3), the author do some pre-processing before going into the mesh reconstruction, stuffs like outlier_removal, grid_simplify etc.
However I noticed that no points are being removed during these steps. So I tried multiple parameters in the outlier_removal/grid_simplify and still, everytime, no points gets removed.
However when working with a vector of point instead of a Point_set_3 object, I do manage to get points removed with the same parameters.
Am I the only one who is unable to remove a point with outlier_removal/grid_simplify on a Point_set_3 object?
If yes, can you show me an example how to make it work?
If no, should I avoid using Point_set_3 objects? Or should I convert into a std::vector before doing the pre-processing steps? And how so?
Issue Details
The code runs fine. No errors.
Source Code
This code subset comes straight out of the tutorial.
https://doc.cgal.org/latest/Manual/tuto_reconstruction.html
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>
#include <CGAL/remove_outliers.h>
#include <CGAL/grid_simplify_point_set.h>
#include <CGAL/jet_smooth_point_set.h>
#include <CGAL/jet_estimate_normals.h>
#include <CGAL/mst_orient_normals.h>
#include <CGAL/poisson_surface_reconstruction.h>
#include <CGAL/Advancing_front_surface_reconstruction.h>
#include <CGAL/Scale_space_surface_reconstruction_3.h>
#include <CGAL/Scale_space_reconstruction_3/Jet_smoother.h>
#include <CGAL/Scale_space_reconstruction_3/Advancing_front_mesher.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <cstdlib>
#include <vector>
#include <fstream>
// types
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point_3;
typedef Kernel::Vector_3 Vector_3;
typedef Kernel::Sphere_3 Sphere_3;
typedef CGAL::Point_set_3<Point_3, Vector_3> Point_set;
int main(int argc, char*argv[])
{
Point_set points;
if (argc < 2)
{
std::cerr << "Usage: " << argv[0] << " [input.xyz/off/ply/las]" << std::endl;
return EXIT_FAILURE;
}
const char* input_file = argv[1];
std::ifstream stream (input_file, std::ios_base::binary);
if (!stream)
{
std::cerr << "Error: cannot read file " << input_file << std::endl;
return EXIT_FAILURE;
}
stream >> points;
std::cout << "Read " << points.size () << " point(s)" << std::endl;
if (points.empty())
return EXIT_FAILURE;
CGAL::remove_outliers<CGAL::Sequential_tag>
(points,
24, // Number of neighbors considered for evaluation
points.parameters().threshold_percent (5.0)); // Percentage of points to remove
std::cout << points.number_of_removed_points()
<< " point(s) are outliers." << std::endl;
// Applying point set processing algorithm to a CGAL::Point_set_3
// object does not erase the points from memory but place them in
// the garbage of the object: memory can be freeed by the user.
points.collect_garbage();
// Compute average spacing using neighborhood of 6 points
double spacing = CGAL::compute_average_spacing<CGAL::Sequential_tag> (points, 6);
// Simplify using a grid of size 2 * average spacing
CGAL::grid_simplify_point_set (points, 2. * spacing);
std::cout << points.number_of_removed_points()
<< " point(s) removed after simplification." << std::endl;
points.collect_garbage();
CGAL::jet_smooth_point_set<CGAL::Sequential_tag> (points, 24);
unsigned int reconstruction_choice
= (argc < 3 ? 0 : atoi(argv[2]));
if (reconstruction_choice == 0) // Poisson
{
CGAL::jet_estimate_normals<CGAL::Sequential_tag>
(points, 24); // Use 24 neighbors
// Orientation of normals, returns iterator to first unoriented point
typename Point_set::iterator unoriented_points_begin =
CGAL::mst_orient_normals(points, 24); // Use 24 neighbors
points.remove (unoriented_points_begin, points.end());
return EXIT_SUCCESS;
}
Environment
I've replicated that issue in a debian VM as well as in a docker environment in macos (debian based as well).
Pretty standard stuffs, I'm using the CMakeLists.txt already available in the tutorial_example.cpp folder and running:
Creates files that will show the compiler how to behave
cmake -DCGAL_DIR=/app/cgal -DCMAKE_BUILD_TYPE=Release .
Build the exe
make
I'm a self taught Python programmer so quite new to the C++ stuffs.

Boost convex hull with longitude and latitude

I am trying to use boost's convex_hull algorithm with longitude/latitude coordinates.
From here: https://archive.fosdem.org/2017/schedule/event/geo_boost_geography/attachments/slides/1748/export/events/attachments/geo_boost_geography/slides/1748/FOSDEM17_vissarion.pdf
I can see that we can calculate the distance between two points and even find the area using longitude/latitude coordinates (see page 19 and 22 of the PDF document).
Combining that with https://www.boost.org/doc/libs/1_75_0/libs/geometry/doc/html/geometry/reference/algorithms/convex_hull.html
I came up with this: https://wandbox.org/permlink/2AGPUtHPWrlGFMTf, but it does not compile, code here for convenience:
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
namespace bg = boost::geometry;
int main()
{
typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree>> point;
typedef boost::geometry::model::polygon<point> polygon;
polygon poly;
bg::read_wkt(" POLYGON ((4.346693 50.858306, 4.367945 50.852455, 4.366227 50.840809, 4.344961 50.833264, 4.338074 50.848677,4.346693 50.858306))",
poly );
polygon hull;
boost::geometry::convex_hull(poly, hull);
using boost::geometry::dsv;
std::cout << "polygon: " << dsv(poly) << std::endl << "hull: " << dsv(hull) << std::endl;
}
Any help is much appreciated.
Yeah, though you may be right that a strategy /can/ be made, that is not implemented.
A little side-by-side tester clearly shows that the strategy is not implemented for the geographical coordinate system:
template <typename cs> void test() {
using point = bg::model::point<double, 2, cs>;
using polygon = bg::model::polygon<point>;
polygon poly;
bg::read_wkt("POLYGON((4.346693 50.858306, 4.367945 50.852455, 4.366227 "
"50.840809, 4.344961 50.833264, 4.338074 50.848677,4.346693 "
"50.858306))",
poly);
std::cout << std::fixed;
std::cout << "Polygon: " << bg::dsv(poly) << std::endl;
std::cout << "Perimeter: " << bg::perimeter(poly) << std::endl;
std::cout << "Area: " << bg::area(poly) << std::endl;
using Strategy = typename bg::strategy_convex_hull<polygon, point>::type;
std::cout << "Strategy " << boost::core::demangle(typeid(Strategy).name()) << "\n";
if constexpr (not std::is_same_v<Strategy, bg::strategy::not_implemented>) {
polygon hull;
bg::convex_hull(poly, hull);
std::cout << "Hull: " << bg::dsv(hull) << std::endl;
}
}
It also demonstrates that some other strategies are implemented (e.g. distance).
See it Live On Coliru
int main() {
std::cout << "Cartesian:\n";
std::cout << "----------\n";
test<bg::cs::cartesian>();
std::cout << "\nGeographic:\n";
std::cout << "-----------\n";
test<bg::cs::geographic<bg::degree>>();
}
Simplifying the the typenames in the output:
Cartesian:
----------
Polygon: (((4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)))
Perimeter: 0.086184
Area: 0.000488
Strategy bg::strategy::convex_hull::graham_andrew<polygon, point>
Hull: (((4.338074, 50.848677), (4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677)))
Geographic:
-----------
Polygon: (((4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)))
Perimeter: 7663.398262
Area: 3848183.734567
Strategy bg::strategy::not_implemented
A look at the documented strategies suggests that graham_andrew is in fact the only one available.
You should probably find out what tweaks are required to get things to work. it is technically possible to force convex_hull to use the Graham/Andrew strategy, but that seems ill-advised as the trait implies that the strategy is specifically deselected based on the coordinate system:
/*!
\brief Traits class binding a convex hull calculation strategy to a coordinate system
\ingroup convex_hull
\tparam Tag tag of coordinate system
\tparam Geometry the geometry type (hull operates internally per hull over geometry)
\tparam Point point-type of output points
*/
template
<
typename Geometry1,
typename Point,
typename CsTag = typename cs_tag<Point>::type
>
struct strategy_convex_hull
{
typedef strategy::not_implemented type;
};
Digging into the implementation of the strategy here's a hopeful hint:
// TODO: User-defiend CS-specific side strategy
typename strategy::side::services::default_strategy<cs_tag>::type side;
Perhaps we could be "done" with "just" specializing the Side Strategy for your coordinate systems? And more interestingly: a strategy::side::geographic exists. I'm out of my depth understanding the parameters (e.g. what the geodetic solution policy means?), but maybe yourself can take it from there?
I'm convinced that if you know what needs to be done, the helpful devs over at the mailing list will be very willing to guide the technical questions on how to fit it into the library.

Geometry, intersection

I have a problem. I would like to intersect a quad with a quad.
int main(){
typedef boost::geometry::model::point_xy<double> TBoostPoint;
typedef boost::geometry::model::polygon<TBoostPoint> TBoostPoly;
TBoostPoint point;
TBoostPoly firstPoly, secondPoly;
boost::geometry::read_wkt("POLYGON(
(1.504477611940313, 3.761194029850755),
(1.504477611940305, 3.573134328358203),
(1.316417910447765, 3.573134328358206),
(1.316417910447769, 3.761194029850752))", firstPoly);
boost::geometry::read_wkt("POLYGON(
(1.504477611940313, 3.761194029850755),
(1.504477611940305, 3.573134328358203),
(1.316417910447765, 3.573134328358206),
(1.316417910447751, 3.761194029850769))", secondPoly);
std::vector<TBoostPoly> outPoly;
boost::geometry::intersection(firstPoly,secondPoly,outPoly);
}
outPoly - is empty, but it not so.
There were 2 main issues.
The output is undefined because the input is invalid.
The input WKT specifies a lot of invalid inner rings (consisting of single points), instead of what you expected, a single outer ring of 5 points (excl. closing point). Fix it:
bg::read_wkt("POLYGON(( 1.504477611940313 3.761194029850755, 1.504477611940305 3.573134328358203, 1.316417910447765 3.573134328358206, 1.316417910447769 3.761194029850752))", first);
bg::read_wkt("POLYGON(( 1.504477611940313 3.761194029850755, 1.504477611940305 3.573134328358203, 1.316417910447765 3.573134328358206, 1.316417910447751 3.761194029850769))", second);
Boost Geometry assumes throughout that you never make errors against the documented preconditions. If you read in the polygon concept page and preconditions for intersection you'll see thew full list¹.
If you don't, you get no friendly errors, just silent failure, corruption or just wrong answers. Yeah. That's bad.
What's worse, BGeo didn't even have a is_valid facility to test the bulk of requirements until Boost 1_57 (IIRC). The good news is, if you upgrade to this version or later your life will be much simpler.
In this case you would have learned that the polygons weren't properly closed:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
namespace bg = boost::geometry;
int main(){
typedef bg::model::d2::point_xy<double> TPoint;
typedef bg::model::polygon<TPoint> TPoly;
TPoly first, second;
bg::read_wkt("POLYGON(( 1.504477611940313 3.761194029850755, 1.504477611940305 3.573134328358203, 1.316417910447765 3.573134328358206, 1.316417910447769 3.761194029850752))", first);
bg::read_wkt("POLYGON(( 1.504477611940313 3.761194029850755, 1.504477611940305 3.573134328358203, 1.316417910447765 3.573134328358206, 1.316417910447751 3.761194029850769))", second);
std::string reason;
// polys not closed!
if (!bg::is_valid(first, reason)) std::cout << "First polygon not valid: " << reason << "\n";
if (!bg::is_valid(second, reason)) std::cout << "Second polygon not valid: " << reason << "\n";
bg::correct(first);
bg::correct(second);
// no more output!
if (!bg::is_valid(first, reason)) std::cout << "First polygon not valid: " << reason << "\n";
if (!bg::is_valid(second, reason)) std::cout << "Second polygon not valid: " << reason << "\n";
std::vector<TPoly> out;
bg::intersection(first, second, out);
for (auto& g : out)
std::cout << "\nresult: " << bg::wkt(g) << "\n";
}
Prints:
First polygon not valid: Geometry is defined as closed but is open
Second polygon not valid: Geometry is defined as closed but is open
Oops. The geos weren't closed! correct(poly) fixes this for us on auto-pilot:
result: POLYGON((1.50448 3.57313,1.31642 3.57313,1.31642 3.76119,1.50448 3.76119,1.50448 3.57313))
¹ outer ring must be counter clockwise, inner cw, polys must be closed... stuff like that.

Boost::geometry Trouble in using within method on point and polygons?

It seems that I have trouble in using correctly the boost geometry library ( Boost::geometry : calculation of the centroid of a polygon ). I very much appreciated the help on my previous question and would like to ask something about the boost::geometry::within method, answering if one geometry is contained in another one.
I'm using it in my code to check if a point is contained in a polygon, and I'm encountering weird results where a point should definitely not be inside a polygon far away but the method still returns True when called.
I'm thinking about a subtlety I'm missing when declaring my polygon, and I would really like to pin down this trouble. Though looking at my code back and forth, I'm lacking ideas in debugging this, and it feels like a got tunnel vision. That's why I'd like to have an hint on this specific example:
My point has coordinates: 221.703 , 256
The polygon is coordinates are, point by point:
266.158 256
266.447 256.5
267.024 256.5
267.313 257
267.024 257.5
267.313 258
which clearly shouldn't contain the point given above.
I'm sorry to ask on something this pedantic, but I'd be really thankful to anyone willing to put their nose in this
My code:
#include <iostream>
#include <boost/geometry.hpp>
using namespace std;
namespace bg = boost::geometry;
typedef bg::model::point<float, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
typedef bg::model::polygon<point, false, true> polygon;
int main(int argc, char * argv[]){
polygon pol;
pol.outer().push_back(point(266.158,256));
pol.outer().push_back(point(266.447,256.5));
pol.outer().push_back(point(267.024,256.5));
pol.outer().push_back(point(267.313,257));
pol.outer().push_back(point(267.024,257.5));
pol.outer().push_back(point(267.313,258));
double x = atof(argv[1]);
double y = atof(argv[2]);
cout << "Is inside: " << ((bg::within(point(x,y),pol)) ? "yes" : "no") << endl;
return 0;
}
When you use bg::model::polygon<point, false, true> you are defining a polygon that uses point as its point type, that has its points in counter clockwise order and that is closed (meaning that its last point is equal to its first). If you either "close" your polygon or use an open polygon, the behaviour of bg::within seems to be what you expect:
Running on Coliru
#include <iostream>
#include <boost/geometry.hpp>
using std::cout;
using std::endl;
namespace bg = boost::geometry;
typedef bg::model::point<float, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
typedef bg::model::polygon<point, false, true> closed_polygon;
typedef bg::model::polygon<point, false, false> open_polygon;
int main(int argc, char * argv[])
{
{
closed_polygon pol;
pol.outer().push_back(point(266.158,256));
pol.outer().push_back(point(266.447,256.5));
pol.outer().push_back(point(267.024,256.5));
pol.outer().push_back(point(267.313,257));
pol.outer().push_back(point(267.024,257.5));
pol.outer().push_back(point(267.313,258));
pol.outer().push_back(point(266.158,256));//you need to close the polygon
double x = 222;
double y = 257;
cout << "Is " << bg::wkt<point>(point(x,y)) << " inside: " << ((bg::within(point(x,y),pol)) ? "yes" : "no") << endl;
x = 267;
y = 257;
cout << "Is " << bg::wkt<point>(point(x,y)) << " inside: " << ((bg::within(point(x,y),pol)) ? "yes" : "no") << endl;
}
{
open_polygon pol;
pol.outer().push_back(point(266.158,256));
pol.outer().push_back(point(266.447,256.5));
pol.outer().push_back(point(267.024,256.5));
pol.outer().push_back(point(267.313,257));
pol.outer().push_back(point(267.024,257.5));
pol.outer().push_back(point(267.313,258));
double x = 222;
double y = 257;
cout << "Is " << bg::wkt<point>(point(x,y)) << " inside: " << ((bg::within(point(x,y),pol)) ? "yes" : "no") << endl;
x = 267;
y = 257;
cout << "Is " << bg::wkt<point>(point(x,y)) << " inside: " << ((bg::within(point(x,y),pol)) ? "yes" : "no") << endl;
}
return 0;
}

Boost geometry cartesian2d.hpp [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I tried to do this clipping example using Boost Geometry in the example here
But in the newest Boost library I can't find ...
boost/geometry/geometries/cartesian2d.hpp
Does anyone have any idea where I might find this file? Or is this tutorial too old, and the file now obsolete?
The tutorial is too old. Much has changed since that tutorial was written.
Anyhow, I've modified the code in your link above so that it compiles in Boost ver 1.53.0 ...
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
using namespace boost::geometry;
typedef model::d2::point_xy<double> point;
typedef model::ring< point > ring;
typedef model::polygon< point > polygon;
typedef model::multi_polygon< polygon > polygons;
typedef model::box< point > box;
// Define a polygon and fill the outer ring.
// In most cases you will read it from a file or database
polygon poly;
{
read_wkt("POLYGON((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))", poly);
}
// 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 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 cent;
centroid(poly, cent);
std::cout << "centroid: " << dsv(cent) << std::endl;
// The number of points have to called per ring separately
std::cout << "number of points in outer ring: " << poly.outer().size() << std::endl;
// Polygons can have one or more inner rings, also called holes, donuts, islands, interior rings.
// Let's add one
{
poly.inners().resize(1);
ring& inner = poly.inners().back();
read_wkt("POLYGON((4.0 2.0, 4.2 1.4, 4.8 1.9, 4.4 2.2, 4.0 2.0))", inner);
}
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: " << (within(make<point>(3.0, 2.0), poly)?"true":"false")
<< " p2: " << (within(make<point>(3.7, 2.0), poly)?"true":"false")
<< " p3: " << (within(make<point>(4.4, 2.0), poly)?"true":"false")
<< 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 bounding box
box cb(make<point>(1.5, 1.5), make<point>(4.5, 2.5));
polygons v;
intersection(cb, poly, v);
std::cout << "Clipped output polygons" << std::endl;
for (polygons::const_iterator it = v.begin(); it != v.end(); ++it)
{
std::cout << dsv(*it) << std::endl;
}
union_(cb, poly, v);
polygon 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 independently
typedef model::polygon<point, true, true, std::vector, std::deque> polygon_deq;
polygon_deq poly2;
polygon_deq::ring_type& r = poly2.outer();
append(r, make<point>(2.8, 1.9));
append(r, make<point>(2.9, 2.4));
append(r, make<point>(3.3, 2.2));
append(r, make<point>(3.2, 1.8));
append(r, make<point>(2.8, 1.9));
std::cout << dsv(poly2) << std::endl;