diff --git a/api/android-for-openmobilemaps.api b/api/android-for-openmobilemaps.api index f1d5491..770ea7a 100644 --- a/api/android-for-openmobilemaps.api +++ b/api/android-for-openmobilemaps.api @@ -124,6 +124,7 @@ public final class com.mapconductor.openmobilemaps.OpenMobileMapsLayers { public static final int RASTER_INDEX_FIRST; public static final int BELOW_INDEX_FIRST; public static final int GROUND_IMAGE_INDEX_FIRST; + public static final int POLYGON_TILE_INDEX_FIRST; public static final int FIXED_INDEX_FIRST; public static final int MARKER_TILE_INDEX_FIRST; public static final int ICON_INDEX; @@ -138,6 +139,7 @@ public final class com.mapconductor.openmobilemaps.OpenMobileMapsLayers { public final void setDesignLayer(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface); public final io.openmobilemaps.mapscore.shared.map.LayerInterface insertBelowOverlays(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface); public final io.openmobilemaps.mapscore.shared.map.LayerInterface insertGroundImage(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface); + public final io.openmobilemaps.mapscore.shared.map.LayerInterface insertPolygonTile(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface); public final io.openmobilemaps.mapscore.shared.map.LayerInterface insertMarkerTile(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface); public final void remove(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface); public final void clearAll(); @@ -354,6 +356,9 @@ public final class com.mapconductor.openmobilemaps.marker.OpenMobileMapsMarkerCo public void destroy(); public java.lang.Object update(java.lang.Object, kotlin.coroutines.Continuation); } +final class com.mapconductor.openmobilemaps.marker.OpenMobileMapsMarkerController$Companion { + public final long getTILE_REFRESH_COALESCE-UwyO8pc(); +} public final class com.mapconductor.openmobilemaps.tile.WebMercatorTileLayerConfig extends io.openmobilemaps.mapscore.shared.map.layers.tiled.Tiled2dMapLayerConfig { public static final double WORLD_WIDTH_METERS; public static final double HALF_WORLD; diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsLayers.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsLayers.kt index 47f2f66..2989555 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsLayers.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsLayers.kt @@ -19,12 +19,12 @@ import io.openmobilemaps.mapscore.shared.map.layers.polygon.PolygonLayerInterfac * ## 重ね順(下から) * * ``` - * 地図デザイン → ラスターレイヤ・グラウンドイメージ → ポリゴン塗り → ポリゴン輪郭 + * 地図デザイン → ラスターレイヤ・グラウンドイメージ → ポリゴンのタイル → ポリゴン塗り → ポリゴン輪郭 * → 円の塗り → 円の輪郭 → ポリライン → マーカー * ``` * * すべてのプロバイダ共通の決まり([com.mapconductor.core.controller.OverlayStacking])。 - * ラスターとグラウンドイメージ、マーカーのタイルは数が変わるので、帯ごとに索引の区間を分けて + * ラスターとグラウンドイメージ、ポリゴン・マーカーのタイルは数が変わるので、帯ごとに索引の区間を分けて * 割り当てる(以前はラスターとグラウンドイメージが同じ区間を空き番号から使い回していたため、 * 追加・送り直しの順で上下が入れ替わった)。 * @@ -73,7 +73,8 @@ class OpenMobileMapsLayers { } private val rasterBand = Band(RASTER_INDEX_FIRST, GROUND_IMAGE_INDEX_FIRST) - private val groundImageBand = Band(GROUND_IMAGE_INDEX_FIRST, FIXED_INDEX_FIRST) + private val groundImageBand = Band(GROUND_IMAGE_INDEX_FIRST, POLYGON_TILE_INDEX_FIRST) + private val polygonTileBand = Band(POLYGON_TILE_INDEX_FIRST, FIXED_INDEX_FIRST) private val markerTileBand = Band(MARKER_TILE_INDEX_FIRST, ICON_INDEX) private val bandOfLayer = mutableMapOf() @@ -139,6 +140,12 @@ class OpenMobileMapsLayers { layer: LayerInterface, ): LayerInterface = insertInBand(map, layer, groundImageBand) + /** ポリゴンのタイル: ポリゴンの帯の一番下(グラウンドイメージの上、ポリゴン塗りの下)。 */ + fun insertPolygonTile( + map: MapInterface, + layer: LayerInterface, + ): LayerInterface = insertInBand(map, layer, polygonTileBand) + /** マーカーのタイル: ポリラインの上、マーカー(アイコン)の下。 */ fun insertMarkerTile( map: MapInterface, @@ -190,6 +197,9 @@ class OpenMobileMapsLayers { /** グラウンドイメージ。ラスターの上、ポリゴンの下。 */ const val GROUND_IMAGE_INDEX_FIRST = 500 + /** ポリゴンのタイル。グラウンドイメージの上、ポリゴン塗りの下。 */ + const val POLYGON_TILE_INDEX_FIRST = 900 + /** 固定のオーバーレイ 6 種。下の枠を使い切らないよう十分離す。 */ const val FIXED_INDEX_FIRST = 1_000 diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt index 65270f7..da86b27 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt @@ -19,6 +19,9 @@ import com.mapconductor.core.marker.MarkerRenderingStrategyInterface import com.mapconductor.core.marker.OnMarkerEventHandler import com.mapconductor.core.marker.StrategyMarkerController import com.mapconductor.core.marker.dispatchGeoMarkerClick +import com.mapconductor.core.polygon.POLYGON_TILE_LAYER_ID +import com.mapconductor.core.polygon.PolygonTiler +import com.mapconductor.core.polygon.polygonTileRasterLayerState import com.mapconductor.openmobilemaps.marker.OpenMobileMapsMarkerController import com.mapconductor.openmobilemaps.tile.WebMercatorTileLayerConfig import com.mapconductor.openmobilemaps.zoom.ZoomAltitudeConverter @@ -164,6 +167,19 @@ class OpenMobileMapsMapViewController( .forEach { rasterLayerController.removeById(it.state.id) } } } + + // Many polygons are drawn as raster tiles, shown through the same RasterLayer + // controller as the marker tiles (upsert / removeById, never the app's layers). + polygonController.tiler = + PolygonTiler().apply { + onTemplate = { template, tileSize -> + if (template != null) { + rasterLayerController.upsert(polygonTileRasterLayerState(template, tileSize)) + } else { + rasterLayerController.removeById(POLYGON_TILE_LAYER_ID) + } + } + } } /** diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsOverlays.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsOverlays.kt index b9cbe13..0f0a232 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsOverlays.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsOverlays.kt @@ -24,6 +24,7 @@ import com.mapconductor.core.marker.MarkerEntityInterface import com.mapconductor.core.marker.MarkerManager import com.mapconductor.core.marker.MarkerOverlayRendererInterface import com.mapconductor.core.polygon.AbstractPolygonOverlayRenderer +import com.mapconductor.core.polygon.POLYGON_TILE_LAYER_ID import com.mapconductor.core.polygon.PolygonController import com.mapconductor.core.polygon.PolygonEntityInterface import com.mapconductor.core.polygon.PolygonManagerInterface @@ -478,14 +479,24 @@ class OpenMobileMapsPolygonOverlayRenderer( override suspend fun removePolygon(entity: PolygonEntityInterface) = Unit override suspend fun onPostProcess() { + // Polygons drawn as tiles (PolygonController.tiler) stay in the manager + // for taps with no native polygon. // 帯の中は zIndex の順(同じなら渡された順)。 - val entities = polygonManager.allEntities().sortedBy { it.state.zIndex } + val entities = + polygonManager + .allEntities() + .sortedBy { it.state.zIndex } + .mapNotNull { nativePolygonOf(it) } // add / addAll ではなく setPolygons を使うこと。4.0 の PolygonLayer は // 原点(第 2 引数)を持つようになっていて、setPolygons を一度も通っていない // レイヤに add すると**何も描かれない**(例外も警告も出ない)。 - fillLayer.setPolygons(entities.flatMapTo(ArrayList()) { it.polygon.fills }, RENDER_ORIGIN) - outlineLayer.setLines(entities.flatMapTo(ArrayList()) { it.polygon.outlines }) + fillLayer.setPolygons(entities.flatMapTo(ArrayList()) { it.fills }, RENDER_ORIGIN) + outlineLayer.setLines(entities.flatMapTo(ArrayList()) { it.outlines }) } + + @Suppress("USELESS_CAST") + private fun nativePolygonOf(entity: PolygonEntityInterface): OpenMobileMapsActualPolygon? = + entity.polygon as OpenMobileMapsActualPolygon? } // ── 円 ──────────────────────────────────────────────────────────────────── @@ -693,6 +704,9 @@ class OpenMobileMapsRasterLayerOverlayRenderer( if (state.id.startsWith("marker-tile-")) { // マーカーのタイルはマーカーの帯(ポリラインの上)。 layers.insertMarkerTile(holder.map, layer.asLayerInterface()) + } else if (state.id == POLYGON_TILE_LAYER_ID) { + // ポリゴンのタイルはポリゴンの帯の一番下(画像になったポリゴンであって、地図の画像ではない)。 + layers.insertPolygonTile(holder.map, layer.asLayerInterface()) } else { layers.insertBelowOverlays(holder.map, layer.asLayerInterface()) },