Преобразование полигона boost::geometry в объект STL
Как получить полигон boost::geometry в объект STL?
Я уверен, что это должно быть просто, потому что я не могу найти примеры нигде в документации. Тем не менее, я потратил около 4 рабочих дней, пытаясь сделать эту крошечную вещь. Я новичок в C++ (долгое время программист на R), но эти мелкие проблемы с преобразованием данных сводят меня с ума.
Да, есть вопрос, название которого очень похоже на мое: получение координат точек из многоугольника Boost Geometry
Но код настолько сложен (и постер постоянно менял его), что я не могу понять, как это сделать, и не могу представить, что другие новички в C++ смогут это сделать.
Это простой пример, который должен быть переведен на некоторые другие типы данных boost::geometry, так что, надеюсь, любой сможет его выполнить.
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
//One thing I tried is a function to use with `for_each_point()` so I set that up first.
template <typename Point>
void get_coordinates(Point const& p)
{
using boost::geometry::get;
std::cout << get<0>(p) get<1>(p) << std::endl;
}
int main()
{
typedef boost::tuple<double, double> point;
typedef boost::geometry::model::polygon<point> polygon;
polygon poly;
boost::geometry::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);
polygon hull;
boost::geometry::convex_hull(poly, hull);
// Now I know I can `dsv()` and print to the screen like this:
using boost::geometry::dsv;
std::cout
<< "hull: " << dsv(hull) << std::endl;
// And/Or I can use my function with for_each_point()
boost::geometry::for_each_point(hull, get_coordinates<point>);
return 0;
}
Как мне получить эти координаты в контейнер STL? Я бы предпочел два std::vector один для x и один для y, но все подойдет.
3 ответа
Полигоны уже находятся в формате контейнера STL, внешнее кольцо boost::geometry::polygon имеет внутреннее кольцо, а внутренние кольца по умолчанию хранят std:: vector.
Что вы могли бы хотеть (учитывая ваши комментарии):
polygon hull;
boost::geometry::convex_hull(poly, hull);
boost::geometry::for_each_point(boost::geometry::exterior_ring(hull), get_coordinates<point>);
Это будет работать, если вы исправите свою функцию get_coordinates (обратите внимание на << использование):
template <typename Point>
void get_coordinates(Point const& p)
{
using boost::geometry::get;
std::cout << get<0>(p) << ", " << get<1>(p) << std::endl;
}
И измените ваши индикаторы комментариев на //;-)
Вы можете использовать итераторы с моделями повышения, чтобы перебирать все точки и добавлять их в любой вид контейнера, который вам нравится.
Модели полигонов немного сложнее, потому что они имеют одно наружное и, возможно, несколько внутренних колец.
Предполагая, что вы хотите, чтобы все точки во внешнем кольце объекта "корпус" (или любого многоугольника, включая исходный "многоугольник") просто перебирали его и добавляли их к стандартному вектору точка-точка.
Если вы хотите вектор x и вектор y, используйте один и тот же метод.
::std::vector< point > hullPoints;
::std::vector< double > hullXPoints;
::std::vector< double > hullYPoints;
// the auto keyword makes declaring iterators easy
for ( auto hullIterator = hull.outer().begin;
hullIterator != hull.outer().end();
++hullIterator )
{
// for a vector of point types, just add the points one by one
hullPoints.push_back( *hullIterator );
// for vectors of x and y, extract the x/y from the point
hullXPoints.push_back( get<0>( *hullIterator ) );
hullYPoints.push_back( get<1>( *hullIterator ) );
}
Например:
boost::geometry::model::polygon<Point> polygon;
polygon.outer().push_back( point );
Итак, polygon.outer() - это std::vector (внешний, как сказал Баренд Герелс). Смотрите здесь: увеличить ссылку