osmium/0000755000175000017500000000000011706552174011337 5ustar daviddavidosmium/osmjs/0000775000175000017500000000000011706551765012501 5ustar daviddavidosmium/osmjs/debian/0000775000175000017500000000000011706551765013723 5ustar daviddavidosmium/osmjs/debian/rules0000775000175000017500000000332611706551765015007 0ustar daviddavid#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 configure: configure-stamp configure-stamp: dh_testdir # Add here commands to configure the package. touch configure-stamp build: build-stamp build-stamp: configure-stamp dh_testdir # Add here commands to compile the package. $(MAKE) touch $@ clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp # Add here commands to clean up after the build process. $(MAKE) clean || /bin/true dh_clean install: build dh_testdir dh_testroot dh_prep dh_installdirs # Add here commands to install the package into debian/osmjs. $(MAKE) DESTDIR=$(CURDIR)/debian/osmjs install # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_installchangelogs dh_installdocs dh_installexamples dh_install # dh_installmenu # dh_installdebconf # dh_installlogrotate # dh_installemacsen # dh_installpam # dh_installmime # dh_python # dh_installinit # dh_installcron # dh_installinfo dh_installman dh_link dh_strip dh_compress dh_fixperms # dh_perl # dh_makeshlibs dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install configure osmium/osmjs/debian/control0000664000175000017500000000053611706551765015332 0ustar daviddavidSource: osmjs Section: utils Priority: optional Maintainer: Jochen Topf Build-Depends: debhelper (>= 7) Standards-Version: 3.9.1 Package: osmjs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: A universal OpenStreetMap Javascript data processor. Javascript framework for working with OpenStreetMap data. osmium/osmjs/debian/changelog0000664000175000017500000000021411706551765015572 0ustar daviddavidosmjs (0.1) maverick; urgency=low * Initial standalone debian package -- Jochen Topf Wed, 4 May 2011 09:42:00 +0100 osmium/osmjs/debian/copyright0000664000175000017500000000154711706551765015665 0ustar daviddavidCopyright (C) 2011 Jochen Topf and others, see https://github.com/joto/osmium . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. On Debian systems, the license text can usually be found in /usr/share/common-licenses. osmium/osmjs/debian/dirs0000664000175000017500000000003011706551765014600 0ustar daviddavidusr/bin usr/share/osmjs osmium/osmjs/debian/compat0000664000175000017500000000000211706551765015121 0ustar daviddavid7 osmium/osmjs/js/0000775000175000017500000000000011706551765013115 5ustar daviddavidosmium/osmjs/js/objects.js0000664000175000017500000000255411706551765015112 0ustar daviddavid/* Osmium Javascript Example objects.js run with: osmjs -l sparsetable -j objects.js OSMFILE */ Osmium.Callbacks.init = function() { print('Start!'); } Osmium.Callbacks.node = function() { print('node ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.user + ' ' + this.changeset + ' ' + this.geom.lon + ' ' + this.geom.lat + ' ' + this.geom.toWKT() + ' [' + this.geom.toHexWKB() + ']'); for (var key in this.tags) { print(' ' + key + '=' + this.tags[key]); } } Osmium.Callbacks.way = function() { print('way ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.user + ' ' + this.changeset + ' ' + this.geom.toWKT()); for (var key in this.tags) { print(' ' + key + '=' + this.tags[key]); } for (var i=0; i < this.nodes.length; i++) { print(' ref ' + this.nodes[i]); } } Osmium.Callbacks.relation = function() { print('relation ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.user + ' ' + this.changeset); for (var key in this.tags) { print(' ' + key + '=' + this.tags[key]); } for (var i=0; i < this.members.length; i++) { m = this.members[i]; print(' member ' + m.type + ' ' + m.ref + ' ' + m.role); } } Osmium.Callbacks.end = function() { print('End!'); } osmium/osmjs/js/count.js0000664000175000017500000000203211706551765014600 0ustar daviddavid/* Osmium Javascript Example count.js run with: osmjs -j count.js OSMFILE */ var tags_counter = {}; var keys_counter = {}; Osmium.Callbacks.init = function() { print('Start!'); } Osmium.Callbacks.node = function() { for (var key in this.tags) { if (keys_counter[key]) { keys_counter[key]++; } else { keys_counter[key] = 1; } var value = this.tags[key]; var t = key + '\t' + value; if (tags_counter[t]) { tags_counter[t]++; } else { tags_counter[t] = 1; } } } Osmium.Callbacks.end = function() { var out_keys_nodes = Osmium.Output.CSV.open('stats-keys-nodes.csv'); for (var key in keys_counter) { out_keys_nodes.print(key, keys_counter[key]); } out_keys_nodes.close(); var out_tags_nodes = Osmium.Output.CSV.open('stats-tags-nodes.csv'); for (tag in tags_counter) { out_tags_nodes.print(tag, tags_counter[tag]); } out_tags_nodes.close(); print('End!'); } osmium/osmjs/js/osm2shape.js0000664000175000017500000001305011706551765015353 0ustar daviddavid/* Osmium Javascript Example Framework for exporting OSM data to shapefiles. osm2shape.js (see also config.js) run with: osmjs -2 -m -l sparsetable -i osm2shape.js -j config.js OSMFILE */ // shapefile geometry types var POINT = 'point'; var LINE = 'line'; var POLYGON = 'polygon'; // shapefile attribute types var INTEGER = 'integer'; var STRING = 'string'; var DOUBLE = 'double'; var BOOL = 'bool'; var files = {}; var rules = { node: [], way: [], area: [] }; function shapefile(name) { var shp = { name: name, fname: name, gtype: 'point', columns: [], column_names: {}, type: function(type) { if (type != 'point' && type != 'line' && type != 'polygon') { print('Unknown shapefile geometry type: ' + type); exit(1); } this.gtype = type; return this; }, column: function(name, type, size) { if (type != 'integer' && type != 'string' && type != 'bool' && type != 'double') { print('Unknown attribute type: ' + type); throw("config error"); } if (size == null) { size = 1; } if (size < 0) { print('Size not allowed: ' + size); } var column = { name: name, type: type, size: size }; this.columns.push(column); this.column_names[name] = column; return this; }, filename: function(name) { this.fname = name; return this; } }; files[name] = shp; return shp; } function rule(type, key, value) { if (value == '*') { value = null; } var rule = { type: type, key: key, value: value, file: null, attrs: {}, output: function(name) { if (! files[name]) { print("Unknown shapefile: " + name); throw("config error"); } this.file = name; return this; }, attr: function(attr, key) { if (this.file == null) { print("Output file not set for rule " + key + '=' + value); throw("config error"); } if (! files[this.file].column_names[attr]) { print("There is no column named '" + attr + "' in output file '" + this.file + "'"); throw("config error"); } if (key == null) { key = attr; } this.attrs[attr] = key; return this; } }; rules[type].push(rule); return rule; } function node(key, value) { return rule('node', key, value); } function way(key, value) { return rule('way', key, value); } function area(key, value) { return rule('area', key, value); } function build_func(key, value) { if (value == null) { return function(obj) { return !!obj.tags[key]; }; } else if (typeof(value) == 'string') { if (value == '*') { return function(obj) { return !!obj.tags[key]; }; } else if (value.match(/\|/)) { value = value.split('|'); } else { return function(obj) { return obj.tags[key] && obj.tags[key] == value; }; } } if (value instanceof Array) { return function(obj) { if (! obj.tags[key]) { return false; } for(var i=0; i < value.length; i++) { if (obj.tags[key] == value[i]) { return true; } } return false; }; } else { print("ERROR"); } } Osmium.Callbacks.init = function() { print("Init"); for (var file in files) { var f = files[file]; f.shp = Osmium.Output.Shapefile.open('./' + f.fname, f.gtype); print('Shapefile: ' + file); print(' Filename: ' + f.fname); print(' Geometry type: ' + f.gtype.toUpperCase()); print(' Columns:'); for (var i=0; i < f.columns.length; i++) { var d = f.columns[i]; print(' ' + (d.name + ' ').substr(0, 11) + d.type.toUpperCase() + ' ' + d.size); f.shp.add_field(d.name, d.type, d.size); } print(''); } for (var type in rules) { for (var i=0; i < rules[type].length; i++) { var rule = rules[type][i]; if (rule.file && files[rule.file]) { rule.match = build_func(rule.key, rule.value); } else { print("Unknown shapefile output: " + rule.file); exit(1); } } } } function tags2attributes(id, tags, attrs) { var obj = { id: id }; for (var a in attrs) { obj[a] = tags[attrs[a]]; } return obj; } function check(type, osm_object) { for (var i=0; i < rules[type].length; i++) { var rule = rules[type][i]; if (rule.match(osm_object)) { var a = tags2attributes(osm_object.id, osm_object.tags, rule.attrs); files[rule.file].shp.add(osm_object.geom, a); } } } Osmium.Callbacks.node = function() { check('node', this); } Osmium.Callbacks.way = function() { check('way', this); } Osmium.Callbacks.area = function() { check('area', this); } Osmium.Callbacks.end = function() { for (var file in files) { files[file].shp.close(); } print("Done"); } osmium/osmjs/js/config.js0000664000175000017500000000643611706551765014731 0ustar daviddavid/* Osmium Javascript Example config.js Uses osm2shape framework for exporting OSM data to shapefiles. (see also osm2shape.js) run with: osmjs -2 -m -l sparsetable -i osm2shape.js -j config.js OSMFILE */ // ---- shapefiles ---- shapefile('natural_pois'). type(POINT). column('id', INTEGER, 10). column('type', STRING, 32). column('name', STRING, 32); shapefile('roads'). type(LINE). column('id', INTEGER, 10). column('type', STRING, 32). column('name', STRING, 32). column('ref', STRING, 16). column('oneway', BOOL). column('maxspeed', INTEGER, 3); shapefile('cycleways'). type(LINE). column('id', INTEGER, 10). column('name', STRING, 32); shapefile('railways'). type(LINE). column('id', INTEGER, 10). column('name', STRING, 32); shapefile('waterways'). type(LINE). column('id', INTEGER, 10). column('type', STRING, 32). column('name', STRING, 32); shapefile('powerlines'). type(LINE). column('id', INTEGER, 10). column('name', STRING, 32); shapefile('boundaries'). type(POLYGON). column('id', INTEGER, 10). column('level', INTEGER, 2). column('name', STRING, 32); shapefile('protected_areas'). type(POLYGON). column('id', INTEGER, 10). column('type', STRING, 32). column('name', STRING, 32); shapefile('landuse'). type(POLYGON). column('id', INTEGER, 10). column('type', STRING, 32). column('name', STRING, 32); shapefile('water'). type(POLYGON). column('id', INTEGER, 10). column('type', STRING, 32). column('name', STRING, 32); shapefile('glaciers'). type(POLYGON). column('id', INTEGER, 10). column('name', STRING, 32); // ---- rules ---- node('natural', 'tree|peak|spring'). output('natural_pois'). attr('type', 'natural'). attr('name'); way('waterway', 'stream|river|ditch|canal|drain'). output('waterways'). attr('type', 'waterway'). attr('name'); way('highway', 'motorway|trunk|primary|secondary'). output('roads'). attr('type', 'highway'). attr('ref'). attr('name'). attr('oneway'). attr('maxspeed'); way('highway', 'cycleway'). output('cycleways'). attr('name'); way('railway', 'rail'). output('railways'). attr('name'); way('power', 'line'). output('powerlines'). attr('name'); area('boundary', 'administrative'). output('boundaries'). attr('level', 'admin_level'). attr('name'); area('boundary', 'national_park|national_forest|protected_area'). output('protected_areas'). attr('type', 'boundary'). attr('name'); area('landuse', 'forest|grass|residential|farm|meadow|farmland|industrial|farmyard|cemetery|commercial|quarry|orchard|vineyard|allotments|retail|construction|recreation_ground|village_green'). output('landuse'). attr('type', 'landuse'). attr('name'); area('natural', 'water'). output('water'). attr('type', 'natural'). attr('name'); area('landuse', 'reservoir'). output('water'). attr('type', 'landuse'). attr('name'); area('waterway', 'riverbank'). output('water'). attr('type', 'waterway'). attr('name'); area('natural', 'glacier'). output('glaciers'). attr('name'); osmium/osmjs/js/area.js0000664000175000017500000000131211706551765014360 0ustar daviddavid/* Osmium Javascript Example area.js run with: osmjs -2 -m -l sparsetable -j area.js OSMFILE */ var areas = Osmium.Output.Shapefile.open('./areas', 'polygon'); areas.add_field('id', 'integer', 10); areas.add_field('type', 'string', 32); areas.add_field('name', 'string', 32); Osmium.Callbacks.init = function() { print('Start!'); } Osmium.Callbacks.area = function() { print('area ' + this.id + " from " + this.from); areas.add(this.geom, { id: this.id, name: this.tags.name, type: this.tags.boundary ? 'boundary' : this.tags.building ? 'building' : 'unknown' }); } Osmium.Callbacks.end = function() { areas.close(); print('End!'); } osmium/osmjs/js/time.js0000664000175000017500000000105211706551765014407 0ustar daviddavid/* time.js (single pass), can be used for timing tests */ var nodes=0, ways=0, relations=0; Osmium.Callbacks.node = function() { nodes += 1; } Osmium.Callbacks.after_nodes = function() { } Osmium.Callbacks.way = function() { if (ways == 0) { print('first way'); } ways += 1; } Osmium.Callbacks.relation = function() { if (relations == 0) { print('first relation'); } relations += 1; } Osmium.Callbacks.end = function() { print('nodes: ' + nodes + ' ways: ' + ways + ' relations: ' + relations); } osmium/osmjs/js/shape_export.js0000664000175000017500000000410211706551765016151 0ustar daviddavid/* Osmium Javascript Example shape_export.js run with: osmjs -2 -m -l sparsetable -j shape_export.js OSMFILE */ var shp_pois = Osmium.Output.Shapefile.open('./pois', 'point'); shp_pois.add_field('id', 'integer', 10); shp_pois.add_field('type', 'string', 32); shp_pois.add_field('name', 'string', 32); var shp_roads = Osmium.Output.Shapefile.open('./roads', 'line'); shp_roads.add_field('id', 'integer', 10); shp_roads.add_field('type', 'string', 32); shp_roads.add_field('name', 'string', 32); shp_roads.add_field('oneway', 'integer', 1); shp_roads.add_field('maxspeed', 'integer', 3); var shp_landuse = Osmium.Output.Shapefile.open('./landuse', 'polygon'); shp_landuse.add_field('id', 'integer', 10); shp_landuse.add_field('type', 'string', 32); var node_tags = { amenity: { restaurant: 'restaurant', pub: 'pub' }, shop: { supermarket: 'supermarket' } } Osmium.Callbacks.init = function() { print("Init"); } Osmium.Callbacks.node = function() { for (var key in this.tags) { if (node_tags[key]) { var type = node_tags[key][this.tags[key]]; if (type) { shp_pois.add(this.geom, { id: this.id, type: type, name: this.tags.name }); } } } } Osmium.Callbacks.way = function() { if (this.tags.highway) { var oneway = 0; var maxspeed = 0; if (this.tags.oneway == '1' || this.tags.oneway == 'yes' || this.tags.oneway == 'true') { oneway = 1; } else if (this.tags.oneway == '-1') { oneway = 2; } if (this.tags.maxspeed && this.tags.maxspeed.match(/^([0-9]+) ?(km\/?h)?$/)) { maxspeed = RegExp.$1; } shp_roads.add(this.geom, { id: this.id, type: this.tags.highway, name: this.tags.name, oneway: oneway, maxspeed: maxspeed }); } } Osmium.Callbacks.area = function() { if (this.tags.landuse) { shp_landuse.add(this.geom, { id: this.id, type: this.tags.landuse }); } } Osmium.Callbacks.end = function() { shp_pois.close(); shp_roads.close(); shp_landuse.close(); print("Done"); } osmium/osmjs/js/objects_2pass.js0000664000175000017500000000320711706551765016216 0ustar daviddavid/* Osmium Javascript Example objects_2pass.js run with: osmjs -2 -m -l sparsetable -j objects_2pass.js OSMFILE */ Osmium.Callbacks.init = function() { print('Start!'); } Osmium.Callbacks.node = function() { print('node ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.user + ' ' + this.changeset + ' ' + this.geom.lon + ' ' + this.geom.lat + ' ' + this.geom.toWKT() + ' [' + this.geom.toHexWKB() + ']'); for (var key in this.tags) { print(' ' + key + '=' + this.tags[key]); } } Osmium.Callbacks.way = function() { print('way ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.user + ' ' + this.changeset + ' ' + this.geom.toWKT()); for (var key in this.tags) { print(' ' + key + '=' + this.tags[key]); } for (var i=0; i < this.nodes.length; i++) { print(' ref ' + this.nodes[i]); } } Osmium.Callbacks.relation = function() { print('relation ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.user + ' ' + this.changeset); for (var key in this.tags) { print(' ' + key + '=' + this.tags[key]); } for (var i=0; i < this.members.length; i++) { m = this.members[i]; print(' member ' + m.type + ' ' + m.ref + ' ' + m.role); } } Osmium.Callbacks.area = function() { print('area from ' + this.from + ' ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.changeset); for (var key in this.tags) { print(' ' + key + '=' + this.tags[key]); } } Osmium.Callbacks.end = function() { print('End!'); } osmium/osmjs/js/testgeom.js0000664000175000017500000000310711706551765015303 0ustar daviddavid/* Osmium Javascript Example testgeom.js run with: osmjs -2 -m -l sparsetable -j testgeom.js OSMFILE */ Osmium.Callbacks.node = function() { print("node id: " + this.id); print("geom.lon: " + this.geom.lon); print("geom.lat: " + this.geom.lat); print("geom.toArray(): " + JSON.stringify(this.geom.toArray())); print("geom.toWKT(): " + this.geom.toWKT()); print("geom.toWKT(true): " + this.geom.toWKT(true)); print("geom.toHexWKB(): " + this.geom.toHexWKB()); print("geom.toHexWKB(true): " + this.geom.toHexWKB(true)); print(""); } Osmium.Callbacks.way = function() { print("way id: " + this.id); print("geom.toArray(): " + JSON.stringify(this.geom.toArray())); print("geom.toWKT(): " + this.geom.toWKT()); print("geom.toWKT(true): " + this.geom.toWKT(true)); print("geom.toHexWKB(): " + this.geom.toHexWKB()); print("geom.toHexWKB(true): " + this.geom.toHexWKB(true)); print("reverse_geom.toWKT(): " + this.reverse_geom.toWKT()); print("polygon_geom.toWKT(): " + this.polygon_geom.toWKT()); print(""); } Osmium.Callbacks.area = function() { print("area id: " + this.id); print("geom.toWKT(): " + this.geom.toWKT()); print("geom.toWKT(true): " + this.geom.toWKT(true)); print("geom.toHexWKB(): " + this.geom.toHexWKB()); print("geom.toHexWKB(true): " + this.geom.toHexWKB(true)); print("geom.toArray(): " + JSON.stringify(this.geom.toArray())); print(""); } osmium/osmjs/Makefile0000664000175000017500000000324611706551765014146 0ustar daviddavid#------------------------------------------------------------------------------ # # Osmium osmjs makefile # #------------------------------------------------------------------------------ CXX = g++ CXXFLAGS = -g #CXXFLAGS = -O3 CXXFLAGS += -Wall -Wextra -Wredundant-decls -Wdisabled-optimization -pedantic #CXXFLAGS += -Wpadded -Winline # uncomment this if you want information on how long it took to build the multipolygons #CXXFLAGS += -DOSMIUM_WITH_MULTIPOLYGON_PROFILING CXXFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 CXXFLAGS += -DOSMIUM_WITH_GEOS $(shell geos-config --cflags) CXXFLAGS += -DOSMIUM_WITH_SHPLIB CXXFLAGS += -DOSMIUM_WITH_JAVASCRIPT # Add this to force V8 garbage collection after each node/way/relation/area callback. # Use only to find memory leaks. It will make osmjs really slow. #CXXFLAGS += -DOSMIUM_V8_FORCE_GC CXXFLAGS += -I../include LDFLAGS = -L/usr/local/lib -lexpat -lpthread LDFLAGS += $(shell geos-config --libs) LIB_V8 = -lv8 -licuuc LIB_SHAPE = -lshp LIB_PROTOBUF = -lz -lprotobuf-lite -losmpbf .PHONY: all clean install all: osmjs osmjs: osmjs.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_V8) $(LIB_SHAPE) install: install -m 755 -g root -o root -d $(DESTDIR)/usr/bin install -m 755 -g root -o root osmjs $(DESTDIR)/usr/bin/osmjs install -m 755 -g root -o root -d $(DESTDIR)/usr/share/osmjs install -m 644 -g root -o root js/osm2shape.js $(DESTDIR)/usr/share/osmjs/osm2shape.js install -m 755 -g root -o root -d $(DESTDIR)/usr/share/doc/osmjs install -m 644 -g root -o root README $(DESTDIR)/usr/share/doc/osmjs/README clean: rm -f *.o core osmjs deb: debuild -I -us -uc deb-clean: debuild clean osmium/osmjs/.gitignore0000664000175000017500000000000611706551765014465 0ustar daviddavidosmjs osmium/osmjs/osmjs.cpp0000664000175000017500000003222511706551765014344 0ustar daviddavid #include #include #include #include #include #include #include #ifdef OSMIUM_WITH_MULTIPOLYGON_PROFILING std::vector > Osmium::OSM::AreaFromRelation::timers; timer Osmium::OSM::AreaFromRelation::write_complex_poly_timer; timer Osmium::OSM::AreaFromRelation::assemble_ways_timer; timer Osmium::OSM::AreaFromRelation::assemble_nodes_timer; timer Osmium::OSM::AreaFromRelation::make_one_ring_timer; timer Osmium::OSM::AreaFromRelation::mor_polygonizer_timer; timer Osmium::OSM::AreaFromRelation::mor_union_timer; timer Osmium::OSM::AreaFromRelation::contains_timer; timer Osmium::OSM::AreaFromRelation::extra_polygons_timer; timer Osmium::OSM::AreaFromRelation::polygon_build_timer; timer Osmium::OSM::AreaFromRelation::inner_ring_touch_timer; timer Osmium::OSM::AreaFromRelation::polygon_intersection_timer; timer Osmium::OSM::AreaFromRelation::multipolygon_build_timer; timer Osmium::OSM::AreaFromRelation::multipolygon_write_timer; timer Osmium::OSM::AreaFromRelation::error_write_timer; #endif // OSMIUM_WITH_MULTIPOLYGON_PROFILING typedef Osmium::Storage::ById storage_byid_t; typedef Osmium::Storage::Mmap storage_mmap_t; typedef Osmium::Handler::CoordinatesForWays cfw_handler_t; class SinglePass : public Osmium::Handler::Base { cfw_handler_t* handler_cfw; Osmium::Handler::Javascript* handler_javascript; public: SinglePass(cfw_handler_t* cfw = NULL, Osmium::Handler::Javascript* js = NULL) : Base(), handler_cfw(cfw), handler_javascript(js) { } void init(Osmium::OSM::Meta& meta) { if (handler_cfw) { handler_cfw->init(meta); } handler_javascript->init(meta); } void node(const shared_ptr& node) { if (handler_cfw) { handler_cfw->node(node); } handler_javascript->node(node); } void after_nodes() { if (handler_cfw) handler_cfw->after_nodes(); } void way(const shared_ptr& way) { if (handler_cfw) { handler_cfw->way(way); } handler_javascript->way(way); } void relation(const shared_ptr& relation) { handler_javascript->relation(relation); } void final() { handler_javascript->final(); } }; class DualPass1 : public Osmium::Handler::Base { cfw_handler_t* handler_cfw; Osmium::Handler::Multipolygon* handler_multipolygon; Osmium::Handler::Javascript* handler_javascript; public: DualPass1(cfw_handler_t* cfw = NULL, Osmium::Handler::Multipolygon* mp = NULL, Osmium::Handler::Javascript* js = NULL) : Base(), handler_cfw(cfw), handler_multipolygon(mp), handler_javascript(js) { } void init(Osmium::OSM::Meta& meta) { if (handler_multipolygon) { handler_multipolygon->init(meta); } if (handler_cfw) { handler_cfw->init(meta); } handler_javascript->init(meta); } void node(const shared_ptr& node) { handler_javascript->node(node); } void before_relations() { if (handler_multipolygon) { handler_multipolygon->before_relations(); } } void relation(const shared_ptr& relation) { if (handler_multipolygon) { handler_multipolygon->relation(relation); } handler_javascript->relation(relation); } void after_relations() { if (handler_multipolygon) { handler_multipolygon->after_relations(); } std::cerr << "1st pass finished" << std::endl; } }; class DualPass2 : public Osmium::Handler::Base { cfw_handler_t* handler_cfw; Osmium::Handler::Multipolygon* handler_multipolygon; Osmium::Handler::Javascript* handler_javascript; public: DualPass2(cfw_handler_t* cfw = NULL, Osmium::Handler::Multipolygon* mp = NULL, Osmium::Handler::Javascript* js = NULL) : Base(), handler_cfw(cfw), handler_multipolygon(mp), handler_javascript(js) { } void node(const shared_ptr& node) { if (handler_cfw) { handler_cfw->node(node); } } void after_nodes() { if (handler_cfw) { handler_cfw->after_nodes(); } } void way(const shared_ptr& way) { if (handler_cfw) { handler_cfw->way(way); } if (handler_multipolygon) { handler_multipolygon->way(way); } handler_javascript->way(way); } void after_ways() { if (handler_multipolygon) { handler_multipolygon->after_ways(); } } void final() { handler_javascript->final(); if (handler_multipolygon) { handler_multipolygon->final(); } } }; /* ================================================== */ v8::Persistent global_context; void print_help() { std::cout << "osmjs [OPTIONS] OSMFILE [SCRIPT_ARG ...]\n" << "Options:\n" << " --help, -h - This help message\n" << " --debug, -d - Enable debugging output\n" << " --include=FILE, -i FILE - Include Javascript file (can be given several times)\n" << " --javascript=FILE, -j FILE - Process given Javascript file\n" << " --location-store=STORE, -l STORE - Set location store (default: 'none')\n" << " --no-repair, -r - Do not attempt to repair broken multipolygons\n" << " --2pass, -2 - Read OSMFILE twice\n" << " --multipolygon, -m - Build multipolygons (implies -2)\n" << "Location stores:\n" << " none - Do not store node locations (you will have no way or polygon geometries)\n" << " array - Store node locations in large array (use for large OSM files)\n" << " disk - Store node locations on disk (use when low on memory)\n" << " sparsetable - Store node locations in sparse table (use for small OSM files)\n" ; } std::string find_include_file(std::string filename) { std::vector search_path; search_path.push_back("."); search_path.push_back("js"); search_path.push_back(std::string(getenv("HOME")) + "/.osmjs"); search_path.push_back("/usr/local/share/osmjs"); search_path.push_back("/usr/share/osmjs"); // add .js if there is no suffix if (filename.find_last_of('.') == std::string::npos) { filename.append(".js"); } // go through search path and find where the file is for (std::vector::iterator vi = search_path.begin(); vi != search_path.end(); vi++) { std::string f = *vi + "/" + filename; if (!access(f.c_str(), R_OK)) { return f; } } std::cerr << "Could not find include file " << filename << " in search path ("; for (std::vector::iterator vi = search_path.begin(); vi != search_path.end(); vi++) { if (vi != search_path.begin()) std::cerr << ":"; std::cerr << *vi; } std::cerr << ")" << std::endl; exit(1); } Osmium::Handler::Javascript* handler_javascript; void cbmp(Osmium::OSM::Area* area) { handler_javascript->area(area); } int main(int argc, char *argv[]) { std::ios_base::sync_with_stdio(false); bool two_passes = false; bool attempt_repair = true; std::string javascript_filename; std::string osm_filename; std::vector include_files; enum location_store_t { NONE, ARRAY, DISK, SPARSETABLE } location_store = NONE; static struct option long_options[] = { {"debug", no_argument, 0, 'd'}, {"include", required_argument, 0, 'i'}, {"javascript", required_argument, 0, 'j'}, {"help", no_argument, 0, 'h'}, {"location-store", required_argument, 0, 'l'}, {"no-repair", no_argument, 0, 'r'}, {"2pass", no_argument, 0, '2'}, {"multipolygon", no_argument, 0, 'm'}, {0, 0, 0, 0} }; bool debug = false; bool multipolygon = false; while (1) { int c = getopt_long(argc, argv, "dhi:j:l:r2m", long_options, 0); if (c == -1) break; switch (c) { case 'd': debug = true; break; case 'i': { std::string f(optarg); include_files.push_back(find_include_file(f)); break; } case 'j': javascript_filename = optarg; break; case 'h': print_help(); exit(0); case 'l': if (!strcmp(optarg, "none")) { location_store = NONE; } else if (!strcmp(optarg, "array")) { location_store = ARRAY; } else if (!strcmp(optarg, "disk")) { location_store = DISK; } else if (!strcmp(optarg, "sparsetable")) { location_store = SPARSETABLE; } else { std::cerr << "Unknown location store: " << optarg << " (available are: 'none, 'array', 'disk' and 'sparsetable')" << std::endl; exit(1); } break; case 'r': attempt_repair = false; break; case '2': two_passes = true; break; case 'm': multipolygon = true; two_passes = true; break; default: exit(1); } } if (javascript_filename.empty()) { std::cerr << "No --javascript/-j option given" << std::endl; exit(1); } if (optind >= argc) { std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE [SCRIPT_ARG ...]" << std::endl; exit(1); } else { osm_filename = argv[optind]; } if (two_passes && osm_filename == "-") { std::cerr << "Can't read from stdin when in dual-pass mode" << std::endl; exit(1); } if (two_passes && ! multipolygon) { std::cerr << "Warning! The command line option -2 has changed its meaning.\nIt now only enables the two-pass mode, multipolygon assembly has to be enabled with -m.\n"; } Osmium::init(debug); Osmium::OSMFile infile(osm_filename); v8::HandleScope handle_scope; v8::Handle global_template = v8::ObjectTemplate::New(); global_template->Set(v8::String::New("print"), v8::FunctionTemplate::New(Osmium::Handler::Javascript::Print)); global_template->Set(v8::String::New("include"), v8::FunctionTemplate::New(Osmium::Handler::Javascript::Include)); global_context = v8::Persistent::New(v8::Context::New(0, global_template)); v8::Context::Scope context_scope(global_context); // put rest of the arguments into Javascript argv array v8::Handle js_argv = v8::Array::New(argc-optind-1); for (int i=optind+1; i ii = v8::Integer::New(i-(optind+1)); v8::Local s = v8::String::New(argv[i]); js_argv->Set(ii, s); } global_context->Global()->Set(v8::String::New("argv"), js_argv); storage_byid_t* store_pos = NULL; if (location_store == ARRAY) { store_pos = new Osmium::Storage::Mmap(); } else if (location_store == DISK) { std::string filename(""); store_pos = new Osmium::Storage::Mmap(filename); } else if (location_store == SPARSETABLE) { store_pos = new Osmium::Storage::SparseTable(); } Osmium::Storage::Mmap store_neg; cfw_handler_t* handler_cfw = (store_pos == NULL) ? NULL : new cfw_handler_t(*store_pos, store_neg); handler_javascript = new Osmium::Handler::Javascript(include_files, javascript_filename.c_str()); if (two_passes) { Osmium::Handler::Multipolygon* handler_multipolygon = NULL; if (multipolygon) { handler_multipolygon = new Osmium::Handler::Multipolygon(attempt_repair, cbmp); } DualPass1 handler1(handler_cfw, handler_multipolygon, handler_javascript); infile.read(handler1); DualPass2 handler2(handler_cfw, handler_multipolygon, handler_javascript); infile.read(handler2); delete handler_multipolygon; } else { SinglePass handler(handler_cfw, handler_javascript); infile.read(handler); } delete handler_javascript; delete handler_cfw; delete store_pos; global_context.Dispose(); } osmium/osmjs/README0000664000175000017500000001653711706551765013375 0ustar daviddavid Osmjs README ============ Osmjs is an Osmium based framework for handling OSM data by calling Javascript callbacks for each object in an OSM data file. This gives you the flexibility of Javascript together with speed of the C++ Osmium framework and the Google V8 Javascript JIT compiler. Multipolygon Support -------------------- Osmjs can assemble multipolygons from relations for you. To enable this you have to use the --2pass/-2 option on the command line. The input file is then read twice. In the first pass all relations of type=multipolygon or type=border are stored in memory, together with the list of ways that are needed to build them. In the second pass multipolygons are assembled from the ways. You will get callbacks for each multipolygon as soon as all ways needed for a multipolygon have gone by and the multipolygon could be assembled. You will also get multipolygon callbacks for closed ways that are not needed for any multipolygon as they potentially describe polygons, too. Unless you give the --no-repair/-r option, Osmium will try to repair broken multipolygons. It can sometimes close open rings and work around self-intersecting rings. Building osmjs --------------- You must have the prerequisites for Osmium installed. See ../README. Call "make" in this directory to build osmjs. Calling osmjs ------------- osmjs [OPTIONS] OSMFILE OSMFILE can be an OSM XML (suffix .osm) (optionally packed with bz2 or gz) or PBF (suffix .osm.pbf) file. In single-pass mode it can also be '-' to read a PBF file from stdin. See osmjs --help for the options. You must at least give the --javascript/-j option with a javascript filename. You need to use the --location-store/-l option if you want way and/or multipolygon geometries. This can take a lot of memory! See "osmjs --help" for more info. Note for 32 bit systems ----------------------- Osmjs has not been fully tested on 32 bit systems. The -l array and -l disk options will not work on 32bit systems, because the memory range they can address is just too small. Javascript Functions -------------------- You can use any normal Javascript functions and objects in your code. Note that there is no DOM, you are not in a browser! The following special functions have been defined: * print(text) -- Output any text to stdout * include(filename) -- Include external Javascript file In addition the "Osmium" object gives you access to some functionality: * Osmium.debug -- Boolean attribute reflecting the setting of the --debug/-d command line option * Osmium.Callbacks -- To set the callback handlers (see below) * Osmium.Output.CSV -- CSV output files (see below) * Osmium.Output.Shapefile -- Shapefile output files (see below) Callbacks --------- The following callbacks can be defined: Osmium.Callbacks.init Osmium.Callbacks.before_nodes Osmium.Callbacks.node Osmium.Callbacks.after_nodes Osmium.Callbacks.before_ways Osmium.Callbacks.way Osmium.Callbacks.after_ways Osmium.Callbacks.before_relations Osmium.Callbacks.relation Osmium.Callbacks.after_relations Osmium.Callbacks.multipolygon Osmium.Callbacks.end If the --2pass/-2 option is *not* given, the callbacks are called in the following order: init, before_nodes, node (for each node), after_nodes, before_ways, way (for each way), after_ways, before_relations, relation (for each relation), after_relations, end. The 'multipolygon' callback is never called! If the --2pass/-2 option is given, the callbacks are called in the following order: init, before_relations, relation (for each relation), after_relations, before_nodes, node (for each node), after_nodes, before_ways, way (for each way) / multipolygon (for each completed multipolygon), after_ways, end. The way and multipolygon callbacks can come in any order. The 'node', 'way', 'relation' and 'multipolygon' callbacks will be called with an OSM object as 'this'. Objects have the following attributes: id, version, timestamp, uid, user, changeset, and tags. 'tags' is a hash. Node objects also have lon and lat attributes. Example: Osmium.Callbacks.node = function() { print('node ' + this.id + ' ' + this.version + ' ' + this.timestamp + ' ' + this.uid + ' ' + this.user + ' ' + this.changeset + ' ' + this.lon + ' ' + this.lat); for (key in this.tags) { print(' ' + key + '=' + this.tags[key]); } } Writing to CSV Files -------------------- You can write some output to CSV files. Currently line endings are always LF, column separator is always a TAB. Example: var csv_file = Osmium.Output.CSV.open("some-filename.csv"); csv_file.print("first column", "second column"); csv_file.close(); Writing to Shapefiles --------------------- (See next chapter for an easier way.) You can write OSM objects to Shapefiles of type POINT, LINE, and POLYGON. To do this you first have to open a shapefile and define the attributes that should be used. Do not give any suffix for the filename. The suffixes '.shp', '.shx', and '.dbf' for the different files will be added automatically. Define a shapefile named "example" with point geometries: var shp = Osmium.Output.Shapefile.open("example", "point"); shp.add_field("id", "integer", 10); shp.add_field("name", "string", 40); Field types are integer, string, double, and bool. Bools are always of length 1, other need the length in characters and doubles also need a precision. You can now add gemetries to the Shapefile: shp.add(some_node.geom, { id: some_node.id, some_node.tags.name }); The geometry of the object (in this case 'some_node') will be put into the shapefile. The second argument to add() is a hash which must contain all the attributes. After use you have to close the shapefile properly or some data may not end up in it: shp.close(); Converting OSM data to Shapefiles --------------------------------- There is an easier way to work with Shapefiles. If you include the osm2shp Javascript library from the command line, you can use a different syntax: osmjs -2 -i osm2shape -j my_config.js some_osm_file.osm.pbf You can define shapefiles like this: shapefile('pois'). type(POINT). column('id', INTEGER, 10). column('type', STRING, 32). column('name', STRING, 32); Note that each line ends in a dot (.), the last with a semikolon (;). Types POINT, LINE, and POLYGON are allowed. You can use INTEGER, STRING, DOUBLE, and BOOL as attribute types. You can also define rules for matching OSM data to the right shapefiles: node('amenity', 'post_box|phone'). output('pois'). attr('type', 'amenity'). attr('name'); This rule matches all nodes with a tag amenity=post_box or amenity=phone and writes the node to the previously defined 'pois' shapefile. The 'id' attribute is filled automatically with the id of the node. The 'type' attribute is filled from the value of the tag with the key 'amenity' and the 'name' attribute is filled from the value of the tag with the 'name' key. You can match: node(), way(), area(). Areas can be closed simple ways or multipolygons. The first argument to these matching functions is always a key. The optional second argument is a value or list of values separated by '|'. If the second argument is missing or '*', the rule matches all objects with the given tag key regardless of the value. osmium/test/0000775000175000017500000000000011706551765012325 5ustar daviddavidosmium/test/test_utils.cpp0000664000175000017500000000076111706551765015234 0ustar daviddavid#include namespace Osmium { namespace Test { std::string to_hex(const std::string& in) { static const char* lookup_hex = "0123456789ABCDEF"; std::string out(""); for (std::string::const_iterator it=in.begin(); it != in.end(); ++it) { out += lookup_hex[(*it >> 4) & 0xf]; out += lookup_hex[*it & 0xf]; } return out; } } // namespace Test } // namespace Osmium osmium/test/test_utils.hpp0000664000175000017500000000037611706551765015243 0ustar daviddavid#ifndef OSMIUM_TEST_UTILS_HPP #define OSMIUM_TEST_UTILS_HPP #include namespace Osmium { namespace Test { std::string to_hex(const std::string& in); } // namespace Test } // namespace Osmium #endif // OSMIUM_TEST_UTILS_HPP osmium/test/testgroup_ogr/0000775000175000017500000000000011706551765015230 5ustar daviddavidosmium/test/testgroup_ogr/setup.sh0000664000175000017500000000010611706551765016721 0ustar daviddavidFLAGS="-DOSMIUM_WITH_OGR `gdal-config --cflags` `gdal-config --libs`" osmium/test/testgroup_ogr/geometry/0000775000175000017500000000000011706551765017063 5ustar daviddavidosmium/test/testgroup_ogr/geometry/test_geometry.cpp0000664000175000017500000000427011706551765022464 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include using boost::test_tools::output_test_stream; #include #include #include #include BOOST_AUTO_TEST_SUITE(Geometry) BOOST_AUTO_TEST_CASE(point_from_position) { Osmium::OSM::Position pos(1.2, 3.4); Osmium::Geometry::Point point(pos); BOOST_CHECK_EQUAL(point.lon(), 1.2); BOOST_CHECK_EQUAL(point.lat(), 3.4); OGRPoint* ogrpoint = point.create_ogr_geometry(); BOOST_CHECK_EQUAL(ogrpoint->getX(), 1.2); BOOST_CHECK_EQUAL(ogrpoint->getY(), 3.4); delete ogrpoint; } BOOST_AUTO_TEST_CASE(linestring_from_way) { Osmium::OSM::Position pos1(1.2, 3.4); Osmium::OSM::Position pos2(2.3, 4.5); Osmium::OSM::WayNodeList wnl; wnl.add(Osmium::OSM::WayNode(1, pos1)); wnl.add(Osmium::OSM::WayNode(2, pos2)); Osmium::Geometry::LineString linestring(wnl); OGRLineString* ogrlinestring = linestring.create_ogr_geometry(); OGRPoint ogrpoint; ogrlinestring->StartPoint(&ogrpoint); BOOST_CHECK_EQUAL(ogrpoint.getX(), 1.2); BOOST_CHECK_EQUAL(ogrpoint.getY(), 3.4); ogrlinestring->getPoint(1, &ogrpoint); BOOST_CHECK_EQUAL(ogrpoint.getX(), 2.3); BOOST_CHECK_EQUAL(ogrpoint.getY(), 4.5); delete ogrlinestring; } BOOST_AUTO_TEST_CASE(polygon_from_way) { Osmium::OSM::Position pos1(1.2, 3.4); Osmium::OSM::Position pos2(2.3, 4.5); Osmium::OSM::WayNodeList wnl; wnl.add(Osmium::OSM::WayNode(1, pos1)); wnl.add(Osmium::OSM::WayNode(2, pos2)); wnl.add(Osmium::OSM::WayNode(1, pos1)); Osmium::Geometry::Polygon polygon(wnl); OGRPolygon* ogrpolygon = polygon.create_ogr_geometry(); std::string ogrwkb; ogrwkb.resize(ogrpolygon->WkbSize()); ogrpolygon->exportToWkb(wkbNDR, (unsigned char*)ogrwkb.c_str()); output_test_stream osmiumwkb; osmiumwkb << polygon.as_WKB(); BOOST_CHECK_EQUAL(osmiumwkb.str().size(), ogrpolygon->WkbSize()); BOOST_CHECK(osmiumwkb.is_equal(ogrwkb)); delete ogrpolygon; } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/0000775000175000017500000000000011706551765015544 5ustar daviddavidosmium/test/testgroup_plain/osmfile/0000775000175000017500000000000011706551765017202 5ustar daviddavidosmium/test/testgroup_plain/osmfile/test_filename.cpp0000664000175000017500000000611711706551765022532 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include #include #include #include BOOST_AUTO_TEST_SUITE(OSMFile) BOOST_AUTO_TEST_CASE(filename_osm) { Osmium::OSMFile file("test.osm"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::XML()); } BOOST_AUTO_TEST_CASE(filename_osm_bz2) { Osmium::OSMFile file("test.osm.bz2"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::XMLbz2()); } BOOST_AUTO_TEST_CASE(filename_osm_gz) { Osmium::OSMFile file("test.osm.gz"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::XMLgz()); } BOOST_AUTO_TEST_CASE(filename_osm_pbf) { Osmium::OSMFile file("test.osm.pbf"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::PBF()); } BOOST_AUTO_TEST_CASE(filename_pbf) { Osmium::OSMFile file("test.pbf"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::PBF()); } BOOST_AUTO_TEST_CASE(filename_osh_pbf) { Osmium::OSMFile file("test.osh.pbf"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::History()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::PBF()); } BOOST_AUTO_TEST_CASE(filename_with_dir) { Osmium::OSMFile file("somedir/test.osm"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::XML()); } BOOST_AUTO_TEST_CASE(filename_with_parent_dir) { Osmium::OSMFile file("../test.osm"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::XML()); } BOOST_AUTO_TEST_CASE(filename_no_suffix) { Osmium::OSMFile file("test"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::PBF()); } BOOST_AUTO_TEST_CASE(filename_unknown_suffix) { Osmium::OSMFile file("test.test"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::PBF()); } BOOST_AUTO_TEST_CASE(filename_empty) { Osmium::OSMFile file(""); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::PBF()); } BOOST_AUTO_TEST_CASE(filename_minus) { Osmium::OSMFile file("-"); BOOST_CHECK_EQUAL(file.get_type(), Osmium::OSMFile::FileType::OSM()); BOOST_CHECK_EQUAL(file.get_encoding(), Osmium::OSMFile::FileEncoding::PBF()); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/utils/0000775000175000017500000000000011706551765016704 5ustar daviddavidosmium/test/testgroup_plain/utils/test_timestamp.cpp0000664000175000017500000000126211706551765022453 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include BOOST_AUTO_TEST_SUITE(Timestamp) BOOST_AUTO_TEST_CASE(zero) { BOOST_CHECK_EQUAL(std::string(""), Osmium::Utils::Timestamp::to_iso(0)); } BOOST_AUTO_TEST_CASE(second_after_epoch) { BOOST_CHECK_EQUAL(std::string("1970-01-01T00:00:01Z"), Osmium::Utils::Timestamp::to_iso(1)); } BOOST_AUTO_TEST_CASE(sometime) { const char* ts= "2011-10-28T09:12:00Z"; time_t t = Osmium::Utils::Timestamp::parse_iso(ts); BOOST_CHECK_EQUAL(std::string(ts), Osmium::Utils::Timestamp::to_iso(t)); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/setup.sh0000664000175000017500000000001111706551765017230 0ustar daviddavidFLAGS="" osmium/test/testgroup_plain/geometry/0000775000175000017500000000000011706551765017377 5ustar daviddavidosmium/test/testgroup_plain/geometry/test_polygon_geometry.cpp0000664000175000017500000000541011706551765024544 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include #include #include #include #include #include BOOST_AUTO_TEST_SUITE(PolygonGeometry) BOOST_AUTO_TEST_CASE(instantiation) { Osmium::OSM::WayNodeList wnl; Osmium::OSM::WayNode n1(1, Osmium::OSM::Position(1.0, 1.0)); Osmium::OSM::WayNode n2(2, Osmium::OSM::Position(1.0, 2.0)); Osmium::OSM::WayNode n3(3, Osmium::OSM::Position(2.0, 2.0)); Osmium::OSM::WayNode n4(1, Osmium::OSM::Position(1.0, 1.0)); wnl.add(n1); wnl.add(n2); wnl.add(n3); BOOST_CHECK_THROW(Osmium::Geometry::Polygon polygon(wnl), Osmium::Exception::IllegalGeometry); // not closed wnl.add(n4); // now its closed Osmium::Geometry::Polygon polygon(wnl); } BOOST_AUTO_TEST_CASE(output) { Osmium::OSM::WayNodeList wnl; Osmium::OSM::WayNode n1(1, Osmium::OSM::Position(1.9, 1.9)); Osmium::OSM::WayNode n2(2, Osmium::OSM::Position(1.9, 2.9)); Osmium::OSM::WayNode n3(3, Osmium::OSM::Position(2.9, 2.9)); Osmium::OSM::WayNode n4(1, Osmium::OSM::Position(1.9, 1.9)); wnl.add(n1); wnl.add(n2); wnl.add(n3); wnl.add(n4); Osmium::Geometry::Polygon polygon(wnl); std::ostringstream out_wkt; out_wkt << polygon.as_WKT(); BOOST_CHECK_EQUAL(out_wkt.str(), "POLYGON((1.9 1.9,1.9 2.9,2.9 2.9,1.9 1.9))"); std::ostringstream out_ewkt; out_ewkt << polygon.as_WKT(true); BOOST_CHECK_EQUAL(out_ewkt.str(), "SRID=4326;POLYGON((1.9 1.9,1.9 2.9,2.9 2.9,1.9 1.9))"); std::ostringstream out_wkb; out_wkb << polygon.as_WKB(); BOOST_CHECK_EQUAL(Osmium::Test::to_hex(out_wkb.str()), "01030000000100000004000000666666666666FE3F666666666666FE3F666666666666FE3F333333333333074033333333333307403333333333330740666666666666FE3F666666666666FE3F"); std::ostringstream out_ewkb; out_ewkb << polygon.as_WKB(true); BOOST_CHECK_EQUAL(Osmium::Test::to_hex(out_ewkb.str()), "0103000020E61000000100000004000000666666666666FE3F666666666666FE3F666666666666FE3F333333333333074033333333333307403333333333330740666666666666FE3F666666666666FE3F"); std::ostringstream out_hexwkb; out_hexwkb << polygon.as_HexWKB(); BOOST_CHECK_EQUAL(out_hexwkb.str(), "01030000000100000004000000666666666666FE3F666666666666FE3F666666666666FE3F333333333333074033333333333307403333333333330740666666666666FE3F666666666666FE3F"); std::ostringstream out_hexewkb; out_hexewkb << polygon.as_HexWKB(true); BOOST_CHECK_EQUAL(out_hexewkb.str(), "0103000020E61000000100000004000000666666666666FE3F666666666666FE3F666666666666FE3F333333333333074033333333333307403333333333330740666666666666FE3F666666666666FE3F"); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/geometry/test_point_geometry.cpp0000664000175000017500000000312311706551765024205 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include #include #include #include #include #include BOOST_AUTO_TEST_SUITE(PointGeometry) BOOST_AUTO_TEST_CASE(instantiation) { Osmium::OSM::Position pos1(1.2, 3.4); Osmium::Geometry::Point point1(pos1); BOOST_CHECK_EQUAL(point1.lon(), 1.2); BOOST_CHECK_EQUAL(point1.lat(), 3.4); } BOOST_AUTO_TEST_CASE(output) { Osmium::OSM::Position pos1(1.2, 3.4); Osmium::Geometry::Point point1(pos1); std::ostringstream out_wkt; out_wkt << point1.as_WKT(); BOOST_CHECK_EQUAL(out_wkt.str(), "POINT(1.2 3.4)"); std::ostringstream out_ewkt; out_ewkt << point1.as_WKT(true); BOOST_CHECK_EQUAL(out_ewkt.str(), "SRID=4326;POINT(1.2 3.4)"); std::ostringstream out_wkb; out_wkb << point1.as_WKB(); BOOST_CHECK_EQUAL(Osmium::Test::to_hex(out_wkb.str()), "0101000000333333333333F33F3333333333330B40"); std::ostringstream out_ewkb; out_ewkb << point1.as_WKB(true); BOOST_CHECK_EQUAL(Osmium::Test::to_hex(out_ewkb.str()), "0101000020E6100000333333333333F33F3333333333330B40"); std::ostringstream out_hexwkb; out_hexwkb << point1.as_HexWKB(); BOOST_CHECK_EQUAL(out_hexwkb.str(), "0101000000333333333333F33F3333333333330B40"); std::ostringstream out_hexewkb; out_hexewkb << point1.as_HexWKB(true); BOOST_CHECK_EQUAL(out_hexewkb.str(), "0101000020E6100000333333333333F33F3333333333330B40"); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/geometry/test_linestring_geometry.cpp0000664000175000017500000000454211706551765025240 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include #include #include #include #include #include BOOST_AUTO_TEST_SUITE(LineStringGeometry) BOOST_AUTO_TEST_CASE(instantiation) { Osmium::OSM::WayNodeList wnl; Osmium::OSM::WayNode n1(1, Osmium::OSM::Position(1.0, 1.0)); Osmium::OSM::WayNode n2(2, Osmium::OSM::Position(1.0, 2.0)); Osmium::OSM::WayNode n3(3, Osmium::OSM::Position(2.0, 2.0)); wnl.add(n1); wnl.add(n2); wnl.add(n3); Osmium::Geometry::LineString line1(wnl); } BOOST_AUTO_TEST_CASE(output) { Osmium::OSM::WayNodeList wnl; Osmium::OSM::WayNode n1(1, Osmium::OSM::Position(1.9, 1.9)); Osmium::OSM::WayNode n2(2, Osmium::OSM::Position(1.9, 2.9)); Osmium::OSM::WayNode n3(3, Osmium::OSM::Position(2.9, 2.9)); wnl.add(n1); wnl.add(n2); wnl.add(n3); Osmium::Geometry::LineString line1(wnl); Osmium::Geometry::LineString line2(wnl, true); std::ostringstream out_wkt; out_wkt << line1.as_WKT(); BOOST_CHECK_EQUAL(out_wkt.str(), "LINESTRING(1.9 1.9,1.9 2.9,2.9 2.9)"); std::ostringstream out_ewkt; out_ewkt << line1.as_WKT(true); BOOST_CHECK_EQUAL(out_ewkt.str(), "SRID=4326;LINESTRING(1.9 1.9,1.9 2.9,2.9 2.9)"); std::ostringstream out_wkb; out_wkb << line2.as_WKB(); BOOST_CHECK_EQUAL(Osmium::Test::to_hex(out_wkb.str()), "01020000000300000033333333333307403333333333330740666666666666FE3F3333333333330740666666666666FE3F666666666666FE3F"); std::ostringstream out_ewkb; out_ewkb << line2.as_WKB(true); BOOST_CHECK_EQUAL(Osmium::Test::to_hex(out_ewkb.str()), "0102000020E61000000300000033333333333307403333333333330740666666666666FE3F3333333333330740666666666666FE3F666666666666FE3F"); std::ostringstream out_hexwkb; out_hexwkb << line1.as_HexWKB(); BOOST_CHECK_EQUAL(out_hexwkb.str(), "010200000003000000666666666666FE3F666666666666FE3F666666666666FE3F333333333333074033333333333307403333333333330740"); std::ostringstream out_hexewkb; out_hexewkb << line1.as_HexWKB(true); BOOST_CHECK_EQUAL(out_hexewkb.str(), "0102000020E610000003000000666666666666FE3F666666666666FE3F666666666666FE3F333333333333074033333333333307403333333333330740"); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/osm/0000775000175000017500000000000011706551765016342 5ustar daviddavidosmium/test/testgroup_plain/osm/test_position.cpp0000664000175000017500000000325511706551765021756 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include using boost::test_tools::output_test_stream; #include BOOST_AUTO_TEST_SUITE(Position) BOOST_AUTO_TEST_CASE(instantiation_with_default_parameters) { Osmium::OSM::Position p; BOOST_CHECK(!p.defined()); } BOOST_AUTO_TEST_CASE(instantiation_with_double_parameters) { Osmium::OSM::Position p1(1.2, 4.5); BOOST_CHECK(p1.defined()); BOOST_CHECK_EQUAL(p1.x(), 12000000); BOOST_CHECK_EQUAL(p1.y(), 45000000); BOOST_CHECK_EQUAL(p1.lon(), 1.2); BOOST_CHECK_EQUAL(p1.lat(), 4.5); Osmium::OSM::Position p2(p1); BOOST_CHECK_EQUAL(p2.lat(), 4.5); Osmium::OSM::Position p3 = p1; BOOST_CHECK_EQUAL(p3.lat(), 4.5); } BOOST_AUTO_TEST_CASE(equality) { Osmium::OSM::Position p1(1.2, 4.5); Osmium::OSM::Position p2(1.2, 4.5); Osmium::OSM::Position p3(1.5, 1.5); BOOST_CHECK_EQUAL(p1, p2); BOOST_CHECK(p1 != p3); } BOOST_AUTO_TEST_CASE(output) { Osmium::OSM::Position p(-3.2, 47.3); output_test_stream out; out << p; BOOST_CHECK(out.is_equal("(-3.2,47.3)")); } BOOST_AUTO_TEST_CASE(conversion_to_uint32_t) { Osmium::OSM::Position p1(-180.0, -90.0); Osmium::OSM::Position p2(-180.0, 90.0); Osmium::OSM::Position p3( 180.0, 90.0); Osmium::OSM::Position p4( 180.0, -90.0); BOOST_CHECK_EQUAL(64440, static_cast(p1)); BOOST_CHECK_EQUAL( 0, static_cast(p2)); BOOST_CHECK_EQUAL( 359, static_cast(p3)); BOOST_CHECK_EQUAL(64799, static_cast(p4)); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/osm/test_way_node_list.cpp0000664000175000017500000000161011706551765022743 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include BOOST_AUTO_TEST_SUITE(WayNodeList) BOOST_AUTO_TEST_CASE(set_position) { Osmium::OSM::WayNodeList wnl; BOOST_CHECK_EQUAL(wnl.size(), 0); BOOST_CHECK(!wnl.has_position()); Osmium::OSM::WayNode wn(5); wnl.add(wn); BOOST_CHECK_EQUAL(wnl.size(), 1); BOOST_CHECK(!wnl.has_position()); BOOST_CHECK_EQUAL(wnl[0].ref(), 5); wnl.add(17); BOOST_CHECK_EQUAL(wnl.size(), 2); BOOST_CHECK_EQUAL(wnl[1].ref(), 17); wnl.clear(); BOOST_CHECK_EQUAL(wnl.size(), 0); } BOOST_AUTO_TEST_CASE(closed_or_not) { Osmium::OSM::WayNodeList wnl; wnl.add(5); wnl.add(7); wnl.add(8); BOOST_CHECK(!wnl.is_closed()); wnl.add(5); BOOST_CHECK( wnl.is_closed()); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/osm/test_bounds.cpp0000664000175000017500000000222711706551765021402 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include using boost::test_tools::output_test_stream; #include BOOST_AUTO_TEST_SUITE(Bounds) BOOST_AUTO_TEST_CASE(instantiation) { Osmium::OSM::Bounds b; BOOST_CHECK(!b.defined()); BOOST_CHECK(!b.bl().defined()); BOOST_CHECK(!b.tr().defined()); } BOOST_AUTO_TEST_CASE(instantiation_and_extend) { Osmium::OSM::Bounds b; b.extend(Osmium::OSM::Position(1.2, 3.4)); BOOST_CHECK(b.defined()); BOOST_CHECK(b.bl().defined()); BOOST_CHECK(b.tr().defined()); b.extend(Osmium::OSM::Position(3.4, 4.5)); b.extend(Osmium::OSM::Position(5.6, 7.8)); BOOST_CHECK_EQUAL(b.bl(), Osmium::OSM::Position(1.2, 3.4)); BOOST_CHECK_EQUAL(b.tr(), Osmium::OSM::Position(5.6, 7.8)); } BOOST_AUTO_TEST_CASE(output) { Osmium::OSM::Bounds b; b.extend(Osmium::OSM::Position(1.2, 3.4)); b.extend(Osmium::OSM::Position(5.6, 7.8)); output_test_stream out; out << b; BOOST_CHECK(out.is_equal("(1.2,3.4,5.6,7.8)")); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/osm/test_node.cpp0000664000175000017500000000157711706551765021044 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include BOOST_AUTO_TEST_SUITE(Node) BOOST_AUTO_TEST_CASE(instantiation_with_default_parameters) { Osmium::OSM::Node n; BOOST_CHECK_EQUAL(0, n.id()); BOOST_CHECK_EQUAL(-1, n.uid()); } BOOST_AUTO_TEST_CASE(order) { Osmium::OSM::Node n1; Osmium::OSM::Node n2; n1.id(10); n1.version(1); n2.id(15); n2.version(2); BOOST_CHECK_EQUAL(true, n1 < n2); BOOST_CHECK_EQUAL(false, n1 > n2); n1.id(20); n1.version(1); n2.id(20); n2.version(2); BOOST_CHECK_EQUAL(true, n1 < n2); BOOST_CHECK_EQUAL(false, n1 > n2); n1.id(-10); n1.version(2); n2.id(-15); n2.version(1); BOOST_CHECK_EQUAL(true, n1 < n2); BOOST_CHECK_EQUAL(false, n1 > n2); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_plain/osm/test_way_node.cpp0000664000175000017500000000171211706551765021713 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include BOOST_AUTO_TEST_SUITE(WayNode) BOOST_AUTO_TEST_CASE(instantiation_with_default_parameters) { Osmium::OSM::WayNode wn; BOOST_CHECK_EQUAL(wn.ref(), 0); BOOST_CHECK(!wn.has_position()); } BOOST_AUTO_TEST_CASE(instantiation_with_id) { Osmium::OSM::WayNode wn(7); BOOST_CHECK_EQUAL(wn.ref(), 7); } BOOST_AUTO_TEST_CASE(equality) { Osmium::OSM::WayNode wn1(7); Osmium::OSM::WayNode wn2(7); Osmium::OSM::WayNode wn3(9); BOOST_CHECK(wn1 == wn2); BOOST_CHECK(wn1 != wn3); } BOOST_AUTO_TEST_CASE(set_position) { Osmium::OSM::WayNode wn(7); BOOST_CHECK_EQUAL(wn.position(), Osmium::OSM::Position()); wn.position(Osmium::OSM::Position(13.5, -7.2)); BOOST_CHECK_EQUAL(wn.position().lon(), 13.5); BOOST_CHECK(wn.has_position()); } BOOST_AUTO_TEST_SUITE_END() osmium/test/testgroup_geos/0000775000175000017500000000000011706551765015376 5ustar daviddavidosmium/test/testgroup_geos/setup.sh0000664000175000017500000000010711706551765017070 0ustar daviddavidFLAGS="-DOSMIUM_WITH_GEOS `geos-config --cflags` `geos-config --libs`" osmium/test/testgroup_geos/geometry/0000775000175000017500000000000011706551765017231 5ustar daviddavidosmium/test/testgroup_geos/geometry/test_point_geometry.cpp0000664000175000017500000000140511706551765024040 0ustar daviddavid#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include #include #include BOOST_AUTO_TEST_SUITE(PointGeometry) BOOST_AUTO_TEST_CASE(instantiation) { Osmium::OSM::Position pos1(1.2, 3.4); Osmium::Geometry::Point point1(pos1); BOOST_CHECK_EQUAL(point1.lon(), 1.2); BOOST_CHECK_EQUAL(point1.lat(), 3.4); } BOOST_AUTO_TEST_CASE(geos_geometry) { Osmium::OSM::Position pos1(1.2, 3.4); Osmium::Geometry::Point point1(pos1); geos::geom::Point* gp = point1.create_geos_geometry(); BOOST_CHECK(gp); BOOST_CHECK_EQUAL(gp->getX(), 1.2); BOOST_CHECK_EQUAL(gp->getY(), 3.4); delete gp; } BOOST_AUTO_TEST_SUITE_END() osmium/test/broken_way_geometries/0000775000175000017500000000000011706551765016710 5ustar daviddavidosmium/test/broken_way_geometries/test.sh0000775000175000017500000000042111706551765020223 0ustar daviddavid#!/bin/sh # # broken_way_geometries/test.sh # rm -f tmp/way.* mkdir -p tmp ../osmjs/osmjs --debug --location-store=sparsetable --include=../osmjs/js/osm2shape.js --javascript=broken_way_geometries/broken_way_geometries.js broken_way_geometries/broken_way_geometries.osm osmium/test/broken_way_geometries/broken_way_geometries.osm0000664000175000017500000000637211706551765024023 0ustar daviddavid osmium/test/broken_way_geometries/broken_way_geometries.js0000664000175000017500000000035711706551765023636 0ustar daviddavid shapefile('ways'). filename('tmp/ways'). type(LINE). column('id', INTEGER, 10). column('test', STRING, 100). column('note', STRING, 100); way('test'). output('ways'). attr('test'). attr('note'); osmium/test/test_main.cpp0000664000175000017500000000013711706551765015015 0ustar daviddavid#define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE Main #include osmium/test/.gitignore0000664000175000017500000000001211706551765014306 0ustar daviddavidtmp tests osmium/test/run_tests.sh0000775000175000017500000000301311706551765014707 0ustar daviddavid#!/bin/sh # # Compile and run unit tests # # ./run_tests.sh [-v] -- compiles and runs all tests # ./run_tests.sh [-v] DIR|GROUP -- compiles and runs tests in one group # ./run_tests.sh [-v] DIR|GROUP SOME_FILE.CPP -- compiles and runs only one test in one group # # -v -- Run tests under valgrind # set -e CXX="g++" CXXFLAGS="-g -Wall -Wextra -Wredundant-decls -Wdisabled-optimization -pedantic -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo" COMPILE="$CXX -I../include -I. $CXXFLAGS -lboost_unit_test_framework -o tests test_utils.cpp" if [ "x$1" = "x-v" ]; then VALGRIND="valgrind --leak-check=full --show-reachable=yes" shift else VALGRIND="" fi #set -x if [ "x$1" = "x" ]; then for DIR in testgroup_*; do GROUP=${DIR##testgroup_} echo "\nTesting group $GROUP...\n" . $DIR/setup.sh FILES="test_main.cpp $DIR/*/test_*.cpp" echo $COMPILE $FLAGS $FILES $COMPILE $FLAGS $FILES $VALGRIND ./tests done else GROUP=${1##testgroup_} DIR=testgroup_$GROUP . $DIR/setup.sh if [ "x$2" = "x" ]; then echo "\nTesting group $GROUP...\n" FILES="test_main.cpp $DIR/*/test_*.cpp" echo $COMPILE $FLAGS $FILES $COMPILE $FLAGS $FILES $VALGRIND ./tests else echo "\nTesting file $2 in group $GROUP...\n" FILES="-DSTAND_ALONE $DIR/$2" echo $COMPILE $FLAGS $FILES $COMPILE $FLAGS $FILES $VALGRIND ./tests fi fi osmium/test/utf8_clipping/0000775000175000017500000000000011706551765015100 5ustar daviddavidosmium/test/utf8_clipping/test.sh0000775000175000017500000000054111706551765016416 0ustar daviddavid#!/bin/sh # # utf8_clipping/test.sh # rm -f tmp/utf8.* mkdir -p tmp #../osmjs/osmjs --debug --include=../osmjs/js/osm2shape.js --javascript=utf8_clipping/utf8_clipping.js utf8_clipping/utf8_clipping.osm ../osmjs/osmjs --debug --include=utf8_clipping/osm2shape_with_debug.js --javascript=utf8_clipping/utf8_clipping.js utf8_clipping/utf8_clipping.osm osmium/test/utf8_clipping/utf8_clipping.js0000664000175000017500000000036011706551765020210 0ustar daviddavid shapefile('utf8'). filename('tmp/utf8'). type(POINT). column('id', INTEGER, 10). column('note', STRING, 100). column('utf8', STRING, 8); node('utf8'). output('utf8'). attr('note'). attr('utf8'); osmium/test/utf8_clipping/utf8_clipping.osm0000664000175000017500000003224211706551765020376 0ustar daviddavid osmium/test/utf8_clipping/osm2shape_with_debug.js0000664000175000017500000001307211706551765021543 0ustar daviddavid// framework for exporting OSM data to shapefiles // shapefile geometry types var POINT = 'point'; var LINE = 'line'; var POLYGON = 'polygon'; // shapefile attribute types var INTEGER = 'integer'; var STRING = 'string'; var DOUBLE = 'double'; var BOOL = 'bool'; var files = {}; var rules = { node: [], way: [], area: [] }; function shapefile(name) { var shp = { name: name, fname: name, gtype: 'point', columns: [], column_names: {}, type: function(type) { if (type != 'point' && type != 'line' && type != 'polygon') { print('Unknown shapefile geometry type: ' + type); exit(1); } this.gtype = type; return this; }, column: function(name, type, size) { if (type != 'integer' && type != 'string' && type != 'bool' && type != 'double') { print('Unknown attribute type: ' + type); throw("config error"); } if (size == null) { size = 1; } if (size < 0) { print('Size not allowed: ' + size); } var column = { name: name, type: type, size: size }; this.columns.push(column); this.column_names[name] = column; return this; }, filename: function(name) { this.fname = name; return this; } }; files[name] = shp; return shp; } function rule(type, key, value) { if (value == '*') { value = null; } var rule = { type: type, key: key, value: value, file: null, attrs: {}, output: function(name) { if (! files[name]) { print("Unknown shapefile: " + name); throw("config error"); } this.file = name; return this; }, attr: function(attr, key) { if (this.file == null) { print("Output file not set for rule " + key + '=' + value); throw("config error"); } if (! files[this.file].column_names[attr]) { print("There is no column named '" + attr + "' in output file '" + this.file + "'"); throw("config error"); } if (key == null) { key = attr; } this.attrs[attr] = key; return this; } }; rules[type].push(rule); return rule; } function node(key, value) { return rule('node', key, value); } function way(key, value) { return rule('way', key, value); } function area(key, value) { return rule('area', key, value); } function build_func(key, value) { if (value == null) { return function(obj) { return !!obj.tags[key]; }; } else if (typeof(value) == 'string') { if (value == '*') { return function(obj) { return !!obj.tags[key]; }; } else if (value.match(/\|/)) { value = value.split('|'); } else { return function(obj) { return obj.tags[key] && obj.tags[key] == value; }; } } if (value instanceof Array) { return function(obj) { if (! obj.tags[key]) { return false; } for(var i=0; i < value.length; i++) { if (obj.tags[key] == value[i]) { return true; } } return false; }; } else { print("ERROR"); } } Osmium.Callbacks.init = function() { print("Init"); for (var file in files) { var f = files[file]; f.shp = Osmium.Output.Shapefile.open('./' + f.fname, f.gtype); print('Shapefile: ' + file); print(' Filename: ' + f.fname); print(' Geometry type: ' + f.gtype.toUpperCase()); print(' Columns:'); for (var i=0; i < f.columns.length; i++) { var d = f.columns[i]; print(' ' + (d.name + ' ').substr(0, 11) + d.type.toUpperCase() + ' ' + d.size); f.shp.add_field(d.name, d.type, d.size); } print(''); } for (var type in rules) { for (var i=0; i < rules[type].length; i++) { var rule = rules[type][i]; if (rule.file && files[rule.file]) { rule.match = build_func(rule.key, rule.value); } else { print("Unknown shapefile output: " + rule.file); exit(1); } } } } function tags2attributes(id, tags, attrs) { var obj = { id: id }; for (var a in attrs) { obj[a] = tags[attrs[a]]; } return obj; } function check(type, osm_object) { for (var i=0; i < rules[type].length; i++) { var rule = rules[type][i]; if (rule.match(osm_object)) { var a = tags2attributes(osm_object.id, osm_object.tags, rule.attrs); files[rule.file].shp.add(osm_object, a); } } } Osmium.Callbacks.node = function() { print("node id=" + this.id); for (var key in this.tags) { print(" k=|" + key + "| v=|" + this.tags[key] + "| (" + this.tags[key].length + ")" ); } check('node', this); } Osmium.Callbacks.way = function() { check('way', this); } Osmium.Callbacks.multipolygon = function() { check('area', this); } Osmium.Callbacks.end = function() { for (var file in files) { files[file].shp.close(); } print("Done"); } osmium/Doxyfile0000664000175000017500000017417611706551765013074 0ustar daviddavid# Doxyfile 1.5.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = "Osmium" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 0.1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = "doc" # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.hpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = NONE # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = OSMIUM_WITH_GEOS OSMIUM_WITH_SHPLIB OSMIUM_WITH_JAVASCRIPT OSMIUM_WITH_OUTPUT_OSM_XML # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. #TAGFILES = doc/libstdc++.tag=http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. #GENERATE_TAGFILE = doc/osmium.tag # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = YES osmium/NOTES_FOR_DEVELOPERS0000664000175000017500000000521511706551765014422 0ustar daviddavid Notes for Developers ==================== (Read this if you want to contribute to Osmium.) Versioning ========== Osmium is currently considered in beta and doesn't use versioning yet. Proper versions will be introduced as soon as it is somewhat stable. Namespace ========= All Osmium code must be in the "Osmium" namespace or one of its sub-namespaces. There are currently some utility classes not in the Osmium namespace, but this should change. Include-Only ============ Osmium is a include-only library. You can't compile the library itself. There is no libosmium. One drawback ist that you can't have static data in classes, because there is no place to put this data. Coding Conventions ================== These coding conventions have been changing over time and some code is still different. * Class names begin with uppercase chars and use CamelCase. * Macros (and only macros) are all uppercase. * Variables, attributes, and function names are lowercase with underscores_between_words. * Class attribute names start with "m_" (member). * Template parameters start with uppercase "T" and use CamelCase. * Typedefs have names_like_this_t which end in "_t". * Macros should only be used for controlling which parts of the code should be included when compiling. * Use descriptive_variable_names, exceptions are well-established conventions like "i" for a loop variable. * Declare variables where they are first used (C++ style), not at the beginning of a function (old C style). * Names from external namespaces (even "std") are always mentioned explicitly. Do not use "using". Use "make indent" in the toplevel directory to fix indentation. It calls "astyle" with the right parameters. This program is in the "astyle" Debian package. Checking your code ================== The Osmium makefiles use pretty draconian warning options for gcc. (-Wall -Wextra -Wredundant-decls -Wdisabled-optimization -pedantic). This is good. Code should never produce any warnings, even with those settings. Call "make check" in the toplevel directory to check your code. It uses cppcheck which finds some bugs that gcc doesn't. But take the result with a grain of salt, it also sometimes produces wrong warnings. Testing ======= There are a unit tests using the Boost Unit Test Framework in the 'test' directory. Go there and type "./run_tests.sh" to compile and run the tests. Many more tests are needed. Documenting the code ==================== All namespaces, classes, functions, attributes, etc. should be documented. Osmium uses the Doxygen (www.doxygen.org) source code documentation system. Call "make doc" in the toplevel directory to generate the documentation. osmium/include/0000775000175000017500000000000011706551765012771 5ustar daviddavidosmium/include/osmium/0000775000175000017500000000000011706551765014302 5ustar daviddavidosmium/include/osmium/handler/0000775000175000017500000000000011706551765015717 5ustar daviddavidosmium/include/osmium/handler/coordinates_for_ways.hpp0000664000175000017500000000670511706551765022663 0ustar daviddavid#ifndef OSMIUM_HANDLER_COORDINATES_FOR_WAYS_HPP #define OSMIUM_HANDLER_COORDINATES_FOR_WAYS_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include namespace Osmium { namespace Handler { /** * Handler to retrieve locations from nodes and add them to ways. * * @tparam TStorage Class that handles the actual storage of the node locations. * It must support the set(id, value) method and operator[] for * reading a value. */ template class CoordinatesForWays : public Base { public: CoordinatesForWays(TStoragePosIDs& storage_pos, TStorageNegIDs& storage_neg) : m_storage_pos(storage_pos), m_storage_neg(storage_neg) { } /** * Store the location of the node in the storage. */ void node(const shared_ptr& node) { int64_t id = node->id(); if (id >= 0) { m_storage_pos.set( id, node->position()); } else { m_storage_neg.set(-id, node->position()); } } void after_nodes() const { if (Osmium::debug()) { std::cerr << "Memory used for node coordinates storage (approximate):\n for positive IDs: " << m_storage_pos.used_memory() / (1024 * 1024) << " MiB\n for negative IDs: " << m_storage_neg.used_memory() / (1024 * 1024) << " MiB\n"; } } /** * Retrieve locations of all nodes in the way from storage and add * them to the way object. */ void way(const shared_ptr& way) { for (Osmium::OSM::WayNodeList::iterator it = way->nodes().begin(); it != way->nodes().end(); ++it) { const int64_t id = it->ref(); it->position(id >= 0 ? m_storage_pos[id] : m_storage_neg[-id]); } } private: /// Object that handles the actual storage of the node locations (with positive IDs). TStoragePosIDs& m_storage_pos; /// Object that handles the actual storage of the node locations (with negative IDs). TStorageNegIDs& m_storage_neg; }; // class CoordinatesForWays } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_COORDINATES_FOR_WAYS_HPP osmium/include/osmium/handler/find_bbox.hpp0000664000175000017500000000316111706551765020363 0ustar daviddavid#ifndef OSMIUM_HANDLER_FIND_BBOX_HPP #define OSMIUM_HANDLER_FIND_BBOX_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace Handler { class FindBbox : public Base { public: FindBbox() : Base(), m_bounds() { } const Osmium::OSM::Bounds bounds() const { return m_bounds; } void node(const shared_ptr& node) { m_bounds.extend(node->position()); } void after_nodes() const { throw Osmium::Input::StopReading(); } private: Osmium::OSM::Bounds m_bounds; }; // class FindBbox } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_FIND_BBOX_HPP osmium/include/osmium/handler/multipolygon.hpp0000664000175000017500000001622411706551765021177 0ustar daviddavid#ifndef OSMIUM_HANDLER_MULTIPOLYGON_HPP #define OSMIUM_HANDLER_MULTIPOLYGON_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include namespace Osmium { namespace Handler { class Multipolygon : public Base { /// a list of areas that need to be completed std::vector m_areas; // a map from way_id to a vector of indexes into the areas array // this is used to find in which multipolygon relations a way is typedef google::sparse_hash_map > way2areaidx_t; way2areaidx_t m_way2areaidx; bool m_attempt_repair; void (*m_callback_area)(Osmium::OSM::Area*); uint64_t m_count_ways_in_all_areas; public: Multipolygon(bool attempt_repair, void (*callback_area)(Osmium::OSM::Area*)) : Base(), m_areas(), m_way2areaidx(), m_attempt_repair(attempt_repair), m_callback_area(callback_area), m_count_ways_in_all_areas(0) { } // in pass 1 void relation(const shared_ptr& relation) { const char* type = relation->tags().get_tag_by_key("type"); // ignore relations without "type" tag if (!type) { return; } bool is_boundary; if (strcmp(type, "multipolygon") == 0) { is_boundary = false; } else if (strcmp(type, "boundary") == 0) { is_boundary = true; } else { return; } int num_ways = 0; for (osm_sequence_id_t i=0; i < relation->members().size(); i++) { const Osmium::OSM::RelationMember* member = relation->get_member(i); if (member->type() == 'w') { m_way2areaidx[member->ref()].push_back(m_areas.size()); num_ways++; } else { std::cerr << "warning: multipolygon/boundary relation " << relation->id() << " has a non-way member which was ignored\n"; } } m_count_ways_in_all_areas += num_ways; Osmium::OSM::AreaFromRelation* area = new Osmium::OSM::AreaFromRelation(new Osmium::OSM::Relation(*relation), is_boundary, num_ways, m_callback_area, m_attempt_repair); m_areas.push_back(area); } // in pass 1 void after_relations() { if (Osmium::debug()) { std::cerr << "found " << m_areas.size() << " areas (each needs " << sizeof(Osmium::OSM::Area) << " bytes, thats together about " << sizeof(Osmium::OSM::Area) * m_areas.size() / (1024 * 1024) << "MB)\n" << "they used " << m_count_ways_in_all_areas << " ways (each will need " << sizeof(Osmium::OSM::Way) << " bytes, thats in the worst case together about " << sizeof(Osmium::OSM::Way) * m_count_ways_in_all_areas / (1024 * 1024) << "MB)\n"; } } // in pass 2 void way(const shared_ptr& way) { way2areaidx_t::const_iterator way2areaidx_iterator(m_way2areaidx.find(way->id())); if (way2areaidx_iterator == m_way2areaidx.end()) { // not in any relation if (way->is_closed() && way->node_count() >= 4) { // way is closed and has enough nodes, build simple multipolygon #ifdef OSMIUM_WITH_GEOS Osmium::Geometry::Polygon polygon(*way); Osmium::OSM::AreaFromWay* area = new Osmium::OSM::AreaFromWay(way.get(), polygon.create_geos_geometry()); #else Osmium::OSM::AreaFromWay* area = new Osmium::OSM::AreaFromWay(way.get()); #endif // OSMIUM_WITH_GEOS if (Osmium::debug()) { std::cerr << "MP simple way_id=" << way->id() << "\n"; } m_callback_area(area); delete area; } return; } // is in at least one multipolygon relation std::vector v = way2areaidx_iterator->second; if (Osmium::debug()) std::cerr << "MP way_id=" << way->id() << " is in " << v.size() << " areas\n"; // go through all the areas this way is in for (unsigned int i=0; i < v.size(); i++) { Osmium::OSM::AreaFromRelation* area = m_areas[v[i]]; if (!area) { throw std::runtime_error("Zero multipolygon. This should not happen. Reason can be a way appearing more than once in your input file."); } if (Osmium::debug()) { std::cerr << "MP multi way_id=" << way->id() << " is in relation_id=" << area->id() << "\n"; } // store copy of current way in multipolygon area->add_member_way(way.get()); if (area->is_complete()) { area->handle_complete_multipolygon(); m_areas[v[i]] = NULL; delete area; } } } // in pass 2 void after_ways() { m_way2areaidx.clear(); } void init(Osmium::OSM::Meta&) { #ifdef OSMIUM_WITH_MULTIPOLYGON_PROFILING Osmium::OSM::AreaFromRelation::init_timings(); #endif // OSMIUM_WITH_MULTIPOLYGON_PROFILING } void final() { #ifdef OSMIUM_WITH_MULTIPOLYGON_PROFILING Osmium::OSM::AreaFromRelation::print_timings(); #endif // OSMIUM_WITH_MULTIPOLYGON_PROFILING } }; // class Multipolygon } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_MULTIPOLYGON_HPP osmium/include/osmium/handler/range_from_history.hpp0000664000175000017500000000626411706551765022340 0ustar daviddavid#ifndef OSMIUM_HANDLER_RANGE_FROM_HISTORY_HPP #define OSMIUM_HANDLER_RANGE_FROM_HISTORY_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ namespace Osmium { namespace Handler { /** * Handler to extract only objects valid in a given timestamp range. * Use from==to to extract objects valid at a certain time. * * Needs the endtime() to be set in objects, so you have to stack it * after the EndTime() handler. */ template class RangeFromHistory : public Base { public: RangeFromHistory(THandler* handler, time_t from, time_t to) : Base(), m_handler(handler), m_from(from), m_to(to) { } void init(Osmium::OSM::Meta& meta) { m_handler->init(meta); } void before_nodes() { m_handler->before_nodes(); } void node(const shared_ptr& node) { if ((node->endtime() == 0 || node->endtime() >= m_from) && node->timestamp() <= m_to) { m_handler->node(node); } } void after_nodes() { m_handler->after_nodes(); } void before_ways() { m_handler->before_ways(); } void way(const shared_ptr& way) { if ((way->endtime() == 0 || way->endtime() >= m_from) && way->timestamp() <= m_to) { m_handler->way(way); } } void after_ways() { m_handler->after_ways(); } void before_relations() { m_handler->before_relations(); } void relation(const shared_ptr& relation) { if ((relation->endtime() == 0 || relation->endtime() >= m_from) && relation->timestamp() <= m_to) { m_handler->relation(relation); } } void after_relations() { m_handler->after_relations(); } void final() { m_handler->final(); } private: THandler* m_handler; const time_t m_from; const time_t m_to; }; // class RangeFromHistory } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_RANGE_FROM_HISTORY_HPP osmium/include/osmium/handler/progress.hpp0000664000175000017500000001573311706551765020305 0ustar daviddavid#ifndef OSMIUM_HANDLER_PROGRESS_HPP #define OSMIUM_HANDLER_PROGRESS_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace Handler { /** * Simple handler that shows progress on terminal by counting * the number of nodes, ways, and relations already read and * printing those counts to stdout. * * If stdout is not a terminal, nothing is printed. * * Note that this handler will hide the cursor. If the program * is terminated before the final handler is called, it will not * be re-activated. Call show_cursor() from an interrupt * handler or similar, to do this properly. */ class Progress : public Base { uint64_t count_nodes; uint64_t count_ways; uint64_t count_relations; int step; bool is_a_tty; timeval first_node; timeval first_way; timeval first_relation; void update_display(bool show_per_second=true) const { std::cout << "[" << count_nodes << "]"; if (count_ways > 0 || count_relations > 0) { std::cout << " [" << count_ways << "]"; if (count_relations > 0) { std::cout << " [" << count_relations << "]"; } } if (show_per_second) { timeval now; gettimeofday(&now, 0); if (count_relations > 0) { float relation_diff = (now.tv_sec - first_relation.tv_sec) * 1000000 + (now.tv_usec - first_relation.tv_usec); int relations_per_sec = (float)count_relations / relation_diff * 1000000; std::cout << " (" << relations_per_sec << " Relations per second) "; } else if (count_ways > 0) { float way_diff = (now.tv_sec - first_way.tv_sec) * 1000000 + (now.tv_usec - first_way.tv_usec); int ways_per_sec = (float)count_ways / way_diff * 1000000; std::cout << " (" << ways_per_sec << " Ways per second) "; } else if (count_nodes > 0) { float node_diff = (now.tv_sec - first_node.tv_sec) * 1000000 + (now.tv_usec - first_node.tv_usec); int nodes_per_sec = (float)count_nodes / node_diff * 1000000; std::cout << " (" << nodes_per_sec << " Nodes per second) "; } } else { std::cout << " "; } std::cout << "\r"; std::cout.flush(); } public: /** * Initialize handler. * @param s Step, after how many nodes/ways/relations the display * should be updated. (default 1000). */ Progress(int s=1000) : Base(), count_nodes(0), count_ways(0), count_relations(0), step(s), is_a_tty(false), first_node(), first_way(), first_relation() { if (isatty(1)) { is_a_tty = true; } } void hide_cursor() const { std::cout << "\x1b[?25l"; } void show_cursor() const { std::cout << "\x1b[?25h"; } void init(Osmium::OSM::Meta&) const { if (is_a_tty) { hide_cursor(); update_display(); } } void node(const shared_ptr& /*object*/) { if (first_node.tv_sec == 0) { gettimeofday(&first_node, 0); } if (is_a_tty && ++count_nodes % step == 0) { update_display(); } } void way(const shared_ptr& /*object*/) { if (first_way.tv_sec == 0) { gettimeofday(&first_way, 0); } if (is_a_tty && ++count_ways % step == 0) { update_display(); } } void relation(const shared_ptr& /*object*/) { if (first_relation.tv_sec == 0) { gettimeofday(&first_relation, 0); } if (is_a_tty && ++count_relations % step == 0) { update_display(); } } void final() const { if (is_a_tty) { update_display(false); std::cout << std::endl; std::cout << " Average: "; timeval now; gettimeofday(&now, 0); if (count_nodes > 0) { float node_diff = (first_way.tv_sec - first_node.tv_sec) * 1000000 + (first_way.tv_usec - first_node.tv_usec); int nodes_per_sec = (float)count_nodes / node_diff * 1000000; std::cout << nodes_per_sec << " Nodes "; } if (count_ways > 0) { float way_diff = (first_relation.tv_sec - first_way.tv_sec) * 1000000 + (first_relation.tv_usec - first_way.tv_usec); int ways_per_sec = (float)count_ways / way_diff * 1000000; std::cout << ways_per_sec << " Ways "; } if (count_relations > 0) { float relation_diff = (now.tv_sec - first_relation.tv_sec) * 1000000 + (now.tv_usec - first_relation.tv_usec); int relations_per_sec = (float)count_relations / relation_diff * 1000000; std::cout << relations_per_sec << " Relations "; } show_cursor(); std::cout << "per second" << std::endl; std::cout.flush(); } } }; // class Progress } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_PROGRESS_HPP osmium/include/osmium/handler/debug.hpp0000664000175000017500000001227711706551765017527 0ustar daviddavid#ifndef OSMIUM_HANDLER_DEBUG_HPP #define OSMIUM_HANDLER_DEBUG_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ namespace Osmium { namespace Handler { /** * This handler dumps information about each callback and about each * object to stdout. */ class Debug : public Base { public: Debug(bool has_multiple_object_versions=false) : Base(), m_has_multiple_object_versions(has_multiple_object_versions) { } void init(Osmium::OSM::Meta& meta) { std::cout << "meta:\n"; if (meta.has_multiple_object_versions()) { m_has_multiple_object_versions = true; } if (meta.bounds().defined()) { std::cout << " bounds=" << meta.bounds() << "\n"; } } void before_nodes() const { std::cout << "before_nodes\n"; } void node(const shared_ptr& node) const { std::cout << "node:\n"; print_meta(node); const Osmium::OSM::Position& position = node->position(); std::cout << " lon=" << std::fixed << std::setprecision(7) << position.lon() << "\n"; std::cout << " lat=" << std::fixed << std::setprecision(7) << position.lat() << "\n"; } void after_nodes() const { std::cout << "after_nodes\n"; } void before_ways() const { std::cout << "before_ways\n"; } void way(const shared_ptr& way) const { std::cout << "way:\n"; print_meta(way); std::cout << " node_count=" << way->node_count() << "\n"; std::cout << " nodes:\n"; Osmium::OSM::WayNodeList::const_iterator end = way->nodes().end(); for (Osmium::OSM::WayNodeList::const_iterator it = way->nodes().begin(); it != end; ++it) { std::cout << " ref=" << it->ref() << "\n"; } } void after_ways() const { std::cout << "after_ways\n"; } void before_relations() const { std::cout << "before_relations\n"; } void relation(const shared_ptr& relation) const { std::cout << "relation:\n"; print_meta(relation); std::cout << " members: (count=" << relation->members().size() << ")\n"; Osmium::OSM::RelationMemberList::const_iterator end = relation->members().end(); for (Osmium::OSM::RelationMemberList::const_iterator it = relation->members().begin(); it != end; ++it) { std::cout << " type=" << it->type() << " ref=" << it->ref() << " role=|" << it->role() << "|" << "\n"; } } void after_relations() const { std::cout << "after_relations\n"; } void final() const { std::cout << "final\n"; } private: bool m_has_multiple_object_versions; void print_meta(const shared_ptr& object) const { std::cout << " id=" << object->id() << "\n version=" << object->version() << "\n uid=" << object->uid() << "\n user=|" << object->user() << "|" << "\n changeset=" << object->changeset() << "\n timestamp=" << object->timestamp_as_string(); if (m_has_multiple_object_versions) { std::cout << "\n visible=" << (object->visible() ? "yes" : "no") << "\n endtime=" << object->endtime_as_string(); } std::cout << "\n tags: (count=" << object->tags().size() << ")\n"; Osmium::OSM::TagList::const_iterator end = object->tags().end(); for (Osmium::OSM::TagList::const_iterator it = object->tags().begin(); it != end; ++it) { std::cout << " k=|" << it->key() << "| v=|" << it->value() << "|" << "\n"; } } }; // class Debug } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_DEBUG_HPP osmium/include/osmium/handler/endtime.hpp0000664000175000017500000000767611706551765020075 0ustar daviddavid#ifndef OSMIUM_HANDLER_ENDTIME_HPP #define OSMIUM_HANDLER_ENDTIME_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ namespace Osmium { namespace Handler { /** * This handler adds the "end time" to each object by taking the start * time (timestamp) of the next object with the same version number. * It makes only sense to use this handler with history files. */ template class EndTime : public Base { public: EndTime(THandler* handler) : Base(), m_handler(handler) { } void init(Osmium::OSM::Meta& meta) { m_handler->init(meta); } void before_nodes() { m_handler->before_nodes(); } void node(const shared_ptr& node) { if (m_last_node) { if (node->id() == m_last_node->id()) { m_last_node->endtime(node->timestamp()); } m_handler->node(m_last_node); } m_last_node = node; } void after_nodes() { if (m_last_node) { m_handler->node(m_last_node); m_last_node.reset(); } m_handler->after_nodes(); } void before_ways() { m_handler->before_ways(); } void way(const shared_ptr& way) { if (m_last_way) { if (way->id() == m_last_way->id()) { m_last_way->endtime(way->timestamp()); } m_handler->way(m_last_way); } m_last_way = way; } void after_ways() { if (m_last_way) { m_handler->way(m_last_way); m_last_way.reset(); } m_handler->after_ways(); } void before_relations() { m_handler->before_relations(); } void relation(const shared_ptr& relation) { if (m_last_relation) { if (relation->id() == m_last_relation->id()) { m_last_relation->endtime(relation->timestamp()); } m_handler->relation(m_last_relation); } m_last_relation = relation; } void after_relations() { if (m_last_relation) { m_handler->relation(m_last_relation); m_last_relation.reset(); } m_handler->after_relations(); } void final() { m_handler->final(); } private: THandler* m_handler; shared_ptr m_last_node; shared_ptr m_last_way; shared_ptr m_last_relation; }; // class EndTime } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_ENDTIME_HPP osmium/include/osmium/handler/statistics.hpp0000664000175000017500000002205511706551765020626 0ustar daviddavid#ifndef OSMIUM_HANDLER_STATISTICS_HPP #define OSMIUM_HANDLER_STATISTICS_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include namespace Osmium { namespace Handler { /** * Osmium handler that collects basic statistics from OSM data and * writes it to a Sqlite database. */ class Statistics : public Base { public: Statistics() : Base() { // if you change anything in this array, also change the corresponding struct below static const char *sn[] = { "nodes", "nodes_without_tags", "node_tags", "max_node_id", "max_tags_on_node", "ways", "way_tags", "way_nodes", "max_way_id", "max_tags_on_way", "max_nodes_on_way", "closed_ways", "relations", "relation_tags", "relation_members", "max_relation_id", "max_tags_on_relation", "max_members_on_relation", "max_user_id", "anon_user_objects", "max_node_version", "max_way_version", "max_relation_version", "sum_node_version", "sum_way_version", "sum_relation_version", "max_changeset_id", 0 // last element (sentinel) must always be 0 }; m_stat_names = sn; // initialize all statistics to zero for (int i=0; m_stat_names[i]; ++i) { ((uint64_t*) &m_stats)[i] = 0; } } void node(const shared_ptr& node) { update_common_stats(node); m_stats.nodes++; if (m_tag_count == 0) { m_stats.nodes_without_tags++; } if (m_id > (int64_t) m_stats.max_node_id) { m_stats.max_node_id = m_id; } m_stats.node_tags += m_tag_count; if (m_tag_count > (int64_t) m_stats.max_tags_on_node) { m_stats.max_tags_on_node = m_tag_count; } if (m_version > (int64_t) m_stats.max_node_version) { m_stats.max_node_version = m_version; } m_stats.sum_node_version += m_version; } void way(const shared_ptr& way) { update_common_stats(way); m_stats.ways++; if (way->is_closed()) { m_stats.closed_ways++; } if (m_id > (int64_t) m_stats.max_way_id) { m_stats.max_way_id = m_id; } m_stats.way_tags += m_tag_count; m_stats.way_nodes += way->node_count(); if (m_tag_count > (int64_t) m_stats.max_tags_on_way) { m_stats.max_tags_on_way = m_tag_count; } if (way->node_count() > (int64_t) m_stats.max_nodes_on_way) { m_stats.max_nodes_on_way = way->node_count(); } if (m_version > (int64_t) m_stats.max_way_version) { m_stats.max_way_version = m_version; } m_stats.sum_way_version += m_version; } void relation(const shared_ptr& relation) { update_common_stats(relation); m_stats.relations++; if (m_id > (int64_t) m_stats.max_relation_id) { m_stats.max_relation_id = m_id; } m_stats.relation_tags += m_tag_count; osm_sequence_id_t member_count = relation->members().size(); m_stats.relation_members += member_count; if (m_tag_count > (int64_t) m_stats.max_tags_on_relation) { m_stats.max_tags_on_relation = m_tag_count; } if (member_count > (int64_t) m_stats.max_members_on_relation) { m_stats.max_members_on_relation = member_count; } if (m_version > (int64_t) m_stats.max_relation_version) { m_stats.max_relation_version = m_version; } m_stats.sum_relation_version += m_version; } void final() { unlink("count.db"); Sqlite::Database db("count.db"); sqlite3* sqlite_db = db.get_sqlite3(); if (SQLITE_OK != sqlite3_exec(sqlite_db, \ "CREATE TABLE stats (" \ " key TEXT, " \ " value INT64 " \ ");", 0, 0, 0)) { std::cerr << "Database error: " << sqlite3_errmsg(sqlite_db) << "\n"; sqlite3_close(sqlite_db); exit(1); } Sqlite::Statement* statement_insert_into_main_stats = db.prepare("INSERT INTO stats (key, value) VALUES (?, ?);"); db.begin_transaction(); for (int i=0; m_stat_names[i]; ++i) { statement_insert_into_main_stats ->bind_text(m_stat_names[i]) ->bind_int64( ((uint64_t*) &m_stats)[i] ) ->execute(); } statement_insert_into_main_stats ->bind_text("nodes_with_tags") ->bind_int64( ((uint64_t*) &m_stats)[0] - ((uint64_t*) &m_stats)[1] ) ->execute(); db.commit(); delete statement_insert_into_main_stats; } private: // if you change anything in this struct, also change the corresponding array above struct statistics { uint64_t nodes; uint64_t nodes_without_tags; uint64_t node_tags; uint64_t max_node_id; uint64_t max_tags_on_node; uint64_t ways; uint64_t way_tags; uint64_t way_nodes; uint64_t max_way_id; uint64_t max_tags_on_way; uint64_t max_nodes_on_way; uint64_t closed_ways; uint64_t relations; uint64_t relation_tags; uint64_t relation_members; uint64_t max_relation_id; uint64_t max_tags_on_relation; uint64_t max_members_on_relation; uint64_t max_user_id; uint64_t anon_user_objects; uint64_t max_node_version; uint64_t max_way_version; uint64_t max_relation_version; uint64_t sum_node_version; uint64_t sum_way_version; uint64_t sum_relation_version; uint64_t max_changeset_id; } m_stats; const char **m_stat_names; osm_object_id_t m_id; osm_version_t m_version; int m_tag_count; void update_common_stats(const shared_ptr& object) { m_id = object->id(); m_version = object->version(); m_tag_count = object->tags().size(); osm_user_id_t uid = object->uid(); if (uid == 0) { m_stats.anon_user_objects++; } if (uid > (int64_t) m_stats.max_user_id) { m_stats.max_user_id = uid; } osm_changeset_id_t changeset = object->changeset(); if (changeset > (int64_t) m_stats.max_changeset_id) { m_stats.max_changeset_id = changeset; } } }; // class Statistics } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_STATISTICS_HPP osmium/include/osmium/input/0000775000175000017500000000000011706551765015441 5ustar daviddavidosmium/include/osmium/input/xml.hpp0000664000175000017500000002303211706551765016752 0ustar daviddavid#ifndef OSMIUM_INPUT_XML_HPP #define OSMIUM_INPUT_XML_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include #include #include namespace Osmium { namespace Input { /** * Class for parsing OSM XML files. * * Generally you are not supposed to instantiate this class yourself. * Instead create an OSMFile object and call its read() method. * * @tparam THandler A handler class (subclass of Osmium::Handler::Base). */ template class XML : public Base { public: /** * Instantiate XML Parser. * * @param file OSMFile instance. * @param handler Instance of THandler. */ XML(Osmium::OSMFile& file, THandler& handler) : Base(file, handler), m_current_object(NULL), m_in_delete_section(false) { } void parse() { int done; XML_Parser parser = XML_ParserCreate(0); if (!parser) { throw std::runtime_error("Error creating parser"); } XML_SetUserData(parser, this); XML_SetElementHandler(parser, Osmium::Input::XML::start_element_wrapper, Osmium::Input::XML::end_element_wrapper); try { do { void* buffer = XML_GetBuffer(parser, c_buffer_size); if (buffer == 0) { throw std::runtime_error("out of memory"); } int result = read(this->get_fd(), buffer, c_buffer_size); if (result < 0) { exit(1); } done = (result == 0); if (XML_ParseBuffer(parser, result, done) == XML_STATUS_ERROR) { XML_Error errorCode = XML_GetErrorCode(parser); long errorLine = XML_GetCurrentLineNumber(parser); long errorCol = XML_GetCurrentColumnNumber(parser); const XML_LChar *errorString = XML_ErrorString(errorCode); std::stringstream errorDesc; errorDesc << "XML parsing error at line " << errorLine << ":" << errorCol; errorDesc << ": " << errorString; throw std::runtime_error(errorDesc.str()); } } while (!done); XML_ParserFree(parser); this->call_after_and_before_on_handler(UNKNOWN); } catch (Osmium::Input::StopReading) { // if a handler says to stop reading, we do } this->call_final_on_handler(); } private: static const int c_buffer_size = 10240; Osmium::OSM::Object* m_current_object; /** * This is used only for change files which contain create, modify, * and delete sections. */ bool m_in_delete_section; static void XMLCALL start_element_wrapper(void* data, const XML_Char* element, const XML_Char** attrs) { ((Osmium::Input::XML *)data)->start_element(element, attrs); } static void XMLCALL end_element_wrapper(void* data, const XML_Char* element) { ((Osmium::Input::XML *)data)->end_element(element); } void init_object(Osmium::OSM::Object& obj, const XML_Char** attrs) { if (m_in_delete_section) { obj.visible(false); } m_current_object = &obj; for (int count = 0; attrs[count]; count += 2) { if (!strcmp(attrs[count], "lon")) { if (this->m_node) { this->m_node->set_x(atof(attrs[count+1])); } } else if (!strcmp(attrs[count], "lat")) { if (this->m_node) { this->m_node->set_y(atof(attrs[count+1])); } } else { m_current_object->set_attribute(attrs[count], attrs[count+1]); } } } void start_element(const XML_Char* element, const XML_Char** attrs) { // order in the following "if" statements is based on frequency of tags in planet file if (!strcmp(element, "nd")) { for (int count = 0; attrs[count]; count += 2) { if (!strcmp(attrs[count], "ref")) { this->m_way->add_node(atoll(attrs[count+1])); } } } else if (!strcmp(element, "node")) { this->call_after_and_before_on_handler(NODE); init_object(this->prepare_node(), attrs); } else if (!strcmp(element, "tag")) { const char *key = "", *value = ""; for (int count = 0; attrs[count]; count += 2) { if (attrs[count][0] == 'k' && attrs[count][1] == 0) { key = attrs[count+1]; } if (attrs[count][0] == 'v' && attrs[count][1] == 0) { value = attrs[count+1]; } } // XXX assert key, value exist if (m_current_object) { m_current_object->tags().add(key, value); } } else if (!strcmp(element, "way")) { this->call_after_and_before_on_handler(WAY); init_object(this->prepare_way(), attrs); } else if (!strcmp(element, "member")) { char type = 'x'; uint64_t ref = 0; const char *role = ""; for (int count = 0; attrs[count]; count += 2) { if (!strcmp(attrs[count], "type")) { type = (char)attrs[count+1][0]; } else if (!strcmp(attrs[count], "ref")) { ref = atoll(attrs[count+1]); } else if (!strcmp(attrs[count], "role")) { role = (char *)attrs[count+1]; } } // XXX assert type, ref, role are set if (m_current_object && this->m_relation) { this->m_relation->add_member(type, ref, role); } } else if (!strcmp(element, "relation")) { this->call_after_and_before_on_handler(RELATION); init_object(this->prepare_relation(), attrs); } else if (!strcmp(element, "bounds")) { Osmium::OSM::Position min; Osmium::OSM::Position max; for (int count = 0; attrs[count]; count += 2) { if (!strcmp(attrs[count], "minlon")) { min.lon(atof(attrs[count+1])); } else if (!strcmp(attrs[count], "minlat")) { min.lat(atof(attrs[count+1])); } else if (!strcmp(attrs[count], "maxlon")) { max.lon(atof(attrs[count+1])); } else if (!strcmp(attrs[count], "maxlat")) { max.lat(atof(attrs[count+1])); } } this->meta().bounds().extend(min).extend(max); } else if (!strcmp(element, "delete")) { m_in_delete_section = true; } } void end_element(const XML_Char* element) { if (!strcmp(element, "node")) { this->call_node_on_handler(); m_current_object = NULL; } else if (!strcmp(element, "way")) { this->call_way_on_handler(); m_current_object = NULL; } else if (!strcmp(element, "relation")) { this->call_relation_on_handler(); m_current_object = NULL; } else if (!strcmp(element, "delete")) { m_in_delete_section = false; } } }; // class XML } // namespace Input } // namespace Osmium #endif // OSMIUM_INPUT_XML_HPP osmium/include/osmium/input/pbf.hpp0000664000175000017500000005316711706551765016735 0ustar daviddavid#ifndef OSMIUM_INPUT_PBF_HPP #define OSMIUM_INPUT_PBF_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include namespace Osmium { namespace Input { /** * Class for parsing PBF files. * * Generally you are not supposed to instantiate this class yourself. * Instead create an OSMFile object and call its read() method. * * @tparam THandler A handler class (subclass of Osmium::Handler::Base). */ template class PBF : public Base { typedef std::pair array_t; unsigned char m_input_buffer[OSMPBF::max_uncompressed_blob_size]; unsigned char m_unpack_buffer[OSMPBF::max_uncompressed_blob_size]; OSMPBF::Blob m_pbf_blob; OSMPBF::BlobHeader m_pbf_blob_header; OSMPBF::PrimitiveBlock m_pbf_primitive_block; int64_t m_date_factor; public: /** * Instantiate PBF Parser * * @param file OSMFile instance. * @param handler Instance of THandler. */ PBF(OSMFile& file, THandler& handler) : Base(file, handler) { GOOGLE_PROTOBUF_VERIFY_VERSION; } /** * Parse PBF file. * * Will throw a subclass of Osmium::OSMFile::FileTypeError when it * turns out while parsing the file, that it is of the wrong type. */ void parse() { try { while (read_blob_header()) { const array_t a = read_blob(m_pbf_blob_header.datasize()); if (m_pbf_blob_header.type() == "OSMData") { if (!m_pbf_primitive_block.ParseFromArray(a.first, a.second)) { throw std::runtime_error("Failed to parse PrimitiveBlock."); } const OSMPBF::StringTable& stringtable = m_pbf_primitive_block.stringtable(); m_date_factor = m_pbf_primitive_block.date_granularity() / 1000; for (int i=0; i < m_pbf_primitive_block.primitivegroup_size(); ++i) { parse_group(m_pbf_primitive_block.primitivegroup(i), stringtable); } } else if (m_pbf_blob_header.type() == "OSMHeader") { OSMPBF::HeaderBlock pbf_header_block; if (!pbf_header_block.ParseFromArray(a.first, a.second)) { throw std::runtime_error("Failed to parse HeaderBlock."); } bool has_historical_information_feature = false; for (int i=0; i < pbf_header_block.required_features_size(); ++i) { const std::string& feature = pbf_header_block.required_features(i); if (feature == "OsmSchema-V0.6") continue; if (feature == "DenseNodes") continue; if (feature == "HistoricalInformation") { has_historical_information_feature = true; continue; } std::ostringstream errmsg; errmsg << "Required feature not supported: " << feature; throw std::runtime_error(errmsg.str()); } const Osmium::OSMFile::FileType* expected_file_type = this->get_file().get_type(); if (expected_file_type == Osmium::OSMFile::FileType::OSM() && has_historical_information_feature) { throw Osmium::OSMFile::FileTypeOSMExpected(); } if (expected_file_type == Osmium::OSMFile::FileType::History() && !has_historical_information_feature) { throw Osmium::OSMFile::FileTypeHistoryExpected(); } if (pbf_header_block.has_bbox()) { const OSMPBF::HeaderBBox& bbox = pbf_header_block.bbox(); this->meta().bounds().extend(Osmium::OSM::Position((double)bbox.left() / OSMPBF::lonlat_resolution, (double)bbox.bottom() / OSMPBF::lonlat_resolution)); this->meta().bounds().extend(Osmium::OSM::Position((double)bbox.right() / OSMPBF::lonlat_resolution, (double)bbox.top() / OSMPBF::lonlat_resolution)); } } else { if (Osmium::debug()) { std::cerr << "Ignoring unknown blob type (" << m_pbf_blob_header.type().data() << ").\n"; } } } this->call_after_and_before_on_handler(UNKNOWN); } catch (Osmium::Input::StopReading) { // if a handler says to stop reading, we do } this->call_final_on_handler(); } private: /** * Parse one PrimitiveGroup inside a PrimitiveBlock. This function will check what * type of data the group contains (nodes, dense nodes, ways, or relations) and * call the proper parsing function. It will also make sure the right before_* * and after_* methods are called. * * @param group The PrimitiveGroup to parse. * @param stringtable The string table inside the PrimitiveBlock with tags and usernames. */ void parse_group(const OSMPBF::PrimitiveGroup& group, const OSMPBF::StringTable& stringtable) { if (group.has_dense()) { this->call_after_and_before_on_handler(NODE); parse_dense_node_group(group, stringtable, &THandler::node); } else if (group.ways_size() != 0) { this->call_after_and_before_on_handler(WAY); parse_way_group(group, stringtable, &THandler::way); } else if (group.relations_size() != 0) { this->call_after_and_before_on_handler(RELATION); parse_relation_group(group, stringtable, &THandler::relation); } else if (group.nodes_size() != 0) { this->call_after_and_before_on_handler(NODE); parse_node_group(group, stringtable, &THandler::node); } else { throw std::runtime_error("Group of unknown type."); } } // empty specialization to optimize the case where the node() method on the handler is empty void parse_node_group(const OSMPBF::PrimitiveGroup& /*group*/, const OSMPBF::StringTable& /*stringtable*/, void (Osmium::Handler::Base::*)(const shared_ptr&) const) { } template void parse_node_group(const OSMPBF::PrimitiveGroup& group, const OSMPBF::StringTable& stringtable, T) { int max_entity = group.nodes_size(); for (int entity=0; entity < max_entity; ++entity) { Osmium::OSM::Node& node = this->prepare_node(); const OSMPBF::Node& pbf_node = group.nodes(entity); node.id(pbf_node.id()); if (pbf_node.has_info()) { node.version(pbf_node.info().version()) .changeset(pbf_node.info().changeset()) .timestamp(pbf_node.info().timestamp() * m_date_factor) .uid(pbf_node.info().uid()) .user(stringtable.s(pbf_node.info().user_sid()).data()); if (pbf_node.info().has_visible()) { node.visible(pbf_node.info().visible()); } } Osmium::OSM::TagList& tags = node.tags(); for (int tag=0; tag < pbf_node.keys_size(); ++tag) { tags.add(stringtable.s( pbf_node.keys( tag ) ).data(), stringtable.s( pbf_node.vals( tag ) ).data()); } node.position(Osmium::OSM::Position( ( (double) pbf_node.lon() * m_pbf_primitive_block.granularity() + m_pbf_primitive_block.lon_offset() ) / OSMPBF::lonlat_resolution, ( (double) pbf_node.lat() * m_pbf_primitive_block.granularity() + m_pbf_primitive_block.lat_offset() ) / OSMPBF::lonlat_resolution)); this->call_node_on_handler(); } } // empty specialization to optimize the case where the way() method on the handler is empty void parse_way_group(const OSMPBF::PrimitiveGroup& /*group*/, const OSMPBF::StringTable& /*stringtable*/, void (Osmium::Handler::Base::*)(const shared_ptr&) const) { } template void parse_way_group(const OSMPBF::PrimitiveGroup& group, const OSMPBF::StringTable& stringtable, T) { int max_entity = group.ways_size(); for (int entity=0; entity < max_entity; ++entity) { Osmium::OSM::Way& way = this->prepare_way(); const OSMPBF::Way& pbf_way = group.ways(entity); way.id(pbf_way.id()); if (pbf_way.has_info()) { way.version(pbf_way.info().version()) .changeset(pbf_way.info().changeset()) .timestamp(pbf_way.info().timestamp() * m_date_factor) .uid(pbf_way.info().uid()) .user(stringtable.s(pbf_way.info().user_sid()).data()); if (pbf_way.info().has_visible()) { way.visible(pbf_way.info().visible()); } } Osmium::OSM::TagList& tags = way.tags(); for (int tag=0; tag < pbf_way.keys_size(); ++tag) { tags.add(stringtable.s( pbf_way.keys( tag ) ).data(), stringtable.s( pbf_way.vals( tag ) ).data()); } uint64_t ref = 0; for (int i=0; i < pbf_way.refs_size(); ++i) { ref += pbf_way.refs(i); way.add_node(ref); } this->call_way_on_handler(); } } // empty specialization to optimize the case where the relation() method on the handler is empty void parse_relation_group(const OSMPBF::PrimitiveGroup& /*group*/, const OSMPBF::StringTable& /*stringtable*/, void (Osmium::Handler::Base::*)(const shared_ptr&) const) { } template void parse_relation_group(const OSMPBF::PrimitiveGroup& group, const OSMPBF::StringTable& stringtable, T) { int max_entity = group.relations_size(); for (int entity=0; entity < max_entity; ++entity) { Osmium::OSM::Relation& relation = this->prepare_relation(); const OSMPBF::Relation& pbf_relation = group.relations(entity); relation.id(pbf_relation.id()); if (pbf_relation.has_info()) { relation.version(pbf_relation.info().version()) .changeset(pbf_relation.info().changeset()) .timestamp(pbf_relation.info().timestamp() * m_date_factor) .uid(pbf_relation.info().uid()) .user(stringtable.s(pbf_relation.info().user_sid()).data()); if (pbf_relation.info().has_visible()) { relation.visible(pbf_relation.info().visible()); } } Osmium::OSM::TagList& tags = relation.tags(); for (int tag=0; tag < pbf_relation.keys_size(); ++tag) { tags.add(stringtable.s( pbf_relation.keys(tag) ).data(), stringtable.s( pbf_relation.vals(tag) ).data()); } uint64_t ref = 0; for (int i=0; i < pbf_relation.types_size(); ++i) { char type = 'x'; switch (pbf_relation.types(i)) { case OSMPBF::Relation::NODE: type = 'n'; break; case OSMPBF::Relation::WAY: type = 'w'; break; case OSMPBF::Relation::RELATION: type = 'r'; break; } ref += pbf_relation.memids(i); relation.add_member(type, ref, stringtable.s( pbf_relation.roles_sid( i ) ).data()); } this->call_relation_on_handler(); } } // empty specialization to optimize the case where the node() method on the handler is empty void parse_dense_node_group(const OSMPBF::PrimitiveGroup& /*group*/, const OSMPBF::StringTable& /*stringtable*/, void (Osmium::Handler::Base::*)(const shared_ptr&) const) { } template void parse_dense_node_group(const OSMPBF::PrimitiveGroup& group, const OSMPBF::StringTable& stringtable, T) { int64_t last_dense_id = 0; int64_t last_dense_latitude = 0; int64_t last_dense_longitude = 0; int64_t last_dense_uid = 0; int64_t last_dense_user_sid = 0; int64_t last_dense_changeset = 0; int64_t last_dense_timestamp = 0; int last_dense_tag = 0; const OSMPBF::DenseNodes& dense = group.dense(); int max_entity = dense.id_size(); for (int entity=0; entity < max_entity; ++entity) { Osmium::OSM::Node& node = this->prepare_node(); last_dense_id += dense.id(entity); node.id(last_dense_id); if (dense.has_denseinfo()) { last_dense_changeset += dense.denseinfo().changeset(entity); last_dense_timestamp += dense.denseinfo().timestamp(entity); last_dense_uid += dense.denseinfo().uid(entity); last_dense_user_sid += dense.denseinfo().user_sid(entity); node.version(dense.denseinfo().version(entity)); node.changeset(last_dense_changeset); node.timestamp(last_dense_timestamp * m_date_factor); node.uid(last_dense_uid); node.user(stringtable.s(last_dense_user_sid).data()); if (dense.denseinfo().visible_size() > 0) { node.visible(dense.denseinfo().visible(entity)); } } last_dense_latitude += dense.lat(entity); last_dense_longitude += dense.lon(entity); node.position(Osmium::OSM::Position( ( (double) last_dense_longitude * m_pbf_primitive_block.granularity() + m_pbf_primitive_block.lon_offset() ) / OSMPBF::lonlat_resolution, ( (double) last_dense_latitude * m_pbf_primitive_block.granularity() + m_pbf_primitive_block.lat_offset() ) / OSMPBF::lonlat_resolution)); while (last_dense_tag < dense.keys_vals_size()) { int tag_key_pos = dense.keys_vals(last_dense_tag); if (tag_key_pos == 0) { last_dense_tag++; break; } Osmium::OSM::TagList& tags = node.tags(); tags.add(stringtable.s(tag_key_pos).data(), stringtable.s(dense.keys_vals(last_dense_tag+1)).data()); last_dense_tag += 2; } this->call_node_on_handler(); } } /** * Convert 4 bytes from network byte order. */ int convert_from_network_byte_order(unsigned char data[4]) { return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; } /** * Read blob header by first reading the size and then the header * * @returns false for EOF, true otherwise */ bool read_blob_header() { unsigned char size_in_network_byte_order[4]; int offset = 0; while (offset < static_cast(sizeof(size_in_network_byte_order))) { int nread = read(this->get_fd(), size_in_network_byte_order + offset, sizeof(size_in_network_byte_order) - offset); if (nread < 0) { throw std::runtime_error("read error"); } else if (nread == 0) { return false; // EOF } offset += nread; } const int size = convert_from_network_byte_order(size_in_network_byte_order); if (size > OSMPBF::max_blob_header_size || size < 0) { std::ostringstream errmsg; errmsg << "BlobHeader size invalid:" << size; throw std::runtime_error(errmsg.str()); } offset = 0; while (offset < size) { int nread = read(this->get_fd(), m_input_buffer + offset, size - offset); if (nread < 1) { throw std::runtime_error("failed to read BlobHeader"); } offset += nread; } if (!m_pbf_blob_header.ParseFromArray(m_input_buffer, size)) { throw std::runtime_error("failed to parse BlobHeader"); } return true; } /** * Read a (possibly compressed) blob of data. If the blob is compressed, it is uncompressed. */ array_t read_blob(const int size) { if (size < 0 || size > OSMPBF::max_uncompressed_blob_size) { std::ostringstream errmsg; errmsg << "invalid blob size: " << size; throw std::runtime_error(errmsg.str()); } int offset = 0; while (offset < size) { int nread = read(this->get_fd(), m_input_buffer + offset, size - offset); if (nread < 1) { throw std::runtime_error("failed to read blob"); } offset += nread; } if (!m_pbf_blob.ParseFromArray(m_input_buffer, size)) { throw std::runtime_error("failed to parse blob"); } if (m_pbf_blob.has_raw()) { return array_t(m_pbf_blob.raw().data(), m_pbf_blob.raw().size()); } else if (m_pbf_blob.has_zlib_data()) { unsigned long raw_size = m_pbf_blob.raw_size(); assert(raw_size <= static_cast(OSMPBF::max_uncompressed_blob_size)); if (uncompress(m_unpack_buffer, &raw_size, reinterpret_cast(m_pbf_blob.zlib_data().data()), m_pbf_blob.zlib_data().size()) != Z_OK || m_pbf_blob.raw_size() != static_cast(raw_size)) { throw std::runtime_error("zlib error"); } return array_t(m_unpack_buffer, raw_size); } else if (m_pbf_blob.has_lzma_data()) { throw std::runtime_error("lzma blobs not implemented"); } else { throw std::runtime_error("Blob contains no data"); } } }; // class PBF } // namespace Input } // namespace Osmium #endif // OSMIUM_INPUT_PBF_HPP osmium/include/osmium/export.hpp0000664000175000017500000000226611706551765016342 0ustar daviddavid#ifndef OSMIUM_EXPORT_HPP #define OSMIUM_EXPORT_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ namespace Osmium { /** * @brief Classes implementing export into non-OSM formats such as to shapefiles. */ namespace Export { } // namespace Export } // namespace Osmium #ifdef OSMIUM_WITH_JAVASCRIPT # include # include #endif #endif // OSMIUM_EXPORT_HPP osmium/include/osmium/storage/0000775000175000017500000000000011706551765015746 5ustar daviddavidosmium/include/osmium/storage/byid.hpp0000664000175000017500000003052011706551765017406 0ustar daviddavid#ifndef OSMIUM_HANDLER_STORE_HPP #define OSMIUM_HANDLER_STORE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include #include #include #include namespace Osmium { /** * @brief Classes handling storage of data. */ namespace Storage { /** * This abstract class defines an interface to storage classes * intended for storing small pieces of data (such as coordinates) * indexed by a positive object ID. The storage must be very * space efficient and able to scale to billions of objects. * * Subclasses have different implementations that will store the * data in different ways in memory and/or on disk. Some storage * classes are better suited when working with the whole planet, * some are better for data extracts. * * Note that these classes are not required to track "empty" fields. * When reading data you have to be sure you have put something in * there before. */ template class ById : boost::noncopyable { public: virtual ~ById() { } /// The "value" type, usually a coordinates class or similar. typedef TValue value_type; /// Set the field with id to value. virtual void set(uint64_t id, TValue value) = 0; /// Retrieve value by key. Does not check for overflow or empty fields. virtual const TValue& operator[](uint64_t id) const = 0; /** * Get the approximate number of items in the storage. The storage * might allocate memory in blocks, so this size might not be * accurate. You can not use this to find out how much memory the * storage uses. Use used_memory() for that. */ virtual uint64_t size() const = 0; /** * Get the memory used for this storage in bytes. Note that this * is not necessarily entirely accurate but an approximation. * For storage classes that store the data in memory, this is * the main memory used, for storage classes storing data on disk * this is the memory used on disk. */ virtual uint64_t used_memory() const = 0; /** * Clear memory used for this storage. After this you can not * use the storage container any more. */ virtual void clear() = 0; }; /** * The FixedArray storage stores location in a huge array. The size of * the array is given when initializing the object, it must be large * enough to hold all items. * * Only use this store when you know beforehand how many IDs there are. * It is mainly provided for cases where the more flexible Mmap storage * class does not work. * * There is no range checking on accessing the store. * * If you are storing node coordinates, you'll need 8 bytes for each node. * At the time of writing this, the largest node ID is about 1.3 billion, * so you'll need about 10 GB of memory. * * Note that this storage class will only work on 64 bit systems if * used for storing node coordinates. 32 bit systems just can't address * that much memory! */ template class FixedArray : public ById { public: /** * Constructor. * * @param max_id One larger than the largest ID you will ever have. * @exception std::bad_alloc Thrown when there is not enough memory. */ FixedArray(const uint64_t max_id) : ById(), m_size(max_id) { m_items = (TValue*) malloc(sizeof(TValue) * max_id); if (!m_items) { throw std::bad_alloc(); } } ~FixedArray() { clear(); } void set(uint64_t id, TValue value) { m_items[id] = value; } const TValue& operator[](uint64_t id) const { return m_items[id]; } uint64_t size() const { return m_size; } uint64_t used_memory() const { return m_size * sizeof(TValue); } void clear() { free(m_items); m_items = NULL; } private: TValue* m_items; uint64_t m_size; }; // class FixedArray /** * The SparseTable store stores items in a Google sparsetable, * a data structure that can hold sparsly filled tables in a * very space efficient way. It will resize automatically. * * Use this node location store if the ID space is only sparsly * populated, such as when working with smaller OSM files (like * country extracts). */ template class SparseTable : public ById { public: /** * Constructor. * * @param grow_size The initial size of the storage (in items). * The storage will grow by at least this size * every time it runs out of space. */ SparseTable(const uint64_t grow_size=10000) : ById(), m_grow_size(grow_size), m_items(grow_size) { } ~SparseTable() { } void set(uint64_t id, TValue value) { if (id >= m_items.size()) { m_items.resize(id + m_grow_size); } m_items[id] = value; } const TValue& operator[](uint64_t id) const { return m_items[id]; } uint64_t size() const { return m_items.size(); } uint64_t used_memory() const { // unused items use 1 bit, used items sizeof(TValue) bytes // http://google-sparsehash.googlecode.com/svn/trunk/doc/sparsetable.html return (m_items.size() / 8) + (m_items.num_nonempty() * sizeof(TValue)); } void clear() { m_items.clear(); } private: uint64_t m_grow_size; google::sparsetable m_items; }; // class SparseTable /** * The Mmap store stores location using the mmap() system call, * either backed by a file on disk or just in-memory. It will grow * automatically. * * If you have enough memory it is preferred to use the in-memory * version. If you don't have enough memory or want the information * to persist, use the file-backed version. Note that you still need * substantial amounts of memory for this to work efficiently. * * Note that this storage class will only work on 64 bit systems if * used for storing node coordinates. 32 bit systems just can't address * that much memory! */ template class Mmap : public ById { public: static const uint64_t size_increment = 10 * 1024 * 1024; /** * Create anonymous mapping without a backing file. * @exception std::bad_alloc Thrown when there is not enough memory. */ Mmap() : ById(), m_size(size_increment), m_fd(-1) { m_items = (TValue*) mmap(NULL, sizeof(TValue) * m_size, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (m_items == MAP_FAILED) { throw std::bad_alloc(); } } /** * Create mapping backed by file. If filename is empty, a temporary * file will be created. * * @param filename The filename (including the path) for the storage. * @param remove Should the file be removed after use? * @exception std::bad_alloc Thrown when there is not enough memory or some other problem. */ Mmap(std::string& filename, bool remove=true) : ById(), m_size(1) { if (filename == "") { FILE* file = tmpfile(); if (!file) { throw std::bad_alloc(); } m_fd = fileno(file); } else { m_fd = open(filename.c_str(), O_RDWR | O_CREAT, 0600); } if (m_fd < 0) { throw std::bad_alloc(); } // now that the file is open we can immediately remove it // (temporary files are always removed) if (remove && filename != "") { if (unlink(filename.c_str()) < 0) { // XXX what to do here? } } // make sure the file is at least as large as the initial size if (get_file_size() < sizeof(TValue) * m_size) { if (ftruncate(m_fd, sizeof(TValue) * m_size) < 0) { throw std::bad_alloc(); } } m_items = (TValue*) mmap(NULL, sizeof(TValue) * m_size, PROT_READ|PROT_WRITE, MAP_SHARED, m_fd, 0); if (m_items == MAP_FAILED) { throw std::bad_alloc(); } } ~Mmap() { clear(); } void set(uint64_t id, TValue value) { if (id >= m_size) { uint64_t new_size = id + size_increment; // if there is a file backing this mmap and its smaller than needed, increase its size if (m_fd >= 0 && get_file_size() < sizeof(TValue) * new_size) { if (ftruncate(m_fd, sizeof(TValue) * new_size) < 0) { throw std::bad_alloc(); } } m_items = (TValue*) mremap(m_items, sizeof(TValue) * m_size, sizeof(TValue) * new_size, MREMAP_MAYMOVE); if (m_items == MAP_FAILED) { throw std::bad_alloc(); } m_size = new_size; } m_items[id] = value; } const TValue& operator[](uint64_t id) const { return m_items[id]; } uint64_t size() const { return m_size; } uint64_t used_memory() const { return m_size * sizeof(TValue); } void clear() { munmap(m_items, sizeof(TValue) * m_size); } private: uint64_t m_size; int m_fd; TValue* m_items; /// Get file size in bytes. uint64_t get_file_size() { struct stat s; if (fstat(m_fd, &s) < 0) { throw std::bad_alloc(); } return s.st_size; } }; // class Mmap } // namespace Storage } // namespace Osmium #endif // OSMIUM_HANDLER_STORE_HPP osmium/include/osmium/storage/objectstore.hpp0000664000175000017500000002156311706551765021011 0ustar daviddavid#ifndef OSMIUM_STORAGE_OBJECTSTORE_HPP #define OSMIUM_STORAGE_OBJECTSTORE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include namespace Osmium { namespace Storage { /** * Stores Nodes, Ways, and Relations in main memory. Can store multiple * versions of the same object. Storage is ordered by id and version. * * The object store uses the handler interface, so storage is simply by * calling the node(), way(), and relation() methods like in any other * handler. * * Note that Osmium OSM objects are rather larger, so this store can use * a lot of memory. In many cases you don't need the whole object but only * parts of it, so using a more space efficient storage might be possible. */ class ObjectStore : public Osmium::Handler::Base { public: ObjectStore() : Base(), m_nodes(), m_ways(), m_relations() { } /** * Insert shared_ptr of Node into object store. */ void node(const shared_ptr& node) { m_nodes.insert(node); } /** * Insert shared_ptr of Way into object store. */ void way(const shared_ptr& way) { m_ways.insert(way); } /** * Insert shared_ptr of Relation into object store. */ void relation(const shared_ptr& relation) { m_relations.insert(relation); } /** * Remove all nodes from object store. */ void clear_nodes() { m_nodes.clear(); } /** * Remove all ways from object store. */ void clear_ways() { m_ways.clear(); } /** * Remove all relations from object store. */ void clear_relations() { m_relations.clear(); } /** * Remove all objects from object store. */ void clear() { clear_nodes(); clear_ways(); clear_relations(); } /** * Feed contents of object store to the given handler. Because * objects are stored ordered by id and version, they will be * fed to the handler in order. * * If clear is set, all nodes/ways/relations are removed from the * object store after the after_nodes/ways/relations() call to the * handler. * * @tparam THandler Handler class. * @param handler Pointer to handler. * @param meta Reference to Osmium::OSM::Meta object which will be given to init() method of handler. * @param clear Should objects be cleared from the object store? Default is true. */ template void feed_to(THandler* handler, Osmium::OSM::Meta& meta, bool clear=true) { handler->init(meta); handler->before_nodes(); std::for_each(m_nodes.begin(), m_nodes.end(), boost::bind(&THandler::node, handler, _1)); handler->after_nodes(); if (clear) { clear_nodes(); } handler->before_ways(); std::for_each(m_ways.begin(), m_ways.end(), boost::bind(&THandler::way, handler, _1)); handler->after_ways(); if (clear) { clear_ways(); } handler->before_relations(); std::for_each(m_relations.begin(), m_relations.end(), boost::bind(&THandler::relation, handler, _1)); handler->after_relations(); if (clear) { clear_relations(); } handler->final(); } private: typedef std::set > nodeset; typedef std::set > wayset; typedef std::set > relationset; nodeset m_nodes; wayset m_ways; relationset m_relations; public: /** * Handler that inserts objects from the store in the right * position in the stream of objects it gets and forwards all * objects to another handler. * * Do not change the object store while this handler is active. */ template class ApplyHandler : public Osmium::Handler::Forward { public: ApplyHandler(ObjectStore& os, THandler* handler, Osmium::OSM::Meta& meta) : Osmium::Handler::Forward(handler), m_object_store(os), m_handler(handler), m_meta(meta), m_nodes_iter(os.m_nodes.begin()), m_nodes_end(os.m_nodes.end()), m_ways_iter(os.m_ways.begin()), m_ways_end(os.m_ways.end()), m_relations_iter(os.m_relations.begin()), m_relations_end(os.m_relations.end()) { } void init(const Osmium::OSM::Meta&) { m_handler->init(m_meta); } void node(const shared_ptr& node) { while (m_nodes_iter != m_nodes_end && **m_nodes_iter < *node) { m_handler->node(*m_nodes_iter++); } m_handler->node(node); } void after_nodes() { while (m_nodes_iter != m_nodes_end) { m_handler->node(*m_nodes_iter++); } m_handler->after_nodes(); m_object_store.clear_nodes(); } void way(const shared_ptr& way) { while (m_ways_iter != m_ways_end && **m_ways_iter < *way) { m_handler->way(*m_ways_iter++); } m_handler->way(way); } void after_ways() { while (m_ways_iter != m_ways_end) { m_handler->way(*m_ways_iter++); } m_handler->after_ways(); m_object_store.clear_ways(); } void relation(const shared_ptr& relation) { while (m_relations_iter != m_relations_end && **m_relations_iter < *relation) { m_handler->relation(*m_relations_iter++); } m_handler->relation(relation); } void after_relations() { while (m_relations_iter != m_relations_end) { m_handler->relation(*m_relations_iter++); } m_handler->after_relations(); m_object_store.clear_relations(); } private: ObjectStore& m_object_store; THandler* m_handler; Osmium::OSM::Meta& m_meta; ObjectStore::nodeset::iterator m_nodes_iter; ObjectStore::nodeset::iterator m_nodes_end; ObjectStore::wayset::iterator m_ways_iter; ObjectStore::wayset::iterator m_ways_end; ObjectStore::relationset::iterator m_relations_iter; ObjectStore::relationset::iterator m_relations_end; }; // class ApplyHandler }; // class ObjectStore } // namespace Storage } // namespace Osmium #endif // OSMIUM_STORAGE_OBJECTSTORE_HPP osmium/include/osmium/javascript/0000775000175000017500000000000011706551765016450 5ustar daviddavidosmium/include/osmium/javascript/template.hpp0000664000175000017500000001445411706551765021004 0ustar daviddavid#ifndef OSMIUM_JAVASCRIPT_TEMPLATE_HPP #define OSMIUM_JAVASCRIPT_TEMPLATE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include namespace Osmium { /** * @brief %Javascript support for %Osmium. */ namespace Javascript { /** * Base class for all Javascript template classes. Javascript * template classes describe templates from which Javascript * objects can be created, so for every C++ class that should * be accessible from Javascript there is a corresponding * template class. * * Note that Javascript templates have nothing to do with C++ * templates. */ class Template { public: template static T& get() { static T t; return t; } /** * Create a Javascript object instance from the Javascript template * wrapping a C++ object. */ v8::Local create_instance(void* wrapped) { v8::Local instance = js_template->NewInstance(); instance->SetInternalField(0, v8::External::New(wrapped)); return instance; } template v8::Persistent create_persistent_instance(TWrapped* wrapped) { v8::Persistent instance = v8::Persistent::New(create_instance(wrapped)); instance.MakeWeak(wrapped, Osmium::Javascript::Template::free_instance); return instance; } template static void free_instance(v8::Persistent instance, void* obj) { instance.Dispose(); delete static_cast(obj); } /** * Function that always returns undefined. */ v8::Handle js_undefined(const v8::Arguments& /*args*/) { return v8::Undefined(); } /* These magic helper function are used to connect Javascript methods to C++ methods. They are given to the SetAccessor, SetIndexedPropertyHandler and SetNamedPropertyHandler functions of a v8::ObjectTemplate object, respectively. The first template argument is the class of the object we want to access, for instance Osmium::OSM::Node. The second template argument is the member function on the object that we want to call when this function is called from Javascript. */ template (TObject::*func)() const> static v8::Handle accessor_getter(v8::Local, const v8::AccessorInfo &info) { return (( reinterpret_cast(v8::Local::Cast(info.Holder()->GetInternalField(0))->Value()) )->*(func))(); } template (TObject::*func)(v8::Local) const> static v8::Handle named_property_getter(v8::Local property, const v8::AccessorInfo &info) { return (( reinterpret_cast(v8::Local::Cast(info.Holder()->GetInternalField(0))->Value()) )->*(func))(property); } template (TObject::*func)(uint32_t) const> static v8::Handle indexed_property_getter(uint32_t index, const v8::AccessorInfo &info) { return (( reinterpret_cast(v8::Local::Cast(info.Holder()->GetInternalField(0))->Value()) )->*(func))(index); } template (TObject::*func)(uint32_t)> static v8::Handle indexed_property_getter(uint32_t index, const v8::AccessorInfo &info) { return (( reinterpret_cast(v8::Local::Cast(info.Holder()->GetInternalField(0))->Value()) )->*(func))(index); } template (TObject::*func)() const> static v8::Handle property_enumerator(const v8::AccessorInfo &info) { return (( reinterpret_cast(v8::Local::Cast(info.Holder()->GetInternalField(0))->Value()) )->*(func))(); } template (TObject::*func)(const v8::Arguments&)> static v8::Handle function_template(const v8::Arguments& args) { return (( reinterpret_cast(v8::Local::Cast(args.Holder()->GetInternalField(0))->Value()) )->*(func))(args); } protected: v8::Persistent js_template; /** * Constructor. */ Template(int field_count=1) { js_template = v8::Persistent::New(v8::ObjectTemplate::New()); js_template->SetInternalFieldCount(field_count); } ~Template() { js_template.Dispose(); } private: // copy constructor and assignment operator are private and can't be used Template(const Template&); Template& operator=(const Template&); }; // class Template } // namespace Javascript } // namespace Osmium #endif // OSMIUM_JAVASCRIPT_TEMPLATE_HPP osmium/include/osmium/CGAlgorithms.h0000664000175000017500000001437211706551765017005 0ustar daviddavid/********************************************************************** * $Id: CGAlgorithms.h 1820 2006-09-06 16:54:23Z mloskot $ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2005-2006 Refractions Research Inc. * Copyright (C) 2001-2002 Vivid Solutions Inc. * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * ********************************************************************** * * Last port: algorithm/CGAlgorithms.java rev. 1.34 (JTS-1.7.1) * **********************************************************************/ #ifndef GEOS_ALGORITHM_CGALGORITHM_H #define GEOS_ALGORITHM_CGALGORITHM_H #include // Forward declarations namespace geos { namespace geom { class Coordinate; class CoordinateSequence; } } namespace geos { namespace algorithm { // geos::algorithm /** * \brief * Specifies and implements various fundamental Computational Geometric * algorithms. * The algorithms supplied in this class are robust for double-precision * floating point. * */ class CGAlgorithms { public: enum { CLOCKWISE=-1, COLLINEAR, COUNTERCLOCKWISE }; enum { RIGHT=-1, LEFT, STRAIGHT }; CGAlgorithms(){}; /** \brief * Test whether a point lies inside a ring. * * The ring may be oriented in either direction. * If the point lies on the ring boundary the result * of this method is unspecified. * * This algorithm does not attempt to first check the * point against the envelope of the ring. * * @param p point to check for ring inclusion * @param ring assumed to have first point identical to last point * @return true if p is inside ring */ static bool isPointInRing(const geom::Coordinate& p, const geom::CoordinateSequence* ring); /// Same as above, but taking a vector of const Coordinates (faster) static bool isPointInRing(const geom::Coordinate& p, const std::vector& ring); /** \brief * Test whether a point lies on a linestring. * * @return true true if * the point is a vertex of the line or lies in the interior of a line * segment in the linestring */ static bool isOnLine(const geom::Coordinate& p, const geom::CoordinateSequence* pt); /** \brief * Computes whether a ring defined by an array of Coordinate is * oriented counter-clockwise. * * - The list of points is assumed to have the first and last * points equal. * - This will handle coordinate lists which contain repeated points. * * This algorithm is only guaranteed to work with valid rings. * If the ring is invalid (e.g. self-crosses or touches), * the computed result may not be correct. * * @param ring an array of coordinates forming a ring * @return true if the ring is oriented counter-clockwise. */ static bool isCCW(const geom::CoordinateSequence* ring); /** \brief * Computes the orientation of a point q to the directed line * segment p1-p2. * * The orientation of a point relative to a directed line * segment indicates which way you turn to get to q after * travelling from p1 to p2. * * @return 1 if q is counter-clockwise from p1-p2 * @return -1 if q is clockwise from p1-p2 * @return 0 if q is collinear with p1-p2 */ static int computeOrientation(const geom::Coordinate& p1, const geom::Coordinate& p2, const geom::Coordinate& q); /** \brief * Computes the distance from a point p to a line segment AB * * Note: NON-ROBUST! * * @param p the point to compute the distance for * @param A one point of the line * @param B another point of the line (must be different to A) * @return the distance from p to line segment AB */ static double distancePointLine(const geom::Coordinate& p, const geom::Coordinate& A, const geom::Coordinate& B); /** \brief * Computes the perpendicular distance from a point p * to the (infinite) line containing the points AB * * @param p the point to compute the distance for * @param A one point of the line * @param B another point of the line (must be different to A) * @return the distance from p to line AB */ static double distancePointLinePerpendicular(const geom::Coordinate& p, const geom::Coordinate& A, const geom::Coordinate& B); /** \brief * Computes the distance from a line segment AB to a line segment CD * * Note: NON-ROBUST! * * @param A a point of one line * @param B the second point of (must be different to A) * @param C one point of the line * @param D another point of the line (must be different to A) */ static double distanceLineLine(const geom::Coordinate& A, const geom::Coordinate& B, const geom::Coordinate& C, const geom::Coordinate& D); /** \brief * Returns the signed area for a ring. The area is positive if * the ring is oriented CW. */ static double signedArea(const geom::CoordinateSequence* ring); /** \brief * Computes the length of a linestring specified by a sequence * of points. * * @param pts the points specifying the linestring * @return the length of the linestring */ static double length(const geom::CoordinateSequence* pts); /** \brief * Returns the index of the direction of the point q * relative to a vector specified by p1-p2. * * @param p1 the origin point of the vector * @param p2 the final point of the vector * @param q the point to compute the direction to * * @return 1 if q is counter-clockwise (left) from p1-p2 * @return -1 if q is clockwise (right) from p1-p2 * @return 0 if q is collinear with p1-p2 */ static int orientationIndex(const geom::Coordinate& p1, const geom::Coordinate& p2, const geom::Coordinate& q); }; } // namespace geos::algorithm } // namespace geos #endif // GEOS_ALGORITHM_CGALGORITHM_H /********************************************************************** * $Log$ * Revision 1.2 2006/05/02 14:51:53 strk * Added port info and fixed doxygen comments for CGAlgorithms class * * Revision 1.1 2006/03/09 16:46:48 strk * geos::geom namespace definition, first pass at headers split * **********************************************************************/ osmium/include/osmium/osmfile_impl.hpp0000664000175000017500000000337011706551765017475 0ustar daviddavid#ifndef OSMIUM_OSMFILE_IMPL_HPP #define OSMIUM_OSMFILE_IMPL_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { template void OSMFile::read(T& handler) { Osmium::Input::Base* input = m_encoding->is_pbf() ? static_cast*>(new Osmium::Input::PBF(*this, handler)) : static_cast*>(new Osmium::Input::XML(*this, handler)); input->parse(); delete input; } Osmium::Output::Base *OSMFile::create_output_file() { Osmium::Output::Base *output = NULL; if (m_encoding->is_pbf()) { output = new Osmium::Output::PBF(*this); } else { #ifdef OSMIUM_WITH_OUTPUT_OSM_XML output = new Osmium::Output::XML(*this); #endif } return output; } } // namespace Osmium #endif // OSMIUM_OSMFILE_IMPL_HPP osmium/include/osmium/handler.hpp0000664000175000017500000001054511706551765016435 0ustar daviddavid#ifndef OSMIUM_HANDLER_HPP #define OSMIUM_HANDLER_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include namespace Osmium { /** * @brief Handlers operate on %OSM data through callbacks. * * All handlers should use Osmium::Handler::Base as a public * base class. See its documentation for details. */ namespace Handler { /** * Base class for all handler classes. * Defines empty methods that can be overwritten in child classes. * * To define your own handler create a subclass of this class. * Only overwrite the methods you actually use. They must be declared public. * If you overwrite the constructor, call the Base constructor without arguments. */ class Base : boost::noncopyable { public: Base() { } void init(Osmium::OSM::Meta&) const { } void before_nodes() const { } void node(const shared_ptr&) const { } void after_nodes() const { } void before_ways() const { } void way(const shared_ptr&) const { } void after_ways() const { } void before_relations() const { } void relation(const shared_ptr&) const { } void after_relations() const { } void area(Osmium::OSM::Area*) const { } void final() const { } }; // class Base /** * This handler forwards all calls to another handler. * Use this as a base for your handler instead of Base() if you want calls * forwarded by default. */ template class Forward : public Base { public: Forward(THandler* handler) : Base(), m_handler(handler) { } void init(Osmium::OSM::Meta& meta) const { m_handler->init(meta); } void before_nodes() const { m_handler->before_nodes(); } void node(const shared_ptr& node) const { m_handler->node(node); } void after_nodes() const { m_handler->after_nodes(); } void before_ways() const { m_handler->before_ways(); } void way(const shared_ptr& way) const { m_handler->way(way); } void after_ways() const { m_handler->after_ways(); } void before_relations() const { m_handler->before_relations(); } void relation(const shared_ptr& relation) const { m_handler->relation(relation); } void after_relations() const { m_handler->after_relations(); } void area(Osmium::OSM::Area* area) const { m_handler->area(area); } void final() const { m_handler->final(); } private: THandler* m_handler; }; // class Forward } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_HPP osmium/include/osmium/input.hpp0000664000175000017500000002172111706551765016155 0ustar daviddavid#ifndef OSMIUM_INPUT_HPP #define OSMIUM_INPUT_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include using std::tr1::shared_ptr; using std::tr1::static_pointer_cast; using std::tr1::const_pointer_cast; using std::tr1::dynamic_pointer_cast; using boost::make_shared; #include #include namespace Osmium { /** * @brief %Input classes parse %OSM files and call a handler on the data they read. */ namespace Input { /** * Handlers can throw this exception to show that they are done. * When a handler, for instance, is only interested in nodes, it * can throw this in the after_nodes() method. The parser will * stop reading the input file after this. * * Note that when you write a handler that calls other handlers * that can throw this, you might have to catch this exception * in your handler. */ class StopReading { }; /** * Virtual base class for all input classes. * * The THandler template parameter of this class (and child classes) * names a policy class on which methods will be called. The class * should implement one or more of the following functions: * * - init(Osmium::OSM::Meta&) * - before_nodes/ways/relations() * - node/way/relation(const shared_ptr&) * - after_nodes/ways/relations() * - final() * - area(Osmium::OSM::Area*) * * init() will be called before all others, final() * after all others. * * For every object node(), way(), or * relation() will be called, respectively. * * When there are several objects of the same type in a row the * before_*() function will be called before them and the * after_*() function after them. If your input file is * sorted as OSM files normally are, i.e. all nodes, then all ways, * then all relations, this will call before_nodes() once, * then for all the nodes node(), then after_nodes(), * then before_ways(), and so on. * This will also work properly if the input file contains, say, first * all relations, than all ways and then all nodes. * * But if you have nodes, ways, and relations intermixed in an input * file these handlers will probably not called in a useful way for you. * You can use osmosis --sort to sort your input file first. * * The method area() is special. It will only be called if * you have the multipolygon handler before your handler. There are no * before/after_areas() methods. Use init() and * final() instead. */ template class Base : boost::noncopyable { public: virtual ~Base() { } /** * Parse an OSM input file. This is a pure virtual function, * it must be overwritten in a child class of Osmium::Input::Base. */ virtual void parse() = 0; protected: Base(Osmium::OSMFile& file, THandler& handler) : m_last_object_type(UNKNOWN), m_file(file), m_handler(handler), m_meta(), m_node(), m_way(), m_relation() { m_meta.has_multiple_object_versions(m_file.has_multiple_object_versions()); m_file.open_for_input(); } void call_after_and_before_on_handler(osm_object_type_t current_object_type) { if (current_object_type != m_last_object_type) { switch (m_last_object_type) { case NODE: m_handler.after_nodes(); break; case WAY: m_handler.after_ways(); break; case RELATION: m_handler.after_relations(); break; default: break; } switch (current_object_type) { case NODE: if (m_last_object_type == UNKNOWN) { m_handler.init(m_meta); } m_handler.before_nodes(); break; case WAY: m_handler.before_ways(); break; case RELATION: m_handler.before_relations(); break; default: break; } m_last_object_type = current_object_type; } } void call_node_on_handler() const { m_handler.node(m_node); } void call_way_on_handler() const { m_handler.way(m_way); } void call_relation_on_handler() const { m_handler.relation(m_relation); } void call_final_on_handler() const { m_handler.final(); } Osmium::OSM::Meta& meta() { return m_meta; } int get_fd() const { return m_file.get_fd(); } const Osmium::OSMFile& get_file() const { return m_file; } /* The following methods prepare the m_node/way/relation member variable for use. If it is empty or in use by somebody other than this parser, a new object will be allocated. If it not is use, it will be reset to it's pristine state by calling the destructor directly and then placement new. This gets around a memory deallocation and re-allocation which was timed to slow down the program noticably. */ Osmium::OSM::Node& prepare_node() { if (m_node && m_node.unique()) { m_node->~Node(); new (m_node.get()) Osmium::OSM::Node(); } else { m_node = make_shared(); } return *m_node; } Osmium::OSM::Way& prepare_way() { if (m_way && m_way.unique()) { m_way->~Way(); new (m_way.get()) Osmium::OSM::Way(2000); } else { m_way = make_shared(2000); } return *m_way; } Osmium::OSM::Relation& prepare_relation() { if (m_relation && m_relation.unique()) { m_relation->~Relation(); new (m_relation.get()) Osmium::OSM::Relation(); } else { m_relation = make_shared(); } return *m_relation; } private: /** * The last object type we read (before the current one). * Used to properly call before and after methods. */ osm_object_type_t m_last_object_type; /** * The OSMFile we opened this file with. */ Osmium::OSMFile m_file; /** * Handler we will call callbacks on. */ THandler& m_handler; Osmium::OSM::Meta m_meta; protected: shared_ptr m_node; shared_ptr m_way; shared_ptr m_relation; }; // class Base } // namespace Input } // namespace Osmium #include #include #endif // OSMIUM_INPUT_HPP osmium/include/osmium/output.hpp0000664000175000017500000000364411706551765016362 0ustar daviddavid#ifndef OSMIUM_OUTPUT_HPP #define OSMIUM_OUTPUT_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { /** * @brief Classes for writing %OSM files. */ namespace Output { class Base : public Osmium::Handler::Base { protected: Osmium::OSMFile m_file; int get_fd() { return m_file.get_fd(); } public: Base(Osmium::OSMFile& file) : m_file(file) { m_file.open_for_output(); } virtual ~Base() { } virtual void init(Osmium::OSM::Meta&) = 0; virtual void node(const shared_ptr&) = 0; virtual void way(const shared_ptr&) = 0; virtual void relation(const shared_ptr&) = 0; virtual void final() = 0; }; // class Base } // namespace Output } // namespace Osmium #include #ifdef OSMIUM_WITH_OUTPUT_OSM_XML # include #endif #endif // OSMIUM_OUTPUT_HPP osmium/include/osmium/utils/0000775000175000017500000000000011706551765015442 5ustar daviddavidosmium/include/osmium/utils/delta.hpp0000664000175000017500000000270011706551765017243 0ustar daviddavid#ifndef OSMIUM_UTILS_DELTA_HPP #define OSMIUM_UTILS_DELTA_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include namespace Osmium { /** * This class models a variable that keeps track of the value * it was last set to and returns the delta between old and * new value from the update() call. */ template class Delta { public: Delta() : m_value(0) { } void clear() { m_value = 0; } T update(T new_value) { std::swap(m_value, new_value); return m_value - new_value; } private: T m_value; }; } #endif // OSMIUM_UTILS_DELTA_HPP osmium/include/osmium/utils/sqlite.hpp0000664000175000017500000001371111706551765017457 0ustar daviddavid#ifndef OSMIUM_UTILS_SQLITE_HPP #define OSMIUM_UTILS_SQLITE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include namespace Osmium { /** * @brief The %Sqlite classes wrap the %Sqlite C library. */ namespace Sqlite { /** * Exception returned by Sqlite wrapper classes when there are errors in the Sqlite3 lib */ class Exception : public std::runtime_error { public: Exception(const std::string &msg, const std::string &error) : std::runtime_error(msg + ": " + error + '\n') { } }; class Statement; /** * Wrapper class for Sqlite database */ class Database { private: sqlite3* db; public: Database(const char* filename) { if (sqlite3_open_v2(filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0)) { sqlite3_close(db); throw Sqlite::Exception("Can't open database", errmsg()); } } ~Database() { sqlite3_close(db); } const std::string &errmsg() const { static std::string error = std::string(sqlite3_errmsg(db)); return error; } sqlite3* get_sqlite3() { return db; } void begin_transaction() { if (SQLITE_OK != sqlite3_exec(db, "BEGIN TRANSACTION;", 0, 0, 0)) { std::cerr << "Database error: " << sqlite3_errmsg(db) << "\n"; sqlite3_close(db); exit(1); } } void commit() { if (SQLITE_OK != sqlite3_exec(db, "COMMIT;", 0, 0, 0)) { std::cerr << "Database error: " << sqlite3_errmsg(db) << "\n"; sqlite3_close(db); exit(1); } } Statement* prepare(const char* sql); }; // class Database /** * Wrapper class for Sqlite prepared statement. */ class Statement { private: Database* db_; sqlite3_stmt* statement; int bindnum; public: Statement(Database* db, const char* sql) : db_(db), statement(0), bindnum(1) { sqlite3_prepare_v2(db->get_sqlite3(), sql, -1, &statement, 0); if (statement == 0) { throw Sqlite::Exception("Can't prepare statement", db_->errmsg()); } } ~Statement() { sqlite3_finalize(statement); } Statement* bind_null() { if (SQLITE_OK != sqlite3_bind_null(statement, bindnum++)) { throw Sqlite::Exception("Can't bind null value", db_->errmsg()); } return this; } Statement* bind_text(const char* value) { if (SQLITE_OK != sqlite3_bind_text(statement, bindnum++, value, -1, SQLITE_STATIC)) { throw Sqlite::Exception("Can't bind text value", db_->errmsg()); } return this; } Statement* bind_text(const std::string& value) { if (SQLITE_OK != sqlite3_bind_text(statement, bindnum++, value.c_str(), -1, SQLITE_STATIC)) { throw Sqlite::Exception("Can't bind text value", db_->errmsg()); } return this; } Statement* bind_int(int value) { if (SQLITE_OK != sqlite3_bind_int(statement, bindnum++, value)) { throw Sqlite::Exception("Can't bind int value", db_->errmsg()); } return this; } Statement* bind_int64(int64_t value) { if (SQLITE_OK != sqlite3_bind_int64(statement, bindnum++, value)) { throw Sqlite::Exception("Can't bind int64 value", db_->errmsg()); } return this; } Statement* bind_double(double value) { if (SQLITE_OK != sqlite3_bind_double(statement, bindnum++, value)) { throw Sqlite::Exception("Can't bind double value", db_->errmsg()); } return this; } Statement* bind_blob(const void* value, int length) { if (SQLITE_OK != sqlite3_bind_blob(statement, bindnum++, value, length, 0)) { throw Sqlite::Exception("Can't bind blob value", db_->errmsg()); } return this; } void execute() { sqlite3_step(statement); if (SQLITE_OK != sqlite3_reset(statement)) { throw Sqlite::Exception("Can't execute statement", db_->errmsg()); } bindnum = 1; } }; // class Statement inline Statement* Database::prepare(const char* sql) { return new Statement(this, sql); } } // namespace Sqlite } // namespace Osmium #endif // OSMIUM_UTILS_SQLITE_HPP osmium/include/osmium/utils/unicode.hpp0000664000175000017500000001150411706551765017602 0ustar daviddavid#ifndef OSMIUM_UTILS_UNICODE_HPP #define OSMIUM_UTILS_UNICODE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include namespace Osmium { /* These unicode conversion functions are used to convert UTF-8 to UTF-16 and then into a v8::String and back, because the functions that v8 has for this do not handle characters outside the Basic Multilingual Plane (>16bit) properly. */ /// Parent exception class for Unicode conversion errors. class Unicode_Conversion_Error { public: UErrorCode error_code; Unicode_Conversion_Error(UErrorCode ec) : error_code(ec) { } /// Is this a buffer overflow? bool buffer_overflow() const { return error_code == U_BUFFER_OVERFLOW_ERROR; } }; /// Exception thrown when a UTF-8 to UTF-16 conversion failed. class UTF8_to_UTF16_Conversion_Error : public Unicode_Conversion_Error { public: UTF8_to_UTF16_Conversion_Error(UErrorCode ec) : Unicode_Conversion_Error(ec) { } }; /// Exception thrown when a UTF-16 to UTF-8 conversion failed. class UTF16_to_UTF8_Conversion_Error : public Unicode_Conversion_Error { public: UTF16_to_UTF8_Conversion_Error(UErrorCode ec) : Unicode_Conversion_Error(ec) { } }; /** * Convert C string with UTF-8 codes into v8::String. * * @exception UTF8_to_UTF16_Conversion_Error Thrown if the conversion failed. * @tparam characters Maximum number of Unicode characters. * @param cstring A NULL terminated C string. * @return A local handle to a v8 String. */ template v8::Local utf8_to_v8_String(const char *cstring) { UErrorCode error_code = U_ZERO_ERROR; UChar dest[characters*2]; int32_t dest_length; u_strFromUTF8(dest, characters*2, &dest_length, cstring, -1, &error_code); if (error_code != U_ZERO_ERROR) { throw UTF8_to_UTF16_Conversion_Error(error_code); } return v8::String::New(dest, dest_length); } /** * Convert v8::String into C string with UTF-8 codes. * * @exception UTF16_to_UTF8_Conversion_Error Thrown if the conversion failed. * @tparam characters Maximum number of Unicode characters. * @param string A v8::String. * @return Returns a pointer to a static buffer with a NULL terminated C string. */ template const char *v8_String_to_utf8(v8::Local string) { UErrorCode error_code = U_ZERO_ERROR; uint16_t src[characters*2]; static char buffer[characters*4]; int32_t buffer_length; string->Write(src, 0, characters*2); u_strToUTF8(buffer, characters*4, &buffer_length, src, std::min(characters*2, string->Length()), &error_code); if (error_code != U_ZERO_ERROR) { throw UTF16_to_UTF8_Conversion_Error(error_code); } return buffer; } // this function does not work without the inline. strange. /** * Sends v8::String to output stream. This will first convert it to a UTF-8 string. * * @exception UTF16_to_UTF8_Conversion_Error Thrown if the conversion failed. * @param string A v8::String. * @param os A reference to an output stream. */ inline void v8_String_to_ostream(v8::Local string, std::ostream &os) { UErrorCode error_code = U_ZERO_ERROR; int length = 4 * (string->Length() + 1); uint16_t *src = (uint16_t *) malloc(length); if (!src) { throw std::bad_alloc(); } char *buffer = (char *) malloc(length); if (!buffer) { throw std::bad_alloc(); } int32_t buffer_length; string->Write(src); u_strToUTF8(buffer, length, &buffer_length, src, string->Length(), &error_code); if (error_code != U_ZERO_ERROR) { throw UTF16_to_UTF8_Conversion_Error(error_code); } os << buffer; free(buffer); free(src); } } // namespace Osmium #endif // OSMIUM_UTILS_UNICODE_HPP osmium/include/osmium/utils/stringtable.hpp0000664000175000017500000001355511706551765020502 0ustar daviddavid#ifndef OSMIUM_UTILS_STRINGTABLE_HPP #define OSMIUM_UTILS_STRINGTABLE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include namespace Osmium { /** * StringTable management for PBF writer * * All strings are stored as indexes to rows in a StringTable. The StringTable contains * one row for each used string, so strings that are used multiple times need to be * stored only once. The StringTable is sorted by usage-count, so the most often used * string is stored at index 1. */ class StringTable { /// type for string IDs (interim and final) typedef uint16_t string_id_t; /** * this is the struct used to build the StringTable. It is stored as * the value-part in the strings-map. * * when a new string is added to the map, its count is set to 0 and * the interim_id is set to the current size of the map. This interim_id * is then stored into the pbf-objects. * * before the PrimitiveBlock is serialized, the map is sorted by count * and stored into the pbf-StringTable. Afterwards the interim-ids are * mapped to the "real" id in the StringTable. * * this way often used strings get lower ids in the StringTable. As the * protobuf-serializer stores numbers in variable bit-lengths, lower * IDs means less used space in the resulting file. */ struct string_info { /** * number of occurrences of this string */ uint16_t count; /** * an intermediate-id */ string_id_t interim_id; }; friend bool operator<(const string_info& lhs, const string_info& rhs) { return lhs.count > rhs.count; } /** * Interim StringTable, storing all strings that should be written to * the StringTable once the block is written to disk. */ typedef std::map string2string_info_t; string2string_info_t m_strings; /** * This vector is used to map the interim IDs to real StringTable IDs after * writing all strings to the StringTable. */ typedef std::vector interim_id2id_t; interim_id2id_t m_id2id_map; int m_size; public: StringTable() : m_strings(), m_id2id_map(), m_size(0) { } /** * record a string in the interim StringTable if it's missing, otherwise just increase its counter, * return the interim-id assigned to the string. */ string_id_t record_string(const std::string& string) { string_info& info = m_strings[string]; if (info.interim_id == 0) { info.interim_id = ++m_size; } else { info.count++; } return info.interim_id; } template static std::pair flip_pair(const std::pair& p) { return std::pair(p.second, p.first); } /** * Sort the interim StringTable and store it to the real protobuf StringTable. * while storing to the real table, this function fills the id2id_map with * pairs, mapping the interim-ids to final and real StringTable ids. * * Note that the m_strings table is a std::map and as such is sorted lexicographically. * When the transformation into the sortedby multimap is done, it gets sorted by * the count. The end result (at least with the glibc standard container/algorithm * implementation) is that the string table is sorted first by reverse count (ie descending) * and then by reverse lexicographic order. */ void store_stringtable(OSMPBF::StringTable* st) { typedef std::multimap cmap; cmap sortedbycount; m_id2id_map.resize(m_size+1); std::transform(m_strings.begin(), m_strings.end(), std::inserter(sortedbycount, sortedbycount.begin()), flip_pair); int n=0; cmap::const_iterator end=sortedbycount.end(); for (cmap::const_iterator it = sortedbycount.begin(); it != end; ++it) { // add the string of the current item to the pbf StringTable st->add_s(it->second); // store the mapping from the interim-id to the real id m_id2id_map[it->first.interim_id] = ++n; } } /** * Map from an interim ID to a real string ID. */ string_id_t map_string_id(const string_id_t interim_id) const { return m_id2id_map[interim_id]; } /** * Clear the stringtable, preparing for the next block. */ void clear() { m_strings.clear(); m_size = 0; } }; // class StringTable } // namespace Osmium #endif // OSMIUM_UTILS_STRINGTABLE_HPP osmium/include/osmium/utils/timer.h0000664000175000017500000000754311706551765016744 0ustar daviddavid/* * BSD licensed from http://sites.google.com/site/jivsoft/Home/ (Ken Wilder) */ #ifndef TIMER_H #define TIMER_H #include #include #include class timer { friend std::ostream& operator<<(std::ostream& os, timer& t); private: bool running; clock_t start_clock; time_t start_time; double acc_time; double elapsed_time(); public: // 'running' is initially false. A timer needs to be explicitly started // using 'start' or 'restart' timer() : running(false), start_clock(0), start_time(0), acc_time(0) { } void start(const char* msg = 0); void restart(const char* msg = 0); void stop(const char* msg = 0); void check(const char* msg = 0); }; // class timer //=========================================================================== // Return the total time that the timer has been in the "running" // state since it was first "started" or last "restarted". For // "short" time periods (less than an hour), the actual cpu time // used is reported instead of the elapsed time. inline double timer::elapsed_time() { time_t acc_sec = time(0) - start_time; if (acc_sec < 3600) return (clock() - start_clock) / (1.0 * CLOCKS_PER_SEC); else return (1.0 * acc_sec); } // timer::elapsed_time //=========================================================================== // Start a timer. If it is already running, let it continue running. // Print an optional message. inline void timer::start(const char* msg) { // Print an optional message, something like "Starting timer t"; if (msg) std::cout << msg << std::endl; // Return immediately if the timer is already running if (running) return; // Set timer status to running and set the start time running = true; start_clock = clock(); start_time = time(0); } // timer::start //=========================================================================== // Turn the timer off and start it again from 0. Print an optional message. inline void timer::restart(const char* msg) { // Print an optional message, something like "Restarting timer t"; if (msg) std::cout << msg << std::endl; // Set timer status to running, reset accumulated time, and set start time running = true; acc_time = 0; start_clock = clock(); start_time = time(0); } // timer::restart //=========================================================================== // Stop the timer and print an optional message. inline void timer::stop(const char* msg) { // Print an optional message, something like "Stopping timer t"; if (msg) std::cout << msg << std::endl; // Compute accumulated running time and set timer status to not running if (running) acc_time += elapsed_time(); running = false; } // timer::stop //=========================================================================== // Print out an optional message followed by the current timer timing. inline void timer::check(const char* msg) { // Print an optional message, something like "Checking timer t"; if (msg) std::cout << msg << " : "; std::cout << "Elapsed time [" << std::setiosflags(std::ios::fixed) << std::setprecision(2) << acc_time + (running ? elapsed_time() : 0) << "] seconds" << std::endl; } // timer::check //=========================================================================== // Allow timers to be printed to ostreams using the syntax 'os << t' // for an ostream 'os' and a timer 't'. For example, "cout << t" will // print out the total amount of time 't' has been "running". inline std::ostream& operator<<(std::ostream& os, timer& t) { os << std::setprecision(2) << std::setiosflags(std::ios::fixed) << t.acc_time + (t.running ? t.elapsed_time() : 0); return os; } //=========================================================================== #endif // TIMER_H osmium/include/osmium/utils/timestamp.hpp0000664000175000017500000000565211706551765020166 0ustar daviddavid#ifndef OSMIUM_UTILS_TIMESTAMP_HPP #define OSMIUM_UTILS_TIMESTAMP_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace Utils { /** * Contains some helper functions to convert timestamps from time_t to * the ISO format used by OSM and back. */ class Timestamp { static const int timestamp_length = 20 + 1; // length of ISO timestamp string yyyy-mm-ddThh:mm:ssZ\0 /** * The timestamp format for OSM timestamps in strftime(3) format. * This is the ISO-Format yyyy-mm-ddThh:mm:ssZ */ static const char* timestamp_format() { static const char f[] = "%Y-%m-%dT%H:%M:%SZ"; return f; } /// Constructor is private, this class is not supposed to be instantiated Timestamp() { } public: static std::string to_iso(time_t timestamp) { if (timestamp == 0) { return std::string(""); } struct tm* tm = gmtime(×tamp); std::string s(timestamp_length, '\0'); /* This const_cast is ok, because we know we have enough space in the string for the format we are using (well at least until the year will have 5 digits). And by setting the size afterwards from the result of strftime we make sure thats set right, too. */ s.resize(strftime(const_cast(s.c_str()), timestamp_length, timestamp_format(), tm)); return s; } static time_t parse_iso(const char* timestamp) { struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; if (strptime(timestamp, Osmium::Utils::Timestamp::timestamp_format(), &tm) == NULL) { throw std::invalid_argument("can't parse timestamp"); } return timegm(&tm); } }; // class Timestamp } // namespace Utils } // namespace Osmium #endif // OSMIUM_UTILS_TIMESTAMP_HPP osmium/include/osmium/export/0000775000175000017500000000000011706551765015623 5ustar daviddavidosmium/include/osmium/export/csv.hpp0000664000175000017500000000511111706551765017125 0ustar daviddavid#ifndef OSMIUM_EXPORT_CSV_HPP #define OSMIUM_EXPORT_CSV_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #ifdef OSMIUM_WITH_JAVASCRIPT # include #endif // OSMIUM_WITH_JAVASCRIPT namespace Osmium { namespace Export { class CSV { public: std::ofstream out; CSV(const char *filename) { out.open(filename); } ~CSV() { out.flush(); out.close(); } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void *)this); } v8::Handle js_print(const v8::Arguments& args) { for (int i = 0; i < args.Length(); i++) { if (i != 0) { out << '\t'; } Osmium::v8_String_to_ostream(args[i]->ToString(), out); } out << std::endl; return v8::Integer::New(1); } v8::Handle js_close(const v8::Arguments& /*args*/) { out.flush(); out.close(); return v8::Undefined(); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->Set("print", v8::FunctionTemplate::New(function_template)); js_template->Set("close", v8::FunctionTemplate::New(function_template)); } }; #endif // OSMIUM_WITH_JAVASCRIPT }; // class CSV } // namespace Export } // namespace Osmium #endif // OSMIUM_EXPORT_CSV_HPP osmium/include/osmium/export/shapefile.hpp0000664000175000017500000005014711706551765020303 0ustar daviddavid#ifndef OSMIUM_EXPORT_SHAPEFILE_HPP #define OSMIUM_EXPORT_SHAPEFILE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #ifdef OSMIUM_WITH_SHPLIB #include #include #include #include namespace Osmium { namespace Export { class Shapefile : boost::noncopyable { // the following limits are defined by the shapefile spec static const unsigned int max_dbf_fields = 16; static const unsigned int max_dbf_field_name_length = 11; static const int max_dbf_field_length = 255; class Field { public: Field(const std::string& name, DBFFieldType type, int width=1, int decimals=0) : m_name(name), m_type(type), m_width(width), m_decimals(decimals) { if (name == "" || name.size() > max_dbf_field_name_length) { throw std::invalid_argument("field name must be between 1 and 11 characters long"); } } const std::string& name() const { return m_name; } DBFFieldType type() const { return m_type; } int width() const { return m_width; } int decimals() const { return m_decimals; } private: std::string m_name; DBFFieldType m_type; int m_width; int m_decimals; }; public: virtual ~Shapefile() { close(); } void close() { if (m_dbf_handle) { DBFClose(m_dbf_handle); m_dbf_handle = 0; } if (m_shp_handle) { SHPClose(m_shp_handle); m_shp_handle = 0; } } /** * Add a field to a shapefile. */ void add_field(Field& field) { if (m_fields.size() < max_dbf_fields) { int field_num = DBFAddField(m_dbf_handle, field.name().c_str(), field.type(), field.width(), field.decimals()); if (field_num != (int)m_fields.size()) { throw std::runtime_error("Failed to add field:" + field.name()); } m_fields.push_back(field); } else { throw std::out_of_range("Can't have more than 16 fields in a shapefile."); } } /** * Add a field to a shapefile. */ void add_field(const std::string& name, ///< The name of the field (1 to 11 characters long) DBFFieldType type, ///< The type of the field (FT_STRING, FT_INTEGER, FT_DOUBLE, or FT_BOOL) int width=1, ///< The width of the field (number of digits for ints and doubles) int decimals=0 ///< The precision of double fields (otherwise ignored) ) { Field field(name, type, width, decimals); add_field(field); } /** * Add a field to a shapefile. */ void add_field(const std::string& name, ///< The name of the field (1 to 11 characters long) const std::string& type, ///< The type of the field ("string", "integer", "double", or "bool") int width=1, ///< The width of the field (number of digits for ints and doubles) int decimals=0 ///< The precision of double fields (otherwise ignored) ) { DBFFieldType ftype; if (type == "string") { ftype = FTString; decimals = 0; } else if (type == "integer") { ftype = FTInteger; decimals = 0; } else if (type == "double") { ftype = FTDouble; } else if (type == "bool") { ftype = FTLogical; width = 1; decimals = 0; } else { throw std::runtime_error("Unknown field type:" + type); } add_field(name, ftype, width, decimals); } /** * Add a new geometry (shape object) to the Shapefile. You have to call * this first for every new shape. After that you call add_attribute() * for all the attributes. * * @param shp_object A pointer to the shape object to be added. The object * will be freed for you by calling SHPDestroyObject()! * @exception Osmium::Exception::IllegalGeometry If shp_object is NULL or * the type of geometry does not fit the type of the * shapefile. */ void add_geometry(SHPObject* shp_object) { if (!shp_object || shp_object->nSHPType != m_shp_handle->nShapeType) { throw Osmium::Exception::IllegalGeometry(); } m_current_shape = SHPWriteObject(m_shp_handle, -1, shp_object); if (m_current_shape == -1 && errno == EINVAL) { // second chance if likely cause is having reached the 2GB limit close(); m_sequence_number++; open(); m_current_shape = SHPWriteObject(m_shp_handle, -1, shp_object); } if (m_current_shape == -1) { throw std::runtime_error("error writing to shapefile"); } SHPDestroyObject(shp_object); } void add_attribute(const int field, const bool value) const { int ok = DBFWriteLogicalAttribute(m_dbf_handle, m_current_shape, field, value ? 'T' : 'F'); if (!ok) { throw std::runtime_error(std::string("Can't add bool to field")); } } void add_attribute(const int field, const int value) const { int ok = DBFWriteIntegerAttribute(m_dbf_handle, m_current_shape, field, value); if (!ok) { throw std::runtime_error(std::string("Can't add integer to field")); } } void add_attribute(const int field, const std::string& value) const { int ok = DBFWriteStringAttribute(m_dbf_handle, m_current_shape, field, value.c_str()); if (!ok) { throw std::runtime_error(std::string("Can't add string to field")); } } void add_attribute(const int field, const char *value) const { int ok = DBFWriteStringAttribute(m_dbf_handle, m_current_shape, field, value); if (!ok) { throw std::runtime_error(std::string("Can't add char* to field")); } } void add_attribute(const int field) const { int ok = DBFWriteNULLAttribute(m_dbf_handle, m_current_shape, field); if (!ok) { throw std::runtime_error(std::string("Can't add null to field")); } } // truncates UTF8 string to fit in shape field void add_attribute_with_truncate(const int field, const char* value) { char dest[max_dbf_field_length+1]; size_t length = m_fields[field].width(); memset(dest, 0, length+1); strncpy(dest, value, length); size_t i = length-1; if (dest[i] & 128) { if (dest[i] & 64) { dest[i] = '\0'; } else if ((dest[i-1] & 224) == 224) { dest[i-1] = '\0'; } else if ((dest[i-2] & 240) == 240) { dest[i-2] = '\0'; } } add_attribute(field, dest); } void add_attribute_with_truncate(const int field, const std::string& value) { add_attribute_with_truncate(field, value.c_str()); } #ifdef OSMIUM_WITH_JAVASCRIPT int add_string_attribute(int n, v8::Local value) const { uint16_t source[(max_dbf_field_length+2)*2]; char dest[(max_dbf_field_length+1)*4]; memset(source, 0, (max_dbf_field_length+2)*4); memset(dest, 0, (max_dbf_field_length+1)*4); int32_t dest_length; UErrorCode error_code = U_ZERO_ERROR; value->ToString()->Write(source, 0, max_dbf_field_length+1); u_strToUTF8(dest, m_fields[n].width(), &dest_length, source, std::min(max_dbf_field_length+1, value->ToString()->Length()), &error_code); if (error_code == U_BUFFER_OVERFLOW_ERROR) { // thats ok, it just means we clip the text at that point } else if (U_FAILURE(error_code)) { throw std::runtime_error("UTF-16 to UTF-8 conversion failed"); } return DBFWriteStringAttribute(m_dbf_handle, m_current_shape, n, dest); } int add_logical_attribute(int n, v8::Local value) const { v8::String::Utf8Value str(value); if (atoi(*str) == 1 || !strncasecmp(*str, "T", 1) || !strncasecmp(*str, "Y", 1)) { return DBFWriteLogicalAttribute(m_dbf_handle, m_current_shape, n, 'T'); } else if ((!strcmp(*str, "0")) || !strncasecmp(*str, "F", 1) || !strncasecmp(*str, "N", 1)) { return DBFWriteLogicalAttribute(m_dbf_handle, m_current_shape, n, 'F'); } else { return DBFWriteNULLAttribute(m_dbf_handle, m_current_shape, n); } } /** * Add a geometry to the shapefile. */ bool add(Osmium::Geometry::Geometry* geometry, ///< the geometry v8::Local attributes) { ///< a %Javascript object (hash) with the attributes try { add_geometry(geometry->create_shp_object()); } catch (Osmium::Exception::IllegalGeometry) { return false; } int ok = 0; for (size_t n=0; n < m_fields.size(); n++) { v8::Local key = v8::String::New(m_fields[n].name().c_str()); if (attributes->HasRealNamedProperty(key)) { v8::Local value = attributes->GetRealNamedProperty(key); if (value->IsUndefined() || value->IsNull()) { DBFWriteNULLAttribute(m_dbf_handle, m_current_shape, n); } else { switch (m_fields[n].type()) { case FTString: ok = add_string_attribute(n, value); break; case FTInteger: ok = DBFWriteIntegerAttribute(m_dbf_handle, m_current_shape, n, value->Int32Value()); break; case FTDouble: throw std::runtime_error("fields of type double not implemented"); break; case FTLogical: ok = add_logical_attribute(n, value); break; default: ok = 0; // should never be here break; } if (!ok) { std::string errmsg("failed to add attribute '"); errmsg += m_fields[n].name(); errmsg += "'\n"; throw std::runtime_error(errmsg); } } } else { DBFWriteNULLAttribute(m_dbf_handle, m_current_shape, n); } } return true; } v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void*)this); } v8::Handle js_add_field(const v8::Arguments& args) { if (args.Length() < 3 || args.Length() > 4) { throw std::runtime_error("Wrong number of arguments to add_field method."); } v8::String::Utf8Value name(args[0]); std::string sname(*name); v8::String::Utf8Value type(args[1]); std::string stype(*type); int width = args[2]->Int32Value(); int decimals = (args.Length() == 4) ? args[3]->Int32Value() : 0; add_field(sname, stype, width, decimals); return v8::Integer::New(1); } v8::Handle js_add(const v8::Arguments& args) { if (args.Length() != 2) { throw std::runtime_error("Wrong number of arguments to add method."); } v8::Local xxx = v8::Local::Cast(args[0]); Osmium::Geometry::Geometry* geometry = (Osmium::Geometry::Geometry*) v8::Local::Cast(xxx->GetInternalField(0))->Value(); try { add(geometry, v8::Local::Cast(args[1])); } catch (Osmium::Exception::IllegalGeometry) { std::cerr << "Ignoring object with illegal geometry." << std::endl; return v8::Integer::New(0); } return v8::Integer::New(1); } v8::Handle js_close(const v8::Arguments& /*args*/) { close(); return v8::Undefined(); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->Set("add_field", v8::FunctionTemplate::New(function_template)); js_template->Set("add", v8::FunctionTemplate::New(function_template)); js_template->Set("close", v8::FunctionTemplate::New(function_template)); } }; #endif // OSMIUM_WITH_JAVASCRIPT protected: /** * The constructor for Shapefile is protected. Use one of * PointShapefile, LineShapefile, or PolygonShapefile. */ Shapefile(const std::string& filename, int type) : m_filename_base(filename), m_fields(), m_type(type), m_sequence_number(0) { open(); } private: /// base filename const std::string m_filename_base; /// fields in DBF std::vector m_fields; // handles to the shapelib objects SHPHandle m_shp_handle; DBFHandle m_dbf_handle; /// entity number of the shape we are currently writing int m_current_shape; /// shapefile type int m_type; /// shapefile sequence number for auto-overflow (0=first) int m_sequence_number; /** * Open and initialize all files belonging to shapefile (.shp/shx/dbf/prj/cpg). * Uses m_filename_base and m_sequence_number plus suffix to build filename. */ void open() { std::ostringstream filename; filename << m_filename_base; if (m_sequence_number) { filename << "_" << m_sequence_number; } m_shp_handle = SHPCreate(filename.str().c_str(), m_type); if (m_shp_handle == 0) { throw std::runtime_error("Can't open shapefile: " + filename.str() + ".shp/shx"); } m_dbf_handle = DBFCreate(filename.str().c_str()); if (m_dbf_handle == 0) { throw std::runtime_error("Can't open shapefile: " + filename.str() + ".dbf"); } std::ofstream file; file.open((filename.str() + ".prj").c_str()); if (file.fail()) { throw std::runtime_error("Can't open shapefile: " + filename.str() + ".prj"); } file << "GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]]" << std::endl; file.close(); file.open((filename.str() + ".cpg").c_str()); if (file.fail()) { throw std::runtime_error("Can't open shapefile: " + filename.str() + ".cpg"); } file << "UTF-8" << std::endl; file.close(); // If any fields are defined already, add them here. This will do nothing if // called from the constructor. for (std::vector::const_iterator it = m_fields.begin(); it != m_fields.end(); ++it) { DBFAddField(m_dbf_handle, it->name().c_str(), it->type(), it->width(), it->decimals()); } } }; // class Shapefile /** * Shapefile containing point geometries. */ class PointShapefile : public Shapefile { public: /** * Create shapefile. * * @param filename Filename (optionally including path) without any suffix. */ PointShapefile(const std::string& filename) : Shapefile(filename, SHPT_POINT) { } }; /** * Shapefile containing line geometries. */ class LineStringShapefile : public Shapefile { public: /** * Create shapefile. * * @param filename Filename (optionally including path) without any suffix. */ LineStringShapefile(const std::string& filename) : Shapefile(filename, SHPT_ARC) { } }; /** * Shapefile containing polygon geometries. */ class PolygonShapefile : public Shapefile { public: /** * Create shapefile. * * @param filename Filename (optionally including path) without any suffix. */ PolygonShapefile(const std::string& filename) : Shapefile(filename, SHPT_POLYGON) { } }; } // namespace Export } // namespace Osmium #endif // OSMIUM_WITH_SHPLIB #endif // OSMIUM_EXPORT_SHAPEFILE_HPP osmium/include/osmium/geometry.hpp0000664000175000017500000002650011706551765016651 0ustar daviddavid#ifndef OSMIUM_GEOMETRY_HPP #define OSMIUM_GEOMETRY_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #ifdef OSMIUM_WITH_GEOS # include # include #endif // OSMIUM_WITH_GEOS #ifdef OSMIUM_WITH_SHPLIB # include #endif // OSMIUM_WITH_SHPLIB #ifdef OSMIUM_WITH_OGR # include #endif // OSMIUM_WITH_OGR #include #include namespace Osmium { /** * @brief %Geometry classes such as for points, linestrings, and polygons. */ namespace Geometry { /// %OSM data always uses SRID 4326 (WGS84). const int srid = 4326; /** * Type of WKB geometry. * These definitions are from * 99-049_OpenGIS_Simple_Features_Specification_For_SQL_Rev_1.1.pdf (for WKB) * and http://trac.osgeo.org/postgis/browser/trunk/doc/ZMSgeoms.txt (for EWKB). * They are used to encode geometries into the WKB format. */ enum wkbGeometryType { wkbPoint = 1, wkbLineString = 2, wkbPolygon = 3, wkbMultiPoint = 4, wkbMultiLineString = 5, wkbMultiPolygon = 6, wkbGeometryCollection = 7, // SRID-presence flag (EWKB) wkbSRID = 0x20000000 }; /** * Byte order marker in WKB geometry. */ enum wkbByteOrder { wkbXDR = 0, // Big Endian wkbNDR = 1 // Little Endian }; #ifdef OSMIUM_WITH_GEOS /** * Return pointer to a static GEOS GeometryFactory object created the * first time this function is run. This is used by all functions in * Osmium that need to create GEOS geometries. */ geos::geom::GeometryFactory* geos_geometry_factory() { static geos::geom::PrecisionModel pm; static geos::geom::GeometryFactory factory(&pm, -1); return &factory; } #endif // OSMIUM_WITH_GEOS class Geometry; /** * This helper class is used to allow writing geometries in different * formats to an output stream. * * If we'd just write * @code * Osmium::Geometry::Geometry geometry; * std::stream out << geometry; * @endcode * we would not know in which format to write. * * Instead we can write * @code * std::stream out << geometry.as_WKT(); * @endcode * and this class magically makes this work. * * @see Geometry::AsWKT * @see Geometry::AsWKB * @see Geometry::AsHexWKB */ template struct StreamFormat { StreamFormat(const Geometry& geometry, bool with_srid) : m_geometry(geometry), m_with_srid(with_srid) {} const Geometry& m_geometry; const bool m_with_srid; }; /** * Output operator for StreamFormat. */ template std::ostream& operator<<(std::ostream& out, StreamFormat format) { return format.m_geometry.write_to_stream(out, format, format.m_with_srid); } /** * Write a value as binary to an output stream. * * @tparam T Type of value. */ template inline void write_binary(std::ostream& out, const T value) { out.write(reinterpret_cast(&value), sizeof(T)); } /** * Write a value as hex encoding of binary to an output stream. * * @tparam T Type of value. */ template inline void write_hex(std::ostream& out, const T value) { static const char* lookup_hex = "0123456789ABCDEF"; for (const char* in = reinterpret_cast(&value); in < reinterpret_cast(&value) + sizeof(T); ++in) { out << lookup_hex[(*in >> 4) & 0xf] << lookup_hex[*in & 0xf]; } } /** * Write header of WKB data structure as binary to output stream. * The header contains: * - the byte order marker * - the geometry type * - (optionally) the SRID */ inline void write_binary_wkb_header(std::ostream& out, bool with_srid, uint32_t type) { write_binary(out, wkbNDR); if (with_srid) { write_binary(out, type | wkbSRID); write_binary(out, srid); } else { write_binary(out, type); } } /** * Write header of WKB data structure as hex encoding of binary to output stream. * The header contains: * - the byte order marker * - the geometry type * - (optionally) the SRID */ inline void write_hex_wkb_header(std::ostream& out, bool with_srid, uint32_t type) { write_hex(out, wkbNDR); if (with_srid) { write_hex(out, type | wkbSRID); write_hex(out, srid); } else { write_hex(out, type); } } /** * Abstract base class for all Osmium geometry classes. Geometries of different * types are created from OSM objects (nodes, ways, relations). Geometries * can be written out and transformed in different ways. */ class Geometry { public: Geometry(osm_object_id_t id=0) : m_id(id) { } virtual ~Geometry() { } osm_object_id_t id() const { return m_id; } // These types are never instantiated, they are used in the write_to_stream() // methods below as parameters to make the overloading mechanism choose the // right version. typedef StreamFormat AsWKT; typedef StreamFormat AsWKB; typedef StreamFormat AsHexWKB; AsWKT as_WKT(bool with_srid=false) const { return AsWKT(*this, with_srid); } AsWKB as_WKB(bool with_srid=false) const { return AsWKB(*this, with_srid); } AsHexWKB as_HexWKB(bool with_srid=false) const { return AsHexWKB(*this, with_srid); } /// Write geometry as WKT to output stream. virtual std::ostream& write_to_stream(std::ostream& out, AsWKT, bool with_srid=false) const = 0; /// Write geometry as WKB to output stream. virtual std::ostream& write_to_stream(std::ostream& out, AsWKB, bool with_srid=false) const = 0; /// Write geometry as hex encoded WKB to output stream. virtual std::ostream& write_to_stream(std::ostream& out, AsHexWKB, bool with_srid=false) const = 0; #ifdef OSMIUM_WITH_SHPLIB virtual SHPObject* create_shp_object() const { return NULL; } #endif // OSMIUM_WITH_SHPLIB #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle js_to_wkt(const v8::Arguments& args) { std::ostringstream oss; bool with_srid = false; if (args.Length() >= 1) { with_srid = args[0]->ToBoolean()->Value(); } oss << this->as_WKT(with_srid); return v8::String::New(oss.str().c_str()); } v8::Handle js_to_wkb(const v8::Arguments& args) { std::ostringstream oss; bool with_srid = false; if (args.Length() >= 1) { with_srid = args[0]->ToBoolean()->Value(); } oss << this->as_WKB(with_srid); return v8::String::New(oss.str().c_str()); } v8::Handle js_to_hexwkb(const v8::Arguments& args) { std::ostringstream oss; bool with_srid = false; if (args.Length() >= 1) { with_srid = args[0]->ToBoolean()->Value(); } oss << this->as_HexWKB(with_srid); return v8::String::New(oss.str().c_str()); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->Set("toWKT", v8::FunctionTemplate::New(function_template)); js_template->Set("toWKB", v8::FunctionTemplate::New(function_template)); js_template->Set("toHexWKB", v8::FunctionTemplate::New(function_template)); } }; #endif // OSMIUM_WITH_JAVASCRIPT private: osm_object_id_t m_id; }; // class Geometry /** * This helper class is used for writing out lists of coordinates * to an output stream. It is intended to be used as a functor argument * in a for_each() call iterating over something that holds a list of * TLonLat objects. * * @tparam TLonLat A class that has the methods 'double lon();' and 'double lat();' */ template class LonLatListWriter { public: LonLatListWriter(std::ostream& out, ///< The output stream char delim_lonlat=' ', ///< The delimiter between longitude and latitude char delim_items=',') ///< The delimiter between consecutive coordinates : m_out(out), m_delim_lonlat(delim_lonlat), m_delim_items(delim_items), m_first(true) { } void operator()(const TLonLat& lonlat) { if (m_first) { m_first = false; } else { m_out << m_delim_items; } m_out << lonlat.lon() << m_delim_lonlat << lonlat.lat(); } private: std::ostream& m_out; char m_delim_lonlat; char m_delim_items; bool m_first; }; // class LonLatListWriter } // namespace Geometry } // namespace Osmium #endif // OSMIUM_GEOMETRY_HPP osmium/include/osmium/osmfile.hpp0000664000175000017500000005101311706551765016451 0ustar daviddavid#ifndef OSMIUM_OSMFILE_HPP #define OSMIUM_OSMFILE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include #include namespace Osmium { // forward declaration namespace Output { class Base; } /** * This class describes an %OSM file in one of several different formats. * It can be used as factory class for generating input and output OSM files. * * If the filename is empty, this means stdin or stdout is used. If you set * the filename to "-" it will be treated the same. */ class OSMFile { public: /** * Low-level system call error. * This should normally not happen unless your system is out of * resources like number of processes or filehandles. */ class SystemError : public std::runtime_error { int m_errno; public: SystemError(const std::string& whatarg, int e) : std::runtime_error(whatarg), m_errno(e) { } /** * Get the system errno variable from the system call that caused * this exception. */ int system_errno() const throw() { return m_errno; } }; /** * Low-level I/O Error. * This exception if thrown if there is an error in an I/O system call. */ class IOError : public std::runtime_error { std::string m_filename; int m_errno; public: IOError(const std::string& whatarg, const std::string& filename, int e) : std::runtime_error(whatarg), m_filename(filename), m_errno(e) { } ~IOError() throw() { } /** * Get the filename that caused this exception. */ const std::string& filename() const throw() { return m_filename; } /** * Get the system errno variable from the system call that caused * this exception. */ int system_errno() const throw() { return m_errno; } }; class ArgumentError : public std::runtime_error { std::string m_value; public: ArgumentError(const std::string& whatarg, const std::string& value="") : std::runtime_error(whatarg), m_value(value) { } ~ArgumentError() throw() { } const std::string& value() const throw() { return m_value; } }; /** * An exception of a subclass of this class is thrown when the type of * a file is not what you expected. */ struct FileTypeError { }; /** * This exception is thrown when you wanted to read a normal OSM file, * but the file opened had a different type. */ struct FileTypeOSMExpected : public FileTypeError { }; /** * This exception is thrown when you wanted to read an OSM file with * historic information, but the file opened had a different type. */ struct FileTypeHistoryExpected : public FileTypeError { }; /** * Instances of this class describe different file types. * * You can not create instances of this class yourself, instead use * the static methods provided to get the predefined instances. */ class FileType : boost::noncopyable { std::string m_suffix; bool m_has_multiple_object_versions; FileType(std::string suffix, bool has_multiple_object_versions) : m_suffix(suffix), m_has_multiple_object_versions(has_multiple_object_versions) { } public: std::string suffix() const { return m_suffix; } bool has_multiple_object_versions() const { return m_has_multiple_object_versions; } /** * Normal OSM file without history. */ static FileType* OSM() { static FileType instance(".osm", false); return &instance; } /** * OSM file with history. */ static FileType* History() { static FileType instance(".osh", true); return &instance; } /** * OSM change file. */ static FileType* Change() { static FileType instance(".osc", true); return &instance; } }; /** * Instances of this class describe different file encodings (ie PBF, * XML or different compressed versions of XML). * * You can not create instances of this class yourself, instead use * the static methods provided to get the predefined instances. */ class FileEncoding : boost::noncopyable { std::string m_suffix; std::string m_compress; std::string m_decompress; bool m_pbf; FileEncoding(std::string suffix, std::string compress, std::string decompress, bool pbf) : m_suffix(suffix), m_compress(compress), m_decompress(decompress), m_pbf(pbf) { } public: std::string suffix() const { return m_suffix; } std::string compress() const { return m_compress; } std::string decompress() const { return m_decompress; } bool is_pbf() const { return m_pbf; } /** * Encoding in PBF. */ static FileEncoding* PBF() { static FileEncoding instance(".pbf", "", "", true); return &instance; } /** * XML encoding, uncompressed. */ static FileEncoding* XML() { static FileEncoding instance("", "", "", false); return &instance; } /** * XML encoding, compressed with gzip. */ static FileEncoding* XMLgz() { static FileEncoding instance(".gz", "gzip", "gzcat", false); return &instance; } /** * XML encoding, compressed with bzip2. */ static FileEncoding* XMLbz2() { static FileEncoding instance(".bz2", "bzip2", "bzcat", false); return &instance; } }; private: /// Type of file. FileType* m_type; /// Encoding of file. FileEncoding* m_encoding; /// File name. std::string m_filename; /// File descriptor. -1 before the file is opened. int m_fd; /** * Contains the child process id if a child was * created to uncompress data or for getting a * URL. */ pid_t m_childpid; /** * Fork and execute the given command in the child. * A pipe is created between the child and the parent. * The child writes to the pipe, the parent reads from it. * This function never returns in the child. * * @param command Command to execute in the child. * @param input 0 for reading from child, 1 for writing to child. * @return File descriptor of pipe in the parent. * @throws SystemError if a system call fails. */ int execute(std::string command, int input) { int pipefd[2]; if (pipe(pipefd) < 0) { throw SystemError("Can't create pipe", errno); } pid_t pid = fork(); if (pid < 0) { throw SystemError("Can't fork", errno); } if (pid == 0) { // child // close all file descriptors except one end of the pipe for (int i=0; i < 32; ++i) { if (i != pipefd[1-input]) { ::close(i); } } if (dup2(pipefd[1-input], 1-input) < 0) { // put end of pipe as stdout/stdin exit(1); } if (input == 0) { open("/dev/null", O_RDONLY); // stdin open("/dev/null", O_WRONLY); // stderr if (execlp(command.c_str(), command.c_str(), m_filename.c_str(), NULL) < 0) { exit(1); } } else { if (open(m_filename.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666) != 1) { exit(1); } open("/dev/null", O_WRONLY); // stderr if (execlp(command.c_str(), command.c_str(), 0, NULL) < 0) { exit(1); } } } // parent m_childpid = pid; ::close(pipefd[1-input]); return pipefd[input]; } /** * Open OSMFile for reading. * * @return File descriptor of open file. * @throws IOError if the file can't be opened. */ int open_input_file() const { if (m_filename == "") { return 0; // stdin } else { int fd = open(m_filename.c_str(), O_RDONLY); if (fd < 0) { throw IOError("Open failed", m_filename, errno); } return fd; } } /** * Open OSMFile for writing. If the file exists, it is truncated, if * not it is created. * * @return File descriptor of open file. * @throws IOError if the file can't be opened. */ int open_output_file() const { if (m_filename == "") { return 1; // stdout } else { int fd = open(m_filename.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666); if (fd < 0) { throw IOError("Open failed", m_filename, errno); } return fd; } } /** * Open OSMFile for reading. Handles URLs or normal files. URLs * are opened by executing the "curl" program (which must be installed) * and reading from its output. * * @return File descriptor of open file or pipe. * @throws SystemError if a system call fails. * @throws IOError if the file can't be opened. */ int open_input_file_or_url() { std::string protocol = m_filename.substr(0, m_filename.find_first_of(':')); if (protocol == "http" || protocol == "https") { return execute("curl", 0); } else { return open_input_file(); } } public: /** * Create OSMFile using type and encoding from filename. If you want * to overwrite these settings you can change them later. * * @param filename Filename including suffix. The type and encoding * of the file will be taken from the suffix. * An empty filename or "-" means stdin or stdout. */ OSMFile(const std::string& filename = "") : m_type(FileType::OSM()), m_encoding(FileEncoding::PBF()), m_filename(filename), m_fd(-1), m_childpid(0) { // stdin/stdout if (filename == "" || filename == "-") { m_filename = ""; default_settings_for_stdinout(); return; } // filename is actually a URL std::string protocol = m_filename.substr(0, m_filename.find_first_of(':')); if (protocol == "http" || protocol == "https") { default_settings_for_url(); return; } // isolate filename suffix size_t n = filename.find_last_of('/'); if (n == std::string::npos) { n = 0; } else { ++n; } std::string suffix(filename.substr(filename.find_first_of('.', n)+1)); set_type_and_encoding(suffix); } void set_type_and_encoding(const std::string& suffix) { if (suffix == "pbf" || suffix == "osm.pbf") { m_type = FileType::OSM(); m_encoding = FileEncoding::PBF(); } else if (suffix == "osm") { m_type = FileType::OSM(); m_encoding = FileEncoding::XML(); } else if (suffix == "osm.bz2") { m_type = FileType::OSM(); m_encoding = FileEncoding::XMLbz2(); } else if (suffix == "osm.gz") { m_type = FileType::OSM(); m_encoding = FileEncoding::XMLgz(); } else if (suffix == "osh.pbf") { m_type = FileType::History(); m_encoding = FileEncoding::PBF(); } else if (suffix == "osh") { m_type = FileType::History(); m_encoding = FileEncoding::XML(); } else if (suffix == "osh.bz2") { m_type = FileType::History(); m_encoding = FileEncoding::XMLbz2(); } else if (suffix == "osh.gz") { m_type = FileType::History(); m_encoding = FileEncoding::XMLgz(); } else if (suffix == "osc") { m_type = FileType::Change(); m_encoding = FileEncoding::XML(); } else if (suffix == "osc.bz2") { m_type = FileType::Change(); m_encoding = FileEncoding::XMLbz2(); } else if (suffix == "osc.gz") { m_type = FileType::Change(); m_encoding = FileEncoding::XMLgz(); } else { default_settings_for_file(); } } /** * Copy constructor. * Only attributes not related to the open file will be * copied. */ OSMFile(const OSMFile& orig) { m_fd = -1; m_childpid = 0; m_type = orig.get_type(); m_encoding = orig.get_encoding(); m_filename = orig.get_filename(); } /** * Assignement operator. * Only attributes not related to the open file will be * copied. */ OSMFile& operator=(const OSMFile& orig) { m_fd = -1; m_childpid = 0; m_type = orig.get_type(); m_encoding = orig.get_encoding(); m_filename = orig.get_filename(); return *this; } ~OSMFile() { try { close(); } catch (...) { // ignore exceptions } } void close() { if (m_fd > 0) { ::close(m_fd); m_fd = -1; } if (m_childpid) { int status; pid_t pid = waitpid(m_childpid, &status, 0); if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { throw IOError("Subprocess returned error", "", errno); } m_childpid = 0; } } /** * Set default settings for type and encoding when the filename is * empty or "-". If you want to have a different default setting * override this in a subclass. */ void default_settings_for_stdinout() { m_type = FileType::OSM(); m_encoding = FileEncoding::PBF(); } /** * Set default settings for type and encoding when the filename is * a normal file. If you want to have a different default setting * override this in a subclass. */ void default_settings_for_file() { m_type = FileType::OSM(); m_encoding = FileEncoding::PBF(); } /** * Set default settings for type and encoding when the filename is a URL. * If you want to have a different default setting override this in a * subclass. */ void default_settings_for_url() { m_type = FileType::OSM(); m_encoding = FileEncoding::XML(); } int get_fd() const { return m_fd; } FileType* get_type() const { return m_type; } OSMFile& set_type(FileType* type) { m_type = type; return *this; } OSMFile& set_type(std::string& type) { if (type == "osm") { m_type = FileType::OSM(); } else if (type == "history" || type == "osh") { m_type = FileType::History(); } else if (type == "change" || type == "osc") { m_type = FileType::Change(); } else { throw ArgumentError("Unknown OSM file type", type); } return *this; } bool has_multiple_object_versions() const { return m_type->has_multiple_object_versions(); } FileEncoding* get_encoding() const { return m_encoding; } OSMFile& set_encoding(FileEncoding* encoding) { m_encoding = encoding; return *this; } OSMFile& set_encoding(std::string& encoding) { if (encoding == "pbf") { m_encoding = FileEncoding::PBF(); } else if (encoding == "xml") { m_encoding = FileEncoding::XML(); } else if (encoding == "xmlgz" || encoding == "gz") { m_encoding = FileEncoding::XMLgz(); } else if (encoding == "xmlbz2" || encoding == "bz2") { m_encoding = FileEncoding::XMLbz2(); } else { throw ArgumentError("Unknown OSM file encoding", encoding); } return *this; } OSMFile& set_filename(std::string& filename) { if (filename == "-") { m_filename = ""; } else { m_filename = filename; } return *this; } std::string get_filename() const { return m_filename; } std::string get_filename_without_suffix() const { return m_filename.substr(m_filename.find_first_of('.')+1); } std::string get_filename_with_default_suffix() const { std::string filename = get_filename_without_suffix(); filename += m_type->suffix() + m_encoding->suffix(); return filename; } void open_for_input() { m_fd = m_encoding->decompress() == "" ? open_input_file_or_url() : execute(m_encoding->decompress(), 0); } void open_for_output() { m_fd = m_encoding->compress() == "" ? open_output_file() : execute(m_encoding->compress(), 1); } /** * Read OSM file and call methods on handler object. */ template void read(T& handler); /** * Create output file from OSMFile. */ Osmium::Output::Base* create_output_file(); }; } // namespace Osmium #endif // OSMIUM_OSMFILE_HPP osmium/include/osmium/geometry/0000775000175000017500000000000011706551765016135 5ustar daviddavidosmium/include/osmium/geometry/multipolygon.hpp0000664000175000017500000003104311706551765021411 0ustar daviddavid#ifndef OSMIUM_GEOMETRY_MULTIPOLYGON_HPP #define OSMIUM_GEOMETRY_MULTIPOLYGON_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #ifdef OSMIUM_WITH_GEOS # include #endif // OSMIUM_WITH_GEOS #include #include namespace Osmium { namespace Geometry { class MultiPolygon : public Geometry { public: MultiPolygon(const Osmium::OSM::Area& area) : Geometry(area.id()), m_area(&area) { #ifdef OSMIUM_WITH_GEOS if (!m_area->get_geometry()) { throw Osmium::Exception::IllegalGeometry(); } #endif // OSMIUM_WITH_GEOS } #ifdef OSMIUM_WITH_GEOS # ifdef OSMIUM_WITH_SHPLIB private: void dump_geometry(const geos::geom::Geometry* g, std::vector& part_start_list, std::vector& x_list, std::vector& y_list) const { switch (g->getGeometryTypeId()) { case geos::geom::GEOS_MULTIPOLYGON: case geos::geom::GEOS_MULTILINESTRING: { for (geos::geom::GeometryCollection::const_iterator it = static_cast(g)->begin(); it != static_cast(g)->end(); ++it) { dump_geometry(*it, part_start_list, x_list, y_list); } break; } case geos::geom::GEOS_POLYGON: { const geos::geom::Polygon* polygon = static_cast(g); dump_geometry(polygon->getExteriorRing(), part_start_list, x_list, y_list); for (size_t i=0; i < polygon->getNumInteriorRing(); ++i) { dump_geometry(polygon->getInteriorRingN(i), part_start_list, x_list, y_list); } break; } case geos::geom::GEOS_LINESTRING: case geos::geom::GEOS_LINEARRING: { part_start_list.push_back(x_list.size()); const geos::geom::CoordinateSequence* cs = static_cast(g)->getCoordinatesRO(); for (size_t i = 0; i < cs->getSize(); ++i) { x_list.push_back(cs->getX(i)); y_list.push_back(cs->getY(i)); } break; } default: throw std::runtime_error("invalid geometry type encountered"); } } public: /** * Create Shapelib geometry of this MultiPolygon. * * Caller takes ownership. You have to call * SHPDestroyObject() with this geometry when you are done. */ SHPObject* create_shp_object() const { if (!m_area->get_geometry()) { throw Osmium::Exception::IllegalGeometry(); } std::vector x_list; std::vector y_list; std::vector part_start_list; dump_geometry(m_area->get_geometry(), part_start_list, x_list, y_list); return SHPCreateObject( SHPT_POLYGON, // nSHPType -1, // iShape part_start_list.size(), // nParts &part_start_list[0], // panPartStart NULL, // panPartType x_list.size(), // nVertices, &x_list[0], // padfX &y_list[0], // padfY NULL, // padfZ NULL); // padfM } # endif // OSMIUM_WITH_SHPLIB std::ostream& write_to_stream(std::ostream& out, AsWKT, bool with_srid=false) const { if (with_srid) { out << "SRID=4326;"; } geos::io::WKTWriter writer; return out << writer.write(m_area->get_geometry()); } std::ostream& write_to_stream(std::ostream& out, AsWKB, bool with_srid=false) const { geos::io::WKBWriter writer; writer.setIncludeSRID(with_srid); writer.write(*(m_area->get_geometry()), out); return out; } std::ostream& write_to_stream(std::ostream& out, AsHexWKB, bool with_srid=false) const { geos::io::WKBWriter writer; writer.setIncludeSRID(with_srid); writer.writeHEX(*(m_area->get_geometry()), out); return out; } # ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void*)this); } v8::Handle js_ring_as_array(const geos::geom::LineString* ring) const { v8::HandleScope scope; const geos::geom::CoordinateSequence* cs = ring->getCoordinatesRO(); v8::Local ring_array = v8::Array::New(cs->getSize()); for (size_t i = 0; i < cs->getSize(); ++i) { v8::Local coord = v8::Array::New(2); coord->Set(0, v8::Number::New(cs->getX(i))); coord->Set(1, v8::Number::New(cs->getY(i))); ring_array->Set(i, coord); } return scope.Close(ring_array); } v8::Handle js_to_array(const v8::Arguments& /*args*/) { v8::HandleScope scope; geos::geom::Geometry* geometry = m_area->get_geometry(); if (geometry->getGeometryTypeId() == geos::geom::GEOS_MULTIPOLYGON) { v8::Local multipolygon_array = v8::Array::New(geometry->getNumGeometries()); for (size_t i=0; i < geometry->getNumGeometries(); ++i) { geos::geom::Polygon* polygon = (geos::geom::Polygon*) geometry->getGeometryN(i); v8::Local polygon_array = v8::Array::New(polygon->getNumInteriorRing()); multipolygon_array->Set(i, polygon_array); polygon_array->Set(0, js_ring_as_array(polygon->getExteriorRing())); for (size_t j=0; j < polygon->getNumInteriorRing(); ++j) { polygon_array->Set(j+1, js_ring_as_array(polygon->getInteriorRingN(j))); } } return scope.Close(multipolygon_array); } else if (geometry->getGeometryTypeId() == geos::geom::GEOS_POLYGON) { const Osmium::OSM::AreaFromWay* area_from_way = dynamic_cast(m_area); if (area_from_way) { v8::Local polygon = v8::Array::New(1); v8::Local ring = v8::Array::New(area_from_way->nodes().size()); int n = 0; for (Osmium::OSM::WayNodeList::const_iterator it = area_from_way->nodes().begin(); it != area_from_way->nodes().end(); ++it) { v8::Local coord = v8::Array::New(2); coord->Set(0, v8::Number::New(it->lon())); coord->Set(1, v8::Number::New(it->lat())); ring->Set(n++, coord); } polygon->Set(0, ring); return scope.Close(polygon); } } return scope.Close(v8::Undefined()); } struct JavascriptTemplate : public Osmium::Geometry::Geometry::JavascriptTemplate { JavascriptTemplate() : Osmium::Geometry::Geometry::JavascriptTemplate() { js_template->Set("toArray", v8::FunctionTemplate::New(function_template)); } }; # endif // OSMIUM_WITH_JAVASCRIPT # ifdef OSMIUM_WITH_OGR private: void add_ring(OGRPolygon* ogrpolygon, const geos::geom::LineString* geosring) const { OGRLinearRing* ogrring = new OGRLinearRing; const geos::geom::CoordinateSequence* cs = geosring->getCoordinatesRO(); ogrring->setNumPoints(cs->getSize()); for (size_t i = 0; i < cs->getSize(); ++i) { ogrring->setPoint(i, cs->getX(i), cs->getY(i), 0); } ogrpolygon->addRingDirectly(ogrring); }; OGRPolygon* make_polygon(const geos::geom::Polygon* geospolygon) const { OGRPolygon* ogrpolygon = new OGRPolygon; add_ring(ogrpolygon, geospolygon->getExteriorRing()); for (size_t i=0; i < geospolygon->getNumInteriorRing(); ++i) { add_ring(ogrpolygon, geospolygon->getInteriorRingN(i)); } return ogrpolygon; } public: /** * Create OGR geometry of this MultiPolygon. * * Caller takes ownership. */ OGRMultiPolygon* create_ogr_geometry() const { OGRMultiPolygon* ogrmp = new OGRMultiPolygon; if (m_area->get_geometry()->getGeometryTypeId() == geos::geom::GEOS_POLYGON) { OGRPolygon* ogrpolygon = make_polygon(dynamic_cast(m_area->get_geometry())); OGRErr result = ogrmp->addGeometryDirectly(ogrpolygon); if (result != OGRERR_NONE) { throw Osmium::Exception::IllegalGeometry(); } return ogrmp; } if (m_area->get_geometry()->getGeometryTypeId() != geos::geom::GEOS_MULTIPOLYGON) { throw Osmium::Exception::IllegalGeometry(); } const geos::geom::GeometryCollection* geosgeom = dynamic_cast(m_area->get_geometry()); for (geos::geom::GeometryCollection::const_iterator it = geosgeom->begin(); it != geosgeom->end(); ++it) { OGRPolygon* ogrpolygon = make_polygon(dynamic_cast(*it)); OGRErr result = ogrmp->addGeometryDirectly(ogrpolygon); if (result != OGRERR_NONE) { throw Osmium::Exception::IllegalGeometry(); } } return ogrmp; } # endif // OSMIUM_WITH_OGR #endif // OSMIUM_WITH_GEOS private: const Osmium::OSM::Area* m_area; }; // class MultiPolygon } // namespace Geometry } // namespace Osmium #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle Osmium::OSM::Area::js_geom() const { if (get_geometry()) { Osmium::Geometry::MultiPolygon* geom = new Osmium::Geometry::MultiPolygon(*this); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } else { Osmium::Geometry::Null* geom = new Osmium::Geometry::Null(); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } } #endif // OSMIUM_WITH_JAVASCRIPT #endif // OSMIUM_GEOMETRY_MULTIPOLYGON_HPP osmium/include/osmium/geometry/polygon.hpp0000664000175000017500000001766211706551765020351 0ustar daviddavid#ifndef OSMIUM_GEOMETRY_POLYGON_HPP #define OSMIUM_GEOMETRY_POLYGON_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include namespace Osmium { namespace Geometry { /** * Polygon geometry. */ class Polygon : public FromWay { public: /** * Create Polygon geometry from a list of nodes. */ Polygon(const Osmium::OSM::WayNodeList& way_node_list, osm_object_id_t id=0) : FromWay(way_node_list, false, id) { if (!way_node_list.is_closed()) { throw Osmium::Exception::IllegalGeometry(); } } /** * Create Polygon geometry from a list of nodes in a way. */ Polygon(const Osmium::OSM::Way& way) : FromWay(way.nodes(), false, way.id()) { if (!way.nodes().is_closed()) { throw Osmium::Exception::IllegalGeometry(); } } std::ostream& write_to_stream(std::ostream& out, AsWKT, bool with_srid=false) const { if (with_srid) { out << "SRID=4326;"; } LonLatListWriter writer(out); out << "POLYGON((" << std::setprecision(10); for_each(m_way_node_list->begin(), m_way_node_list->end(), writer); return out << "))"; } std::ostream& write_to_stream(std::ostream& out, AsWKB, bool with_srid=false) const { write_binary_wkb_header(out, with_srid, wkbPolygon); write_binary(out, 1); // ring count write_binary(out, m_way_node_list->size()); // ring #1 point count for (Osmium::OSM::WayNodeList::const_iterator it = m_way_node_list->begin(); it != m_way_node_list->end(); ++it) { write_binary(out, it->lon()); write_binary(out, it->lat()); } return out; } std::ostream& write_to_stream(std::ostream& out, AsHexWKB, bool with_srid=false) const { write_hex_wkb_header(out, with_srid, wkbPolygon); write_hex(out, 1); // ring count write_hex(out, m_way_node_list->size()); // ring #1 point count for (Osmium::OSM::WayNodeList::const_iterator it = m_way_node_list->begin(); it != m_way_node_list->end(); ++it) { write_hex(out, it->lon()); write_hex(out, it->lat()); } return out; } #ifdef OSMIUM_WITH_GEOS /** * Creates GEOS geometry of this Polygon. * * Caller takes ownership. */ geos::geom::Geometry* create_geos_geometry() const { try { std::vector* c = new std::vector; for (Osmium::OSM::WayNodeList::const_iterator it = m_way_node_list->begin(); it != m_way_node_list->end(); ++it) { c->push_back(it->position()); } geos::geom::CoordinateSequence* cs = Osmium::Geometry::geos_geometry_factory()->getCoordinateSequenceFactory()->create(c); geos::geom::LinearRing* lr = Osmium::Geometry::geos_geometry_factory()->createLinearRing(cs); return static_cast(Osmium::Geometry::geos_geometry_factory()->createPolygon(lr, NULL)); } catch (const geos::util::GEOSException& exc) { std::cerr << "error building polygon geometry, leave it as NULL\n"; return NULL; } } #endif // OSMIUM_WITH_GEOS #ifdef OSMIUM_WITH_SHPLIB /** * Create Shapelib geometry of this Polygon. * * Caller takes ownership. You have to call * SHPDestroyObject() with this geometry when you are done. */ SHPObject* create_shp_object() const { return create_line_or_polygon(SHPT_POLYGON); } #endif // OSMIUM_WITH_SHPLIB #ifdef OSMIUM_WITH_OGR /** * Create OGR geometry of this Polygon. * * Caller takes ownership. */ OGRPolygon* create_ogr_geometry() const { OGRPolygon* p = new OGRPolygon(); OGRLinearRing* r = new OGRLinearRing(); for (Osmium::OSM::WayNodeList::const_reverse_iterator it = m_way_node_list->rbegin(); it != m_way_node_list->rend(); ++it) { r->addPoint(it->lon(), it->lat()); } p->addRingDirectly(r); return p; } #endif // OSMIUM_WITH_OGR #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void *)this); } v8::Handle js_to_array(const v8::Arguments& /*args*/) { v8::HandleScope scope; v8::Local polygon = v8::Array::New(1); v8::Local linear_ring = v8::Array::New(m_way_node_list->size()); polygon->Set(0, linear_ring); unsigned int max = m_way_node_list->size() - 1; if (m_reverse) { for (unsigned int i=0; i <= max; ++i) { linear_ring->Set(max - i, (*m_way_node_list)[i].position().js_to_array()); } } else { for (unsigned int i=0; i <= max; ++i) { linear_ring->Set(i, (*m_way_node_list)[i].position().js_to_array()); } } return scope.Close(polygon); } struct JavascriptTemplate : public Osmium::Geometry::Geometry::JavascriptTemplate { JavascriptTemplate() : Osmium::Geometry::Geometry::JavascriptTemplate() { js_template->Set("toArray", v8::FunctionTemplate::New(function_template)); } }; #endif // OSMIUM_WITH_JAVASCRIPT }; // class Polygon } // namespace Geometry } // namespace Osmium #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle Osmium::OSM::Way::js_polygon_geom() const { if (m_node_list.has_position() && m_node_list.is_closed()) { Osmium::Geometry::Polygon* geom = new Osmium::Geometry::Polygon(*this); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } else { Osmium::Geometry::Null* geom = new Osmium::Geometry::Null(); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } } #endif // OSMIUM_WITH_JAVASCRIPT #endif // OSMIUM_GEOMETRY_POLYGON_HPP osmium/include/osmium/geometry/null.hpp0000664000175000017500000000515511706551765017626 0ustar daviddavid#ifndef OSMIUM_GEOMETRY_NULL_HPP #define OSMIUM_GEOMETRY_NULL_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include namespace Osmium { namespace Geometry { /** * The Null geometry is a placeholder, if no valid geometry could be * created. */ class Null : public Geometry { public: Null() : Geometry() { } std::ostream& write_to_stream(std::ostream& out, AsWKT, bool /*with_srid=false*/) const { return out; } std::ostream& write_to_stream(std::ostream& out, AsWKB, bool /*with_srid=false*/) const { return out; } std::ostream& write_to_stream(std::ostream& out, AsHexWKB, bool /*with_srid=false*/) const { return out; } #ifdef OSMIUM_WITH_JAVASCRIPT struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->Set("toWKT", v8::FunctionTemplate::New(function_template)); js_template->Set("toWKB", v8::FunctionTemplate::New(function_template)); js_template->Set("toHexWKB", v8::FunctionTemplate::New(function_template)); js_template->Set("toArray", v8::FunctionTemplate::New(function_template)); } }; #endif // OSMIUM_WITH_JAVASCRIPT }; // class Null } // namespace Geometry } // namespace Osmium #endif // OSMIUM_GEOMETRY_HPP osmium/include/osmium/geometry/from_way.hpp0000664000175000017500000001055711706551765020501 0ustar daviddavid#ifndef OSMIUM_GEOMETRY_FROM_WAY_HPP #define OSMIUM_GEOMETRY_FROM_WAY_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace Geometry { class FromWay : public Geometry { protected: FromWay(const Osmium::OSM::WayNodeList& way_node_list, bool reverse=false, osm_object_id_t id=0) : Geometry(id), m_way_node_list(&way_node_list), m_reverse(reverse) { } #ifdef OSMIUM_WITH_SHPLIB /** * Create a SHPObject for this way and return it. * * Caller takes ownership. You have to call * SHPDestroyObject() with this geometry when you are done. */ SHPObject* create_line_or_polygon(int shp_type) const { if (!m_way_node_list->has_position()) { throw std::runtime_error("node coordinates not available for building way geometry"); } int size = m_way_node_list->size(); if (size == 0 || size == 1) { if (Osmium::debug()) { std::cerr << "error building way geometry for way " << id() << ": must at least contain two nodes" << std::endl; } throw Osmium::Exception::IllegalGeometry(); } std::vector lon_checked; lon_checked.reserve(size); lon_checked.push_back((*m_way_node_list)[0].position().lon()); std::vector lat_checked; lat_checked.reserve(size); lat_checked.push_back((*m_way_node_list)[0].position().lat()); for (int i=1; i < size; i++) { if ((*m_way_node_list)[i] == (*m_way_node_list)[i-1]) { if (Osmium::debug()) { std::cerr << "warning building way geometry for way " << id() << ": contains node " << (*m_way_node_list)[i].ref() << " twice" << std::endl; } } else if ((*m_way_node_list)[i].position() == (*m_way_node_list)[i-1].position()) { if (Osmium::debug()) { std::cerr << "warning building way geometry for way " << id() << ": contains position " << (*m_way_node_list)[i].position() << " twice" << std::endl; } } else { lon_checked.push_back((*m_way_node_list)[i].position().lon()); lat_checked.push_back((*m_way_node_list)[i].position().lat()); } } if (lon_checked.size() == 1) { if (Osmium::debug()) { std::cerr << "error building way geometry for way " << id() << ": must at least contain two different points" << std::endl; } throw Osmium::Exception::IllegalGeometry(); } if (m_reverse) { reverse(lon_checked.begin(), lon_checked.end()); reverse(lat_checked.begin(), lat_checked.end()); } return SHPCreateSimpleObject(shp_type, lon_checked.size(), &(lon_checked[0]), &(lat_checked[0]), NULL); } #endif // OSMIUM_WITH_SHPLIB const Osmium::OSM::WayNodeList* m_way_node_list; const bool m_reverse; }; // class FromWay } // namespace Geometry } // namespace Osmium #endif // OSMIUM_GEOMETRY_FROM_WAY_HPP osmium/include/osmium/geometry/linestring.hpp0000664000175000017500000002346411706551765021035 0ustar daviddavid#ifndef OSMIUM_GEOMETRY_LINESTRING_HPP #define OSMIUM_GEOMETRY_LINESTRING_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace Geometry { /** * LineString geometry. */ class LineString : public FromWay { public: /** * Create LineString geometry from a list of nodes. */ LineString(const Osmium::OSM::WayNodeList& way_node_list, ///< Way node list this geometry should be created from bool reverse=false, ///< Create reverse geometry osm_object_id_t id=0) ///< Object ID of the way this geometry was created from : FromWay(way_node_list, reverse, id) { } /** * Create LineString geometry from a list of nodes in a way. */ LineString(const Osmium::OSM::Way& way, ///< Way this geometry should be created from bool reverse=false) ///< Create reverse geometry : FromWay(way.nodes(), reverse, way.id()) { } std::ostream& write_to_stream(std::ostream& out, AsWKT, bool with_srid=false) const { if (with_srid) { out << "SRID=4326;"; } LonLatListWriter writer(out); out << "LINESTRING(" << std::setprecision(10); if (m_reverse) { for_each(m_way_node_list->rbegin(), m_way_node_list->rend(), writer); } else { for_each(m_way_node_list->begin(), m_way_node_list->end(), writer); } return out << ")"; } std::ostream& write_to_stream(std::ostream& out, AsWKB, bool with_srid=false) const { write_binary_wkb_header(out, with_srid, wkbLineString); write_binary(out, m_way_node_list->size()); if (m_reverse) { for (Osmium::OSM::WayNodeList::const_reverse_iterator it = m_way_node_list->rbegin(); it != m_way_node_list->rend(); ++it) { write_binary(out, it->lon()); write_binary(out, it->lat()); } } else { for (Osmium::OSM::WayNodeList::const_iterator it = m_way_node_list->begin(); it != m_way_node_list->end(); ++it) { write_binary(out, it->lon()); write_binary(out, it->lat()); } } return out; } std::ostream& write_to_stream(std::ostream& out, AsHexWKB, bool with_srid=false) const { write_hex_wkb_header(out, with_srid, wkbLineString); write_hex(out, m_way_node_list->size()); if (m_reverse) { for (Osmium::OSM::WayNodeList::const_reverse_iterator it = m_way_node_list->rbegin(); it != m_way_node_list->rend(); ++it) { write_hex(out, it->lon()); write_hex(out, it->lat()); } } else { for (Osmium::OSM::WayNodeList::const_iterator it = m_way_node_list->begin(); it != m_way_node_list->end(); ++it) { write_hex(out, it->lon()); write_hex(out, it->lat()); } } return out; } #ifdef OSMIUM_WITH_GEOS /** * Create GEOS geometry of this LineString. * * Caller takes ownership. */ geos::geom::Geometry* create_geos_geometry() const { try { std::vector* c = new std::vector; if (m_reverse) { for (Osmium::OSM::WayNodeList::const_reverse_iterator it = m_way_node_list->rbegin(); it != m_way_node_list->rend(); ++it) { c->push_back(it->position()); } } else { for (Osmium::OSM::WayNodeList::const_iterator it = m_way_node_list->begin(); it != m_way_node_list->end(); ++it) { c->push_back(it->position()); } } geos::geom::CoordinateSequence* cs = Osmium::Geometry::geos_geometry_factory()->getCoordinateSequenceFactory()->create(c); return static_cast(Osmium::Geometry::geos_geometry_factory()->createLineString(cs)); } catch (const geos::util::GEOSException& exc) { if (Osmium::debug()) { std::cerr << "error building geometry for way #" << id() << " (returning NULL): " << exc.what(); } return NULL; } } #endif // OSMIUM_WITH_GEOS #ifdef OSMIUM_WITH_SHPLIB /** * Create Shapelib geometry of this LineString. * * Caller takes ownership. You have to call * SHPDestroyObject() with this geometry when you are done. */ SHPObject* create_shp_object() const { return create_line_or_polygon(SHPT_ARC); } #endif // OSMIUM_WITH_SHPLIB #ifdef OSMIUM_WITH_OGR /** * Create OGR geometry of this LineString; * * Caller takes ownership. */ OGRLineString* create_ogr_geometry() const { OGRLineString* p = new OGRLineString(); if (m_reverse) { for (Osmium::OSM::WayNodeList::const_reverse_iterator it = m_way_node_list->rbegin(); it != m_way_node_list->rend(); ++it) { p->addPoint(it->lon(), it->lat()); } } else { for (Osmium::OSM::WayNodeList::const_iterator it = m_way_node_list->begin(); it != m_way_node_list->end(); ++it) { p->addPoint(it->lon(), it->lat()); } } return p; } #endif // OSMIUM_WITH_OGR #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void *)this); } v8::Handle js_to_array(const v8::Arguments& /*args*/) { v8::HandleScope scope; v8::Local linestring = v8::Array::New(m_way_node_list->size()); unsigned int max = m_way_node_list->size() - 1; if (m_reverse) { for (unsigned int i=0; i <= max; ++i) { linestring->Set(max - i, (*m_way_node_list)[i].position().js_to_array()); } } else { for (unsigned int i=0; i <= max; ++i) { linestring->Set(i, (*m_way_node_list)[i].position().js_to_array()); } } return scope.Close(linestring); } struct JavascriptTemplate : public Osmium::Geometry::Geometry::JavascriptTemplate { JavascriptTemplate() : Osmium::Geometry::Geometry::JavascriptTemplate() { js_template->Set("toArray", v8::FunctionTemplate::New(function_template)); } }; #endif // OSMIUM_WITH_JAVASCRIPT }; // class LineString } // namespace Geometry } // namespace Osmium #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle Osmium::OSM::Way::js_geom() const { if (m_node_list.has_position()) { Osmium::Geometry::LineString* geom = new Osmium::Geometry::LineString(*this); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } else { Osmium::Geometry::Null* geom = new Osmium::Geometry::Null(); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } } v8::Handle Osmium::OSM::Way::js_reverse_geom() const { if (m_node_list.has_position()) { Osmium::Geometry::LineString* geom = new Osmium::Geometry::LineString(*this, true); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } else { Osmium::Geometry::Null* geom = new Osmium::Geometry::Null(); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } } #endif // OSMIUM_WITH_JAVASCRIPT #endif // OSMIUM_GEOMETRY_LINESTRING_HPP osmium/include/osmium/geometry/point.hpp0000664000175000017500000001315511706551765020004 0ustar daviddavid#ifndef OSMIUM_GEOMETRY_POINT_HPP #define OSMIUM_GEOMETRY_POINT_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #ifdef OSMIUM_WITH_GEOS # include #endif // OSMIUM_WITH_GEOS #include #include namespace Osmium { namespace Geometry { /** * Point geometry. */ class Point : public Geometry { public: /** * Create point geometry from a position. */ Point(const Osmium::OSM::Position& position, osm_object_id_t id=0) : Geometry(id), m_position(position) { } /** * Create point geometry from position of a node. */ Point(const Osmium::OSM::Node& node) : Geometry(node.id()), m_position(Osmium::OSM::Position(node.get_lon(), node.get_lat())) { } double lon() const { return m_position.lon(); } double lat() const { return m_position.lat(); } std::ostream& write_to_stream(std::ostream& out, AsWKT, bool with_srid=false) const { if (with_srid) { out << "SRID=4326;"; } return out << "POINT(" << std::setprecision(10) << lon() << " " << lat() << ")"; } std::ostream& write_to_stream(std::ostream& out, AsWKB, bool with_srid=false) const { write_binary_wkb_header(out, with_srid, wkbPoint); write_binary(out, lon()); write_binary(out, lat()); return out; } std::ostream& write_to_stream(std::ostream& out, AsHexWKB, bool with_srid=false) const { write_hex_wkb_header(out, with_srid, wkbPoint); write_hex(out, lon()); write_hex(out, lat()); return out; } #ifdef OSMIUM_WITH_GEOS /** * Creates GEOS geometry of this Point. * * Caller takes ownership. */ geos::geom::Point* create_geos_geometry() const { return Osmium::Geometry::geos_geometry_factory()->createPoint(m_position); } #endif // OSMIUM_WITH_GEOS #ifdef OSMIUM_WITH_SHPLIB /** * Create Shapelib geometry of this Point. * * Caller takes ownership. You have to call * SHPDestroyObject() with this geometry when you are done. */ SHPObject* create_shp_object() const { double x = lon(); double y = lat(); return SHPCreateSimpleObject(SHPT_POINT, 1, &x, &y, NULL); } #endif // OSMIUM_WITH_SHPLIB #ifdef OSMIUM_WITH_OGR /** * Create OGR geometry of this Point. * * Caller takes ownership. */ OGRPoint* create_ogr_geometry() const { OGRPoint* p = new OGRPoint(lon(), lat()); return p; } #endif // OSMIUM_WITH_OGR #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void*)this); } v8::Handle js_lon() const { return v8::Number::New(lon()); } v8::Handle js_lat() const { return v8::Number::New(lat()); } v8::Handle js_to_array(const v8::Arguments& /*args*/) { return m_position.js_to_array(); } struct JavascriptTemplate : public Osmium::Geometry::Geometry::JavascriptTemplate { JavascriptTemplate() : Osmium::Geometry::Geometry::JavascriptTemplate() { js_template->SetAccessor(v8::String::NewSymbol("lon"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("lat"), accessor_getter); js_template->Set("toArray", v8::FunctionTemplate::New(function_template)); } }; #endif // OSMIUM_WITH_JAVASCRIPT private: const Osmium::OSM::Position m_position; }; // class Point } // namespace Geometry } // namespace Osmium #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle Osmium::OSM::Node::js_get_geom() const { Osmium::Geometry::Point* geom = new Osmium::Geometry::Point(*this); return Osmium::Javascript::Template::get().create_persistent_instance(geom); } #endif // OSMIUM_WITH_JAVASCRIPT #endif // OSMIUM_GEOMETRY_POINT_HPP osmium/include/osmium/osm.hpp0000664000175000017500000000256311706551765015617 0ustar daviddavid#ifndef OSMIUM_OSM_HPP #define OSMIUM_OSM_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ namespace Osmium { /** * @brief Basic classes for tags, nodes, ways, etc. */ namespace OSM { } // namespace OSM } // namespace Osmium #include #include #include #include #include #include #include #include #include #include #endif // OSMIUM_OSM_HPP osmium/include/osmium/output/0000775000175000017500000000000011706551765015642 5ustar daviddavidosmium/include/osmium/output/xml.hpp0000664000175000017500000002137711706551765017165 0ustar daviddavid#ifndef OSMIUM_OUTPUT_XML_HPP #define OSMIUM_OUTPUT_XML_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ // this is required to allow using libxml's xmlwriter in parallel to expat xml parser under debian #undef XMLCALL #include // XXX error handling is mostly missing... namespace Osmium { namespace Output { class XML : public Base { public: XML(Osmium::OSMFile& file) : Base(file), m_last_op('\0') { xml_writer = xmlNewTextWriter(xmlOutputBufferCreateFd(this->get_fd(), NULL)); } ~XML() { } void init(Osmium::OSM::Meta& meta) { xmlTextWriterSetIndent(xml_writer, 1); xmlTextWriterSetIndentString(xml_writer, BAD_CAST " "); xmlTextWriterStartDocument(xml_writer, NULL, "utf-8", NULL); // if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { xmlTextWriterStartElement(xml_writer, BAD_CAST "osmChange"); // } else { xmlTextWriterStartElement(xml_writer, BAD_CAST "osm"); // } xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "version", BAD_CAST "0.6"); xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "generator", BAD_CAST "Osmium (http://wiki.openstreetmap.org/wiki/Osmium)"); if (meta.bounds().defined()) { xmlTextWriterStartElement(xml_writer, BAD_CAST "bounds"); // xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "minlon", "%.7f", meta.bounds().bl().lon()); xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "minlat", "%.7f", meta.bounds().bl().lat()); xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "maxlon", "%.7f", meta.bounds().tr().lon()); xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "maxlat", "%.7f", meta.bounds().tr().lat()); xmlTextWriterEndElement(xml_writer); // } } void node(const shared_ptr& node) { if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { open_close_op_tag(node->visible() ? (node->version() == 1 ? 'c' : 'm') : 'd'); } xmlTextWriterStartElement(xml_writer, BAD_CAST "node"); // write_meta(node); const Osmium::OSM::Position position = node->position(); xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "lat", "%.7f", position.lat()); xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "lon", "%.7f", position.lon()); write_tags(node->tags()); xmlTextWriterEndElement(xml_writer); // } void way(const shared_ptr& way) { if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { open_close_op_tag(way->visible() ? (way->version() == 1 ? 'c' : 'm') : 'd'); } xmlTextWriterStartElement(xml_writer, BAD_CAST "way"); // write_meta(way); Osmium::OSM::WayNodeList::const_iterator end = way->nodes().end(); for (Osmium::OSM::WayNodeList::const_iterator it = way->nodes().begin(); it != end; ++it) { xmlTextWriterStartElement(xml_writer, BAD_CAST "nd"); // xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "ref", "%d", it->ref()); xmlTextWriterEndElement(xml_writer); // } write_tags(way->tags()); xmlTextWriterEndElement(xml_writer); // } void relation(const shared_ptr& relation) { if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { open_close_op_tag(relation->visible() ? (relation->version() == 1 ? 'c' : 'm') : 'd'); } xmlTextWriterStartElement(xml_writer, BAD_CAST "relation"); // write_meta(relation); Osmium::OSM::RelationMemberList::const_iterator end = relation->members().end(); for (Osmium::OSM::RelationMemberList::const_iterator it = relation->members().begin(); it != end; ++it) { xmlTextWriterStartElement(xml_writer, BAD_CAST "member"); // xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "type", BAD_CAST it->type_name()); xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "ref", "%d", it->ref()); xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "role", BAD_CAST it->role()); xmlTextWriterEndElement(xml_writer); // } write_tags(relation->tags()); xmlTextWriterEndElement(xml_writer); // } void final() { if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { open_close_op_tag('\0'); } xmlTextWriterEndElement(xml_writer); // or xmlFreeTextWriter(xml_writer); m_file.close(); } private: xmlTextWriterPtr xml_writer; void write_meta(const shared_ptr& object) { xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "id", "%d", object->id()); xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "version", "%d", object->version()); xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "timestamp", BAD_CAST object->timestamp_as_string().c_str()); // uid == 0 -> anonymous if (object->uid() > 0) { xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "uid", "%d", object->uid()); xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "user", BAD_CAST object->user()); } xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "changeset", "%d", object->changeset()); if (m_file.has_multiple_object_versions() && m_file.get_type() != Osmium::OSMFile::FileType::Change()) { xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "visible", object->visible() ? BAD_CAST "true" : BAD_CAST "false"); } } void write_tags(const Osmium::OSM::TagList& tags) { Osmium::OSM::TagList::const_iterator end = tags.end(); for (Osmium::OSM::TagList::const_iterator it = tags.begin(); it != end; ++it) { xmlTextWriterStartElement(xml_writer, BAD_CAST "tag"); // xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "k", BAD_CAST it->key()); xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "v", BAD_CAST it->value()); xmlTextWriterEndElement(xml_writer); // } } char m_last_op; void open_close_op_tag(char op) { if (op == m_last_op) { return; } if (m_last_op) { xmlTextWriterEndElement(xml_writer); } switch (op) { case 'c': xmlTextWriterStartElement(xml_writer, BAD_CAST "create"); break; case 'm': xmlTextWriterStartElement(xml_writer, BAD_CAST "modify"); break; case 'd': xmlTextWriterStartElement(xml_writer, BAD_CAST "delete"); break; } m_last_op = op; } }; // class XML } // namespace Output } // namespace Osmium #endif // OSMIUM_OUTPUT_XML_HPP osmium/include/osmium/output/pbf.hpp0000664000175000017500000012040611706551765017125 0ustar daviddavid#ifndef OSMIUM_OUTPUT_PBF_HPP #define OSMIUM_OUTPUT_PBF_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ /* About the .osm.pbf file format This is an excerpt of The .osm.pbf format and it's derived formats (.osh.pbf and .osc.pbf) are encoded using googles protobuf library for the low-level storage. They are constructed by nesting data on two levels: On the lower level the file is constructed using BlobHeaders and Blobs. A .osm.pbf file contains multiple sequences of 1. a 4-byte header size, stored in network-byte-order 2. a BlobHeader of exactly this size 3. a Blob The BlobHeader tells the reader about the type and size of the following Blob. The Blob can contain data in raw or zlib-compressed form. After uncompressing the blob it is treated differently depending on the type specified in the BlobHeader. The contents of the Blob belongs to the higher level. It contains either an HeaderBlock (type="OSMHeader") or an PrimitiveBlock (type="OSMData"). The file needs to have at least one HeaderBlock before the first PrimitiveBlock. The HeaderBlock contains meta-information like the writing program or a bbox. It may also contain multiple "required features" that describe what kinds of input a reading program needs to handle in order to fully understand the files' contents. The PrimitiveBlock can store multiple types of objects (i.e. 5 nodes, 2 ways and 1 relation). It contains one or more PrimitiveGroup which in turn contain multiple nodes, ways or relations. A PrimitiveGroup should only contain one kind of object. There's a special kind of "object type" called dense-nodes. It is used to store nodes in a very dense format, avoiding message overheads and using delta-encoding for nearly all ids. All Strings are stored as indexes to rows in a StringTable. The StringTable contains one row for each used string, so strings that are used multiple times need to be stored only once. The StringTable is sorted by usage-count, so the most often used string is stored at index 1. A simple outline of a .osm.pbf file could look like this: 4-bytes header size BlobHeader Blob HeaderBlock 4-bytes header size BlobHeader Blob PrimitiveBlock StringTable PrimitiveGroup 5 nodes PrimitiveGroup 2 ways PrimitiveGroup 1 relation More complete outlines of real .osm.pbf files can be created using the osmpbf-outline tool: */ // netinet provides the network-byte-order conversion function #include // the algorithm-lib contains the sort functions #include // math is used for round() in lonlat2int #include #include #include // StringTable management #include #include namespace Osmium { namespace Output { class PBF : public Base { /** * Maximum number of items in a primitive block. * * The uncompressed length of a Blob *should* be less * than 16 megabytes and *must* be less than 32 megabytes. * * A block may contain any number of entities, as long as * the size limits for the surrounding blob are obeyed. * However, for simplicity, the current Osmosis (0.38) * as well as Osmium implementation always * uses at most 8k entities in a block. */ static const uint32_t max_block_contents = 8000; /** * The output buffer (block) will be filled to about * 95% and then written to disk. This leaves more than * enough space for the string table (which typically * needs about 0.1 to 0.3% of the block size). */ static const int buffer_fill_percent = 95; /** * protobuf-struct of a Blob */ OSMPBF::Blob pbf_blob; /** * protobuf-struct of a BlobHeader */ OSMPBF::BlobHeader pbf_blob_header; /** * protobuf-struct of a HeaderBlock */ OSMPBF::HeaderBlock pbf_header_block; /** * protobuf-struct of a PrimitiveBlock */ OSMPBF::PrimitiveBlock pbf_primitive_block; /** * pointer to PrimitiveGroups inside the current PrimitiveBlock, * used for writing nodes, ways or relations */ OSMPBF::PrimitiveGroup* pbf_nodes; OSMPBF::PrimitiveGroup* pbf_ways; OSMPBF::PrimitiveGroup* pbf_relations; /** * to flexibly handle multiple resolutions, the granularity, or * resolution used for representing locations is adjustable in * multiples of 1 nanodegree. The default scaling factor is 100 * nanodegrees, corresponding to about ~1cm at the equator. * These is the current resolution of the OSM database. */ int m_location_granularity; /** * the granularity used for representing timestamps is also adjustable in * multiples of 1 millisecond. The default scaling factor is 1000 * milliseconds, which is the current resolution of the OSM database. */ int m_date_granularity; /** * should nodes be serialized into the dense format? * * nodes can be encoded one of two ways, as a Node * (m_use_dense_format = false) and a special dense format. * In the dense format, all information is stored 'column wise', * as an array of ID's, array of latitudes, and array of * longitudes. Each column is delta-encoded. This reduces * header overheads and allows delta-coding to work very effectively. */ bool m_use_dense_format; /** * should the PBF blobs contain zlib compressed data? * * the zlib compression is optional, it's possible to store the * blobs in raw format. Disabling the compression can improve the * writing speed a little but the output will be 2x to 3x bigger. */ bool m_use_compression; /** * While the .osm.pbf-format is able to carry all meta information, it is * also able to omit this information to reduce size. */ bool m_should_add_metadata; /** * Should the visible flag be added on objects? */ bool m_add_visible; /** * counter used to quickly check the number of objects stored inside * the current PrimitiveBlock. When the counter reaches max_block_contents * the PrimitiveBlock is serialized into a Blob and flushed to the file. * * this check is performed in check_block_contents_counter() which is * called once for each object. */ uint16_t primitive_block_contents; uint32_t primitive_block_size; // StringTable management Osmium::StringTable string_table; /// Buffer used while compressing blobs. char m_compression_buffer[OSMPBF::max_uncompressed_blob_size]; /** * These variables are used to calculate the * delta-encoding while storing dense-nodes. It holds the last seen values * from which the difference is stored into the protobuf. */ Delta m_delta_id; Delta m_delta_lat; Delta m_delta_lon; Delta m_delta_timestamp; Delta m_delta_changeset; Delta m_delta_uid; Delta m_delta_user_sid; ///// Blob writing ///// /** * Take a string and pack its contents. * * @param in String input. * @return Number of bytes after compression. */ size_t zlib_compress(std::string &in) { // zlib compression context z_stream z; // next byte to compress z.next_in = (uint8_t*) in.c_str(); // number of bytes to compress z.avail_in = in.size(); // place to store compressed bytes z.next_out = (uint8_t*) m_compression_buffer; // space for compressed data z.avail_out = OSMPBF::max_uncompressed_blob_size; // custom allocator functions - not used z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; // initiate the compression if (deflateInit(&z, Z_DEFAULT_COMPRESSION) != Z_OK) { throw std::runtime_error("failed to init zlib stream"); } // compress if (deflate(&z, Z_FINISH) != Z_STREAM_END) { throw std::runtime_error("failed to deflate zlib stream"); } // finish compression if (deflateEnd(&z) != Z_OK) { throw std::runtime_error("failed to deinit zlib stream"); } // print debug info about the compression if (Osmium::debug()) { std::cerr << "pack " << in.size() << " bytes to " << z.total_out << " bytes (1:" << (double)in.size() / z.total_out << ")" << std::endl; } // number of compressed bytes return z.total_out; } /** * Serialize a protobuf-message together into a Blob, optionally apply compression * and write it together with a BlobHeader to the file. * * @param type Type-string used in the BlobHeader. * @param msg Protobuf-message. */ void store_blob(const std::string &type, const google::protobuf::MessageLite &msg) { // buffer to serialize the protobuf message to std::string data; // serialize the protobuf message to the string msg.SerializeToString(&data); if (use_compression()) { // compress using zlib size_t out = zlib_compress(data); // set the compressed data on the Blob pbf_blob.set_zlib_data(m_compression_buffer, out); } else { // no compression // print debug info about the raw data if (Osmium::debug()) { std::cerr << "store uncompressed " << data.size() << " bytes" << std::endl; } // just set the raw data on the Blob pbf_blob.set_raw(data); } // set the size of the uncompressed data on the blob pbf_blob.set_raw_size(data.size()); // clear the blob string data.clear(); // serialize and clear the Blob pbf_blob.SerializeToString(&data); pbf_blob.Clear(); // set the header-type to the supplied string on the BlobHeader pbf_blob_header.set_type(type); // set the size of the serialized blob on the BlobHeader pbf_blob_header.set_datasize(data.size()); // a place to serialize the BlobHeader to std::string blobhead; // serialize and clear the BlobHeader pbf_blob_header.SerializeToString(&blobhead); pbf_blob_header.Clear(); // the 4-byte size of the BlobHeader, transformed from Host- to Network-Byte-Order uint32_t sz = htonl(blobhead.size()); // write to the file: the 4-byte BlobHeader-Size followed by the BlobHeader followed by the Blob if (::write(get_fd(), &sz, sizeof(sz)) < 0) { throw std::runtime_error("file error"); } if (::write(get_fd(), blobhead.c_str(), blobhead.size()) < 0) { throw std::runtime_error("file error"); } if (::write(get_fd(), data.c_str(), data.size()) < 0) { throw std::runtime_error("file error"); } } /** * Before a PrimitiveBlock gets serialized, all interim StringTable-ids needs to be * mapped to the associated real StringTable ids. This is done in this function. * * This function needs to know about the concrete structure of all item types to find * all occurrences of string-ids. */ void map_string_ids() { // test, if the node-block has been allocated if (pbf_nodes) { // iterate over all nodes, passing them to the map_common_string_ids function for (int i=0, l=pbf_nodes->nodes_size(); imutable_nodes(i)); } // test, if the node-block has a densenodes structure if (pbf_nodes->has_dense()) { // get a pointer to the densenodes structure OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense(); // in the densenodes structure keys and vals are encoded in an intermixed // array, individual nodes are seperated by a value of 0 (0 in the StringTable // is always unused). String-ids of 0 are thus kept alone. for (int i=0, l=dense->keys_vals_size(); i 0 to real string ids uint16_t sid = dense->keys_vals(i); if (sid > 0) { dense->set_keys_vals(i, string_table.map_string_id(sid)); } } // test if the densenodes block has meta infos if (dense->has_denseinfo()) { // get a pointer to the denseinfo structure OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); // iterate over all username string-ids for (int i=0, l= denseinfo->user_sid_size(); i 0 to real string ids uint16_t user_sid = string_table.map_string_id(denseinfo->user_sid(i)); // delta encode the string-id denseinfo->set_user_sid(i, m_delta_user_sid.update(user_sid)); } } } } // test, if the ways-block has been allocated if (pbf_ways) { // iterate over all ways, passing them to the map_common_string_ids function for (int i=0, l=pbf_ways->ways_size(); imutable_ways(i)); } } // test, if the relations-block has been allocated if (pbf_relations) { // iterate over all relations for (int i=0, l=pbf_relations->relations_size(); imutable_relations(i); // pass them to the map_common_string_ids function map_common_string_ids(relation); // iterate over all relation members, mapping the interim string-ids // of the role to real string ids for (int mi=0, ml=relation->roles_sid_size(); miset_roles_sid(mi, string_table.map_string_id(relation->roles_sid(mi))); } } } } /** * a helper function used in map_string_ids to map common interim string-ids of the * user name and all tags to real string ids. * * pbf_object_t is either OSMPBF::Node, OSMPBF::Way or OSMPBF::Relation. */ template void map_common_string_ids(pbf_object_t* in) { // if the object has meta-info attached if (in->has_info()) { // map the interim-id of the user name to a real id OSMPBF::Info* info = in->mutable_info(); info->set_user_sid(string_table.map_string_id(info->user_sid())); } // iterate over all tags and map the interim-ids of the key and the value to real ids for (int i=0, l=in->keys_size(); iset_keys(i, string_table.map_string_id(in->keys(i))); in->set_vals(i, string_table.map_string_id(in->vals(i))); } } ///// MetaData helper ///// /** * convert a double lat or lon value to an int, respecting the current blocks granularity */ int64_t lonlat2int(double lonlat) { return round(lonlat * OSMPBF::lonlat_resolution / location_granularity()); } /** * convert a timestamp to an int, respecting the current blocks granularity */ int64_t timestamp2int(time_t timestamp) { return round(timestamp * ((double)1000 / date_granularity())); } /** * helper function used in the write()-calls to apply common information from an osmium-object * onto a pbf-object. * * pbf_object_t is either OSMPBF::Node, OSMPBF::Way or OSMPBF::Relation. */ template void apply_common_info(const shared_ptr& in, pbf_object_t* out) { // set the object-id out->set_id(in->id()); // iterate over all tags and set the keys and vals, recording the strings in the // interim StringTable and storing the interim ids Osmium::OSM::TagList::const_iterator end = in->tags().end(); for (Osmium::OSM::TagList::const_iterator it = in->tags().begin(); it != end; ++it) { out->add_keys(string_table.record_string(it->key())); out->add_vals(string_table.record_string(it->value())); } if (should_add_metadata()) { // add an info-section to the pbf object and set the meta-info on it OSMPBF::Info* out_info = out->mutable_info(); if (m_add_visible) { out_info->set_visible(in->visible()); } out_info->set_version(in->version()); out_info->set_timestamp(timestamp2int(in->timestamp())); out_info->set_changeset(in->changeset()); out_info->set_uid(in->uid()); out_info->set_user_sid(string_table.record_string(in->user())); } } ///// High-Level Block writing ///// /** * store the current pbf_header_block into a Blob and clear this struct afterwards. */ void store_header_block() { if (Osmium::debug()) { std::cerr << "storing header block" << std::endl; } store_blob("OSMHeader", pbf_header_block); pbf_header_block.Clear(); } /** * store the interim StringTable to the current pbf_primitive_block, map all interim string ids * to real StringTable ids and then store the current pbf_primitive_block into a Blob and clear * this struct and all related pointers and maps afterwards. */ void store_primitive_block() { if (Osmium::debug()) { std::cerr << "storing primitive block with " << primitive_block_contents << " items" << std::endl; } // store the interim StringTable into the protobuf object string_table.store_stringtable(pbf_primitive_block.mutable_stringtable()); // map all interim string ids to real ids map_string_ids(); // store the Blob store_blob("OSMData", pbf_primitive_block); // clear the PrimitiveBlock struct pbf_primitive_block.Clear(); // add empty StringTable entry at index 0 // StringTable index 0 is rserved as delimiter in the densenodes key/value list // this line also ensures that there's always a valid StringTable pbf_primitive_block.mutable_stringtable()->add_s(""); // set the granularity pbf_primitive_block.set_granularity(location_granularity()); pbf_primitive_block.set_date_granularity(date_granularity()); // clear the interim StringTable and its id map string_table.clear(); // reset the delta variables m_delta_id.clear(); m_delta_lat.clear(); m_delta_lon.clear(); m_delta_timestamp.clear(); m_delta_changeset.clear(); m_delta_uid.clear(); m_delta_user_sid.clear(); // reset the contents-counter to zero primitive_block_contents = 0; primitive_block_size = 0; // reset the node/way/relation pointers to NULL pbf_nodes = NULL; pbf_ways = NULL; pbf_relations = NULL; } /** * this little function checks primitive_block_contents counter against its maximum and calls * store_primitive_block to flush the block to the disk when it's reached. It's also responsible * for increasing this counter. * * this function also checks the estimated size of the current block and calls store_primitive_block * when the estimated size reaches buffer_fill_percent of the maximum uncompressed blob size. */ void check_block_contents_counter() { if (primitive_block_contents >= max_block_contents) { store_primitive_block(); } else if (primitive_block_size > (static_cast(OSMPBF::max_uncompressed_blob_size) * buffer_fill_percent / 100)) { if (Osmium::debug()) { std::cerr << "storing primitive_block with only " << primitive_block_contents << " items, because its ByteSize (" << primitive_block_size << ") reached " << (static_cast(primitive_block_size) / static_cast(OSMPBF::max_uncompressed_blob_size) * 100.0) << "% of the maximum blob-size" << std::endl; } store_primitive_block(); } primitive_block_contents++; } ///// Block content writing ///// /** * Add a node to the block. * * @param node The node to add. */ void write_node(const shared_ptr& node) { // add a way to the group OSMPBF::Node* pbf_node = pbf_nodes->add_nodes(); // copy the common meta-info from the osmium-object to the pbf-object apply_common_info(node, pbf_node); // modify lat & lon to integers, respecting the block's granularity and copy // the ints to the pbf-object pbf_node->set_lon(lonlat2int(node->get_lon())); pbf_node->set_lat(lonlat2int(node->get_lat())); } /** * Add a node to the block using DenseNodes. * * @param node The node to add. */ void write_dense_node(const shared_ptr& node) { // add a DenseNodes-Section to the PrimitiveGroup OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense(); // copy the id, delta encoded dense->add_id(m_delta_id.update(node->id())); // copy the longitude, delta encoded dense->add_lon(m_delta_lon.update(lonlat2int(node->get_lon()))); // copy the latitude, delta encoded dense->add_lat(m_delta_lat.update(lonlat2int(node->get_lat()))); // in the densenodes structure keys and vals are encoded in an intermixed // array, individual nodes are seperated by a value of 0 (0 in the StringTable // is always unused) // so for three nodes the keys_vals array may look like this: 3 5 2 1 0 0 8 5 // the first node has two tags (3=>5 and 2=>1), the second node has does not // have any tags and the third node has a single tag (8=>5) Osmium::OSM::TagList::const_iterator end = node->tags().end(); for (Osmium::OSM::TagList::const_iterator it = node->tags().begin(); it != end; ++it) { dense->add_keys_vals(string_table.record_string(it->key())); dense->add_keys_vals(string_table.record_string(it->value())); } dense->add_keys_vals(0); if (should_add_metadata()) { // add a DenseInfo-Section to the PrimitiveGroup OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); denseinfo->add_version(node->version()); if (m_add_visible) { denseinfo->add_visible(node->visible()); } // copy the timestamp, delta encoded denseinfo->add_timestamp(m_delta_timestamp.update(timestamp2int(node->timestamp()))); // copy the changeset, delta encoded denseinfo->add_changeset(m_delta_changeset.update(node->changeset())); // copy the user id, delta encoded denseinfo->add_uid(m_delta_uid.update(node->uid())); // record the user-name to the interim stringtable and copy the // interim string-id to the pbf-object denseinfo->add_user_sid(string_table.record_string(node->user())); } } /** * Add a way to the block. * * @param way The way to add. */ void write_way(const shared_ptr& way) { // add a way to the group OSMPBF::Way* pbf_way = pbf_ways->add_ways(); // copy the common meta-info from the osmium-object to the pbf-object apply_common_info(way, pbf_way); // last way-node-id used for delta-encoding Delta delta_id; // iterate over all way-nodes for (int i=0, l = way->node_count(); iadd_refs(delta_id.update(way->get_node_id(i))); } // count up blob size by the size of the Way primitive_block_size += pbf_way->ByteSize(); } /** * Add a relation to the block. * * @param relation The relation to add. */ void write_relation(const shared_ptr& relation) { // add a relation to the group OSMPBF::Relation* pbf_relation = pbf_relations->add_relations(); // copy the common meta-info from the osmium-object to the pbf-object apply_common_info(relation, pbf_relation); Delta delta_id; // iterate over all relation-members for (int i=0, l=relation->members().size(); iget_member(i); // record the relation-member role to the interim stringtable and copy the // interim string-id to the pbf-object pbf_relation->add_roles_sid(string_table.record_string(mem->role())); // copy the relation-member-id, delta encoded pbf_relation->add_memids(delta_id.update(mem->ref())); // copy the relation-member-type, mapped to the OSMPBF enum switch (mem->type()) { case 'n': pbf_relation->add_types(OSMPBF::Relation::NODE); break; case 'w': pbf_relation->add_types(OSMPBF::Relation::WAY); break; case 'r': pbf_relation->add_types(OSMPBF::Relation::RELATION); break; default: throw std::runtime_error("Unknown relation member type: " + mem->type()); } } // count up blob size by the size of the Relation primitive_block_size += pbf_relation->ByteSize(); } public: /** * Create PBF output object from OSMFile. */ PBF(Osmium::OSMFile& file) : Base(file), pbf_nodes(NULL), pbf_ways(NULL), pbf_relations(NULL), m_location_granularity(pbf_primitive_block.granularity()), m_date_granularity(pbf_primitive_block.date_granularity()), m_use_dense_format(true), m_use_compression(true), m_should_add_metadata(true), m_add_visible(file.has_multiple_object_versions()), primitive_block_contents(0), primitive_block_size(0), string_table(), m_compression_buffer(), m_delta_id(), m_delta_lat(), m_delta_lon(), m_delta_timestamp(), m_delta_changeset(), m_delta_uid(), m_delta_user_sid() { GOOGLE_PROTOBUF_VERIFY_VERSION; } /** * getter to check whether the densenodes-feature is used */ bool use_dense_format() const { return m_use_dense_format; } /** * setter to set whether the densenodes-feature is used */ PBF& use_dense_format(bool flag) { m_use_dense_format = flag; return *this; } /** * getter to check whether zlib-compression is used */ bool use_compression() const { return m_use_compression; } /** * setter to set whether zlib-compression is used */ PBF& use_compression(bool flag) { m_use_compression = flag; return *this; } /** * getter to access the granularity */ int location_granularity() const { return m_location_granularity; } /** * setter to set the granularity */ PBF& location_granularity(int g) { m_location_granularity = g; return *this; } /** * getter to access the date_granularity */ int date_granularity() const { return m_date_granularity; } /** * Set date granularity. */ PBF& date_granularity(int g) { m_date_granularity = g; return *this; } /** * Getter to check whether metadata should be added. */ bool should_add_metadata() const { return m_should_add_metadata; } /** * Setter to set whether to add metadata. */ PBF& should_add_metadata(bool flag) { m_should_add_metadata = flag; return *this; } /** * Initialize the writing process. * * This initializes the header-block, sets the required-features and * the writing-program and adds the obligatory StringTable-Index 0. */ void init(Osmium::OSM::Meta& meta) { if (Osmium::debug()) { std::cerr << "pbf write init" << std::endl; } // add the schema version as required feature to the HeaderBlock pbf_header_block.add_required_features("OsmSchema-V0.6"); // when the densenodes-feature is used, add DenseNodes as required feature if (use_dense_format()) { pbf_header_block.add_required_features("DenseNodes"); } // when the resulting file will carry history information, add // HistoricalInformation as required feature if (m_file.get_type() == Osmium::OSMFile::FileType::History()) { pbf_header_block.add_required_features("HistoricalInformation"); } // set the writing program pbf_header_block.set_writingprogram("Osmium (http://wiki.openstreetmap.org/wiki/Osmium)"); if (meta.bounds().defined()) { OSMPBF::HeaderBBox* bbox = pbf_header_block.mutable_bbox(); bbox->set_left(meta.bounds().bl().lon() * OSMPBF::lonlat_resolution); bbox->set_bottom(meta.bounds().bl().lat() * OSMPBF::lonlat_resolution); bbox->set_right(meta.bounds().tr().lon() * OSMPBF::lonlat_resolution); bbox->set_top(meta.bounds().tr().lat() * OSMPBF::lonlat_resolution); } store_header_block(); // add empty StringTable entry at index 0 // StringTable index 0 is reserved as delimiter in the densenodes key/value list // this line also ensures that there's always a valid StringTable pbf_primitive_block.mutable_stringtable()->add_s(""); // set the granularity pbf_primitive_block.set_granularity(location_granularity()); pbf_primitive_block.set_date_granularity(date_granularity()); } /** * Add a node to the pbf. * * A call to this method won't write the node to the file directly but * cache it for later bulk-writing. Calling write_final ensures that everything * gets written and every file pointer is closed. */ void node(const shared_ptr& node) { // first of we check the contents-counter which may flush the cached nodes to // disk if the limit is reached. This call also increases the contents-counter check_block_contents_counter(); if (Osmium::debug()) { std::cerr << "node " << node->id() << " v" << node->version() << std::endl; } // if no PrimitiveGroup for nodes has been added, add one and save the pointer if (!pbf_nodes) { pbf_nodes = pbf_primitive_block.add_primitivegroup(); } if (use_dense_format()) { write_dense_node(node); } else { write_node(node); } } /** * Add a way to the pbf. * * A call to this method won't write the way to the file directly but * cache it for later bulk-writing. Calling write_final ensures that everything * gets written and every file pointer is closed. */ void way(const shared_ptr& way) { // first of we check the contents-counter which may flush the cached ways to // disk if the limit is reached. This call also increases the contents-counter check_block_contents_counter(); if (Osmium::debug()) { std::cerr << "way " << way->id() << " v" << way->version() << " with " << way->node_count() << " nodes" << std::endl; } // if no PrimitiveGroup for nodes has been added, add one and save the pointer if (!pbf_ways) { pbf_ways = pbf_primitive_block.add_primitivegroup(); } write_way(way); } /** * Add a relation to the pbf. * * A call to this method won't write the way to the file directly but * cache it for later bulk-writing. Calling write_final ensures that everything * gets written and every file pointer is closed. */ void relation(const shared_ptr& relation) { // first of we check the contents-counter which may flush the cached relations to // disk if the limit is reached. This call also increases the contents-counter check_block_contents_counter(); if (Osmium::debug()) { std::cerr << "relation " << relation->id() << " v" << relation->version() << " with " << relation->members().size() << " members" << std::endl; } // if no PrimitiveGroup for relations has been added, add one and save the pointer if (!pbf_relations) { pbf_relations = pbf_primitive_block.add_primitivegroup(); } write_relation(relation); } /** * Finalize the writing process, flush any open primitive blocks to the file and * close the file. */ void final() { if (Osmium::debug()) { std::cerr << "finishing" << std::endl; } // if the current block contains any elements, flush it to the protobuf if (primitive_block_contents > 0) { store_primitive_block(); } m_file.close(); } }; // class PBF } // namespace Output } // namespace Osmium #endif // OSMIUM_OUTPUT_PBF_HPP osmium/include/osmium/HandlerJavascript.hpp0000664000175000017500000003170211706551765020422 0ustar daviddavid#ifndef OSMIUM_HANDLER_JAVASCRIPT_HPP #define OSMIUM_HANDLER_JAVASCRIPT_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include extern v8::Persistent global_context; namespace Osmium { namespace Handler { class Javascript : public Base { /*** * Load Javascript file into string */ static std::string load_file(const char* filename) { std::ifstream javascript_file(filename, std::ifstream::in); if (javascript_file.fail()) { std::cerr << "Can't open file " << filename << std::endl; exit(1); } std::stringstream buffer; buffer << javascript_file.rdbuf(); return buffer.str(); } static const char* ToCString(const v8::String::Utf8Value& value) { return *value ? *value : ""; } /** * Print Javascript exception to stderr */ static void report_exception(v8::TryCatch* try_catch) { v8::HandleScope handle_scope; v8::String::Utf8Value exception(try_catch->Exception()); const char* exception_string = ToCString(exception); v8::Handle message = try_catch->Message(); if (message.IsEmpty()) { std::cerr << exception_string << std::endl; } else { v8::String::Utf8Value filename(message->GetScriptResourceName()); std::cerr << *filename << ":" << message->GetLineNumber() << ": " << exception_string << std::endl; v8::String::Utf8Value sourceline(message->GetSourceLine()); std::cerr << *sourceline << std::endl; int start = message->GetStartColumn(); int end = message->GetEndColumn(); for (int i = 0; i < start; i++) { std::cerr << " "; } for (int i = start; i < end; i++) { std::cerr << "^"; } std::cerr << std::endl; } } v8::Persistent callbacks_object; v8::Persistent osmium_object; struct js_cb { v8::Handle init; v8::Handle node; v8::Handle way; v8::Handle relation; v8::Handle area; v8::Handle end; } cb; public: static v8::Handle Print(const v8::Arguments& args) { v8::HandleScope handle_scope; for (int i = 0; i < args.Length(); i++) { Osmium::v8_String_to_ostream(args[i]->ToString(), std::cout); std::cout << "\n"; } return handle_scope.Close(v8::Integer::New(1)); } static v8::Handle Include(const v8::Arguments& args) { for (int i=0; i < args.Length(); i++) { v8::String::Utf8Value filename(args[i]); std::string javascript_source = load_file(*filename); if (javascript_source.length() > 0) { v8::TryCatch tryCatch; v8::Handle script = v8::Script::Compile(v8::String::New(javascript_source.c_str()), v8::String::New(*filename)); if (script.IsEmpty()) { std::cerr << "Compiling included script failed:" << std::endl; report_exception(&tryCatch); exit(1); } v8::Handle result = script->Run(); if (result.IsEmpty()) { std::cerr << "Running included script failed:" << std::endl; report_exception(&tryCatch); exit(1); } } } return v8::Undefined(); } static v8::Handle OutputCSVOpen(const v8::Arguments& args) { if (args.Length() != 1) { return v8::Undefined(); } else { v8::String::Utf8Value str(args[0]); Osmium::Export::CSV* oc = new Osmium::Export::CSV(*str); return oc->js_instance(); } } #ifdef OSMIUM_WITH_SHPLIB static v8::Handle OutputShapefileOpen(const v8::Arguments& args) { if (args.Length() != 2) { return v8::Undefined(); } else { v8::String::Utf8Value str(args[0]); v8::String::AsciiValue type(args[1]); std::string filename(*str); Osmium::Export::Shapefile* oc; if (!strcmp(*type, "point")) { oc = new Osmium::Export::PointShapefile(filename); } else if (!strcmp(*type, "line")) { oc = new Osmium::Export::LineStringShapefile(filename); } else if (!strcmp(*type, "polygon")) { oc = new Osmium::Export::PolygonShapefile(filename); } else { throw std::runtime_error("unkown shapefile type"); } return oc->js_instance(); } } #endif // OSMIUM_WITH_SHPLIB Javascript(std::vector include_files, const char* filename) : Base() { // v8::HandleScope handle_scope; v8::Handle init_source = v8::String::New("Osmium = { Callbacks: {}, Output: { } };"); v8::Handle init_script = v8::Script::Compile(init_source); osmium_object = v8::Persistent::New(init_script->Run()->ToObject()); v8::Handle output_object = osmium_object->Get(v8::String::NewSymbol("Output"))->ToObject(); osmium_object->Set(v8::String::NewSymbol("debug"), v8::Boolean::New(Osmium::debug())); v8::Handle output_csv_template = v8::ObjectTemplate::New(); output_csv_template->Set(v8::String::NewSymbol("open"), v8::FunctionTemplate::New(OutputCSVOpen)); output_object->Set(v8::String::NewSymbol("CSV"), output_csv_template->NewInstance()); #ifdef OSMIUM_WITH_SHPLIB v8::Handle output_shapefile_template = v8::ObjectTemplate::New(); output_shapefile_template->Set(v8::String::NewSymbol("open"), v8::FunctionTemplate::New(OutputShapefileOpen)); output_object->Set(v8::String::NewSymbol("Shapefile"), output_shapefile_template->NewInstance()); #endif // OSMIUM_WITH_SHPLIB v8::Handle callbacks_object = osmium_object->Get(v8::String::NewSymbol("Callbacks"))->ToObject(); v8::TryCatch tryCatch; for (std::vector::const_iterator vi(include_files.begin()); vi != include_files.end(); vi++) { if (Osmium::debug()) { std::cerr << "include javascript file: " << *vi << std::endl; } std::string javascript_source = load_file((*vi).c_str()); v8::Handle script = v8::Script::Compile(v8::String::New(javascript_source.c_str()), v8::String::New((*vi).c_str())); if (script.IsEmpty()) { std::cerr << "Compiling script failed:" << std::endl; report_exception(&tryCatch); exit(1); } v8::Handle result = script->Run(); if (result.IsEmpty()) { std::cerr << "Running script failed:" << std::endl; report_exception(&tryCatch); exit(1); } } std::string javascript_source = load_file(filename); if (javascript_source.length() == 0) { std::cerr << "Javascript file " << filename << " is empty" << std::endl; exit(1); } v8::Handle script = v8::Script::Compile(v8::String::New(javascript_source.c_str()), v8::String::New(filename)); if (script.IsEmpty()) { std::cerr << "Compiling script failed:" << std::endl; report_exception(&tryCatch); exit(1); } v8::Handle result = script->Run(); if (result.IsEmpty()) { std::cerr << "Running script failed:" << std::endl; report_exception(&tryCatch); exit(1); } v8::Handle cc; cc = callbacks_object->Get(v8::String::NewSymbol("init")); if (cc->IsFunction()) { cb.init = v8::Handle::Cast(cc); } cc = callbacks_object->Get(v8::String::NewSymbol("node")); if (cc->IsFunction()) { cb.node = v8::Handle::Cast(cc); } cc = callbacks_object->Get(v8::String::NewSymbol("way")); if (cc->IsFunction()) { cb.way = v8::Handle::Cast(cc); } cc = callbacks_object->Get(v8::String::NewSymbol("relation")); if (cc->IsFunction()) { cb.relation = v8::Handle::Cast(cc); } cc = callbacks_object->Get(v8::String::NewSymbol("area")); if (cc->IsFunction()) { cb.area = v8::Handle::Cast(cc); } cc = callbacks_object->Get(v8::String::NewSymbol("end")); if (cc->IsFunction()) { cb.end = v8::Handle::Cast(cc); } } ~Javascript() { callbacks_object.Dispose(); } void init(Osmium::OSM::Meta&) { if (!cb.init.IsEmpty()) { (void) cb.init->Call(cb.init, 0, 0); } } void node(const shared_ptr& node) { if (!cb.node.IsEmpty()) { (void) cb.node->Call(node->get_instance(), 0, 0); } #ifdef OSMIUM_V8_FORCE_GC while (!v8::V8::IdleNotification()) { }; #endif // OSMIUM_V8_FORCE_GC } void way(const shared_ptr& way) { if (!cb.way.IsEmpty()) { (void) cb.way->Call(way->get_instance(), 0, 0); } #ifdef OSMIUM_V8_FORCE_GC while (!v8::V8::IdleNotification()) { }; #endif // OSMIUM_V8_FORCE_GC } void relation(const shared_ptr& relation) { if (!cb.relation.IsEmpty()) { (void) cb.relation->Call(relation->get_instance(), 0, 0); } #ifdef OSMIUM_V8_FORCE_GC while (!v8::V8::IdleNotification()) { }; #endif // OSMIUM_V8_FORCE_GC } void area(Osmium::OSM::Area* area) { if (!cb.area.IsEmpty()) { (void) cb.area->Call(area->get_instance(), 0, 0); } #ifdef OSMIUM_V8_FORCE_GC while (!v8::V8::IdleNotification()) { }; #endif // OSMIUM_V8_FORCE_GC } void final() { if (!cb.end.IsEmpty()) { (void) cb.end->Call(cb.end, 0, 0); } } }; // class Javascript } // namespace Handler } // namespace Osmium #endif // OSMIUM_HANDLER_JAVASCRIPT_HPP osmium/include/osmium/exceptions.hpp0000664000175000017500000000240211706551765017172 0ustar daviddavid#ifndef OSMIUM_EXCEPTIONS_HPP #define OSMIUM_EXCEPTIONS_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include namespace Osmium { /** * @brief Exceptions used in different parts of %Osmium. */ namespace Exception { /** * This exception is thrown when OSM data can't be assembled * into proper geometries. */ class IllegalGeometry { }; } // namespace Exception } // namespace Osmium #endif // OSMIUM_EXCEPTIONS_HPP osmium/include/osmium/osm/0000775000175000017500000000000011706551765015100 5ustar daviddavidosmium/include/osmium/osm/way_node_list.hpp0000664000175000017500000001265211706551765020457 0ustar daviddavid#ifndef OSMIUM_OSM_WAY_NODE_LIST_HPP #define OSMIUM_OSM_WAY_NODE_LIST_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace OSM { class WayNodeList { public: /** * If a WayNodeList object is created and the number of nodes is * not given to the constructor, space for this many nodes is * reserved. 99.9% of all ways have 500 or less nodes. */ static const int default_size = 500; WayNodeList(unsigned int size=default_size) : m_list() { m_list.reserve(size); } osm_sequence_id_t size() const { return m_list.size(); } void clear() { m_list.clear(); } typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; typedef std::vector::reverse_iterator reverse_iterator; typedef std::vector::const_reverse_iterator const_reverse_iterator; iterator begin() { return m_list.begin(); } const_iterator begin() const { return m_list.begin(); } iterator end() { return m_list.end(); } const_iterator end() const { return m_list.end(); } reverse_iterator rbegin() { return m_list.rbegin(); } const_reverse_iterator rbegin() const { return m_list.rbegin(); } reverse_iterator rend() { return m_list.rend(); } const_reverse_iterator rend() const { return m_list.rend(); } WayNode& operator[](int i) { return m_list[i]; } const WayNode& operator[](int i) const { return m_list[i]; } const WayNode& front() const { return m_list.front(); } const WayNode& back() const { return m_list.back(); } bool is_closed() const { return m_list.front().ref() == m_list.back().ref(); } bool has_position() const { if (m_list.empty()) { return false; } else { return m_list.back().has_position(); } } WayNodeList& add(const WayNode& way_node) { m_list.push_back(way_node); return *this; } WayNodeList& add(osm_object_id_t ref) { m_list.push_back(WayNode(ref)); return *this; } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void *)this); } v8::Handle js_length() const { return v8::Number::New(m_list.size()); } v8::Handle js_get_node_id(uint32_t index) const { return v8::Number::New(m_list[index].ref()); } v8::Handle js_enumerate_nodes() const { v8::HandleScope scope; v8::Local array = v8::Array::New(m_list.size()); for (unsigned int i=0; i < m_list.size(); ++i) { array->Set(i, v8::Integer::New(i)); } return scope.Close(array); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->SetAccessor(v8::String::NewSymbol("length"), accessor_getter); js_template->SetIndexedPropertyHandler( indexed_property_getter, 0, 0, 0, property_enumerator ); } }; #endif // OSMIUM_WITH_JAVASCRIPT private: std::vector m_list; #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local m_js_instance; #endif // OSMIUM_WITH_JAVASCRIPT }; // class WayNodeList } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_WAY_NODE_LIST_HPP osmium/include/osmium/osm/way.hpp0000664000175000017500000001740711706551765016422 0ustar daviddavid#ifndef OSMIUM_OSM_WAY_HPP #define OSMIUM_OSM_WAY_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include /** @file * @brief Contains the Osmium::OSM::Way class. */ #ifdef OSMIUM_WITH_GEOS # include # include # include # include # include #endif // OSMIUM_WITH_GEOS #include namespace Osmium { namespace OSM { class Way : public Object, boost::less_than_comparable { WayNodeList m_node_list; public: /// Construct a Way object. Way() : Object(), m_node_list() { init(); } Way(int size_of_node_list) : Object(), m_node_list(size_of_node_list) { init(); } /// Copy a Way object. Way(const Way& w) : Object(w) { init(); m_node_list = w.m_node_list; } const WayNodeList& nodes() const { return m_node_list; } WayNodeList& nodes() { return m_node_list; } private: void init() { #ifdef OSMIUM_WITH_JAVASCRIPT v8::HandleScope handle_scope; js_object_instance = v8::Persistent::New(JavascriptTemplate::get().create_instance(this)); #endif // OSMIUM_WITH_JAVASCRIPT } public: osm_object_type_t get_type() const { return WAY; } osm_object_id_t get_node_id(osm_sequence_id_t n) const { return m_node_list[n].ref(); } double get_lon(osm_sequence_id_t n) const { return m_node_list[n].position().lon(); } double get_lat(osm_sequence_id_t n) const { return m_node_list[n].position().lat(); } /** * Add a node with the given id to the way. * * Will throw a range error if the way already has max_nodes_in_way nodes. */ void add_node(osm_object_id_t ref) { m_node_list.add(ref); } /** * Returns the number of nodes in this way. */ osm_sequence_id_t node_count() const { return m_node_list.size(); } /** * Returns the id of the first node. */ osm_object_id_t get_first_node_id() const { return m_node_list.front().ref(); } /** * Returns the id of the last node. */ osm_object_id_t get_last_node_id() const { return m_node_list.back().ref(); } /** * Check whether this way is closed. A way is closed if the first and last node have the same id. */ bool is_closed() const { return m_node_list.is_closed(); } #ifdef OSMIUM_WITH_GEOS /** * Returns the GEOS geometry of the first node. * Caller takes ownership of the pointer. */ geos::geom::Point* get_first_node_geometry() const { if (!m_node_list.front().has_position()) { throw std::range_error("geometry for nodes not available"); } return Osmium::Geometry::geos_geometry_factory()->createPoint(m_node_list.front().position()); } /** * Returns the GEOS geometry of the last node. * Caller takes ownership of the pointer. */ geos::geom::Point* get_last_node_geometry() const { if (!m_node_list.back().has_position()) { throw std::range_error("geometry for nodes not available"); } return Osmium::Geometry::geos_geometry_factory()->createPoint(m_node_list.back().position()); } /** * Returns the GEOS geometry of the way. * Caller takes ownership of the pointer. */ geos::geom::Geometry* create_geos_geometry() const { try { std::vector* c = new std::vector; for (osm_sequence_id_t i=0; i < m_node_list.size(); ++i) { c->push_back(m_node_list[i].position()); } geos::geom::CoordinateSequence* cs = Osmium::Geometry::geos_geometry_factory()->getCoordinateSequenceFactory()->create(c); return (geos::geom::Geometry*) Osmium::Geometry::geos_geometry_factory()->createLineString(cs); } catch (const geos::util::GEOSException& exc) { std::cerr << "error building way geometry, leave it as NULL\n"; return NULL; } } #endif // OSMIUM_WITH_GEOS #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle js_nodes() const { return m_node_list.js_instance(); } v8::Handle js_geom() const; v8::Handle js_reverse_geom() const; v8::Handle js_polygon_geom() const; struct JavascriptTemplate : public Osmium::OSM::Object::JavascriptTemplate { JavascriptTemplate() : Osmium::OSM::Object::JavascriptTemplate() { js_template->SetAccessor(v8::String::NewSymbol("nodes"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("geom"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("reverse_geom"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("polygon_geom"), accessor_getter); } }; #endif // OSMIUM_WITH_JAVASCRIPT /** * Ways can be ordered by id and version. * Note that we use the absolute value of the id for a * better ordering of objects with negative ids. */ friend bool operator<(const Way& lhs, const Way& rhs) { if (lhs.id() == rhs.id()) { return lhs.version() < rhs.version(); } else { return abs(lhs.id()) < abs(rhs.id()); } } /** * Ordering for shared_ptrs of Ways. */ friend bool operator<(const shared_ptr& lhs, const shared_ptr& rhs) { return *lhs < *rhs; } }; // class Way } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_WAY_HPP osmium/include/osmium/osm/tag_list.hpp0000664000175000017500000001212111706551765017414 0ustar daviddavid#ifndef OSMIUM_OSM_TAG_LIST_HPP #define OSMIUM_OSM_TAG_LIST_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include namespace Osmium { namespace OSM { /** * An ordered container for Tags. * * Tag keys are assumed to be unique in a TagList, but this is not * checked. */ class TagList { public: TagList() : m_tags() { } /// Return the number of tags in this tag list. int size() const { return m_tags.size(); } bool empty() const { return m_tags.empty(); } /// Remove all tags from the tag list. void clear() { m_tags.clear(); } Tag& operator[](int i) { return m_tags[i]; } const Tag& operator[](int i) const { return m_tags[i]; } typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; iterator begin() { return m_tags.begin(); } const_iterator begin() const { return m_tags.begin(); } iterator end() { return m_tags.end(); } const_iterator end() const { return m_tags.end(); } /// Add new tag with given key and value to list. void add(const char* key, const char* value) { m_tags.push_back(Tag(key, value)); } const char* get_tag_by_key(const char* key) const { for (const_iterator it = begin(); it != end(); ++it) { if (!strcmp(it->key(), key)) { return it->value(); } } return 0; } const char* get_tag_key(unsigned int n) const { if (n < m_tags.size()) { return m_tags[n].key(); } throw std::range_error("no tag with this index"); } const char* get_tag_value(unsigned int n) const { if (n < m_tags.size()) { return m_tags[n].value(); } throw std::range_error("no tag with this index"); } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void*)this); } v8::Handle js_get_tag_value_by_key(v8::Local property) const { const char* key = Osmium::v8_String_to_utf8(property); const char* value = get_tag_by_key(key); if (value) { return Osmium::utf8_to_v8_String(value); } return v8::Undefined(); } v8::Handle js_enumerate_tag_keys() const { v8::HandleScope scope; v8::Local array = v8::Array::New(m_tags.size()); const_iterator end = this->end(); int i = 0; for (const_iterator it = begin(); it != end; ++it) { array->Set(i++, Osmium::utf8_to_v8_String(it->key())); } return scope.Close(array); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->SetNamedPropertyHandler( named_property_getter, 0, 0, 0, property_enumerator ); } }; #endif // OSMIUM_WITH_JAVASCRIPT private: std::vector m_tags; }; // class TagList } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_TAG_LIST_HPP osmium/include/osmium/osm/tag.hpp0000664000175000017500000000342111706551765016364 0ustar daviddavid#ifndef OSMIUM_OSM_TAG_HPP #define OSMIUM_OSM_TAG_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace OSM { /** * An OSM tag. * * Tag keys and values are not allowed to be longer than 255 characters * each, but this is not checked by this class. */ class Tag { public: static const int max_utf16_length_key = 2 * (255 + 1); ///< maximum number of UTF-16 units static const int max_utf16_length_value = 2 * (255 + 1); Tag(const char* key, const char* value) : m_key(key), m_value(value) { } const char* key() const { return m_key.c_str(); } const char* value() const { return m_value.c_str(); } private: std::string m_key; std::string m_value; }; } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_TAG_HPP osmium/include/osmium/osm/relation_member_list.hpp0000664000175000017500000001033711706551765022014 0ustar daviddavid#ifndef OSMIUM_OSM_RELATION_MEMBER_LIST_HPP #define OSMIUM_OSM_RELATION_MEMBER_LIST_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace OSM { class RelationMemberList { public: RelationMemberList() : m_list() { } osm_sequence_id_t size() const { return m_list.size(); } void clear() { m_list.clear(); } RelationMember& operator[](int i) { return m_list[i]; } const RelationMember& operator[](int i) const { return m_list[i]; } typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; iterator begin() { return m_list.begin(); } const_iterator begin() const { return m_list.begin(); } iterator end() { return m_list.end(); } const_iterator end() const { return m_list.end(); } void add_member(const char type, osm_object_id_t ref, const char *role) { /* first we resize the vector... */ m_list.resize(m_list.size()+1); /* ...and get an address for the new element... */ RelationMember *m = &m_list[m_list.size()-1]; /* ...so that we can directly write into the memory and avoid a second copy */ m->type(type); m->ref(ref); m->role(role); } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void *)this); } v8::Handle js_get_member(uint32_t index) { return m_list[index].js_instance(); } v8::Handle js_enumerate_members() const { v8::HandleScope scope; v8::Local array = v8::Array::New(m_list.size()); for (unsigned int i=0; i < m_list.size(); i++) { array->Set(i, v8::Integer::New(i)); } return scope.Close(array); } v8::Handle js_length() const { return v8::Number::New(m_list.size()); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->SetAccessor(v8::String::NewSymbol("length"), accessor_getter); js_template->SetIndexedPropertyHandler( indexed_property_getter, 0, 0, 0, property_enumerator ); } }; #endif // OSMIUM_WITH_JAVASCRIPT private: std::vector m_list; }; // class RelationMemberList } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_RELATION_MEMBER_LIST_HPP osmium/include/osmium/osm/relation_member.hpp0000664000175000017500000001001511706551765020752 0ustar daviddavid#ifndef OSMIUM_OSM_RELATION_MEMBER_HPP #define OSMIUM_OSM_RELATION_MEMBER_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include namespace Osmium { namespace OSM { class RelationMember { public: static const int max_characters_role = 255; static const int max_utf16_length_role = 2 * (max_characters_role + 1); ///< maximum number of UTF-16 units static const int max_length_role = 255 * 4 + 1; /* 255 UTF-8 characters + null byte */ osm_object_id_t ref() const { return m_ref; } RelationMember& ref(osm_object_id_t ref) { m_ref = ref; return *this; } char type() const { return m_type; } const char *type_name() const { switch (type()) { case 'n': return "node"; case 'w': return "way"; case 'r': return "relation"; default: return "unknown"; } } RelationMember& type(char type) { m_type = type; return *this; } const char *role() const { return m_role; } RelationMember& role(const char* role) { if (! memccpy(m_role, role, 0, max_length_role)) { throw std::length_error("role too long"); } return *this; } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Local js_instance() const { return JavascriptTemplate::get().create_instance((void*)this); } v8::Handle js_ref() const { return v8::Number::New(ref()); } v8::Handle js_type() const { char t[2]; t[0] = type(); t[1] = 0; return v8::String::NewSymbol(t); } v8::Handle js_role() const { return Osmium::utf8_to_v8_String(role()); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->SetAccessor(v8::String::NewSymbol("type"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("ref"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("role"), accessor_getter); } }; #endif // OSMIUM_WITH_JAVASCRIPT private: osm_object_id_t m_ref; char m_type; char m_role[max_length_role]; }; // class RelationMember } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_RELATION_MEMBER_HPP osmium/include/osmium/osm/way_node.hpp0000664000175000017500000000437011706551765017422 0ustar daviddavid#ifndef OSMIUM_OSM_WAY_NODE_HPP #define OSMIUM_OSM_WAY_NODE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace OSM { class WayNode { public: WayNode(osm_object_id_t ref=0) : m_ref(ref) { } WayNode(osm_object_id_t ref, const Position& position) : m_ref(ref), m_position(position) { } osm_object_id_t ref() const { return m_ref; } const Position& position() const { return m_position; } WayNode& position(const Position& position) { m_position = position; return *this; } bool has_position() const { return m_position.defined(); } double lon() const { return m_position.lon(); } double lat() const { return m_position.lat(); } friend bool operator==(const WayNode& wn1, const WayNode& wn2) { return wn1.ref() == wn2.ref(); } friend bool operator!=(const WayNode& wn1, const WayNode& wn2) { return !(wn1 == wn2); } private: osm_object_id_t m_ref; Position m_position; }; // class WayNode } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_WAY_NODE_HPP osmium/include/osmium/osm/object.hpp0000664000175000017500000003124111706551765017060 0ustar daviddavid#ifndef OSMIUM_OSM_OBJECT_HPP #define OSMIUM_OSM_OBJECT_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ /** @file * @brief Contains the Osmium::OSM::Object class. */ #include #include #include #include #include using std::tr1::shared_ptr; #ifdef OSMIUM_WITH_SHPLIB # include #endif // OSMIUM_WITH_SHPLIB #include #include #include namespace Osmium { namespace OSM { /** * Parent class for nodes, ways, and relations. */ class Object { public: static const int max_characters_username = 255; static const int max_utf16_length_username = 2 * (max_characters_username + 1); ///< maximum number of UTF-16 units static const int max_length_username = 255 * 4 + 1; ///< maximum length of OSM user name (255 UTF-8 characters + null byte) osm_object_id_t id() const { return m_id; } Object& id(osm_object_id_t id) { m_id = id; return *this; } Object& id(const char* id) { m_id = atol(id); return *this; } osm_version_t version() const { return m_version; } Object& version(osm_version_t version) { m_version = version; return *this; } Object& version(const char* version) { m_version = atoi(version); return *this; } osm_changeset_id_t changeset() const { return m_changeset; } Object& changeset(osm_changeset_id_t changeset) { m_changeset = changeset; return *this; } Object& changeset(const char* changeset) { m_changeset = atol(changeset); return *this; } osm_user_id_t uid() const { return m_uid; } Object& uid(osm_user_id_t uid) { m_uid = uid; return *this; } Object& uid(const char* uid) { m_uid = atol(uid); return *this; } time_t timestamp() const { return m_timestamp; } time_t endtime() const { return m_endtime; } /** * Get the timestamp when this object last changed. * @return Timestamp as a string in ISO format (yyyy-mm-ddThh:mm:ssZ). Empty string if unset. */ std::string timestamp_as_string() const { return Osmium::Utils::Timestamp::to_iso(m_timestamp); } /** * Get the timestamp until which this object is valid. * @return Timestamp as a string in ISO format (yyyy-mm-ddThh:mm:ssZ). Empty string if unset. */ std::string endtime_as_string() const { return Osmium::Utils::Timestamp::to_iso(m_endtime); } /** * Set the timestamp when this object last changed. * @param timestamp Time in seconds since epoch. * @return Reference to object to make calls chainable. */ Object& timestamp(time_t timestamp) { m_timestamp = timestamp; return *this; } /** * Set the endtime after which this object is no longer valid. * (This is only used when working with history data.) * @param timestamp Time in seconds since epoch. * @return Reference to object to make calls chainable. */ Object& endtime(time_t timestamp) { m_endtime = timestamp; return *this; } /** * Set the timestamp when this object last changed. * @param timestamp Timestamp in the format "yyyy-mm-ddThh:mm:ssZ". * @return Reference to object to make calls chainable. * @exception std::invalid_argument Thrown when the given string * can't be parsed as a timestamp. The object timestamp will remain * unchanged in this case. */ Object& timestamp(const char* timestamp) { m_timestamp = Osmium::Utils::Timestamp::parse_iso(timestamp); return *this; } /** * Get the name of the user who last changed this object. * @return Pointer to internal buffer with user name. */ const char* user() const { return m_user; } /** * Set the name of the user who last changed this object. * @return Reference to object to make calls chainable. * @exception std::length_error Thrown when the username contains more than max_characters_username (255 UTF-8 characters). When the exception is thrown the username is set to "". */ Object& user(const char* user) { if (! memccpy(m_user, user, 0, max_length_username)) { m_user[0] = '\0'; throw std::length_error("user name too long"); } return *this; } /** * Get the visible flag of this object. * (This is only used in OSM files with history.) * @return Visible flag. */ bool visible() const { return m_visible; } /** * Set the visible flag of this object. * (This is only used in OSM files with history.) * @return Reference to object to make calls chainable. */ Object& visible(bool visible) { m_visible = visible; return *this; } /** * Set the visible flag of this object. * (This is only used in OSM files with history.) * @return Reference to object to make calls chainable. */ Object& visible(const char* visible) { if (!strcmp(visible, "false")) { m_visible = false; } return *this; } virtual osm_object_type_t get_type() const = 0; /** * Set named attribute. * @param attr Name of the attribute (must be one of "id", "version", "changeset", "timestamp", "uid", "user", "visible") * @param value Value of the attribute */ void set_attribute(const char* attr, const char* value) { if (!strcmp(attr, "id")) { id(value); } else if (!strcmp(attr, "version")) { version(value); } else if (!strcmp(attr, "changeset")) { changeset(value); } else if (!strcmp(attr, "timestamp")) { timestamp(value); } else if (!strcmp(attr, "uid")) { uid(value); } else if (!strcmp(attr, "user")) { user(value); } else if (!strcmp(attr, "visible")) { visible(value); } } const TagList& tags() const { return m_tags; } TagList& tags() { return m_tags; } void tags(TagList& tags) { m_tags = tags; } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Persistent js_object_instance; v8::Persistent get_instance() const { return js_object_instance; } v8::Handle js_id() const { return v8::Number::New(id()); } v8::Handle js_version() const { return v8::Integer::New(version()); } v8::Handle js_timestamp_as_string() const { return v8::String::New(timestamp_as_string().c_str()); } v8::Handle js_uid() const { return v8::Integer::New(uid()); } v8::Handle js_user() const { return Osmium::utf8_to_v8_String(user()); } v8::Handle js_changeset() const { return v8::Number::New(changeset()); } v8::Handle js_visible() const { return v8::Boolean::New(visible()); } v8::Handle js_tags() const { return tags().js_instance(); } struct JavascriptTemplate : public Osmium::Javascript::Template { JavascriptTemplate() : Osmium::Javascript::Template() { js_template->SetAccessor(v8::String::NewSymbol("id"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("version"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("timestamp"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("uid"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("user"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("changeset"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("tags"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("visible"), accessor_getter); } }; #endif // OSMIUM_WITH_JAVASCRIPT protected: Object() : m_id(0), m_version(0), m_changeset(0), m_timestamp(0), m_endtime(0), m_uid(-1), // to be compatible with Osmosis we use -1 for unknown user id m_visible(true), m_tags() { m_user[0] = '\0'; } Object(const Object &o) { m_id = o.m_id; m_version = o.m_version; m_uid = o.m_uid; m_changeset = o.m_changeset; m_timestamp = o.m_timestamp; m_endtime = o.m_endtime; m_tags = o.m_tags; m_visible = o.m_visible; strncpy(m_user, o.m_user, max_length_username); } virtual ~Object() { #ifdef OSMIUM_WITH_JAVASCRIPT js_object_instance.Dispose(); #endif // OSMIUM_WITH_JAVASCRIPT } private: osm_object_id_t m_id; ///< object id osm_version_t m_version; ///< object version osm_changeset_id_t m_changeset; ///< id of last changeset that changed this object time_t m_timestamp; ///< when this object changed last time_t m_endtime; ///< when this object version was replaced by a new one osm_user_id_t m_uid; ///< user id of user who last changed this object char m_user[max_length_username]; ///< name of user who last changed this object bool m_visible; ///< object visible (only when working with history data) TagList m_tags; }; // class Object } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_OBJECT_HPP osmium/include/osmium/osm/bounds.hpp0000664000175000017500000000515611706551765017112 0ustar daviddavid#ifndef OSMIUM_OSM_BOUNDS_HPP #define OSMIUM_OSM_BOUNDS_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include namespace Osmium { namespace OSM { class Bounds { public: Bounds() : m_min_x(std::numeric_limits::max()), m_max_x(std::numeric_limits::min()), m_min_y(std::numeric_limits::max()), m_max_y(std::numeric_limits::min()) { } Bounds& extend(const Position& position) { if (position.x() < m_min_x) m_min_x = position.x(); if (position.x() > m_max_x) m_max_x = position.x(); if (position.y() < m_min_y) m_min_y = position.y(); if (position.y() > m_max_y) m_max_y = position.y(); return *this; } bool defined() const { return m_min_x != std::numeric_limits::max(); } /** * Bottom-left position. */ Position bl() const { return Position(m_min_x, m_min_y); } /** * Top-right position. */ Position tr() const { return Position(m_max_x, m_max_y); } friend std::ostream& operator<<(std::ostream& out, const Bounds& bounds) { out << '(' << bounds.bl().lon() << ',' << bounds.bl().lat() << ',' << bounds.tr().lon() << ',' << bounds.tr().lat() << ')'; return out; } private: int32_t m_min_x; int32_t m_max_x; int32_t m_min_y; int32_t m_max_y; }; // class Bounds } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_BOUNDS_HPP osmium/include/osmium/osm/relation.hpp0000664000175000017500000000741611706551765017436 0ustar daviddavid#ifndef OSMIUM_OSM_RELATION_HPP #define OSMIUM_OSM_RELATION_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include namespace Osmium { namespace OSM { class Relation : public Object, boost::less_than_comparable { public: Relation() : Object(), m_members() { #ifdef OSMIUM_WITH_JAVASCRIPT v8::HandleScope handle_scope; js_object_instance = v8::Persistent::New(JavascriptTemplate::get().create_instance(this)); #endif // OSMIUM_WITH_JAVASCRIPT } Relation(const Relation &r) : Object(r) { m_members = r.members(); #ifdef OSMIUM_WITH_JAVASCRIPT v8::HandleScope handle_scope; js_object_instance = v8::Persistent::New(JavascriptTemplate::get().create_instance(this)); #endif // OSMIUM_WITH_JAVASCRIPT } const RelationMemberList& members() const { return m_members; } osm_object_type_t get_type() const { return RELATION; } void add_member(const char type, osm_object_id_t ref, const char *role) { m_members.add_member(type, ref, role); } const RelationMember *get_member(osm_sequence_id_t index) const { if (index < m_members.size()) { return &m_members[index]; } return NULL; } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle js_members() const { return members().js_instance(); } struct JavascriptTemplate : public Osmium::OSM::Object::JavascriptTemplate { JavascriptTemplate() : Osmium::OSM::Object::JavascriptTemplate() { js_template->SetAccessor(v8::String::NewSymbol("members"), accessor_getter); } }; #endif // OSMIUM_WITH_JAVASCRIPT /** * Relations can be ordered by id and version. * Note that we use the absolute value of the id for a * better ordering of objects with negative ids. */ friend bool operator<(const Relation& lhs, const Relation& rhs) { if (lhs.id() == rhs.id()) { return lhs.version() < rhs.version(); } else { return abs(lhs.id()) < abs(rhs.id()); } } /** * Ordering for shared_ptrs of Relations. */ friend bool operator<(const shared_ptr& lhs, const shared_ptr& rhs) { return *lhs < *rhs; } private: RelationMemberList m_members; }; // class Relation } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_RELATION_HPP osmium/include/osmium/osm/types.hpp0000664000175000017500000000330611706551765016757 0ustar daviddavid#ifndef OSMIUM_OSM_TYPES_HPP #define OSMIUM_OSM_TYPES_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include enum osm_object_type_t { UNKNOWN = -1, NODE = 0, WAY = 1, RELATION = 2, AREA_FROM_WAY = 3, AREA_FROM_RELATION = 4 }; /* * The following typedefs are chosen so that they can represent all needed * numbers and still be reasonably space efficient. As the %OSM database is * growing rapidly, 64 bit IDs will be needed at some point! */ typedef int32_t osm_object_id_t; ///< type for %OSM object (node, way, or relation) IDs typedef uint32_t osm_version_t; ///< type for %OSM object version number typedef int32_t osm_changeset_id_t; ///< type for %OSM changeset IDs typedef int32_t osm_user_id_t; ///< type for %OSM user IDs typedef uint32_t osm_sequence_id_t; ///< type for %OSM nodes and members sequence IDs #endif // OSMIUM_OSM_TYPES_HPP osmium/include/osmium/osm/meta.hpp0000664000175000017500000000415211706551765016541 0ustar daviddavid#ifndef OSMIUM_OSM_META_HPP #define OSMIUM_OSM_META_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include namespace Osmium { namespace OSM { /** * Meta information from the header of an OSM file. */ class Meta { public: Meta() : m_bounds(), m_has_multiple_object_versions(false) { } Meta(const Bounds& bounds) : m_bounds(bounds), m_has_multiple_object_versions(false) { } Bounds& bounds() { return m_bounds; } const Bounds& bounds() const { return m_bounds; } bool has_multiple_object_versions() const { return m_has_multiple_object_versions; } Meta& has_multiple_object_versions(bool h) { m_has_multiple_object_versions = h; return *this; } private: Bounds m_bounds; /** * Are there possibly multiple versions of the same object in this stream of objects? * This is true for history files and for change files, but not for normal OSM files. */ bool m_has_multiple_object_versions; }; // class Meta } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_META_HPP osmium/include/osmium/osm/node.hpp0000664000175000017500000000705111706551765016541 0ustar daviddavid#ifndef OSMIUM_OSM_NODE_HPP #define OSMIUM_OSM_NODE_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include /** @file * @brief Contains the Osmium::OSM::Node class. */ #include namespace Osmium { namespace OSM { class Node : public Object, boost::less_than_comparable { static const int max_length_coordinate = 12 + 1; ///< maximum length of coordinate string (3 digits + dot + 8 digits + null byte) Position m_position; public: Node() : Object(), m_position() { #ifdef OSMIUM_WITH_JAVASCRIPT v8::HandleScope handle_scope; js_object_instance = v8::Persistent::New(JavascriptTemplate::get().create_instance(this)); #endif // OSMIUM_WITH_JAVASCRIPT } const Position position() const { return m_position; } Node& position(Position position) { m_position = position; return *this; } osm_object_type_t get_type() const { return NODE; } void set_x(double x) { m_position.lon(x); } void set_y(double y) { m_position.lat(y); } double get_lon() const { return m_position.lon(); } double get_lat() const { return m_position.lat(); } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle js_get_geom() const; struct JavascriptTemplate : public Osmium::OSM::Object::JavascriptTemplate { JavascriptTemplate() : Osmium::OSM::Object::JavascriptTemplate() { js_template->SetAccessor(v8::String::NewSymbol("geom"), accessor_getter); } }; #endif // OSMIUM_WITH_JAVASCRIPT /** * Nodes can be ordered by id and version. * Note that we use the absolute value of the id for a * better ordering of objects with negative id. */ friend bool operator<(const Node& lhs, const Node& rhs) { if (lhs.id() == rhs.id()) { return lhs.version() < rhs.version(); } else { return abs(lhs.id()) < abs(rhs.id()); } } /** * Ordering for shared_ptrs of Nodes. */ friend bool operator<(const shared_ptr& lhs, const shared_ptr& rhs) { return *lhs < *rhs; } }; // class Node } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_NODE_HPP osmium/include/osmium/osm/area.hpp0000664000175000017500000014156111706551765016531 0ustar daviddavid#ifndef OSMIUM_OSM_AREA_HPP #define OSMIUM_OSM_AREA_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include #include #include #include #ifdef OSMIUM_WITH_MULTIPOLYGON_PROFILING # include # define START_TIMER(x) x##_timer.start(); # define STOP_TIMER(x) x##_timer.stop(); #else # define START_TIMER(x) # define STOP_TIMER(x) #endif // OSMIUM_WITH_MULTIPOLYGON_PROFILING #ifdef OSMIUM_WITH_GEOS # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include // this should come from /usr/include/geos/algorithm, but its missing there in some Ubuntu versions # include "../CGAlgorithms.h" #endif // OSMIUM_WITH_GEOS #ifdef OSMIUM_WITH_SHPLIB # include #endif // OSMIUM_WITH_SHPLIB #include #include #include namespace Osmium { namespace OSM { enum innerouter_t { UNSET, INNER, OUTER }; enum direction_t { NO_DIRECTION, CLOCKWISE, COUNTERCLOCKWISE }; #ifdef OSMIUM_WITH_GEOS class WayInfo { friend class AreaFromRelation; Osmium::OSM::Way *way; int used; int sequence; bool invert; bool duplicate; std::string errorhint; innerouter_t innerouter; innerouter_t orig_innerouter; geos::geom::Geometry *way_geom; int firstnode; int lastnode; bool tried; WayInfo() { way = NULL; used = -1; innerouter = UNSET; orig_innerouter = UNSET; sequence = 0; invert = false; duplicate = false; way_geom = NULL; firstnode = -1; lastnode = -1; tried = false; } WayInfo(Osmium::OSM::Way *w, innerouter_t io) { way = w; way_geom = w->create_geos_geometry(); orig_innerouter = io; used = -1; innerouter = UNSET; sequence = 0; invert = false; duplicate = false; tried = false; firstnode = w->get_first_node_id(); lastnode = w->get_last_node_id(); } /** Special version with a synthetic way, not backed by real way object. */ WayInfo(geos::geom::Geometry *g, int first, int last, innerouter_t io) { way = NULL; way_geom = g; orig_innerouter = io; used = -1; innerouter = UNSET; sequence = 0; invert = false; duplicate = false; tried = false; firstnode = first; lastnode = last; } ~WayInfo() { delete way_geom; } geos::geom::Point *get_firstnode_geom() { return (way ? way->get_first_node_geometry() : NULL); } geos::geom::Point *get_lastnode_geom() { return (way ? way->get_last_node_geometry() : NULL); } }; class RingInfo { friend class AreaFromRelation; geos::geom::Polygon *polygon; direction_t direction; std::vector ways; std::vector inner_rings; bool nested; RingInfo *contained_by; int ring_id; RingInfo() { polygon = NULL; direction = NO_DIRECTION; nested = false; contained_by = NULL; ring_id = -1; } }; #endif // OSMIUM_WITH_GEOS /// virtual parent class for AreaFromWay and AreaFromRelation class Area : public Object { protected: #ifdef OSMIUM_WITH_GEOS geos::geom::Geometry *geometry; Area(geos::geom::Geometry *geom = NULL) : geometry(geom) { #else Area() { #endif // OSMIUM_WITH_GEOS # ifdef OSMIUM_WITH_JAVASCRIPT v8::HandleScope handle_scope; js_object_instance = v8::Persistent::New(JavascriptTemplate::get().create_instance(this)); # endif // OSMIUM_WITH_JAVASCRIPT } ~Area() { #ifdef OSMIUM_WITH_GEOS delete(geometry); #endif // OSMIUM_WITH_GEOS } public: #ifdef OSMIUM_WITH_GEOS geos::geom::Geometry* get_geometry() const { return geometry; } #endif // OSMIUM_WITH_GEOS #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle js_from() const { const char *value = (get_type() == AREA_FROM_WAY) ? "way" : "relation"; return v8::String::NewSymbol(value); } v8::Handle js_geom() const; struct JavascriptTemplate : public Osmium::OSM::Object::JavascriptTemplate { JavascriptTemplate() : Osmium::OSM::Object::JavascriptTemplate() { js_template->SetAccessor(v8::String::NewSymbol("from"), accessor_getter); js_template->SetAccessor(v8::String::NewSymbol("geom"), accessor_getter); } }; #endif // OSMIUM_WITH_JAVASCRIPT }; // class Area /*** * Area created from a way. * The way pointer given to the constructor will not be stored, all * needed attributes are copied. */ class AreaFromWay : public Area { public: WayNodeList m_node_list; #ifdef OSMIUM_WITH_GEOS AreaFromWay(Way* way, geos::geom::Geometry* geom) : Area(geom) { #else AreaFromWay(Way* way) : Area() { #endif // OSMIUM_WITH_GEOS id(way->id()); version(way->version()); changeset(way->changeset()); timestamp(way->timestamp()); uid(way->uid()); user(way->user()); tags(way->tags()); m_node_list = way->nodes(); } ~AreaFromWay() { } const WayNodeList& nodes() const { return m_node_list; } WayNodeList& nodes() { return m_node_list; } osm_object_type_t get_type() const { return AREA_FROM_WAY; } }; // class AreaFromWay /*** * Area created from a relation with tag type=multipolygon or type=boundary */ class AreaFromRelation : public Area { bool boundary; ///< was this area created from relation with tag type=boundary? /// the relation this area was build from Relation *relation; /// the member ways of this area std::vector member_ways; /// number of ways in this area int num_ways; /// how many ways are missing before we can build the multipolygon int missing_ways; std::string geometry_error_message; /// callback we should call when a multipolygon was completed void (*callback)(Osmium::OSM::Area*); /// whether we want to repair a broken geometry bool attempt_repair; bool ignore_tag(const std::string &s) { if (s=="type") return true; if (s=="created_by") return true; if (s=="source") return true; if (s=="note") return true; return false; } bool same_tags(const Object* a, const Object* b) { if ((a == NULL) || (b == NULL)) return false; const TagList& at = a->tags(); const TagList& bt = b->tags(); std::map aTags; TagList::const_iterator end = at.end(); for (TagList::const_iterator it = at.begin(); it != end; ++it) { if (ignore_tag(it->key())) continue; aTags[it->key()] = it->value(); } end = bt.end(); for (TagList::const_iterator it = bt.begin(); it != end; ++it) { if (ignore_tag(it->key())) continue; if (aTags[it->key()] != it->value()) return false; aTags.erase(it->key()); } if (!aTags.empty()) return false; return true; } /** returns false if there was a collision, true otherwise */ bool merge_tags(Object* a, const Object* b) { bool rv = true; TagList& at = a->tags(); const TagList& bt = b->tags(); std::map aTags; TagList::const_iterator end = at.end(); for (TagList::const_iterator it = at.begin(); it != end; ++it) { if (ignore_tag(it->key())) continue; aTags[it->key()] = it->value(); } end = bt.end(); for (TagList::const_iterator it = bt.begin(); it != end; ++it) { if (ignore_tag(it->key())) continue; if (aTags.find(it->key()) != aTags.end()) { if (aTags[it->key()] != it->value()) rv = false; } else { at.add(it->key(), it->value()); aTags[it->key()] = it->value(); } } return rv; } bool untagged(const Object* r) { if (r == NULL) return true; const TagList& tags = r->tags(); if (tags.empty()) return true; TagList::const_iterator end = tags.end(); for (TagList::const_iterator it = tags.begin(); it != end; ++it) { if (! ignore_tag(it->key()) ) { return false; } } return true; } public: AreaFromRelation(Relation* r, bool b, int n, void (*callback)(Osmium::OSM::Area*), bool repair) : Area(), boundary(b), relation(r), callback(callback) { num_ways = n; missing_ways = n; #ifdef OSMIUM_WITH_GEOS geometry = NULL; #endif // OSMIUM_WITH_GEOS id(r->id()); attempt_repair = repair; } #ifdef OSMIUM_WITH_MULTIPOLYGON_PROFILING static std::vector > timers; static timer write_complex_poly_timer; static timer assemble_ways_timer; static timer assemble_nodes_timer; static timer make_one_ring_timer; static timer mor_polygonizer_timer; static timer mor_union_timer; static timer contains_timer; static timer extra_polygons_timer; static timer polygon_build_timer; static timer inner_ring_touch_timer; static timer polygon_intersection_timer; static timer multipolygon_build_timer; static timer multipolygon_write_timer; static timer error_write_timer; static void init_timings() { timers.push_back(std::pair (" thereof assemble_ways", &assemble_ways_timer)); timers.push_back(std::pair (" thereof make_one_ring", &make_one_ring_timer)); timers.push_back(std::pair (" thereof union", &mor_union_timer)); timers.push_back(std::pair (" thereof polygonizer", &mor_polygonizer_timer)); timers.push_back(std::pair (" thereof contains", &contains_timer)); timers.push_back(std::pair (" thereof extra_polygons", &extra_polygons_timer)); timers.push_back(std::pair (" thereof polygon_build", &polygon_build_timer)); timers.push_back(std::pair (" thereof inner_ring_touch", &inner_ring_touch_timer)); timers.push_back(std::pair (" thereof intersections", &polygon_intersection_timer)); timers.push_back(std::pair (" thereof multipolygon_build", &multipolygon_build_timer)); timers.push_back(std::pair (" thereof multipolygon_write", &multipolygon_write_timer)); timers.push_back(std::pair (" thereof error_write", &error_write_timer)); } static void print_timings() { for (unsigned int i=0; i* coords = orig_cs->toVector(); int inv = coords->size(); int val = 0; int current = (inv + val) / 2; bool simple; // find the longest non-intersecting stretch from the beginning // of the way. while (1) { std::vector *vv = new std::vector(coords->begin(), coords->begin() + current); geos::geom::CoordinateSequence *cs = geos::geom::CoordinateArraySequenceFactory::instance()->create(vv); geos::geom::LineString *a = Osmium::Geometry::geos_geometry_factory()->createLineString(cs); if (!(simple = a->isSimple())) { inv = current; } else { val = current; } delete a; if (current == (inv+val)/2) break; current = (inv + val) / 2; } if (!simple) current--; unsigned int cutoutstart = current; inv = 0; val = coords->size(); current = (inv + val) / 2; // find the longest non-intersecting stretch from the end // of the way. Note that this is likely to overlap with the // stretch found above - assume a 10-node way where nodes 3 // and 7 are identical, then we will find the sequence 0..6 // above, and 4..9 here! while (1) { std::vector *vv = new std::vector(coords->begin() + current, coords->end()); geos::geom::CoordinateSequence *cs = geos::geom::CoordinateArraySequenceFactory::instance()->create(vv); geos::geom::LineString *a = Osmium::Geometry::geos_geometry_factory()->createLineString(cs); if (!(simple = a->isSimple())) { inv = current; } else { val = current; } delete a; if (current == (inv+val)/2) break; current = (inv + val) / 2; } if (!simple) current++; unsigned int cutoutend = current; // assemble a new linear ring by cutting out the problematic bit. // if the "problematic bit" however is longer than half the way, // then try using the "problematic bit" by itself. std::vector *vv = new std::vector(); if (cutoutstart < cutoutend) { unsigned int t = cutoutstart; cutoutstart = cutoutend; cutoutend = t; } if (cutoutstart-cutoutend > coords->size() / 2) { vv->insert(vv->end(), coords->begin() + cutoutend, coords->begin() + cutoutstart); vv->insert(vv->end(), vv->at(0)); } else { vv->insert(vv->end(), coords->begin(), coords->begin() + cutoutend); vv->insert(vv->end(), coords->begin() + cutoutstart, coords->end()); } geos::geom::CoordinateSequence *cs = geos::geom::CoordinateArraySequenceFactory::instance()->create(vv); geos::geom::LinearRing *a = Osmium::Geometry::geos_geometry_factory()->createLinearRing(cs); // if this results in a valid ring, return it; else return NULL. if (!a->isValid()) return NULL; geos::geom::LinearRing *b = dynamic_cast(a->clone()); //delete a; return b; } /** * Tries to collect 1...n ways from the n ways in the given list so that * they form a closed ring. If this is possible, flag those as being used * by ring #ringcount in the way list and return the geometry. (The method * may be called again to find further rings.) If this is not possible, * return NULL. */ RingInfo *make_one_ring(std::vector &ways, osm_object_id_t first, osm_object_id_t last, int ringcount, int sequence) { // have we found a loop already? if (first && first == last) { geos::geom::CoordinateSequence *cs = geos::geom::CoordinateArraySequenceFactory::instance()->create((size_t)0, (size_t)0); geos::geom::LinearRing *lr = NULL; try { START_TIMER(mor_polygonizer); WayInfo **sorted_ways = new WayInfo*[sequence]; for (unsigned int i=0; iused == ringcount) { sorted_ways[ways[i]->sequence] = ways[i]; } } for (int i=0; iadd(dynamic_cast(sorted_ways[i]->way_geom)->getCoordinatesRO(), false, !sorted_ways[i]->invert); } delete[] sorted_ways; lr = Osmium::Geometry::geos_geometry_factory()->createLinearRing(cs); STOP_TIMER(mor_polygonizer); if (!lr->isSimple() || !lr->isValid()) { //delete lr; lr = NULL; if (attempt_repair) { lr = create_non_intersecting_linear_ring(cs); if (lr) { if (Osmium::debug()) std::cerr << "successfully repaired an invalid ring" << std::endl; } } if (!lr) return NULL; } bool ccw = geos::algorithm::CGAlgorithms::isCCW(lr->getCoordinatesRO()); RingInfo *rl = new RingInfo(); rl->direction = ccw ? COUNTERCLOCKWISE : CLOCKWISE; rl->polygon = Osmium::Geometry::geos_geometry_factory()->createPolygon(lr, NULL); return rl; } catch (const geos::util::GEOSException& exc) { if (Osmium::debug()) std::cerr << "Exception: " << exc.what() << std::endl; return NULL; } } // have we not allocated anything yet, then simply start with first available way, // or return NULL if all are taken. if (!first) { for (unsigned int i=0; iused != -1) continue; ways[i]->used = ringcount; ways[i]->sequence = 0; ways[i]->invert = false; RingInfo *rl = make_one_ring(ways, ways[i]->firstnode, ways[i]->lastnode, ringcount, 1); if (rl) { rl->ways.push_back(ways[i]); return rl; } ways[i]->used = -2; break; } return NULL; } // try extending our current line at the rear end // since we are looking for a LOOP, no sense to try extending it at both ends // as we'll eventually get there anyway! for (unsigned int i=0; iused < 0) ways[i]->tried = false; } for (unsigned int i=0; iused >= 0) continue; if (ways[i]->tried) continue; ways[i]->tried = true; int old_used = ways[i]->used; if (ways[i]->firstnode == last) { // add way to end ways[i]->used = ringcount; ways[i]->sequence = sequence; ways[i]->invert = false; RingInfo *result = make_one_ring(ways, first, ways[i]->lastnode, ringcount, sequence+1); if (result) { result->ways.push_back(ways[i]); return result; } ways[i]->used = old_used; } else if (ways[i]->lastnode == last) { // add way to end, but turn it around ways[i]->used = ringcount; ways[i]->sequence = sequence; ways[i]->invert = true; RingInfo *result = make_one_ring(ways, first, ways[i]->firstnode, ringcount, sequence+1); if (result) { result->ways.push_back(ways[i]); return result; } ways[i]->used = old_used; } } // we have exhausted all combinations. return NULL; } /** * Checks if there are any dangling ends, and connects them to the * nearest other dangling end with a straight line. This could * conceivably introduce intersections, but it's the best we can * do. * * Returns true on success. * * (This implementation always succeeds because it is impossible for * there to be only one dangling end in a collection of lines.) */ bool find_and_repair_holes_in_rings(std::vector *ways) { // collect the remaining debris (=unused ways) and find dangling nodes. std::map dangling_node_map; for (std::vector::iterator i(ways->begin()); i != ways->end(); i++) { if ((*i)->used < 0) { (*i)->innerouter = UNSET; (*i)->used = -1; for (int j=0; j<2; j++) { int nid = j ? (*i)->firstnode : (*i)->lastnode; if (dangling_node_map[nid]) { delete dangling_node_map[nid]; dangling_node_map[nid] = NULL; } else { dangling_node_map[nid] = j ? (*i)->get_firstnode_geom() : (*i)->get_lastnode_geom(); } } } } do { int mindist_id = 0; double mindist = -1; int node1_id = 0; geos::geom::Point *node1 = NULL; geos::geom::Point *node2 = NULL; // find one pair consisting of a random node from the list (node1) // plus the node that lies closest to it. for (std::map::iterator i(dangling_node_map.begin()); i!= dangling_node_map.end(); i++) { if (!i->second) continue; if (node1 == NULL) { node1 = i->second; node1_id = i->first; i->second = NULL; mindist = -1; } else { # if GEOS_VERSION_MAJOR < 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR <= 2) double dist = geos::operation::distance::DistanceOp::distance(node1, (i->second)); // deprecated in newer version of GEOS # else double dist = geos::operation::distance::DistanceOp::distance(*node1, *(i->second)); # endif if ((dist < mindist) || (mindist < 0)) { mindist = dist; mindist_id = i->first; } } } // if such a pair has been found, synthesize a connecting way. if (node1 && mindist > -1) { // if we find that there are dangling nodes but aren't // repairing - break out. if (!attempt_repair) return false; // drop node2 from dangling map node2 = dangling_node_map[mindist_id]; dangling_node_map[mindist_id] = NULL; std::vector *c = new std::vector; c->push_back(*(node1->getCoordinate())); c->push_back(*(node2->getCoordinate())); geos::geom::CoordinateSequence *cs = Osmium::Geometry::geos_geometry_factory()->getCoordinateSequenceFactory()->create(c); geos::geom::Geometry *geometry = (geos::geom::Geometry *) Osmium::Geometry::geos_geometry_factory()->createLineString(cs); ways->push_back(new WayInfo(geometry, node1_id, mindist_id, UNSET)); if (Osmium::debug()) std::cerr << "fill gap between nodes " << node1_id << " and " << mindist_id << std::endl; } else { break; } } while (1); return true; } /** * Tries to build a multipolygon from the given relation. * */ bool build_geometry() { std::vector ways; // the timestamp of the multipolygon will be the maximum of the timestamp from the relation and from all member ways timestamp(relation->timestamp()); // assemble all ways which are members of this relation into a // vector of WayInfo elements. this holds room for the way pointer // and some extra flags. START_TIMER(assemble_ways); for (std::vector::iterator i(member_ways.begin()); i != member_ways.end(); i++) { if (i->timestamp() > timestamp()) { timestamp(i->timestamp()); } WayInfo *wi = new WayInfo(&(*i), UNSET); if (wi->way_geom) { geos::io::WKTWriter wkt; } else { delete wi; return geometry_error("invalid way geometry in multipolygon relation member"); } ways.push_back(wi); // TODO drop duplicate ways automatically in repair mode? // TODO maybe add INNER/OUTER instead of UNSET to enable later warnings on role mismatch } STOP_TIMER(assemble_ways); std::vector ringlist; // convenience defines to aid in clearing up on error return. #define clear_ringlist() \ for (std::vector::const_iterator rli(ringlist.begin()); rli != ringlist.end(); rli++) delete *rli; #define clear_wayinfo() \ for (std::vector::const_iterator win(ways.begin()); win != ways.end(); win++) delete *win; // try and create as many closed rings as possible from the assortment // of ways. make_one_ring will automatically flag those that have been // used so they are not used again. do { START_TIMER(make_one_ring); RingInfo *r = make_one_ring(ways, 0, 0, ringlist.size(), 0); STOP_TIMER(make_one_ring); if (r == NULL) break; r->ring_id = ringlist.size(); ringlist.push_back(r); } while (1); if (ringlist.empty()) { // FIXME return geometry_error("no rings"); } if (!find_and_repair_holes_in_rings(&ways)) { clear_ringlist(); clear_wayinfo(); return geometry_error("un-connectable dangling ends"); } // re-run ring building, taking into account the newly created "repair" bits. // (in case there were no dangling bits, make_one_ring terminates quickly.) do { START_TIMER(make_one_ring); RingInfo *r = make_one_ring(ways, 0, 0, ringlist.size(), 0); STOP_TIMER(make_one_ring); if (r == NULL) break; r->ring_id = ringlist.size(); ringlist.push_back(r); } while (1); if (ringlist.empty()) { clear_ringlist(); clear_wayinfo(); return geometry_error("no rings"); } std::vector *polygons = new std::vector(); geos::geom::MultiPolygon *mp = NULL; // find out which ring contains which other ring, so we know // which are inner rings and which outer. don't trust the "role" // specifications. START_TIMER(contains); bool **contains = new bool*[ringlist.size()]; bool *contained_by_even_number = new bool[ringlist.size()]; // reset array for (unsigned int i=0; ipolygon); for (unsigned int j=0; jcontains(ringlist[j]->polygon); contained_by_even_number[j] ^= contains[i][j]; } delete pp; } // we now have an array that has a true value whenever something is // contained by something else; if a contains b and b contains c, then // our array says that a contains b, b contains c, and a contains c. // thin out the array so that only direct relationships remain (and // the "a contains c" is dropped). for (unsigned int i=0; inested = true; break; } } } } } // populate the "inner_rings" list and the "contained_by" pointer // in the ring list based on the data collected. the "contains" // array can be thrown away afterwards. for (unsigned int i=0; icontained_by = ringlist[i]; ringlist[i]->inner_rings.push_back(ringlist[j]); } } delete[] contains[i]; } delete[] contains; delete[] contained_by_even_number; STOP_TIMER(contains); // now look at all enclosed (inner) rings that consist of only one way. // if such an inner ring has way tags, do the following: // * emit an extra polygon for the inner ring if the tags are different // from the relation's // * emit a warning, and ignore the inner ring, if the tags are the same // as for the relation START_TIMER(extra_polygons); for (unsigned int i=0; icontained_by) { if (ringlist[i]->ways.size() == 1 && !untagged(ringlist[i]->ways[0]->way)) { std::vector *g = new std::vector; if (ringlist[i]->direction == CLOCKWISE) { g->push_back(ringlist[i]->polygon->clone()); } else { geos::geom::LineString *tmp = dynamic_cast(ringlist[i]->polygon->getExteriorRing()->reverse()); geos::geom::LinearRing *reversed_ring = Osmium::Geometry::geos_geometry_factory()->createLinearRing(tmp->getCoordinates()); delete tmp; g->push_back(Osmium::Geometry::geos_geometry_factory()->createPolygon(reversed_ring, NULL)); } geos::geom::MultiPolygon *special_mp = Osmium::Geometry::geos_geometry_factory()->createMultiPolygon(g); if (same_tags(ringlist[i]->ways[0]->way, relation)) { // warning // warnings.insert("duplicate_tags_on_inner"); } else if (ringlist[i]->contained_by->ways.size() == 1 && same_tags(ringlist[i]->ways[0]->way, ringlist[i]->contained_by->ways[0]->way)) { // warning // warnings.insert("duplicate_tags_on_inner"); } else { Osmium::OSM::AreaFromWay *internal_mp = new Osmium::OSM::AreaFromWay(ringlist[i]->ways[0]->way, special_mp); callback(internal_mp); delete internal_mp; // AreaFromWay destructor deletes the // geometry, so avoid to delete it again. special_mp = NULL; } delete special_mp; } } } STOP_TIMER(extra_polygons); // for all non-enclosed rings, assemble holes and build polygon. START_TIMER(polygon_build) for (unsigned int i=0; icontained_by) continue; std::vector *holes = new std::vector(); // ownership is later transferred to polygon START_TIMER(inner_ring_touch) for (int j=0; j<((int)ringlist[i]->inner_rings.size()-1); j++) { if (!ringlist[i]->inner_rings[j]->polygon) continue; geos::geom::LinearRing *ring = (geos::geom::LinearRing *) ringlist[i]->inner_rings[j]->polygon->getExteriorRing(); // check if some of the rings touch another ring. for (unsigned int k=j + 1; kinner_rings.size(); k++) { if (!ringlist[i]->inner_rings[k]->polygon) continue; const geos::geom::Geometry *compare = ringlist[i]->inner_rings[k]->polygon->getExteriorRing(); geos::geom::Geometry *inter = NULL; try { if (!ring->intersects(compare)) continue; inter = ring->intersection(compare); } catch (const geos::util::GEOSException& exc) { // nop; } if (inter && (inter->getGeometryTypeId() == geos::geom::GEOS_LINESTRING || inter->getGeometryTypeId() == geos::geom::GEOS_MULTILINESTRING)) { // touching inner rings // this is allowed, but we must fix them up into a valid // geometry geos::geom::Geometry *diff = ring->symDifference(compare); geos::operation::polygonize::Polygonizer *p = new geos::operation::polygonize::Polygonizer(); p->add(diff); std::vector* polys = p->getPolygons(); if (polys && polys->size() == 1) { ringlist[i]->inner_rings[j]->polygon = polys->at(0); bool ccw = geos::algorithm::CGAlgorithms::isCCW(polys->at(0)->getExteriorRing()->getCoordinatesRO()); ringlist[i]->inner_rings[j]->direction = ccw ? COUNTERCLOCKWISE : CLOCKWISE; ringlist[i]->inner_rings[k]->polygon = NULL; j=-1; break; } } else { // other kind of intersect between inner rings; this is // not allwoed and will lead to an exception later when // building the MP } } } STOP_TIMER(inner_ring_touch) for (unsigned int j=0; jinner_rings.size(); j++) { if (!ringlist[i]->inner_rings[j]->polygon) continue; geos::geom::LinearRing *ring = (geos::geom::LinearRing *) ringlist[i]->inner_rings[j]->polygon->getExteriorRing(); if (ringlist[i]->inner_rings[j]->direction == CLOCKWISE) { // reverse ring geos::geom::LineString *tmp = dynamic_cast(ring->reverse()); geos::geom::LinearRing *reversed_ring = Osmium::Geometry::geos_geometry_factory()->createLinearRing(tmp->getCoordinates()); delete tmp; holes->push_back(reversed_ring); } else { holes->push_back(ring); } } geos::geom::LinearRing *ring = (geos::geom::LinearRing *) ringlist[i]->polygon->getExteriorRing(); if (ringlist[i]->direction == COUNTERCLOCKWISE) { geos::geom::LineString *tmp = dynamic_cast(ring->reverse()); geos::geom::LinearRing *reversed_ring = Osmium::Geometry::geos_geometry_factory()->createLinearRing(tmp->getCoordinates()); ring = reversed_ring; delete tmp; } else { ring = dynamic_cast(ring->clone()); } delete ringlist[i]->polygon; ringlist[i]->polygon = NULL; geos::geom::Polygon *p = NULL; bool valid = false; try { p = Osmium::Geometry::geos_geometry_factory()->createPolygon(ring, holes); if (p) valid = p->isValid(); } catch (const geos::util::GEOSException& exc) { // nop if (Osmium::debug()) std::cerr << "Exception during creation of polygon for relation #" << relation->id() << ": " << exc.what() << " (treating as invalid polygon)" << std::endl; } if (!valid) { // polygon is invalid. clear_ringlist(); clear_wayinfo(); if (p) delete p; else delete ring; return geometry_error("invalid ring"); } else { polygons->push_back(p); for (unsigned int k=0; kways.size(); k++) { WayInfo *wi = ringlist[i]->ways[k]; // may have "hole filler" ways in there, not backed by // proper way and thus no tags: if (wi->way == NULL) continue; if (untagged(wi->way)) { // way not tagged - ok } else if (same_tags(relation, wi->way)) { // way tagged the same as relation/previous ways, ok } else if (untagged(relation)) { // relation untagged; use tags from way; ok merge_tags(relation, wi->way); } wi->innerouter = OUTER; if (wi->orig_innerouter == INNER && wi->errorhint.empty()) { // warning: inner/outer mismatch } } // copy tags from relation into area tags(relation->tags()); } // later delete ringlist[i]; // ringlist[i] = NULL; } STOP_TIMER(polygon_build); clear_ringlist(); clear_wayinfo(); if (polygons->empty()) { return geometry_error("no rings"); } START_TIMER(multipolygon_build); bool valid = false; try { mp = Osmium::Geometry::geos_geometry_factory()->createMultiPolygon(polygons); valid = mp->isValid(); } catch (const geos::util::GEOSException& exc) { // nop }; STOP_TIMER(multipolygon_build); if (valid) { geometry = mp; return true; } return geometry_error("multipolygon invalid"); } bool geometry_error(const char *message) { geometry_error_message = message; if (Osmium::debug()) { std::cerr << "building mp failed: " << geometry_error_message << std::endl; } geometry = NULL; return false; } #endif // OSMIUM_WITH_GEOS }; // class AreaFromRelation } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_AREA_HPP osmium/include/osmium/osm/position.hpp0000664000175000017500000001055011706551765017456 0ustar daviddavid#ifndef OSMIUM_OSM_POSITION_HPP #define OSMIUM_OSM_POSITION_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #ifdef OSMIUM_WITH_GEOS # include #endif namespace Osmium { namespace OSM { /** * Positions are stored in 32 bit integers for the x and y * coordinates, respectively. This gives you an accuracy of a few * centimeters, good enough for OSM use. (The main OSM database uses * the same scheme.) */ class Position { public: explicit Position() : m_x(std::numeric_limits::max()), m_y(std::numeric_limits::max()) { } explicit Position(int32_t x, int32_t y) : m_x(x), m_y(y) { } explicit Position(double lon, double lat) : m_x(double_to_fix(lon)), m_y(double_to_fix(lat)) { } bool defined() const { return m_x != std::numeric_limits::max() && m_x != std::numeric_limits::min(); } int32_t x() const { return m_x; } int32_t y() const { return m_y; } double lon() const { return fix_to_double(m_x); } double lat() const { return fix_to_double(m_y); } Position& lon(double lon) { m_x = double_to_fix(lon); return *this; } Position& lat(double lat) { m_y = double_to_fix(lat); return *this; } #ifdef OSMIUM_WITH_JAVASCRIPT v8::Handle js_to_array() const { v8::HandleScope scope; v8::Local array = v8::Array::New(2); array->Set(0, v8::Number::New(lon())); array->Set(1, v8::Number::New(lat())); return scope.Close(array); } #endif // OSMIUM_WITH_JAVASCRIPT friend bool operator==(const Position& p1, const Position& p2) { return p1.m_x == p2.m_x && p1.m_y == p2.m_y; } friend bool operator!=(const Position& p1, const Position& p2) { return !(p1 == p2); } friend std::ostream& operator<<(std::ostream& out, const Position& position) { out << '(' << position.lon() << ',' << position.lat() << ')'; return out; } /// conversion to uint32_t operator uint32_t() const { int32_t x = 180 + m_x / precision; int32_t y = 90 - m_y / precision; if (x < 0) x = 0; if (y < 0) y = 0; if (x >= 360) x = 359; if (y >= 180) y = 179; return 360 * y + x; } #ifdef OSMIUM_WITH_GEOS /** * Conversion of Position to GEOS Coordinate. */ operator geos::geom::Coordinate() const { geos::geom::Coordinate c(lon(), lat()); return c; } #endif private: static const int precision = 10000000; int32_t m_x; int32_t m_y; static int32_t double_to_fix(double c) { return round(c * precision); } static double fix_to_double(int32_t c) { return static_cast(c) / precision; } }; } // namespace OSM } // namespace Osmium #endif // OSMIUM_OSM_POSITION_HPP osmium/include/osmium.hpp0000664000175000017500000000654111706551765015021 0ustar daviddavid#ifndef OSMIUM_OSMIUM_HPP #define OSMIUM_OSMIUM_HPP /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ /** * @mainpage * * %Osmium is a fast and flexible C++ and Javascript toolkit and framework for * working with OSM data. * * This is the API documentation that was automatically created from the * source code. For more general information see * http://wiki.openstreetmap.org/wiki/Osmium . * * %Osmium is free software and available under the LGPLv3 or GPLv3. The * source code is at https://github.com/joto/osmium . */ #ifdef OSMIUM_WITH_JAVASCRIPT # include # include # include #endif // OSMIUM_WITH_JAVASCRIPT #include /** * @brief All %Osmium code is in this namespace. */ namespace Osmium { /** * Internal class to manage global state. */ class Framework { Framework(bool d) : debug(d) { } ~Framework() { // this is needed even if the protobuf lib was never used so that valgrind doesn't report any errors google::protobuf::ShutdownProtobufLibrary(); } bool debug; friend Framework& init(bool debug); friend void set_debug(bool d); friend bool debug(); }; // class Framework /** * Initialize the Osmium library. Call this before using any of the Osmium * functions. * * @param debug Enable or disable the debugging output. */ Framework& init(bool debug=false) { static Framework f(debug); return f; } /** * Enable or disable the debugging output. */ void set_debug(bool d) { init().debug = d; } /** * Is debugging output set? */ bool debug() { return init().debug; } } // namespace Osmium // check way geometry before making a shplib object from it // normally this should be defined, otherwise you will generate invalid linestring geometries #define OSMIUM_CHECK_WAY_GEOMETRY #ifdef OSMIUM_WITH_JAVASCRIPT # include #endif // OSMIUM_WITH_JAVASCRIPT #include #include #include #include #include #include #include #include #include #include #include #include #ifdef OSMIUM_WITH_JAVASCRIPT # include #endif // OSMIUM_WITH_JAVASCRIPT #endif // OSMIUM_OSMIUM_HPP osmium/Makefile0000664000175000017500000000330611706551765013010 0ustar daviddavid#------------------------------------------------------------------------------ # # Osmium main makefile # #------------------------------------------------------------------------------ all: clean: rm -fr doc/html install: doc install -m 755 -g root -o root -d $(DESTDIR)/usr/include install -m 755 -g root -o root -d $(DESTDIR)/usr/share/doc/libosmium-dev install -m 644 -g root -o root README $(DESTDIR)/usr/share/doc/libosmium-dev/README install -m 644 -g root -o root include/osmium.hpp $(DESTDIR)/usr/include cp --recursive include/osmium $(DESTDIR)/usr/include cp --recursive doc/html $(DESTDIR)/usr/share/doc/libosmium-dev check: cppcheck --enable=all -I include */*.cpp test/*/test_*.cpp # This will try to compile each include file on its own to detect missing # #include directives. Note that if this reports [OK], it is not enough # to be sure it will compile in production code. But if it reports [FAILED] # we know we are missing something. check-includes: echo "check includes report:" >check-includes-report; \ for FILE in include/*.hpp include/*/*.hpp include/*/*/*.hpp; do \ echo "$${FILE}:" >>check-includes-report; \ echo -n "$${FILE} "; \ if `g++ -I include $${FILE} 2>>check-includes-report`; then \ echo "[OK]"; \ else \ echo "[FAILED]"; \ fi; \ rm -f $${FILE}.gch; \ done indent: astyle --style=java --indent-namespaces --indent-switches --pad-header --suffix=none --recursive include/\*.hpp examples/\*.cpp examples/\*.hpp osmjs/\*.cpp test/\*.cpp doc: doc/html/files.html doc/html/files.html: include/*.hpp include/*/*.hpp include/*/*/*.hpp doxygen >/dev/null deb: debuild -I -us -uc deb-clean: debuild clean osmium/.gitignore0000664000175000017500000000003711706551765013336 0ustar daviddavidcore doc check-includes-report osmium/examples/0000775000175000017500000000000011706551765013164 5ustar daviddavidosmium/examples/osmium_toshape.cpp0000664000175000017500000001011411706551765016721 0ustar daviddavid/* This is an example tool that converts OSM data to a shapefile. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include typedef Osmium::Storage::SparseTable storage_sparsetable_t; typedef Osmium::Storage::Mmap storage_mmap_t; typedef Osmium::Handler::CoordinatesForWays cfw_handler_t; class MyShapeHandler : public Osmium::Handler::Base { Osmium::Export::PointShapefile* shapefile_point; Osmium::Export::LineStringShapefile* shapefile_linestring; storage_sparsetable_t store_pos; storage_mmap_t store_neg; cfw_handler_t* handler_cfw; public: MyShapeHandler() { handler_cfw = new cfw_handler_t(store_pos, store_neg); shapefile_point = new Osmium::Export::PointShapefile("postboxes"); shapefile_point->add_field("id", FTInteger, 10); shapefile_point->add_field("operator", FTString, 30); shapefile_linestring = new Osmium::Export::LineStringShapefile("roads"); shapefile_linestring->add_field("id", FTInteger, 10); shapefile_linestring->add_field("type", FTString, 30); } ~MyShapeHandler() { delete shapefile_linestring; delete shapefile_point; } void init(Osmium::OSM::Meta& meta) { handler_cfw->init(meta); } void node(const shared_ptr& node) { handler_cfw->node(node); const char* amenity = node->tags().get_tag_by_key("amenity"); if (amenity && !strcmp(amenity, "post_box")) { try { Osmium::Geometry::Point point(*node); shapefile_point->add_geometry(point.create_shp_object()); shapefile_point->add_attribute(0, node->id()); const char* op = node->tags().get_tag_by_key("operator"); if (op) { shapefile_point->add_attribute(1, std::string(op)); } } catch (Osmium::Exception::IllegalGeometry) { std::cerr << "Ignoring illegal geometry for node " << node->id() << ".\n"; } } } void after_nodes() { handler_cfw->after_nodes(); } void way(const shared_ptr& way) { handler_cfw->way(way); const char* highway = way->tags().get_tag_by_key("highway"); if (highway) { try { Osmium::Geometry::LineString linestring(*way); shapefile_linestring->add_geometry(linestring.create_shp_object()); shapefile_linestring->add_attribute(0, way->id()); shapefile_linestring->add_attribute(1, std::string(highway)); } catch (Osmium::Exception::IllegalGeometry) { std::cerr << "Ignoring illegal geometry for way " << way->id() << ".\n"; } } } }; /* ================================================== */ int main(int argc, char *argv[]) { Osmium::init(true); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl; exit(1); } Osmium::OSMFile infile(argv[1]); MyShapeHandler handler; infile.read(handler); } osmium/examples/osmium_sizeof.cpp0000664000175000017500000000713111706551765016562 0ustar daviddavid/* This is a small tool to find out the sizes of some basic classes. It is only used for Osmium development. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include int main() { Osmium::init(); std::cout << "sizeof(Osmium::OSM::Object)=" << sizeof(Osmium::OSM::Object) << "\n"; std::cout << "sizeof(Osmium::OSM::Node)=" << sizeof(Osmium::OSM::Node) << " (Object+" << sizeof(Osmium::OSM::Node) - sizeof(Osmium::OSM::Object) << ")\n"; std::cout << "sizeof(Osmium::OSM::Way)=" << sizeof(Osmium::OSM::Way) << " (Object+" << sizeof(Osmium::OSM::Way) - sizeof(Osmium::OSM::Object) << ")\n"; std::cout << "sizeof(Osmium::OSM::Relation)=" << sizeof(Osmium::OSM::Relation) << " (Object+" << sizeof(Osmium::OSM::Relation) - sizeof(Osmium::OSM::Object) << ")\n"; std::cout << "sizeof(Osmium::OSM::Area)=" << sizeof(Osmium::OSM::Area) << " (Object+" << sizeof(Osmium::OSM::Area) - sizeof(Osmium::OSM::Object) << ")\n"; std::cout << "sizeof(Osmium::OSM::AreaFromWay)=" << sizeof(Osmium::OSM::AreaFromWay) << " (Object+" << sizeof(Osmium::OSM::AreaFromWay) - sizeof(Osmium::OSM::Object) << ")\n"; std::cout << "sizeof(Osmium::OSM::AreaFromRelation)=" << sizeof(Osmium::OSM::AreaFromRelation) << " (Object+" << sizeof(Osmium::OSM::AreaFromRelation) - sizeof(Osmium::OSM::Object) << ")\n"; // std::cout << "sizeof(Osmium::OSM::WayInfo)=" << sizeof(Osmium::OSM::WayInfo) << "\n"; // std::cout << "sizeof(Osmium::OSM::RingInfo)=" << sizeof(Osmium::OSM::RingInfo) << "\n"; std::cout << "sizeof(OSMPBF::BlobHeader)=" << sizeof(OSMPBF::BlobHeader) << "\n"; std::cout << "sizeof(OSMPBF::Blob)=" << sizeof(OSMPBF::Blob) << "\n"; std::cout << "sizeof(OSMPBF::HeaderBlock)=" << sizeof(OSMPBF::HeaderBlock) << "\n"; std::cout << "sizeof(OSMPBF::PrimitiveBlock)=" << sizeof(OSMPBF::PrimitiveBlock) << "\n"; std::cout << "sizeof(OSMPBF::PrimitiveGroup)=" << sizeof(OSMPBF::PrimitiveGroup) << "\n"; std::cout << "sizeof(OSMPBF::Node)=" << sizeof(OSMPBF::Node) << "\n"; std::cout << "sizeof(OSMPBF::Way)=" << sizeof(OSMPBF::Way) << "\n"; std::cout << "sizeof(OSMPBF::Relation)=" << sizeof(OSMPBF::Relation) << "\n"; std::cout << "sizeof(OSMPBF::DenseNodes)=" << sizeof(OSMPBF::DenseNodes) << "\n"; std::cout << "sizeof(OSMPBF::StringTable)=" << sizeof(OSMPBF::StringTable) << "\n"; std::cout << "sizeof(Osmium::Output::PBF)=" << sizeof(Osmium::Output::PBF) << "\n"; std::cout << "sizeof(Osmium::Output::XML)=" << sizeof(Osmium::Output::XML) << "\n"; } osmium/examples/osmium_time.cpp0000664000175000017500000000423711706551765016225 0ustar daviddavid/* This is a small tool to time osmium. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include class MyTimerHandler : public Osmium::Handler::Base { uint64_t m_nodes; uint64_t m_ways; uint64_t m_relations; public: MyTimerHandler() : m_nodes(0), m_ways(0), m_relations(0) { } void node(const shared_ptr& /*node*/) { m_nodes++; } void way(const shared_ptr& /*way*/) { m_ways++; } void relation(const shared_ptr& /*relation*/) { m_relations++; } void final() { std::cout << "nodes: " << m_nodes << " ways: " << m_ways << " relations: " << m_relations << std::endl; } }; /* ================================================== */ int main(int argc, char *argv[]) { Osmium::init(true); time_t t0 = time(NULL); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl; exit(1); } Osmium::OSMFile infile(argv[1]); MyTimerHandler handler; infile.read(handler); struct tms tms; times(&tms); std::cout << "user time: " << ((double)tms.tms_utime) / sysconf(_SC_CLK_TCK) << "s system time: " << ((double)tms.tms_stime) / sysconf(_SC_CLK_TCK) << "s wallclock time: " << time(NULL) - t0 << "s" << std::endl; } osmium/examples/osmium_progress.cpp0000664000175000017500000000244411706551765017131 0ustar daviddavid/* This is a small tool demonstrates the use of the progress handler. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include /* ================================================== */ int main(int argc, char *argv[]) { Osmium::init(true); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl; exit(1); } Osmium::OSMFile infile(argv[1]); Osmium::Handler::Progress handler; infile.read(handler); } osmium/examples/osmium_convert.cpp0000664000175000017500000001350711706551765016747 0ustar daviddavid/* Convert OSM files from one format into another. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include class ConvertHandler : public Osmium::Handler::Base { Osmium::OSMFile& m_outfile; Osmium::Handler::Progress m_progress_handler; Osmium::Output::Base* output; public: ConvertHandler(Osmium::OSMFile& osmfile) : m_outfile(osmfile) { } ~ConvertHandler() { } void init(Osmium::OSM::Meta& meta) { output = m_outfile.create_output_file(); output->init(meta); m_progress_handler.init(meta); } void node(const shared_ptr& node) { output->node(node); m_progress_handler.node(node); } void way(const shared_ptr& way) { output->way(way); m_progress_handler.way(way); } void relation(const shared_ptr& relation) { output->relation(relation); m_progress_handler.relation(relation); } void final() { output->final(); m_progress_handler.final(); delete output; } }; /* ================================================== */ void print_help() { std::cout << "osmium_convert [OPTIONS] [INFILE [OUTFILE]]\n\n" \ << "If INFILE or OUTFILE is not given stdin/stdout is assumed.\n" \ << "File format is given as suffix in format .TYPE[.ENCODING].\n" \ << "Use -f and -t options to force format.\n" \ << "\nFile types:\n" \ << " osm normal OSM file\n" \ << " osh OSM file with history information\n" \ << "\nFile encodings:\n" \ << " (none) XML encoding\n" \ << " gz XML encoding compressed with gzip\n" \ << " bz2 XML encoding compressed with bzip2\n" \ << " pbf binary PBF encoding\n" \ << "\nOptions:\n" \ << " -h, --help This help message\n" \ << " -d, --debug Enable debugging output\n" \ << " -f, --from-format=FORMAT Input format\n" \ << " -t, --to-format=FORMAT Output format\n"; } int main(int argc, char *argv[]) { static struct option long_options[] = { {"debug", no_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"from-format", required_argument, 0, 'f'}, {"to-format", required_argument, 0, 't'}, {0, 0, 0, 0} }; bool debug = false; std::string input_format; std::string output_format; while (true) { int c = getopt_long(argc, argv, "dhf:t:", long_options, 0); if (c == -1) { break; } switch (c) { case 'd': debug = true; break; case 'h': print_help(); exit(0); case 'f': input_format = optarg; break; case 't': output_format = optarg; break; default: exit(1); } } std::string input; std::string output; int remaining_args = argc - optind; if (remaining_args > 2) { std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]" << std::endl; exit(1); } else if (remaining_args == 2) { input = argv[optind]; output = argv[optind+1]; } else if (remaining_args == 1) { input = argv[optind]; } Osmium::init(debug); Osmium::OSMFile infile(input); if (!input_format.empty()) { try { infile.set_type_and_encoding(input_format); } catch (Osmium::OSMFile::ArgumentError& e) { std::cerr << "Unknown format for input: " << e.value() << std::endl; exit(1); } } Osmium::OSMFile outfile(output); if (!output_format.empty()) { try { outfile.set_type_and_encoding(output_format); } catch (Osmium::OSMFile::ArgumentError& e) { std::cerr << "Unknown format for output: " << e.value() << std::endl; exit(1); } } if (infile.get_type() == Osmium::OSMFile::FileType::OSM() && outfile.get_type() == Osmium::OSMFile::FileType::History()) { std::cerr << "Warning! You are converting from an OSM file without history information to one with history information.\nThis will almost certainly not do what you want!" << std::endl; } else if (infile.get_type() == Osmium::OSMFile::FileType::History() && outfile.get_type() == Osmium::OSMFile::FileType::OSM()) { std::cerr << "Warning! You are converting from an OSM file with history information to one without history information.\nThis will almost certainly not do what you want!" << std::endl; } else if (infile.get_type() != outfile.get_type()) { std::cerr << "Warning! Source and destination are not of the same type." << std::endl; } ConvertHandler handler(outfile); infile.read(handler); } osmium/examples/nodedensity.cpp0000664000175000017500000000744011706551765016222 0ustar daviddavid/* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include /* ================================================== */ typedef uint16_t node_count_t; class NodeDensityHandler : public Osmium::Handler::Base { node_count_t* m_node_count; int m_xsize; int m_ysize; double m_factor; int m_min; int m_max; int m_diff; int m_max_count; public: NodeDensityHandler(int size = 1024, int min = 0, int max = 99999) : Base(), m_xsize(size*2), m_ysize(size), m_min(min), m_max(max) { m_factor = m_ysize / 180; m_node_count = static_cast(calloc(m_xsize * m_ysize, sizeof(node_count_t))); m_max_count = 0; m_diff = m_max - m_min; } ~NodeDensityHandler() { free(m_node_count); } void node(const shared_ptr& node) { int x = int( (180 + node->position().lon()) * m_factor ); int y = int( ( 90 - node->position().lat()) * m_factor ); if (x < 0) x = 0; if (x >= m_xsize) x = m_xsize-1; if (y < 0) y = 0; if (y >= m_ysize) y = m_ysize-1; int n = y * m_xsize + x; if (m_node_count[n] < std::numeric_limits::max() - 1) { m_node_count[n]++; } if (m_node_count[n] > m_max_count) { m_max_count = m_node_count[n]; } } void after_nodes() { std::cerr << "max_count=" << m_max_count << "\n"; gdImagePtr im = gdImageCreate(m_xsize, m_ysize); for (int i=0; i <= 255; ++i) { gdImageColorAllocate(im, i, i, i); } int n=0; for (int y=0; y < m_ysize; ++y) { for (int x=0; x < m_xsize; ++x) { int val = m_node_count[n++]; if (val < m_min) val = m_min; if (val > m_max) val = m_max; gdImageSetPixel(im, x, y, static_cast((val - m_min) * 255 / m_diff)); } } gdImagePng(im, stdout); gdImageDestroy(im); throw Osmium::Input::StopReading(); } }; // class NodeDensityHandler /* ================================================== */ int main(int argc, char *argv[]) { Osmium::init(); if (argc != 5) { std::cerr << "Usage: " << argv[0] << " OSMFILE SIZE MIN MAX\n\n"; std::cerr << " OSMFILE - OSM file of any type.\n"; std::cerr << " SIZE - Y-size of resulting image (X-size will be double).\n"; std::cerr << " MIN - Node counts smaller than this will be black.\n"; std::cerr << " MAX - Node counts larger than this will be white.\n\n"; std::cerr << "Output will be a PNG file on STDOUT. Make sure to redirect.\n"; exit(1); } int size = atoi(argv[2]); int min = atoi(argv[3]); int max = atoi(argv[4]); Osmium::OSMFile infile(argv[1]); NodeDensityHandler handler(size, min, max); infile.read(handler); } osmium/examples/osmium_toogr.cpp0000664000175000017500000001522311706551765016416 0ustar daviddavid/* This is an example tool that converts OSM data to a spatialite database using the OGR library. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include typedef Osmium::Storage::SparseTable storage_sparsetable_t; typedef Osmium::Storage::Mmap storage_mmap_t; typedef Osmium::Handler::CoordinatesForWays cfw_handler_t; class MyOGRHandler : public Osmium::Handler::Base { OGRDataSource* m_data_source; OGRLayer* m_layer_point; OGRLayer* m_layer_linestring; storage_sparsetable_t store_pos; storage_mmap_t store_neg; cfw_handler_t* handler_cfw; public: MyOGRHandler() { handler_cfw = new cfw_handler_t(store_pos, store_neg); OGRRegisterAll(); const char* driver_name = "SQLite"; OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name); if (driver == NULL) { std::cerr << driver_name << " driver not available.\n"; exit(1); } CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE"); const char* options[] = { "SPATIALITE=TRUE", NULL }; m_data_source = driver->CreateDataSource("ogr_out.sqlite", const_cast(options)); if (m_data_source == NULL) { std::cerr << "Creation of output file failed.\n"; exit(1); } OGRSpatialReference sparef("EPSG:4326"); m_layer_point = m_data_source->CreateLayer("postboxes", &sparef, wkbPoint, NULL); if (m_layer_point == NULL) { std::cerr << "Layer creation failed.\n"; exit(1); } OGRFieldDefn layer_point_field_id("id", OFTInteger); layer_point_field_id.SetWidth(10); if (m_layer_point->CreateField(&layer_point_field_id) != OGRERR_NONE ) { std::cerr << "Creating id field failed.\n"; exit(1); } OGRFieldDefn layer_point_field_operator("operator", OFTString); layer_point_field_operator.SetWidth(30); if (m_layer_point->CreateField(&layer_point_field_operator) != OGRERR_NONE ) { std::cerr << "Creating operator field failed.\n"; exit(1); } m_layer_linestring = m_data_source->CreateLayer("roads", &sparef, wkbLineString, NULL); if (m_layer_linestring == NULL) { std::cerr << "Layer creation failed.\n"; exit(1); } OGRFieldDefn layer_linestring_field_id("id", OFTInteger); layer_linestring_field_id.SetWidth(10); if (m_layer_linestring->CreateField(&layer_linestring_field_id) != OGRERR_NONE ) { std::cerr << "Creating id field failed.\n"; exit(1); } OGRFieldDefn layer_linestring_field_operator("type", OFTString); layer_linestring_field_operator.SetWidth(30); if (m_layer_linestring->CreateField(&layer_linestring_field_operator) != OGRERR_NONE ) { std::cerr << "Creating operator field failed.\n"; exit(1); } } ~MyOGRHandler() { OGRDataSource::DestroyDataSource(m_data_source); delete handler_cfw; } void init(Osmium::OSM::Meta& meta) { handler_cfw->init(meta); } void node(const shared_ptr& node) { handler_cfw->node(node); const char* amenity = node->tags().get_tag_by_key("amenity"); if (amenity && !strcmp(amenity, "post_box")) { try { Osmium::Geometry::Point point(*node); OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn()); OGRPoint* ogrpoint = point.create_ogr_geometry(); feature->SetGeometry(ogrpoint); feature->SetField("id", node->id()); feature->SetField("operator", node->tags().get_tag_by_key("operator")); if (m_layer_point->CreateFeature(feature) != OGRERR_NONE) { std::cerr << "Failed to create feature.\n"; exit(1); } OGRFeature::DestroyFeature(feature); delete ogrpoint; } catch (Osmium::Exception::IllegalGeometry) { std::cerr << "Ignoring illegal geometry for node " << node->id() << ".\n"; } } } void after_nodes() { handler_cfw->after_nodes(); } void way(const shared_ptr& way) { handler_cfw->way(way); const char* highway = way->tags().get_tag_by_key("highway"); if (highway) { try { Osmium::Geometry::LineString linestring(*way); OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn()); OGRLineString* ogrlinestring = linestring.create_ogr_geometry(); feature->SetGeometry(ogrlinestring); feature->SetField("id", way->id()); feature->SetField("type", highway); if (m_layer_linestring->CreateFeature(feature) != OGRERR_NONE) { std::cerr << "Failed to create feature.\n"; exit(1); } OGRFeature::DestroyFeature(feature); delete ogrlinestring; } catch (Osmium::Exception::IllegalGeometry) { std::cerr << "Ignoring illegal geometry for way " << way->id() << ".\n"; } } } }; /* ================================================== */ int main(int argc, char *argv[]) { Osmium::init(true); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl; exit(1); } Osmium::OSMFile infile(argv[1]); MyOGRHandler handler; infile.read(handler); } osmium/examples/osmium_range_from_history.cpp0000664000175000017500000000276711706551765021175 0ustar daviddavid/* Program to test the RangeFromHistory handler. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include int main(int argc, char *argv[]) { Osmium::init(); if (argc != 3) { std::cerr << "Usage: " << argv[0] << " INFILE OUTFILE\n"; exit(1); } Osmium::OSMFile infile(argv[1]); Osmium::OSMFile outfile(argv[2]); Osmium::Handler::RangeFromHistory range_handler(outfile.create_output_file(), time(0), time(0)); Osmium::Handler::EndTime > handler(&range_handler); infile.read(handler); } osmium/examples/osmium_find_bbox.cpp0000664000175000017500000000301411706551765017211 0ustar daviddavid/* This is a small tool to find the bounding box of the input file. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include /* ================================================== */ int main(int argc, char *argv[]) { Osmium::init(); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl; exit(1); } Osmium::OSMFile infile(argv[1]); Osmium::Handler::FindBbox handler; infile.read(handler); Osmium::OSM::Bounds b = handler.bounds(); std::cout << "minlon=" << b.bl().lon() << " minlat=" << b.bl().lat() << " maxlon=" << b.tr().lon() << " maxlat=" << b.tr().lat() << std::endl; } osmium/examples/Makefile0000664000175000017500000000611111706551765014623 0ustar daviddavid#------------------------------------------------------------------------------ # # Makefile for Osmium examples. # #------------------------------------------------------------------------------ CXX = g++ #CXX = clang CXXFLAGS = -g #CXXFLAGS = -O3 CXXFLAGS += -Wall -Wextra -Wredundant-decls -Wdisabled-optimization -pedantic -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo #CXXFLAGS += -Wpadded -Winline -Weffc++ -Wold-style-cast # uncomment this if you want information on how long it took to build the multipolygons #CXXFLAGS += -DOSMIUM_WITH_MULTIPOLYGON_PROFILING CXXFLAGS_GEOS = -DOSMIUM_WITH_GEOS $(shell geos-config --cflags) CXXFLAGS_SHAPE = -DOSMIUM_WITH_SHPLIB $(CXXFLAGS_GEOS) CXXFLAGS_LIBXML2 = -DOSMIUM_WITH_OUTPUT_OSM_XML $(shell xml2-config --cflags) CXXFLAGS_OGR = -DOSMIUM_WITH_OGR $(shell gdal-config --cflags) CXXFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 CXXFLAGS += -I../include LDFLAGS = -L/usr/local/lib -lexpat -lpthread LIB_GD = -lgd -lz -lm LIB_SQLITE = -lsqlite3 LIB_V8 = -lv8 LIB_GEOS = $(shell geos-config --libs) LIB_SHAPE = -lshp $(LIB_GEOS) LIB_PROTOBUF = -lz -lprotobuf-lite -losmpbf LIB_XML2 = $(shell xml2-config --libs) LIB_OGR = $(shell gdal-config --libs) PROGRAMS = \ osmium_convert \ osmium_debug \ osmium_store_and_debug \ osmium_find_bbox \ osmium_progress \ osmium_range_from_history \ osmium_sizeof \ osmium_stats \ osmium_time \ osmium_toogr \ osmium_toogr2 \ osmium_toshape \ nodedensity .PHONY: all clean all: $(PROGRAMS) osmium_convert: osmium_convert.cpp $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_XML2) osmium_store_and_debug: osmium_store_and_debug.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) osmium_debug: osmium_debug.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) # $(CXX) $(CXXFLAGS) -DOSMIUM_DEBUG_WITH_ENDTIME -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) osmium_find_bbox: osmium_find_bbox.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) osmium_progress: osmium_progress.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) osmium_range_from_history: osmium_range_from_history.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) osmium_sizeof: osmium_sizeof.cpp $(CXX) $(CXXFLAGS) $(CXXFLAGS_LIBXML2) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_XML2) osmium_stats: osmium_stats.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_SQLITE) osmium_time: osmium_time.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) osmium_toogr: osmium_toogr.cpp $(CXX) $(CXXFLAGS) $(CXXFLAGS_OGR) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_OGR) osmium_toogr2: osmium_toogr2.cpp $(CXX) $(CXXFLAGS) $(CXXFLAGS_OGR) $(CXXFLAGS_GEOS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_OGR) $(LIB_GEOS) osmium_toshape: osmium_toshape.cpp $(CXX) $(CXXFLAGS) $(CXXFLAGS_SHAPE) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_SHAPE) nodedensity: nodedensity.cpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIB_PROTOBUF) $(LIB_GD) clean: rm -f *.o core $(PROGRAMS) osmium/examples/.gitignore0000664000175000017500000000031311706551765015151 0ustar daviddavidnodedensity osmium_convert osmium_debug osmium_find_bbox osmium_progress osmium_range_from_history osmium_sizeof osmium_stats osmium_store_and_debug osmium_time osmium_toogr osmium_toogr2 osmium_toshape osmium/examples/osmium_store_and_debug.cpp0000664000175000017500000000305511706551765020410 0ustar daviddavid/* This is a small tool to dump the contents of the input file. If OSMIUM_DEBUG_WITH_ENDTIME is defined when compiling, the Osmium::Handler::EndTime is used. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include int main(int argc, char *argv[]) { Osmium::init(true); if (argc != 3) { std::cerr << "Usage: " << argv[0] << " OSMFILE1 OSMFILE2\n"; exit(1); } Osmium::OSMFile infile1(argv[1]); Osmium::OSMFile infile2(argv[2]); Osmium::Storage::ObjectStore os; infile1.read(os); Osmium::Handler::Debug debug; Osmium::OSM::Meta meta; Osmium::Storage::ObjectStore::ApplyHandler ah(os, &debug, meta); infile2.read(ah); } osmium/examples/osmium_stats.cpp0000664000175000017500000000242411706551765016421 0ustar daviddavid/* This is a small tool to try the Statistics handler */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include /* ================================================== */ int main(int argc, char *argv[]) { Osmium::init(); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl; exit(1); } Osmium::OSMFile infile(argv[1]); Osmium::Handler::Statistics handler; infile.read(handler); } osmium/examples/osmium_toogr2.cpp0000664000175000017500000001351211706551765016477 0ustar daviddavid/* This is an example tool that converts OSM data to a spatialite database using the OGR library. This version creates multipolygons and reads the input file twice to do that. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #include #include #include #include #include typedef Osmium::Storage::SparseTable storage_sparsetable_t; typedef Osmium::Storage::Mmap storage_mmap_t; typedef Osmium::Handler::CoordinatesForWays cfw_handler_t; class MyOGRHandlerPass1 : public Osmium::Handler::Base { Osmium::Handler::Multipolygon* handler_multipolygon; public: MyOGRHandlerPass1(Osmium::Handler::Multipolygon* hmp) : handler_multipolygon(hmp) { } ~MyOGRHandlerPass1() { } void before_relations() { handler_multipolygon->before_relations(); } void relation(const shared_ptr& relation) { handler_multipolygon->relation(relation); } void after_relations() { handler_multipolygon->after_relations(); std::cerr << "1st pass finished" << std::endl; } }; /* ================================================== */ class MyOGRHandlerPass2 : public Osmium::Handler::Base { OGRDataSource* m_data_source; OGRLayer* m_layer_mp; storage_sparsetable_t store_pos; storage_mmap_t store_neg; cfw_handler_t* handler_cfw; Osmium::Handler::Multipolygon* handler_multipolygon; public: MyOGRHandlerPass2(Osmium::Handler::Multipolygon* hmp) : handler_multipolygon(hmp) { handler_cfw = new cfw_handler_t(store_pos, store_neg); OGRRegisterAll(); const char* driver_name = "SQLite"; OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name); if (driver == NULL) { std::cerr << driver_name << " driver not available.\n"; exit(1); } CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE"); const char* options[] = { "SPATIALITE=TRUE", NULL }; m_data_source = driver->CreateDataSource("ogr_out.sqlite", const_cast(options)); if (m_data_source == NULL) { std::cerr << "Creation of output file failed.\n"; exit(1); } OGRSpatialReference sparef("EPSG:4326"); m_layer_mp = m_data_source->CreateLayer("areas", &sparef, wkbMultiPolygon, NULL); if (m_layer_mp == NULL) { std::cerr << "Layer creation failed.\n"; exit(1); } OGRFieldDefn layer_mp_field_id("id", OFTInteger); layer_mp_field_id.SetWidth(10); if (m_layer_mp->CreateField(&layer_mp_field_id) != OGRERR_NONE ) { std::cerr << "Creating id field failed.\n"; exit(1); } } ~MyOGRHandlerPass2() { OGRDataSource::DestroyDataSource(m_data_source); delete handler_cfw; } void init(Osmium::OSM::Meta& meta) { handler_cfw->init(meta); } void node(const shared_ptr& node) { handler_cfw->node(node); } void after_nodes() { handler_cfw->after_nodes(); } void way(const shared_ptr& way) { handler_cfw->way(way); handler_multipolygon->way(way); } void area(Osmium::OSM::Area* area) { const char* building = area->tags().get_tag_by_key("building"); if (building) { try { Osmium::Geometry::MultiPolygon mp(*area); OGRFeature* feature = OGRFeature::CreateFeature(m_layer_mp->GetLayerDefn()); OGRMultiPolygon* ogrmp = mp.create_ogr_geometry(); feature->SetGeometry(ogrmp); feature->SetField("id", area->id()); if (m_layer_mp->CreateFeature(feature) != OGRERR_NONE) { std::cerr << "Failed to create feature.\n"; exit(1); } OGRFeature::DestroyFeature(feature); delete ogrmp; } catch (Osmium::Exception::IllegalGeometry) { std::cerr << "Ignoring illegal geometry for multipolygon " << area->id() << ".\n"; } } } }; MyOGRHandlerPass2* hpass2; /* ================================================== */ void cbmp(Osmium::OSM::Area* area) { hpass2->area(area); } int main(int argc, char *argv[]) { Osmium::init(true); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE" << std::endl; exit(1); } Osmium::OSMFile infile(argv[1]); bool attempt_repair = true; Osmium::Handler::Multipolygon handler_multipolygon(attempt_repair, cbmp); // first pass MyOGRHandlerPass1 handler_pass1(&handler_multipolygon); infile.read(handler_pass1); // second pass MyOGRHandlerPass2 handler_pass2(&handler_multipolygon); hpass2 = &handler_pass2; infile.read(handler_pass2); } osmium/examples/osmium_debug.cpp0000664000175000017500000000320411706551765016346 0ustar daviddavid/* This is a small tool to dump the contents of the input file. If OSMIUM_DEBUG_WITH_ENDTIME is defined when compiling, the Osmium::Handler::EndTime is used. */ /* Copyright 2011 Jochen Topf and others (see README). This file is part of Osmium (https://github.com/joto/osmium). Osmium is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License or (at your option) the GNU General Public License as published by the Free Software Foundation, either version 3 of the Licenses, or (at your option) any later version. Osmium is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU General Public License for more details. You should have received a copy of the Licenses along with Osmium. If not, see . */ #include #include #ifdef OSMIUM_DEBUG_WITH_ENDTIME # include #endif // OSMIUM_DEBUG_WITH_ENDTIME int main(int argc, char *argv[]) { std::ios_base::sync_with_stdio(false); Osmium::init(true); if (argc != 2) { std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; exit(1); } Osmium::OSMFile infile(argv[1]); #ifdef OSMIUM_DEBUG_WITH_ENDTIME Osmium::Handler::Debug debug_handler(true); Osmium::Handler::EndTime handler(&debug_handler); #else Osmium::Handler::Debug handler; #endif // OSMIUM_DEBUG_WITH_ENDTIME infile.read(handler); } osmium/examples/README0000664000175000017500000000370011706551765014044 0ustar daviddavid Osmium Examples =============== This folder contains a number of example applications to demonstrate the use of the Osmium framework for other developers. FILES ----- * nodedensity This application will write a heatmap-like PNG to stdout based on the density of nodes in the supplied input file. * osmium_convert This application can be used to convert between the several OSM file formats like OSM (xml), gzip-compressed XML, bzip2-compressed XML and PBF. * osmium_debug This is a small tool to dump the contents of the input file. * osmium_find_bbox This is a small tool to find the bounding box of the input file. * osmium_progress This is a small tool demonstrating the use of the progress handler. * osmium_range_from_history Program to test the RangeFromHistory handler. * osmium_sizeof This is a small tool to find out the sizes of some basic classes. It is only used for Osmium development. * osmium_stats This is a small tool to try the Statistics handler. * osmium_store_and_debug This is a small tool to dump the contents of the input file. * osmium_time A small application that counts the various nodes, ways and relations in an input file and shows the time that it took to do that. * osmium_toogr This is an example tool that converts OSM data to a spatialite database using the OGR library. * osmium_toogr2 This is an example tool that converts OSM data to a spatialite database using the OGR library. (This version creates multipolygons and reads the input file twice to do that.) * osmium_toshape An example application that converts any kind of OSM file into a set of shapefiles. It is filtering out highways as linestrings and postboxes as points. BUILDING -------- First you need to (build and) install all the prerequisites as mentioned in the README file inside the main project folder. To build the example applications go into the "examples" directory and call "make". osmium/LICENSE-GPLv30000664000175000017500000010451311706551765013250 0ustar daviddavid GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . osmium/THANKS0000664000175000017500000000015711706551765012264 0ustar daviddavid Parts of the Osmium/Osmjs development was funded through a project of the European Environment Agency (EEA). osmium/README0000664000175000017500000001143311706551765012230 0ustar daviddavid Osmium ====== http://wiki.openstreetmap.org/wiki/Osmium Osmium is a C++ framework for working with OSM data files. Osmium can read OSM data in XML or binary format (PBF) and can call different handlers for each OSM object. Available handlers include: * Javascript handler (calls Javascript callbacks you provide) * Multipolygon handler (assembles areas(multipolygons) from relations and ways) * NodeLocationStore handler (stores node locations and builds way geometries from them) * Statistics handler (does some general statistics) * (others...) Of course, you can also write your own handlers. There are a few applications that use Osmium in the examples directory. The osmjs directory contains the osmjs application that calls your Javascript code which can then work with the OSM data. It can, for instance, be used to convert OSM data into Shapefiles. Note that OSM input files must contain objects in the right order for Osmium to work properly: first nodes, then ways, then relations. Normally OSM files are sorted this way, but if yours aren't, you can use Osmosis with the --sort option to do this. PREREQUISITES ------------- Different parts of Osmium and the applications build on top of it need different libraries: boost (several libraries) http://www.boost.org/ Debian/Ubuntu: libboost-dev zlib (for PBF support) http://www.zlib.net/ Debian/Ubuntu: zlib1g-dev shapelib (for shapefile support in osmjs) http://shapelib.maptools.org/ Debian/Ubuntu: libshp-dev libsqlite3 (for some applications only) http://sqlite.org/ Debian/Ubuntu: libsqlite3-dev libgd (for tagstats and nodedensity applications only) http://www.libgd.org/ Debian/Ubuntu: libgd2-xpm-dev GDAL (for OGR support) http://gdal.org/ Debian/Ubuntu: libgdal1-dev Expat (for parsing XML files) http://expat.sourceforge.net/ Debian/Ubuntu: libexpat1-dev GEOS (for assembling multipolygons etc.) http://trac.osgeo.org/geos/ Debian/Ubuntu: libgeos-dev Google sparsehash http://code.google.com/p/google-sparsehash/ Debian/Ubuntu: libsparsehash-dev Google V8 Javascript engine (for Javascript support) http://code.google.com/apis/v8/ Debian/Ubuntu: libv8-dev LibICU (for UTF-8/UTF-16 conversion, only for Javascript support) http://site.icu-project.org/ Debian/Ubuntu: libicu-dev Google protocol buffers (for PBF support) http://code.google.com/p/protobuf/ (at least Version 2.3.0 needed) Debian/Ubuntu: libprotobuf-dev protobuf-compiler Also see http://wiki.openstreetmap.org/wiki/PBF_Format Doxygen (to build API documentation) http://www.stack.nl/~dimitri/doxygen/ Debian/Ubuntu: doxygen libboost-test (for tests) http://www.boost.org/doc/libs/1_47_0/libs/test/doc/html/index.html Debian/Ubuntu: libboost-test-dev OSMPBF (for PBF support) https://github.com/scrosby/OSM-binary You need to build this first. You need to either install the Debian/Ubuntu packages (or equivalent for other distributions) or install those libraries from source. Most libraries should be available in all distributions. The Google libs (V8, protobuf, sparsehash) are only available in newer distributions (Ubuntu since Maverick). FILES ----- Doxyfile - Needed for building the Osmium C++ docs, call "make doc" to build. include - C/C++ include files. All of Osmium is in those header files which are needed for building Osmium applications. osmjs - Osmium application "osmjs". osmjs/js - Example Javascript handlers. examples - Osmium example applications. BUILDING -------- First you need to (build and) install all the prerequisites. Osmium is a header-only library, so there is nothing to build for the library itself. Call "make doc" in the top-level directory to build the Osmium C++ docs. Call "make install" to install the include files and documentation. See "examples/README" for build instructions of the example applications. See "osmjs/README" for build instructions of osmjs. Call "make clean" in any of those places to clean up. TESTING ------- There are a few tests using the Boost Unit Test Framework in the 'test' directory. Go there and type "./run_tests.sh" to compile and run the tests. Many more tests are needed, any help appreciated. LICENSE ------- Osmium is available under the GNU LGPL version 3 or later, or - at your option - the GNU GPL version 3 or later. See http://eigen.tuxfamily.org/index.php?title=Licensing_FAQ for a good description of what that means. AUTHORS ------- Osmium was mainly written and is maintained by Jochen Topf . Other authors: * Frederik Ramm (Multipolygon code, ...) * Christian Vetter (PBF parser) * Scott A. Crosby (PBF format) * Peter Körner (XML and PBF writer, ...) osmium/LICENSE-LGPLv30000664000175000017500000001674311706551765013373 0ustar daviddavid GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.