All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.recurse.geocoding.reverse.SortTileRecursive Maven / Gradle / Ivy

Go to download

A reverse geocoder that converts latitude and longitude coordinates to information about a country such as names, ISO codes and locales.

The newest version!
package uk.recurse.geocoding.reverse;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

// algorithm paper: http://www.dtic.mil/dtic/tr/fulltext/u2/a324493.pdf
class SortTileRecursive {

    private static final int PAGE_SIZE = 16;
    private static final Comparator X_COORDINATE =
            Comparator.comparingDouble(geometry -> geometry.boundingBox().centroidLongitude());
    private static final Comparator Y_COORDINATE =
            Comparator.comparingDouble(geometry -> geometry.boundingBox().centroidLatitude());

    static MultiPolygon pack(Stream rectangles) {
        List packed = pack(rectangles.collect(toList()));
        return new MultiPolygon(packed.toArray(new Geometry[0]));
    }

    static List pack(List rectangles) {
        int leafPages = ceilDiv(rectangles.size(), PAGE_SIZE);
        if (leafPages <= 1) {
            return rectangles;
        }
        int verticalSlices = ceilSqrt(leafPages);
        List nodes = new ArrayList<>(leafPages);
        rectangles.sort(X_COORDINATE);
        for (List verticalSlice : partition(rectangles, verticalSlices)) {
            verticalSlice.sort(Y_COORDINATE);
            int runs = ceilDiv(verticalSlice.size(), PAGE_SIZE);
            for (List run : partition(verticalSlice, runs)) {
                nodes.add(new MultiPolygon(run.toArray(new Geometry[0])));
            }
        }
        return pack(nodes);
    }

    private static  List> partition(List list, int n) {
        int size = ceilDiv(list.size(), n);
        List> partitions = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            int start = i * size;
            int end = Math.min(start + size, list.size());
            partitions.add(list.subList(start, end));
        }
        return partitions;
    }

    private static int ceilDiv(double x, double y) {
        return (int) Math.ceil(x / y);
    }

    private static int ceilSqrt(double a) {
        return (int) Math.ceil(Math.sqrt(a));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy