https://github.com/tue-alga/CoordinatedSchematization
Raw File
Tip revision: 9ffc292c946498d56f7938a86628adba534a9085 authored by TUE\bacusters on 01 July 2021, 09:20:10 UTC
Add base schematization library
Tip revision: 9ffc292
MapTrajectoriesToFaces.h
#ifndef SCHEMATLIB_TRAJECTORYSCHEMATIZAATION_H
#define SCHEMATLIB_TRAJECTORYSCHEMATIZAATION_H
#include "OffroadTraits.h"
#include "SchematLib/MapSimplification/FaceMergeTraits.h"
#include "SchematLib/MapSimplification/PathMapper.h"

namespace SchematLib::TrajectorySchematization
{
    template<typename EmbeddedGraph>
    class MapTrajectoriesToFaces
    {
    public:
        // By IDs.
        using FaceToTrajectoriesMap = std::map<std::size_t, std::set<std::size_t>>;
        using Traits = MapSimplification::FaceMergeTraits;
        using OffroadTraits = OffroadTraits<EmbeddedGraph>;
        using Trajectory = typename OffroadTraits::OffroadTrajectory; // List of edge IDs.

        struct FaceTrajectories
        {
            using VertexId = std::size_t;
            using TrajectoryId = std::size_t;
            std::vector<std::pair<VertexId, VertexId>> through;
            std::vector<VertexId> enter;
            std::vector<VertexId> exit;
            std::vector<TrajectoryId> inside;
        };

    private:
        struct ArrangementMapping
        {
            std::map<std::size_t, Traits::HE_handle> edgeIdToEdge;
            std::map<std::size_t, Traits::Vertex_handle> vertexIdToVertex;

            void compute(const Traits::Arr& arrangement)
            {
                for(auto he : arrangement.halfedge_handles())
                {
                    if(he->data().id.has_value())
                    {
                        edgeIdToEdge[he->data().id.value()] = he;
                    }
                }
                for(auto v: arrangement.vertex_handles())
                {
                    vertexIdToVertex[v->data().id] = v;
                }
            }
        };

        template<typename Observer>
        void handleTrajectory(const EmbeddedGraph& sourceGraph, const CGAL::Arr_trapezoid_ric_point_location<Traits::Arr>& pointLocation,
            const Trajectory& trajectory, std::size_t trajectoryNum, const Observer& observer,
            std::map<std::size_t, FaceTrajectories>& toFaceMapping)
        {
            if (trajectory.empty()) return;

            std::map<std::size_t, typename EmbeddedGraph::edge_descriptor> edgeIdtoEdge;
            GCpp::DS::computeEdgeIdToEdgeMap(sourceGraph, edgeIdtoEdge);

            // Find face that contains most of the trajectory.
            std::vector<Traits::Point_2> points;
            Traits traits;
            for(std::size_t i = 0; i < trajectory.size()+1; ++i)
            {
                typename EmbeddedGraph::vertex_descriptor v;
                if(i == 0)
                {
                    v = boost::source(edgeIdtoEdge[trajectory.at(0)], sourceGraph);
                }
                else
                {
                    v= boost::target(edgeIdtoEdge[trajectory.at(i-1)], sourceGraph);
                }
                points.push_back(traits.gcppToCgalPosition(GCpp::DS::get_vertex_location(v,sourceGraph)));
            }
            // Determine most hit face
            std::map<std::size_t, std::size_t> countPerFace;
            std::size_t maxCountFid = 0;
            std::size_t maxVal = 0;
            for(const auto& p : points)
            {
                auto result= pointLocation.locate(p);
                const Traits::Arr::Face_const_handle* f;
                if ((f = boost::get<Traits::Arr::Face_const_handle>(&result)))
                {
                    if ((*f)->is_unbounded()) continue;
                    if((*f)->data().id.has_value())
                    {
                        const auto fId = (*f)->data().id.value();
                        if (countPerFace.find(fId) == countPerFace.end()) countPerFace[fId] = 0;
                        countPerFace[fId]++;
                        if(countPerFace[fId] > maxVal)
                        {
                            maxVal = countPerFace[fId];
                            maxCountFid = fId;
                        }
                    }
                }
            }
            // TODO: may mean assigned to outer face, or we somehow only hit vertices.
            if (maxVal == 0) return;

            MapSimplification::PathMapper mapper(observer);
            // Determine type
            const auto& data = trajectory.trajectoryData();
            if(data.startOnBoundary)
            {
                if(data.endOnBoundary)
                {
                    // Map vertices
                    auto startResult = mapper.decodeVertex(data.startVId);
                    if (std::holds_alternative<MapSimplification::EdgeTrackingObserver::Deleted>(startResult)) throw std::runtime_error("Cannot delete vertices!");
                    auto startV = std::get < MapSimplification::EdgeTrackingObserver::Vertex>(startResult).id;
                    auto endV = std::get < MapSimplification::EdgeTrackingObserver::Vertex>(mapper.decodeVertex(data.endVId)).id;

                    toFaceMapping[maxCountFid].through.push_back(std::make_pair(startV, endV));
                }
                else
                {
                    auto vert = std::get < MapSimplification::EdgeTrackingObserver::Vertex>(mapper.decodeVertex(data.startVId)).id;
                    toFaceMapping[maxCountFid].enter.push_back(vert);
                }
            }
            else
            {
                if(data.endOnBoundary)
                {
                    auto vert = std::get < MapSimplification::EdgeTrackingObserver::Vertex>(mapper.decodeVertex(data.endVId)).id;
                    toFaceMapping[maxCountFid].exit.push_back(vert);
                }
                else
                {
                    toFaceMapping[maxCountFid].inside.push_back(trajectoryNum);
                }
            }
        }
    public:
        template<typename Observer>
        void operator()(const MapSimplification::FaceMergeTraits::Arr& arrangement,
                const EmbeddedGraph& sourceGraph,
                const std::vector<typename OffroadTraits::OffroadTrajectory>& offroadTrajectories,
                const Observer& observer,
                        std::map<std::size_t, FaceTrajectories>& toFaceMapping)
        {
            // Map trajectories to a face by majority vote for now.
            // Find out their original enter/exit vertices or through vertices.

            CGAL::Arr_trapezoid_ric_point_location<Traits::Arr> pointLocation(arrangement);

            // Compute mapping for edges
            std::map<std::size_t, Traits::HE_handle> edgeIdToEdge;
            for(auto he : arrangement.halfedge_handles())
            {
                if (!he->data().id.has_value()) throw std::runtime_error("Missing ID on edge");
                edgeIdToEdge[he->data().id.value()] = he;
            }
            // Potentially compute vertices for trajectory to determine directionality.
            // TODO
            std::size_t trajectoryNum = 0;
            for(const auto& traj: offroadTrajectories)
            {
                handleTrajectory(sourceGraph, pointLocation, traj, trajectoryNum, observer, toFaceMapping);
                ++trajectoryNum;
            }
        }
    };
}
#endif
back to top