简体   繁体   English

使用 Boost 的两个 3d 线串的地图几何交集

[英]Map-geometry intersection of two 3d linestrings using Boost

I'm trying to determine the point of intersection between two 3d linestring using Boost, but in certain cases I'm not getting the expected result.我正在尝试使用 Boost 确定两个 3d 线串之间的交点,但在某些情况下,我没有得到预期的结果。

From my understanding [1], Boost should be calculating the intersection using Map geometry - that is, the Z coordinate is not considered.根据我的理解 [1],Boost 应该使用Map 几何来计算交点 - 即不考虑 Z 坐标。 This is the functionality I'm after.这是我追求的功能。

However, my testing shows if one linestring is always above the other (case 1 in the code listing below), then I get no intersections.但是,我的测试显示如果一个线串总是在另一个线串之上(下面代码清单中的案例 1),那么我没有得到任何交叉点。

But, if the second line crosses the plane containing the first line - case 2 - then an intersection is found - even though the two lines don't intersect in 3d space.但是,如果第二条线穿过包含第一条线的平面 - 案例 2 - 则找到一个交点 - 即使两条线在 3d 空间中不相交。

Is my understanding wrong?我的理解错了吗? Or, is there a way to make case 1 work?或者,有没有办法让案例 1 工作?

My workaround has been to ensure the first linestring will always cross the plane of the second... But it seems hacky.我的解决方法是确保第一个线串始终穿过第二个线串的平面……但这似乎很笨拙。

Thanks谢谢

#include <iostream>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/algorithms/intersection.hpp>

namespace bg = boost::geometry;

int main()
{
    typedef bg::model::point<double, 3, bg::cs::cartesian> point_t;
    typedef bg::model::linestring<point_t> linestring_t;

    linestring_t ls1{{0, 0, 1}, {1, 1, 1}};
    linestring_t ls2{{0, 1, 0}, {1, 0, 0}};
    linestring_t ls3{{0, 1, 0}, {1, 0, 1}};

    std::vector<point_t> intersections;

    bg::intersection(ls1, ls2, intersections);


    std::cout << "Case 1: Intersection between l1 and l2? " << (intersections.size() > 0 ? "Yes" : "No") << std::endl;

    bg::intersection(ls1, ls3, intersections);
    std::cout << "Case 2: Intersection between l1 and l3? " << (intersections.size() > 0 ? "Yes" : "No") << std::endl;


    return 0;
}

output: output:

Case 1: Intersection between l1 and l2? No
Case 2: Intersection between l1 and l3? Yes

References:参考:

[1] "How to intersection to 3D polygons by Boost C++ library?", https://stackoverflow.com/a/49012544/338230 [1] “如何通过 Boost C++ 库与 3D 多边形相交?”, https://stackoverflow.com/a/49012544/

The linked answer merely states that链接的答案仅表明

  • Boost Geometry area did support implement dimensions>2¹ Boost Geometry area确实支持实现尺寸>2¹
  • The OGM standard allows conforming implementations to work in map geometry, although they can implement full 3d geometry, as long as it is consistent with another standard. OGM 标准允许一致的实现在 map 几何结构中工作,尽管它们可以实现完整的 3d 几何结构,只要它与另一个标准一致。

I can't find anything different with regards to intersection today.我今天找不到关于intersection的任何不同之处。 It is rather surprising to me that the documentation doesn't clearly warn against unspecified behaviour.令我惊讶的是,文档没有明确警告未指明的行为。

However, it would appear that the only way to get map-geo behavior is by manually mapping:但是,似乎获得地图地理行为的唯一方法是手动映射:

Live On Coliru住在科利鲁

#include <iostream>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/geometries/multi_point.hpp>
#include <boost/geometry/algorithms/for_each.hpp>

namespace bg = boost::geometry;
static inline constexpr auto io = [](auto& g) { return bg::dsv(g); }; // switch to bg::wkt easily
using point_t      = bg::model::point<double, 3, bg::cs::cartesian>;
using points_t     = bg::model::multi_point<point_t>;
using linestring_t = bg::model::linestring<point_t>;

struct ZeroZ {
    inline void operator()(point_t& p)          const  { p.set<2>(0);                  } 
    template <typename G> void operator()(G& g) const  { bg::for_each_point(g, *this); } 
} static inline constexpr zeroz{};

int main() {
    std::cout << std::fixed << std::setprecision(2);

    linestring_t const lss[] = {
        {{0, 0, 1}, {1, 1, 1}},
        {{0, 1, 0}, {1, 0, 0}},
        {{0, 1, 0}, {1, 0, 1}},
    };

    for (auto a : lss) for (auto b : lss) {
        points_t c, d;
        bg::intersection(a, b, c);

        std::cout << "Normal:  " << io(a) << " with " << io(b) << " ->" << io(c) << "\n";
        zeroz(a);
        zeroz(b);

        bg::intersection(a, b, d);
        if (!bg::equals(c, d))
            std::cout << " -- but: " << io(a) << " with " << io(b) << " ->" << io(d) << "\n";
    }
}

Prints印刷

Normal:  ((0.00, 0.00, 1.00), (1.00, 1.00, 1.00)) with ((0.00, 0.00, 1.00), (1.00, 1.00, 1.00)) ->((0.00, 0.00, 1.00), (1.00, 1.00, 1.00))
 -- but: ((0.00, 0.00, 0.00), (1.00, 1.00, 0.00)) with ((0.00, 0.00, 0.00), (1.00, 1.00, 0.00)) ->((0.00, 0.00, 0.00), (1.00, 1.00, 0.00))
Normal:  ((0.00, 0.00, 0.00), (1.00, 1.00, 0.00)) with ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) ->((0.50, 0.50, 0.00))
Normal:  ((0.00, 0.00, 0.00), (1.00, 1.00, 0.00)) with ((0.00, 1.00, 0.00), (1.00, 0.00, 1.00)) ->((0.50, 0.50, 0.00))
Normal:  ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) with ((0.00, 0.00, 1.00), (1.00, 1.00, 1.00)) ->()
 -- but: ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) with ((0.00, 0.00, 0.00), (1.00, 1.00, 0.00)) ->((0.50, 0.50, 0.00))
Normal:  ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) with ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) ->((0.00, 1.00, 0.00), (1.00, 0.00, 0.00))
Normal:  ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) with ((0.00, 1.00, 0.00), (1.00, 0.00, 1.00)) ->((0.00, 1.00, 0.00), (1.00, 0.00, 0.00))
Normal:  ((0.00, 1.00, 0.00), (1.00, 0.00, 1.00)) with ((0.00, 0.00, 1.00), (1.00, 1.00, 1.00)) ->((0.50, 0.50, 0.00))
Normal:  ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) with ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) ->((0.00, 1.00, 0.00), (1.00, 0.00, 0.00))
Normal:  ((0.00, 1.00, 0.00), (1.00, 0.00, 0.00)) with ((0.00, 1.00, 0.00), (1.00, 0.00, 1.00)) ->((0.00, 1.00, 0.00), (1.00, 0.00, 0.00))

¹ at the time, not even checked whether that changed ¹当时,甚至没有检查是否改变了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM