Index: src/uk/me/parabola/imgfmt/app/Coord.java =================================================================== --- src/uk/me/parabola/imgfmt/app/Coord.java (revision 4912) +++ src/uk/me/parabola/imgfmt/app/Coord.java (working copy) @@ -56,6 +56,7 @@ private static final int HIGH_PREC_BITS = 30; public static final int DELTA_SHIFT = HIGH_PREC_BITS - 24; private static final int MAX_DELTA = 1 << (DELTA_SHIFT - 2); // max delta abs value that is considered okay + private static final int HIGH_DELTA = 1 << (DELTA_SHIFT - 1); // positive delta that doesn't fit into 6 bits private static final long FACTOR_HP = 1L << HIGH_PREC_BITS; private static final int HIGH_PREC_UNUSED_BITS = Integer.SIZE - HIGH_PREC_BITS; @@ -83,24 +84,39 @@ } /** - * Construct from regular latitude and longitude. + * Construct from regular latitude and longitude given in degrees. * @param latitude The latitude in degrees. * @param longitude The longitude in degrees. */ public Coord(double latitude, double longitude) { - this.latitude = Utils.toMapUnit(latitude); - this.longitude = Utils.toMapUnit(longitude); + int lat24 = Utils.toMapUnit(latitude); + int lon24 = Utils.toMapUnit(longitude); int latHighPrec = toHighPrec(latitude); int lonHighPrec = toHighPrec(longitude); - this.latDelta = (byte) ((this.latitude << DELTA_SHIFT) - latHighPrec); - this.lonDelta = (byte) ((this.longitude << DELTA_SHIFT) - lonHighPrec); - + byte dLat = (byte) ((lat24 << DELTA_SHIFT) - latHighPrec); + byte dLon = (byte) ((lon24 << DELTA_SHIFT) - lonHighPrec); + + // correct possible overflow in delta value + if (dLat == HIGH_DELTA) { + dLat = -HIGH_DELTA; + lat24--; + } + if (dLon == HIGH_DELTA) { + dLon = -HIGH_DELTA; + lon24--; + } + + this.latitude = lat24; + this.longitude = lon24; + this.latDelta = dLat; + this.lonDelta = dLon; + // verify math assert (this.latitude << DELTA_SHIFT) - (int) latDelta == latHighPrec; assert (this.longitude << DELTA_SHIFT) - (int) lonDelta == lonHighPrec; } - private Coord (int lat, int lon, byte latDelta, byte lonDelta){ + private Coord(int lat, int lon, byte latDelta, byte lonDelta) { this.latitude = lat; this.longitude = lon; this.latDelta = latDelta; @@ -118,7 +134,19 @@ int lon24 = (lonHighPrec + (1 << (DELTA_SHIFT - 1))) >> DELTA_SHIFT; byte dLat = (byte) ((lat24 << DELTA_SHIFT) - latHighPrec); byte dLon = (byte) ((lon24 << DELTA_SHIFT) - lonHighPrec); - return new Coord(lat24, lon24, dLat, dLon); + + // correct possible overflow in delta value + if (dLat == HIGH_DELTA) { + dLat = -HIGH_DELTA; + lat24--; + } + if (dLon == HIGH_DELTA) { + dLon = -HIGH_DELTA; + lon24--; + } + + Coord p = new Coord(lat24, lon24, dLat, dLon); + return p; } public static Coord makeHighPrecCoord(int latHp, int lonHp, Long2ObjectOpenHashMap coordPool) {