Exemplo n.º 1
0
def create_terrain_file(tile, texture_file_name, til_x_left, til_y_top,
                        zoomlevel, provider_code, tri_type, is_overlay):
    if not os.path.exists(os.path.join(tile.build_dir, 'terrain')):
        os.makedirs(os.path.join(tile.build_dir, 'terrain'))
    suffix = '_water' if tri_type == 1 else '_sea' if tri_type == 2 else ''
    if is_overlay: suffix += '_overlay'
    ter_file_name = texture_file_name[:-4] + suffix + '.ter'
    if use_test_texture: texture_file_name = 'test_texture.dds'
    with open(os.path.join(tile.build_dir, 'terrain', ter_file_name),
              'w') as f:
        f.write('A\n800\nTERRAIN\n\n')
        [lat_med, lon_med] = GEO.gtile_to_wgs84(til_x_left + 8, til_y_top + 8,
                                                zoomlevel)
        texture_approx_size = int(
            GEO.webmercator_pixel_size(lat_med, zoomlevel) * 4096)
        f.write('LOAD_CENTER '+'{:.5f}'.format(lat_med)+' '\
               +'{:.5f}'.format(lon_med)+' '\
               +str(texture_approx_size)+' 4096\n')
        f.write('BASE_TEX_NOWRAP ../textures/' + texture_file_name + '\n')
        if tri_type in (1, 2) and not is_overlay:  # experimental water
            f.write('TEXTURE_NORMAL ' + str(2**(17 - zoomlevel)) +
                    ' ../textures/water_normal_map.dds\n')
            f.write('GLOBAL_specular 1.0\n')
            f.write('NORMAL_METALNESS\n')
            if not os.path.exists(
                    os.path.join(tile.build_dir, 'textures',
                                 'water_normal_map.dds')):
                shutil.copy(
                    os.path.join(FNAMES.Utils_dir, 'water_normal_map.dds'),
                    os.path.join(tile.build_dir, 'textures'))
        elif tri_type == 1 or (tri_type == 2 and is_overlay
                               == 'ratio_water'):  #constant transparency level
            f.write('BORDER_TEX ../textures/water_transition.png\n')
            if not os.path.exists(
                    os.path.join(tile.build_dir, 'textures',
                                 'water_transition.png')):
                shutil.copy(
                    os.path.join(FNAMES.Utils_dir, 'water_transition.png'),
                    os.path.join(tile.build_dir, 'textures'))
        elif tri_type == 2:  #border_tex mask
            f.write('LOAD_CENTER_BORDER '+'{:.5f}'.format(lat_med)+' '\
               +'{:.5f}'.format(lon_med)+' '+str(texture_approx_size)+' '+str(4096//2**(zoomlevel-tile.mask_zl))+'\n')
            f.write('BORDER_TEX ../textures/' + FNAMES.mask_file(
                til_x_left, til_y_top, zoomlevel, provider_code) + '\n')
        elif tile.use_decal_on_terrain:
            f.write('DECAL_LIB lib/g10/decals/maquify_1_green_key.dcl\n')
        if tri_type in (1, 2):
            f.write('WET\n')
        if tri_type in (1, 2) or not tile.terrain_casts_shadows:
            f.write('NO_SHADOW\n')
        return ter_file_name
Exemplo n.º 2
0
def build_masks(tile):
    ##########################################
    def transition_profile(ratio, ttype):
        if ttype == 'spline':
            return 3 * ratio**2 - 2 * ratio**3
        elif ttype == 'linear':
            return ratio
        elif ttype == 'parabolic':
            return 2 * ratio - ratio**2

    ##########################################
    UI.red_flag = False
    UI.logprint("Step 2.5 for tile lat=", tile.lat, ", lon=", tile.lon,
                ": starting.")
    UI.vprint(
        0, "\nStep 2.5 : Building masks for tile " +
        FNAMES.short_latlon(tile.lat, tile.lon) + " : \n--------\n")
    timer = time.time()
    if not os.path.exists(FNAMES.mesh_file(tile.build_dir, tile.lat,
                                           tile.lon)):
        UI.lvprint(0, "ERROR: Mesh file ",
                   FNAMES.mesh_file(tile.build_dir, tile.lat, tile.lon),
                   "absent.")
        UI.exit_message_and_bottom_line('')
        return 0
    if not os.path.exists(FNAMES.mask_dir(tile.lat, tile.lon)):
        os.makedirs(FNAMES.mask_dir(tile.lat, tile.lon))
    mesh_file_name_list = []
    for close_lat in range(tile.lat - 1, tile.lat + 2):
        for close_lon in range(tile.lon - 1, tile.lon + 2):
            close_build_dir = tile.build_dir if tile.grouped else tile.build_dir.replace(
                FNAMES.tile_dir(tile.lat, tile.lon),
                FNAMES.tile_dir(close_lat, close_lon))
            close_mesh_file_name = FNAMES.mesh_file(close_build_dir, close_lat,
                                                    close_lon)
            if os.path.isfile(close_mesh_file_name):
                mesh_file_name_list.append(close_mesh_file_name)
    ####################
    dico_masks = {}
    dico_masks_inland = {}
    ####################
    [til_x_min, til_y_min] = GEO.wgs84_to_orthogrid(tile.lat + 1, tile.lon,
                                                    tile.mask_zl)
    [til_x_max, til_y_max] = GEO.wgs84_to_orthogrid(tile.lat, tile.lon + 1,
                                                    tile.mask_zl)
    UI.vprint(1, "-> Deleting existing masks")
    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):
            try:
                os.remove(
                    os.path.join(FNAMES.mask_dir(tile.lat, tile.lon),
                                 FNAMES.legacy_mask(til_x, til_y)))
            except:
                pass
    UI.vprint(1, "-> Reading mesh data")
    for mesh_file_name in mesh_file_name_list:
        try:
            f_mesh = open(mesh_file_name, "r")
            UI.vprint(1, "   * ", mesh_file_name)
        except:
            UI.lvprint(1, "Mesh file ", mesh_file_name,
                       " could not be read. Skipped.")
            continue
        for i in range(0, 4):
            f_mesh.readline()
        nbr_pt_in = int(f_mesh.readline())
        pt_in = numpy.zeros(5 * nbr_pt_in, 'float')
        for i in range(0, nbr_pt_in):
            pt_in[5 * i:5 * i +
                  3] = [float(x) for x in f_mesh.readline().split()[:3]]
        for i in range(0, 3):
            f_mesh.readline()
        for i in range(0, nbr_pt_in):
            pt_in[5 * i + 3:5 * i +
                  5] = [float(x) for x in f_mesh.readline().split()[:2]]
        for i in range(0, 2):  # skip 2 lines
            f_mesh.readline()
        nbr_tri_in = int(f_mesh.readline())  # read nbr of tris
        step_stones = nbr_tri_in // 100
        percent = -1
        UI.vprint(
            2,
            " Attribution process of masks buffers to water triangles for " +
            str(mesh_file_name) + ".")
        for i in range(0, nbr_tri_in):
            if i % step_stones == 0:
                percent += 1
                UI.progress_bar(1, int(percent * 5 / 10))
                if UI.red_flag:
                    UI.exit_message_and_bottom_line()
                    return 0
            (n1, n2, n3,
             tri_type) = [int(x) - 1 for x in f_mesh.readline().split()[:4]]
            tri_type += 1
            tri_type = (tri_type & 2) or (tri_type & 1)
            if (not tri_type) or (tri_type == 1
                                  and not tile.use_masks_for_inland):
                continue
            (lon1, lat1) = pt_in[5 * n1:5 * n1 + 2]
            (lon2, lat2) = pt_in[5 * n2:5 * n2 + 2]
            (lon3, lat3) = pt_in[5 * n3:5 * n3 + 2]
            bary_lat = (lat1 + lat2 + lat3) / 3
            bary_lon = (lon1 + lon2 + lon3) / 3
            (til_x, til_y) = GEO.wgs84_to_orthogrid(bary_lat, bary_lon,
                                                    tile.mask_zl)
            if til_x < til_x_min - 16 or til_x > til_x_max + 16 or til_y < til_y_min - 16 or til_y > til_y_max + 16:
                continue
            (til_x2, til_y2) = GEO.wgs84_to_orthogrid(bary_lat, bary_lon,
                                                      tile.mask_zl + 2)
            a = (til_x2 // 16) % 4
            b = (til_y2 // 16) % 4
            if (til_x, til_y) in dico_masks:
                dico_masks[(til_x, til_y)].append(
                    (lat1, lon1, lat2, lon2, lat3, lon3))
            else:
                dico_masks[(til_x, til_y)] = [(lat1, lon1, lat2, lon2, lat3,
                                               lon3)]
            if a == 0:
                if (til_x - 16, til_y) in dico_masks:
                    dico_masks[(til_x - 16, til_y)].append(
                        (lat1, lon1, lat2, lon2, lat3, lon3))
                else:
                    dico_masks[(til_x - 16, til_y)] = [(lat1, lon1, lat2, lon2,
                                                        lat3, lon3)]
                if b == 0:
                    if (til_x - 16, til_y - 16) in dico_masks:
                        dico_masks[(til_x - 16, til_y - 16)].append(
                            (lat1, lon1, lat2, lon2, lat3, lon3))
                    else:
                        dico_masks[(til_x - 16, til_y - 16)] = [
                            (lat1, lon1, lat2, lon2, lat3, lon3)
                        ]
                elif b == 3:
                    if (til_x - 16, til_y + 16) in dico_masks:
                        dico_masks[(til_x - 16, til_y + 16)].append(
                            (lat1, lon1, lat2, lon2, lat3, lon3))
                    else:
                        dico_masks[(til_x - 16, til_y + 16)] = [
                            (lat1, lon1, lat2, lon2, lat3, lon3)
                        ]
            elif a == 3:
                if (til_x + 16, til_y) in dico_masks:
                    dico_masks[(til_x + 16, til_y)].append(
                        (lat1, lon1, lat2, lon2, lat3, lon3))
                else:
                    dico_masks[(til_x + 16, til_y)] = [(lat1, lon1, lat2, lon2,
                                                        lat3, lon3)]
                if b == 0:
                    if (til_x + 16, til_y - 16) in dico_masks:
                        dico_masks[(til_x + 16, til_y - 16)].append(
                            (lat1, lon1, lat2, lon2, lat3, lon3))
                    else:
                        dico_masks[(til_x + 16, til_y - 16)] = [
                            (lat1, lon1, lat2, lon2, lat3, lon3)
                        ]
                elif b == 3:
                    if (til_x + 16, til_y + 16) in dico_masks:
                        dico_masks[(til_x + 16, til_y + 16)].append(
                            (lat1, lon1, lat2, lon2, lat3, lon3))
                    else:
                        dico_masks[(til_x + 16, til_y + 16)] = [
                            (lat1, lon1, lat2, lon2, lat3, lon3)
                        ]
            if b == 0:
                if (til_x, til_y - 16) in dico_masks:
                    dico_masks[(til_x, til_y - 16)].append(
                        (lat1, lon1, lat2, lon2, lat3, lon3))
                else:
                    dico_masks[(til_x, til_y - 16)] = [(lat1, lon1, lat2, lon2,
                                                        lat3, lon3)]
            elif b == 3:
                if (til_x, til_y + 16) in dico_masks:
                    dico_masks[(til_x, til_y + 16)].append(
                        (lat1, lon1, lat2, lon2, lat3, lon3))
                else:
                    dico_masks[(til_x, til_y + 16)] = [(lat1, lon1, lat2, lon2,
                                                        lat3, lon3)]
        f_mesh.close()
        if not tile.use_masks_for_inland:
            UI.vprint(2, "   Taking care of inland water near shoreline")
            f_mesh = open(mesh_file_name, "r")
            for i in range(0, 4):
                f_mesh.readline()
            nbr_pt_in = int(f_mesh.readline())
            for i in range(0, 2 * nbr_pt_in + 5):
                f_mesh.readline()
            nbr_tri_in = int(f_mesh.readline())  # read nbr of tris
            step_stones = nbr_tri_in // 100
            percent = -1
            for i in range(0, nbr_tri_in):
                if i % step_stones == 0:
                    percent += 1
                    UI.progress_bar(1, int(percent * 5 / 10))
                    if UI.red_flag:
                        UI.exit_message_and_bottom_line()
                        return 0
                (n1, n2, n3, tri_type) = [
                    int(x) - 1 for x in f_mesh.readline().split()[:4]
                ]
                tri_type += 1
                tri_type = (tri_type & 2) or (tri_type & 1)
                if not (tri_type == 1):
                    continue
                (lon1, lat1) = pt_in[5 * n1:5 * n1 + 2]
                (lon2, lat2) = pt_in[5 * n2:5 * n2 + 2]
                (lon3, lat3) = pt_in[5 * n3:5 * n3 + 2]
                bary_lat = (lat1 + lat2 + lat3) / 3
                bary_lon = (lon1 + lon2 + lon3) / 3
                (til_x,
                 til_y) = GEO.wgs84_to_orthogrid(bary_lat, bary_lon,
                                                 tile.mask_zl)
                if til_x < til_x_min - 16 or til_x > til_x_max + 16 or til_y < til_y_min - 16 or til_y > til_y_max + 16:
                    continue
                (til_x2,
                 til_y2) = GEO.wgs84_to_orthogrid(bary_lat, bary_lon,
                                                  tile.mask_zl + 2)
                a = (til_x2 // 16) % 4
                b = (til_y2 // 16) % 4
                # Here an inland water tri is added ONLY if sea water tri were already added for this mask extent
                if (til_x, til_y) in dico_masks:
                    if (til_x, til_y) in dico_masks_inland:
                        dico_masks_inland[(til_x, til_y)].append(
                            (lat1, lon1, lat2, lon2, lat3, lon3))
                    else:
                        dico_masks_inland[(til_x, til_y)] = [
                            (lat1, lon1, lat2, lon2, lat3, lon3)
                        ]
            f_mesh.close()
    UI.vprint(1, "-> Construction of the masks")
    if tile.masks_use_DEM_too:
        tile.ensure_elevation_data()

    task_len = len(dico_masks)
    task_done = 0
    for (til_x, til_y) in dico_masks:
        if UI.red_flag:
            UI.exit_message_and_bottom_line()
            return 0
        task_done += 1
        UI.progress_bar(1, 50 + int(49 * task_done / task_len))
        if til_x < til_x_min or til_x > til_x_max or til_y < til_y_min or til_y > til_y_max:
            continue
        (latm0, lonm0) = GEO.gtile_to_wgs84(til_x, til_y, tile.mask_zl)
        (px0, py0) = GEO.wgs84_to_pix(latm0, lonm0, tile.mask_zl)
        px0 -= 1024
        py0 -= 1024
        # 1) We start with a black mask
        mask_im = Image.new("L", (4096 + 2 * 1024, 4096 + 2 * 1024), 'black')
        mask_draw = ImageDraw.Draw(mask_im)
        # 2) We fill it with white over the extent of each tile around for which we had a mesh available
        for mesh_file_name in mesh_file_name_list:
            latlonstr = mesh_file_name.split('.mes')[-2][-7:]
            lathere = int(latlonstr[0:3])
            lonhere = int(latlonstr[3:7])
            (px1, py1) = GEO.wgs84_to_pix(lathere, lonhere, tile.mask_zl)
            (px2, py2) = GEO.wgs84_to_pix(lathere, lonhere + 1, tile.mask_zl)
            (px3, py3) = GEO.wgs84_to_pix(lathere + 1, lonhere + 1,
                                          tile.mask_zl)
            (px4, py4) = GEO.wgs84_to_pix(lathere + 1, lonhere, tile.mask_zl)
            px1 -= px0
            px2 -= px0
            px3 -= px0
            px4 -= px0
            py1 -= py0
            py2 -= py0
            py3 -= py0
            py4 -= py0
            mask_draw.polygon([(px1, py1), (px2, py2), (px3, py3), (px4, py4)],
                              fill='white')
        # 3a)  We overwrite the withe part of the mask with grey (ratio_water dependent) where inland water was detected in the first part above
        if (til_x, til_y) in dico_masks_inland:
            for (lat1, lon1, lat2, lon2, lat3,
                 lon3) in dico_masks_inland[(til_x, til_y)]:
                (px1, py1) = GEO.wgs84_to_pix(lat1, lon1, tile.mask_zl)
                (px2, py2) = GEO.wgs84_to_pix(lat2, lon2, tile.mask_zl)
                (px3, py3) = GEO.wgs84_to_pix(lat3, lon3, tile.mask_zl)
                px1 -= px0
                px2 -= px0
                px3 -= px0
                py1 -= py0
                py2 -= py0
                py3 -= py0
                mask_draw.polygon([(px1, py1), (px2, py2), (px3, py3)],
                                  fill=int(255 * (1 - tile.ratio_water)))
        # 3b) We overwrite the withe + grey part of the mask with black where sea water was detected in the first part above
        for (lat1, lon1, lat2, lon2, lat3, lon3) in dico_masks[(til_x, til_y)]:
            (px1, py1) = GEO.wgs84_to_pix(lat1, lon1, tile.mask_zl)
            (px2, py2) = GEO.wgs84_to_pix(lat2, lon2, tile.mask_zl)
            (px3, py3) = GEO.wgs84_to_pix(lat3, lon3, tile.mask_zl)
            px1 -= px0
            px2 -= px0
            px3 -= px0
            py1 -= py0
            py2 -= py0
            py3 -= py0
            mask_draw.polygon([(px1, py1), (px2, py2), (px3, py3)],
                              fill='black')
        del (mask_draw)
        #mask_im=mask_im.convert("L")
        img_array = numpy.array(mask_im, dtype=numpy.uint8)

        if tile.masks_use_DEM_too:
            #computing the part of the mask coming from the DEM:
            (latmax, lonmin) = GEO.pix_to_wgs84(px0, py0, tile.mask_zl)
            (latmin, lonmax) = GEO.pix_to_wgs84(px0 + 6144, py0 + 6144,
                                                tile.mask_zl)
            (x03857, y03857) = GEO.transform('4326', '3857', lonmin, latmax)
            (x13857, y13857) = GEO.transform('4326', '3857', lonmax, latmin)
            ((lonmin, lonmax, latmin,
              latmax), demarr4326) = tile.dem.super_level_set(
                  1, (lonmin, lonmax, latmin, latmax))
            if demarr4326.any():
                demim4326 = Image.fromarray(
                    demarr4326.astype(numpy.uint8) * 255)
                del (demarr4326)
                s_bbox = (lonmin, latmax, lonmax, latmin)
                t_bbox = (x03857, y03857, x13857, y13857)
                demim3857 = IMG.gdalwarp_alternative(s_bbox, '4326', demim4326,
                                                     t_bbox, '3857',
                                                     (6144, 6144))
                demim3857 = demim3857.filter(
                    ImageFilter.GaussianBlur(
                        0.3 *
                        2**(tile.mask_zl - 14)))  # slight increase of area
                dem_array = (numpy.array(demim3857, dtype=numpy.uint8) >
                             0).astype(numpy.uint8) * 255
                del (demim3857)
                del (demim4326)
                img_array = numpy.maximum(img_array, dem_array)

        custom_mask_array = numpy.zeros((4096, 4096), dtype=numpy.uint8)
        if tile.masks_custom_extent:
            (latm1, lonm1) = GEO.gtile_to_wgs84(til_x + 16, til_y + 16,
                                                tile.mask_zl)
            bbox_4326 = (lonm0, latm0, lonm1, latm1)
            masks_im = IMG.has_data(bbox_4326,
                                    tile.masks_extent_code,
                                    True,
                                    mask_size=(4096, 4096),
                                    is_sharp_resize=False,
                                    is_mask_layer=False)
            if masks_im:
                custom_mask_array = (numpy.array(masks_im, dtype=numpy.uint8) *
                                     tile.ratio_water).astype(numpy.uint8)

        if (img_array.max() == 0) and (
                custom_mask_array.max() == 0
        ):  # no need to test if the mask is all white since it would otherwise not be present in dico_mask
            UI.vprint(1, "   Skipping", FNAMES.legacy_mask(til_x, til_y))
            continue
        else:
            UI.vprint(1, "   Creating", FNAMES.legacy_mask(til_x, til_y))

        # Blur of the mask
        pxscal = GEO.webmercator_pixel_size(tile.lat + 0.5, tile.mask_zl)
        if tile.masking_mode == "sand":
            blur_width = int(tile.masks_width / pxscal)
        elif tile.masking_mode == "rocks":
            blur_width = tile.masks_width / pxscal
        elif tile.masking_mode == "3steps":
            blur_width = [L / pxscal for L in tile.masks_width]
        if tile.masking_mode == "sand" and blur_width:
            # convolution with a hat function
            b_img_array = numpy.array(img_array)
            kernel = numpy.array(range(1, 2 * blur_width))
            kernel[blur_width:] = range(blur_width - 1, 0, -1)
            kernel = kernel / blur_width**2
            for i in range(0, len(b_img_array)):
                b_img_array[i] = numpy.convolve(b_img_array[i], kernel, 'same')
            b_img_array = b_img_array.transpose()
            for i in range(0, len(b_img_array)):
                b_img_array[i] = numpy.convolve(b_img_array[i], kernel, 'same')
            b_img_array = b_img_array.transpose()
            b_img_array = 2 * numpy.minimum(b_img_array, 127)
            b_img_array = numpy.array(b_img_array, dtype=numpy.uint8)
        elif tile.masking_mode == "rocks" and blur_width:
            # slight increase of the mask, then gaussian blur, nonlinear map and a tiny bit of smoothing again on a short scale along the shore
            b_img_array=(numpy.array(Image.fromarray(img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(blur_width/1.7)),dtype=numpy.uint8)>0).astype(numpy.uint8)*255
            #blur it
            b_img_array=numpy.array(Image.fromarray(b_img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(blur_width)),dtype=numpy.uint8)
            #nonlinear transform to make the transition quicker at the shore (gaussian is too flat)
            gamma = 2.5
            b_img_array=(((numpy.tan((b_img_array.astype(numpy.float32)-127.5)/128*atan(3))-numpy.tan(-127.5/128*atan(3)))\
                    *254/(2*numpy.tan(127.5/128*atan(3))))**gamma/(255**(gamma-1))).astype(numpy.uint8)
            #b_img_array=numpy.minimum(b_img_array,200)
            #still some slight smoothing at the shore
            b_img_array=numpy.maximum(b_img_array,numpy.array(Image.fromarray(img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(2**(tile.mask_zl-14))),dtype=numpy.uint8))
        elif tile.masking_mode == "3steps":
            # why trying something so complicated...
            transin = blur_width[0]
            midzone = blur_width[1]
            transout = blur_width[2]
            shore_level = 255
            sea_level = int(tile.ratio_water * 255)
            b_img_array = b_mask_array = numpy.array(img_array)
            # First the transition at the shore
            # We go from shore_level to sea_level in transin meters
            stepsin = int(transin / 3)
            for i in range(stepsin):
                value = shore_level + transition_profile(
                    (i + 1) / stepsin, 'parabolic') * (sea_level - shore_level)
                b_mask_array=(numpy.array(Image.fromarray(b_mask_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(1)),dtype=numpy.uint8)>0).astype(numpy.uint8)*255
                b_img_array[(b_img_array == 0) * (b_mask_array != 0)] = value
                UI.vprint(2, value)
            # Next the intermediate zone at constant transparency
            sea_b_radius = midzone / 3
            sea_b_radius_buffered = (midzone + transout) / 2
            b_mask_array=(numpy.array(Image.fromarray(b_mask_array).convert("L").\
                filter(ImageFilter.GaussianBlur(sea_b_radius_buffered)),dtype=numpy.uint8)>0).astype(numpy.uint8)*255
            b_mask_array=(numpy.array(Image.fromarray(b_mask_array).convert("L").\
                filter(ImageFilter.GaussianBlur(sea_b_radius_buffered-sea_b_radius)),dtype=numpy.uint8)==255).astype(numpy.uint8)*255
            b_img_array[(b_img_array == 0) * (b_mask_array != 0)] = sea_level
            # Finally the transition to the X-Plane sea
            # We go from sea_level to 0 in transout meters
            stepsout = int(transout / 3)
            for i in range(stepsout):
                value = sea_level * (1 - transition_profile(
                    (i + 1) / stepsout, 'linear'))
                b_mask_array=(numpy.array(Image.fromarray(b_mask_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(1)),dtype=numpy.uint8)>0).astype(numpy.uint8)*255
                b_img_array[(b_img_array == 0) * (b_mask_array != 0)] = value
                UI.vprint(2, value)
            # To smoothen the thresolding introduced above we do a global short extent gaussian blur
            b_img_array=numpy.array(Image.fromarray(b_img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(2)),dtype=numpy.uint8)
        else:
            # Just a (futile) copy
            b_img_array = numpy.array(img_array)

        # Ensure land is kept to 255 on the mask to avoid unecessary ones, crop to final size, and take the
        # max with the possible custom extent mask
        img_array = numpy.maximum(img_array, b_img_array)[1024:4096 + 1024,
                                                          1024:4096 + 1024]
        img_array = numpy.maximum(img_array, custom_mask_array)

        if not (img_array.max() == 0 or img_array.min() == 255):
            masks_im = Image.fromarray(
                img_array)  #.filter(ImageFilter.GaussianBlur(3))
            masks_im.save(
                os.path.join(FNAMES.mask_dir(tile.lat, tile.lon),
                             FNAMES.legacy_mask(til_x, til_y)))
            UI.vprint(2, "     Done.")
        else:
            UI.vprint(1, "     Ends-up being discarded.")
    UI.progress_bar(1, 100)
    UI.timings_and_bottom_line(timer)
    UI.logprint("Step 2.5 for tile lat=", tile.lat, ", lon=", tile.lon,
                ": normal exit.")
    return
Exemplo n.º 3
0
    def build_mask(til_x, til_y):
        if til_x < til_x_min or til_x > til_x_max or til_y < til_y_min or til_y > til_y_max:
            return 1
        (latm0, lonm0) = GEO.gtile_to_wgs84(til_x, til_y, tile.mask_zl)
        (px0, py0) = GEO.wgs84_to_pix(latm0, lonm0, tile.mask_zl)
        px0 -= 1024
        py0 -= 1024
        # 1) We start with a black mask
        mask_im = Image.new("L", (4096 + 2 * 1024, 4096 + 2 * 1024), 'black')
        mask_draw = ImageDraw.Draw(mask_im)
        # 2) We fill it with white over the extent of each tile around for which we had a mesh available
        for mesh_file_name in mesh_file_name_list:
            latlonstr = mesh_file_name.split('.mes')[-2][-7:]
            lathere = int(latlonstr[0:3])
            lonhere = int(latlonstr[3:7])
            (px1, py1) = GEO.wgs84_to_pix(lathere, lonhere, tile.mask_zl)
            (px2, py2) = GEO.wgs84_to_pix(lathere, lonhere + 1, tile.mask_zl)
            (px3, py3) = GEO.wgs84_to_pix(lathere + 1, lonhere + 1,
                                          tile.mask_zl)
            (px4, py4) = GEO.wgs84_to_pix(lathere + 1, lonhere, tile.mask_zl)
            px1 -= px0
            px2 -= px0
            px3 -= px0
            px4 -= px0
            py1 -= py0
            py2 -= py0
            py3 -= py0
            py4 -= py0
            mask_draw.polygon([(px1, py1), (px2, py2), (px3, py3), (px4, py4)],
                              fill='white')
        # 3a)  We overwrite the white part of the mask with grey (ratio_water dependent) where inland water was detected in the first part above
        if (til_x, til_y) in dico_masks_inland:
            for (lat1, lon1, lat2, lon2, lat3,
                 lon3) in dico_masks_inland[(til_x, til_y)]:
                (px1, py1) = GEO.wgs84_to_pix(lat1, lon1, tile.mask_zl)
                (px2, py2) = GEO.wgs84_to_pix(lat2, lon2, tile.mask_zl)
                (px3, py3) = GEO.wgs84_to_pix(lat3, lon3, tile.mask_zl)
                px1 -= px0
                px2 -= px0
                px3 -= px0
                py1 -= py0
                py2 -= py0
                py3 -= py0
                mask_draw.polygon(
                    [(px1, py1), (px2, py2), (px3, py3)],
                    fill=sea_level)  # int(255*(1-tile.ratio_water)))
        # 3b) We overwrite the white + grey part of the mask with black where sea water was detected in the first part above
        for (lat1, lon1, lat2, lon2, lat3, lon3) in dico_masks[(til_x, til_y)]:
            (px1, py1) = GEO.wgs84_to_pix(lat1, lon1, tile.mask_zl)
            (px2, py2) = GEO.wgs84_to_pix(lat2, lon2, tile.mask_zl)
            (px3, py3) = GEO.wgs84_to_pix(lat3, lon3, tile.mask_zl)
            px1 -= px0
            px2 -= px0
            px3 -= px0
            py1 -= py0
            py2 -= py0
            py3 -= py0
            mask_draw.polygon([(px1, py1), (px2, py2), (px3, py3)],
                              fill='black')
        del (mask_draw)
        # mask_im=mask_im.convert("L")
        img_array = numpy.array(mask_im, dtype=numpy.uint8)

        if tile.masks_use_DEM_too:
            # computing the part of the mask coming from the DEM:
            (latmax, lonmin) = GEO.pix_to_wgs84(px0, py0, tile.mask_zl)
            (latmin, lonmax) = GEO.pix_to_wgs84(px0 + 6144, py0 + 6144,
                                                tile.mask_zl)
            (x03857, y03857) = GEO.transform('4326', '3857', lonmin, latmax)
            (x13857, y13857) = GEO.transform('4326', '3857', lonmax, latmin)
            ((lonmin, lonmax, latmin,
              latmax), demarr4326) = tile.dem.super_level_set(
                  mask_altitude_above, (lonmin, lonmax, latmin, latmax))
            if demarr4326.any():
                demim4326 = Image.fromarray(
                    demarr4326.astype(numpy.uint8) * 255)
                del (demarr4326)
                s_bbox = (lonmin, latmax, lonmax, latmin)
                t_bbox = (x03857, y03857, x13857, y13857)
                demim3857 = IMG.gdalwarp_alternative(s_bbox, '4326', demim4326,
                                                     t_bbox, '3857',
                                                     (6144, 6144))
                demim3857 = demim3857.filter(
                    ImageFilter.GaussianBlur(
                        0.3 *
                        2**(tile.mask_zl - 14)))  # slight increase of area
                dem_array = (numpy.array(demim3857, dtype=numpy.uint8) >
                             0).astype(numpy.uint8) * 255
                del (demim3857)
                del (demim4326)
                img_array = numpy.maximum(img_array, dem_array)

        custom_mask_array = numpy.zeros((4096, 4096), dtype=numpy.uint8)
        if tile.masks_custom_extent:
            (latm1, lonm1) = GEO.gtile_to_wgs84(til_x + 16, til_y + 16,
                                                tile.mask_zl)
            bbox_4326 = (lonm0, latm0, lonm1, latm1)
            masks_im = IMG.has_data(bbox_4326,
                                    tile.masks_custom_extent,
                                    True,
                                    mask_size=(4096, 4096),
                                    is_sharp_resize=False,
                                    is_mask_layer=False)
            if masks_im:
                custom_mask_array = (numpy.array(masks_im, dtype=numpy.uint8) *
                                     (sea_level / 255)).astype(numpy.uint8)

        if (img_array.max() == 0) and (
                custom_mask_array.max() == 0
        ):  # no need to test if the mask is all white since it would otherwise not be present in dico_mask
            UI.vprint(1, "   Skipping", FNAMES.legacy_mask(til_x, til_y))
            return 1
        else:
            UI.vprint(1, "   Creating", FNAMES.legacy_mask(til_x, til_y))
        # Blur of the mask
        pxscal = GEO.webmercator_pixel_size(tile.lat + 0.5, tile.mask_zl)
        if tile.masking_mode == "sand":
            blur_width = int(tile.masks_width / pxscal)
        elif tile.masking_mode == "rocks":
            blur_width = tile.masks_width / (2 * pxscal)
        elif tile.masking_mode == "3steps":
            blur_width = [L / pxscal for L in tile.masks_width]
        if tile.masking_mode == "sand" and blur_width:
            # convolution with a hat function
            b_img_array = numpy.array(img_array)
            kernel = numpy.array(range(1, 2 * blur_width))
            kernel[blur_width:] = range(blur_width - 1, 0, -1)
            kernel = kernel / blur_width**2
            for i in range(0, len(b_img_array)):
                b_img_array[i] = numpy.convolve(b_img_array[i], kernel, 'same')
            b_img_array = b_img_array.transpose()
            for i in range(0, len(b_img_array)):
                b_img_array[i] = numpy.convolve(b_img_array[i], kernel, 'same')
            b_img_array = b_img_array.transpose()
            b_img_array = 2 * numpy.minimum(b_img_array, 127)
            b_img_array = numpy.array(b_img_array, dtype=numpy.uint8)
        elif tile.masking_mode == "rocks" and blur_width:
            # slight increase of the mask, then gaussian blur, nonlinear map and a tiny bit of smoothing again on a short scale along the shore
            b_img_array = (numpy.array(Image.fromarray(img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(blur_width / 1.7)), dtype=numpy.uint8) > 0).astype(numpy.uint8) * 255
            # blur it
            b_img_array = numpy.array(Image.fromarray(b_img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(blur_width)), dtype=numpy.uint8)
            # nonlinear transform to make the transition quicker at the shore (gaussian is too flat)
            gamma = 2.5
            b_img_array = (((numpy.tan((b_img_array.astype(numpy.float32) - 127.5) / 128 * atan(3)) - numpy.tan(-127.5 / 128 * atan(3)))\
                    *254 / (2 * numpy.tan(127.5 / 128 * atan(3)))) ** gamma / (255 ** (gamma - 1))).astype(numpy.uint8)
            # b_img_array=(1.4*(255-((256-b_img_array.astype(numpy.float32))/256.0)**0.2*255)).astype(numpy.uint8)
            # b_img_array=numpy.minimum(b_img_array,200)
            # still some slight smoothing at the shore
            b_img_array = numpy.maximum(b_img_array, numpy.array(Image.fromarray(img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(2 ** (tile.mask_zl - 14))), dtype=numpy.uint8))
        elif tile.masking_mode == "3steps":
            # why trying something so complicated...
            transin = blur_width[0]
            midzone = blur_width[1]
            transout = blur_width[2]
            # print(transin,midzone,transout)
            shore_level = 255
            b_img_array = b_mask_array = numpy.array(img_array)
            # First the transition at the shore
            # We go from shore_level to sea_level in transin meters
            stepsin = int(transin / 3)
            for i in range(stepsin):
                value = shore_level + transition_profile(
                    (i + 1) / stepsin, 'parabolic') * (sea_level - shore_level)
                b_mask_array = (numpy.array(Image.fromarray(b_mask_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(1)), dtype=numpy.uint8) > 0).astype(numpy.uint8) * 255
                b_img_array[(b_img_array == 0) * (b_mask_array != 0)] = value
                UI.vprint(2, value)
            # Next the intermediate zone at constant transparency
            sea_b_radius = midzone / 3
            sea_b_radius_buffered = (midzone + transout) / 3
            b_mask_array = (numpy.array(Image.fromarray(b_mask_array).convert("L").\
                filter(ImageFilter.GaussianBlur(sea_b_radius_buffered)), dtype=numpy.uint8) > 0).astype(numpy.uint8) * 255
            b_mask_array = (numpy.array(Image.fromarray(b_mask_array).convert("L").\
                filter(ImageFilter.GaussianBlur(sea_b_radius_buffered - sea_b_radius)), dtype=numpy.uint8) == 255).astype(numpy.uint8) * 255
            b_img_array[(b_img_array == 0) * (b_mask_array != 0)] = sea_level
            # Finally the transition to the X-Plane sea
            # We go from sea_level to 0 in transout meters
            stepsout = int(transout / 3)
            for i in range(stepsout):
                value = sea_level * (1 - transition_profile(
                    (i + 1) / stepsout, 'linear'))
                b_mask_array = (numpy.array(Image.fromarray(b_mask_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(1)), dtype=numpy.uint8) > 0).astype(numpy.uint8) * 255
                b_img_array[(b_img_array == 0) * (b_mask_array != 0)] = value
                UI.vprint(2, value)
            # To smoothen the thresolding introduced above we do a global short extent gaussian blur
            b_img_array = numpy.array(Image.fromarray(b_img_array).convert("L").\
                    filter(ImageFilter.GaussianBlur(2)), dtype=numpy.uint8)
        else:
            # Just a (futile) copy
            b_img_array = numpy.array(img_array)

        # Ensure land is kept to 255 on the mask to avoid unecessary ones, crop to final size, and take the
        # max with the possible custom extent mask
        img_array = numpy.maximum((img_array > 0).astype(numpy.uint8) * 255,
                                  b_img_array)[1024:4096 + 1024,
                                               1024:4096 + 1024]
        img_array = numpy.maximum(img_array, custom_mask_array)

        if not (img_array.max() == 0 or img_array.min() == 255):
            masks_im = Image.fromarray(
                img_array)  # .filter(ImageFilter.GaussianBlur(3))
            masks_im.save(
                os.path.join(dest_dir, FNAMES.legacy_mask(til_x, til_y)))
            UI.vprint(2, "     Done.")
        else:
            UI.vprint(1, "     Ends-up being discarded.")
        return 1
Exemplo n.º 4
0
def extract_mesh_to_obj(mesh_file,til_x_left,til_y_top,zoomlevel,provider_code): 
    UI.red_flag=False
    timer=time.time()
    (latmax,lonmin)=GEO.gtile_to_wgs84(til_x_left,til_y_top,zoomlevel)
    (latmin,lonmax)=GEO.gtile_to_wgs84(til_x_left+16,til_y_top+16,zoomlevel)
    obj_file_name=FNAMES.obj_file(til_x_left,til_y_top,zoomlevel,provider_code)
    mtl_file_name=FNAMES.mtl_file(til_x_left,til_y_top,zoomlevel,provider_code)
    f_mesh=open(mesh_file,"r")
    for i in range(4):
        f_mesh.readline()
    nbr_pt_in=int(f_mesh.readline())
    UI.vprint(1,"    Reading nodes...")
    pt_in=numpy.zeros(5*nbr_pt_in,'float')
    for i in range(nbr_pt_in):
        pt_in[5*i:5*i+3]=[float(x) for x in f_mesh.readline().split()[:3]]
    for i in range(3):
        f_mesh.readline()
    for i in range(nbr_pt_in):
        pt_in[5*i+3:5*i+5]=[float(x) for x in f_mesh.readline().split()[:2]]
    for i in range(0,2): # skip 2 lines
        f_mesh.readline()
    if UI.red_flag: UI.exit_message_and_bottom_line(); return 0
    UI.vprint(1,"    Reading triangles...")
    nbr_tri_in=int(f_mesh.readline()) # read nbr of tris
    textured_nodes={}
    textured_nodes_inv={}
    nodes_st_coord={}
    len_textured_nodes=0
    dico_new_tri={}
    len_dico_new_tri=0
    for i in range(0,nbr_tri_in):
        (n1,n2,n3)=[int(x)-1 for x in f_mesh.readline().split()[:3]]
        (lon1,lat1,z1,u1,v1)=pt_in[5*n1:5*n1+5]
        (lon2,lat2,z2,u2,v2)=pt_in[5*n2:5*n2+5]
        (lon3,lat3,z3,u3,v3)=pt_in[5*n3:5*n3+5]
        if is_in_region((lat1+lat2+lat3)/3.0,(lon1+lon2+lon3)/3.0,latmin,latmax,lonmin,lonmax):
            if n1 not in textured_nodes_inv:
                len_textured_nodes+=1 
                textured_nodes_inv[n1]=len_textured_nodes
                textured_nodes[len_textured_nodes]=n1
                nodes_st_coord[len_textured_nodes]=GEO.st_coord(lat1,lon1,til_x_left,til_y_top,zoomlevel,provider_code)
            n1new=textured_nodes_inv[n1]
            if n2 not in textured_nodes_inv:
                len_textured_nodes+=1 
                textured_nodes_inv[n2]=len_textured_nodes
                textured_nodes[len_textured_nodes]=n2
                nodes_st_coord[len_textured_nodes]=GEO.st_coord(lat2,lon2,til_x_left,til_y_top,zoomlevel,provider_code)
            n2new=textured_nodes_inv[n2]
            if n3 not in textured_nodes_inv:
                len_textured_nodes+=1 
                textured_nodes_inv[n3]=len_textured_nodes
                textured_nodes[len_textured_nodes]=n3
                nodes_st_coord[len_textured_nodes]=GEO.st_coord(lat3,lon3,til_x_left,til_y_top,zoomlevel,provider_code)
            n3new=textured_nodes_inv[n3]
            dico_new_tri[len_dico_new_tri]=(n1new,n2new,n3new)
            len_dico_new_tri+=1
    nbr_vert=len_textured_nodes
    nbr_tri=len_dico_new_tri
    if UI.red_flag: UI.exit_message_and_bottom_line(); return 0
    UI.vprint(1,"    Writing the obj file.")
    # first the obj file
    f=open(obj_file_name,"w")
    for i in range(1,nbr_vert+1):
        j=textured_nodes[i]
        f.write("v "+'{:.9f}'.format(pt_in[5*j]-lonmin)+" "+\
                '{:.9f}'.format(pt_in[5*j+1]-latmin)+" "+\
                '{:.9f}'.format(pt_in[5*j+2])+"\n") 
    f.write("\n")
    for i in range(1,nbr_vert+1):
        j=textured_nodes[i]
        f.write("vn "+'{:.9f}'.format(pt_in[5*j+3])+" "+'{:.9f}'.format(pt_in[5*j+4])+" "+'{:.9f}'.format(sqrt(max(1-pt_in[5*j+3]**2-pt_in[5*j+4]**2,0)))+"\n")
    f.write("\n")
    for i in range(1,nbr_vert+1):
        j=textured_nodes[i]
        f.write("vt "+'{:.9f}'.format(nodes_st_coord[i][0])+" "+\
                '{:.9f}'.format(nodes_st_coord[i][1])+"\n")
    f.write("\n")
    f.write("usemtl orthophoto\n\n")
    for i in range(0,nbr_tri):
        (one,two,three)=dico_new_tri[i]
        f.write("f "+str(one)+"/"+str(one)+"/"+str(one)+" "+str(two)+"/"+str(two)+"/"+str(two)+" "+str(three)+"/"+str(three)+"/"+str(three)+"\n")
    f_mesh.close()
    f.close()
    # then the mtl file
    f=open(mtl_file_name,'w')
    f.write("newmtl orthophoto\nmap_Kd "+FNAMES.geotiff_file_name_from_attributes(til_x_left,til_y_top,zoomlevel,provider_code)+"\n")
    f.close()
    UI.timings_and_bottom_line(timer)
    return
Exemplo n.º 5
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 in ['True', 'ICAO']:
        UI.vprint(1, "-> Checking airport locations for upgraded zoomlevel.")
        try:
            f = open(FNAMES.apt_file(tile), 'rb')
            dico_airports = pickle.load(f)
            f.close()
        except:
            UI.vprint(
                1, "   WARNING: File", FNAMES.apt_file(tile),
                "is missing (erased after Step 1?), cannot check airport info for upgraded zoomlevel."
            )
            dico_airports = {}
        if tile.cover_airports_with_highres == 'ICAO':
            airports_list = [
                airport for airport in dico_airports
                if dico_airports[airport]['key_type'] == 'icao'
            ]
        else:
            airports_list = dico_airports.keys()
        for airport in airports_list:
            (xmin, ymin, xmax,
             ymax) = dico_airports[airport]['boundary'].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_left2,
             til_y_top2) = GEO.wgs84_to_orthogrid(ymin + tile.lat,
                                                  xmax + tile.lon,
                                                  tile.cover_zl)
            (ymin, xmax) = GEO.gtile_to_wgs84(til_x_left2 + 16,
                                              til_y_top2 + 16, tile.cover_zl)
            ymin -= tile.lat
            xmax -= tile.lon
            xmin = max(0, xmin)
            xmax = min(1, xmax)
            ymin = max(0, ymin)
            ymax = min(1, ymax)
            # 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
    dico_customzl = {}
    dico_tmp = {}
    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)
    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
    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)
    if tile.cover_airports_with_highres == 'Existing':
        # what we find in the texture folder of the existing tile
        for f in os.listdir(os.path.join(tile.build_dir, 'textures')):
            if f[-4:] != '.dds': continue
            items = f.split('_')
            (til_y_text, til_x_text) = [int(x) for x in items[:2]]
            zoomlevel = int(items[-1][-6:-4])
            provider_code = '_'.join(items[2:])[:-6]
            for til_x in range(til_x_text * 2**(tile.mesh_zl - zoomlevel),
                               (til_x_text + 16) *
                               2**(tile.mesh_zl - zoomlevel)):
                for til_y in range(til_y_text * 2**(tile.mesh_zl - zoomlevel),
                                   (til_y_text + 16) *
                                   2**(tile.mesh_zl - zoomlevel)):
                    if ((til_x, til_y) not in dico_customzl) or dico_customzl[
                        (til_x, til_y)][2] <= zoomlevel:
                        dico_customzl[(til_x,
                                       til_y)] = (til_x_text, til_y_text,
                                                  zoomlevel, provider_code)
    return dico_customzl
Exemplo n.º 6
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.")
        try:
            f = open(FNAMES.apt_file(tile), 'rb')
            dico_airports = pickle.load(f)
            f.close()
        except:
            UI.vprint(
                1, "   WARNING: File", FNAMES.apt_file(tile),
                "is missing (erased after Step 1?), cannot check airport info for upgraded zoomlevel."
            )
            dico_airports = {}
        for airport in dico_airports:
            (xmin, ymin, xmax,
             ymax) = dico_airports[airport]['boundary'].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_left2,
             til_y_top2) = GEO.wgs84_to_orthogrid(ymin + tile.lat,
                                                  xmax + tile.lon,
                                                  tile.cover_zl)
            (ymin, xmax) = GEO.gtile_to_wgs84(til_x_left2 + 16,
                                              til_y_top2 + 16, tile.cover_zl)
            ymin -= tile.lat
            xmax -= tile.lon
            xmin = max(0, xmin)
            xmax = min(1, xmax)
            ymin = max(0, ymin)
            ymax = min(1, ymax)
            # 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
    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.º 7
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