efficient way to handle 2d line segments

后端 未结 3 1461
闹比i
闹比i 2021-02-04 14:49

I am having huge set of 2D line segments. So, I know; Line number, Begin (X,Y,Z) and End (x,Y,Z) of each line segment. I want to get proximity line segments for a g

相关标签:
3条回答
  • 2021-02-04 14:52

    Theoretically searching for the nearest Segments should be possible using any kind of spatial index or space partitioning data structure. Most often the interface of such spatial index allows to store Boxes (AABBs) or Points so in these cases you'd be forced to store bounding Boxes of Segments and then after querying for the closest Boxes check again the corresponding Segments. However it's possible to index Segments directly. E.g. in case of kd-tree it would be a version containing internal nodes defining splitting planes and leafs storing segments.

    Boost.Geometry R-tree supports Segments in Boost version 1.56.0 and above. Below is the example for 2d segments using this spatial index implementation:

    // Required headers
    #include <iostream>
    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/point.hpp>
    #include <boost/geometry/geometries/segment.hpp>
    #include <boost/geometry/index/rtree.hpp>
    
    // Convenient namespaces
    namespace bg = boost::geometry;
    namespace bgm = boost::geometry::model;
    namespace bgi = boost::geometry::index;
    
    // Convenient types
    typedef bgm::point<double, 2, bg::cs::cartesian> point;
    typedef bgm::segment<point> segment;
    typedef std::pair<segment, size_t> value;
    typedef bgi::rtree<value, bgi::rstar<16> > rtree;
    
    // Function object needed to filter the same segment in query()
    // Note that in C++11 you could pass a lambda expression instead
    struct different_id
    {
        different_id(size_t i) : id(i) {}
        bool operator()(value const& v) const { return v.second != id; }
        size_t id;
    };
    
    int main()
    {
        // The container for pairs of segments and IDs
        std::vector<value> segments;
        // Fill the container
        for ( size_t i = 0 ; i < 10 ; ++i )
        {
            // Example segment
            segment seg(point(i, i), point(i+1, i+1));
            segments.push_back(std::make_pair(seg, i));
        }
    
        // Create the rtree
        rtree rt(segments.begin(), segments.end());
        // The number of closest segments
        size_t k = 3;
    
        // The container for results
        std::vector< std::vector<value> > closest(segments.size());
    
        for ( size_t i = 0 ; i < segments.size() ; ++i )
        {
            // Find k segments nearest to the i-th segment not including i-th segment
            rt.query(bgi::nearest(segments[i].first, k) && bgi::satisfies(different_id(i)),
                     std::back_inserter(closest[i]));
        }
    
        // Print the results
        for ( size_t i = 0 ; i < closest.size() ; ++i )
        {
            std::cout << "Segments closest to the segment " << i << " are:" << std::endl;
            for ( size_t j = 0 ; j < closest[i].size() ; ++j )
                std::cout << closest[i][j].second << ' ';
            std::cout << std::endl;
        }
    }
    

    In case you needed ALL of the Segments that are closer than some threshold you could use iterative queries (example).

    0 讨论(0)
  • 2021-02-04 15:08

    Build a segment Voronoi diagram, then take proximity candidates from neighbouring cells.

    0 讨论(0)
  • 2021-02-04 15:15

    Yes, R-trees can do this. They are designed for arbitrary objects with spatial extend, not limited to point data. Actually some of the earliest examples used polygons.

    Have you tried using them?

    0 讨论(0)
提交回复
热议问题