Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional coordinate stability considerations #898

Merged
merged 2 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/main/java/com/conveyal/r5/analyst/FreeFormPointSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@ public Envelope getWgsEnvelope () {
public WebMercatorExtents getWebMercatorExtents () {
final int DEFAULT_ZOOM = 9;
Envelope wgsEnvelope = this.getWgsEnvelope();
WebMercatorExtents webMercatorExtents = WebMercatorExtents.forWgsEnvelope(wgsEnvelope, DEFAULT_ZOOM);
return webMercatorExtents;
return WebMercatorExtents.forBufferedWgsEnvelope(wgsEnvelope, DEFAULT_ZOOM);
}

/** Construct a freeform point set containing one opportunity at each specified geographic coordinate. */
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/conveyal/r5/analyst/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public Grid (WebMercatorExtents extents) {
* @param wgsEnvelope Envelope of grid, in absolute WGS84 lat/lon coordinates
*/
public Grid (int zoom, Envelope wgsEnvelope) {
this(WebMercatorExtents.forWgsEnvelope(wgsEnvelope, zoom));
this(WebMercatorExtents.forBufferedWgsEnvelope(wgsEnvelope, zoom));
}

public static class PixelWeight {
Expand Down Expand Up @@ -618,7 +618,7 @@ public static List<Grid> fromCsv(InputStreamProvider csvInputStreamProvider,
reader.close();

checkWgsEnvelopeSize(envelope, "CSV points");
WebMercatorExtents extents = WebMercatorExtents.forWgsEnvelope(envelope, zoom);
WebMercatorExtents extents = WebMercatorExtents.forBufferedWgsEnvelope(envelope, zoom);
checkPixelCount(extents, numericColumns.size());

if (progressListener != null) {
Expand Down Expand Up @@ -690,7 +690,7 @@ public static List<Grid> fromShapefile (File shapefile, int zoom, ProgressListen
ShapefileReader reader = new ShapefileReader(shapefile);
Envelope envelope = reader.wgs84Bounds();
checkWgsEnvelopeSize(envelope, "Shapefile");
WebMercatorExtents extents = WebMercatorExtents.forWgsEnvelope(envelope, zoom);
WebMercatorExtents extents = WebMercatorExtents.forBufferedWgsEnvelope(envelope, zoom);
List<String> numericAttributes = reader.numericAttributes();
Set<String> uniqueNumericAttributes = new HashSet<>(numericAttributes);
if (uniqueNumericAttributes.size() != numericAttributes.size()) {
Expand Down Expand Up @@ -772,7 +772,7 @@ public double getOpportunityCount (int i) {
public static Grid fromFreeForm (FreeFormPointSet freeForm, int zoom) {
// TODO make and us a strongly typed WgsEnvelope class here and in various places
Envelope wgsEnvelope = freeForm.getWgsEnvelope();
WebMercatorExtents webMercatorExtents = WebMercatorExtents.forWgsEnvelope(wgsEnvelope, zoom);
WebMercatorExtents webMercatorExtents = WebMercatorExtents.forBufferedWgsEnvelope(wgsEnvelope, zoom);
Grid grid = new Grid(webMercatorExtents);
grid.name = freeForm.name;
for (int f = 0; f < freeForm.featureCount(); f++) {
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/conveyal/r5/analyst/WebMercatorExtents.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ public static WebMercatorExtents forTrimmedWgsEnvelope (Envelope wgsEnvelope, in
return WebMercatorExtents.forWgsEnvelope(wgsEnvelope, zoom);
}

/**
* The opposite of forTrimmedWgsEnvelope: makes the envelope a tiny bit bigger before constructing the extents.
* This helps deal with numerical imprecision where we want to be sure all points within a supplied envelope will
* fall inside cells of the resulting web Mercator grid.
*/
public static WebMercatorExtents forBufferedWgsEnvelope (Envelope wgsEnvelope, int zoom) {
// Expand a protective copy of the envelope slightly.
wgsEnvelope = wgsEnvelope.copy();
wgsEnvelope.expandBy(WGS_EPSILON);
return WebMercatorExtents.forWgsEnvelope(wgsEnvelope, zoom);
}

/**
* Produces a new Envelope in WGS84 coordinates that tightly encloses the pixels of this WebMercatorExtents.
* The edges of that Envelope will run exactly down the borders between neighboring web Mercator pixels.
Expand Down