Commit 046231b1 by Rick Gruber-Riemer

Re-structure of land-use related code

parent 1e7d0bd2
 ... ... @@ -5,6 +5,7 @@ shamelessly translated from calc-tile.pl """ import os from math import floor import numpy as np def bucket_span(lat): ... ... @@ -27,7 +28,7 @@ def bucket_span(lat): return .125 def format_lon (lon): def format_lon(lon): """Format longitude as e/w.""" if lon < 0.: return "w%03d" % int(0. - lon) ... ... @@ -35,7 +36,7 @@ def format_lon (lon): return "e%03d" % int(lon) def format_lat (lat): def format_lat(lat): """Format latitude as n/s.""" if lat < 0.: return "s%02d" % int(0. - lat) ... ... @@ -43,13 +44,14 @@ def format_lat (lat): return "n%02d" % int(lat) def root_directory_name ((lon, lat)): def root_directory_name((lon, lat)): """Generate the directory name for a location.""" lon_chunk = floor(lon/10.0) * 10 lat_chunk = floor(lat/10.0) * 10 return format_lon(lon_chunk) + format_lat(lat_chunk) + os.sep def directory_name ((lon, lat)): def directory_name((lon, lat)): """Generate the directory name for a location.""" lon_floor = floor(lon) lat_floor = floor(lat) ... ... @@ -62,8 +64,7 @@ def directory_name ((lon, lat)): def tile_index((lon, lat), x=0, y=0): if x == 0 and y == 0: y = calc_y(lat) x = calc_x(lon,lat) x = calc_x(lon, lat) index = (int(floor(lon)) + 180) << 14 index += (int(floor(lat)) + 90) << 6 ... ... @@ -81,30 +82,39 @@ def construct_stg_file_name(center_global): """Returns the file name of the stg-file at a given global lat/lon location""" return "%07i.stg" % tile_index(center_global) def construct_btg_file_name(center_global): """Returns the file name of the stg-file at a given global lat/lon location""" return "%07i.btg.gz" % tile_index(center_global) def get_north_lat(lat,y): return float(floor(lat)) + y / 8.0 + .125; def get_south_lat(lat,y): return float(floor(lat)) + y / 8.0; def get_north_lat(lat, y): return float(floor(lat)) + y / 8.0 + .125 def get_south_lat(lat, y): return float(floor(lat)) + y / 8.0 def get_west_lon(lon,lat, x): if( x == 0): def get_west_lon(lon, lat, x): if x == 0: return float(floor(lon)) else: return float(floor(lon)) + x * (bucket_span(lat)) def get_east_lon(lon,lat, x): if( x == 0): def get_east_lon(lon, lat, x): if x == 0: return float(floor(lon)) + (bucket_span(lat)) else: return float(floor(lon)) + x * (bucket_span(lat)) + (bucket_span(lat)) def calc_x(lon,lat): def calc_x(lon, lat): """ FIXME: is this correct? Also: some returns do not take calculations into account. According to http://wiki.flightgear.org/Tile_Index_Scheme it would be calculated differently """ EPSILON = 0.0000001 span = bucket_span(lat) if span < EPSILON: ... ... @@ -121,12 +131,22 @@ def calc_x(lon,lat): lon = -180 return 0 def calc_y(lat): return int((lat - floor(lat)) * 8) def get_stg_files_in_boundary(boundary_west, boundary_south, boundary_east, boundary_north, path_to_scenery): """Based on boundary rectangle returns a list of stg-files (incl. full path) to be found within the boundary of the scenery""" stg_files = [] for my_lat in np.arange(boundary_south, boundary_north, 0.125): # latitude for my_lon in np.arange(boundary_west, boundary_east, bucket_span(my_lat)): # longitude coords = (my_lon, my_lat) stg_files.append(construct_path_to_stg(path_to_scenery, coords) + construct_stg_file_name(coords)) return stg_files if __name__ == "__main__": for lon, lat, idx in ((13.687944, 51.074664, 3171138), (13.9041667, 51.1072222, 3171139), ... ...
