davidmoten / grumpy

OGC WMS server allowing custom rendered layers in java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problem with creating Rectangle based on 4 coordinates from predicted Positions

KrazyD opened this issue · comments

I'm trying to create com.github.davidmoten.rtree2.geometry.Geometries.rectangle from coordinates com.github.davidmoten.grumpy.core.Position with following code:

Position from = Position.create(90D, 179D);
int DIR_NORTH = 0;
int DIR_SOUTH = 180;
int DIR_EAST = 90;
int DIR_WEST = 270;
double distanceKm = 2.0D;
Position north = from.predict(distanceKm, DIR_NORTH);
Position south = from.predict(distanceKm, DIR_SOUTH);
Position east = from.predict(distanceKm, DIR_EAST);
Position west = from.predict(distanceKm, DIR_WEST);
return rectangle(south.getLat(), west.getLon(), north.getLat(), east.getLon());

But, when create Position.from(90D, -179D), east.getLon() give -89, while west.getLon() give 90.9. In this case rectangle creation throw IllegalArgumentException() in constructor of RectangleDouble(). A similar exception i am getting when create Position with positive longitude.
I have not yet been able to figure out which formula is used in the predict() method. This seems to be the formula for finding bearing.

Could you, please, help me to figure out, how to fix my problem creating rectangle given longitude and latitude.

Sorry @KrazyD I missed this. I'll have a look.

by setting latitude to 90 you are on the North Pole. That is a singularity for predictions based on direction because north, south, east, west are meaningless or ambiguous at that point. The relevant code is in https://github.com/davidmoten/grumpy/blob/master/grumpy-core/src/main/java/com/github/davidmoten/grumpy/core/Position.java:

public final Position predict(double distanceKm, double courseDegrees) {
assertWithMsg(alt == 0.0, "Predictions only valid for Earth's surface");
double dr = distanceKm / EARTH_RADIUS_KM;
double latR = toRadians(lat);
double lonR = toRadians(lon);
double courseR = toRadians(courseDegrees);
double lat2Radians = asin(sin(latR) * cos(dr) + cos(latR) * sin(dr) * cos(courseR));
double lon2Radians = atan2(sin(courseR) * sin(dr) * cos(latR), cos(dr) - sin(latR)
* sin(lat2Radians));
double lon3Radians = mod(lonR + lon2Radians + PI, 2 * PI) - PI;
return new Position(FastMath.toDegrees(lat2Radians), FastMath.toDegrees(lon3Radians));
}