-1

我已经获得了一个 boost 多多边形的 WKT 字符串,它是由一个名为 vectorPolygons 的向量中的 boost 多边形的联合构成的

std::vector<boost::geometry::Polygon> vectorPolygons;

在 vectorPolygons 中添加数据后,下面的代码计算它的并集,然后提取多多边形的 WKT

if (!vectorPolygons.empty())
{
    multi_polygon boost_multipolygon;   // Will store union of polygons

    // Create the union of all the polygons
    for (const boost::geometry::Polygon& p : vectorPolygons) {
        // add another polygon each iteration
        multi_polygon tmp_poly;
        boost::geometry::union_(boost_multipolygon, p, tmp_poly);
        boost_multipolygon= tmp_poly;
        boost::geometry::clear(tmp_poly);
    }

    std::string validity_reason;
    bool valid = boost::geometry::is_valid(boost_multipolygon, validity_reason);

    if (!valid)
    {
        boost::geometry::correct(boost_multipolygon);
    }

    std::stringstream ss;

    ss << boost::geometry::wkt(boost_multipolygon);
    std::string wkt = ss.str();

    
}

WKT 字符串如下所示

MULTIPOLYGON(((40000 30000,40000 -0,30000 -0,30000 10000,20000 10000,20000 20000,10000 20000,0 20000,0 30000,40000 30000)))

当我使用下面的代码示例显示这个多面体时,我不确定为什么它的显示总是倒置。实际上,它应该与它所显示的完全相反。

boost::geometry::correct在提取 WKT 之前,我也尝试在 boost 多面体上使用,但仍然显示始终旋转。我做错了什么?

这是试图显示上面生成的 WKT 的代码,输出是颠倒的

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


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

#include <vector>


namespace boost {
    namespace geometry {
        typedef model::d2::point_xy<double> point;
        typedef model::polygon<point> polygon;
    }
}

using multi_polygon = boost::geometry::model::multi_polygon<boost::geometry::polygon>;
namespace bg = boost::geometry;

