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
ReadGeneralization.cpp
#include "SchematLib/IO/ReadGeneralization.h"
namespace SchematLib::IO {
    std::string_view ReadGeneralization::strip(const std::string& string)
    {
        if (string.empty()) return string;
        std::size_t start = 0;
        std::size_t end = string.size() - 1;
        for (; start < string.size(); ++start)
        {
            if (!std::isspace(string[start])) break;
        }
        if (start == string.size()) return "";
        // Check end condition
        for (; end >= start; --end)
        {
            if (!std::isspace(string[end])) break;
        }
        return std::string_view(string.data() + start, (end - start) + 1);
    }

    bool ReadGeneralization::startsWith(const std::string& str, char c)
    {
        return !str.empty() && str[0] == c;
    }

    bool ReadGeneralization::startsWith(const std::string& str, const std::string& needle)
    {
        if (str.size() < needle.size()) return false;
        for (std::size_t i = 0; i < needle.size(); ++i)
        {
            if (str[i] != needle[i])return false;
        }
        return true;
    }

    void ReadGeneralization::operator()(const std::filesystem::path& generalizationFile,
                                        Models::UndirectedEmbeddedGraph& graph)
    {
        namespace fs = std::filesystem;
        if (!fs::exists(generalizationFile))
        {
            throw std::runtime_error("Generalization path does not exist");
        }
        // TODO: make this safe for other graphs at some point

        std::ifstream stream(generalizationFile.string());
        std::string line;
        ParsingState state = ParsingState::None;
        std::size_t expectedEdges = 0;
        std::size_t expectedVertices = 0;
        std::size_t currentVertex = 0;
        std::size_t nextEdgeId = 0;
        std::size_t maxVertId = 0;

        while (std::getline(stream, line))
        {
            // Ignore empty lines.
            if (line.empty()) continue;

            auto view = strip(line);
            std::string strippedLine(view);
            std::stringstream lineStream(strippedLine);

            if (startsWith(strippedLine, '#'))
            {
                if (state == ParsingState::None)
                {
                    char c;
                    lineStream >> c;
                    lineStream >> expectedVertices;
                    state = ParsingState::Vertices;
                    graph = Models::UndirectedEmbeddedGraph(expectedVertices);
                    graph.m_use_canonical_edges_ids = false;
                }
                else if (state == ParsingState::Vertices)
                {
                    state = ParsingState::Edges;
                    char c;
                    lineStream >> c;
                    lineStream >> expectedEdges;
                }
                else
                {
                    throw std::runtime_error("Unrecognized '#' line in input");
                }
                continue;
            }
            // Data
            if (state == ParsingState::Vertices)
            {
                Models::NT x, y;
                std::size_t id;
                lineStream >> x >> y >> id;
                boost::put(GCpp::DS::vertex_location_t{}, graph, currentVertex, Models::Point(x, y));

                if (lineStream.fail())
                {
                    boost::put(GCpp::DS::vertex_id_t{}, graph, currentVertex, currentVertex);
                    maxVertId = std::max(maxVertId, currentVertex);
                }
                else
                {
                    boost::put(GCpp::DS::vertex_id_t{}, graph, currentVertex, id);
                    maxVertId = std::max(maxVertId, id);
                }
                ++currentVertex;
            }
            else if (state == ParsingState::Edges)
            {
                std::size_t src, target, eId;
                lineStream >> src >> target >> eId;
                auto result = GCpp::DS::safe_add_edge(src, target, graph);
                if(!result.second)
                {
                    throw std::runtime_error("Did not add edge?");
                }
                assert(result.second);
                boost::put(GCpp::DS::edge_id_t{}, graph, result.first, eId);
                nextEdgeId = std::max(nextEdgeId, eId + 1);
            }
        }
        boost::get_property(graph, GCpp::DS::next_vertex_id_t{}) = maxVertId+1;
        boost::get_property(graph, GCpp::DS::next_edge_id_t{}) = nextEdgeId;
    }

    void WriteGeneralization::operator()(const std::filesystem::path& generalizationFile,
        const Models::UndirectedEmbeddedGraph& graph)
    {
        std::ofstream out(generalizationFile.string());
        if (!out.is_open()) throw std::runtime_error("Could not open output file " + generalizationFile.string());
        this->operator()(out, graph);
    }

    void WriteGeneralization::operator()(std::ostream& output, const Models::UndirectedEmbeddedGraph& graph)
    {
        namespace it = GCpp::Helpers::Iterators;
        output << "# " << boost::num_vertices(graph) << '\n';
        for(auto v : it::range(boost::vertices(graph)))
        {
            const auto loc = GCpp::DS::get_vertex_location(v, graph);
            output << loc.x() << " " << loc.y() << GCpp::DS::getVertexId(graph, v) << '\n';
        }
        for(auto e: it::range(boost::edges(graph)))
        {
            output << boost::source(e, graph) << " " << boost::target(e, graph) << " " << GCpp::DS::getEdgeId(graph, e) << '\n';
        }
    }

    void WriteGeneralization::operator()(const std::filesystem::path& generalizationFile,
        const MapSimplification::FaceMergeTraits::Arr& graph)
    {
        std::ofstream stream(generalizationFile.string());
        this->operator()(stream, graph);
    }

    void WriteGeneralization::operator()(std::ostream& output, const MapSimplification::FaceMergeTraits::Arr& graph)
    {
        namespace it = GCpp::Helpers::Iterators;
        output << "# " << graph.number_of_vertices() << '\n';
        for (auto v : graph.vertex_handles())
        {
            const auto loc = v->point();
            output << CGAL::to_double(loc.x()) << " " << CGAL::to_double(loc.y()) << v->data().id << '\n';
        }
        output << "# " << graph.number_of_edges();
        for (auto e : graph.edge_handles())
        {
            output << e->source()->data().id << " " << e->target()->data().id << " " << e->data().id.value() << '\n';
        }
        output << "# " << graph.number_of_faces();
        for (MapSimplification::FaceMergeTraits::Arr::Face_const_handle f : graph.face_handles())
        {
            if (f->is_unbounded() ) continue;
            output << f->data().id.value() << " ";
            std::vector<std::size_t> edgeIds;
            auto circ = f->outer_ccb();
            MapSimplification::FaceMergeTraits::for_each_ccb_edge(f, [&edgeIds](auto edge, auto& cmd)
            {
                edgeIds.push_back(edge->data().id.value());
            });
            output << edgeIds.size();
            for (auto e : edgeIds)
            {
                output << ' ' << e;
            }
        }
    }
}
back to top