Esempio n. 1
0
def write_coordinate_value(output_file, coord):
    value = coord2int(coord)
    write_value(output_file,
                value,
                data_format=DTYPE_FORMAT_SIGNED_I,
                lower_value_limit=THRES_DTYPE_SIGNED_I_LOWER,
                upper_value_limit=THRES_DTYPE_SIGNED_I_UPPER)
Esempio n. 2
0
    def compute_exact_shortcuts(xmax, xmin, ymax, ymin, line):
        shortcuts_for_line = set()

        # x_longs = binary_reader.x_coords_of(line)
        x_longs, y_longs = ints_of(line)

        # y_longs = binary_reader.y_coords_of(line)
        y_longs.append(y_longs[0])
        x_longs.append(x_longs[0])

        step = 1 / NR_SHORTCUTS_PER_LAT
        # print('checking the latitudes')
        for lat in latitudes_to_check(ymax, ymin):
            # print(lat)
            # print(coordinate_to_longlong(lat))
            # print(y_longs)
            # print(x_intersections(coordinate_to_longlong(lat), x_longs, y_longs))
            # raise ValueError
            intersects = sorted([int2coord(x) for x in
                                 x_intersections(coord2int(lat), x_longs, y_longs)])
            # print(intersects)

            nr_of_intersects = len(intersects)
            if nr_of_intersects % 2 != 0:
                raise ValueError('an uneven number of intersections has been accounted')

            for i in range(0, nr_of_intersects, 2):
                possible_longitudes = []
                # collect all the zones between two intersections [in,out,in,out,...]
                iplus = i + 1
                intersection_in = intersects[i]
                intersection_out = intersects[iplus]
                if intersection_in == intersection_out:
                    # the polygon has a point exactly on the border of a shortcut zone here!
                    # only select the top shortcut if it is actually inside the polygon (point a little up is inside)
                    if contained(coord2int(intersection_in), coord2int(lat) + 1, x_longs,
                                 y_longs):
                        shortcuts_for_line.add((x_shortcut(intersection_in), y_shortcut(lat) - 1))
                    # the bottom shortcut is always selected
                    shortcuts_for_line.add((x_shortcut(intersection_in), y_shortcut(lat)))

                else:
                    # add all the shortcuts for the whole found area of intersection
                    possible_y_shortcut = y_shortcut(lat)

                    # both shortcuts should only be selected when the polygon doesnt stays on the border
                    middle = intersection_in + (intersection_out - intersection_in) / 2
                    if contained(coord2int(middle), coord2int(lat) + 1, x_longs,
                                 y_longs):
                        while intersection_in < intersection_out:
                            possible_longitudes.append(intersection_in)
                            intersection_in += step

                        possible_longitudes.append(intersection_out)

                        # the shortcut above and below of the intersection should be selected!
                        possible_y_shortcut_min1 = possible_y_shortcut - 1
                        for possible_x_coord in possible_longitudes:
                            shortcuts_for_line.add((x_shortcut(possible_x_coord), possible_y_shortcut))
                            shortcuts_for_line.add((x_shortcut(possible_x_coord), possible_y_shortcut_min1))
                    else:
                        # polygon does not cross the border!
                        while intersection_in < intersection_out:
                            possible_longitudes.append(intersection_in)
                            intersection_in += step

                        possible_longitudes.append(intersection_out)

                        # only the shortcut above of the intersection should be selected!
                        for possible_x_coord in possible_longitudes:
                            shortcuts_for_line.add((x_shortcut(possible_x_coord), possible_y_shortcut))

        # print('now all the longitudes to check')
        # same procedure horizontally
        step = 1 / NR_SHORTCUTS_PER_LAT
        for lng in longitudes_to_check(xmax, xmin):
            # print(lng)
            # print(coordinate_to_longlong(lng))
            # print(x_longs)
            # print(x_intersections(coordinate_to_longlong(lng), x_longs, y_longs))
            intersects = sorted([int2coord(y) for y in
                                 y_intersections(coord2int(lng), x_longs, y_longs)])
            # print(intersects)

            nr_of_intersects = len(intersects)
            if nr_of_intersects % 2 != 0:
                raise ValueError('an uneven number of intersections has been accounted')

            possible_latitudes = []
            for i in range(0, nr_of_intersects, 2):
                # collect all the zones between two intersections [in,out,in,out,...]
                iplus = i + 1
                intersection_in = intersects[i]
                intersection_out = intersects[iplus]
                if intersection_in == intersection_out:
                    # the polygon has a point exactly on the border of a shortcut here!
                    # only select the left shortcut if it is actually inside the polygon (point a little left is inside)
                    if contained(coord2int(lng) - 1, coord2int(intersection_in), x_longs,
                                 y_longs):
                        shortcuts_for_line.add((x_shortcut(lng) - 1, y_shortcut(intersection_in)))
                    # the right shortcut is always selected
                    shortcuts_for_line.add((x_shortcut(lng), y_shortcut(intersection_in)))

                else:
                    # add all the shortcuts for the whole found area of intersection
                    possible_x_shortcut = x_shortcut(lng)

                    # both shortcuts should only be selected when the polygon doesnt stays on the border
                    middle = intersection_in + (intersection_out - intersection_in) / 2
                    if contained(coord2int(lng) - 1, coord2int(middle), x_longs,
                                 y_longs):
                        while intersection_in < intersection_out:
                            possible_latitudes.append(intersection_in)
                            intersection_in += step

                        possible_latitudes.append(intersection_out)

                        # both shortcuts right and left of the intersection should be selected!
                        possible_x_shortcut_min1 = possible_x_shortcut - 1
                        for possible_latitude in possible_latitudes:
                            shortcuts_for_line.add((possible_x_shortcut, y_shortcut(possible_latitude)))
                            shortcuts_for_line.add((possible_x_shortcut_min1, y_shortcut(possible_latitude)))

                    else:
                        while intersection_in < intersection_out:
                            possible_latitudes.append(intersection_in)
                            intersection_in += step
                        # only the shortcut right of the intersection should be selected!
                        possible_latitudes.append(intersection_out)

                        for possible_latitude in possible_latitudes:
                            shortcuts_for_line.add((possible_x_shortcut, y_shortcut(possible_latitude)))

        return shortcuts_for_line
Esempio n. 3
0
def ints_of(line=0):
    x_coords, y_coords = polygons[line]
    return [coord2int(x) for x in x_coords], [coord2int(x) for x in y_coords]
Esempio n. 4
0
    def test_distance_computation(self):
        def km2rad(km):
            return km / 6371

        def km2deg(km):
            return degrees(km2rad(km))

        p_test_cases = [
            # (x,y),
            (0, 1),
            (1, 0),
            (0, -1),
            (-1, 0),

            # on the line test cases
            # (-0.5, 0.5),
            # (0, 0.5),
            # (-0.5, 0),
            # (0.5, 0),
        ]

        p1_lng_rad = radians(0.0)
        p1_lat_rad = radians(0.0)

        for x, y in p_test_cases:
            result = distance_to_point_on_equator(radians(x), radians(y),
                                                  p1_lng_rad)
            if km2deg(result) != 1:
                raise AssertionError('should be equal:', km2deg(result), 1)
            hav_result = haversine(radians(x), radians(y), p1_lng_rad, 0)
            if km2deg(hav_result) != 1.0:
                raise AssertionError('should be equal:', km2deg(hav_result),
                                     1.0)

        for i in range(1000):
            rnd_point = random_point()
            lng_rnd_point2 = random_point()[0]
            hav_result = degrees(
                haversine(radians(rnd_point[0]), radians(rnd_point[1]),
                          lng_rnd_point2, 0))
            result = degrees(
                distance_to_point_on_equator(radians(rnd_point[0]),
                                             radians(rnd_point[1]),
                                             lng_rnd_point2))
            if abs(hav_result - result) > 0.000001:
                raise AssertionError(i, 'should be equal:', hav_result, result,
                                     rnd_point, lng_rnd_point2)

        x_coords = [0.5, -0.5, -0.5, 0.5]
        y_coords = [0.5, 0.5, -0.5, -0.5]
        points = [
            [coord2int(x) for x in x_coords],
            [coord2int(x) for x in y_coords],
        ]
        trans_points = [
            [None for x in x_coords],
            [None for x in y_coords],
        ]

        x_rad = radians(1.0)
        y_rad = radians(0.0)

        print(km2deg(haversine(x_rad, y_rad, p1_lng_rad, p1_lat_rad)))
        assert km2deg(haversine(x_rad, y_rad, p1_lng_rad, p1_lat_rad)) == 1

        distance_exact = distance_to_polygon_exact(x_rad, y_rad, len(x_coords),
                                                   points, trans_points)
        print(km2deg(distance_exact))
        assert km2deg(distance_exact) == 0.5
        print('=====')
        distance = distance_to_polygon(x_rad, y_rad, len(x_coords), points)
        print(km2deg(distance))
        assert abs(km2deg(distance) - sqrt(2) / 2) < 0.00001
Esempio n. 5
0
def compile_binaries():
    global nr_of_lines
    global shortcuts

    def print_shortcut_statistics():
        frequencies = []
        max_val = max(*nr_of_entries_in_shortcut)
        print('shortcut statistics:')
        print('highest entry amount is', max_val)
        while max_val >= 0:
            frequencies.append(nr_of_entries_in_shortcut.count(max_val))
            max_val -= 1

        frequencies.reverse()
        print('frequencies of entry amounts (from 0 to max entries):')
        print(frequencies)
        empty_shortcuts = frequencies[0]
        print('relative accumulated frequencies [%]:')
        acc = accumulated_frequency(frequencies)
        print(acc)
        print([round(100 - x, 2) for x in acc])
        print(percent(empty_shortcuts, amount_of_shortcuts), '% of all shortcuts are empty\n')

        amount_of_different_zones = []
        for entry in shortcut_entries:
            registered_zone_ids = []
            for polygon_nr in entry:
                id = poly_zone_ids[polygon_nr]
                if id not in registered_zone_ids:
                    registered_zone_ids.append(id)

            amount_of_different_zones.append(len(registered_zone_ids))

        frequencies = []
        max_val = max(*amount_of_different_zones)
        print('highest amount of different zones in one shortcut is', max_val)
        while max_val >= 1:
            frequencies.append(amount_of_different_zones.count(max_val))
            max_val -= 1
        # show the proper amount of shortcuts with 0 zones (=nr of empty shortcuts)
        frequencies.append(empty_shortcuts)
        frequencies.reverse()
        print('frequencies of entry amounts (from 0 to max):')
        print(frequencies)
        print('relative accumulated frequencies [%]:')
        acc = accumulated_frequency(frequencies)
        print(acc)
        print([round(100 - x, 2) for x in acc])
        print('--------------------------------\n')

    def included_shortcut_row_nrs(max_lat, min_lat):
        return list(range(y_shortcut(max_lat), y_shortcut(min_lat) + 1))

    def included_shortcut_column_nrs(max_lng, min_lng):
        return list(range(x_shortcut(min_lng), x_shortcut(max_lng) + 1))

    def longitudes_to_check(max_lng, min_lng):
        output_list = []
        step = 1 / NR_SHORTCUTS_PER_LNG
        current = ceil(min_lng * NR_SHORTCUTS_PER_LNG) / NR_SHORTCUTS_PER_LNG
        end = floor(max_lng * NR_SHORTCUTS_PER_LNG) / NR_SHORTCUTS_PER_LNG
        while current < end:
            output_list.append(current)
            current += step

        output_list.append(end)
        return output_list

    def latitudes_to_check(max_lat, min_lat):
        output_list = []
        step = 1 / NR_SHORTCUTS_PER_LAT
        current = ceil(min_lat * NR_SHORTCUTS_PER_LAT) / NR_SHORTCUTS_PER_LAT
        end = floor(max_lat * NR_SHORTCUTS_PER_LAT) / NR_SHORTCUTS_PER_LAT
        while current < end:
            output_list.append(current)
            current += step

        output_list.append(end)
        return output_list

    def compute_x_intersection(y, x1, x2, y1, y2):
        """returns the x intersection from a horizontal line in y with the line from x1,y1 to x1,y2
        """
        delta_y = y2 - y1
        if delta_y == 0:
            return x1
        return ((y - y1) * (x2 - x1) / delta_y) + x1

    def compute_y_intersection(x, x1, x2, y1, y2):
        """returns the y intersection from a vertical line in x with the line from x1,y1 to x1,y2
        """
        delta_x = x2 - x1
        if delta_x == 0:
            return x1
        return ((x - x1) * (y2 - y1) / delta_x) + y1

    def x_intersections(y, x_coords, y_coords):
        intersects = []
        for i in range(len(y_coords) - 1):
            iplus1 = i + 1
            if y_coords[i] <= y:
                # print('Y1<=y')
                if y_coords[iplus1] > y:
                    # this was a crossing. compute the intersect
                    # print('Y2>y')
                    intersects.append(
                        compute_x_intersection(y, x_coords[i], x_coords[iplus1], y_coords[i], y_coords[iplus1]))
            else:
                # print('Y1>y')
                if y_coords[iplus1] <= y:
                    # this was a crossing. compute the intersect
                    # print('Y2<=y')
                    intersects.append(compute_x_intersection(y, x_coords[i], x_coords[iplus1], y_coords[i],
                                                             y_coords[iplus1]))
        return intersects

    def y_intersections(x, x_coords, y_coords):

        intersects = []
        for i in range(len(y_coords) - 1):
            iplus1 = i + 1
            if x_coords[i] <= x:
                if x_coords[iplus1] > x:
                    # this was a crossing. compute the intersect
                    intersects.append(
                        compute_y_intersection(x, x_coords[i], x_coords[iplus1], y_coords[i], y_coords[iplus1]))
            else:
                if x_coords[iplus1] <= x:
                    # this was a crossing. compute the intersect
                    intersects.append(compute_y_intersection(x, x_coords[i], x_coords[iplus1], y_coords[i],
                                                             y_coords[iplus1]))
        return intersects

    def compute_exact_shortcuts(xmax, xmin, ymax, ymin, line):
        shortcuts_for_line = set()

        # x_longs = binary_reader.x_coords_of(line)
        x_longs, y_longs = ints_of(line)

        # y_longs = binary_reader.y_coords_of(line)
        y_longs.append(y_longs[0])
        x_longs.append(x_longs[0])

        step = 1 / NR_SHORTCUTS_PER_LAT
        # print('checking the latitudes')
        for lat in latitudes_to_check(ymax, ymin):
            # print(lat)
            # print(coordinate_to_longlong(lat))
            # print(y_longs)
            # print(x_intersections(coordinate_to_longlong(lat), x_longs, y_longs))
            # raise ValueError
            intersects = sorted([int2coord(x) for x in
                                 x_intersections(coord2int(lat), x_longs, y_longs)])
            # print(intersects)

            nr_of_intersects = len(intersects)
            if nr_of_intersects % 2 != 0:
                raise ValueError('an uneven number of intersections has been accounted')

            for i in range(0, nr_of_intersects, 2):
                possible_longitudes = []
                # collect all the zones between two intersections [in,out,in,out,...]
                iplus = i + 1
                intersection_in = intersects[i]
                intersection_out = intersects[iplus]
                if intersection_in == intersection_out:
                    # the polygon has a point exactly on the border of a shortcut zone here!
                    # only select the top shortcut if it is actually inside the polygon (point a little up is inside)
                    if contained(coord2int(intersection_in), coord2int(lat) + 1, x_longs,
                                 y_longs):
                        shortcuts_for_line.add((x_shortcut(intersection_in), y_shortcut(lat) - 1))
                    # the bottom shortcut is always selected
                    shortcuts_for_line.add((x_shortcut(intersection_in), y_shortcut(lat)))

                else:
                    # add all the shortcuts for the whole found area of intersection
                    possible_y_shortcut = y_shortcut(lat)

                    # both shortcuts should only be selected when the polygon doesnt stays on the border
                    middle = intersection_in + (intersection_out - intersection_in) / 2
                    if contained(coord2int(middle), coord2int(lat) + 1, x_longs,
                                 y_longs):
                        while intersection_in < intersection_out:
                            possible_longitudes.append(intersection_in)
                            intersection_in += step

                        possible_longitudes.append(intersection_out)

                        # the shortcut above and below of the intersection should be selected!
                        possible_y_shortcut_min1 = possible_y_shortcut - 1
                        for possible_x_coord in possible_longitudes:
                            shortcuts_for_line.add((x_shortcut(possible_x_coord), possible_y_shortcut))
                            shortcuts_for_line.add((x_shortcut(possible_x_coord), possible_y_shortcut_min1))
                    else:
                        # polygon does not cross the border!
                        while intersection_in < intersection_out:
                            possible_longitudes.append(intersection_in)
                            intersection_in += step

                        possible_longitudes.append(intersection_out)

                        # only the shortcut above of the intersection should be selected!
                        for possible_x_coord in possible_longitudes:
                            shortcuts_for_line.add((x_shortcut(possible_x_coord), possible_y_shortcut))

        # print('now all the longitudes to check')
        # same procedure horizontally
        step = 1 / NR_SHORTCUTS_PER_LAT
        for lng in longitudes_to_check(xmax, xmin):
            # print(lng)
            # print(coordinate_to_longlong(lng))
            # print(x_longs)
            # print(x_intersections(coordinate_to_longlong(lng), x_longs, y_longs))
            intersects = sorted([int2coord(y) for y in
                                 y_intersections(coord2int(lng), x_longs, y_longs)])
            # print(intersects)

            nr_of_intersects = len(intersects)
            if nr_of_intersects % 2 != 0:
                raise ValueError('an uneven number of intersections has been accounted')

            possible_latitudes = []
            for i in range(0, nr_of_intersects, 2):
                # collect all the zones between two intersections [in,out,in,out,...]
                iplus = i + 1
                intersection_in = intersects[i]
                intersection_out = intersects[iplus]
                if intersection_in == intersection_out:
                    # the polygon has a point exactly on the border of a shortcut here!
                    # only select the left shortcut if it is actually inside the polygon (point a little left is inside)
                    if contained(coord2int(lng) - 1, coord2int(intersection_in), x_longs,
                                 y_longs):
                        shortcuts_for_line.add((x_shortcut(lng) - 1, y_shortcut(intersection_in)))
                    # the right shortcut is always selected
                    shortcuts_for_line.add((x_shortcut(lng), y_shortcut(intersection_in)))

                else:
                    # add all the shortcuts for the whole found area of intersection
                    possible_x_shortcut = x_shortcut(lng)

                    # both shortcuts should only be selected when the polygon doesnt stays on the border
                    middle = intersection_in + (intersection_out - intersection_in) / 2
                    if contained(coord2int(lng) - 1, coord2int(middle), x_longs,
                                 y_longs):
                        while intersection_in < intersection_out:
                            possible_latitudes.append(intersection_in)
                            intersection_in += step

                        possible_latitudes.append(intersection_out)

                        # both shortcuts right and left of the intersection should be selected!
                        possible_x_shortcut_min1 = possible_x_shortcut - 1
                        for possible_latitude in possible_latitudes:
                            shortcuts_for_line.add((possible_x_shortcut, y_shortcut(possible_latitude)))
                            shortcuts_for_line.add((possible_x_shortcut_min1, y_shortcut(possible_latitude)))

                    else:
                        while intersection_in < intersection_out:
                            possible_latitudes.append(intersection_in)
                            intersection_in += step
                        # only the shortcut right of the intersection should be selected!
                        possible_latitudes.append(intersection_out)

                        for possible_latitude in possible_latitudes:
                            shortcuts_for_line.add((possible_x_shortcut, y_shortcut(possible_latitude)))

        return shortcuts_for_line

    def construct_shortcuts():
        print('building shortucts...')
        print('currently at polygon nr:')
        line = 0
        for xmax, xmin, ymax, ymin in all_boundaries:
            # xmax, xmin, ymax, ymin = boundaries_of(line=line)
            if line % 100 == 0:
                print(line)
                # print([xmax, xmin, ymax, ymin])

            column_nrs = included_shortcut_column_nrs(xmax, xmin)
            row_nrs = included_shortcut_row_nrs(ymax, ymin)

            if big_zone(xmax, xmin, ymax, ymin):

                # print('line ' + str(line))
                # print('This is a big zone! computing exact shortcuts')
                # print('Nr of entries before')
                # print(len(column_nrs) * len(row_nrs))
                # print('columns and rows before optimisation:')
                # print(column_nrs)
                # print(row_nrs)
                # print(ints_of(line))

                # This is a big zone! compute exact shortcuts with the whole polygon points
                shortcuts_for_line = compute_exact_shortcuts(xmax, xmin, ymax, ymin, line)
                # n += len(shortcuts_for_line)

                min_x_shortcut = column_nrs[0]
                max_x_shortcut = column_nrs[-1]
                min_y_shortcut = row_nrs[0]
                max_y_shortcut = row_nrs[-1]
                shortcuts_to_remove = []

                # remove shortcuts from outside the possible/valid area
                for x, y in shortcuts_for_line:
                    if x < min_x_shortcut or x > max_x_shortcut or y < min_y_shortcut or y > max_y_shortcut:
                        shortcuts_to_remove.append((x, y))

                for s in shortcuts_to_remove:
                    shortcuts_for_line.remove(s)

                # print('and after:')
                # print(len(shortcuts_for_line))
                # print(shortcuts_for_line)
                # column_nrs_after = set()
                # row_nrs_after = set()
                # for x, y in shortcuts_for_line:
                #     column_nrs_after.add(x)
                #     row_nrs_after.add(y)
                # print(column_nrs_after)
                # print(row_nrs_after)
                # print(shortcuts_for_line)

                if len(shortcuts_for_line) > len(column_nrs) * len(row_nrs):
                    raise ValueError(
                        'there are more shortcuts than before now. there is something wrong with the algorithm!')
                if len(shortcuts_for_line) < 3:
                    raise ValueError('algorithm not valid! less than 3 zones detected (should be at least 3)')

            else:
                shortcuts_for_line = []
                for column_nr in column_nrs:
                    for row_nr in row_nrs:
                        shortcuts_for_line.append((column_nr, row_nr))
                        # print(shortcuts_for_line)

            for shortcut in shortcuts_for_line:
                shortcuts[shortcut] = shortcuts.get(shortcut, []) + [line]

            line += 1
            # print('collected entries:')
            # print(n)

    start_time = datetime.now()
    construct_shortcuts()
    end_time = datetime.now()
    print('calculating the shortcuts took:', end_time - start_time, '\n')

    # there are two floats per coordinate (lng, lat)
    nr_of_floats = 2 * sum(all_lengths)

    # write number of entries in shortcut field (x,y)
    nr_of_entries_in_shortcut = []
    shortcut_entries = []
    amount_filled_shortcuts = 0

    def sort_poly_shortcut(poly_nrs):
        # TODO write test
        # the list of polygon ids in each shortcut is sorted after freq. of appearance of their zone id
        # this is critical for ruling out zones faster
        # (as soon as just polygons of one zone are left this zone can be returned)
        # only around 5% of all shortcuts include polygons from more than one zone
        # in most of those cases there are only two types of zones (= entries in counted_zones) and one of them
        # has only one entry (important to check the zone with one entry first!).
        polygon_ids = [poly_zone_ids[poly_nr] for poly_nr in poly_nrs]
        id_freq = [polygon_ids.count(id) for id in polygon_ids]
        zipped = list(zip(poly_nrs, polygon_ids, id_freq))
        # also make sure polygons with the same zone freq. are ordered after their zone id
        # (polygons from different zones should not get mixed up)
        sort = sorted((sorted(zipped, key=lambda x: x[1])), key=lambda x: x[2])
        return [x[0] for x in sort]  # take only the polygon nrs

    # count how many shortcut addresses will be written:
    # flatten out the shortcuts in one list in the order they are going to be written inside the polygon file
    for x in range(360 * NR_SHORTCUTS_PER_LNG):
        for y in range(180 * NR_SHORTCUTS_PER_LAT):
            try:
                shortcuts_this_entry = shortcuts[(x, y)]
                shortcut_entries.append(sort_poly_shortcut(shortcuts_this_entry))
                amount_filled_shortcuts += 1
                nr_of_entries_in_shortcut.append(len(shortcuts_this_entry))
                # print((x,y,this_lines_shortcuts))
            except KeyError:
                nr_of_entries_in_shortcut.append(0)

    amount_of_shortcuts = len(nr_of_entries_in_shortcut)
    print_shortcut_statistics()

    if amount_of_shortcuts != 360 * 180 * NR_SHORTCUTS_PER_LNG * NR_SHORTCUTS_PER_LAT:
        print(amount_of_shortcuts)
        raise ValueError('this number of shortcut zones is wrong')

    print('The number of filled shortcut zones are:', amount_filled_shortcuts, '(=',
          round((amount_filled_shortcuts / amount_of_shortcuts) * 100, 2), '% of all shortcuts)')

    # for every shortcut <H and <I is written (nr of entries and address)
    shortcut_space = 360 * NR_SHORTCUTS_PER_LNG * 180 * NR_SHORTCUTS_PER_LAT * (NR_BYTES_H + NR_BYTES_I)
    for nr in nr_of_entries_in_shortcut:
        # every line in every shortcut takes up 2bytes
        shortcut_space += NR_BYTES_H * nr

    print('The number of polygons is:', nr_of_lines)
    print('The number of floats in all the polygons is (2 per point):', nr_of_floats)

    path = 'poly_nr2zone_id.bin'
    print('writing file', path)
    output_file = open(path, 'wb')
    for zone_id in poly_nr2zone_id:
        output_file.write(pack(b'<H', zone_id))
    output_file.close()

    print('Done\n')
    # write zone_ids
    path = 'poly_zone_ids.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for zone_id in poly_zone_ids:
        output_file.write(pack(b'<H', zone_id))
    output_file.close()

    # write boundary_data
    path = 'poly_max_values.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for xmax, xmin, ymax, ymin in all_boundaries:
        output_file.write(pack(b'<iiii', coord2int(xmax), coord2int(xmin), coord2int(ymax), coord2int(ymin)))
    output_file.close()

    # write polygon_data, addresses and number of values
    path = 'poly_data.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    addresses = []
    i = 0
    for x_coords, y_coords in all_coords:
        addresses.append(output_file.tell())
        if all_lengths[i] != len(x_coords):
            raise ValueError('x_coords do not have the expected length!', all_lengths[i], len(x_coords))
        for x in x_coords:
            output_file.write(pack(b'<i', coord2int(x)))
        for y in y_coords:
            output_file.write(pack(b'<i', coord2int(y)))
        i += 1
    output_file.close()

    path = 'poly_adr2data.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for adr in addresses:
        output_file.write(pack(b'<I', adr))
    output_file.close()

    path = 'poly_coord_amount.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for length in all_lengths:
        output_file.write(pack(b'<I', length))
    output_file.close()

    # [SHORTCUT AREA]
    # write all nr of entries
    path = 'shortcuts_entry_amount.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for nr in nr_of_entries_in_shortcut:
        if nr > 300:
            raise ValueError("There are too many polygons in this shortcut:", nr)
        output_file.write(pack(b'<H', nr))
    output_file.close()

    # write  Address of first Polygon_nr  in shortcut field (x,y)
    # Attention: 0 is written when no entries are in this shortcut
    adr = 0
    path = 'shortcuts_adr2data.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for nr in nr_of_entries_in_shortcut:
        if nr == 0:
            output_file.write(pack(b'<I', 0))
        else:
            output_file.write(pack(b'<I', adr))
            # each line_nr takes up 2 bytes of space
            adr += 2 * nr
    output_file.close()

    # write Line_Nrs for every shortcut
    path = 'shortcuts_data.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for entries in shortcut_entries:
        for entry in entries:
            if entry > nr_of_lines:
                raise ValueError(entry)
            output_file.write(pack(b'<H', entry))
    output_file.close()

    # write corresponding zone id for every shortcut (iff unique)
    path = 'shortcuts_unique_id.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    if poly_zone_ids[-1] >= INVALID_ZONE_ID:
        raise ValueError(
            'There are too many zones for this data type (H). The shortcuts_unique_id file need a Invalid Id!')
    for x in range(360 * NR_SHORTCUTS_PER_LNG):
        for y in range(180 * NR_SHORTCUTS_PER_LAT):
            try:
                shortcuts_this_entry = shortcuts[(x, y)]
                unique_id = poly_zone_ids[shortcuts_this_entry[0]]
                for nr in shortcuts_this_entry:
                    if poly_zone_ids[nr] != unique_id:
                        # there is a polygon from a different zone (hence an invalid id should be written)
                        unique_id = INVALID_ZONE_ID
                        break
                output_file.write(pack(b'<H', unique_id))
            except KeyError:
                # also write an Invalid Id when there is no polygon at all
                output_file.write(pack(b'<H', INVALID_ZONE_ID))

    output_file.close()
    # [HOLE AREA, Y = number of holes (very few: around 22)]
    hole_space = 0

    # '<H' for every hole store the related line
    path = 'hole_poly_ids.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    i = 0
    for line in polynrs_of_holes:
        if line > nr_of_lines:
            raise ValueError(line, nr_of_lines)
        output_file.write(pack(b'<H', line))
        i += 1
    hole_space += output_file.tell()
    output_file.close()

    if i > amount_of_holes:
        raise ValueError('There are more related lines than holes.')

    # '<H'  Y times [H unsigned short: nr of values (coordinate PAIRS! x,y in int32 int32) in this hole]
    path = 'hole_coord_amount.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for length in all_hole_lengths:
        output_file.write(pack(b'<H', length))
    hole_space += output_file.tell()
    output_file.close()

    # '<I' Y times [ I unsigned int: absolute address of the byte where the data of that hole starts]
    adr = 0
    path = 'hole_adr2data.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for length in all_hole_lengths:
        output_file.write(pack(b'<I', adr))
        # each pair of points takes up 8 bytes of space
        adr += 2 * NR_BYTES_I * length
    hole_space += output_file.tell()
    output_file.close()

    # Y times [ 2x i signed ints for every hole: x coords, y coords ]
    # write hole polygon_data
    path = 'hole_data.bin'
    print('writing file "', path, '"')
    output_file = open(path, 'wb')
    for x_coords, y_coords in all_holes:
        for x in x_coords:
            output_file.write(pack(b'<i', coord2int(x)))
        for y in y_coords:
            output_file.write(pack(b'<i', coord2int(y)))
    hole_space += output_file.tell()
    output_file.close()

    polygon_space = nr_of_floats * NR_BYTES_I
    total_space = polygon_space + hole_space + shortcut_space

    print('the polygon data makes up', percent(polygon_space, total_space), '% of the data')
    print('the shortcuts make up', percent(shortcut_space, total_space), '% of the data')
    print('holes make up', percent(hole_space, total_space), '% of the data')
    print('Success!')
    return