From 544673c84cbc5a2ea3fb9434e6fc173fbf9ec4c5 Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 23:55:27 -0800 Subject: [PATCH] Put rasters and ground images under map items; separate draw-order bands Raster and ground image MapLayers had the default priority and were drawn above polygons, circles and polylines. Polygons and circles shared drawOrder 0..511. Rasters now render before the style's "route" layer and ground images before "traffic_on_route" (raster < ground image, both under map items). Map items get disjoint drawOrder bands: polygons 0..339, circles 340..679, polylines 680..1023. Marker tiles keep rendering last. Stacking order (all providers, all platforms), bottom to top: raster layers < ground images < polygons < circles < polylines < markers. Needs android-sdk-core with OverlayStacking (fix/overlay-stacking-order). --- api/android-for-here.api | 8 +++++ .../mapconductor/here/HereOverlayStacking.kt | 34 +++++++++++++++++++ .../here/circle/HereCircleOverlayRenderer.kt | 5 +-- .../HereGroundImageOverlayRenderer.kt | 3 ++ .../polygon/HerePolygonOverlayRenderer.kt | 7 ++-- .../polyline/HerePolylineOverlayRenderer.kt | 5 +-- .../raster/HereRasterLayerOverlayRenderer.kt | 15 ++++++++ 7 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/mapconductor/here/HereOverlayStacking.kt diff --git a/api/android-for-here.api b/api/android-for-here.api index ecca64e..bca3220 100644 --- a/api/android-for-here.api +++ b/api/android-for-here.api @@ -184,6 +184,14 @@ public final class com.mapconductor.here.HereMapViewSaver extends com.mapconduct public com.mapconductor.core.map.MapViewStateInterface createState(java.lang.String, android.os.Bundle, com.mapconductor.core.map.MapCameraPosition); public java.lang.String getStateId(com.mapconductor.core.map.MapViewStateInterface); } +public final class com.mapconductor.here.HereOverlayStacking { + public static final com.mapconductor.here.HereOverlayStacking INSTANCE; + public final int polygonDrawOrder(int); + public final int circleDrawOrder(int); + public final int polylineDrawOrder(int); + public final com.here.sdk.mapview.MapLayerPriority rasterPriority(); + public final com.here.sdk.mapview.MapLayerPriority groundImagePriority(); +} public final class com.mapconductor.here.HereTypeAliasKt { } public final class com.mapconductor.here.HereViewControllerStoreKt { diff --git a/src/main/java/com/mapconductor/here/HereOverlayStacking.kt b/src/main/java/com/mapconductor/here/HereOverlayStacking.kt new file mode 100644 index 0000000..83f5257 --- /dev/null +++ b/src/main/java/com/mapconductor/here/HereOverlayStacking.kt @@ -0,0 +1,34 @@ +package com.mapconductor.here + +import com.here.sdk.mapview.MapLayerPriority +import com.here.sdk.mapview.MapLayerPriorityBuilder + +/** + * 重なり順(ラスター < GroundImage < ポリゴン < サークル < ポリライン < マーカー)。 + * + * HERE では: + * - ポリゴン・サークル・ポリラインは map item で、`drawOrder` を 1 本の数で比べる。 + * 帯ごとに区間を分けて割り当てる(帯の中は zIndex の順)。 + * - ラスターと GroundImage は MapLayer。既定の優先度だと map item より上に描かれて + * ポリゴン等を覆うので、ベースマップのレイヤー(ルートの手前)に入れる。 + * ラスター → GroundImage の順になるよう、別々のレイヤーの手前を指定する。 + * - マーカーは map item の上に描かれる(drawOrder はマーカーどうしの順)。 + */ +internal object HereOverlayStacking { + private const val BAND = 340 + + fun polygonDrawOrder(zIndex: Int): Int = zIndex.coerceIn(0, BAND - 1) + + fun circleDrawOrder(zIndex: Int): Int = BAND + zIndex.coerceIn(0, BAND - 1) + + fun polylineDrawOrder(zIndex: Int): Int = 2 * BAND + zIndex.coerceIn(0, 1023 - 2 * BAND) + + /** ラスター: ベースマップの "route" レイヤーの手前(GroundImage より下)。 */ + fun rasterPriority(): MapLayerPriority = MapLayerPriorityBuilder().renderedBeforeLayer(RASTER_ANCHOR).build() + + /** GroundImage: "traffic_on_route" レイヤーの手前(ラスターより上、map item より下)。 */ + fun groundImagePriority(): MapLayerPriority = MapLayerPriorityBuilder().renderedBeforeLayer(GROUND_IMAGE_ANCHOR).build() + + private const val RASTER_ANCHOR = "route" + private const val GROUND_IMAGE_ANCHOR = "traffic_on_route" +} diff --git a/src/main/java/com/mapconductor/here/circle/HereCircleOverlayRenderer.kt b/src/main/java/com/mapconductor/here/circle/HereCircleOverlayRenderer.kt index 650c875..37c5811 100644 --- a/src/main/java/com/mapconductor/here/circle/HereCircleOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/here/circle/HereCircleOverlayRenderer.kt @@ -15,6 +15,7 @@ import com.mapconductor.core.features.normalize import com.mapconductor.core.geometry.circleToRing import com.mapconductor.core.geometry.closeRing import com.mapconductor.here.HereActualCircle +import com.mapconductor.here.HereOverlayStacking import com.mapconductor.here.HereViewHolder import com.mapconductor.here.toGeoCoordinates import kotlinx.coroutines.CoroutineScope @@ -36,7 +37,7 @@ class HereCircleOverlayRenderer( Color.valueOf(state.strokeColor.toArgb()), lineWidth, ).apply { - drawOrder = (state.zIndex ?: 0).coerceIn(0, 511) + drawOrder = HereOverlayStacking.circleDrawOrder(state.zIndex ?: 0) } coroutine.launch { holder.map.addMapPolygon(mapCircle) @@ -96,7 +97,7 @@ class HereCircleOverlayRenderer( ) } if (finger.zIndex != prevFinger.zIndex) { - current.circle.drawOrder = (current.state.zIndex ?: 0).coerceIn(0, 511) + current.circle.drawOrder = HereOverlayStacking.circleDrawOrder(current.state.zIndex ?: 0) } circle diff --git a/src/main/java/com/mapconductor/here/groundimage/HereGroundImageOverlayRenderer.kt b/src/main/java/com/mapconductor/here/groundimage/HereGroundImageOverlayRenderer.kt index 55f48f4..3783659 100644 --- a/src/main/java/com/mapconductor/here/groundimage/HereGroundImageOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/here/groundimage/HereGroundImageOverlayRenderer.kt @@ -12,6 +12,7 @@ import com.mapconductor.core.groundimage.GroundImageState import com.mapconductor.core.groundimage.GroundImageTileProvider import com.mapconductor.core.tileserver.LocalTileServer import com.mapconductor.here.HereActualGroundImage +import com.mapconductor.here.HereOverlayStacking import com.mapconductor.here.HereViewHolder import android.util.Log import kotlinx.coroutines.CoroutineScope @@ -136,6 +137,8 @@ class HereGroundImageOverlayRenderer( MapLayerBuilder() .withName(layerName) .withDataSource(config.name, MapContentType.RASTER_IMAGE) + // GroundImage の帯(ラスターの上、ポリゴン等の map item の下)。 + .withPriority(HereOverlayStacking.groundImagePriority()) .forMap(holder.mapView.hereMap) .build() HereGroundImageHandle( diff --git a/src/main/java/com/mapconductor/here/polygon/HerePolygonOverlayRenderer.kt b/src/main/java/com/mapconductor/here/polygon/HerePolygonOverlayRenderer.kt index adf1b56..1b602f3 100644 --- a/src/main/java/com/mapconductor/here/polygon/HerePolygonOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/here/polygon/HerePolygonOverlayRenderer.kt @@ -17,6 +17,7 @@ import com.mapconductor.core.polygon.PolygonState import com.mapconductor.core.polygon.splitPolygonWithHolesIntoSimpleRings import com.mapconductor.core.polygon.unionHoles import com.mapconductor.here.HereActualPolygon +import com.mapconductor.here.HereOverlayStacking import com.mapconductor.here.HereViewHolder import android.util.Log import kotlinx.coroutines.CoroutineScope @@ -145,7 +146,7 @@ class HerePolygonOverlayRenderer( } } if (finger.zIndex != prevFinger.zIndex) { - polygon.forEach { it.drawOrder = current.state.zIndex.coerceIn(0, 511) } + polygon.forEach { it.drawOrder = HereOverlayStacking.polygonDrawOrder(current.state.zIndex) } } polygon @@ -161,7 +162,7 @@ class HerePolygonOverlayRenderer( val strokeWidth = ResourceProvider.dpToPx(state.strokeWidth) val transparentFill = Color.valueOf(0f, 0f, 0f, 0f) val fillColor = Color.valueOf(state.fillColor.toArgb()) - val order = state.zIndex.coerceIn(0, 511) + val order = HereOverlayStacking.polygonDrawOrder(state.zIndex) buildList { // 塗り: 穴を持たないピース群へ分解し、1 ピース 1 枚で塗る。 @@ -231,7 +232,7 @@ class HerePolygonOverlayRenderer( Color.valueOf(state.fillColor.toArgb()), Color.valueOf(state.strokeColor.toArgb()), outlineWidth, - ).apply { drawOrder = state.zIndex.coerceIn(0, 511) } + ).apply { drawOrder = HereOverlayStacking.polygonDrawOrder(state.zIndex) } } private fun toRing( diff --git a/src/main/java/com/mapconductor/here/polyline/HerePolylineOverlayRenderer.kt b/src/main/java/com/mapconductor/here/polyline/HerePolylineOverlayRenderer.kt index 6bc12e1..df4398a 100644 --- a/src/main/java/com/mapconductor/here/polyline/HerePolylineOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/here/polyline/HerePolylineOverlayRenderer.kt @@ -16,6 +16,7 @@ import com.mapconductor.core.polyline.PolylineState import com.mapconductor.core.spherical.Planar import com.mapconductor.core.spherical.WGS84Geodesic import com.mapconductor.here.HereActualPolyline +import com.mapconductor.here.HereOverlayStacking import com.mapconductor.here.HereViewHolder import com.mapconductor.here.toGeoCoordinates import kotlinx.coroutines.CoroutineScope @@ -32,7 +33,7 @@ class HerePolylineOverlayRenderer( val representation = createRepresentation(state) val mapPolyline = MapPolyline(geoPolyline, representation).apply { - drawOrder = (state.zIndex + 512).coerceIn(512, 1023) + drawOrder = HereOverlayStacking.polylineDrawOrder(state.zIndex) } coroutine.launch { @@ -66,7 +67,7 @@ class HerePolylineOverlayRenderer( } if (finger.zIndex != prevFinger.zIndex) { - polyline.drawOrder = (current.state.zIndex + 512).coerceIn(512, 1023) + polyline.drawOrder = HereOverlayStacking.polylineDrawOrder(current.state.zIndex) needsReAdd = true } diff --git a/src/main/java/com/mapconductor/here/raster/HereRasterLayerOverlayRenderer.kt b/src/main/java/com/mapconductor/here/raster/HereRasterLayerOverlayRenderer.kt index f81b068..212000a 100644 --- a/src/main/java/com/mapconductor/here/raster/HereRasterLayerOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/here/raster/HereRasterLayerOverlayRenderer.kt @@ -3,6 +3,8 @@ package com.mapconductor.here.raster import com.here.sdk.mapview.MapContentType import com.here.sdk.mapview.MapLayer import com.here.sdk.mapview.MapLayerBuilder +import com.here.sdk.mapview.MapLayerPriority +import com.here.sdk.mapview.MapLayerPriorityBuilder import com.here.sdk.mapview.datasource.RasterDataSource import com.here.sdk.mapview.datasource.RasterDataSourceConfiguration import com.here.sdk.mapview.datasource.RasterTileSource @@ -19,6 +21,7 @@ import com.mapconductor.core.raster.TileScheme import com.mapconductor.core.tileserver.LocalTileServer import com.mapconductor.core.tileserver.TileProviderInterface import com.mapconductor.core.tileserver.TileRequest +import com.mapconductor.here.HereOverlayStacking import com.mapconductor.here.HereViewHolder import java.io.ByteArrayOutputStream import java.net.HttpURLConnection @@ -132,6 +135,7 @@ class HereRasterLayerOverlayRenderer( MapLayerBuilder() .withName(tileSpec.layerName) .withDataSource(tileSpec.sourceName, MapContentType.RASTER_IMAGE) + .withPriority(priorityFor(state)) .forMap(holder.mapView.hereMap) .build() layer.setEnabled(state.visible) @@ -150,6 +154,17 @@ class HereRasterLayerOverlayRenderer( } } + /** + * アプリのラスターはラスターの帯(GroundImage・map item の下)。マーカーのタイルは + * マーカーの帯なので、ポリゴン等の map item より上(最後に描く)。 + */ + private fun priorityFor(state: RasterLayerState): MapLayerPriority = + if (state.id.startsWith("marker-tile-")) { + MapLayerPriorityBuilder().renderedLast().build() + } else { + HereOverlayStacking.rasterPriority() + } + private fun updateLayer( handle: HereRasterLayerHandle, state: RasterLayerState,