Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example cpp boost #52

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions examples/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 2.6)

Project(dijkstra)

set(Boost_USE_MULTITHREADED ON)
FIND_PACKAGE(Boost 1.38 COMPONENTS program_options required)

INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${LINK_DIRECTORIES} ${Boost_LIBRARY_DIRS})

ADD_EXECUTABLE(dijkstra main.cpp)

set_target_properties(dijkstra PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)

129 changes: 129 additions & 0 deletions examples/cpp/io/ReadRG.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include <fstream>
#include <iostream>
#include <string>
#include <vector>


struct Node {
double lat, lon;

Node() {};
Node(double lat, double lon) : lat(lat), lon(lon) {}
};

struct Edge {
int s, t;
double weight;

Edge() {};
Edge(int s, int t, double weight) : s(s), t(t), weight(weight) {}
};

struct NodeEdges {
std::vector<Node> nodes;
std::vector<Edge> edges;
};

class ReadRG {
public:
static NodeEdges read_graph(std::string filename) {
std::fstream f(filename);

if (!f.is_open()) {
std::cout << "failed to open " << filename << std::endl;
return NodeEdges();
}

std::cout << "opened " << filename << std::endl;
if (!header_valid(f)) {
return NodeEdges();
}
skip_commented_lines(f);

int nmb_nodes{-1};
int nmb_edges{-1};
f >> nmb_nodes >> nmb_edges;

std::cout << "graph contains: " << nmb_nodes << " nodes and " << nmb_edges << " edges" << std::endl;

NodeEdges result;
result.nodes = read_nodes(f, nmb_nodes);
result.edges = read_edges(f, nmb_edges);
return result;
}

private:
static bool header_valid(std::fstream& f) {
const std::string expected_header = "# Road Graph File v.0.3";
std::string header;
std::getline(f, header);
if (header != expected_header) {
std::cout << "header mismatch! expected: " << expected_header << " read: " << header << std::endl;
return false;
}
std::cout << "header check passed!" << std::endl;
return true;
}

static void skip_commented_lines(std::fstream& f) {
std::string dummy;
while(f.peek() == '#') {
std::getline(f, dummy);
}
}

static std::vector<Node> read_nodes(std::fstream& f, const int nmb_nodes) {
std::cout << "reading nodes... " << std::flush;
std::vector<Node> nodes;
for (int i = 0; i < nmb_nodes; ++i) {
assert(!f.eof());
print_progress(i, nmb_nodes);
double x, y;
int index;
f >> index >> x >> y;
nodes.emplace_back(x, y);
}
std::cout << " done!" << std::endl;
return nodes;
}

static std::vector<Edge> read_edges(std::fstream& f, const int nmb_edges) {
std::cout << "reading edges... " << std::flush;
std::vector<Edge> edges;
for (int i = 0; i < nmb_edges; ++i) {
assert(!f.eof());
print_progress(i, nmb_edges);

int s, t;
double length;
std::string category;
int speed;
std::string forward, backward;

f >> s >> t >> length >> category >> speed >> forward >> backward;

const double time = (1.0/((double)speed * 1000.0 / 3600.0) * 100.0 * (double)length);
if (forward == "True") {
edges.emplace_back(s, t, time);
}
if (backward == "True") {
edges.emplace_back(t, s, time);
}
}
std::cout << " done!" << std::endl;
return edges;
}

static inline void print_progress(int i, int max) {
if (i == (int)(max * 0.25)) {
std::cout << "..25%" << std::flush;
} else if (i == (int)(max * 0.5)) {
std::cout << "\t ..50%" << std::flush;
} else if (i == (int)(max * 0.75)) {
std::cout << "\t ..75%" << std::flush;
} else if (i == (int)(max - 1)) {
std::cout << "\t ..100%" << std::flush;
}
}

};
121 changes: 121 additions & 0 deletions examples/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include <boost/config.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>

#include <boost/graph/graph_traits.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/adjacency_list.hpp>

#include "io/ReadRG.h"

struct SimpleNode {
double lat, lon;

SimpleNode() {}
SimpleNode(double lat, double lon) : lat(lat), lon(lon) {}
};

