Point: Store coordinate as pair of double, rather than 1E6 ints.

This makes the lat/lon member variables private and adds 1E6 variants for getters and the static constructor.
Also, Location now stores a Point for its coordinate, rather than 1E6 ints. The 1E6-based constructors have been removed.
This commit is contained in:
Andreas Schildbach 2018-11-15 21:59:38 +01:00
parent a7f6abc4b9
commit e6474db222
49 changed files with 514 additions and 462 deletions

View file

@ -477,12 +477,11 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
}
private void appendXmlCoordRequestParameters(final HttpUrl.Builder url, final EnumSet<LocationType> types,
final int lat, final int lon, final int maxDistance, final int maxLocations) {
final Point coord, final int maxDistance, final int maxLocations) {
appendCommonRequestParams(url, "XML");
url.addEncodedQueryParameter("coord",
ParserUtils.urlEncode(
String.format(Locale.ENGLISH, "%2.6f:%2.6f:WGS84", latLonToDouble(lon), latLonToDouble(lat)),
requestUrlEncoding));
url.addEncodedQueryParameter("coord", ParserUtils.urlEncode(
String.format(Locale.ENGLISH, "%2.6f:%2.6f:WGS84", coord.getLonAsDouble(), coord.getLatAsDouble()),
requestUrlEncoding));
if (useStringCoordListOutputFormat)
url.addEncodedQueryParameter("coordListOutputFormat", "STRING");
url.addEncodedQueryParameter("max", Integer.toString(maxLocations != 0 ? maxLocations : 50));
@ -500,10 +499,10 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
}
}
protected NearbyLocationsResult xmlCoordRequest(final EnumSet<LocationType> types, final int lat, final int lon,
protected NearbyLocationsResult xmlCoordRequest(final EnumSet<LocationType> types, final Point coord,
final int maxDistance, final int maxStations) throws IOException {
final HttpUrl.Builder url = coordEndpoint.newBuilder();
appendXmlCoordRequestParameters(url, types, lat, lon, maxDistance, maxStations);
appendXmlCoordRequestParameters(url, types, coord, maxDistance, maxStations);
final AtomicReference<NearbyLocationsResult> result = new AtomicReference<>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -572,10 +571,10 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return result.get();
}
protected NearbyLocationsResult mobileCoordRequest(final EnumSet<LocationType> types, final int lat, final int lon,
protected NearbyLocationsResult mobileCoordRequest(final EnumSet<LocationType> types, final Point coord,
final int maxDistance, final int maxStations) throws IOException {
final HttpUrl.Builder url = coordEndpoint.newBuilder();
appendXmlCoordRequestParameters(url, types, lat, lon, maxDistance, maxStations);
appendXmlCoordRequestParameters(url, types, coord, maxDistance, maxStations);
final AtomicReference<NearbyLocationsResult> result = new AtomicReference<>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -836,8 +835,8 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
@Override
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.hasLocation())
return xmlCoordRequest(types, location.lat, location.lon, maxDistance, maxLocations);
if (location.hasCoord())
return xmlCoordRequest(types, location.coord, maxDistance, maxLocations);
if (location.type != LocationType.STATION)
throw new IllegalArgumentException("cannot handle: " + location.type);
@ -1964,10 +1963,6 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return P_STATION_NAME_WHITESPACE.matcher(name).replaceAll(" ");
}
protected static double latLonToDouble(final int value) {
return (double) value / 1000000;
}
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
@Nullable TripOptions options) {
@ -2810,7 +2805,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
if ("WGS84".equals(coordParts[2])) {
final int lat = (int) Math.round(Double.parseDouble(coordParts[1]));
final int lon = (int) Math.round(Double.parseDouble(coordParts[0]));
coords = new Point(lat, lon);
coords = Point.from1E6(lat, lon);
} else {
coords = null;
}
@ -2934,7 +2929,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
while (XmlPullUtil.optEnter(pp, "itdCoordinateBaseElem")) {
final int lon = (int) Math.round(Double.parseDouble(XmlPullUtil.valueTag(pp, "x")));
final int lat = (int) Math.round(Double.parseDouble(XmlPullUtil.valueTag(pp, "y")));
path.add(new Point(lat, lon));
path.add(Point.from1E6(lat, lon));
XmlPullUtil.skipExit(pp, "itdCoordinateBaseElem");
}
@ -2951,7 +2946,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
final String[] parts = coordStr.split(",");
final int lat = (int) Math.round(Double.parseDouble(parts[1]));
final int lon = (int) Math.round(Double.parseDouble(parts[0]));
return new Point(lat, lon);
return Point.from1E6(lat, lon);
}
private Point processCoordAttr(final XmlPullParser pp) {
@ -2965,7 +2960,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
if (!"WGS84".equals(mapName))
return null;
return new Point(y, x);
return Point.from1E6(y, x);
}
private Fare processItdGenericTicketGroup(final XmlPullParser pp, final String net, final Currency currency)
@ -3029,10 +3024,11 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
private void appendLocationParams(final HttpUrl.Builder url, final Location location, final String paramSuffix) {
final String name = locationValue(location);
if ((location.type == LocationType.ADDRESS || location.type == LocationType.COORD) && location.hasLocation()) {
if ((location.type == LocationType.ADDRESS || location.type == LocationType.COORD) && location.hasCoord()) {
url.addEncodedQueryParameter("type_" + paramSuffix, "coord");
url.addEncodedQueryParameter("name_" + paramSuffix, ParserUtils.urlEncode(
String.format(Locale.ENGLISH, "%.6f:%.6f", location.lon / 1E6, location.lat / 1E6) + ":WGS84",
String.format(Locale.ENGLISH, "%.6f:%.6f", location.getLonAsDouble(), location.getLatAsDouble())
+ ":WGS84",
requestUrlEncoding));
} else if (name != null) {
url.addEncodedQueryParameter("type_" + paramSuffix, locationTypeValue(location));

View file

@ -57,6 +57,7 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Point;
import de.schildbach.pte.dto.Position;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.QueryDeparturesResult;
@ -131,8 +132,8 @@ public abstract class AbstractHafasClientInterfaceProvider extends AbstractHafas
@Override
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.hasLocation())
return jsonLocGeoPos(types, location.lat, location.lon, maxDistance, maxLocations);
if (location.hasCoord())
return jsonLocGeoPos(types, location.coord, maxDistance, maxLocations);
else
throw new IllegalArgumentException("cannot handle: " + location);
}
@ -162,7 +163,7 @@ public abstract class AbstractHafasClientInterfaceProvider extends AbstractHafas
jsonContext.products, jsonContext.walkSpeed, later ? jsonContext.laterContext : jsonContext.earlierContext);
}
protected final NearbyLocationsResult jsonLocGeoPos(final EnumSet<LocationType> types, final int lat, final int lon,
protected final NearbyLocationsResult jsonLocGeoPos(final EnumSet<LocationType> types, final Point coord,
int maxDistance, int maxLocations) throws IOException {
if (maxDistance == 0)
maxDistance = DEFAULT_MAX_DISTANCE;
@ -171,7 +172,8 @@ public abstract class AbstractHafasClientInterfaceProvider extends AbstractHafas
final boolean getStations = types.contains(LocationType.STATION);
final boolean getPOIs = types.contains(LocationType.POI);
final String request = wrapJsonApiRequest("LocGeoPos", "{\"ring\":" //
+ "{\"cCrd\":{\"x\":" + lon + ",\"y\":" + lat + "},\"maxDist\":" + maxDistance + "}," //
+ "{\"cCrd\":{\"x\":" + coord.getLonAs1E6() + ",\"y\":" + coord.getLatAs1E6() + "}," //
+ "\"maxDist\":" + maxDistance + "}," //
+ "\"getStops\":" + getStations + "," //
+ "\"getPOIs\":" + getPOIs + "," //
+ "\"maxLoc\":" + maxLocations + "}", //
@ -411,9 +413,9 @@ public abstract class AbstractHafasClientInterfaceProvider extends AbstractHafas
if (!locations.isEmpty())
return locations.get(0);
}
if (location.hasLocation()) {
final List<Location> locations = jsonLocGeoPos(EnumSet.allOf(LocationType.class), location.lat,
location.lon, 0, 1).locations;
if (location.hasCoord()) {
final List<Location> locations = jsonLocGeoPos(EnumSet.allOf(LocationType.class), location.coord, 0,
1).locations;
if (!locations.isEmpty())
return locations.get(0);
}
@ -805,8 +807,8 @@ public abstract class AbstractHafasClientInterfaceProvider extends AbstractHafas
final JSONObject crd = loc.optJSONObject("crd");
if (crd != null)
return new Location(locationType, id, crd.getInt("y"), crd.getInt("x"), placeAndName[0], placeAndName[1],
products);
return new Location(locationType, id, Point.from1E6(crd.getInt("y"), crd.getInt("x")), placeAndName[0],
placeAndName[1], products);
else
return new Location(LocationType.STATION, id, null, placeAndName[0], placeAndName[1], products);
}

View file

@ -248,9 +248,9 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
final String id = XmlPullUtil.attr(pp, "externalStationNr");
final int x = XmlPullUtil.intAttr(pp, "x");
final int y = XmlPullUtil.intAttr(pp, "y");
final Point coord = Point.from1E6(y, x);
final String[] placeAndName = splitStationName(name);
return new Location(LocationType.STATION, id, y, x, placeAndName[0], placeAndName[1]);
return new Location(LocationType.STATION, id, coord, placeAndName[0], placeAndName[1]);
}
throw new IllegalStateException("cannot handle: " + type);
}
@ -263,7 +263,8 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
name = null;
final int x = XmlPullUtil.intAttr(pp, "x");
final int y = XmlPullUtil.intAttr(pp, "y");
return new Location(LocationType.POI, null, y, x, null, name);
final Point coord = Point.from1E6(y, x);
return new Location(LocationType.POI, null, coord, null, name);
}
throw new IllegalStateException("cannot handle: " + type);
}
@ -276,9 +277,9 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
name = null;
final int x = XmlPullUtil.intAttr(pp, "x");
final int y = XmlPullUtil.intAttr(pp, "y");
final Point coord = Point.from1E6(y, x);
final String[] placeAndName = splitAddress(name);
return new Location(LocationType.ADDRESS, null, y, x, placeAndName[0], placeAndName[1]);
return new Location(LocationType.ADDRESS, null, coord, placeAndName[0], placeAndName[1]);
}
throw new IllegalStateException("cannot handle: " + type);
}
@ -346,23 +347,23 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
if (type == 1) // station
{
final String[] placeAndName = splitStationName(value);
location = new Location(LocationType.STATION, localId, lat, lon, placeAndName[0],
placeAndName[1]);
location = new Location(LocationType.STATION, localId, Point.from1E6(lat, lon),
placeAndName[0], placeAndName[1]);
} else if (type == 2) // address
{
final String[] placeAndName = splitAddress(value);
location = new Location(LocationType.ADDRESS, null, lat, lon, placeAndName[0],
placeAndName[1]);
location = new Location(LocationType.ADDRESS, null, Point.from1E6(lat, lon),
placeAndName[0], placeAndName[1]);
} else if (type == 4) // poi
{
final String[] placeAndName = splitPOI(value);
location = new Location(LocationType.POI, localId, lat, lon, placeAndName[0],
location = new Location(LocationType.POI, localId, Point.from1E6(lat, lon), placeAndName[0],
placeAndName[1]);
} else if (type == 128) // crossing
{
final String[] placeAndName = splitAddress(value);
location = new Location(LocationType.ADDRESS, localId, lat, lon, placeAndName[0],
placeAndName[1]);
location = new Location(LocationType.ADDRESS, localId, Point.from1E6(lat, lon),
placeAndName[0], placeAndName[1]);
} else if (type == 87) {
location = null;
// don't know what to do
@ -1115,7 +1116,7 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
while (XmlPullUtil.test(pp, "Point")) {
final int x = XmlPullUtil.intAttr(pp, "x");
final int y = XmlPullUtil.intAttr(pp, "y");
path.add(new Point(y, x));
path.add(Point.from1E6(y, x));
XmlPullUtil.next(pp);
}
XmlPullUtil.skipExit(pp, "Polyline");
@ -1248,13 +1249,13 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
private static final String locationXml(final Location location) {
if (location.type == LocationType.STATION && location.hasId())
return "<Station externalId=\"" + normalizeStationId(location.id) + "\" />";
else if (location.type == LocationType.POI && location.hasLocation())
return "<Poi type=\"WGS84\" x=\"" + location.lon + "\" y=\"" + location.lat + "\" />";
else if (location.type == LocationType.ADDRESS && location.hasLocation())
return "<Address type=\"WGS84\" x=\"" + location.lon + "\" y=\"" + location.lat + "\" name=\""
+ (location.place != null ? location.place + ", " : "") + location.name + "\" />";
else if (location.type == LocationType.COORD && location.hasLocation())
return "<Coord type=\"WGS84\" x=\"" + location.lon + "\" y=\"" + location.lat + "\" />";
else if (location.type == LocationType.POI && location.hasCoord())
return "<Poi type=\"WGS84\" x=\"" + location.getLonAs1E6() + "\" y=\"" + location.getLatAs1E6() + "\" />";
else if (location.type == LocationType.ADDRESS && location.hasCoord())
return "<Address type=\"WGS84\" x=\"" + location.getLonAs1E6() + "\" y=\"" + location.getLatAs1E6()
+ "\" name=\"" + (location.place != null ? location.place + ", " : "") + location.name + "\" />";
else if (location.type == LocationType.COORD && location.hasCoord())
return "<Coord type=\"WGS84\" x=\"" + location.getLonAs1E6() + "\" y=\"" + location.getLatAs1E6() + "\" />";
else
throw new IllegalArgumentException("cannot handle: " + location);
}
@ -1266,11 +1267,11 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
if (location.type == LocationType.STATION && location.hasId()) {
id.append("@L=").append(normalizeStationId(location.id));
} else if (location.hasLocation()) {
id.append("@X=").append(location.lon);
id.append("@Y=").append(location.lat);
id.append("@O=").append(location.name != null ? location.name
: String.format(Locale.ENGLISH, "%.6f, %.6f", location.lat / 1E6, location.lon / 1E6));
} else if (location.hasCoord()) {
id.append("@X=").append(location.getLonAs1E6());
id.append("@Y=").append(location.getLatAs1E6());
id.append("@O=").append(location.name != null ? location.name : String.format(Locale.ENGLISH, "%.6f, %.6f",
location.getLatAsDouble(), location.getLonAsDouble()));
} else if (location.name != null) {
id.append("@G=").append(location.name);
if (location.type != LocationType.ANY)
@ -1286,7 +1287,7 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
return 1;
if (type == LocationType.POI)
return 4;
if (type == LocationType.COORD || (type == LocationType.ADDRESS && location.hasLocation()))
if (type == LocationType.COORD || (type == LocationType.ADDRESS && location.hasCoord()))
return 16;
if (type == LocationType.ADDRESS && location.name != null)
return 2;
@ -1310,12 +1311,12 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
if (via.type == LocationType.STATION && via.hasId()) {
url.addQueryParameter("REQ0JourneyStops1.0L", via.id);
} else if (via.hasLocation()) {
url.addQueryParameter("REQ0JourneyStops1.0X", Integer.toString(via.lon));
url.addQueryParameter("REQ0JourneyStops1.0Y", Integer.toString(via.lat));
} else if (via.hasCoord()) {
url.addQueryParameter("REQ0JourneyStops1.0X", Integer.toString(via.getLonAs1E6()));
url.addQueryParameter("REQ0JourneyStops1.0Y", Integer.toString(via.getLatAs1E6()));
if (via.name == null)
url.addQueryParameter("REQ0JourneyStops1.0O",
String.format(Locale.ENGLISH, "%.6f, %.6f", via.lat / 1E6, via.lon / 1E6));
String.format(Locale.ENGLISH, "%.6f, %.6f", via.getLatAsDouble(), via.getLonAsDouble()));
} else if (via.name != null) {
url.addEncodedQueryParameter("REQ0JourneyStops1.0G", ParserUtils
.urlEncode(via.name + (via.type != LocationType.ANY ? "!" : ""), requestUrlEncoding));
@ -2029,13 +2030,13 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
if (type == 1) {
final String[] placeAndName = splitStationName(name);
return new Location(LocationType.STATION, null, lat, lon, placeAndName[0], placeAndName[1]);
return new Location(LocationType.STATION, null, Point.from1E6(lat, lon), placeAndName[0], placeAndName[1]);
} else if (type == 2) {
final String[] placeAndName = splitAddress(name);
return new Location(LocationType.ADDRESS, null, lat, lon, placeAndName[0], placeAndName[1]);
return new Location(LocationType.ADDRESS, null, Point.from1E6(lat, lon), placeAndName[0], placeAndName[1]);
} else if (type == 3) {
final String[] placeAndName = splitPOI(name);
return new Location(LocationType.POI, null, lat, lon, placeAndName[0], placeAndName[1]);
return new Location(LocationType.POI, null, Point.from1E6(lat, lon), placeAndName[0], placeAndName[1]);
} else {
throw new IllegalStateException("unknown type: " + type + " " + name);
}
@ -2185,8 +2186,8 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
final int lon = stationInputStream.readIntReverse();
final int lat = stationInputStream.readIntReverse();
return new Location(LocationType.STATION, id != 0 ? Integer.toString(id) : null, lat, lon,
placeAndName[0], placeAndName[1]);
return new Location(LocationType.STATION, id != 0 ? Integer.toString(id) : null,
Point.from1E6(lat, lon), placeAndName[0], placeAndName[1]);
} finally {
stationInputStream.close();
}
@ -2196,23 +2197,23 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
@Override
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.hasLocation())
return nearbyLocationsByCoordinate(types, location.lat, location.lon, maxDistance, maxLocations);
if (location.hasCoord())
return nearbyLocationsByCoordinate(types, location.coord, maxDistance, maxLocations);
else if (location.type == LocationType.STATION && location.hasId())
return nearbyStationsById(location.id, maxDistance);
else
throw new IllegalArgumentException("cannot handle: " + location);
}
protected final NearbyLocationsResult nearbyLocationsByCoordinate(final EnumSet<LocationType> types, final int lat,
final int lon, final int maxDistance, final int maxLocations) throws IOException {
protected final NearbyLocationsResult nearbyLocationsByCoordinate(final EnumSet<LocationType> types,
final Point coord, final int maxDistance, final int maxLocations) throws IOException {
if (types.contains(LocationType.STATION)) {
final HttpUrl.Builder url = queryEndpoint.newBuilder().addPathSegment(apiLanguage + "y");
appendJsonNearbyStationsParameters(url, lat, lon, maxDistance, maxLocations);
appendJsonNearbyStationsParameters(url, coord, maxDistance, maxLocations);
return jsonNearbyLocations(url.build());
} else if (types.contains(LocationType.POI)) {
final HttpUrl.Builder url = queryEndpoint.newBuilder().addPathSegment(apiLanguage + "y");
appendJsonNearbyPOIsParameters(url, lat, lon, maxDistance, maxLocations);
appendJsonNearbyPOIsParameters(url, coord, maxDistance, maxLocations);
return jsonNearbyLocations(url.build());
} else {
return new NearbyLocationsResult(null, Collections.<Location> emptyList());
@ -2239,12 +2240,11 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
private static final Pattern P_XML_NEARBY_STATIONS_COARSE = Pattern.compile("\\G<\\s*St\\s*(.*?)/?>(?:\n|\\z)",
Pattern.DOTALL);
private static final Pattern P_XML_NEARBY_STATIONS_FINE = Pattern.compile(
"" //
+ "evaId=\"(\\d+)\"\\s*" // id
+ "name=\"([^\"]+)\".*?" // name
+ "(?:x=\"(\\d+)\"\\s*)?" // x
+ "(?:y=\"(\\d+)\"\\s*)?" // y
private static final Pattern P_XML_NEARBY_STATIONS_FINE = Pattern.compile("" //
+ "evaId=\"(\\d+)\"\\s*" // id
+ "name=\"([^\"]+)\".*?" // name
+ "(?:x=\"(\\d+)\"\\s*)?" // x
+ "(?:y=\"(\\d+)\"\\s*)?" // y
, Pattern.DOTALL);
private static final Pattern P_XML_NEARBY_STATIONS_MESSAGES = Pattern
.compile("<Err code=\"([^\"]*)\" text=\"([^\"]*)\"");
@ -2276,19 +2276,15 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
final String parsedName = ParserUtils.resolveEntities(mFine.group(2)).trim();
final int parsedLon;
final int parsedLat;
if (mFine.group(3) != null && mFine.group(4) != null) {
parsedLon = Integer.parseInt(mFine.group(3));
parsedLat = Integer.parseInt(mFine.group(4));
} else {
parsedLon = 0;
parsedLat = 0;
}
final Point parsedCoord;
if (mFine.group(3) != null && mFine.group(4) != null)
parsedCoord = Point.from1E6(Integer.parseInt(mFine.group(4)), Integer.parseInt(mFine.group(3)));
else
parsedCoord = null;
final String[] placeAndName = splitStationName(parsedName);
stations.add(new Location(LocationType.STATION, parsedId, parsedLat, parsedLon, placeAndName[0],
placeAndName[1]));
stations.add(
new Location(LocationType.STATION, parsedId, parsedCoord, placeAndName[0], placeAndName[1]));
} else {
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "' on " + url);
}
@ -2297,7 +2293,7 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
return new NearbyLocationsResult(null, stations);
}
protected void appendJsonNearbyStationsParameters(final HttpUrl.Builder url, final int lat, final int lon,
protected void appendJsonNearbyStationsParameters(final HttpUrl.Builder url, final Point coord,
final int maxDistance, final int maxStations) {
url.addQueryParameter("performLocating", "2");
url.addQueryParameter("tpl", "stop2json");
@ -2309,19 +2305,19 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
// density|80
// get_stopweight|yes
// get_infotext|yes
url.addQueryParameter("look_x", Integer.toString(lon));
url.addQueryParameter("look_y", Integer.toString(lat));
url.addQueryParameter("look_x", Integer.toString(coord.getLonAs1E6()));
url.addQueryParameter("look_y", Integer.toString(coord.getLatAs1E6()));
url.addQueryParameter("look_maxno", Integer.toString(maxStations != 0 ? maxStations : 200));
url.addQueryParameter("look_maxdist", Integer.toString(maxDistance != 0 ? maxDistance : 5000));
}
protected void appendJsonNearbyPOIsParameters(final HttpUrl.Builder url, final int lat, final int lon,
final int maxDistance, final int maxStations) {
protected void appendJsonNearbyPOIsParameters(final HttpUrl.Builder url, final Point coord, final int maxDistance,
final int maxStations) {
url.addQueryParameter("performLocating", "4");
url.addQueryParameter("tpl", "poi2json");
url.addQueryParameter("look_pois", ""); // all categories
url.addQueryParameter("look_x", Integer.toString(lon));
url.addQueryParameter("look_y", Integer.toString(lat));
url.addQueryParameter("look_x", Integer.toString(coord.getLonAs1E6()));
url.addQueryParameter("look_y", Integer.toString(coord.getLatAs1E6()));
url.addQueryParameter("look_maxno", Integer.toString(maxStations != 0 ? maxStations : 200));
url.addQueryParameter("look_maxdist", Integer.toString(maxDistance != 0 ? maxDistance : 5000));
}
@ -2353,8 +2349,8 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
if (stopWeight != 0) {
final String[] placeAndName = splitStationName(urlname);
final Set<Product> products = prodclass != -1 ? intToProducts(prodclass) : null;
locations.add(new Location(LocationType.STATION, id, lat, lon, placeAndName[0],
placeAndName[1], products));
locations.add(new Location(LocationType.STATION, id, Point.from1E6(lat, lon),
placeAndName[0], placeAndName[1], products));
}
}
}
@ -2373,7 +2369,8 @@ public abstract class AbstractHafasLegacyProvider extends AbstractHafasProvider
final int lon = poi.getInt("x");
final String[] placeAndName = splitPOI(urlname);
locations.add(new Location(LocationType.POI, id, lat, lon, placeAndName[0], placeAndName[1]));
locations.add(new Location(LocationType.POI, id, Point.from1E6(lat, lon), placeAndName[0],
placeAndName[1]));
}
}

View file

@ -310,8 +310,8 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
private String printLocation(final Location location) {
if (location.hasId())
return location.id;
else if (location.hasLocation())
return (double) (location.lon) / 1E6 + ";" + (double) (location.lat) / 1E6;
else if (location.hasCoord())
return location.getLonAsDouble() + ";" + location.getLatAsDouble();
else
return "";
}
@ -695,9 +695,9 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
// Build url depending of location type.
final HttpUrl.Builder url = url();
if (location.hasLocation()) {
final double lon = location.lon / 1E6;
final double lat = location.lat / 1E6;
if (location.hasCoord()) {
final double lon = location.getLonAsDouble();
final double lat = location.getLatAsDouble();
url.addPathSegment("coords").addPathSegment(lon + ";" + lat);
} else if (location.type == LocationType.STATION) {
if (!location.isIdentified())

View file

@ -112,8 +112,8 @@ public class BayernProvider extends AbstractEfaProvider {
@Override
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.hasLocation())
return mobileCoordRequest(types, location.lat, location.lon, maxDistance, maxLocations);
if (location.hasCoord())
return mobileCoordRequest(types, location.coord, maxDistance, maxLocations);
if (location.type != LocationType.STATION)
throw new IllegalArgumentException("cannot handle: " + location.type);

View file

@ -157,7 +157,7 @@ public class HslProvider extends AbstractNetworkProvider {
final String id = xmlValueTag(pp, "code");
final String name = xmlValueTag(pp, "name_fi");
final Point pt = coordStrToPoint(xmlValueTag(pp, "coords"));
result.set(new Location(LocationType.STATION, id, pt.lat, pt.lon, null, name));
result.set(new Location(LocationType.STATION, id, pt, null, name));
} catch (final XmlPullParserException x) {
throw new ParserException("cannot parse xml: " + bodyPeek, x);
}
@ -175,7 +175,7 @@ public class HslProvider extends AbstractNetworkProvider {
public NearbyLocationsResult queryNearbyLocations(EnumSet<LocationType> types, Location location, int maxDistance,
int maxStations) throws IOException {
final HttpUrl.Builder url = apiUrl("stops_area");
if (!location.hasLocation()) {
if (!location.hasCoord()) {
if (location.type != LocationType.STATION)
throw new IllegalArgumentException("cannot handle: " + location.type);
if (!location.hasId())
@ -209,7 +209,7 @@ public class HslProvider extends AbstractNetworkProvider {
XmlPullUtil.skipExit(pp, "node");
stations.add(new Location(LocationType.STATION, id, pt.lat, pt.lon, place, name));
stations.add(new Location(LocationType.STATION, id, pt, place, name));
}
result.set(new NearbyLocationsResult(header, stations));
@ -384,8 +384,7 @@ public class HslProvider extends AbstractNetworkProvider {
if (shortCode != null)
name = name + " (" + shortCode + ")";
locations
.add(new SuggestedLocation(new Location(type, id, pt.lat, pt.lon, null, name), weight));
locations.add(new SuggestedLocation(new Location(type, id, pt, null, name), weight));
weight -= 1;
}
@ -628,7 +627,7 @@ public class HslProvider extends AbstractNetworkProvider {
LocationType type = LocationType.ANY;
if (code != null)
type = LocationType.STATION;
Location loc = new Location(type, code, pt.lat, pt.lon, stopAddress, name);
Location loc = new Location(type, code, pt, stopAddress, name);
if (path.size() == 0) {
departure = loc;
@ -653,8 +652,8 @@ public class HslProvider extends AbstractNetworkProvider {
if (legType.equals("walk")) {
// ugly hack to set the name of the last arrival
if (arrival != null && arrival.name == null) {
arrival = new Location(arrival.type, arrival.id, arrival.lat, arrival.lon,
arrival.place, to.name);
arrival = new Location(arrival.type, arrival.id, arrival.coord, arrival.place,
to.name);
}
legs.add(new Trip.Individual(Trip.Individual.Type.WALK, departure, departureTime,

View file

@ -232,10 +232,6 @@ public class NegentweeProvider extends AbstractNetworkProvider {
}
}
private Point pointFromLocation(Location location) throws JSONException {
return new Point(location.lat, location.lon);
}
private LocationType locationTypeFromTypeString(String type) throws JSONException {
switch (type) {
case "station":
@ -322,7 +318,7 @@ public class NegentweeProvider extends AbstractNetworkProvider {
private String locationToQueryParameterString(Location loc) {
if (loc.hasId()) {
return loc.id;
} else if (loc.hasLocation()) {
} else if (loc.hasCoord()) {
return loc.getLatAsDouble() + "," + loc.getLonAsDouble();
} else {
return null;
@ -408,18 +404,18 @@ public class NegentweeProvider extends AbstractNetworkProvider {
// First stop
Stop firstStop = stopFromJSONObject(stops.getJSONObject(0));
foundPoints.add(pointFromLocation(firstStop.location));
foundPoints.add(firstStop.location.coord);
// Intermediate stops
LinkedList<Stop> foundStops = new LinkedList<>();
for (int j = 1; j < stops.length() - 1; j++) {
foundStops.add(stopFromJSONObject(stops.getJSONObject(j)));
foundPoints.add(pointFromLocation(foundStops.getLast().location));
foundPoints.add(foundStops.getLast().location.coord);
}
// Last stop
Stop lastStop = stopFromJSONObject(stops.getJSONObject(stops.length() - 1));
foundPoints.add(pointFromLocation(lastStop.location));
foundPoints.add(lastStop.location.coord);
switch (leg.getString("type").toLowerCase()) {
case "scheduled":
@ -578,14 +574,14 @@ public class NegentweeProvider extends AbstractNetworkProvider {
Point locationPoint = Point.fromDouble(latlon.getDouble("lat"), latlon.getDouble("long"));
return new Location(locationTypeFromTypeString(locationType), location.getString("id"), locationPoint.lat,
locationPoint.lon, !(place == null) ? place.optString("name", null) : null, locationName, null);
return new Location(locationTypeFromTypeString(locationType), location.getString("id"), locationPoint,
!(place == null) ? place.optString("name", null) : null, locationName, null);
}
private List<Location> solveAmbiguousLocation(Location location) throws IOException {
if (location.hasId()) {
return Arrays.asList(location);
} else if (location.hasLocation()) {
} else if (location.hasCoord()) {
return queryNearbyLocations(EnumSet.of(location.type), location, -1, -1).locations;
} else if (location.hasName()) {
return queryLocationsByName(location.name, EnumSet.of(location.type));
@ -715,7 +711,7 @@ public class NegentweeProvider extends AbstractNetworkProvider {
public NearbyLocationsResult queryNearbyLocations(EnumSet<LocationType> types, Location location, int maxDistance,
int maxLocations) throws IOException {
// Coordinates are required
if (!location.hasLocation()) {
if (!location.hasCoord()) {
try {
if (location.hasId()) {
location = queryLocationById(location.id);
@ -728,7 +724,7 @@ public class NegentweeProvider extends AbstractNetworkProvider {
return new NearbyLocationsResult(this.resultHeader, NearbyLocationsResult.Status.SERVICE_DOWN);
}
if (location == null || !location.hasLocation()) {
if (location == null || !location.hasCoord()) {
return new NearbyLocationsResult(this.resultHeader, NearbyLocationsResult.Status.INVALID_ID);
}
}
@ -814,7 +810,7 @@ public class NegentweeProvider extends AbstractNetworkProvider {
lineDestinationResult.add(new LineDestination(
new Line(null, departure.getString("operatorName"), lineProduct, mode.getString("name"),
null, Standard.STYLES.get(lineProduct), null, null),
new Location(LocationType.STATION, null, 0, 0, null,
new Location(LocationType.STATION, null, null, null,
departure.getString("destinationName"), EnumSet.of(lineProduct))));
}
@ -864,10 +860,10 @@ public class NegentweeProvider extends AbstractNetworkProvider {
@Override
public QueryTripsResult queryTrips(Location from, @Nullable Location via, Location to, Date date, boolean dep,
@Nullable TripOptions options) throws IOException {
if (!(from.hasId() || from.hasLocation()))
if (!(from.hasId() || from.hasCoord()))
return ambiguousQueryTrips(from, via, to);
if (!(to.hasId() || to.hasLocation()))
if (!(to.hasId() || to.hasCoord()))
return ambiguousQueryTrips(from, via, to);
// Default query options
@ -880,7 +876,7 @@ public class NegentweeProvider extends AbstractNetworkProvider {
new QueryParameter("before", "1"), new QueryParameter("after", "5")));
if (via != null) {
if (!(via.hasId() || via.hasLocation()))
if (!(via.hasId() || via.hasCoord()))
return ambiguousQueryTrips(from, via, to);
queryParameters.add(new QueryParameter("via", locationToQueryParameterString(via)));

View file

@ -53,8 +53,8 @@ public class StvProvider extends AbstractEfaProvider {
@Override
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.hasLocation())
return mobileCoordRequest(types, location.lat, location.lon, maxDistance, maxLocations);
if (location.hasCoord())
return mobileCoordRequest(types, location.coord, maxDistance, maxLocations);
if (location.type != LocationType.STATION)
throw new IllegalArgumentException("cannot handle: " + location.type);

View file

@ -363,9 +363,9 @@ public class VrsProvider extends AbstractNetworkProvider {
// g=p means group by product; not used here
final HttpUrl.Builder url = API_BASE.newBuilder();
url.addQueryParameter("eID", "tx_vrsinfo_ass2_timetable");
if (location.hasLocation()) {
if (location.hasCoord()) {
url.addQueryParameter("r",
String.format(Locale.ENGLISH, "%.6f,%.6f", location.lat / 1E6, location.lon / 1E6));
String.format(Locale.ENGLISH, "%.6f,%.6f", location.getLatAsDouble(), location.getLonAsDouble()));
} else if (location.type == LocationType.STATION && location.hasId()) {
url.addQueryParameter("i", location.id);
} else {
@ -857,15 +857,15 @@ public class VrsProvider extends AbstractNetworkProvider {
}
List<Point> points = new ArrayList<>();
points.add(new Point(segmentOrigin.lat, segmentOrigin.lon));
points.add(segmentOrigin.coord);
if (EXACT_POINTS && segment.has("polygon")) {
parsePolygon(segment.getString("polygon"), points);
} else {
for (Stop intermediateStop : intermediateStops) {
points.add(new Point(intermediateStop.location.lat, intermediateStop.location.lon));
points.add(intermediateStop.location.coord);
}
}
points.add(new Point(segmentDestination.lat, segmentDestination.lon));
points.add(segmentDestination.coord);
if (type.equals("walk")) {
if (departurePlanned == null)
departurePlanned = legs.get(legs.size() - 1).getArrivalTime();
@ -941,8 +941,7 @@ public class VrsProvider extends AbstractNetworkProvider {
String pointsArr[] = polygonStr.split("\\s");
for (String point : pointsArr) {
String latlon[] = point.split(",");
polygonArr.add(new Point((int) Math.round(Double.parseDouble(latlon[0]) * 1E6),
(int) Math.round(Double.parseDouble(latlon[1]) * 1E6)));
polygonArr.add(Point.fromDouble(Double.parseDouble(latlon[0]), Double.parseDouble(latlon[1])));
}
}
}
@ -970,7 +969,7 @@ public class VrsProvider extends AbstractNetworkProvider {
@Override
public Point[] getArea() throws IOException {
return new Point[] { new Point(50937531, 6960279) };
return new Point[] { Point.from1E6(50937531, 6960279) };
}
private static Product productFromLineNumber(String number) {
@ -1113,9 +1112,10 @@ public class VrsProvider extends AbstractNetworkProvider {
place += "-" + location.getString("district");
}
}
final int lat = (int) Math.round(location.optDouble("x", 0) * 1E6);
final int lon = (int) Math.round(location.optDouble("y", 0) * 1E6);
return new LocationWithPosition(new Location(locationType, id, lat, lon, place, name),
final double lat = location.optDouble("x", 0);
final double lon = location.optDouble("y", 0);
final Point coord = Point.fromDouble(lat, lon);
return new LocationWithPosition(new Location(locationType, id, coord, place, name),
position != null ? new Position(position.substring(position.lastIndexOf(" ") + 1)) : null);
}
@ -1124,8 +1124,8 @@ public class VrsProvider extends AbstractNetworkProvider {
return null;
} else if (loc.id != null) {
return loc.id;
} else if (loc.lat != 0 && loc.lon != 0) {
return String.format(Locale.ENGLISH, "%f,%f", loc.lat / 1E6, loc.lon / 1E6);
} else if (loc.coord != null) {
return String.format(Locale.ENGLISH, "%f,%f", loc.getLatAsDouble(), loc.getLonAsDouble());
} else {
SuggestLocationsResult suggestLocationsResult = suggestLocations(loc.name);
final List<Location> suggestedLocations = suggestLocationsResult.getLocations();

View file

@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -39,17 +39,16 @@ public final class Location implements Serializable {
public final LocationType type;
public final @Nullable String id;
public final int lat, lon;
public final @Nullable Point coord;
public final @Nullable String place;
public final @Nullable String name;
public final @Nullable Set<Product> products;
public Location(final LocationType type, final String id, final int lat, final int lon, final String place,
final String name, final Set<Product> products) {
public Location(final LocationType type, final String id, final Point coord, final String place, final String name,
final Set<Product> products) {
this.type = checkNotNull(type);
this.id = id;
this.lat = lat;
this.lon = lon;
this.coord = coord;
this.place = place;
this.name = name;
this.products = products;
@ -59,36 +58,22 @@ public final class Location implements Serializable {
if (type == LocationType.ANY) {
checkArgument(id == null, "type ANY cannot have ID");
} else if (type == LocationType.COORD) {
checkArgument(hasLocation(), "coordinates missing");
checkArgument(hasCoord(), "coordinates missing");
checkArgument(place == null && name == null, "coordinates cannot have place or name");
}
}
public Location(final LocationType type, final String id, final int lat, final int lon, final String place,
final String name) {
this(type, id, lat, lon, place, name, null);
}
public Location(final LocationType type, final String id, final Point coord, final String place, final String name,
final Set<Product> products) {
this(type, id, coord != null ? coord.lat : 0, coord != null ? coord.lon : 0, place, name, products);
}
public Location(final LocationType type, final String id, final Point coord, final String place,
final String name) {
this(type, id, coord != null ? coord.lat : 0, coord != null ? coord.lon : 0, place, name);
this(type, id, coord, place, name, null);
}
public Location(final LocationType type, final String id, final String place, final String name) {
this(type, id, 0, 0, place, name);
}
public Location(final LocationType type, final String id, final int lat, final int lon) {
this(type, id, lat, lon, null, null);
this(type, id, null, place, name);
}
public Location(final LocationType type, final String id, final Point coord) {
this(type, id, coord != null ? coord.lat : 0, coord != null ? coord.lon : 0);
this(type, id, coord, null, null);
}
public Location(final LocationType type, final String id) {
@ -96,27 +81,35 @@ public final class Location implements Serializable {
}
public static Location coord(final int lat, final int lon) {
return new Location(LocationType.COORD, null, lat, lon);
return new Location(LocationType.COORD, null, Point.from1E6(lat, lon));
}
public static Location coord(final Point coord) {
return new Location(LocationType.COORD, null, coord.lat, coord.lon);
return new Location(LocationType.COORD, null, coord);
}
public final boolean hasId() {
return !Strings.isNullOrEmpty(id);
}
public final boolean hasLocation() {
return lat != 0 || lon != 0;
public final boolean hasCoord() {
return coord != null;
}
public double getLatAsDouble() {
return lat / 1E6;
return coord.getLatAsDouble();
}
public double getLonAsDouble() {
return lon / 1E6;
return coord.getLonAsDouble();
}
public int getLatAs1E6() {
return coord.getLatAs1E6();
}
public int getLonAs1E6() {
return coord.getLonAs1E6();
}
public final boolean hasName() {
@ -131,7 +124,7 @@ public final class Location implements Serializable {
return true;
if (type == LocationType.ADDRESS || type == LocationType.COORD)
return hasLocation();
return hasCoord();
return false;
}
@ -165,8 +158,8 @@ public final class Location implements Serializable {
return false;
if (this.id != null)
return Objects.equal(this.id, other.id);
if (this.lat != 0 && this.lon != 0)
return this.lat == other.lat && this.lon == other.lon;
if (this.coord != null)
return Objects.equal(this.coord, other.coord);
// only discriminate by name/place if no ids are given
if (!Objects.equal(this.place, other.place))
@ -185,7 +178,7 @@ public final class Location implements Serializable {
return false;
if (!Objects.equal(this.id, other.id))
return false;
if (this.lat != other.lat && this.lon != other.lon)
if (!Objects.equal(this.coord, other.coord))
return false;
if (!Objects.equal(this.place, other.place))
return false;
@ -201,14 +194,14 @@ public final class Location implements Serializable {
if (id != null)
return Objects.hashCode(type, id);
else
return Objects.hashCode(type, lat, lon);
return Objects.hashCode(type, coord);
}
@Override
public String toString() {
final ToStringHelper helper = MoreObjects.toStringHelper(this).addValue(type).addValue(id);
if (hasLocation())
helper.addValue(lat + "/" + lon);
if (hasCoord())
helper.addValue(coord);
return helper.add("place", place).add("name", name).add("products", products).omitNullValues().toString();
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,6 +18,7 @@
package de.schildbach.pte.dto;
import java.io.Serializable;
import java.util.Locale;
import com.google.common.base.Objects;
@ -27,23 +28,35 @@ import com.google.common.base.Objects;
public final class Point implements Serializable {
private static final long serialVersionUID = -256077054671402897L;
public final int lat, lon;
private final double lat, lon;
public Point(final int lat, final int lon) {
private Point(final double lat, final double lon) {
this.lat = lat;
this.lon = lon;
}
public static Point fromDouble(final double lat, final double lon) {
return new Point((int) Math.round(lat * 1E6), (int) Math.round(lon * 1E6));
return new Point(lat, lon);
}
public static Point from1E6(final int lat, final int lon) {
return new Point(lat / 1E6, lon / 1E6);
}
public double getLatAsDouble() {
return lat / 1E6;
return lat;
}
public double getLonAsDouble() {
return lon / 1E6;
return lon;
}
public int getLatAs1E6() {
return (int) Math.round(lat * 1E6);
}
public int getLonAs1E6() {
return (int) Math.round(lon * 1E6);
}
@Override
@ -67,6 +80,6 @@ public final class Point implements Serializable {
@Override
public String toString() {
return lat + "/" + lon;
return String.format(Locale.ENGLISH, "%.7f/%.7f", lat, lon);
}
}

View file

@ -240,9 +240,8 @@ public final class Trip implements Serializable {
final StringBuilder builder = new StringBuilder();
for (final Leg leg : legs) {
builder.append(leg.departure.hasId() ? leg.departure.id : leg.departure.lat + '/' + leg.departure.lon)
.append('-');
builder.append(leg.arrival.hasId() ? leg.arrival.id : leg.arrival.lat + '/' + leg.arrival.lon).append('-');
builder.append(leg.departure.hasId() ? leg.departure.id : leg.departure.coord).append('-');
builder.append(leg.arrival.hasId() ? leg.arrival.id : leg.arrival.coord).append('-');
if (leg instanceof Individual) {
builder.append("individual");