缩放/扩展带孔多边形的轮廓

3
我想使用boost::polygon来扩展/缩小带孔多边形。为了更清楚,我有一个单一的数据结构。
boost::polygon::polygon_with_holes_data<int> inPoly

其中inPoly包含描述矩形轮廓和三角形(在下面的图片中是左边的黑色图案)的数据,该三角形成为矩形内的孔。

现在我想要:

a)扩展整个东西,使矩形变大并且孔变小(导致下面图片中的红色多边形),或者

b)缩小它,使矩形变小并且孔变大(导致下面图片中的绿色图像)。

Polygon

角落不一定需要是直的,也可以是圆形或者其他形状。

我的问题:如何使用boost::polygon来完成这个任务?

谢谢!


也许是这个:https://www.boost.org/doc/libs/1_73_0/libs/geometry/doc/html/geometry/reference/algorithms/buffer/buffer_7_with_strategies.html - Bob__
这是boost::geometry,它不能与boost::polygon::polygon_with_holes_data一起使用 - 这是我的数据可用的格式。或者有没有将它们转换为相关的boost:geometry结构的函数? - Elmi
2个回答

4

我回答了这个问题:如何使用Boost Geometry扩展多边形?

是的,您可以教给Boost Geometry如何操作Boost Polygon类型:

#include <boost/geometry/geometries/adapted/boost_polygon.hpp>

我按照你所描述的方式设计了一个测试多边形:
boost::polygon::polygon_with_holes_data<int> inPoly;
bg::read_wkt("POLYGON ((0 0,0 1000,1000 1000,1000 0,0 0),(100 100,900 100,500 700,100 100))", inPoly);

现在显然我们不能直接在适配的多边形上进行buffer,也不能直接使用bg::assignbg::convert。因此,我想出了一个丑陋的解决方法,将其转换为WKT格式并再次转换回来。然后您可以进行缓冲操作,并类似地进行转换。

这不是非常优雅,但它确实可以工作:

poly in;
bg::read_wkt(boost::lexical_cast<std::string>(bg::wkt(inPoly)), in);

完整演示

包括SVG输出:

在Coliru上实时演示

#include <boost/polygon/polygon.hpp>
#include <boost/polygon/polygon_set_data.hpp>
#include <boost/polygon/polygon_with_holes_data.hpp>

#include <boost/geometry.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/algorithms/buffer.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/adapted/boost_polygon.hpp>
#include <fstream>

namespace bp = boost::polygon;
namespace bg = boost::geometry;
using P = bp::polygon_with_holes_data<int>;
using PS = bp::polygon_set_data<int>;
using coordinate_type = bg::coordinate_type<P>::type;

int main() {
    P inPoly, grow, shrink;
    bg::read_wkt("POLYGON ((0 0,0 1000,1000 1000,1000 0,0 0),(100 100,900 100,500 700,100 100))", inPoly);

    {
        // define our boost geometry types
        namespace bs = bg::strategy::buffer;
        namespace bgm = bg::model;
        using pt = bgm::d2::point_xy<coordinate_type>;
        using poly = bgm::polygon<pt>;
        using mpoly = bgm::multi_polygon<poly>;

        // define our buffering strategies
        using dist = bs::distance_symmetric<coordinate_type>;
        bs::side_straight  side_strategy;
        const int points_per_circle = 12;
        bs::join_round   join_strategy(points_per_circle);
        bs::end_round    end_strategy(points_per_circle);
        bs::point_circle point_strategy(points_per_circle);

        poly in;
        bg::read_wkt(boost::lexical_cast<std::string>(bg::wkt(inPoly)), in);

        for (auto [offset, output_p] : { std::tuple(+15, &grow), std::tuple(-15, &shrink) }) {
            mpoly out;
            bg::buffer(in, out, dist(offset), side_strategy, join_strategy, end_strategy, point_strategy);

            assert(out.size() == 1);
            bg::read_wkt(boost::lexical_cast<std::string>(bg::wkt(out.front())), *output_p);
        }
    }

    {
        std::ofstream svg("output.svg");
        using pt = bg::model::d2::point_xy<coordinate_type>;
        boost::geometry::svg_mapper<pt> mapper(svg, 400, 400);
        mapper.add(inPoly);
        mapper.add(grow);
        mapper.add(shrink);

        mapper.map(inPoly, "fill-opacity:0.3;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
        mapper.map(grow, "fill-opacity:0.05;fill:rgb(255,0,0);stroke:rgb(255,0,0);stroke-width:2");
        mapper.map(shrink, "fill-opacity:0.05;fill:rgb(0,0,255);stroke:rgb(0,0,255);stroke-width:2");
    }
}

生成了 output.svg 文件:

图片描述在此处输入


抱歉,我不知道我的另一个问题去哪了 - 非常感谢您提供详细的答案!!! - Elmi

2

我有些意外地发现boost::polygon也提供了一个非常易于使用的单一函数:boost::polygon::polygon_set_data。该函数提供了一个resize()函数,正好可以完成上述描述的功能。使用额外的参数corner_fill_arc和num_segments,可以创建圆角。

不知道为什么这个函数位于boost::polygon::polygon_set_data中,而不是位于boost::polygon::polygon_with_holes_data中,我认为后者更合理。


1
可能是Boost Geometry算法返回多边形的原因相同。不过还是感谢您发布这个答案。我从来没有完全掌握Boost Polygon,而且这个功能非常难以发现(我可以说命名也很糟糕)。 - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接