typedef boost::property<boost::edge_weight_t, double> EdgeWeightProperty;
typedef boost::adjacency_list < boost::listS, boost::vecS, boost::directedS,
SimpleNode, EdgeWeightProperty > Graph;
typedef boost::graph_traits < Graph >::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits < Graph >::edge_descriptor edge_descriptor;

typedef boost::graph_traits<Graph>::vertex_iterator vertex_iter;

Graph build_graph(const NodeEdges& nodeEdges) {
Graph graph;

std::vector<Graph::vertex_descriptor> nodes;
for (const Node& n: nodeEdges.nodes) {
Graph::vertex_descriptor vertex = boost::add_vertex(graph);
graph[vertex].lat = n.lat;
graph[vertex].lon = n.lon;
nodes.push_back(vertex);
}

for (const Edge& e: nodeEdges.edges) {
boost::add_edge(nodes[e.s], nodes[e.t], e.weight, graph);
}

return graph;
}

std::string line_string(double lat1, double lon1, double lat2, double lon2) {
std::ostringstream out;
out << std::setprecision(10);
out << "<Placemark>";
out << "<styleUrl>#linestyleExample</styleUrl>" << std::endl;
out << "<LineString><coordinates>" << std::endl;
out << lon1 << ", " << lat1 << ", 0." << std::endl;
out << lon2 << ", " << lat2 << ", 0." << std::endl;
out << "</coordinates></LineString></Placemark>";
return out.str();
}

std::string point_marker(double lat, double lon) {
std::ostringstream out;
out << std::setprecision(10);
out << "<Placemark><Point><coordinates>" << std::endl;
out << lon << ", " << lat << ", 0." << std::endl;
out << "</coordinates></Point></Placemark>" << std::endl;
return out.str();
}

static string hexColor(int val = 255, int min = 0, int max = 255) {
std::stringstream out;
out << "<Style id=\"linestyleExample\"><LineStyle>" << std::endl;
out << "<color>" << std::endl;
out << "f0000ff" << std::endl;
out << "</color>" << std::endl;
out << "<width>1</width>" << std::endl;
out << "</LineStyle></Style>" << std::endl;
return out.str();
}


void to_kml(const Graph& graph, const vertex_descriptor& start, const std::vector<vertex_descriptor>& parents, std::vector<int>& distances) {
const std::string filename = "out.kml";
std::ofstream f(filename);
const std::string header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><kml xmlns=\"http://earth.google.com/kml/2.0\"><Document>";
f << header << std::endl;

f << point_marker(graph[start].lat, graph[start].lon);
boost::graph_traits < Graph >::vertex_iterator vertexIterator, vend;
for (boost::tie(vertexIterator, vend) = boost::vertices(graph); vertexIterator != vend; ++vertexIterator) {
std::string middle = line_string(graph[*vertexIterator].lat, graph[*vertexIterator].lon, graph[parents[*vertexIterator]].lat, graph[parents[*vertexIterator]].lon);
std::cout << middle << std::endl;
f << middle << std::endl;
}
std::cout << std::endl;

const std::string footer = "</Document> </kml>";
f << footer << std::endl;
}

void dijkstra(Graph& graph, int id) {
std::vector<vertex_descriptor> parents(boost::num_vertices(graph));
std::vector<int> distances(boost::num_vertices(graph));

std::pair<vertex_iter, vertex_iter> vp = vertices(graph);
vertex_descriptor start = *(vp.first);
boost::dijkstra_shortest_paths(graph, start, boost::predecessor_map(&parents[0]).distance_map(&distances[0]));
to_kml(graph, start, parents, distances);
}

int main(int argc, char* argv[]) {
if (argc < 2) {
std::cout << "missing filename!" << std::endl;
std::cout << "./dijkstra <filename>" << std::endl;
return -1;
}

NodeEdges nodesAndEdges = ReadRG::read_graph("../../data/karlsruhe_small.pycgr");
Graph graph = build_graph(nodesAndEdges);
dijkstra(graph, 0);

return 0;
}