11.08., 9:00 - 11:00: Due to updates GitLab will be unavailable for some minutes between 09:00 and 11:00.

Commit 90af637b authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

Merge branch 'master' of https://gitlab.lrz.de/vadere/vadere

parents dfb29cb9 3baf88e6
<osm>
<node id="1" visible="true" version="11" changeset="10291545" timestamp="2012-01-04T14:39:37Z" user="mawi42" uid="42393" lat="1.1" lon="1.2"/>
<node id="2" visible="true" version="9" changeset="2270948" timestamp="2009-08-26T20:02:36Z" user="pfui_osm_korinthenkacker" uid="36809" lat="2.1" lon="2.2"/>
<node id="3" visible="true" version="10" changeset="6745590" timestamp="2010-12-23T14:00:32Z" user="mawi42" uid="42393" lat="3.1" lon="3.2"/>
</osm>
\ No newline at end of file
# Convert OpenStreetMap XML file exported from https://www.openstreetmap.org/
# Convert an OpenStreetMap XML file exported from https://www.openstreetmap.org/
# to a Vadere topology (in Cartesian coordinates).
#
# Steps to run this script:
......@@ -110,36 +110,24 @@ def extract_base_point(xml_tree):
return base_point
def extract_end_point(xml_tree):
end_node = xml_tree.xpath("/osm/bounds")[0]
end_point = (end_node.get("maxlat"), end_node.get("maxlon"))
return end_point
def assert_that_start_and_end_point_are_equal(node_references):
assert node_references[0].get("ref") == node_references[-1].get("ref")
def convert_nodes_to_cartesian_points(nodes, lookup_table_latitude_and_longitude, base_point):
def convert_nodes_to_cartesian_points(nodes, lookup_table_latitude_and_longitude):
cartesian_points = []
# Use base point to normalize coordinates to (0,0).
(baseX, baseY, base_zone_number, base_zone_letter) = utm.from_latlon(float(base_point[0]), float(base_point[1]))
# Omit last node because it should be the same as the first one.
for node in nodes[:len(nodes) - 1]:
reference = node.get("ref")
latitude, longitude = lookup_table_latitude_and_longitude[reference]
(x, y, zone_number, zone_letter) = utm.from_latlon(float(latitude), float(longitude))
# TODO: handle coordinates from different segments properly.
assert base_zone_number == zone_number, "Overstepped UTM boundary(zone number)"
assert base_zone_letter == zone_letter, "Overstepped UTM boundary(zone letter)"
point_to_add = (x-baseX, y - baseY)
x, y, zone_number, zone_letter = utm.from_latlon(float(latitude), float(longitude))
point = (x, y)
cartesian_points.append(point_to_add)
# TODO: assert that ALL nodes fall into same zone_number and zone_letter!
cartesian_points.append(point)
return cartesian_points
......@@ -148,9 +136,7 @@ def create_vadere_obstacles_from_points(cartesian_points):
vadere_obstacle_string = """{
"shape" : {
"type" : "POLYGON",
"points" : [
$points
]
"points" : [ $points ]
},
"id" : -1
}"""
......@@ -167,18 +153,15 @@ def create_vadere_obstacles_from_points(cartesian_points):
return vadere_obstacle_as_string
def build_vadere_topography_input_with_obstacles(obstacles, base_point, end_point):
def build_vadere_topography_input_with_obstacles(obstacles, width, height):
with open("vadere_topography_default.txt", "r") as myfile:
vadere_topography_input = myfile.read().replace('\n', '')
base_point_cartesian = utm.from_latlon(float(base_point[0]), float(base_point[1]))
end_point_cartesian = utm.from_latlon(float(end_point[0]), float(end_point[1]))
width = math.ceil(end_point_cartesian[0] - base_point_cartesian[0])
height = math.ceil(end_point_cartesian[1] - base_point_cartesian[1])
vadere_topography_output = Template(vadere_topography_input).substitute(width=width, height=height, obstacles=obstacles)
return vadere_topography_output
def print_xml_parsing_statistics(filename, nodes_dictionary, simple_buildings, complex_buildings, base_point):
print("File: {}".format(filename))
print(" Nodes: {}".format(len(nodes_dictionary)))
......@@ -186,6 +169,7 @@ def print_xml_parsing_statistics(filename, nodes_dictionary, simple_buildings, c
print(" Complex buildings: {}".format(len(complex_buildings)))
print(" Base point: {}".format(base_point))
def print_output(outputfile, output):
if outputfile == None:
print(output)
......@@ -194,33 +178,81 @@ def print_output(outputfile, output):
print(output, file=text_file)
if __name__ == "__main__":
args = parse_command_line_arguments()
def find_width_and_height(buildings_cartesian):
# search for the highest x- and y-coordinates within the points
width = 0
height = 0
for cartesian_points in buildings_cartesian:
for point in cartesian_points:
width = max(width, point[0])
height = max(height, point[1])
return math.ceil(width), math.ceil(height)
xml_tree = etree.parse(args.filename)
def find_new_basepoint(buildings_cartesian):
# "buildings_cartesian" is a list of lists!!!
# The inner list contains the (x,y) tuples!
# search for the lowest x- and y-coordinates within the points
all_points = [point for building in buildings_cartesian for point in building]
nodes_dictionary_with_lat_and_lon = extract_latitude_and_longitude_for_each_xml_node(xml_tree)
tuple_with_min_x = min(all_points, key=lambda point: point[0])
tuple_with_min_y = min(all_points, key=lambda point: point[1])
simple_buildings = filter_for_buildings(xml_tree)
complex_buildings = filter_for_buildings_in_relations(xml_tree)
return (tuple_with_min_x[0], tuple_with_min_y[1])
base_point = extract_base_point(xml_tree)
end_point = extract_end_point(xml_tree)
print_xml_parsing_statistics(args.filename, nodes_dictionary_with_lat_and_lon, simple_buildings, complex_buildings, base_point)
def shift_points(buildings_utm, shift_in_x_direction, shift_in_y_direction):
new_buildings = []
for cartesian_points in buildings_utm:
shifted_cartesian_points = \
[(point[0] + shift_in_x_direction, point[1] + shift_in_y_direction) for point in cartesian_points]
new_buildings.append(shifted_cartesian_points)
return new_buildings
list_of_vadere_obstacles_as_strings = []
for building in simple_buildings + complex_buildings:
def convert_buildings_to_cartesian(buildings_as_xml_nodes):
buildings_in_cartesian = []
for building in buildings_as_xml_nodes:
# Collect nodes that belong to the current building.
node_references = building.xpath("./nd")
assert_that_start_and_end_point_are_equal(node_references)
cartesian_points = convert_nodes_to_cartesian_points(node_references, nodes_dictionary_with_lat_and_lon, base_point)
cartesian_points = convert_nodes_to_cartesian_points(node_references, nodes_dictionary_with_lat_and_lon)
buildings_in_cartesian.append(cartesian_points)
return buildings_in_cartesian
def convert_buildings_as_cartesian_to_buildings_as_vadere_obstacles(buildings_as_cartesian):
list_of_vadere_obstacles_as_strings = []
for cartesian_points in buildings_as_cartesian:
vadere_obstacles_as_strings = create_vadere_obstacles_from_points(cartesian_points)
list_of_vadere_obstacles_as_strings.append(vadere_obstacles_as_strings)
return list_of_vadere_obstacles_as_strings
if __name__ == "__main__":
args = parse_command_line_arguments()
xml_tree = etree.parse(args.filename)
nodes_dictionary_with_lat_and_lon = extract_latitude_and_longitude_for_each_xml_node(xml_tree)
simple_buildings = filter_for_buildings(xml_tree)
complex_buildings = filter_for_buildings_in_relations(xml_tree)
extracted_base_point = extract_base_point(xml_tree)
print_xml_parsing_statistics(args.filename, nodes_dictionary_with_lat_and_lon, simple_buildings, complex_buildings, extracted_base_point)
buildings_as_cartesian = convert_buildings_to_cartesian(simple_buildings + complex_buildings)
# make sure everything lies within the topography
new_base = find_new_basepoint(buildings_as_cartesian)
buildings_as_cartesian = shift_points(buildings_as_cartesian, -new_base[0], -new_base[1])
width_topography, height_topography = find_width_and_height(buildings_as_cartesian)
list_of_vadere_obstacles_as_strings = convert_buildings_as_cartesian_to_buildings_as_vadere_obstacles(buildings_as_cartesian)
obstacles_joined = ",\n".join(list_of_vadere_obstacles_as_strings)
vadere_topography_output = build_vadere_topography_input_with_obstacles(obstacles_joined, base_point, end_point)
vadere_topography_output = build_vadere_topography_input_with_obstacles(obstacles_joined, width_topography, height_topography)
print_output(args.output, vadere_topography_output)
from lxml import etree
import osm2vadere
import unittest
import utm
class TestOsm2vadere(unittest.TestCase):
def test_utm_conversion(self):
# tests if the distances of the Allianz Arena match up
# from the website https://allianz-arena.com/de/die-arena/fakten/allgemeine-informationen: Dimension Stadion: 258 m x 227 m x 52 m (Bruttorauminhalt)
# the stadion isn't alligned horizontal, therefore the calculated distances are bigger.
base_allianz_arena = (48.21762, 11.62305)
end_allianz_arena = (48.22001, 11.62628)
base_cartesian = utm.from_latlon(base_allianz_arena[0], base_allianz_arena[1])
end_cartesian = utm.from_latlon(end_allianz_arena[0], end_allianz_arena[1])
x_distance = end_cartesian[0] - base_cartesian[0]
y_distance = end_cartesian[1] - base_cartesian[1]
#print(end_cartesian[0] - base_cartesian[0], end_cartesian[1] - base_cartesian[1])
self.assertTrue(x_distance > 227 and x_distance < 235)
self.assertTrue(y_distance > 258 and y_distance < 275)
def test_extract_latitude_and_longitude_for_each_xml_node(self):
xml_tree = etree.parse("maps/map_for_testing.osm")
nodes_dictionary_with_lat_and_lon = osm2vadere.extract_latitude_and_longitude_for_each_xml_node(xml_tree)
self.assertTrue(nodes_dictionary_with_lat_and_lon.get("1")[0] == "1.1")
self.assertTrue (nodes_dictionary_with_lat_and_lon.get("1")[1] == "1.2")
self.assertTrue (nodes_dictionary_with_lat_and_lon.get("2")[0] == "2.1")
self.assertTrue (nodes_dictionary_with_lat_and_lon.get("2")[1] == "2.2")
self.assertTrue (nodes_dictionary_with_lat_and_lon.get("3")[0] == "3.1")
self.assertTrue (nodes_dictionary_with_lat_and_lon.get("3")[1] == "3.2")
def test_find_width_and_height(self):
building_normal = [(1, 1), (3, 1), (1, 3), (3, 3)]
building_negative_coordinates = [(-1, 4), (-3, 2), (10, 2)]
building_with_floating_points = [(2.3, 1.4), (-10.5, 7), (9.99, 3), (5, 7.1), (3, 4)]
buildings_cartesian = [building_normal, building_negative_coordinates, building_with_floating_points]
width, height = osm2vadere.find_width_and_height(buildings_cartesian)
self.assertTrue(width == 10)
self.assertTrue(height == 8) # 7.1 is the maximum but the function returns math.ceil
def test_find_new_basepoint(self):
building_normal = [(1, 1), (3, 1), (1, 3), (3, 3)]
building_negative_coordinates = [(-1, 4), (-3, 2), (10, 2)]
building_with_floating_points = [(2.3, 1.4), (-10.5, 7), (9.99, 3), (5, 7.1), (3, 4)]
buildings_cartesian = [building_normal, building_negative_coordinates, building_with_floating_points]
new_base_point = osm2vadere.find_new_basepoint(buildings_cartesian)
self.assertTrue(new_base_point == [-10.5, 0])
building_negative_coordinates.append((3, -5))
new_base_point = osm2vadere.find_new_basepoint(buildings_cartesian)
self.assertTrue(new_base_point == [-10.5, -5])
buildings_cartesian_only_positive = [[(1, 3), (1, 2), (2, 2)], [(2, 4), (7, 7), (6, 6)]]
new_base_point = osm2vadere.find_new_basepoint(buildings_cartesian_only_positive)
self.assertTrue(new_base_point == [0, 0])
def test_shift_points(self):
buildings_cartesian = [[(1, 3), (-1, 2), (2.2, 2)], [(2, 4), (7, 7), (6, 6)]]
buildings_cartesian_shifted_by_one_and_two = osm2vadere.shift_points(buildings_cartesian, 1, 2)
self.assertTrue(buildings_cartesian_shifted_by_one_and_two == [[(2, 5), (0, 4), (3.2, 4)], [(3, 6), (8, 9), (7, 8)]])
if __name__ == "__main__":
unittest.main()
......@@ -8,6 +8,11 @@ import org.vadere.state.attributes.Attributes;
@ModelAttributeClass
public class AttributesBHM extends Attributes {
/**
* My documentation for xyz.
* @author BK
* @see AttributesBMM
*/
private double stepLengthIntercept = 0.4625;
private double stepLengthSlopeSpeed = 0.2345;
private double stepLengthSD = 0.036;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment