def build_apron_areas(tile, airport_layer, dico_airports):
    for airport in dico_airports:
        wayid_list = dico_airports[airport]['apron']
        aprons = []
        for wayid in wayid_list:
            try:
                pol = geometry.Polygon(
                    numpy.round(
                        numpy.array([
                            airport_layer.dicosmn[nodeid]
                            for nodeid in airport_layer.dicosmw[wayid]
                        ]) - numpy.array([[tile.lon, tile.lat]]), 7))
                if not pol.is_valid:
                    UI.vprint(
                        2, "Unable to turn apron area to polygon, close to",
                        airport_layer.dicosmn[airport_layer.dicosmw[wayid][0]])
                    continue
            except:
                UI.vprint(
                    2, "Unable to turn apron area to polygon, close to",
                    airport_layer.dicosmn[airport_layer.dicosmw[wayid][0]])
                continue
            aprons.append(pol)
        aprons = VECT.ensure_MultiPolygon(ops.cascaded_union(aprons))
        dico_airports[airport]['apron'] = (aprons,
                                           dico_airports[airport]['apron'])
    return
def build_taxiway_areas(tile, airport_layer, dico_airports):
    for airport in dico_airports:
        wayid_list = dico_airports[airport]['taxiway']
        taxiways = geometry.MultiLineString([
            geometry.LineString(
                numpy.round(
                    numpy.array([
                        airport_layer.dicosmn[nodeid]
                        for nodeid in airport_layer.dicosmw[wayid]
                    ]) - numpy.array([[tile.lon, tile.lat]]), 7))
            for wayid in wayid_list
        ])
        taxiways = VECT.ensure_MultiPolygon(
            VECT.improved_buffer(taxiways, 15, 3, 0.5))
        dico_airports[airport]['taxiway'] = (taxiways,
                                             dico_airports[airport]['taxiway'])
    return
def encode_hangars(tile, dico_airports, vector_map, patches_list):
    seeds = []
    for airport in dico_airports:
        if airport in patches_list: continue
        for pol in VECT.ensure_MultiPolygon(
                VECT.cut_to_tile(dico_airports[airport]['hangar'])):
            way = numpy.array(pol.exterior.coords)
            alti_way = numpy.ones(
                (len(way), 1)) * numpy.min(tile.dem.alt_vec(way))
            vector_map.insert_way(numpy.hstack([way, alti_way]),
                                  'HANGAR',
                                  check=True)
            seeds.append(numpy.array(pol.representative_point()))
    if seeds:
        if 'HANGAR' in vector_map.seeds:
            vector_map.seeds['HANGAR'] += seeds
        else:
            vector_map.seeds['HANGAR'] = seeds
    return 1
def build_hangar_areas(tile, airport_layer, dico_airports):
    for airport in dico_airports:
        wayid_list = dico_airports[airport]['hangar']
        hangars = []
        for wayid in wayid_list:
            try:
                pol = geometry.Polygon(
                    numpy.round(
                        numpy.array([
                            airport_layer.dicosmn[nodeid]
                            for nodeid in airport_layer.dicosmw[wayid]
                        ]) - numpy.array([[tile.lon, tile.lat]]), 7))
                if not pol.is_valid: continue
            except:
                UI.vprint(
                    2, "Unable to turn hangar area to polygon, close to",
                    airport_layer.dicosmn[airport_layer.dicosmw[wayid][0]])
                continue
            hangars.append(pol)
        hangars = VECT.ensure_MultiPolygon(
            VECT.improved_buffer(ops.cascaded_union(hangars), 2, 1, 0.5))
        dico_airports[airport]['hangar'] = hangars
def update_airport_boundaries(tile, dico_airports):
    for airport in dico_airports:
        apt = dico_airports[airport]
        boundary = ops.cascaded_union([
            apt['taxiway'][0], apt['apron'][0], apt['hangar'], apt['runway'][0]
        ])
        if apt['boundary']:
            apt['boundary'] = VECT.ensure_MultiPolygon(
                ops.cascaded_union([
                    affinity.translate(apt['boundary'], -tile.lon, -tile.lat),
                    boundary
                ]).buffer(0).simplify(0.00001))
        else:
            apt['boundary'] = VECT.ensure_MultiPolygon(
                boundary.buffer(0).simplify(0.00001))
    # pickle dico_airports for later use in Step 2 (apt_curv_tol) and Step 3 (cover_airports_with_high_res)
    try:
        with open(FNAMES.apt_file(tile), 'wb') as outf:
            pickle.dump(dico_airports, outf)
    except:
        UI.vprint(1, "WARNING: Could not save airport info to file",
                  FNAMES.apt_file(tile))
    return
 def road_is_too_much_banked(way, filtered_segs):
     (col,
      row) = numpy.minimum(numpy.maximum(numpy.round(way[0] * 1000), 0),
                           1000)
     if apt_array[int(1000 - row), int(col)]: return True
     (col,
      row) = numpy.minimum(numpy.maximum(numpy.round(way[-1] * 1000), 0),
                           1000)
     if apt_array[int(1000 - row), int(col)]: return True
     if filtered_segs >= tile.max_levelled_segs: return False
     return (numpy.abs(
         tile.dem.alt_vec(way) -
         tile.dem.alt_vec(VECT.shift_way(way, tile.lane_width))) >=
             tile.road_banking_limit).any()
Exemplo n.º 7
0
def include_sea(vector_map, tile):
    UI.vprint(0, "-> Dealing with coastline")
    sea_layer = OSM.OSM_layer()
    custom_coastline = FNAMES.custom_coastline(tile.lat, tile.lon)
    if os.path.isfile(custom_coastline):
        sea_layer.update_dicosm(custom_coastline, target_tags=None)
    else:
        queries = ['way["natural"="coastline"]']
        tags_of_interest = []
        if not OSM.OSM_queries_to_OSM_layer(queries,
                                            sea_layer,
                                            tile.lat,
                                            tile.lon,
                                            tags_of_interest,
                                            cached_suffix='coastline'):
            return 0
    coastline = OSM.OSM_to_MultiLineString(sea_layer, tile.lat, tile.lon, None)
    if not coastline.is_empty:
        # 1) encoding the coastline
        UI.vprint(1, "    * Encoding coastline.")
        vector_map.encode_MultiLineString(VECT.cut_to_tile(
            coastline, strictly_inside=True),
                                          tile.dem.alt_vec,
                                          'SEA',
                                          check=True,
                                          refine=False)
        UI.vprint(3, "...done.")
        # 2) finding seeds (transform multilinestring coastline to polygon coastline
        # linemerge being expensive we first set aside what is already known to be closed loops
        UI.vprint(1, "    * Reconstructing its topology.")
        loops = geometry.MultiLineString(
            [line for line in coastline.geoms if line.is_ring])
        remainder = VECT.ensure_MultiLineString(
            VECT.cut_to_tile(geometry.MultiLineString(
                [line for line in coastline.geoms if not line.is_ring]),
                             strictly_inside=True))
        UI.vprint(3, "Linemerge...")
        if not remainder.is_empty:
            remainder = VECT.ensure_MultiLineString(ops.linemerge(remainder))
        UI.vprint(3, "...done.")
        coastline = geometry.MultiLineString([line for line in remainder] +
                                             [line for line in loops])
        sea_area = VECT.ensure_MultiPolygon(
            VECT.coastline_to_MultiPolygon(coastline, tile.lat, tile.lon))
        if sea_area.geoms:
            UI.vprint(1, "      Found ", len(sea_area.geoms),
                      "contiguous patch(es).")
        for polygon in sea_area.geoms:
            seed = numpy.array(polygon.representative_point())
            if 'SEA' in vector_map.seeds:
                vector_map.seeds['SEA'].append(seed)
            else:
                vector_map.seeds['SEA'] = [seed]
Exemplo n.º 8
0
def include_water(vector_map, tile):
    UI.vprint(0, "-> Dealing with inland water")
    water_layer = OSM.OSM_layer()
    custom_water = FNAMES.custom_water(tile.lat, tile.lon)
    if os.path.isfile(custom_water):
        water_layer.update_dicosm(custom_water, target_tags=None)
    else:
        queries = [
            'rel["natural"="water"]', 'rel["waterway"="riverbank"]',
            'way["natural"="water"]', 'way["waterway"="riverbank"]',
            'way["waterway"="dock"]'
        ]
        tags_of_interest = ["name"]
        if not OSM.OSM_queries_to_OSM_layer(queries,
                                            water_layer,
                                            tile.lat,
                                            tile.lon,
                                            tags_of_interest,
                                            cached_suffix='water'):
            return 0
    UI.vprint(1, "    * Building water multipolygon.")
    water_area = OSM.OSM_to_MultiPolygon(water_layer, tile.lat, tile.lon)
    if not water_area.is_empty:
        UI.vprint(1, "      Cleaning it.")
        try:
            (idx_water, dico_water) = VECT.MultiPolygon_to_Indexed_Polygons(
                water_area,
                merge_overlappings=tile.clean_bad_geometries,
                limit=VECT.max_pols_for_merge)
        except:
            return 0
        UI.vprint(
            2, "      Number of water Multipolygons : " + str(len(dico_water)))
        UI.vprint(1, "      Encoding it.")
        vector_map.encode_MultiPolygon(dico_water,
                                       tile.dem.alt_vec,
                                       'WATER',
                                       area_limit=tile.min_area / 10000,
                                       simplify=0.00001,
                                       check=True)
    return 1
Exemplo n.º 9
0
def include_airports(vector_map, tile, patches_area):
    # patches_area if not None is the extent to substract from runway_area
    # we enlarge it (local copy) slightly for security
    patches_area = patches_area.buffer(0.00002)
    UI.vprint(0, "-> Dealing with airports")
    airport_layer = OSM.OSM_layer()
    queries = [('rel["aeroway"="runway"]', 'rel["aeroway"="taxiway"]',
                'rel["aeroway"="apron"]', 'way["aeroway"="runway"]',
                'way["aeroway"="taxiway"]', 'way["aeroway"="apron"]')]
    tags_of_interest = ["all"]
    if not OSM.OSM_queries_to_OSM_layer(queries,
                                        airport_layer,
                                        tile.lat,
                                        tile.lon,
                                        tags_of_interest,
                                        cached_suffix='airports'):
        return 0
    # Runway and taxiway center lines (they will be incorporated to ensure triangles
    # are not too badly aligned with these lines (improves removal of bumpiness)
    runway_network = OSM.OSM_to_MultiLineString(airport_layer, tile.lat,
                                                tile.lon, [])
    # Buffer these for later smoothing
    runway_area = VECT.improved_buffer(runway_network, 0.0003, 0.0001, 0.00001)
    if not runway_area: return 0
    runway_area = runway_area.difference(patches_area).buffer(0).simplify(
        0.00001)
    runway_network = runway_network.difference(patches_area)
    # Now we encode in vector_map
    vector_map.encode_MultiLineString(runway_network,
                                      tile.dem.alt_vec,
                                      'DUMMY',
                                      check=True,
                                      refine=20)
    vector_map.encode_MultiPolygon(runway_area,
                                   tile.dem.alt_vec,
                                   'SMOOTHED_ALT',
                                   check=True,
                                   refine=50)
    return 1
Exemplo n.º 10
0
def include_roads(vector_map, tile, apt_array, apt_area):
    def road_is_too_much_banked(way, filtered_segs):
        (col,
         row) = numpy.minimum(numpy.maximum(numpy.round(way[0] * 1000), 0),
                              1000)
        if apt_array[int(1000 - row), int(col)]: return True
        (col,
         row) = numpy.minimum(numpy.maximum(numpy.round(way[-1] * 1000), 0),
                              1000)
        if apt_array[int(1000 - row), int(col)]: return True
        if filtered_segs >= tile.max_levelled_segs: return False
        return (numpy.abs(
            tile.dem.alt_vec(way) -
            tile.dem.alt_vec(VECT.shift_way(way, tile.lane_width))) >=
                tile.road_banking_limit).any()

    def alt_vec_shift(way):
        return tile.dem.alt_vec(VECT.shift_way(way, tile.lane_width))

    if not tile.road_level: return
    UI.vprint(0, "-> Dealing with roads")
    tags_of_interest = ["bridge", "tunnel"]
    #Need to evaluate if including bridges is better or worse
    tags_for_exclusion = set(["bridge", "tunnel"])
    #tags_for_exclusion=set(["tunnel"])
    road_layer = OSM.OSM_layer()
    queries = [
        'way["highway"="motorway"]', 'way["highway"="trunk"]',
        'way["highway"="primary"]', 'way["highway"="secondary"]',
        'way["railway"="rail"]', 'way["railway"="narrow_gauge"]'
    ]
    if not OSM.OSM_queries_to_OSM_layer(queries,
                                        road_layer,
                                        tile.lat,
                                        tile.lon,
                                        tags_of_interest,
                                        cached_suffix='big_roads'):
        return 0
    UI.vprint(1, "    * Checking which large roads need levelling.")
    (road_network_banked, road_network_flat) = OSM.OSM_to_MultiLineString(
        road_layer, tile.lat, tile.lon, tags_for_exclusion,
        road_is_too_much_banked)
    if UI.red_flag: return 0
    if tile.road_level >= 2:
        road_layer = OSM.OSM_layer()
        queries=[\
           'way["highway"="tertiary"]']
        if tile.road_level >= 3:
            queries += [
                'way["highway"="unclassified"]', 'way["highway"="residential"]'
            ]
        if tile.road_level >= 4:
            queries += ['way["highway"="service"]']
        if tile.road_level >= 5:
            queries += ['way["highway"="track"]']
        if not OSM.OSM_queries_to_OSM_layer(queries,
                                            road_layer,
                                            tile.lat,
                                            tile.lon,
                                            tags_of_interest,
                                            cached_suffix='small_roads'):
            return 0
        UI.vprint(1, "    * Checking which smaller roads need levelling.")
        timer = time.time()
        (road_network_banked_2,road_network_flat_2)=OSM.OSM_to_MultiLineString(road_layer,\
                tile.lat,tile.lon,tags_for_exclusion,road_is_too_much_banked)
        UI.vprint(3, "Time for check :", time.time() - timer)
        road_network_banked = geometry.MultiLineString(
            list(road_network_banked) + list(road_network_banked_2))
    if not road_network_banked.is_empty:
        UI.vprint(1, "    * Buffering banked road network as multipolygon.")
        timer = time.time()
        road_area = VECT.improved_buffer(road_network_banked.difference(
            VECT.improved_buffer(apt_area, tile.lane_width + 2, 0, 0)),
                                         tile.lane_width,
                                         2,
                                         0.5,
                                         show_progress=True)
        UI.vprint(3, "Time for improved buffering:", time.time() - timer)
        if UI.red_flag: return 0
        UI.vprint(1, "      Encoding it.")
        vector_map.encode_MultiPolygon(road_area,
                                       alt_vec_shift,
                                       'INTERP_ALT',
                                       check=True,
                                       refine=100)
        if UI.red_flag: return 0
    if not road_network_flat.is_empty:
        road_network_flat = road_network_flat.difference(
            VECT.improved_buffer(apt_area, 15, 0, 0)).simplify(0.00001)
        UI.vprint(
            1,
            "    * Encoding the remaining primary road network as linestrings."
        )
        vector_map.encode_MultiLineString(road_network_flat,
                                          tile.dem.alt_vec,
                                          'DUMMY',
                                          check=True)
    return 1
