Last active
September 16, 2015 03:19
-
-
Save charterchap/c0a2c5251880bbf1abe7 to your computer and use it in GitHub Desktop.
Figure out OSM road lengths
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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