I want to create a boost graph from a GeoJSON file containg a network of linestrings. Some linestrings have common nodes. In other words: everything is somehow connected. the file looks like this: (here only 3 linestrings: in reality more than 8000).
{"type": "Feature", "properties": {"id": 1}, "geometry": { "type": "LineString", "coordinates": [ [ 147.0, -4.8 ], [ 141.0, -2.0 ] ]}},
{"type": "Feature", "properties": {"id": 2}, "geometry": { "type": "LineString", "coordinates": [ [ 152.6, -5.2 ], [ 152.05, -3.8 ], [ 147.0, -4.8 ] ] } },
{"type": "Feature", "properties": {"id": 3}, "geometry": { "type": "LineString", "coordinates": [ [ 147.0, -4.8 ], [ 144.73, 0.0 ] ] } },
You see that the coordinate [147.0, -4.8] is part of all 3 linestrings.
I iterate over this file and save these information in a vector linestrings containing struct variables called linestring:
struct linestring //data of one linestring
{
int id;
std::vector<std::vector<double>> pos; //2D vector conatining x and y positions
};
std::vector <linestring> linestrings; //containing the inforamtion of all linestrings
Now I want to use this to build a boost graph:
struct Nodes
{
double x;
double y;
};
struct Legs
{
int id;
double distance;
//edge weight calculated with distance=sqrt((x2-x1)^2+(y2-y1)^2) euclidean distance
};
typedef adjacency_list<listS, vecS, undirectedS, Nodes, Legs> graph_t;
graph_t LinestringGraph;
Which commands are recommended for such a job?
I don't want to add all vertexes and check for redundancy by iterating or other time consuming stuff.
Is there a possibility to add an edge with the custom id and the calculated edge weight together with the vertexes containing the custom property of xy-coordinate.
I want to do something like this: PSEUDOCODE:
iterate over the vector linestrings
count the number of waypoints in the linestring
//e.g. in id=2 are "coordinates":
// [ [ 152.6, -5.2 ], [ 152.05, -3.8 ], [ 147.0, -4.8 ] ]
//edge from [ 152.6, -5.2 ] to [ 152.05, -3.8 ]
// and from [ 152.05, -3.8 ] to [ 147.0, -4.8 ]
add counted edges to the boost graph
and weight with euclidean distance of start and end coordinate of
the current (part)linestring.
if one vertex already exists (e.g. [ 147.0, -4.8 ])
do not create a new vertex --> use the existing
###################################### AFTER the very helpful answer of @sehe and @ravenspoint (Thank you for the very quick reply. I never expect such help) I tried this:
#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
using namespace boost;
struct point // single point/node
{
double lon, lat; //not yet x, y because I want to use longitude and latitude
auto operator==(const point &other)
{
return abs(this->lon - other.lon)< 0.000000000001
&& abs(this->lat - other.lat < 0.000000000001;
}
//thanks for the operator hint from @sehe
};
struct Legs
{
int id;
double Distance; // edge weight
};
struct linestring // data of single linestring
{
int id;
std::vector<point> coords; // vector with double lon/lat
};
using G = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
point, Legs>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;
int main()
{
std::vector<linestring> linestrings; // vector with all linestrings
//some not relevant code for this question: reading in the JSON file with poco
//everything is now stored in the vector linestrings
//you can acess it in the following way:
for (linestring i : linestrings)
{
std::cout << std::endl;
std::cout << "id: " << i.id << std::endl;
std::cout << "Number of waypoints: "
<< i.coords.size() << " \nwaypoints are: (lon, lat): ";
for (point waypoint : i.coords)
{
std::cout << std::endl;
std::cout << "(" << waypoint.lon << ", " << waypoint.lat << ")";
}
std::cout << std::endl;
}
std::map<point, V> mapping;
for (auto &f : linestrings)
{
for (auto &p : f.coords)
{
std::cout << std::endl;
std::cout << p.lon << ", " << p.lat << std::endl;
if (auto it = mapping.find(p); it == mapping.end())
{
mapping.emplace(p, add_vertex(p, g));
}
}
};
return 0;
}
With this I get the error: error C2678: binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion) I tried instead of operator== the operator< but still same result/error
after the line from @sehe
int next_edge_id = 0;
I don't understand how to proceed and add the edges to the graph according to a linestring in the linestrings vector.