landuse.py 0 → 100644
This diff is collapsed.
 ... ... @@ -27,6 +27,7 @@ import unittest import xml.sax import coordinates import landuse import osmparser import osmparser_wrapper import parameters ... ... @@ -372,20 +373,6 @@ class LineWithoutCables(object): return my_shared_pylon.lon, my_shared_pylon.lat class Landuse(LineWithoutCables): TYPE_COMMERCIAL = 10 TYPE_INDUSTRIAL = 20 TYPE_RESIDENTIAL = 30 TYPE_RETAIL = 40 TYPE_NON_OSM = 50 # used for landuses constructed by osm2pylons and not in original data from OSM def __init__(self, osm_id): super(Landuse, self).__init__(osm_id) self.type_ = 0 self.polygon = None self.number_of_buildings = 0 class Highway(LineWithoutCables): TYPE_MOTORWAY = 11 TYPE_TRUNK = 12 ... ... @@ -858,23 +845,6 @@ class RailLine(Line): return is_right def process_osm_building_refs(nodes_dict, ways_dict, my_coord_transformator): my_buildings = {} # osm_id as key, Polygon for way in ways_dict.values(): for key in way.tags: if "building" == key: coordinates = [] for ref in way.refs: if ref in nodes_dict: my_node = nodes_dict[ref] coordinates.append(my_coord_transformator.toLocal((my_node.lon, my_node.lat))) if 2 < len(coordinates): my_polygon = Polygon(coordinates) if my_polygon.is_valid and not my_polygon.is_empty: my_buildings[way.osm_id] = my_polygon.convex_hull return my_buildings def process_osm_rail_overhead(nodes_dict, ways_dict, my_elev_interpolator, my_coord_transformator): my_railways = {} # osm_id as key, RailLine my_shared_nodes = {} # node osm_id as key, list of WayLine objects as value ... ... @@ -1076,84 +1046,6 @@ def merge_streetlamp_buffers(landuse_refs): return landuse_buffers def process_osm_landuse_refs(nodes_dict, ways_dict, my_coord_transformator, building_refs): my_landuses = {} # osm_id as key, Landuse for way in ways_dict.values(): my_landuse = Landuse(way.osm_id) valid_landuse = True for key in way.tags: value = way.tags[key] if "landuse" == key: if value == "commercial": my_landuse.type_ = Landuse.TYPE_COMMERCIAL elif value == "industrial": my_landuse.type_ = Landuse.TYPE_INDUSTRIAL elif value == "residential": my_landuse.type_ = Landuse.TYPE_RESIDENTIAL elif value == "retail": my_landuse.type_ = Landuse.TYPE_RETAIL else: valid_landuse = False else: valid_landuse = False if valid_landuse: # Process the Nodes my_coordinates = [] for ref in way.refs: if ref in nodes_dict: my_node = nodes_dict[ref] x, y = my_coord_transformator.toLocal((my_node.lon, my_node.lat)) my_coordinates.append((x, y)) if len(my_coordinates) >= 3: my_landuse.polygon = Polygon(my_coordinates) if my_landuse.polygon.is_valid and not my_landuse.polygon.is_empty: my_landuses[my_landuse.osm_id] = my_landuse logging.debug("OSM land-uses found: %s", len(my_landuses)) if parameters.C2P_LANDUSE_GENERATE_LANDUSE: # Add "missing" landuses based on building clusters my_landuse_candidates = [] index = 10000000000 for my_building in building_refs.values(): # check whether the building already is in a land use within_existing_landuse = False for my_landuse in my_landuses.values(): if my_building.intersects(my_landuse.polygon): within_existing_landuse = True break if not within_existing_landuse: # create new clusters of land uses buffer_distance = parameters.C2P_LANDUSE_BUILDING_BUFFER_DISTANCE if my_building.area > parameters.C2P_LANDUSE_BUILDING_BUFFER_DISTANCE**2: factor = math.sqrt(my_building.area / parameters.C2P_LANDUSE_BUILDING_BUFFER_DISTANCE**2) buffer_distance = min(factor*parameters.C2P_LANDUSE_BUILDING_BUFFER_DISTANCE , parameters.C2P_LANDUSE_BUILDING_BUFFER_DISTANCE_MAX) buffer_polygon = my_building.buffer(buffer_distance) buffer_polygon = buffer_polygon within_existing_landuse = False for candidate in my_landuse_candidates: if buffer_polygon.intersects(candidate.polygon): candidate.polygon = candidate.polygon.union(buffer_polygon) candidate.number_of_buildings += 1 within_existing_landuse = True break if not within_existing_landuse: index += 1 my_candidate = Landuse(index) my_candidate.polygon = buffer_polygon my_candidate.number_of_buildings = 1 my_candidate.type_ = Landuse.TYPE_NON_OSM my_landuse_candidates.append(my_candidate) # add landuse candidates to landuses logging.debug("Candidate land-uses found: %s", len(my_landuse_candidates)) for candidate in my_landuse_candidates: if candidate.polygon.area >= parameters.C2P_LANDUSE_MIN_AREA: my_landuses[candidate.osm_id] = candidate return my_landuses def process_osm_power_aerialway(nodes_dict, ways_dict, my_elev_interpolator, my_coord_transformator, building_refs): """ Transforms a dict of Node and a dict of Way OSMElements from osmparser.py to a dict of WayLine objects for ... ... @@ -1461,14 +1353,12 @@ def main(): logging.info("Transforming OSM data to Line and Pylon objects") # the lists below are in sequence: buildings references, power/aerialway, railway overhead, landuse and highway valid_node_keys = ["power", "structure", "material", "height", "colour", "aerialway" , "railway" ] , "railway"] valid_way_keys = ["building" , "power", "aerialway", "voltage", "cables", "wires" , "railway", "electrified", "tunnel" , "landuse" , "highway", "junction" ] , "highway", "junction"] valid_relation_keys = [] req_relation_keys = [] req_way_keys = ["building", "power", "aerialway", "railway", "landuse", "highway"] ... ... @@ -1479,7 +1369,7 @@ def main(): # References for buildings building_refs = {} if parameters.C2P_PROCESS_POWERLINES or parameters.C2P_PROCESS_AERIALWAYS or parameters.C2P_PROCESS_STREETLAMPS: building_refs = process_osm_building_refs(handler.nodes_dict, handler.ways_dict, coord_transformator) building_refs = landuse.process_osm_building_refs(handler.nodes_dict, handler.ways_dict, coord_transformator) logging.info('Number of reference buildings: %s', len(building_refs)) # Power lines and aerialways powerlines = {} ... ... @@ -1508,7 +1398,11 @@ def main(): # street lamps highways = {} if parameters.C2P_PROCESS_STREETLAMPS: landuse_refs = process_osm_landuse_refs(handler.nodes_dict, handler.ways_dict, coord_transformator, building_refs) landuse_refs = landuse.process_osm_landuse_refs(handler.nodes_dict, handler.ways_dict, coord_transformator) if parameters.LU_LANDUSE_GENERATE_LANDUSE: generated_landuses = landuse.generate_landuse_from_buildings(landuse_refs, building_refs) for generated in generated_landuses.values(): landuse_refs[generated.osm_id] = generated logging.info('Number of landuse references: %s', len(landuse_refs)) streetlamp_buffers = merge_streetlamp_buffers(landuse_refs) logging.info('Number of streetlamp buffers: %s', len(streetlamp_buffers)) ... ...
 ... ... @@ -167,15 +167,18 @@ C2P_CATENARY_MIN_DISTANCE = 30 C2P_POWER_LINE_ALLOW_100M = False C2P_LANDUSE_GENERATE_LANDUSE = True C2P_LANDUSE_BUILDING_BUFFER_DISTANCE = 25 C2P_LANDUSE_BUILDING_BUFFER_DISTANCE_MAX = 50 C2P_LANDUSE_MIN_AREA = 5000 C2P_STREETLAMPS_MAX_DISTANCE_LANDUSE = 100 C2P_STREETLAMPS_RESIDENTIAL_DISTANCE = 40 C2P_STREETLAMPS_OTHER_DISTANCE = 70 #============================================================================= # PARAMETERS RELATED TO landuse.py #============================================================================= LU_LANDUSE_GENERATE_LANDUSE = True LU_LANDUSE_BUILDING_BUFFER_DISTANCE = 25 LU_LANDUSE_BUILDING_BUFFER_DISTANCE_MAX = 50 LU_LANDUSE_MIN_AREA = 5000 #============================================================================= # PARAMETERS RELATED TO ROADS IN roads.py #============================================================================= ... ...
 ... ... @@ -147,45 +147,83 @@ class STG_Manager(object): the_stg.write() def read(path, stg_fname, our_magic): """Accepts a scenery sub-path, as in 'w010n40/w005n48/', and an .stg file name. In the future, take care of multiple scenery paths here. Returns list of buildings representing static/shared objects in .stg, with full path. """ objs = [] our_magic_start = delimiter_string(our_magic, True) our_magic_end = delimiter_string(our_magic, False) ours = False class STGEntry(object): SHARED_OBJECT = "OBJECT_SHARED" STATIC_OBJECT = "OBJECT_STATIC" def __init__(self, type_string, obj_filename, stg_path, lon, lat, elev, hdg): self.is_static = True if type_string == STGEntry.SHARED_OBJECT: self.is_static = False self.obj_filename = obj_filename self.stg_path = stg_path # the path of the stg_file without file name and trailing path-separator self.lon = lon self.lat = lat self.elev = elev self.hdg = hdg def get_object_type_as_string(self): if self.is_static: return STGEntry.STATIC_OBJECT return STGEntry.SHARED_OBJECT def get_obj_path_and_name(self): return self.stg_path + os.sep + self.obj_filename def read_stg_entries(stg_path_and_name, our_magic): """Reads an stg-file and extracts STGEntry objects outside of marked areas for our_magic. TODO: In the future, take care of multiple scenery paths here. TODO: should be able to take a list of our_magic""" entries = [] # list of STGEntry objects if None is not our_magic: our_magic_start = delimiter_string(our_magic, True) our_magic_end = delimiter_string(our_magic, False) ours = False try: f = open(path + stg_fname) for line in f.readlines(): if line.startswith(our_magic_start): ours = True continue if line.startswith(our_magic_end): ours = False continue if ours: continue if line.startswith('#') or line.lstrip() == "": continue splitted = line.split() typ, ac_path = splitted[0:2] lon = float(splitted[2]) lat = float(splitted[3]) # alt = float(splitted[4]) point = shg.Point(tools.transform.toLocal((lon, lat))) hdg = float(splitted[5]) logging.debug("stg: %s %s", typ, path + ac_path) objs.append(osm2city.Building(osm_id=-1, tags=-1, outer_ring=point, name=path + ac_path, height=0, levels=0, stg_typ=typ, stg_hdg=hdg)) f.close() with open(stg_path_and_name, 'r') as my_file: path, stg_name = os.path.split(stg_path_and_name) for line in my_file: if None is not our_magic: if line.startswith(our_magic_start): ours = True continue if line.startswith(our_magic_end): ours = False continue if ours: continue if line.startswith('#') or line.lstrip() == "": continue splitted = line.split() type_ = splitted[0] obj_filename = splitted[1] lon = float(splitted[2]) lat = float(splitted[3]) elev = float(splitted[4]) hdg = float(splitted[5]) entries.append(STGEntry(type_, obj_filename, path, lon, lat, elev, hdg)) logging.debug("stg: %s %s", type_, path + os.sep + obj_filename) except IOError, reason: logging.warning("stg_io:read: Ignoring unreadable file %s", reason) return [] return entries return objs def read(path, stg_fname, our_magic): """Same as read_stg_entries, but returns osm2city.Building objects""" stg_entries = read_stg_entries(path + stg_fname, our_magic) building_objs = [] for entry in stg_entries: point = shg.Point(tools.transform.toLocal((entry.lon, entry.lat))) building_objs.append(osm2city.Building(osm_id=-1, tags=-1, outer_ring=point , name=entry.get_obj_path_and_name() , height=0, levels=0, stg_typ=entry.get_object_type_as_string() , stg_hdg=entry.hdg)) return building_objs def delimiter_string(our_magic, is_start): ... ...
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!