int main()
{
    // Specify the basic type
    typedef boost::geometry::model::d2::point_xy<double> point_type;

    multi_polygon b;
    boost::geometry::read_wkt("MULTIPOLYGON(((40000 30000,40000 -0,30000 -0,30000 10000,20000 10000,20000 20000,10000 20000,0 20000,0 30000,40000 30000)))", b);
    boost::geometry::correct(b);


    // Declare a stream and an SVG mapper
    std::ofstream svg("my_map.svg");
    boost::geometry::svg_mapper<point_type> mapper(svg, 500, 500);

    // Add geometries such that all these geometries fit on the map
    mapper.add(b);


    // Draw the geometries on the SVG map, using a specific SVG style

    mapper.map(b, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:2");


    // Destructor of map will be called - adding </svg>
    // Destructor of stream will be called, closing the file

    return 0;
}
4

1 回答 1

1

没有“正面朝上”。笛卡尔坐标系就是这样:坐标系。如何将它们映射到视觉投影上是您的选择。

这是我系统上的输出:

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <fstream>
#include <iostream>
namespace bg = boost::geometry;

int main()
{
    using Point = bg::model::d2::point_xy<double>;
    using Poly  = bg::model::polygon<Point>;

    bg::model::multi_polygon<Poly> p;
    bg::read_wkt("MULTIPOLYGON(((40 30,40 -0,30 -0,30 10,20 10,20 20,10 20,0 20,0 30,40 30)))",
                 p);

    {
        std::ofstream svg("my_map.svg");
        bg::svg_mapper<Point> mapper(svg, 400, 400);

        mapper.add(p);
        mapper.map(p, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:1");
    }
}

显示为

在此处输入图像描述

所以你可以看到轴向下/向右增长。这与我能找到的第一个随机在线 WKT 渲染器一致:

在此处输入图像描述

通过这个计数,我将输出评为“正确”。

翻转它?

您可以手动翻转系统:

for (auto& pt : make_iterator_range(bg::points_begin(p), bg::points_end(p))) {
    pt.x(pt.x() * -1);
    pt.y(pt.y() * -1);
}

结果

在此处输入图像描述

一种更通用的方法是使用可以在任意距离/数量上缩放、旋转和平移的变换:https ://www.boost.org/doc/libs/1_78_0/libs/geometry/doc/html/geometry/reference/算法/变换/transform_3_with_strategy.html

更新

我已经用 cololiru.stacked-crooked.com/a/2ba8df83a1ecce91 上的实际数据更新了示例。您共享的代码将我的输入标记为无效,并且 boost::geometry::correct 对其进行操作并旋转输出。是否无法保留输入以使输出不旋转?–测试 16 小时前

逐点说明:“是否无法保留输入”-是的,始终可以保留无效输入,并且您应该期望保留无效输出。

但是,你没有说要纠正什么。我用你的数据运行了我的代码:

POLYGON((30 10,30 -0,40 -0,40 10,30 10)): -100
Correcting source poly: Geometry has wrong orientation
Union: MULTIPOLYGON(((30 10,40 10,40 -0,30 -0,30 10))): 100
POLYGON((30 20,30 10,40 10,40 20,30 20)): -100
Correcting source poly: Geometry has wrong orientation
Union: MULTIPOLYGON(((40 -0,30 -0,30 10,30 20,40 20,40 -0))): 200
POLYGON((30 30,30 20,40 20,40 30,30 30)): -100
Correcting source poly: Geometry has wrong orientation
Union: MULTIPOLYGON(((40 -0,30 -0,30 20,30 30,40 30,40 -0))): 300
POLYGON((20 20,20 10,30 10,30 20,20 20)): -100
Correcting source poly: Geometry has wrong orientation
Union: MULTIPOLYGON(((30 20,30 30,40 30,40 -0,30 -0,30 10,20 10,20 20,30 20))): 400
POLYGON((20 30,20 20,30 20,30 30,20 30)): -100
Correcting source poly: Geometry has wrong orientation
Union: MULTIPOLYGON(((40 30,40 -0,30 -0,30 10,20 10,20 20,20 30,40 30))): 500
POLYGON((10 30,10 20,20 20,20 30,10 30)): -100
Correcting source poly: Geometry has wrong orientation
Union: MULTIPOLYGON(((40 30,40 -0,30 -0,30 10,20 10,20 20,10 20,10 30,40 30))): 600
POLYGON((0 30,0 20,10 20,10 30,0 30)): -100
Correcting source poly: Geometry has wrong orientation
Union: MULTIPOLYGON(((40 30,40 -0,30 -0,30 10,20 10,20 20,10 20,0 20,0 30,40 30))): 700
The important bit: "Correcting source poly: Geometry has wrong orientation".

在某种程度上,您的数据并非无效,它只是对所选几何类型无效!您可以简单地更改多边形类型的方向:

using Poly = bg::model::polygon<Point, false>;

没有任何进一步的改变,你得到:http ://coliru.stacked-crooked.com/a/f02e56fc2402112d

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <fstream>
#include <iostream>
namespace bg = boost::geometry;

template <typename T> auto from_wkt(std::string const& wkt) {
    T result;
    bg::read_wkt(wkt, result);
    return result;
}

template <typename T> void check(T& geo, std::string_view label) {
    for (std::string reason; !bg::is_valid(geo, reason); bg::correct(geo)) {
        std::cout << "Correcting " << label << ": " << reason << "\n";
    }
}

int main()
{
    using Point = bg::model::d2::point_xy<double>;
    using Poly = bg::model::polygon<Point, false>;
    using MPoly = bg::model::multi_polygon<Poly>;

    std::vector vectorPolygons{
        from_wkt<Poly>(R"(POLYGON(( 30 10, 30 -0, 40 -0, 40 10, 30 10 )))"),
        from_wkt<Poly>(R"(POLYGON(( 30 20, 30 10, 40 10, 40 20, 30 20 )))"),
        from_wkt<Poly>(R"(POLYGON(( 30 30, 30 20, 40 20, 40 30, 30 30 )))"),
        from_wkt<Poly>(R"(POLYGON(( 20 20, 20 10, 30 10, 30 20, 20 20 )))"),
        from_wkt<Poly>(R"(POLYGON(( 20 30, 20 20, 30 20, 30 30, 20 30 )))"),
        from_wkt<Poly>(R"(POLYGON(( 10 30, 10 20, 20 20, 20 30, 10 30 )))"),
        from_wkt<Poly>(R"(POLYGON((  0 30,  0 20, 10 20, 10 30,  0 30 )))"),
    };

    MPoly union_poly; // will store union of polygons

    for (auto& p : vectorPolygons) {
        std::cout << bg::wkt(p) << ": " << bg::area(p) << "\n";
        check(p, "source poly");

        MPoly tmp;
        boost::geometry::union_(union_poly, p, tmp);
        union_poly.swap(tmp);

        //check(union_poly, "union");
        std::cout << "Union: " << bg::wkt(union_poly) << ": "
            << bg::area(union_poly) << "\n";
    }

    {
        std::ofstream svg("my_map.svg");
        bg::svg_mapper<Point> mapper(svg, 400, 400);

        mapper.add(union_poly);
        mapper.map(union_poly,
            "fill-opacity:0.1;fill:rgb(51,51,153);stroke:rgb(51,51,153);"
            "stroke-width:0");

        for (auto const& p : vectorPolygons) {
            mapper.add(p);
            mapper.map(
                p,
                "fill-opacity:0.3;fill:rgb(77,77,77);stroke:rgb(77,77,77);"
                "stroke-width:1;stroke-dasharray:1 2");
        }
    }
}

印刷

POLYGON((30 10,30 -0,40 -0,40 10,30 10)): 100
Union: MULTIPOLYGON(((30 10,30 -0,40 -0,40 10,30 10))): 100
POLYGON((30 20,30 10,40 10,40 20,30 20)): 100
Union: MULTIPOLYGON(((40 -0,40 20,30 20,30 10,30 -0,40 -0))): 200
POLYGON((30 30,30 20,40 20,40 30,30 30)): 100
Union: MULTIPOLYGON(((40 -0,40 30,30 30,30 20,30 -0,40 -0))): 300
POLYGON((20 20,20 10,30 10,30 20,20 20)): 100
Union: MULTIPOLYGON(((30 20,20 20,20 10,30 10,30 -0,40 -0,40 30,30 30,30 20))): 400
POLYGON((20 30,20 20,30 20,30 30,20 30)): 100
Union: MULTIPOLYGON(((40 30,20 30,20 20,20 10,30 10,30 -0,40 -0,40 30))): 500
POLYGON((10 30,10 20,20 20,20 30,10 30)): 100
Union: MULTIPOLYGON(((40 30,10 30,10 20,20 20,20 10,30 10,30 -0,40 -0,40 30))): 600
POLYGON((0 30,0 20,10 20,10 30,0 30)): 100
Union: MULTIPOLYGON(((40 30,0 30,0 20,10 20,20 20,20 10,30 10,30 -0,40 -0,40 30))): 700

概括

故事的寓意:始终检查您的输入数据是否有效。

另外,请注意,这些都没有“旋转”输出。输出只是未定义,而不是您想要的(它更类似于您正在寻找的形状的“负补码”,但这实际上是偶然的,结果是未指定的,因为输入违反了先决条件)。


于 2022-01-11T15:32:23.920 回答