我正在尝试使用Boost确定两个3d线串之间的交点,但是在某些情况下,我没有得到预期的结果。

根据我的理解[1],Boost应该使用 map 几何计算交点-也就是说,不考虑Z坐标。这是我追求的功能。

但是,我的测试表明,如果一个线串始终在另一个线串之上(下面的代码 list 中的情况1),那么我没有任何交集。

但是,如果第二条线与包含第一条线的平面相交-情况2-即使两个线在3d空间中不相交,也会找到相交处。

我的理解错了吗?还是有办法使案例1发挥作用?

我的解决方法是确保第一个线串始终与第二个线串交叉……但是似乎很不客气。

谢谢

#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;
}

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

引用文献:

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

最佳答案

链接的答案仅说明

  • Boost Geometry area支持工具尺寸大于2¹
  • OGM标准允许一致的实现在 map 几何中工作,尽管它们可以实现完整的3d几何,只要它与另一个标准一致即可。

  • 关于intersection,我找不到任何不同的地方。令我惊讶的是,文档并未明确警告未指明的行为。

    但是,似乎获得map-geo行为的唯一方法是手动映射:

    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";
        }
    }
    

    版画
    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))
    

    ¹当时甚至都没有检查这种情况是否发生了变化

    09-30 23:25