如何使用C ++ boost几何来从两个polgons创建ring(donut)?

时间:2017-12-07 00:13:49

标签: c++ boost geometry boost-geometry

我试图计算2个多边形之间的差异(事实上,为简单起见,直线形状)。例如,shape1具有点列表{0 0,100,0,100 100,0 100},并且shape2具有点列表{25 25,75 25,75 75,25 75}。 所以按照概念,我期待" shape1 - shape2"将为我提供4个矩形盒子,可以制作戒指或圆环形状。我不知道如何实现这一目标,但我发现"提升"图书馆在线并尝试过这样:

enter image description here

#include <iostream>
#include <list>

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

#include <boost/foreach.hpp>


int main()
{
    typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;

    polygon green, blue;

    boost::geometry::read_wkt( "POLYGON((0 0 100 0 100 100 0 100))", green);

    boost::geometry::read_wkt( "POLYGON((25 25 75 22 75 75 25 75))", blue);

    std::list<polygon> output;
    boost::geometry::difference(green, blue, output);

    int i = 0;
    std::cout << "green - blue:" << std::endl;
    BOOST_FOREACH(polygon const& p, output)
    {
        std::cout << i++ << ": " << boost::geometry::area(p) << std::endl;
    }


    output.clear();
    boost::geometry::difference(blue, green, output);

    i = 0;
    std::cout << "blue - green:" << std::endl;
    BOOST_FOREACH(polygon const& p, output)
    {
        std::cout << i++ << ": " << boost::geometry::area(p) << std::endl;
    }


    return 0;
}

然而,没有打印出来...我的计划是找出一种方法将输出结果转换为矩形框{0 0 100 0 100 25 0 25} {0 75 100 75 100 100 0 100} {0 25 25 25 25 75 0 75}和{75 25 100 25 100 75 75 75},但我感到沮丧的是,上述代码根本没有打印出来。 谁能给我一些指导? 我附上了一张图片,展示了我想做的事情。事实上,我已经拥有了代表这个甜甜圈的所有点坐标,所以也许我可以跳过&#34;差异()函数&#34; ?如果是这种情况,困难的部分将是将甜甜圈转换成矩形段。 (我们假设这里的所有多边形都是直线形状。) 感谢。

2 个答案:

答案 0 :(得分:0)

您的起始多边形没有所需的方向。您可以使用is_valid自行查找。方便的是,您可以使用correct来解决输入数据中最常见的问题:

std::string reason;
if (!bg::is_valid(geometry, reason))
{
    std::cout << "Correcting " << bg::wkt(geometry) << " to ";
    bg::correct(geometry);
    std::cout << bg::wkt(geometry) << "\n";

    if (!bg::is_valid(geometry, reason))
        std::cout << "UNCORRECTIBLE: " << reason << "\n";
}

当你这样做时,你会发现:

Correcting POLYGON((0 0,100 0,100 100,0 100,0 0)) to POLYGON((0 0,0 100,100 100,100 0,0 0))
Correcting POLYGON((25 25,75 22,75 75,25 75,25 25)) to POLYGON((25 25,25 75,75 75,75 22,25 25))

现在,当你得到差异时,你将得到预期的结果:

auto do_diff = [](std::string caption, auto const& a, auto const& b) {
    multi output;
    bg::difference(a, b, output);

    std::cout << caption << bg::wkt(output) << std::endl;
};

do_diff("green - blue:", green, blue);
do_diff("blue - green:", blue, green);

完整演示

<强> Live On Coliru

#include <iostream>
#include <fstream>

#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/foreach.hpp>

namespace bg = boost::geometry; 

int main() {
    typedef bg::model::d2::point_xy<double> point;
    typedef bg::model::polygon<point> polygon;
    typedef bg::model::multi_polygon<polygon> multi;

    polygon green, blue;

    bg::read_wkt("POLYGON((0 0 100 0 100 100 0 100))", green);
    bg::read_wkt("POLYGON((25 25 75 22 75 75 25 75))", blue);

    auto test = [](polygon& geometry) {
        std::string reason;
        if (!bg::is_valid(geometry, reason))
        {
            std::cout << "Correcting " << bg::wkt(geometry) << " to ";
            bg::correct(geometry);
            std::cout << bg::wkt(geometry) << "\n";

            if (!bg::is_valid(geometry, reason))
                std::cout << "UNCORRECTIBLE: " << reason << "\n";
        }
    };

    test(green);
    test(blue);

    auto do_diff = [](std::string caption, polygon const& a, polygon const& b) {
        multi output;
        bg::difference(a, b, output);

        std::cout << caption << bg::wkt(output) << std::endl;
    };

    do_diff("green - blue:", green, blue);
    do_diff("blue - green:", blue, green);

    {
        std::ofstream svg("output.svg");
        boost::geometry::svg_mapper<point> mapper(svg, 400, 400);
        mapper.add(blue);
        mapper.add(green);

        mapper.map(blue, "fill-opacity:0.5;fill:rgb(0,0,153);stroke:rgb(0,0,200);stroke-width:2");
        mapper.map(green, "fill-opacity:0.5;fill:rgb(0,153,0);stroke:rgb(0,200,0);stroke-width:2");
    }
}

打印

Correcting POLYGON((0 0,100 0,100 100,0 100,0 0)) to POLYGON((0 0,0 100,100 100,100 0,0 0))
Correcting POLYGON((25 25,75 22,75 75,25 75,25 25)) to POLYGON((25 25,25 75,75 75,75 22,25 25))
green - blue:MULTIPOLYGON(((0 0,0 100,100 100,100 0,0 0),(25 25,75 22,75 75,25 75,25 25)))
blue - green:MULTIPOLYGON()

并写svg:

enter image description here

答案 1 :(得分:0)

  

other answer将结束你的沮丧/困惑,这个答案会让你更有成效:)

而且,是的,你可以跳过差异函数:

bg::read_wkt("POLYGON((0 0 0 100 100 100 100 0 0 0) (25 25 75 22 75 75 25 75 25 25))", donut);

指定内环(反方向!)。

结果:

enter image description here

由该程序生成:

<强> Live On Coliru

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

#include <iostream>
#include <fstream>

namespace bg = boost::geometry; 

int main() {
    typedef bg::model::d2::point_xy<double> point;
    typedef bg::model::polygon<point> polygon;

    polygon donut;
    bg::read_wkt("POLYGON((0 0 0 100 100 100 100 0 0 0) (25 25 75 22 75 75 25 75 25 25))", donut);

    std::ofstream svg("output.svg");
    boost::geometry::svg_mapper<point> mapper(svg, 400, 400);
    mapper.add(donut);

    mapper.map(donut, "fill-opacity:0.5;fill:rgb(0,0,153);stroke:rgb(0,0,200);stroke-width:2");
}