Избыточные вершины при масштабировании полигона с буст-буфером геометрии

Я использую геометрию повышения для управления некоторыми полигонами, и мне нужно как расширять, так и уменьшать их на заданные величины. Я использую boost::geometry::buffer для этого, и мне интересно, есть ли лучшая альтернатива. Меня беспокоит то, что если я расширяю, скажем, прямоугольник, я получаю многоугольник с 12 вершинами (8 из них не имеют значения). Вот пример кода:

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

using point_t = boost::geometry::model::d2::point_xy<double>;
using polygon_t = boost::geometry::model::polygon<point_t>;
using mpolygon_t = boost::geometry::model::multi_polygon<polygon_t>;

mpolygon_t expand_polygon(const polygon_t& polygon,
                          const double distance) {
    mpolygon_t scaled_polygon;
    // DistanceStrategy is symmetric; want straight lines (no curves)
    boost::geometry::strategy::buffer::distance_symmetric<double>
      distance_strategy{distance};

    // SideStrategy is straight; grow equally on all sides
    boost::geometry::strategy::buffer::side_straight side_strategy;

    // JoinStrategy is miter; 1.0 as limit; Sharp (not rounded) joins
    boost::geometry::strategy::buffer::join_miter join_strategy;

    // EndStrategy is flat; flat (not rounded) ends
    boost::geometry::strategy::buffer::end_flat end_strategy;

    // PointStrategy is square; squares, not circles, if poly is just a point
    boost::geometry::strategy::buffer::point_square point_strategy;

    boost::geometry::buffer(polygon, scaled_polygon,
                            distance_strategy,
                            side_strategy,
                            join_strategy,
                            end_strategy,
                            point_strategy);

    // return scaled polygon offset by supplied distance
    return scaled_polygon;
}

int main() {
    using boost::geometry::get;
    polygon_t rect;
    boost::geometry::read_wkt("POLYGON((5 5,5 8,8 8,8 5, 5 5))", rect);
    mpolygon_t expanded_mpoly = expand_polygon(rect, 1.0);
    auto list_coordinates = [](const point_t& pt) {
                                std::cout.precision(std::numeric_limits<double>::max_digits10);
                                std::cout << "vertex(" << get<0>(pt)
                                          << ", " << get<1>(pt) << ")" << std::endl;
                            };
    boost::geometry::for_each_point(expanded_mpoly, list_coordinates);

    return 0;
}

И вот результат:

vertex(4, 5)
vertex(4, 8)
vertex(4, 9)
vertex(5, 9)
vertex(8, 9)
vertex(9, 9)
vertex(9, 8)
vertex(9, 5)
vertex(9, 4)
vertex(8, 4)
vertex(5, 4)
vertex(4, 4)
vertex(4, 5)

Есть ли аргумент стратегии, который мне нужно предоставить? Какая-то другая вотчина наддува, на которую мне следует обратить внимание?


person user888379    schedule 22.08.2018    source источник


Ответы (1)


Boost содержит алгоритм simplify (использует Ramer–Douglas–Peucker алгоритм). Например в вашем полигоне 3 точки p1,p2,p3, вычисляем расстояние между точкой p2 и линией |p1p3| , если это расстояние меньше заданного значения epsilon , p2 точка удаляется из полигона. Таким образом, если вы используете эту функцию с очень маленьким значением epsilon (чтобы удалить коллинеарные точки), вы можете удалить все лишние точки со всех ребер полигона. Попробуй это

mpolygon_t out; // to hold new geometry
boost::geometry::simplify(expanded_mpoly,out,0.00001); // very small epsilon value
auto list_coordinates = [](const point_t& pt) {
                            std::cout.precision(std::numeric_limits<double>::max_digits10);
                            std::cout << "vertex(" << get<0>(pt)
                                      << ", " << get<1>(pt) << ")" << std::endl;
                        };
boost::geometry::for_each_point(out, list_coordinates); // print out

как результат вы видите

vertex(9, 9)
vertex(9, 4)
vertex(4, 4)
vertex(4, 9)
vertex(9, 9)
person rafix07    schedule 22.08.2018
comment
Это очень полезно, спасибо! Я собираюсь немного подождать, прежде чем принять этот ответ, на случай, если есть подход, который не создает посторонних точек. - person user888379; 22.08.2018