diff --git a/OsmAnd-java/src/main/java/com/jwetherell/openmap/common/MoreMath.java b/OsmAnd-java/src/main/java/com/jwetherell/openmap/common/MoreMath.java index 2e2e119291..2a2fe11384 100644 --- a/OsmAnd-java/src/main/java/com/jwetherell/openmap/common/MoreMath.java +++ b/OsmAnd-java/src/main/java/com/jwetherell/openmap/common/MoreMath.java @@ -36,6 +36,16 @@ public abstract class MoreMath { */ public static final transient double HALF_PI_D = Math.PI / 2.0d; + /** + * Math.PI/4 + */ + public static final transient float QUAD_PI = (float) Math.PI / 4.0f; + + /** + * Math.PI/4 + */ + public static final transient double QUAD_PI_D = Math.PI / 4.0d; + /** * Checks if a ~= b. Use this to test equality of floating point numbers. *

diff --git a/OsmAnd-java/src/main/java/net/osmand/data/RotatedTileBox.java b/OsmAnd-java/src/main/java/net/osmand/data/RotatedTileBox.java index 4edeebb92e..9afe9ef3a9 100644 --- a/OsmAnd-java/src/main/java/net/osmand/data/RotatedTileBox.java +++ b/OsmAnd-java/src/main/java/net/osmand/data/RotatedTileBox.java @@ -1,6 +1,8 @@ package net.osmand.data; import net.osmand.util.MapUtils; +import static net.osmand.util.MapUtils.getPowZoom; + public class RotatedTileBox { /// primary fields @@ -193,8 +195,8 @@ public class RotatedTileBox { if(tile < 0) { return 0; } - if(tile >= MapUtils.getPowZoom(zoom)) { - return MapUtils.getPowZoom(zoom) - .000001; + if(tile >= getPowZoom(zoom)) { + return getPowZoom(zoom) - .000001; } return tile; } @@ -233,7 +235,7 @@ public class RotatedTileBox { } public float getPixXFromTile(double tileX, double tileY, float zoom) { - double pw = MapUtils.getPowZoom(zoom - this.zoom); + double pw = getPowZoom(zoom - this.zoom); double xTile = tileX / pw; double yTile = tileY / pw; return getPixXFromTile(xTile, yTile); @@ -260,7 +262,7 @@ public class RotatedTileBox { } public float getPixYFromTile(double tileX, double tileY, float zoom) { - double pw = MapUtils.getPowZoom(zoom - this.zoom); + double pw = getPowZoom(zoom - this.zoom); double xTile = (tileX / pw); double yTile = (tileY / pw); return getPixYFromTile(xTile, yTile); @@ -393,15 +395,15 @@ public class RotatedTileBox { public QuadPointDouble getLeftTopTile(double zoom) { checkTileRectangleCalculated(); - return new QuadPointDouble((tileLT.x * MapUtils.getPowZoom(zoom - this.zoom)), - (tileLT.y * MapUtils.getPowZoom(zoom - this.zoom))); + return new QuadPointDouble((tileLT.x * getPowZoom(zoom - this.zoom)), + (tileLT.y * getPowZoom(zoom - this.zoom))); } public QuadPointDouble getRightBottomTile(float zoom) { checkTileRectangleCalculated(); - return new QuadPointDouble((tileRB.x * MapUtils.getPowZoom(zoom - this.zoom)), - (tileRB.y * MapUtils.getPowZoom(zoom - this.zoom))); + return new QuadPointDouble((tileRB.x * getPowZoom(zoom - this.zoom)), + (tileRB.y * getPowZoom(zoom - this.zoom))); } diff --git a/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java b/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java index 853ca0e204..ccf51b5b94 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java @@ -11,6 +11,9 @@ import net.osmand.data.QuadPoint; import net.osmand.data.QuadRect; import net.osmand.util.GeoPointParserUtil.GeoParsedPoint; +import static com.jwetherell.openmap.common.MoreMath.QUAD_PI; +import static com.jwetherell.openmap.common.MoreMath.QUAD_PI_D; + /** * This utility class includes : @@ -633,6 +636,31 @@ public class MapUtils { || (l1 != null && l2 != null && Math.abs(l1.getLatitude() - l2.getLatitude()) < 0.00001 && Math.abs(l1.getLongitude() - l2.getLongitude()) < 0.00001); } + + public static LatLon rhumbDestinationPoint(LatLon latLon, double distance, double bearing) + { + double radius = 6371e3; + + double d = distance / radius; // angular distance in radians + double phi1 = Math.toRadians(latLon.getLatitude()); + double lambda1 = Math.toRadians(latLon.getLongitude()); + double theta = Math.toRadians(bearing); + + double deltaPhi = d * Math.cos(theta); + double phi2 = phi1 + deltaPhi; + + // check for some daft bugger going past the pole, normalise latitude if so + //if (ABS(phi2) > M_PI_2) + // phi2 = phi2>0 ? M_PI-phi2 : -M_PI-phi2; + + double deltaPsi = Math.log(Math.tan(phi2 / 2 + QUAD_PI_D) / Math.tan(phi1 / 2 + QUAD_PI_D)); + double q = Math.abs(deltaPsi) > 10e-12 ? deltaPhi / deltaPsi : Math.cos(phi1); // E-W course becomes incorrect with 0/0 + + double deltalambda = d * Math.sin(theta) / q; + double lambda2 = lambda1 + deltalambda; + + return new LatLon(Math.toDegrees(phi2), Math.toDegrees(lambda2)); + } } diff --git a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java index 2103340dab..e5f5655738 100644 --- a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java @@ -209,16 +209,12 @@ public class ContextMenuLayer extends OsmandMapLayer { markerCustomized = true; } if (x != null && y != null && x.size() > 2) { - double lat = MapUtils.get31LatitudeY(y.get(0)); - double lon = MapUtils.get31LongitudeX(x.get(0)); - int px, py, prevX, prevY; - prevX = (int) box.getPixXFromLatLon(lat, lon); - prevY = (int) box.getPixYFromLatLon(lat, lon); + float px, py, prevX, prevY; + prevX = box.getPixXFrom31(x.get(0), y.get(0)); + prevY = box.getPixYFrom31(x.get(0), y.get(0)); for (int i = 1; i < x.size(); i++) { - lat = MapUtils.get31LatitudeY(y.get(i)); - lon = MapUtils.get31LongitudeX(x.get(i)); - px = (int) box.getPixXFromLatLon(lat, lon); - py = (int) box.getPixYFromLatLon(lat, lon); + px = box.getPixXFrom31(x.get(i), y.get(i)); + py = box.getPixYFrom31(x.get(i), y.get(i)); canvas.drawLine(prevX, prevY, px, py, outlinePaint); prevX = px; prevY = py; diff --git a/OsmAnd/src/net/osmand/plus/views/RulerControlLayer.java b/OsmAnd/src/net/osmand/plus/views/RulerControlLayer.java index 87c2a15d0d..ace13fa868 100644 --- a/OsmAnd/src/net/osmand/plus/views/RulerControlLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/RulerControlLayer.java @@ -9,6 +9,7 @@ import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.PathMeasure; +import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; @@ -45,6 +46,7 @@ public class RulerControlLayer extends OsmandMapLayer { private static final int TEXT_SIZE = 14; private static final int DISTANCE_TEXT_SIZE = 16; private static final float COMPASS_CIRCLE_FITTING_RADIUS_COEF = 1.25f; + private static final float CIRCLE_ANGLE_STEP = 5; private final MapActivity mapActivity; private OsmandApplication app; @@ -282,11 +284,11 @@ public class RulerControlLayer extends OsmandMapLayer { RenderingLineAttributes attrs = mode == RulerMode.FIRST ? circleAttrs : circleAttrsAlt; int compassCircleId = getCompassCircleId(tb, center); for (int i = 1; i <= cacheDistances.size(); i++) { - if (showCompass && i == compassCircleId) { - drawCompassCircle(canvas, tb, compassCircleId, center, attrs); - } else { + //if (showCompass && i == compassCircleId) { + //drawCompassCircle(canvas, tb, compassCircleId, center, attrs); + //} else { drawCircle(canvas, tb, i, center, attrs); - } + //} } } } @@ -504,9 +506,41 @@ public class RulerControlLayer extends OsmandMapLayer { String text = cacheDistances.get(circleNumber - 1); float[] textCoords = calculateTextCoords(text, text, circleRadius, center, attrs); + List> arrays = new ArrayList<>(); + List points = new ArrayList<>(); + LatLon centerLatLon = tb.getCenterLatLon(); + for (int a = -180; a <= 180; a += CIRCLE_ANGLE_STEP) { + LatLon latLon = MapUtils.rhumbDestinationPoint(centerLatLon, circleRadius / tb.getPixDensity(), a); + if (Math.abs(latLon.getLatitude()) > 90 || Math.abs(latLon.getLongitude()) > 180) { + if (points.size() > 0) { + arrays.add(points); + points = new ArrayList<>(); + } + continue; + } + + float x = tb.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude()); + float y = tb.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude()); + points.add(new PointF(x, y)); + } + if (points.size() > 0) { + arrays.add(points); + } + canvas.rotate(-tb.getRotate(), center.x, center.y); - canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.shadowPaint); - canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.paint); + for (List pts : arrays) { + float[] arr = new float[pts.size() * 2]; + int i = 0; + for (PointF pt : pts) { + arr[i++] = pt.x; + arr[i++] = pt.y; + } + canvas.drawLines(arr, attrs.shadowPaint); + canvas.drawLines(arr, attrs.paint); + } + + //canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.shadowPaint); + //canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.paint); drawTextCoords(canvas, text, textCoords, attrs); canvas.rotate(tb.getRotate(), center.x, center.y); }