Skip to content

Instantly share code, notes, and snippets.

@yohanboniface
Created November 17, 2017 14:21
Show Gist options
  • Save yohanboniface/7df8229fc481cd1b0194fa2788c7bd2d to your computer and use it in GitHub Desktop.
Save yohanboniface/7df8229fc481cd1b0194fa2788c7bd2d to your computer and use it in GitHub Desktop.
Extract boundaries from OpenStreetMap (as lines, to keep individual tags, like maritime=*)
# put here the name of keys for ways that are assumed to be polygons if they are closed
# see http://wiki.openstreetmap.org/wiki/Map_Features
closed_ways_are_polygons=aeroway,amenity,boundary,building,craft,geological,historic,landuse,leisure,military,natural,office,place,shop,sport,tourism
# comment to avoid laundering of keys ( ':' turned into '_' )
attribute_name_laundering=yes
# uncomment to report all nodes, including the ones without any (significant) tag
report_all_nodes=yes
# uncomment to report all ways, including the ones without any (significant) tag
report_all_ways=yes
[multipolygons]
# common attributes
# note: for multipolygons, osm_id=yes instanciates a osm_id field for the id of relations
# and a osm_way_id field for the id of closed ways. Both fields are exclusively set.
osm_id=yes
osm_version=no
osm_timestamp=no
osm_uid=no
osm_user=no
osm_changeset=no
# keys to report as OGR fields
attributes=name,name:fr,name:en,name:ar,name:es,boundary,border_type,admin_level,maritime
# keys that should NOT be reported in the "other_tags" field
ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
# uncomment to avoid creation of "other_tags" field
other_tags=no
[multilinestrings]
# common attributes
# note: for multipolygons, osm_id=yes instanciates a osm_id field for the id of relations
# and a osm_way_id field for the id of closed ways. Both fields are exclusively set.
osm_id=yes
osm_version=no
osm_timestamp=no
osm_uid=no
osm_user=no
osm_changeset=no
# keys to report as OGR fields
attributes=name,name:fr,name:en,name:ar,name:es,boundary,border_type,admin_level,maritime
# keys that should NOT be reported in the "other_tags" field
ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
# uncomment to avoid creation of "other_tags" field
other_tags=no
[lines]
# common attributes
# note: for multipolygons, osm_id=yes instanciates a osm_id field for the id of relations
# and a osm_way_id field for the id of closed ways. Both fields are exclusively set.
osm_id=yes
osm_version=no
osm_timestamp=no
osm_uid=no
osm_user=no
osm_changeset=no
# keys to report as OGR fields
attributes=name,name:fr,name:en,name:ar,name:es,boundary,border_type,admin_level,maritime
# keys that should NOT be reported in the "other_tags" field
ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
# uncomment to avoid creation of "other_tags" field
other_tags=no
"""
Filter all objects with a coastline tag.
This example shows how to write objects to a file.
We need to go twice over the file. First read the ways, filter the ones
we are interested in and remember the nodes required. Then, in a second
run all the relevant nodes and ways are written out.
"""
import osmium
import sys
class WayFilter(osmium.SimpleHandler):
def __init__(self):
super().__init__()
self.ways = set()
def relation(self, rel):
if (rel.tags.get('boundary') == 'administrative' and
rel.tags.get('admin_level') == '2'):
for way in rel.members:
self.ways.add(way.ref)
class NodeFilter(osmium.SimpleHandler):
def __init__(self, ways):
super().__init__()
self.nodes = set()
self.ways = ways
def way(self, way):
if way.id in self.ways:
for node in way.nodes:
self.nodes.add(node.ref)
class BoundaryWriter(osmium.SimpleHandler):
def __init__(self, writer, ways, nodes):
super().__init__()
self.writer = writer
self.nodes = nodes
self.ways = ways
def node(self, node):
if node.id in self.nodes:
self.writer.add_node(node)
def way(self, way):
if way.id in self.ways:
self.writer.add_way(way)
if __name__ == '__main__':
if len(sys.argv) != 3:
print("Usage: python extract.py <infile> <outfile>")
sys.exit(-1)
# go through the relations to find all relevant ways
ways = WayFilter()
ways.apply_file(sys.argv[1])
# go through the ways to find all relevant nodes
nodes = NodeFilter(ways.ways)
nodes.apply_file(sys.argv[1])
# go through the file again and write out the data
writer = osmium.SimpleWriter(sys.argv[2])
BoundaryWriter(writer, ways.ways, nodes.nodes).apply_file(sys.argv[1])
writer.close()
# Get the planet (38G)
wget https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/pbf/planet-latest.osm.pbf
# Install Osmium
git clone https://github.com/osmcode/libosmium.git
git clone https://github.com/osmcode/osmium-tool.git
cd osmium-tool/
mkdir build
cd build
cmake ..
make
# Filter boundaries
./osmium tags-filter ../../planet-latest.osm.pbf r/admin_level=2 -o ../../boundary.osm.pbf
# Extract ways
python extract.py boundary.osm.pbf boundary_lines.osm.pbf
# Transform to SHP with ogr2ogr
ogr2ogr --config OSM_CONFIG_FILE boundary.ini -skipfailures boundary.shp boundary_lines.osm.pbf -sql "SELECT * FROM multipolygons WHERE admin_level='2'" -lco ENCODING=UTF-8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment