Skip to content

Commit

Permalink
Merge pull request #898 from conveyal/wgs-mercator-buffer
Browse files Browse the repository at this point in the history
Additional coordinate stability considerations
  • Loading branch information
abyrd authored Nov 2, 2023
2 parents 4397ac7 + 1ef4141 commit 862ae15
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 6 deletions.
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

0 comments on commit 862ae15

Please sign in to comment.