Find all linesegments=edges within a certain distance to a point in a graph, how to combine boost-graph with boost-geometry?

谁都会走 提交于 2019-12-12 04:35:07

问题


I have a set of user paths (2 dim) in a game setup that are modelled as a set of lines (arcs) and waypoints = vertices. The whole set of paths can be seen as a graph where the edges are line segments that have additional properties like length, probability, etc.

Now I have to identify the set of (straight) line segments = edges within a certain distance to the user's current position in order to find the user's position in the graph.

How to implement this as simply as possible without reinventing the wheel? How to implement the search efficiently?

I thought of using boost-graph for handling the graph and to combine it with boost-geometry. E.g. see TrajGraph which uses bundled properties in boost-graph:

struct Tvertex
{
    float x, y; //vertex=waypoint position
};

struct Tarc_segment
{
    float len, curvature, prob; //line segment=edge properties
};

typedef adjacency_list<vecS, vecS, directedS, Tvertex, Tarc_segment> TrajGraph;

Now in order to store the line segment as an edge property one could add boost geometry's model::linestring and use boost-geometry's nearest neighbour query to find the line segments. But afaik boost-geometry does not allow to attach properties to linestrings as boost-graph does. Hence how to get the edge(s) from the linestring(s)?

A simple brute-force solution might be to traverse the whole edge-list of the graph and calculate the distance to each line segment. See here and here for how to calculate the distance to a straight line segment.


回答1:


It is certainly possible to attach properties to linestrings in Boost.Geometry, actually Boost.Geometry is made for doing such things. You can just derive from boost::geometry::model::linestring, or implement any other range-based structure (e.g. std::vector) and register that as a linestring. See the c03 example.

For the relation with Boost.Graph, see one of the examples in Boost.Geometry: 07_a or 07_b where a similar thing is done. What is done there is storing a Boost.Geometry linestring into the Boost.Graph edge (with a property), together with other properties, so that is another way of doing this.




回答2:


For lines I would use the Hesse Normal Form for each segment calculate the distance and select or discard that line.

The Hesse Normal Form

/// Hesse Normal Form
/// \NOTE: Since negative distances from the origin are accepted, it is almost
///        a Hesse Normal Form, only)
template<class ScalarType>
class HesseNormalForm2D
{
    public:
    typedef ScalarType Scalar;
    typedef Normal2D<Scalar> Normal;
    typedef Vector2D<Scalar> Vector;
    typedef Point2D<Scalar> Point;
    typedef Line2D<Scalar> Line;

    public:
    /// An invalid line initialized with NaN.
    static HesseNormalForm2D nan() { return HesseNormalForm2D(Normal::nan(), Scalar::nan()); }

    /// An undefined line.
    HesseNormalForm2D() {}

    /// A line defined by a normal and a distance form the origin.
    explicit HesseNormalForm2D(const Normal& n, const Scalar& d)
    :   m_n(n), m_d(d)
    {}

    /// The Hesse Normal Form of a line.
    /// ATTENTION The scalar value d of the line may be negative.
    explicit HesseNormalForm2D(const Point& p, const Vector& v) {
        m_n = -orthonormal(v);
        m_d = scalar_product(m_n, Vector(p));
    }

    /// The Hesse Normal Form of a line.
    /// ATTENTION The scalar value d of the line may be negative.
    explicit HesseNormalForm2D(const Point& p0, const Point& p1) {
        m_n = -orthonormal(p1 - p0);
        m_d = scalar_product(m_n, Vector(p0));
    }

    /// The Hesse Normal Form of a line.
    /// ATTENTION The scalar value d of the line may be negative.
    explicit HesseNormalForm2D(const Line&);

    /// The normal.
    const Normal& n() const { return m_n; }
    /// The normal.
    Normal& n() { return m_n; }
    /// The distance from the origin.
    const Scalar& d() const { return m_d; }
    /// The distance from the origin.
    Scalar& d() { return m_d; }

    /// The distance of a point to the line.
    /// \NOTE The point x on the line L with the smallest distance to p is:
    ///       x = p - L(p) * L.n()
    Scalar operator () (const Point& p) const {
        return scalar_product(Vector(p), n()) - d();
    }

    private:
    Normal m_n;
    Scalar m_d;
};

To generalize it you would have a different class considering the different attributes you need (Line, Arc, ... ).



来源:https://stackoverflow.com/questions/18318651/find-all-linesegments-edges-within-a-certain-distance-to-a-point-in-a-graph-how

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!