Hi all,
I've found out that this problem is caused by a flaw in the "high precision"
code. Under special conditions, two points with almost identical coordinates
are internally represented
with very different values. There is a possible overflow in the delta values,
the value +32 should not occur as it cannot be represented with 6 bits, but the
calculations produce this value.
I think I have an ugly fix for this but the resulting map still shows (smaller)
gaps and a unit test needs corrections, so there is more to do.
Attached is a patch that checks for this overflow. Work in progress and maybe
causes trouble in other areas, e.g. in South America where we have negative
lat/lon values.
@Ticker: The unit test für LineClipperTest fails. I am not sure if only the
test has to be changed (how) or if the code in LineClipper can be improved. I
seem to remember that you suggested to use
the code in ShapeSplitter instead.
________________________________________
Von: mkgmap-dev <[email protected]> im Auftrag von Gerd
Petermann <[email protected]>
Gesendet: Dienstag, 26. September 2023 19:58
An: Development list for mkgmap
Betreff: Re: [mkgmap-dev] Gaps in surfaces
Hi Michael,
okay, I can reproduce the problem. I assume it is caused by the code which
subtracts the inner area from the multipolygon area.
No idea if this can be fixed easily.
Gerd
________________________________________
Von: mkgmap-dev <[email protected]> im Auftrag von
Forstner Michael <[email protected]>
Gesendet: Dienstag, 26. September 2023 19:44
An: 'Development list for mkgmap'
Betreff: Re: [mkgmap-dev] Gaps in surfaces
Hello Gerd,
here is the area: https://www.openstreetmap.org/#map=19/48.57117/13.96920 I
understand that it is necessary to make rounding. If a point of two surfaces
is equal in OSM, the point should also be equal in Garmin.
Thank you!
Best regards,
Michael
_______________________________________________
mkgmap-dev mailing list
[email protected]
https://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev
_______________________________________________
mkgmap-dev mailing list
[email protected]
https://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev
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<Coord> coordPool) {
_______________________________________________
mkgmap-dev mailing list
[email protected]
https://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev