
uk.recurse.geocoding.reverse.SortTileRecursive Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of reverse-country-code Show documentation
Show all versions of reverse-country-code Show documentation
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 extends Geometry> 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