Is there any way of making boost::geometry::area
work with a vector of pairs? It says here https://www.boost.org/doc/libs/1_75_0/libs/geometry/doc/html/geometry/reference/algorithms/area/area_1.html that it should work with MultiPoint. So I have called BOOST_GEOMETRY_REGISTER_MULTI_POINT
- which works for convex_hull
, but it does not work for area
. Or do I have to create a Polygon and append the points to it as shown here:
https://www.boost.org/doc/libs/1_75_0/libs/geometry/doc/html/geometry/reference/models/model_polygon.html
This is my code:
#include <iostream>
#include <cstdlib>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/multi/geometries/register/multi_point.hpp>
BOOST_GEOMETRY_REGISTER_POINT_2D(decltype(std::pair<double, double>{}), double, cs::cartesian, first, second)
BOOST_GEOMETRY_REGISTER_MULTI_POINT(decltype(std::vector<std::pair<double, double>>{}))
using MultiPoint = std::vector<std::pair<double, double>>;
MultiPoint getHull(const MultiPoint& points)
{
MultiPoint hull{};
boost::geometry::convex_hull(points, hull);
return hull; // This returns a vector of pairs of points respresenting a hull
}
double getHullArea(const MultiPoint& points)
{
return boost::geometry::area(points); // This always return 0
}
int main()
{
// Unit square
auto points = MultiPoint{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0,0}};
auto hull = getHull(points); // This works as expected
auto area = getHullArea(hull); // This always return 0
}
Yes it support MultiPoint. And you get the documented behaviour:
So, you get area is 0, like you should be expecting.
Clearly you want to adapt as an areal geometry. Let's assume your pairs are Points that form a Ring.
using Point = std::pair<double, double>;
using Ring = std::vector<Point>;
BOOST_GEOMETRY_REGISTER_POINT_2D(Point, double, cs::cartesian, first, second)
BOOST_GEOMETRY_REGISTER_RING(Ring)
Now it works as you should expect:
#include <iostream>
#include <cstdlib>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/ring.hpp>
namespace bg = boost::geometry;
using Point = std::pair<double, double>;
using Ring = std::vector<Point>;
BOOST_GEOMETRY_REGISTER_POINT_2D(Point, double, cs::cartesian, first, second)
BOOST_GEOMETRY_REGISTER_RING(Ring)
Ring getHull(const Ring& points) {
Ring hull;
bg::convex_hull(points, hull);
return hull;
}
double getArea(const Ring& points) {
return bg::area(points);
}
int main() {
for (Ring points : {
Ring{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}},
Ring{{0, 0}, {0, 2}, {3, 2}, {3, 1}, {1, 1}, {1, 0}, {0, 0}},
})
{
std::cout << "-----\nInput:\t" << bg::wkt(points) << "\n";
if (std::string reason; !bg::is_valid(points)) {
std::cout << "Input:\t" << reason << "\n";
bg::correct(points);
std::cout << bg::wkt(points) << "\n";
}
std::cout << "Hull:\t" << bg::wkt(getHull(points)) << "\n";
std::cout << "Area:\t" << getArea(points) << "\n";
std::cout << "Hull Area:\t" << getArea(getHull(points)) << "\n";
}
}
Prints
-----
Input: POLYGON((0 0,0 1,1 1,1 0,0 0))
Hull: POLYGON((0 0,0 1,1 1,1 0,0 0))
Area: 1
Hull Area: 1
-----
Input: POLYGON((0 0,0 2,3 2,3 1,1 1,1 0,0 0))
Hull: POLYGON((0 0,0 2,3 2,3 1,1 0,0 0))
Area: 4
Hull Area: 5
As you can see I added a more interesting example: