calc_tile.py 4.47 KB
Newer Older
Thomas Albrecht's avatar
Thomas Albrecht committed
1 2
# -*- coding: utf-8 -*-
"""
3
shamelessly translated from calc-tile.pl
Thomas Albrecht's avatar
Thomas Albrecht committed
4
"""
5
import os
6
from math import floor
7
import numpy as np
8

9

Thomas Albrecht's avatar
Thomas Albrecht committed
10 11 12
def bucket_span(lat):
    """Latitude Range -> Tile Width (deg)"""
    alat = abs(lat)
13 14 15 16 17 18 19 20 21 22 23 24 25 26
    if alat >= 89:
        return 360
    if alat >= 88:
        return 8
    if alat >= 86:
        return 4
    if alat >= 83:
        return 2
    if alat >= 76:
        return 1
    if alat >= 62:
        return .5
    if alat >= 22:
        return .25
Thomas Albrecht's avatar
Thomas Albrecht committed
27 28
    return .125

29

30
def format_lon(lon):
31 32 33 34 35 36
    """Format longitude as e/w."""
    if lon < 0.:
        return "w%03d" % int(0. - lon)
    else:
        return "e%03d" % int(lon)

37

38
def format_lat(lat):
39 40 41 42 43 44
    """Format latitude as n/s."""
    if lat < 0.:
        return "s%02d" % int(0. - lat)
    else:
        return "n%02d" % int(lat)

45

46
def root_directory_name(xxx_todo_changeme):
portree_kid's avatar
portree_kid committed
47
    """Generate the directory name for a location."""
48
    (lon, lat) = xxx_todo_changeme
portree_kid's avatar
portree_kid committed
49 50 51 52
    lon_chunk = floor(lon/10.0) * 10
    lat_chunk = floor(lat/10.0) * 10
    return format_lon(lon_chunk) + format_lat(lat_chunk) + os.sep 

53

54
def directory_name(xxx_todo_changeme1):
55
    """Generate the directory name for a location."""
56
    (lon, lat) = xxx_todo_changeme1
57 58 59 60 61 62 63
    lon_floor = floor(lon)
    lat_floor = floor(lat)
    lon_chunk = floor(lon/10.0) * 10
    lat_chunk = floor(lat/10.0) * 10
    return format_lon(lon_chunk) + format_lat(lat_chunk) + os.sep \
         + format_lon(lon_floor) + format_lat(lat_floor)

64

65 66
def tile_index(xxx_todo_changeme2, x=0, y=0):
    (lon, lat) = xxx_todo_changeme2
portree_kid's avatar
portree_kid committed
67 68
    if x == 0 and y == 0:
        y = calc_y(lat)
69
        x = calc_x(lon, lat)
Thomas Albrecht's avatar
Thomas Albrecht committed
70

portree_kid's avatar
portree_kid committed
71 72
    index = (int(floor(lon)) + 180) << 14
    index += (int(floor(lat)) + 90) << 6
Thomas Albrecht's avatar
Thomas Albrecht committed
73 74 75 76 77
    index += y << 3
    index += x
    return index


78 79 80 81 82 83 84 85 86
def construct_path_to_stg(base_directory, center_global):
    """Returns the path to the stg-files in a FG scenery directory hierarchy at a given global lat/lon location"""
    return base_directory + os.sep + 'Objects' + os.sep + directory_name(center_global) + os.sep


def construct_stg_file_name(center_global):
    """Returns the file name of the stg-file at a given global lat/lon location"""
    return "%07i.stg" % tile_index(center_global)

87

portree_kid's avatar
portree_kid committed
88 89 90 91
def construct_btg_file_name(center_global):
    """Returns the file name of the stg-file at a given global lat/lon location"""
    return "%07i.btg.gz" % tile_index(center_global)

portree_kid's avatar
portree_kid committed
92

93 94 95 96 97 98
def get_north_lat(lat, y):
    return float(floor(lat)) + y / 8.0 + .125


def get_south_lat(lat, y):
    return float(floor(lat)) + y / 8.0
99

100 101 102

def get_west_lon(lon, lat, x):
    if x == 0:
portree_kid's avatar
portree_kid committed
103 104 105 106 107
        return float(floor(lon))
    else: 
        return float(floor(lon)) + x * (bucket_span(lat))


108 109
def get_east_lon(lon, lat, x):
    if x == 0:
portree_kid's avatar
portree_kid committed
110 111 112 113
        return float(floor(lon)) + (bucket_span(lat))
    else: 
        return float(floor(lon)) + x * (bucket_span(lat)) + (bucket_span(lat))

114 115 116 117 118 119

def calc_x(lon, lat):
    """
    FIXME: is this correct? Also: some returns do not take calculations into account.
    According to http://wiki.flightgear.org/Tile_Index_Scheme it would be calculated differently
    """
portree_kid's avatar
portree_kid committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    EPSILON = 0.0000001
    span = bucket_span(lat)
    if span < EPSILON:
        lon = 0
        return 0
    elif span <= 1.0:
        return int((lon - floor(lon)) / span)
    else:
        if lon >= 0:
            lon = int(int(lon/span) * span)
        else:
            lon = int(int((lon+1)/span) * span - span)
            if lon < -180:
                lon = -180
        return 0

136

portree_kid's avatar
portree_kid committed
137 138 139
def calc_y(lat):
    return int((lat - floor(lat)) * 8)
    
140 141 142 143 144 145 146 147 148 149 150 151

def get_stg_files_in_boundary(boundary_west, boundary_south, boundary_east, boundary_north, path_to_scenery):
    """Based on boundary rectangle returns a list of stg-files (incl. full path) to be found within the boundary of
    the scenery"""
    stg_files = []
    for my_lat in np.arange(boundary_south, boundary_north, 0.125):  # latitude
        for my_lon in np.arange(boundary_west, boundary_east, bucket_span(my_lat)):  # longitude
            coords = (my_lon, my_lat)
            stg_files.append(construct_path_to_stg(path_to_scenery, coords) + construct_stg_file_name(coords))
    return stg_files


Thomas Albrecht's avatar
Thomas Albrecht committed
152 153 154 155 156 157
if __name__ == "__main__":
    for lon, lat, idx in ((13.687944, 51.074664, 3171138),
                          (13.9041667, 51.1072222, 3171139),
                          (13.775, 51.9638889, 3171195),
                          (0.258094, 29.226081, 2956745),
                          (-2.216667, 30.008333, 2907651)):
158 159
        print(tile_index([lon, lat]) - idx)
        print(directory_name([lon, lat]))