Skip to content

Instantly share code, notes, and snippets.

@charterchap
Last active September 16, 2015 03:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charterchap/c0a2c5251880bbf1abe7 to your computer and use it in GitHub Desktop.
Save charterchap/c0a2c5251880bbf1abe7 to your computer and use it in GitHub Desktop.
Figure out OSM road lengths
/*
This is an example tool that computes the sums of highway lengths.
by Frederik Ramm <frederik@remote.org>
notes from Charter Chapman:
I picked this up in 2015 and it didn't work :( so hammered it until it worked
You need the latest of the old Osmium
https://github.com/joto/osmium
compile w/ (note there are dependencies here, see Osmium README)
g++ ./osmium_road_length.cpp -I../osmium/include/ -std=c++11 -lexpat \
-lprotobuf -lz -pthread -lz -lprotobuf-lite -losmpbf -o road_lengths
works on .pbf files from http://download.geofabrik.de/
*/
#include <cstdlib>
#include <map>
#include <string>
#include <iostream>
#define OSMIUM_WITH_PBF_INPUT
#define OSMIUM_WITH_XML_INPUT
// So if you actually install osmium these will be
// include <osmium.hpp> , etc
#include "../osmium/include/osmium.hpp"
#include "../osmium/include/osmium/storage/byid.hpp"
#include "../osmium/include/osmium/handler/coordinates_for_ways.hpp"
#include "../osmium/include/osmium/storage/byid/sparse_table.hpp"
#include "../osmium/include/osmium/storage/byid/mmap_file.hpp"
#include "../osmium/include/osmium/handler/coordinates_for_ways.hpp"
#include "../osmium/include/osmium/osm/way.hpp"
#include "../osmium/include/osmium/osmfile.hpp"
typedef Osmium::Storage::ById::SparseTable<Osmium::OSM::Position> storage_sparsetable_t;
typedef Osmium::Storage::ById::MmapFile<Osmium::OSM::Position> storage_mmap_t;
typedef Osmium::Handler::CoordinatesForWays<storage_sparsetable_t, storage_mmap_t> cfw_handler_t;
class RoadLengthHandler : public Osmium::Handler::Base {
storage_sparsetable_t store_pos;
storage_mmap_t store_neg;
cfw_handler_t* handler_cfw;
std::map<std::string, unsigned int> length;
std::map<std::string, unsigned int> lengthms;
std::string hwy;
public:
RoadLengthHandler()
{
handler_cfw = new cfw_handler_t(store_pos, store_neg);
}
~RoadLengthHandler()
{
}
void init(Osmium::OSM::Meta& meta)
{
handler_cfw->init(meta);
}
void node(const shared_ptr<Osmium::OSM::Node const>& node)
{
handler_cfw->node(node);
}
void after_nodes()
{
handler_cfw->after_nodes();
}
unsigned int distance(double lat1, double lon1, double lat2, double lon2)
{
if ((lon1==lon2)&&(lat1==lat2)) return 0;
double r = 6371000;
lon1 = lon1 * M_PI/180;
lon2 = lon2 * M_PI/180;
lat1 = lat1 * M_PI/180;
lat2 = lat2 * M_PI/180;
double dlat = lat2-lat1;
double dlon = lon2-lon1;
double x = pow(sin(dlat/2),2) + cos(lat1) * cos(lat2) * pow(sin(dlon/2),2);
double y = 2 * atan2(sqrt(x), sqrt(1-x));
return r*y+0.5;
}
unsigned int way_length(const shared_ptr<Osmium::OSM::Way>& way)
{
double last_lat, last_lon, this_lat, this_lon;
unsigned int len = 0;
if (way->nodes().size() < 2) return 0;
last_lat = way->nodes().front().lat();
last_lon = way->nodes().front().lon();
for (unsigned int i=1; i< way->nodes().size(); i++)
{
this_lat = way->nodes()[i].lat();
this_lon = way->nodes()[i].lon();
len += distance(last_lat, last_lon, this_lat, this_lon);
last_lon = this_lon;
last_lat = this_lat;
}
return len;
}
void way(const shared_ptr<Osmium::OSM::Way>& way)
{
handler_cfw->way(way);
const char* highway = way->tags().get_value_by_key("highway");
if (highway)
{
hwy.assign(highway);
int wl = way_length(way);
length[hwy] += wl;
if (way->tags().get_value_by_key("maxspeed")) lengthms[hwy]+=wl;
}
}
void after_ways()
{
double total = 0;
for (std::map<std::string, unsigned int>::const_iterator i = length.begin(); i != length.end(); i++)
{
total += i->second / 1000.0;
// printf("%-20s%8.1fkm (with ms: %8.1f)\n", i->first.c_str(), i->second / 1000.0, lengthms[i->first]/1000.0);
}
// printf("TOTAL: %-20s%8.1fkm (with ms: %8.1f)\n", i->first.c_str(), i->second / 1000.0, lengthms[i->first]/1000.0);
std::cout << total << std::endl;
}
};
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl;
exit(1);
}
Osmium::OSMFile infile(argv[1]);
RoadLengthHandler handler;
Osmium::Input::read(infile, handler);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment