From a20f1de4caa0dd830672e4b0725e1bf7e1a95495 Mon Sep 17 00:00:00 2001 From: Dmitry Naumov Date: Thu, 27 Jul 2023 23:19:44 +0500 Subject: [PATCH] Fix fitting rect/point to map #17553 --- .../java/net/osmand/data/RotatedTileBox.java | 33 +++++++++++++++- .../osmand/plus/views/OsmandMapTileView.java | 38 +++++++++++++------ 2 files changed, 59 insertions(+), 12 deletions(-) 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 54bf2eeeac1..bf4b821da3e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/data/RotatedTileBox.java +++ b/OsmAnd-java/src/main/java/net/osmand/data/RotatedTileBox.java @@ -1,7 +1,11 @@ package net.osmand.data; +import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; +import java.util.ArrayList; +import java.util.List; + public class RotatedTileBox { /// primary fields @@ -30,6 +34,7 @@ public class RotatedTileBox { private double oyTile; private QuadRect tileBounds; private QuadRect latLonBounds; + private List rotatedLatLonBounds; private QuadPointDouble tileLT; private QuadPointDouble tileRT; private QuadPointDouble tileRB; @@ -63,13 +68,18 @@ private void copyDerivedFields(RotatedTileBox r) { rotateSin = r.rotateSin; oxTile = r.oxTile; oyTile = r.oyTile; - if (r.tileBounds != null && r.latLonBounds != null) { + if (r.tileBounds != null && r.latLonBounds != null && !Algorithms.isEmpty(r.rotatedLatLonBounds)) { tileBounds = new QuadRect(r.tileBounds); latLonBounds = new QuadRect(r.latLonBounds); tileLT = new QuadPointDouble(r.tileLT); tileRT = new QuadPointDouble(r.tileRT); tileRB = new QuadPointDouble(r.tileRB); tileLB = new QuadPointDouble(r.tileLB); + + rotatedLatLonBounds = new ArrayList<>(); + for (LatLon latLon : r.rotatedLatLonBounds) { + rotatedLatLonBounds.add(new LatLon(latLon.getLatitude(), latLon.getLongitude())); + } } } @@ -193,6 +203,12 @@ public void calculateTileRectangle() { float right = (float) MapUtils.getLongitudeFromTile(zoom, alignTile(bounds.right)); tileBounds = bounds; latLonBounds = new QuadRect(left, top, right, bottom); + + rotatedLatLonBounds = new ArrayList<>(); + rotatedLatLonBounds.add(new LatLon(MapUtils.getLatitudeFromTile(zoom, alignTile(y1)), MapUtils.getLongitudeFromTile(zoom, alignTile(x1)))); + rotatedLatLonBounds.add(new LatLon(MapUtils.getLatitudeFromTile(zoom, alignTile(y2)), MapUtils.getLongitudeFromTile(zoom, alignTile(x2)))); + rotatedLatLonBounds.add(new LatLon(MapUtils.getLatitudeFromTile(zoom, alignTile(y3)), MapUtils.getLongitudeFromTile(zoom, alignTile(x3)))); + rotatedLatLonBounds.add(new LatLon(MapUtils.getLatitudeFromTile(zoom, alignTile(y4)), MapUtils.getLongitudeFromTile(zoom, alignTile(x4)))); } private double alignTile(double tile) { @@ -506,6 +522,21 @@ public boolean containsTilePoint(QuadPointDouble qp) { return tx >= 0 && tx <= pixWidth && ty >= 0 && ty <= pixHeight; } + public boolean containsRectInRotatedRect(double left, double top, double right, double bottom) { + List rect = new ArrayList<>(); + rect.add(new LatLon(top, left)); + rect.add(new LatLon(top, right)); + rect.add(new LatLon(bottom, right)); + rect.add(new LatLon(bottom, left)); + rect.add(rect.get(0)); + + checkTileRectangleCalculated(); + List rotatedLatLonRect = new ArrayList<>(this.rotatedLatLonBounds); + rotatedLatLonRect.add(rotatedLatLonRect.get(0)); + + return Algorithms.isFirstPolygonInsideSecond(rect, rotatedLatLonRect); + } + public boolean containsLatLon(double lat, double lon) { double tx = getPixXFromLatLon(lat, lon); double ty = getPixYFromLatLon(lat, lon); diff --git a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java index 40a793795a4..cd2434eb402 100644 --- a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java +++ b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java @@ -1550,17 +1550,29 @@ public void fitRectToMap(double left, double right, double top, double bottom, double clat = bottom / 2 + top / 2; double clon = left / 2 + right / 2; tb.setLatLonCenter(clat, clon); - while (tb.getZoom() < MAX_ZOOM_LIMIT && tb.containsLatLon(top, left) && tb.containsLatLon(bottom, right)) { - tb.setZoom(tb.getZoom() + 1); + + int minZoom = Math.max(getMinZoom(), MIN_ZOOM_LIMIT); + int maxZoom = Math.min(getMaxZoom(), MAX_ZOOM_LIMIT); + Zoom zoom = new Zoom(tb.getZoom(), (float) tb.getZoomFloatPart(), minZoom, maxZoom); + + while (zoom.isZoomInAllowed() && tb.containsRectInRotatedRect(left, top, right, bottom)) { + zoom.zoomIn(); + tb.setZoomAndAnimation(zoom.getBaseZoom(), 0, zoom.getZoomFloatPart()); } - while (tb.getZoom() >= MIN_ZOOM_LIMIT && (!tb.containsLatLon(top, left) || !tb.containsLatLon(bottom, right))) { - tb.setZoom(tb.getZoom() - 1); + while (zoom.isZoomOutAllowed() && !tb.containsRectInRotatedRect(left, top, right, bottom)) { + zoom.zoomOut(); + tb.setZoomAndAnimation(zoom.getBaseZoom(), 0, zoom.getZoomFloatPart()); } + if (dy != 0 || dx != 0) { - clat = tb.getLatFromPixel(tb.getPixWidth() / 2f, tb.getPixHeight() / 2f + dy); - clon = tb.getLonFromPixel(tb.getPixWidth() / 2f + dx, tb.getPixHeight() / 2f); + float x = tb.getPixWidth() / 2f + dx; + float y = tb.getPixHeight() / 2f + dy; + clat = tb.getLatFromPixel(x, y); + clon = tb.getLonFromPixel(x, y); } - animatedDraggingThread.startMoving(clat, clon, tb.getZoom(), true); + + animatedDraggingThread.startMoving(clat, clon, zoom.getBaseZoom(), zoom.getZoomFloatPart(), + true, false, null, null); } public RotatedTileBox getTileBox(int tileBoxWidthPx, int tileBoxHeightPx, int marginTopPx) { @@ -1580,8 +1592,10 @@ public RotatedTileBox getTileBox(int tileBoxWidthPx, int tileBoxHeightPx, int ma tb.setPixelDimensions(tbw, tbh); if (dy != 0) { - double clat = tb.getLatFromPixel(tb.getPixWidth() / 2, tb.getPixHeight() / 2 - dy); - double clon = tb.getLonFromPixel(tb.getPixWidth() / 2, tb.getPixHeight() / 2); + float x = tb.getPixWidth() / 2f; + float y = tb.getPixHeight() / 2f - dy; + double clat = tb.getLatFromPixel(x, y); + double clon = tb.getLonFromPixel(x, y); tb.setLatLonCenter(clat, clon); } return tb; @@ -1603,8 +1617,10 @@ public void fitLocationToMap(double clat, double clon, int zoom, tb.setLatLonCenter(clat, clon); tb.setZoom(zoom); if (dy != 0) { - clat = tb.getLatFromPixel(tb.getPixWidth() / 2, tb.getPixHeight() / 2 + dy); - clon = tb.getLonFromPixel(tb.getPixWidth() / 2, tb.getPixHeight() / 2); + float x = tb.getPixWidth() / 2f; + float y = tb.getPixHeight() / 2f - dy; + clat = tb.getLatFromPixel(x, y); + clon = tb.getLonFromPixel(x, y); } if (animated) { animatedDraggingThread.startMoving(clat, clon, tb.getZoom(), true);