Exemplo n.º 11
0
def include_roads(vector_map, tile):
    if not tile.road_level: return
    UI.vprint(0, "-> Dealing with roads")
    tags_of_interest = ["bridge", "tunnel"]
    #Need to evaluate if including bridges is better or worse
    tags_for_exclusion = set(["bridge", "tunnel"])
    #tags_for_exclusion=set(["tunnel"])
    road_layer = OSM.OSM_layer()
    queries = [
        'way["highway"="motorway"]', 'way["highway"="trunk"]',
        'way["highway"="primary"]', 'way["highway"="secondary"]',
        'way["railway"="rail"]', 'way["railway"="narrow_gauge"]'
    ]
    if not OSM.OSM_queries_to_OSM_layer(queries,
                                        road_layer,
                                        tile.lat,
                                        tile.lon,
                                        tags_of_interest,
                                        cached_suffix='big_roads'):
        return 0
    UI.vprint(1, "    * Checking which large roads need levelling.")
    (road_network_banked, road_network_flat) = OSM.OSM_to_MultiLineString(
        road_layer, tile.lat, tile.lon,
        tags_for_exclusion, lambda way: tile.dem.way_is_too_much_banked(
            way, tile.road_banking_limit))
    if UI.red_flag: return 0
    if tile.road_level >= 2:
        road_layer = OSM.OSM_layer()
        queries=[\
           'way["highway"="tertiary"]']
        if tile.road_level >= 3:
            queries += [
                'way["highway"="unclassified"]', 'way["highway"="residential"]'
            ]
        if tile.road_level >= 4:
            queries += ['way["highway"="service"]']
        if tile.road_level >= 5:
            queries += ['way["highway"="track"]']
        if not OSM.OSM_queries_to_OSM_layer(queries,
                                            road_layer,
                                            tile.lat,
                                            tile.lon,
                                            tags_of_interest,
                                            cached_suffix='small_roads'):
            return 0
        UI.vprint(1, "    * Checking which smaller roads need levelling.")
        timer = time.time()
        (road_network_banked_2,road_network_flat_2)=OSM.OSM_to_MultiLineString(road_layer,\
                tile.lat,tile.lon,tags_for_exclusion,lambda way: tile.dem.way_is_too_much_banked(way,tile.road_banking_limit),limit_segs=tile.max_levelled_segs)
        UI.vprint(3, "Time for check :", time.time() - timer)
        road_network_banked = geometry.MultiLineString(
            list(road_network_banked) +
            list(road_network_banked_2)).simplify(0.000005)
    if not road_network_banked.is_empty:
        UI.vprint(1, "    * Buffering banked road network as multipolygon.")
        timer = time.time()
        road_area = VECT.improved_buffer(road_network_banked, 0.00004, 0.00002,
                                         0.000005)
        UI.vprint(3, "Time for improved buffering:", time.time() - timer)
        if UI.red_flag: return 0
        UI.vprint(1, "      Encoding it.")
        vector_map.encode_MultiPolygon(road_area,
                                       tile.dem.alt_vec_road,
                                       'INTERP_ALT',
                                       check=True,
                                       refine=False)
        if UI.red_flag: return 0
    if not road_network_flat.is_empty:
        road_network_flat = road_network_flat.simplify(
            0.00001)  #.difference(road_area)
        UI.vprint(
            1,
            "    * Encoding the remaining primary road network as linestrings."
        )
        vector_map.encode_MultiLineString(road_network_flat,
                                          tile.dem.alt_vec_road,
                                          'DUMMY',
                                          check=True)
    return 1
