mirror of
https://github.com/enzet/map-machine.git
synced 2025-07-22 02:48:02 +02:00
Add OSM data downloading using API.
This commit is contained in:
parent
f1a5c2244c
commit
945af54dc9
5 changed files with 73 additions and 89 deletions
42
readme.md
42
readme.md
|
@ -22,25 +22,53 @@ There are simple Python renderer that generates SVG map from OpenStreetMap data.
|
||||||
You can run it using:
|
You can run it using:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 roentgen.py -i ${INPUT_FILE_NAME} -o ${OUTPUT_FILE_NAME}
|
python3 run.py \
|
||||||
|
-bbox ${LONGITUDE_1},${LATITUDE_1},${LONGITUDE_2},${LATITUDE_2} \
|
||||||
|
-o ${OUTPUT_FILE_NAME} \
|
||||||
|
-s ${WIDTH},${HEIGHT}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options ###
|
Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 run.py -bbox 2.284,48.86,2.29,48.865 -o map.svg -s 1000,1000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Main arguments ###
|
||||||
|
|
||||||
|
#### Required ####
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr><td>Option</td><td>Value</td><td>Description</td></tr>
|
<tr><td>Option</td><td>Value</td><td>Description</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><tt>-bbox</tt>, <tt>--boundary-box</tt></td>
|
<td><tt>-bbox</tt>, <tt>--boundary-box</tt></td>
|
||||||
<td>
|
<td>
|
||||||
<tt><longitude 1>,<latitude 1>,<longitude 2>,<latitude 2></tt>
|
<tt><longitude 1>,<latitude 1>,<longitude
|
||||||
(decimal float)
|
2>,<latitude 2></tt>
|
||||||
</td>
|
</td>
|
||||||
<td>Boundary box to draw</td>
|
<td>Boundary box to draw.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><tt>-s</tt>, <tt>--size</tt></td>
|
<td><tt>-s</tt>, <tt>--size</tt></td>
|
||||||
<td><tt><width>,<height></tt> (pixels)</td>
|
<td><tt><width>,<height></tt></td>
|
||||||
<td>Result image size</td>
|
<td>Result image size in pixels.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><tt>-o</tt></td>
|
||||||
|
<td><tt><path></tt></td>
|
||||||
|
<td>Path to output SVG file name.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### Optional ####
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><td>Option</td><td>Value</td><td>Description</td></tr>
|
||||||
|
<tr>
|
||||||
|
<td><tt>-i</tt></td>
|
||||||
|
<td><tt><path></tt></td>
|
||||||
|
<td>Path to input XML file name. If this argument is not set, XML file
|
||||||
|
will be downloaded throung Openstreetmap API.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from roentgen import ui
|
||||||
from roentgen import svg
|
from roentgen import svg
|
||||||
from roentgen.flinger import GeoFlinger, Geo
|
from roentgen.flinger import GeoFlinger, Geo
|
||||||
from roentgen.osm_reader import OSMReader, OSMWay
|
from roentgen.osm_reader import OSMReader, OSMWay
|
||||||
|
from roentgen.osm_getter import get_osm
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List, Optional, Set
|
from typing import List, Optional, Set
|
||||||
|
@ -1064,17 +1065,25 @@ def main():
|
||||||
if not options:
|
if not options:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
background_color = "EEEEEE" # "DDDDDD"
|
background_color = "EEEEEE"
|
||||||
if options.mode in ["user-coloring", "time"]:
|
if options.mode in ["user-coloring", "time"]:
|
||||||
background_color = "111111"
|
background_color = "111111"
|
||||||
outline_color = "111111"
|
|
||||||
|
|
||||||
|
if options.input_file_name:
|
||||||
input_file_name = options.input_file_name
|
input_file_name = options.input_file_name
|
||||||
|
else:
|
||||||
|
content = get_osm(options.boundary_box)
|
||||||
|
if not content:
|
||||||
|
ui.error("cannot download OSM data")
|
||||||
|
input_file_name = os.path.join("map", options.boundary_box + ".osm")
|
||||||
|
|
||||||
if not os.path.isfile(input_file_name):
|
if not os.path.isfile(input_file_name):
|
||||||
print("Fatal: no such file: " + input_file_name + ".")
|
print("Fatal: no such file: " + input_file_name + ".")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
boundary_box = list(map(
|
||||||
|
lambda x: float(x.replace('m', '-')), options.boundary_box.split(',')))
|
||||||
|
|
||||||
full = False # Full keys getting
|
full = False # Full keys getting
|
||||||
|
|
||||||
if options.mode in ["user-coloring", "time"]:
|
if options.mode in ["user-coloring", "time"]:
|
||||||
|
@ -1095,10 +1104,8 @@ def main():
|
||||||
"<title>Rӧntgen</title><style>path:hover {stroke: #FF0000;}</style>\n")
|
"<title>Rӧntgen</title><style>path:hover {stroke: #FF0000;}</style>\n")
|
||||||
output_file.rect(0, 0, w, h, color=background_color)
|
output_file.rect(0, 0, w, h, color=background_color)
|
||||||
|
|
||||||
if "boundary_box" in options:
|
min1 = Geo(boundary_box[1], boundary_box[0])
|
||||||
bb = options.boundary_box
|
max1 = Geo(boundary_box[3], boundary_box[2])
|
||||||
min1 = Geo(bb[1], bb[0])
|
|
||||||
max1 = Geo(bb[3], bb[2])
|
|
||||||
|
|
||||||
authors = {}
|
authors = {}
|
||||||
missed_tags = {}
|
missed_tags = {}
|
||||||
|
|
|
@ -25,7 +25,7 @@ def get_data(address: str, parameters: Dict[str, str], is_secure: bool=False, na
|
||||||
"""
|
"""
|
||||||
url = "http" + ("s" if is_secure else "") + "://" + address
|
url = "http" + ("s" if is_secure else "") + "://" + address
|
||||||
if len(parameters) > 0:
|
if len(parameters) > 0:
|
||||||
url += "?" + "&".join(parameters) # urllib.parse.urlencode(parameters)
|
url += "?" + urllib.parse.urlencode(parameters)
|
||||||
if not name:
|
if not name:
|
||||||
name = url
|
name = url
|
||||||
print("getting " + name)
|
print("getting " + name)
|
||||||
|
@ -36,51 +36,3 @@ def get_data(address: str, parameters: Dict[str, str], is_secure: bool=False, na
|
||||||
pool_manager.clear()
|
pool_manager.clear()
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
return result.data
|
return result.data
|
||||||
|
|
||||||
|
|
||||||
def get_content(address, parameters, cache_file_name, kind, is_secure, name=None, exceptions=None, update_cache=False):
|
|
||||||
"""
|
|
||||||
Read content from URL or from cached file.
|
|
||||||
|
|
||||||
:param address: first part of URL without "http://"
|
|
||||||
:param parameters: URL parameters
|
|
||||||
:param cache_file_name: name of cache file
|
|
||||||
:param kind: type of content: "html" or "json"
|
|
||||||
:return: content if exist
|
|
||||||
"""
|
|
||||||
if exceptions and address in exceptions:
|
|
||||||
return None
|
|
||||||
if os.path.isfile(cache_file_name) and \
|
|
||||||
datetime(1, 1, 1).fromtimestamp(os.stat(cache_file_name).st_mtime) > \
|
|
||||||
datetime.now() - timedelta(days=90) and \
|
|
||||||
not update_cache:
|
|
||||||
with open(cache_file_name) as cache_file:
|
|
||||||
if kind == "json":
|
|
||||||
try:
|
|
||||||
return json.load(cache_file)
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
if kind == "html":
|
|
||||||
return cache_file.read()
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
data = get_data(address, parameters, is_secure=is_secure, name=name)
|
|
||||||
if kind == "json":
|
|
||||||
try:
|
|
||||||
obj = json.loads(data)
|
|
||||||
with open(cache_file_name, "w+") as cached:
|
|
||||||
cached.write(json.dumps(obj, indent=4))
|
|
||||||
return obj
|
|
||||||
except ValueError:
|
|
||||||
print("cannot get " + address + " " + str(parameters))
|
|
||||||
return None
|
|
||||||
if kind == "html":
|
|
||||||
with open(cache_file_name, "w+") as cached:
|
|
||||||
cached.write(data)
|
|
||||||
return data
|
|
||||||
except Exception as e:
|
|
||||||
print("during getting JSON from " + address + " with parameters " + str(parameters))
|
|
||||||
print(e)
|
|
||||||
if exceptions:
|
|
||||||
exceptions.append(address)
|
|
||||||
return None
|
|
||||||
|
|
|
@ -1,48 +1,47 @@
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from roentgen.ui import error
|
from roentgen.ui import error
|
||||||
from roentgen import network
|
from roentgen import network
|
||||||
|
|
||||||
|
|
||||||
USAGE: str = '<box coordinates: left,bottom,right,top>'
|
def get_osm(boundary_box: str, to_update: bool = False) -> Optional[str]:
|
||||||
|
result_file_name = os.path.join("map", boundary_box + ".osm")
|
||||||
|
|
||||||
|
if not to_update and os.path.isfile(result_file_name):
|
||||||
|
return open(result_file_name).read()
|
||||||
|
|
||||||
def main(boundary_box: str):
|
matcher = re.match("(?P<left>[0-9.-]*),(?P<bottom>[0-9.-]*)," +
|
||||||
result_file_name = 'map/' + boundary_box + '.xml'
|
"(?P<right>[0-9.-]*),(?P<top>[0-9.-]*)", boundary_box)
|
||||||
|
|
||||||
matcher = re.match('(?P<left>[0-9\\.-]*),(?P<bottom>[0-9\\.-]*),' + \
|
|
||||||
'(?P<right>[0-9\\.-]*),(?P<top>[0-9\\.-]*)', boundary_box)
|
|
||||||
|
|
||||||
if not matcher:
|
if not matcher:
|
||||||
error('invalid boundary box')
|
error("invalid boundary box")
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
left = float(matcher.group('left'))
|
left = float(matcher.group("left"))
|
||||||
bottom = float(matcher.group('bottom'))
|
bottom = float(matcher.group("bottom"))
|
||||||
right = float(matcher.group('right'))
|
right = float(matcher.group("right"))
|
||||||
top = float(matcher.group('top'))
|
top = float(matcher.group("top"))
|
||||||
except Exception:
|
except ValueError:
|
||||||
error('parsing boundary box')
|
error("parsing boundary box")
|
||||||
return
|
return
|
||||||
|
|
||||||
if left >= right:
|
if left >= right:
|
||||||
error('negative horizontal boundary')
|
error("negative horizontal boundary")
|
||||||
return
|
return
|
||||||
if bottom >= top:
|
if bottom >= top:
|
||||||
error('negative vertical boundary')
|
error("negative vertical boundary")
|
||||||
return
|
return
|
||||||
if right - left > 0.5 or top - bottom > 0.5:
|
if right - left > 0.5 or top - bottom > 0.5:
|
||||||
error('box too big')
|
error("box too big")
|
||||||
return
|
return
|
||||||
network.get_content('api.openstreetmap.org/api/0.6/map',
|
|
||||||
{'bbox': boundary_box}, result_file_name, 'html', is_secure=True)
|
|
||||||
|
|
||||||
|
content = network.get_data("api.openstreetmap.org/api/0.6/map",
|
||||||
|
{"bbox": boundary_box}, is_secure=True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
open(result_file_name, "w+").write(content.decode("utf-8"))
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print('Usage: python ' + sys.argv[0] + ' ' + USAGE)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
main(sys.argv[1])
|
return content.decode("utf-8")
|
||||||
|
|
2
run.py
2
run.py
|
@ -1,6 +1,4 @@
|
||||||
from roentgen.osm_getter import main
|
|
||||||
from roentgen.mapper import main
|
from roentgen.mapper import main
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# main("2.374,48.843,2.378,48.846")
|
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue