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

StackOverflow https://stackoverflow.com/questions/18318651

Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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, ... ).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top