Exemplo n.º 12
0
def build_poly_file(tile):
    UI.red_flag = 0
    UI.logprint("Step 1 for tile lat=", tile.lat, ", lon=", tile.lon,
                ": starting.")
    UI.vprint(
        0, "\nStep 1 : Building vector data for tile " +
        FNAMES.short_latlon(tile.lat, tile.lon) + " : \n--------\n")
    timer = time.time()

    if not os.path.exists(tile.build_dir):
        os.makedirs(tile.build_dir)
    if not os.path.exists(FNAMES.osm_dir(tile.lat, tile.lon)):
        os.makedirs(FNAMES.osm_dir(tile.lat, tile.lon))
    node_file = FNAMES.input_node_file(tile)
    poly_file = FNAMES.input_poly_file(tile)
    vector_map = VECT.Vector_Map()

    tile.ensure_elevation_data()

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Patches
    patches_area = include_patches(vector_map, tile)
    UI.vprint(1, "    Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Airports
    include_airports(vector_map, tile, patches_area)
    UI.vprint(1, "    Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Roads
    include_roads(vector_map, tile)
    UI.vprint(1, "    Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Sea
    include_sea(vector_map, tile)
    UI.vprint(1, "    Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Water
    include_water(vector_map, tile)
    UI.vprint(1, "    Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Buildings
    # include_buildings(vector_map)
    # if UI.red_flag: UI.exit_message_and_bottom_line(); return 0

    # Orthogrid
    UI.vprint(0, "-> Inserting edges related to the orthophotos grid")
    xgrid = set()  # x coordinates of vertical grid lines
    ygrid = set()  # y coordinates of horizontal grid lines
    (til_xul, til_yul) = GEO.wgs84_to_orthogrid(tile.lat + 1, tile.lon,
                                                tile.mesh_zl)
    (til_xlr, til_ylr) = GEO.wgs84_to_orthogrid(tile.lat, tile.lon + 1,
                                                tile.mesh_zl)
    for til_x in range(til_xul + 16, til_xlr + 1, 16):
        pos_x = (til_x / (2**(tile.mesh_zl - 1)) - 1)
        xgrid.add(pos_x * 180 - tile.lon)
    for til_y in range(til_yul + 16, til_ylr + 1, 16):
        pos_y = (1 - (til_y) / (2**(tile.mesh_zl - 1)))
        ygrid.add(360 / pi * atan(exp(pi * pos_y)) - 90 - tile.lat)
    xgrid.add(0)
    xgrid.add(1)
    ygrid.add(0)
    ygrid.add(1)
    xgrid = list(sorted(xgrid))
    ygrid = list(sorted(ygrid))
    ortho_network = geometry.MultiLineString(
        [geometry.LineString([(x, 0), (x, 1)]) for x in xgrid] +
        [geometry.LineString([(0, y), (1, y)]) for y in ygrid])
    vector_map.encode_MultiLineString(ortho_network,
                                      tile.dem.alt_vec,
                                      'DUMMY',
                                      check=True,
                                      skip_cut=True)

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Gluing edges
    UI.vprint(0, "-> Inserting additional boundary edges for gluing")
    segs = 2500
    gluing_network=geometry.MultiLineString([\
        geometry.LineString([(x,0) for x in numpy.arange(0,segs+1)/segs]),\
        geometry.LineString([(x,1) for x in numpy.arange(0,segs+1)/segs]),\
        geometry.LineString([(0,y) for y in numpy.arange(0,segs+1)/segs]),\
        geometry.LineString([(1,y) for y in numpy.arange(0,segs+1)/segs])])
    vector_map.encode_MultiLineString(gluing_network,
                                      tile.dem.alt_vec,
                                      'DUMMY',
                                      check=True,
                                      skip_cut=True)

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0
    UI.vprint(0, "-> Transcription to the files ", poly_file, "and .node")
    if not vector_map.seeds:
        if tile.dem.alt_dem.max() >= 1:
            vector_map.seeds['SEA'] = [numpy.array([1000, 1000])]
        else:
            vector_map.seeds['SEA'] = [numpy.array([0.5, 0.5])]
    vector_map.write_node_file(node_file)
    vector_map.write_poly_file(poly_file)

    UI.vprint(1, "\nFinal number of constrained edges :",
              len(vector_map.dico_edges))
    UI.timings_and_bottom_line(timer)
    UI.logprint("Step 1 for tile lat=", tile.lat, ", lon=", tile.lon,
                ": normal exit.")
    return 1
Exemplo n.º 13
0
def zone_list_to_ortho_dico(tile):
        # tile.zone_list is a list of 3-uples of the form ([(lat0,lat0),...(latN,lonN),zoomlevel,provider_code)
        # where higher lines have priority over lower ones.
        masks_im=Image.new("L",(4096,4096),'black')
        masks_draw=ImageDraw.Draw(masks_im)
        airport_array=numpy.zeros((4096,4096),dtype=numpy.bool)
        if tile.cover_airports_with_highres:
            UI.vprint(1,"-> Checking airport locations for upgraded zoomlevel.")
            airport_layer=OSM.OSM_layer()
            queries=[('rel["aeroway"="runway"]','rel["aeroway"="taxiway"]','rel["aeroway"="apron"]',
              'way["aeroway"="runway"]','way["aeroway"="taxiway"]','way["aeroway"="apron"]')]
            tags_of_interest=["all"]
            if not OSM.OSM_queries_to_OSM_layer(queries,airport_layer,tile.lat,tile.lon,tags_of_interest,cached_suffix='airports'): 
                return 0
            runway_network=OSM.OSM_to_MultiLineString(airport_layer,tile.lat,tile.lon)
            runway_area=VECT.improved_buffer(runway_network,0.0003,0.0001,0.00001)
            runway_area=VECT.ensure_MultiPolygon(runway_area)
            for polygon in runway_area.geoms:
                (xmin,ymin,xmax,ymax)=polygon.bounds
                # extension
                xmin-=1000*tile.cover_extent*GEO.m_to_lon(tile.lat)
                xmax+=1000*tile.cover_extent*GEO.m_to_lon(tile.lat)
                ymax+=1000*tile.cover_extent*GEO.m_to_lat
                ymin-=1000*tile.cover_extent*GEO.m_to_lat
                # round off to texture boundaries at tile.cover_zl zoomlevel
                (til_x_left,til_y_top)=GEO.wgs84_to_orthogrid(ymax+tile.lat,xmin+tile.lon,tile.cover_zl)
                (ymax,xmin)=GEO.gtile_to_wgs84(til_x_left,til_y_top,tile.cover_zl)
                ymax-=tile.lat; xmin-=tile.lon
                (til_x_left,til_y_top)=GEO.wgs84_to_orthogrid(ymin+tile.lat,xmax+tile.lon,tile.cover_zl)
                (ymin,xmax)=GEO.gtile_to_wgs84(til_x_left+16,til_y_top+16,tile.cover_zl)
                ymin-=tile.lat; xmax-=tile.lon
                # mark to airport_array
                colmin=round(xmin*4095)
                colmax=round(xmax*4095)
                rowmax=round((1-ymin)*4095)
                rowmin=round((1-ymax)*4095)
                airport_array[rowmin:rowmax+1,colmin:colmax+1]=1 
            del(airport_layer)
            del(runway_network) 
            del(runway_area)
        dico_tmp={}
        dico_customzl={}
        i=1
        base_zone=((tile.lat,tile.lon,tile.lat,tile.lon+1,tile.lat+1,tile.lon+1,tile.lat+1,tile.lon,tile.lat,tile.lon),tile.default_zl,tile.default_website)
        for region in [base_zone]+tile.zone_list[::-1]:
            dico_tmp[i]=(region[1],region[2])
            pol=[(round((x-tile.lon)*4095),round((tile.lat+1-y)*4095)) for (x,y) in zip(region[0][1::2],region[0][::2])]
            masks_draw.polygon(pol,fill=i)
            i+=1
        til_x_min,til_y_min=GEO.wgs84_to_orthogrid(tile.lat+1,tile.lon,tile.mesh_zl)
        til_x_max,til_y_max=GEO.wgs84_to_orthogrid(tile.lat,tile.lon+1,tile.mesh_zl)
        for til_x in range(til_x_min,til_x_max+1,16):
            for til_y in range(til_y_min,til_y_max+1,16):
                (latp,lonp)=GEO.gtile_to_wgs84(til_x+8,til_y+8,tile.mesh_zl)
                lonp=max(min(lonp,tile.lon+1),tile.lon) 
                latp=max(min(latp,tile.lat+1),tile.lat) 
                x=round((lonp-tile.lon)*4095)
                y=round((tile.lat+1-latp)*4095)
                (zoomlevel,provider_code)=dico_tmp[masks_im.getpixel((x,y))]
                if airport_array[y,x]: 
                    zoomlevel=max(zoomlevel,tile.cover_zl)
                til_x_text=16*(int(til_x/2**(tile.mesh_zl-zoomlevel))//16)
                til_y_text=16*(int(til_y/2**(tile.mesh_zl-zoomlevel))//16)
                dico_customzl[(til_x,til_y)]=(til_x_text,til_y_text,zoomlevel,provider_code)
        return dico_customzl
Exemplo n.º 14
0
def keep_obj8(lat_anchor, lon_anchor, alt_anchor, heading_anchor, objfile_name,
              vector_map, tile):
    dico_idx_nodes = {}
    idx_node = 0
    dico_index = {}
    index = 0
    latscale = GEO.m_to_lat
    lonscale = latscale / cos(lat_anchor * pi / 180)
    f = open(objfile_name, 'r')
    for line in f.readlines():
        if line[0:2] == 'VT':
            (xo, yo, zo) = [float(s) for s in line.split()[1:4]]
            Xo = xo * cos(heading_anchor * pi / 180) - zo * sin(
                heading_anchor * pi / 180)
            Zo = xo * sin(heading_anchor * pi / 180) + zo * cos(
                heading_anchor * pi / 180)
            y = numpy.round(lat_anchor - latscale * float(Zo) - tile.lat, 7)
            x = numpy.round(lon_anchor + lonscale * float(Xo) - tile.lon, 7)
            z = yo + alt_anchor
            dico_idx_nodes[idx_node] = vector_map.insert_node(x, y, z)
            idx_node += 1
        elif line[0:3] == 'IDX':
            dico_index[index] = [int(x) for x in line.split()[1:]]
            index += 1
        elif line[0:4] == 'TRIS':
            (offset, count) = [int(x) for x in line.split()[1:3]]
            list = []
            count_tmp = 0
            try:
                polist = []
                while count_tmp < count:
                    list += dico_index[offset]
                    count_tmp += len(dico_index[offset])
                    offset += 1
                for j in range(count // 3):
                    (a, b,
                     c) = [dico_idx_nodes[x] for x in list[3 * j:3 * j + 3]]
                    if a == b or a == c or b == c: continue
                    for (initp, endp) in ((a, b), (b, c), (c, a)):
                        vector_map.insert_edge(
                            initp,
                            endp,
                            vector_map.dico_attributes['INTERP_ALT'],
                            check=True)
                    seed = (numpy.array(vector_map.nodes_dico[a]) +
                            numpy.array(vector_map.nodes_dico[b]) +
                            numpy.array(vector_map.nodes_dico[c])) / 3
                    if 'INTERP_ALT' in vector_map.seeds:
                        vector_map.seeds['INTERP_ALT'].append(seed)
                    else:
                        vector_map.seeds['INTERP_ALT'] = [seed]
                    polist.append(
                        geometry.Polygon([
                            vector_map.nodes_dico[a], vector_map.nodes_dico[b],
                            vector_map.nodes_dico[c], vector_map.nodes_dico[a]
                        ]))
                multipol = VECT.ensure_MultiPolygon(ops.cascaded_union(polist))
            except:
                pass
    f.close()
    return multipol
Exemplo n.º 15
0
def include_water(vector_map, tile):
    large_lake_threshold = tile.max_area * 1e6 / (GEO.lat_to_m *
                                                  GEO.lon_to_m(tile.lat + 0.5))

    def filter_large_lakes(pol, osmid, dicosmtags):
        if pol.area < large_lake_threshold: return False
        area = int(pol.area * GEO.lat_to_m * GEO.lon_to_m(tile.lat + 0.5) /
                   1e6)
        if (osmid in dicosmtags) and ('name' in dicosmtags[osmid]):
            if (dicosmtags[osmid]['name'] in good_imagery_list):
                UI.vprint(1, "      * ", dicosmtags[osmid]['name'],
                          "kept will complete imagery although it is", area,
                          "km^2.")
                return False
            else:
                UI.vprint(
                    1, "      * ", dicosmtags[osmid]['name'],
                    "will be masked like the sea due to its large area of",
                    area, "km^2.")
                return True
        else:
            pt = pol.exterior.coords[
                0] if 'Multi' not in pol.geom_type else pol[0].exterior.coords[
                    0]
            UI.vprint(1, "      * ",
                      "Some large OSM water patch close to lat=",
                      '{:.2f}'.format(pt[1] + tile.lon), "lon=",
                      '{:.2f}'.format(pt[0] + tile.lat),
                      "will be masked due to its large area of", area, "km^2.")
            return True

    UI.vprint(0, "-> Dealing with inland water")
    water_layer = OSM.OSM_layer()
    custom_water = FNAMES.custom_water(tile.lat, tile.lon)
    custom_water_dir = FNAMES.custom_water_dir(tile.lat, tile.lon)
    if os.path.isfile(custom_water):
        UI.vprint(1, "    * User defined custom water data detected.")
        water_layer.update_dicosm(custom_water,
                                  input_tags=None,
                                  target_tags=None)
    elif os.path.isdir(custom_water_dir):
        UI.vprint(
            1,
            "    * User defined custom water data detected (multiple files).")
        for osm_file in os.listdir(custom_water_dir):
            UI.vprint(2, "      ", osm_file)
            water_layer.update_dicosm(os.path.join(custom_water_dir, osm_file),
                                      input_tags=None,
                                      target_tags=None)
            water_layer.write_to_file(custom_water)
    else:
        queries = [
            'rel["natural"="water"]', 'rel["waterway"="riverbank"]',
            'way["natural"="water"]', 'way["waterway"="riverbank"]',
            'way["waterway"="dock"]'
        ]
        tags_of_interest = ["name"]
        if not OSM.OSM_queries_to_OSM_layer(queries,
                                            water_layer,
                                            tile.lat,
                                            tile.lon,
                                            tags_of_interest,
                                            cached_suffix='water'):
            return 0
    UI.vprint(1, "    * Building water multipolygon.")
    (water_area,
     sea_equiv_area) = OSM.OSM_to_MultiPolygon(water_layer, tile.lat, tile.lon,
                                               filter_large_lakes)
    if not water_area.is_empty:
        UI.vprint(1, "      Cleaning it.")
        try:
            (idx_water, dico_water) = VECT.MultiPolygon_to_Indexed_Polygons(
                water_area, merge_overlappings=tile.clean_bad_geometries)
        except:
            return 0
        UI.vprint(
            2, "      Number of water Multipolygons : " + str(len(dico_water)))
        UI.vprint(1, "      Encoding it.")
        vector_map.encode_MultiPolygon(dico_water,
                                       tile.dem.alt_vec,
                                       'WATER',
                                       area_limit=tile.min_area / 10000,
                                       simplify=tile.water_simplification *
                                       GEO.m_to_lat,
                                       check=True)
    if not sea_equiv_area.is_empty:
        UI.vprint(
            1, "      Separate treatment for larger pieces requiring masks.")
        try:
            (idx_water, dico_water) = VECT.MultiPolygon_to_Indexed_Polygons(
                sea_equiv_area, merge_overlappings=tile.clean_bad_geometries)
        except:
            return 0
        UI.vprint(
            2, "      Number of water Multipolygons : " + str(len(dico_water)))
        UI.vprint(1, "      Encoding them.")
        vector_map.encode_MultiPolygon(dico_water,
                                       tile.dem.alt_vec,
                                       'SEA_EQUIV',
                                       area_limit=tile.min_area / 10000,
                                       simplify=tile.water_simplification *
                                       GEO.m_to_lat,
                                       check=True)
    return 1
Exemplo n.º 16
0
 def alt_vec_shift(way):
     return tile.dem.alt_vec(VECT.shift_way(way, tile.lane_width))
Exemplo n.º 17
0
def build_poly_file(tile):
    if UI.is_working: return 0
    UI.is_working = 1
    UI.red_flag = 0
    # in case that was forgotten by the user
    tile.iterate = 0
    # update the lat/lon scaling factor in VECT
    VECT.scalx = cos((tile.lat + 0.5) * pi / 180)
    # Let's go !
    UI.logprint("Step 1 for tile lat=", tile.lat, ", lon=", tile.lon,
                ": starting.")
    UI.vprint(
        0, "\nStep 1 : Building vector data for tile " +
        FNAMES.short_latlon(tile.lat, tile.lon) + " : \n--------\n")
    timer = time.time()

    if not os.path.exists(tile.build_dir):
        os.makedirs(tile.build_dir)
    if not os.path.exists(FNAMES.osm_dir(tile.lat, tile.lon)):
        os.makedirs(FNAMES.osm_dir(tile.lat, tile.lon))
    node_file = FNAMES.input_node_file(tile)
    poly_file = FNAMES.input_poly_file(tile)
    vector_map = VECT.Vector_Map()

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    if O4_ESP_Globals.build_for_ESP and os.path.isfile(
            O4_Config_Utils.ESP_scenproc_loc):
        include_scenproc(tile)

    # Airports
    (apt_array, apt_area) = include_airports(vector_map, tile)
    UI.vprint(1, "   Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Roads
    include_roads(vector_map, tile, apt_array, apt_area)
    if tile.road_level:
        UI.vprint(1, "   Number of edges at this point:",
                  len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Sea
    include_sea(vector_map, tile)
    UI.vprint(1, "   Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Water
    include_water(vector_map, tile)
    UI.vprint(1, "   Number of edges at this point:",
              len(vector_map.dico_edges))

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Buildings
    # include_buildings(vector_map)
    # if UI.red_flag: UI.exit_message_and_bottom_line(); return 0

    # Orthogrid
    UI.vprint(0, "-> Inserting edges related to the orthophotos grid")
    xgrid = set()  # x coordinates of vertical grid lines
    ygrid = set()  # y coordinates of horizontal grid lines
    (til_xul, til_yul) = GEO.wgs84_to_orthogrid(tile.lat + 1, tile.lon,
                                                tile.mesh_zl)
    (til_xlr, til_ylr) = GEO.wgs84_to_orthogrid(tile.lat, tile.lon + 1,
                                                tile.mesh_zl)
    for til_x in range(til_xul + 16, til_xlr + 1, 16):
        pos_x = (til_x / (2**(tile.mesh_zl - 1)) - 1)
        xgrid.add(pos_x * 180 - tile.lon)
    for til_y in range(til_yul + 16, til_ylr + 1, 16):
        pos_y = (1 - (til_y) / (2**(tile.mesh_zl - 1)))
        ygrid.add(360 / pi * atan(exp(pi * pos_y)) - 90 - tile.lat)
    xgrid.add(0)
    xgrid.add(1)
    ygrid.add(0)
    ygrid.add(1)
    xgrid = list(sorted(xgrid))
    ygrid = list(sorted(ygrid))
    eps = 2**-5
    ortho_network = geometry.MultiLineString(
        [geometry.LineString([(x, 0.0 - eps), (x, 1.0 + eps)])
         for x in xgrid] +
        [geometry.LineString([(0.0 - eps, y), (1.0 + eps, y)]) for y in ygrid])
    vector_map.encode_MultiLineString(ortho_network,
                                      tile.dem.alt_vec,
                                      'DUMMY',
                                      check=True,
                                      skip_cut=True)

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0

    # Gluing edges
    UI.vprint(0, "-> Inserting additional boundary edges for gluing")
    segs = 2048
    gluing_network=geometry.MultiLineString([\
        geometry.LineString([(x,0) for x in numpy.arange(0,segs+1)/segs]),\
        geometry.LineString([(x,1) for x in numpy.arange(0,segs+1)/segs]),\
        geometry.LineString([(0,y) for y in numpy.arange(0,segs+1)/segs]),\
        geometry.LineString([(1,y) for y in numpy.arange(0,segs+1)/segs])])
    vector_map.encode_MultiLineString(gluing_network,
                                      tile.dem.alt_vec,
                                      'DUMMY',
                                      check=True,
                                      skip_cut=True)

    if UI.red_flag:
        UI.exit_message_and_bottom_line()
        return 0
    UI.vprint(0, "-> Transcription to the files ", poly_file, "and .node")
    if not vector_map.seeds:
        if tile.dem.alt_dem.max() >= 1:
            vector_map.seeds['SEA'] = [numpy.array([1000, 1000])]
        else:
            vector_map.seeds['SEA'] = [numpy.array([0.5, 0.5])]
    vector_map.snap_to_grid(15)
    vector_map.write_node_file(node_file)
    vector_map.write_poly_file(poly_file)

    UI.vprint(1, "\nFinal number of constrained edges :",
              len(vector_map.dico_edges))
    UI.timings_and_bottom_line(timer)
    UI.logprint("Step 1 for tile lat=", tile.lat, ", lon=", tile.lon,
                ": normal exit.")
    return 1
Exemplo n.º 18
0
def sort_and_reconstruct_runways(tile, airport_layer, dico_airports):
    ### Runways in OSM are either encoded as linear features or as area features, and sometimes both for the same runway. Here we identify them and
    ### remove duplicates. Runways of linear type are also often split in OSM between multiple parts (displaced threshold etc), we also group them
    ### together in this funcion.
    for airport in dico_airports:
        ## Distinction between linear and area runways
        runways_as_area = [
        ]  # runways that are encoded in OSM as a polygon around their boundary
        runways_as_line = [
        ]  # runways that are encoded in OSM as a linestrings
        linear = [
        ]  # temporary list containing parts (displaced threshold, etc) of OSM runways as linestrings
        linear_width = [
        ]  # whenever the width tag appears for runways that are linear features, if not we'll try to guess the width from the length
        for wayid in dico_airports[airport]['runway']:
            if airport_layer.dicosmw[wayid][0] == airport_layer.dicosmw[wayid][
                    -1]:
                runway_pol = geometry.Polygon(
                    numpy.round(
                        numpy.array([
                            airport_layer.dicosmn[nodeid]
                            for nodeid in airport_layer.dicosmw[wayid]
                        ]) - numpy.array([tile.lon, tile.lat]), 7))
                if not runway_pol.is_empty and runway_pol.is_valid and runway_pol.area > 1e-7:
                    runway_pol_rect = VECT.min_bounding_rectangle(runway_pol)
                    if wayid not in airport_layer.dicosmtags[
                            'w'] or 'custom' not in airport_layer.dicosmtags[
                                'w'][wayid]:
                        discrep = runway_pol_rect.hausdorff_distance(
                            runway_pol)
                        if discrep > 0.0008:
                            UI.logprint(
                                "Bad runway (geometry too far from a rectangle) close to",
                                airport, "at",
                                dico_airports[airport]['repr_node'])
                            UI.vprint(
                                1,
                                "   !Bad runway (geometry too far from a rectangle) close to",
                                airport, "at",
                                dico_airports[airport]['repr_node'])
                            UI.vprint(
                                1, "   !You may correct it editing the file ",
                                FNAMES.osm_cached(tile.lat, tile.lon,
                                                  'airports'), "in JOSM.")
                            continue
                    rectangle = numpy.array(
                        VECT.min_bounding_rectangle(
                            runway_pol).exterior.coords)
                    if VECT.length_in_meters(
                            rectangle[0:2]) < VECT.length_in_meters(
                                rectangle[1:3]):
                        runway_start = (rectangle[0] + rectangle[1]) / 2
                        runway_end = (rectangle[2] + rectangle[3]) / 2
                        runway_width = VECT.length_in_meters(rectangle[0:2])
                    else:
                        runway_start = (rectangle[1] + rectangle[2]) / 2
                        runway_end = (rectangle[0] + rectangle[3]) / 2
                        runway_width = VECT.length_in_meters(rectangle[1:3])
                    runways_as_area.append(
                        (runway_pol, runway_start, runway_end, runway_width))
                else:
                    UI.logprint(
                        1,
                        "Bad runway (geometry invalid or going back over itself) close to",
                        airport, "at", dico_airports[airport]['repr_node'])
                    UI.vprint(
                        1,
                        "   !Bad runway (geometry invalid or going back over itself) close to",
                        airport, "at", dico_airports[airport]['repr_node'])
                    UI.vprint(
                        1, "   !You may correct it editing the file ",
                        FNAMES.osm_cached(tile.lat, tile.lon, 'airports'),
                        "in JOSM.")
                    continue
            else:
                linear.append(airport_layer.dicosmw[wayid])
                try:
                    linear_width.append(
                        float(airport_layer.dicosmtags['w'][wayid]['width']))
                except:
                    linear_width.append(
                        0
                    )  # 0 is just a mark for non existing data, a fictive length will be given later based on the runway length
        ## Line merge runway parts defined as linear features
        runway_parts_are_grouped = False
        while not runway_parts_are_grouped:
            runway_parts_are_grouped = True
            for i in range(len(linear) - 1):
                dir_i = numpy.arctan2(
                    *(numpy.array(airport_layer.dicosmn[linear[i][-1]]) -
                      numpy.array(airport_layer.dicosmn[linear[i][0]])))
                for j in range(i + 1, len(linear)):
                    dir_j = numpy.arctan2(
                        *(numpy.array(airport_layer.dicosmn[linear[j][-1]]) -
                          numpy.array(airport_layer.dicosmn[linear[j][0]])))
                    # Some different runways may share a common end-point in OSM, in this case we don't want to group them into a single one
                    if not numpy.min(
                            numpy.abs(
                                numpy.array([-2 * pi, -pi, 0, pi, 2 * pi]) -
                                (dir_i - dir_j))) < 0.2:
                        continue
                    if linear[i][-1] == linear[j][0]:
                        linear = [
                            linear[k]
                            for k in range(len(linear)) if k not in (i, j)
                        ] + [linear[i] + linear[j][1:]]
                        linear_width = [
                            linear_width[k] for k in range(len(linear_width))
                            if k not in (i, j)
                        ] + [max(linear_width[i], linear_width[j])]
                        runway_parts_are_grouped = False
                        break
                    elif linear[i][-1] == linear[j][-1]:
                        linear = [
                            linear[k]
                            for k in range(len(linear)) if k not in (i, j)
                        ] + [linear[i] + linear[j][-2::-1]]
                        linear_width = [
                            linear_width[k] for k in range(len(linear_width))
                            if k not in (i, j)
                        ] + [max(linear_width[i], linear_width[j])]
                        runway_parts_are_grouped = False
                        break
                    elif linear[i][0] == linear[j][0]:
                        linear = [
                            linear[k]
                            for k in range(len(linear)) if k not in (i, j)
                        ] + [linear[i][-1::-1] + linear[j][1:]]
                        linear_width = [
                            linear_width[k] for k in range(len(linear_width))
                            if k not in (i, j)
                        ] + [max(linear_width[i], linear_width[j])]
                        runway_parts_are_grouped = False
                        break
                    elif linear[i][0] == linear[j][-1]:
                        linear = [
                            linear[k]
                            for k in range(len(linear)) if k not in (i, j)
                        ] + [linear[j] + linear[i][1:]]
                        linear_width = [
                            linear_width[k] for k in range(len(linear_width))
                            if k not in (i, j)
                        ] + [max(linear_width[i], linear_width[j])]
                        runway_parts_are_grouped = False
                        break
                if not runway_parts_are_grouped: break
        ## Grow linear runways into rectangle ones and check wether they are duplicates of existing area ones, in which case they are skipped
        for (nodeid_list, width) in zip(linear, linear_width):
            runway_start = airport_layer.dicosmn[nodeid_list[0]]
            runway_end = airport_layer.dicosmn[nodeid_list[-1]]
            runway_length = GEO.dist(runway_start, runway_end)
            runway_start = numpy.round(
                numpy.array(runway_start) - numpy.array([tile.lon, tile.lat]),
                7)
            runway_end = numpy.round(
                numpy.array(runway_end) - numpy.array([tile.lon, tile.lat]), 7)
            if width:
                width += 10
            else:
                width = 30 + runway_length // 1000
            pol = geometry.Polygon(
                VECT.buffer_simple_way(
                    numpy.vstack((runway_start, runway_end)), width))
            keep_this = True
            i = 0
            for pol2 in runways_as_area:
                if (pol2[0].intersection(pol)).area > 0.6 * min(
                        pol.area, pol2[0].area):
                    # update area one with start end and width from linear one
                    runways_as_area[i] = (pol2[0], runway_start, runway_end,
                                          width)
                    # and then skip the linear one
                    keep_this = False
                    break
                i += 1
            if keep_this:
                runways_as_line.append((pol, runway_start, runway_end, width))
        ##  Save this into the dico_airport dictionnary
        runway = VECT.ensure_MultiPolygon(
            ops.cascaded_union(
                [item[0] for item in runways_as_area + runways_as_line]))
        dico_airports[airport]['runway'] = (runway, runways_as_area,
                                            runways_as_line)
    return
Exemplo n.º 19
0
def encode_runways_taxiways_and_aprons(tile, airport_layer, dico_airports,
                                       vector_map, patches_list):
    seeds = {'RUNWAY': [], 'TAXIWAY': [], 'APRON': []}
    total_rwy = 0
    total_taxi = 0
    for airport in dico_airports:
        if airport in patches_list:
            continue
        apt = dico_airports[airport]
        total_rwy += len(apt['runway'][1] + apt['runway'][2])
        total_taxi += len(apt['taxiway'][1])
        # First build the altitude generator function : that is a number of least square polynomial
        # approximations of altitudes along ways (runways, taxiways, etc). These will be used later
        # approriately weighted all together in order to give altitudes to any node in a runway or
        # taxiway (this weighting is highly important to avoid steppint effects close to intersections)
        alt_idx = index.Index()
        alt_dico = {}
        id = 0
        for (runway_pol, runway_start, runway_end,
             runway_width) in apt['runway'][1] + apt['runway'][2]:
            center_way = numpy.vstack((runway_start, runway_end))
            runway_length = VECT.length_in_meters(center_way)
            steps = int(max(runway_chunks, runway_length // 7))
            (linestring,
             polyfit) = VECT.least_square_fit_altitude_along_way(center_way,
                                                                 steps,
                                                                 tile.dem,
                                                                 weights=True)
            #(linestring,polyfit)=VECT.spline_fit_altitude_along_way(center_way,steps,tile.dem)#,weights=True)
            alt_idx.insert(id, linestring.bounds)
            alt_dico[id] = (linestring, polyfit, runway_width)
            id += 1
        for wayid in apt['taxiway'][1]:
            taxiway = numpy.array([
                airport_layer.dicosmn[nodeid]
                for nodeid in airport_layer.dicosmw[wayid]
            ]) - numpy.array([[tile.lon, tile.lat]])
            taxiway_length = VECT.length_in_meters(taxiway)
            steps = int(max(runway_chunks, taxiway_length // 7))
            (linestring, polyfit) = VECT.least_square_fit_altitude_along_way(
                taxiway, steps, tile.dem)
            #(linestring,polyfit)=VECT.spline_fit_altitude_along_way(taxiway,steps,tile.dem)
            alt_idx.insert(id, linestring.bounds)
            alt_dico[id] = (linestring, polyfit, 15)
            id += 1
        # Now that alt_gen is filled, we may proceed to encoding
        pols = [
        ]  # we keep track of encoded pols to later plant seeds inside crossings etc
        ## First runways
        for (runway_pol, runway_start, runway_end,
             runway_width) in apt['runway'][1] + apt['runway'][2]:
            runway_length = VECT.length_in_meters(
                numpy.vstack((runway_start, runway_end)))
            refine_size = max(runway_length // runway_chunks, chunk_min_size)
            for pol in VECT.ensure_MultiPolygon(VECT.cut_to_tile(runway_pol)):
                way = numpy.round(
                    VECT.refine_way(numpy.array(pol.exterior.coords),
                                    refine_size), 7)
                alti_way = numpy.array([
                    VECT.weighted_alt(node, alt_idx, alt_dico, tile.dem)
                    for node in way
                ]).reshape((len(way), 1))
                vector_map.insert_way(numpy.hstack([way, alti_way]),
                                      'RUNWAY',
                                      check=True)
                pols.append(pol)
        for pol in pols:
            for subpol in VECT.ensure_MultiPolygon(
                    pol.difference(
                        ops.cascaded_union(
                            [pol2 for pol2 in pols if pol2 != pol]))):
                seeds['RUNWAY'].append(
                    numpy.array(subpol.representative_point()))
            for subpol in VECT.ensure_MultiPolygon(
                    pol.intersection(
                        ops.cascaded_union(
                            [pol2 for pol2 in pols if pol2 != pol]))):
                seeds['RUNWAY'].append(
                    numpy.array(subpol.representative_point()))
        ## Then taxiways
        ## Not sure if it is best to separate them from the runway or not...
        cleaned_taxiway_area = VECT.improved_buffer(
            apt['taxiway'][0].difference(
                VECT.improved_buffer(apt['runway'][0], 5, 0, 0).union(
                    VECT.improved_buffer(apt['hangar'], 20, 0, 0))), 3, 2, 0.5)
        #cleaned_taxiway_area=VECT.improved_buffer(apt['taxiway'][0].difference(VECT.improved_buffer(apt['hangar'],20,0,0)),0,1,0.5)
        for pol in VECT.ensure_MultiPolygon(
                VECT.cut_to_tile(cleaned_taxiway_area)):
            if not pol.is_valid or pol.is_empty or pol.area < 1e-9:
                continue
            way = numpy.round(VECT.refine_way(numpy.array(pol.exterior), 20),
                              7)
            alti_way = numpy.array([
                VECT.weighted_alt(node, alt_idx, alt_dico, tile.dem)
                for node in way
            ]).reshape((len(way), 1))
            vector_map.insert_way(numpy.hstack([way, alti_way]),
                                  'TAXIWAY',
                                  check=True)
            for subpol in pol.interiors:
                way = numpy.round(VECT.refine_way(numpy.array(subpol), 20), 7)
                alti_way = numpy.array([
                    VECT.weighted_alt(node, alt_idx, alt_dico, tile.dem)
                    for node in way
                ]).reshape((len(way), 1))
                vector_map.insert_way(numpy.hstack([way, alti_way]),
                                      'TAXIWAY',
                                      check=True)
            seeds['TAXIWAY'].append(numpy.array(pol.representative_point()))
        ## Try to bring some aprons with, we are looking for the small ones along runways, you just need to add the 'include' tag to that apron in JOSM (local copy)
        for wayid in apt['apron'][1]:
            if wayid not in airport_layer.dicosmtags[
                    'w'] or 'include' not in airport_layer.dicosmtags['w'][
                        wayid]:
                continue
            try:
                way = numpy.round(
                    numpy.array([
                        airport_layer.dicosmn[nodeid]
                        for nodeid in airport_layer.dicosmw[wayid]
                    ]) - numpy.array([tile.lon, tile.lat]), 7)
                way = numpy.round(VECT.refine_way(way, 15), 7)
                apron_pol = geometry.Polygon(way)
                if not apron_pol.is_empty and runway_pol.is_valid:
                    alti_way = numpy.array([
                        VECT.weighted_alt(node, alt_idx, alt_dico, tile.dem)
                        for node in way
                    ]).reshape((len(way), 1))
                    vector_map.insert_way(numpy.hstack([way, alti_way]),
                                          'APRON',
                                          check=True)
                    seeds['APRON'].append(
                        numpy.array(apron_pol.representative_point()))
            except:
                pass
    for surface in ('RUNWAY', 'TAXIWAY', 'APRON'):
        if seeds[surface]:
            if surface in vector_map.seeds:
                vector_map.seeds[surface] += seeds[surface]
            else:
                vector_map.seeds[surface] = seeds[surface]
    plural_rwy = 's' if total_rwy > 1 else ''
    plural_taxi = 's' if total_taxi > 1 else ''
    UI.vprint(1, "   Auto-patched", total_rwy, "runway" + plural_rwy + " and",
              total_taxi, "piece" + plural_taxi + " of taxiway.")
    return ops.cascaded_union([dico_airports[airport]['runway'][0] for airport in dico_airports]+\
                              [dico_airports[airport]['taxiway'][0] for airport in dico_airports]+\
                              [dico_airports[airport]['apron'][0] for airport in dico_airports])
Exemplo n.º 20
0
def smooth_raster_over_airports(tile, dico_airports, preserve_boundary=True):
    max_pix = tile.apt_smoothing_pix
    for airport in dico_airports:
        if 'smoothing_pix' in dico_airports[airport]:
            try:
                max_pix = max(int(dico_airports[airport]['smoothing_pix']),
                              max_pix)
            except:
                pass
    if not max_pix:
        tile.dem.write_to_file(FNAMES.alt_file(tile))
        return
    if preserve_boundary:
        up = numpy.array(tile.dem.alt_dem[:max_pix])
        down = numpy.array(tile.dem.alt_dem[-max_pix:])
        left = numpy.array(tile.dem.alt_dem[:, :max_pix])
        right = numpy.array(tile.dem.alt_dem[:, -max_pix:])
    x0 = tile.dem.x0
    x1 = tile.dem.x1
    y0 = tile.dem.y0
    y1 = tile.dem.y1
    xstep = (x1 - x0) / tile.dem.nxdem
    ystep = (y1 - y0) / tile.dem.nydem
    upscale = max(ceil(ystep * GEO.lat_to_m / 10),
                  1)  # target 10m of pixel size at most to avoiding aliasing
    for airport in dico_airports:
        try:
            pix = int(dico_airports[airport]
                      ['smoothing_pix']) if 'smoothing_pix' in dico_airports[
                          airport] else tile.apt_smoothing_pix
        except:
            pix = tile.apt_smoothing_pix
        if not pix: continue
        (xmin, ymin, xmax, ymax) = dico_airports[airport]['boundary'].bounds
        colmin = max(floor((xmin - x0) / xstep) - pix, 0)
        colmax = min(ceil((xmax - x0) / xstep) + pix, tile.dem.nxdem - 1)
        rowmin = max(floor((y1 - ymax) / ystep) - pix, 0)
        rowmax = min(ceil((y1 - ymin) / ystep) + pix, tile.dem.nydem - 1)
        if colmin >= colmax or rowmin >= rowmax: continue
        X0 = x0 + colmin * xstep
        Y1 = y1 - rowmin * ystep
        airport_im = Image.new('L', (upscale * (colmax - colmin + 1), upscale *
                                     (rowmax - rowmin + 1)))
        airport_draw = ImageDraw.Draw(airport_im)
        full_area = VECT.ensure_MultiPolygon(
            ops.cascaded_union([
                dico_airports[airport]['boundary'],
                dico_airports[airport]['runway'][0],
                dico_airports[airport]['hangar'],
                dico_airports[airport]['taxiway'][0],
                dico_airports[airport]['apron'][0]
            ]))
        for polygon in full_area:
            exterior_pol_pix = [(round(upscale * (X - X0) / xstep),
                                 round(upscale * (Y1 - Y) / ystep))
                                for (X, Y) in polygon.exterior.coords]
            airport_draw.polygon(exterior_pol_pix, fill='white')
            for inner_ring in polygon.interiors:
                interior_pol_pix = [(round(upscale * (X - X0) / xstep),
                                     round(upscale * (Y1 - Y) / ystep))
                                    for (X, Y) in inner_ring.coords]
                airport_draw.polygon(interior_pol_pix, fill='black')
        airport_im = airport_im.resize(
            (colmax - colmin + 1, rowmax - rowmin + 1), Image.BICUBIC)
        tile.dem.alt_dem[rowmin:rowmax + 1, colmin:colmax + 1] = DEM.smoothen(
            tile.dem.alt_dem[rowmin:rowmax + 1, colmin:colmax + 1],
            pix,
            airport_im,
            preserve_boundary=False)
    if preserve_boundary:
        pix = max_pix
        for i in range(pix):
            tile.dem.alt_dem[i] = i / pix * tile.dem.alt_dem[i] + (
                pix - i) / pix * up[i]
            tile.dem.alt_dem[-i - 1] = i / pix * tile.dem.alt_dem[-i - 1] + (
                pix - i) / pix * down[-i - 1]
        for i in range(pix):
            tile.dem.alt_dem[:, i] = i / pix * tile.dem.alt_dem[:, i] + (
                pix - i) / pix * left[:, i]
            tile.dem.alt_dem[:, -i -
                             1] = i / pix * tile.dem.alt_dem[:, -i - 1] + (
                                 pix - i) / pix * right[:, -i - 1]
    tile.dem.write_to_file(FNAMES.alt_file(tile))
    return
Exemplo n.º 21
0
             query += '"' + char + '"'
         else:
             query += char
 else:
     query = None
 if nargs in (7, 8):
     epsg_code = sys.argv[3]
 if nargs == 8:
     grid_size_or_bbox = eval(sys.argv[4])
 else:
     grid_size = 0.02 if epsg_code == '4326' else 2000
 pixel_size = float(sys.argv[nargs - 3])
 buffer_width = float(sys.argv[nargs - 2]) / pixel_size
 mask_width = int(int(sys.argv[nargs - 1]) / pixel_size)
 pixel_size = pixel_size / 111120 if epsg_code == '4326' else pixel_size  # assuming meters if not degrees
 vector_map = VECT.Vector_Map()
 osm_layer = OSM.OSM_layer()
 if not os.path.exists(cached_file_name):
     print("OSM query...")
     if not OSM.OSM_query_to_OSM_layer(
             query, '', osm_layer, cached_file_name=cached_file_name):
         print("OSM query failed. Exiting.")
         del (vector_map)
         time.sleep(1)
         sys.exit(0)
 else:
     print("Recycling OSM file...")
     osm_layer.update_dicosm(cached_file_name, None)
 print("Transform to multipolygon...")
 multipolygon_area = OSM.OSM_to_MultiPolygon(osm_layer, 0, 0)
 del (osm_layer)
Exemplo n.º 22
0
def build_curv_tol_weight_map(tile, weight_array):
    if tile.apt_curv_tol != tile.curvature_tol:
        UI.vprint(
            1,
            "-> Modifying curv_tol weight map according to runway locations.")
        airport_layer = OSM.OSM_layer()
        queries = [('rel["aeroway"="runway"]', 'rel["aeroway"="taxiway"]',
                    'rel["aeroway"="apron"]', 'way["aeroway"="runway"]',
                    'way["aeroway"="taxiway"]', 'way["aeroway"="apron"]')]
        tags_of_interest = ["all"]
        if not OSM.OSM_queries_to_OSM_layer(queries,
                                            airport_layer,
                                            tile.lat,
                                            tile.lon,
                                            tags_of_interest,
                                            cached_suffix='airports'):
            return 0
        runway_network = OSM.OSM_to_MultiLineString(airport_layer, tile.lat,
                                                    tile.lon)
        runway_area = VECT.improved_buffer(runway_network, 0.0003, 0.0001,
                                           0.00001)
        if not runway_area: return 0
        runway_area = VECT.ensure_MultiPolygon(runway_area)
        for polygon in runway_area.geoms if (
                'Multi' in runway_area.geom_type
                or 'Collection' in runway_area.geom_type) else [runway_area]:
            (xmin, ymin, xmax, ymax) = polygon.bounds
            x_shift = 1000 * tile.apt_curv_ext * GEO.m_to_lon(tile.lat)
            y_shift = 1000 * tile.apt_curv_ext * GEO.m_to_lat
            colmin = round((xmin - x_shift) * 1000)
            colmax = round((xmax + x_shift) * 1000)
            rowmax = round(((1 - ymin) + y_shift) * 1000)
            rowmin = round(((1 - ymax) - y_shift) * 1000)
            weight_array[
                rowmin:rowmax + 1, colmin:colmax +
                1] = tile.curvature_tol / tile.apt_curv_tol if tile.apt_curv_tol > 0 else 1
        del (airport_layer)
        del (runway_network)
        del (runway_area)
    if tile.coast_curv_tol != tile.curvature_tol:
        UI.vprint(
            1,
            "-> Modifying curv_tol weight map according to coastline location."
        )
        sea_layer = OSM.OSM_layer()
        queries = ['way["natural"="coastline"]']
        tags_of_interest = []
        if not OSM.OSM_queries_to_OSM_layer(queries,
                                            sea_layer,
                                            tile.lat,
                                            tile.lon,
                                            tags_of_interest,
                                            cached_suffix='coastline'):
            return 0
        for nodeid in sea_layer.dicosmn:
            (lonp, latp) = [float(x) for x in sea_layer.dicosmn[nodeid]]
            x_shift = 1000 * tile.coast_curv_ext * GEO.m_to_lon(tile.lat)
            y_shift = tile.coast_curv_ext / (111.12)
            colmin = round((lonp - tile.lon - x_shift) * 1000)
            colmax = round((lonp - tile.lon + x_shift) * 1000)
            rowmax = round((tile.lat + 1 - latp + y_shift) * 1000)
            rowmin = round((tile.lat + 1 - latp - y_shift) * 1000)
            weight_array[
                rowmin:rowmax + 1, colmin:colmax +
                1] = tile.curvature_tol / tile.coast_curv_tol if tile.coast_curv_tol > 0 else 1
        del (sea_layer)
    # It could be of interest to write the weight file as a png for user editing
    #Image.fromarray((weight_array!=1).astype(numpy.uint8)*255).save('weight.png')
    return