From 22363c254903e1783cefe4f504096ef26db13fc1 Mon Sep 17 00:00:00 2001 From: atsunatsu Date: Wed, 16 Sep 2026 16:53:54 +0800 Subject: [PATCH] fix(map): roamed-grid stripes keep geographic density MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stripe spacing now scales as 44px * 2^(zoom-7) instead of a fixed 44px on screen: at the map's max zoom (7.0) the stripes keep the established look, and at lower zooms they shrink with the map, so stripes stay pinned to the map (same stripes-per-cell at every level) — denser on screen when zoomed out, sparser when zoomed in. --- .../feature/map/MaidenheadGridOverlay.kt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/feature/map/src/main/java/com/rtbishop/look4sat/feature/map/MaidenheadGridOverlay.kt b/feature/map/src/main/java/com/rtbishop/look4sat/feature/map/MaidenheadGridOverlay.kt index c7391a20..32ff3e73 100644 --- a/feature/map/src/main/java/com/rtbishop/look4sat/feature/map/MaidenheadGridOverlay.kt +++ b/feature/map/src/main/java/com/rtbishop/look4sat/feature/map/MaidenheadGridOverlay.kt @@ -226,7 +226,7 @@ class MaidenheadGridOverlay : Overlay() { if (xRight < 0f || xLeft > canvas.width) continue val label = cellLabel(lat, lon, zoom) if (label in roamedGrids && label != ownGrid) { - drawStripes(canvas, xLeft, yTop, xRight, yBottom) + drawStripes(canvas, xLeft, yTop, xRight, yBottom, zoom) } } } @@ -246,7 +246,7 @@ class MaidenheadGridOverlay : Overlay() { val xRight = xRightBase + turn * worldWidthPx.toFloat() if (xRight < 0f || xLeft > canvas.width) continue if (yBottom < 0f || yTop > canvas.height) continue - drawStripes(canvas, xLeft, yTop, xRight, yBottom) + drawStripes(canvas, xLeft, yTop, xRight, yBottom, zoom) } } } @@ -396,17 +396,21 @@ class MaidenheadGridOverlay : Overlay() { * rectangle, from top-left to bottom-right. The paint is nearly opaque so * stripes stay blue even over a green worked fill underneath. */ - private fun drawStripes(canvas: Canvas, xLeft: Float, yTop: Float, xRight: Float, yBottom: Float) { + private fun drawStripes(canvas: Canvas, xLeft: Float, yTop: Float, xRight: Float, yBottom: Float, zoom: Double) { if (xRight <= xLeft || yBottom <= yTop) return canvas.save() canvas.clipRect(xLeft, yTop, xRight, yBottom) val height = yBottom - yTop + // Geographic density is kept constant: spacing is the reference pixel + // spacing (STRIPE_SPACING_PX at the map's max zoom) scaled by 2^(zoom-max), + // so stripes shrink/grow with the map instead of staying fixed on screen. + val spacing = STRIPE_SPACING_PX * Math.pow(2.0, zoom - MAX_GRID_ZOOM).toFloat() // Start one stripe-width left of the cell so the top-left corner is // always covered; each stripe runs from (x, top) to (x+height, bottom). var x = xLeft - height while (x < xRight) { canvas.drawLine(x, yTop, x + height, yBottom, roamStripePaint) - x += STRIPE_SPACING_PX + x += spacing } canvas.restore() } @@ -509,5 +513,12 @@ class MaidenheadGridOverlay : Overlay() { // 44f spacing (was 16f — too dense per user) with 14f-wide stripes; // sparse GridMaster-style zebra. const val STRIPE_SPACING_PX = 44f + /** + * Reference zoom for stripe spacing: the map's max zoom (MapScreen sets + * maxZoomLevel = 7.0). At this zoom stripes are STRIPE_SPACING_PX apart; + * at lower zooms spacing scales by 2^(zoom-max) so the geographic + * density matches the max-zoom look at every level. + */ + const val MAX_GRID_ZOOM = 7.0 } }