3D ski maps. WIP.

osm.py 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. """
  2. This module contains functions to fetch OSM metadata.
  3. It filters the OpenStreetMap XML data file and exports only the
  4. geographically relevant informations in a JSON file.
  5. """
  6. import xml.etree.ElementTree as ET
  7. from . import geodata
  8. def fetch_metadta(lat_min, lng_min, lat_max, lng_max, data_file=""):
  9. """
  10. This function extracts the relevant information from the OSM
  11. metadata (slopes, aerialways, and their associated metadata).
  12. It returns a list of such items.
  13. data_file is the path to a downloaded OSM XML file. If data_file is not
  14. specified, the script will query the OSM API.
  15. """
  16. # ways is the returned list of matching items
  17. ways = []
  18. if data_file is "":
  19. # TODO: Get the metadata from the OSM API
  20. pass
  21. # Parse the input XML file
  22. xml = ET.parse(data_file)
  23. root = xml.getroot()
  24. # Find geographically relevant nodes, by iterating over all of them
  25. # nodes are points at the end of ways, so we will look for ways using these
  26. # nodes and only these nodes.
  27. nodes = {}
  28. for node in root.iter("node"):
  29. lat = float(node.attrib["lat"])
  30. lng = float(node.attrib["lon"])
  31. if(lat_min <= lat and lat <= lat_max and
  32. lng_min <= lng and lng <= lng_max):
  33. # If the node is within the target area, store it and convert its
  34. # coordinates to Lambert93
  35. x, y = geodata.latlng_to_lambert93(lat, lng)
  36. id = node.attrib["id"]
  37. nodes[id] = {"id": id,
  38. "lat": lat,
  39. "lng": lng,
  40. "x": x,
  41. "y": y}
  42. # Now, iterate over all the ways
  43. for way in root.iter("way"):
  44. # Way element to append to the way list if within given area
  45. way_to_append = {
  46. "name": "",
  47. "type": "",
  48. "nodes": [],
  49. # Slopes-specific attributes
  50. "difficulty": "",
  51. # Aerial ways specific attributes
  52. "bubble": "",
  53. "capacity": "",
  54. "duration": "",
  55. "heating": "",
  56. "occupancy": ""
  57. }
  58. # Flag indicating that the way is not within given area
  59. ignore_way = False
  60. for nd in way.iter("nd"):
  61. # Fetch all the nodes associated to the current way
  62. if nd.attrib["ref"] in nodes:
  63. way_to_append.nodes.append(nodes[nd.attrib["ref"]])
  64. else:
  65. # If one of them is not within given area, ignore the way
  66. ignore_way = True
  67. if 0 == len(way_to_append.nodes) or ignore_way:
  68. continue
  69. # Parse the tag elements for the current way, which contain the
  70. # metadata
  71. for tag in way.iter("tag"):
  72. # For each relevant tags, if available, store it in the
  73. # corresponding attribute
  74. if tag.attrib["k"] == "name":
  75. way_to_append.name = tag.attrib["v"]
  76. elif tag.attrib["k"] == "piste:difficulty":
  77. way_to_append.difficulty = tag.attrib["v"]
  78. elif tag.attrib["k"] == "piste:type":
  79. way_to_append.type = tag.attrib["v"]
  80. elif tag.attrib["k"] == "aerialway":
  81. way_to_append.type = tag.attrib["v"]
  82. elif tag.attrib["k"] == "aerialway:bubble":
  83. way_to_append.bubble = tag.attrib["v"]
  84. elif tag.attrib["k"] == "aerialway:capacity":
  85. way_to_append.capacity = tag.attrib["v"]
  86. elif tag.attrib["k"] == "aerialway:duration":
  87. way_to_append.duration = tag.attrib["v"]
  88. elif tag.attrib["k"] == "aerialway:heating":
  89. way_to_append.heating = tag.attrib["v"]
  90. elif tag.attrib["k"] == "aerialway:occupancy":
  91. way_to_append.occupancy = tag.attrib["v"]
  92. # Finally, if we got there, the way is ok and the way dict can be
  93. # appended to the ways list
  94. ways.append(way_to_append)
  95. # Return a list of relevant ways with associated metadata
  96. return ways