Boost几何返回相交和相交的不一致结果

问题描述

在我的应用程序中,我主要使用增强几何来执行交集 和差异计算。不幸的是,我注意到不一致 在结果中:

  • bg::相交和
  • bg::intersection

enter image description here

我要做的是:

  1. 计算多边形 1 和多边形 2(= 多边形 3)的交集。
  2. 从polygon1(= poly4)中移除(bg::difference)这个交点
  3. 生成的多边形 4 不应与多边形 2 有任何交集。
tasks = list(map(asyncio.create_task,coros))
try:
    results = await asyncio.gather(*tasks)
finally:
    # if there are unfinished tasks,that is because one of them
    # raised - cancel the rest
    for t in tasks:
        if not t.done():
            t.cancel()

奇怪的是 bg::intersects 返回 true 而 bg::intersection 返回一个空的交集。

有谁知道为什么会发生这种情况? (也许是准确性问题?)和 更有趣的是:我怎样才能避免这些问题?

我试图通过使用其他函数来避免“相交”,但结果没有帮助。请参阅 b2 和 b3 的计算。

PS:不幸的是,这个例子似乎会导致在 coliru 上崩溃。

解决方法

实际上 intersection 函数的返回值是未指定的:见

What does boost::geometry::intersection return

因此,您需要查看交叉点本身:

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/logic/tribool_io.hpp>

using boost::tribool;
using boost::indeterminate;

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

int main() {
    polygon_t a,b;

    bg::read_wkt("POLYGON(("
        "12227.0 4967.0000000000009,12238.0 4967.0000000000009,"
        "12238.0 4813.0000000000009,12227.0 4813.0000000000009,"
        "12227.0 4967.0000000000009))",a);
    bg::read_wkt("POLYGON(("
        "12254.0 4947.0,12219.0 4982.0,12219.0 5020.0,12254.0 5055.0,"
        "12261.0 5055.0,12263.0 5055.0,12283.0 5055.0,12283.0 4947.0,"
        "12263.0 4947.0,12261.0 4947.0,12254.0 4947.0))",b);

#define CHECK(expected,expr)                                                  \
    do {                                                                       \
        auto const& actual = (expr);                                           \
        auto ok = ((expected) == actual);                                      \
        if (ok == true) {                                                      \
            std::cout << "PASS";                                               \
        } else if (ok == false) {                                              \
            std::cout << "FAIL";                                               \
        } else {                                                               \
            std::cout << "?";                                                  \
        }                                                                      \
        std::cout << "\t" << #expr << " -> " << std::boolalpha << actual       \
                  << "\n";                                                     \
        if (!(ok == true))                                                               \
            std::cout << "  (expected value was " << (expected) << ")\n";      \
    } while (false)

    mpolygon_t ab_intersect;
    auto dump = [](auto label,auto& geo) {
        std::cout << label << " area " << bg::area(geo) << " " << bg::wkt(geo) << "\n";
    };

    CHECK(true,bg::intersection(a,b,ab_intersect));
    CHECK(1,ab_intersect.size());
    dump("a",a);
    dump("b",b);
    dump("ab_intersect",ab_intersect);

    mpolygon_t a_minus_b,b_minus_a;
    bg::difference(a,ab_intersect,a_minus_b);
    bg::difference(b,b_minus_a);
    CHECK(1,a_minus_b.size());
    CHECK(1,b_minus_a.size());
    dump("a_minus_b",a_minus_b);
    dump("b_minus_a",b_minus_a);

    auto checks = [dump](auto& reduced,auto& other) {
        CHECK(true,bg::intersects(reduced,other));

        mpolygon_t check;
        bg::intersection(reduced,other,check);

        CHECK(true,check.empty());
        dump("check",check);
    };

    std::cout << "-- reduced a vs b: -------\n";
    checks(a_minus_b,b);
    std::cout << "-- reduced b vs a: -------\n";
    checks(b_minus_a,a);
}

印刷品

PASS    bg::intersection(a,ab_intersect) -> true
PASS    ab_intersect.size() -> 1
a area 1694 POLYGON((12227 4967,12238 4967,12238 4813,12227 4813,12227 4967))
b area 5687 POLYGON((12254 4947,12219 4982,12219 5020,12254 5055,12261 5055,12263 5055,12283 5055,12283 4947,12263 4947,12261 4947,12254 4947))
ab_intersect area 8 MULTIPOLYGON(((12234 4967,12238 4963,12234 4967)))
PASS    a_minus_b.size() -> 1
PASS    b_minus_a.size() -> 1
a_minus_b area 1686 MULTIPOLYGON(((12234 4967,12227 4967,12234 4967)))
b_minus_a area 5679 MULTIPOLYGON(((12238 4963,12234 4967,12254 4947,12238 4963)))
-- reduced a vs b: -------
PASS    bg::intersects(reduced,other) -> true
PASS    check.empty() -> true
check area 0 MULTIPOLYGON()
-- reduced b vs a: -------
PASS    bg::intersects(reduced,other) -> true
PASS    check.empty() -> true
check area 0 MULTIPOLYGON()
,

我提到的行为不是错误而是完全正确的:

bg::intersection() 返回一个空多边形但是

如果我用线串作为输出参数调用它:

using linestring_t = bg::model::linestring<point_t>;
linestring_t int1;
bg::intersection(poly2,poly4,int1);
std::cout << "int1: " << bg::wkt(int1) << std::endl;

它有效。

TL;DR bg::intersects() 和 bg::intersection() 的用法和我的解释是错误的!

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...