From 06fc977c560d9810391ea720b58e9e360a9513a0 Mon Sep 17 00:00:00 2001 From: Grufoony Date: Thu, 14 Nov 2024 10:36:57 +0100 Subject: [PATCH 1/3] Add `exportCoordinates` function to Graph class --- src/dsm/headers/Graph.cpp | 50 ++++++++++++++++++++++++++++++++++++--- src/dsm/headers/Graph.hpp | 5 +++- test/Test_graph.cpp | 34 +++++++++++++++++++------- 3 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/dsm/headers/Graph.cpp b/src/dsm/headers/Graph.cpp index f3d18e4a0..bbebdcb4c 100644 --- a/src/dsm/headers/Graph.cpp +++ b/src/dsm/headers/Graph.cpp @@ -220,9 +220,7 @@ namespace dsm { if (fileExt == "dsm") { // first input number is the number of nodes std::ifstream file{fileName}; - if (!file.is_open()) { - throw std::invalid_argument(buildLog("Cannot find file: " + fileName)); - } + assert((void("Coordinates file not found."), file.is_open())); Size n; file >> n; if (n < m_nodes.size()) { @@ -236,6 +234,33 @@ namespace dsm { m_nodes[i]->setCoords(std::make_pair(lat, lon)); } } + } else if (fileExt == "csv") { + std::ifstream ifs{fileName}; + assert((void("Coordinates file not found."), ifs.is_open())); + // Check if the first line is nodeId;lat;lon + std::string line; + std::getline(ifs, line); + assert((void("Invalid file format."), line == "nodeId;lat;lon")); + double dLat, dLon; + while (!ifs.eof()) { + std::getline(ifs, line); + if (line.empty()) { + continue; + } + std::istringstream iss{line}; + std::string nodeId, lat, lon; + std::getline(iss, nodeId, ';'); + std::getline(iss, lat, ';'); + std::getline(iss, lon, '\n'); + dLat = lat == "Nan" ? 0. : std::stod(lat); + dLon = lon == "Nan" ? 0. : std::stod(lon); + if (m_nodes.contains(std::stoul(nodeId))) { + m_nodes[std::stoul(nodeId)]->setCoords(std::make_pair(dLat, dLon)); + } else { + std::cerr << std::format("WARNING: Node with id {} not found.", nodeId) + << std::endl; + } + } } else { throw std::invalid_argument(buildLog("File extension not supported.")); } @@ -361,6 +386,25 @@ namespace dsm { } } + void Graph::exportCoordinates(std::string const& path) { + // assert that path ends with ".csv" + assert((void("Only csv export is supported."), + path.substr(path.find_last_of(".")) == ".csv")); + std::ofstream file{path}; + // Column names + file << "nodeId;lat;lon\n"; + for (const auto& [id, node] : m_nodes) { + file << id << ';'; + if (node->coords().has_value()) { + file << node->coords().value().first << ';' << node->coords().value().second; + } else { + file << "Nan;Nan"; + } + file << '\n'; + } + file.close(); + } + void Graph::addNode(std::unique_ptr node) { m_nodes.emplace(std::make_pair(node->id(), std::move(node))); } diff --git a/src/dsm/headers/Graph.hpp b/src/dsm/headers/Graph.hpp index 1f2cbaff6..02c77ceaa 100644 --- a/src/dsm/headers/Graph.hpp +++ b/src/dsm/headers/Graph.hpp @@ -136,10 +136,13 @@ namespace dsm { void importOSMEdges(const std::string& fileName); /// @brief Export the graph's adjacency matrix to a file - /// @param path The path to the file to export the adjacency matrix to. + /// @param path The path to the file to export the adjacency matrix to (default: ./matrix.dsm) /// @param isAdj A boolean value indicating if the file contains the adjacency matrix or the distance matrix. /// @throws std::invalid_argument if the file is not found or invalid void exportMatrix(std::string path = "./matrix.dsm", bool isAdj = true); + /// @brief Export the nodes' coordinates to a file + /// @param path The path to the file to export the nodes' coordinates to (default: ./nodes.dsm) + void exportCoordinates(std::string const& path = "./coordinates.csv"); /// @brief Add a node to the graph /// @param node A std::unique_ptr to the node to add diff --git a/test/Test_graph.cpp b/test/Test_graph.cpp index f6234a277..598b8e014 100644 --- a/test/Test_graph.cpp +++ b/test/Test_graph.cpp @@ -128,15 +128,31 @@ TEST_CASE("Graph") { CHECK(graph2.nodeSet().size() == 3); CHECK(graph2.streetSet().size() == 4); } - SUBCASE("importCoordinates") { - Graph graph{}; - CHECK_THROWS(graph.importCoordinates("./data/coords.txt")); - graph.importMatrix("./data/matrix.dsm"); - graph.importCoordinates("./data/coords.dsm"); - const auto& nodes = graph.nodeSet(); - CHECK_EQ(nodes.at(0)->coords(), std::make_pair(0., 0.)); - CHECK_EQ(nodes.at(1)->coords(), std::make_pair(1., 0.)); - CHECK_EQ(nodes.at(2)->coords(), std::make_pair(2., 0.)); + SUBCASE("Coordinates import/export") { + GIVEN("A Graph object with the adj matrix imported") { + Graph graph{}; + graph.importMatrix("./data/matrix.dsm"); + auto const& nodes = graph.nodeSet(); + WHEN("We import the coordinates in dsm format") { + graph.importCoordinates("./data/coords.dsm"); + THEN("The coordinates are correctly imported") { + CHECK_EQ(nodes.at(0)->coords(), std::make_pair(0., 0.)); + CHECK_EQ(nodes.at(1)->coords(), std::make_pair(1., 0.)); + CHECK_EQ(nodes.at(2)->coords(), std::make_pair(2., 0.)); + } + THEN("We are able to save coordinates in csv format") { + graph.exportCoordinates("./data/coordinates.csv"); + } + } + WHEN("We import the coordinates in csv format") { + graph.importCoordinates("./data/coordinates.csv"); + THEN("The coordinates are correctly imported") { + CHECK_EQ(nodes.at(0)->coords(), std::make_pair(0., 0.)); + CHECK_EQ(nodes.at(1)->coords(), std::make_pair(1., 0.)); + CHECK_EQ(nodes.at(2)->coords(), std::make_pair(2., 0.)); + } + } + } } SUBCASE("importMatrix - raw matrix") { Graph graph{}; From 3fca640c9b43f90d17caa10ec31e605bd3c0fe0d Mon Sep 17 00:00:00 2001 From: Grufoony Date: Thu, 14 Nov 2024 10:37:24 +0100 Subject: [PATCH 2/3] Add csv file for tests --- test/data/coordinates.csv | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 test/data/coordinates.csv diff --git a/test/data/coordinates.csv b/test/data/coordinates.csv new file mode 100644 index 000000000..77ba290a3 --- /dev/null +++ b/test/data/coordinates.csv @@ -0,0 +1,4 @@ +nodeId;lat;lon +1;1;0 +0;0;0 +2;2;0 From 97d236ab2d4f509f46f458d80516e12124d06500 Mon Sep 17 00:00:00 2001 From: Grufoony Date: Thu, 14 Nov 2024 10:41:29 +0100 Subject: [PATCH 3/3] Update version --- src/dsm/dsm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsm/dsm.hpp b/src/dsm/dsm.hpp index 72d902545..bb7d9c61d 100644 --- a/src/dsm/dsm.hpp +++ b/src/dsm/dsm.hpp @@ -6,7 +6,7 @@ static constexpr uint8_t DSM_VERSION_MAJOR = 2; static constexpr uint8_t DSM_VERSION_MINOR = 1; -static constexpr uint8_t DSM_VERSION_PATCH = 4; +static constexpr uint8_t DSM_VERSION_PATCH = 5; #define DSM_VERSION \ std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH)