Skip to content

Commit

Permalink
Combine WGS84 to web Mercator functions
Browse files Browse the repository at this point in the history
WebMercatorGridPointSet methods now call static Grid functions with zoom.
All functions are now using standard Java Math (not FastMath).
  • Loading branch information
abyrd committed Oct 16, 2023
1 parent 1eaa461 commit 8b1fdce
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 45 deletions.
32 changes: 16 additions & 16 deletions src/main/java/com/conveyal/r5/analyst/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.csvreader.CsvReader;
import com.google.common.io.LittleEndianDataInputStream;
import com.google.common.io.LittleEndianDataOutputStream;
import org.apache.commons.math3.util.FastMath;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.io.AbstractGridFormat;
Expand Down Expand Up @@ -64,14 +63,9 @@

import static com.conveyal.gtfs.util.Util.human;
import static com.conveyal.r5.common.GeometryUtils.checkWgsEnvelopeSize;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.Double.parseDouble;
import static org.apache.commons.math3.util.FastMath.atan;
import static org.apache.commons.math3.util.FastMath.cos;
import static org.apache.commons.math3.util.FastMath.log;
import static org.apache.commons.math3.util.FastMath.sinh;
import static org.apache.commons.math3.util.FastMath.tan;
import static java.lang.Math.*;

/**
* Class that represents a grid of opportunity counts in the spherical Mercator "projection" at a given zoom level.
Expand Down Expand Up @@ -462,6 +456,7 @@ public int featureCount() {

/** Like lonToPixel but returns fractional values for positions within a pixel instead of integer pixel numbers. */
public static double lonToFractionalPixel (double lon, int zoom) {
// Factor of 256 yields a pixel value rather than the tile number.
return (lon + 180) / 360 * Math.pow(2, zoom) * 256;
}

Expand All @@ -474,12 +469,13 @@ public static int lonToPixel (double lon, int zoom) {
}

/**
* Return the longitude of the west edge of any pixel at the given zoom level and x pixel number measured from the
* west edge of the world (assuming an integer x pixel number). Noninteger x pixel coordinates will return
* WGS84 locations within that pixel.
* Given an integer web Mercator pixel number, return the longitude in degrees of the west edge of that pixel at
* the given zoom level measured from the west edge of the world (not relative to this grid or to any particular
* tile). Given a non-integer web Mercator pixel number, return WGS84 locations within that pixel.
* Naming should somehow be revised to clarify that it doesn't return the center of the pixel.
*/
public static double pixelToLon (double xPixel, int zoom) {
return xPixel / (Math.pow(2, zoom) * 256) * 360 - 180;
return xPixel / (pow(2, zoom) * 256) * 360 - 180;
}

/**
Expand All @@ -492,7 +488,7 @@ public static double pixelToCenterLon (int xPixel, int zoom) {

/** Like latToPixel but returns fractional values for positions within a pixel instead of integer pixel numbers. */
public static double latToFractionalPixel (double lat, int zoom) {
double latRad = FastMath.toRadians(lat);
final double latRad = toRadians(lat);
return (1 - log(tan(latRad) + 1 / cos(latRad)) / Math.PI) * Math.pow(2, zoom - 1) * 256;
}

Expand All @@ -502,12 +498,16 @@ public static int latToPixel (double lat, int zoom) {
}

/**
* Return the latitude of the north edge of any pixel at the given zoom level and y coordinate relative to the top
* edge of the world (assuming an integer pixel). Noninteger pixels will return locations within the pixel.
* We're using FastMath here, because the built-in math functions were taking a large amount of time in profiling.
* Given an integer web Mercator pixel number, return the latitude in degrees of the north edge of that pixel at the
* given zoom level relative to the top (north) edge of the world (not relative to this grid or to any particular
* tile). Given a non-integer web Mercator pixel number, return WGS84 locations within that pixel.
*
* TODO Profile this some time because we had versions using both FastMath and built-in Math functions.
* The difference should be less significant these days. Java now has a StrictMath and the normal Math is optimized.
*/
public static double pixelToLat (double yPixel, int zoom) {
return FastMath.toDegrees(atan(sinh(Math.PI - (yPixel / 256d) / Math.pow(2, zoom) * 2 * Math.PI)));
final double tile = yPixel / 256d;
return toDegrees(atan(sinh(PI - tile * PI * 2 / pow(2, zoom))));
}

/**
Expand Down
37 changes: 8 additions & 29 deletions src/main/java/com/conveyal/r5/analyst/WebMercatorGridPointSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,54 +150,33 @@ public TIntList getPointsInEnvelope (Envelope envelopeFixedDegrees) {
}

// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Mathematics
// FIXME Grid.java has seemingly identical definitions of these same mercator-to-wgs methods.
// These methods should just be wrappers that pass in this WebMercatorGridPointSet's zoom level.
// Grid also has methods that distinguish between pixel corner and center. Those corner methods should be renamed.
// WebMercatorGridPointSet, Grid, and WebMercatorExtents are in the same package and should share methods.

/**
* Return the x pixel number containing the given longitude at this grid's zoom level, relative to the left edge
* of the world (not relative to this grid or to any particular tile).
* TODO This method could be reusable and static if zoom level was a parameter. And moved to WebMercatorExtents.
* See com.conveyal.r5.analyst.Grid#lonToPixel(double, int)
*/
public int lonToPixel (double lon) {
// factor of 256 is to get a pixel value not a tile number
return (int) ((lon + 180) / 360 * Math.pow(2, zoom) * 256);
return Grid.lonToPixel(lon, zoom);
}

/**
* Return the y pixel number containing the given latitude at this grid's zoom level, relative to the top edge of
* the world (not relative to this grid or to any particular tile).
* TODO This method could be reusable and static if zoom level was a parameter. And moved to WebMercatorExtents.
* See com.conveyal.r5.analyst.Grid#latToPixel(double, int)
*/
public int latToPixel (double lat) {
double invCos = 1 / Math.cos(Math.toRadians(lat));
double tan = Math.tan(Math.toRadians(lat));
double ln = Math.log(tan + invCos);
return (int) ((1 - ln / Math.PI) * Math.pow(2, zoom - 1) * 256);
return Grid.latToPixel(lat, zoom);
}

/**
* Return the longitude in degrees of the west edge of any pixel at the specified x coordinate relative to the left
* edge of the world (not relative to this grid or to any particular tile), at this grid's zoom level.
* TODO This method could be reusable and static if zoom level was a parameter.
* It should probably also be renamed to clarify that it doesn't return the center of the pixel.
* Another equivalent method is found in Grid, and should probably be merged with this one and WebMercatorExtents.
* See com.conveyal.r5.analyst.Grid#pixelToLon(double, int)
*/
public double pixelToLon (double x) {
return x / (Math.pow(2, zoom) * 256) * 360 - 180;
return Grid.pixelToLon(x, zoom);
}

/**
* Return the latitude in degrees of the north edge of any pixel at the specified y coordinate relative to the top
* edge of the world (not relative to this grid or to any particular tile), at this grid's zoom level.
* TODO This method could be reusable and static if zoom level was a parameter.
* It should probably also be renamed to clarify that it doesn't return the center of the pixel.
* Another equivalent method is found in Grid, and should probably be merged with this one and WebMercatorExtents.
* See com.conveyal.r5.analyst.Grid#pixelToLat(double, int)
*/
public double pixelToLat (double y) {
double tile = y / 256d;
return Math.toDegrees(Math.atan(Math.sinh(Math.PI - tile * Math.PI * 2 / Math.pow(2, zoom))));
return Grid.pixelToLat(y, zoom);
}

@Override
Expand Down

0 comments on commit 8b1fdce

Please sign in to comment.