From 2056aad452eeb9bec879c52b3144a9fd78f299fd Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 17:05:15 -0800 Subject: [PATCH] Extend core PolygonController for Mappls polygons MapplsPolygonConductor implemented SlottedOverlayController by hand because it drives two renderers (fill + a polyline per outline, since a fill layer cannot draw a stroke wider than 1 px). Every change to core's PolygonController had to be copied over, and it was missed twice. Replace it with MapplsPolygonController, which extends core's PolygonController, and MapplsPolygonCompositeRenderer, which presents the existing fill and outline renderers as one renderer. The fill renderer's onRemove now redraws without the removed polygons, since core's clear() does not call onPostProcess. --- api/android-for-mappls.api | 41 +++-- .../com/mapconductor/mappls/MapplsMapView.kt | 14 +- .../mappls/MapplsViewController.kt | 4 +- .../mappls/MapplsViewControllerStyle.kt | 12 +- .../polygon/MapplsPolygonCompositeRenderer.kt | 78 +++++++++ .../mappls/polygon/MapplsPolygonConductor.kt | 153 ------------------ .../mappls/polygon/MapplsPolygonController.kt | 17 ++ .../polygon/MapplsPolygonOverlayRenderer.kt | 16 +- 8 files changed, 143 insertions(+), 192 deletions(-) create mode 100644 src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonCompositeRenderer.kt delete mode 100644 src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonConductor.kt create mode 100644 src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonController.kt diff --git a/api/android-for-mappls.api b/api/android-for-mappls.api index 31bc400..8fe3338 100644 --- a/api/android-for-mappls.api +++ b/api/android-for-mappls.api @@ -90,7 +90,7 @@ public final class com.mapconductor.mappls.MapplsMapViewKt { public static final com.mapconductor.mappls.MapplsViewController createMapplsViewController(com.mapconductor.mappls.MapplsMapViewHolderInterface, com.mapconductor.core.marker.MarkerTilingOptions, com.mapconductor.core.map.MutableMapServiceRegistry); public static final com.mapconductor.mappls.marker.MapplsMarkerController getMarkerController(com.mapconductor.mappls.MapplsMapViewHolderInterface, com.mapconductor.core.marker.MarkerTilingOptions); public static final com.mapconductor.mappls.polyline.MapplsPolylineController getPolylineController(com.mapconductor.mappls.MapplsMapViewHolderInterface); - public static final com.mapconductor.mappls.polygon.MapplsPolygonConductor getPolygonController(com.mapconductor.mappls.MapplsMapViewHolderInterface); + public static final com.mapconductor.mappls.polygon.MapplsPolygonController getPolygonController(com.mapconductor.mappls.MapplsMapViewHolderInterface); public static final com.mapconductor.mappls.circle.MapplsCircleController getCircleController(com.mapconductor.mappls.MapplsMapViewHolderInterface); public static final com.mapconductor.mappls.raster.MapplsRasterLayerController getRasterLayerController(com.mapconductor.mappls.MapplsMapViewHolderInterface); public static final com.mapconductor.mappls.groundimage.MapplsGroundImageController getGroundImageController(com.mapconductor.mappls.MapplsMapViewHolderInterface); @@ -116,8 +116,8 @@ public final class com.mapconductor.mappls.MapplsPolyUtilsKt { public final class com.mapconductor.mappls.MapplsTypeAliasKt { } public final class com.mapconductor.mappls.MapplsViewController extends com.mapconductor.core.controller.BaseMapViewController implements com.mapconductor.mappls.MapplsViewControllerInterface,com.mappls.sdk.maps.MapplsMap$OnMapClickListener,com.mappls.sdk.maps.MapplsMap$OnMapLongClickListener,com.mappls.sdk.maps.MapplsMap$OnMoveListener,com.mappls.sdk.maps.MapplsMap$OnCameraMoveListener,com.mappls.sdk.maps.MapplsMap$OnCameraIdleListener { - public com.mapconductor.mappls.MapplsViewController(com.mapconductor.mappls.MapplsMapViewHolderInterface, com.mapconductor.mappls.marker.MapplsMarkerController, com.mapconductor.mappls.polyline.MapplsPolylineController, com.mapconductor.mappls.polygon.MapplsPolygonConductor, com.mapconductor.mappls.groundimage.MapplsGroundImageController, com.mapconductor.mappls.circle.MapplsCircleController, com.mapconductor.mappls.raster.MapplsRasterLayerController, kotlinx.coroutines.CoroutineScope, kotlinx.coroutines.CoroutineScope); - public com.mapconductor.mappls.MapplsViewController(com.mapconductor.mappls.MapplsMapViewHolderInterface, com.mapconductor.mappls.marker.MapplsMarkerController, com.mapconductor.mappls.polyline.MapplsPolylineController, com.mapconductor.mappls.polygon.MapplsPolygonConductor, com.mapconductor.mappls.groundimage.MapplsGroundImageController, com.mapconductor.mappls.circle.MapplsCircleController, com.mapconductor.mappls.raster.MapplsRasterLayerController, kotlinx.coroutines.CoroutineScope, kotlinx.coroutines.CoroutineScope, int, kotlin.jvm.internal.DefaultConstructorMarker); + public com.mapconductor.mappls.MapplsViewController(com.mapconductor.mappls.MapplsMapViewHolderInterface, com.mapconductor.mappls.marker.MapplsMarkerController, com.mapconductor.mappls.polyline.MapplsPolylineController, com.mapconductor.mappls.polygon.MapplsPolygonController, com.mapconductor.mappls.groundimage.MapplsGroundImageController, com.mapconductor.mappls.circle.MapplsCircleController, com.mapconductor.mappls.raster.MapplsRasterLayerController, kotlinx.coroutines.CoroutineScope, kotlinx.coroutines.CoroutineScope); + public com.mapconductor.mappls.MapplsViewController(com.mapconductor.mappls.MapplsMapViewHolderInterface, com.mapconductor.mappls.marker.MapplsMarkerController, com.mapconductor.mappls.polyline.MapplsPolylineController, com.mapconductor.mappls.polygon.MapplsPolygonController, com.mapconductor.mappls.groundimage.MapplsGroundImageController, com.mapconductor.mappls.circle.MapplsCircleController, com.mapconductor.mappls.raster.MapplsRasterLayerController, kotlinx.coroutines.CoroutineScope, kotlinx.coroutines.CoroutineScope, int, kotlin.jvm.internal.DefaultConstructorMarker); public com.mapconductor.mappls.MapplsMapViewHolderInterface getHolder(); public kotlinx.coroutines.CoroutineScope getMainCoroutine(); public kotlinx.coroutines.CoroutineScope getDefaultCoroutine(); @@ -365,27 +365,22 @@ public class com.mapconductor.mappls.marker.MarkerLayer { public final boolean wouldSkipDraw(java.util.List>); public final void draw(java.util.List>, com.mappls.sdk.maps.Style); } -public final class com.mapconductor.mappls.polygon.MapplsPolygonConductor implements com.mapconductor.core.controller.SlottedOverlayController> { - public com.mapconductor.mappls.polygon.MapplsPolygonConductor(com.mapconductor.mappls.polygon.MapplsPolygonOverlayRenderer, com.mapconductor.mappls.polyline.MapplsPolylineOverlayRenderer); - public final com.mapconductor.mappls.polygon.MapplsPolygonOverlayRenderer getPolygonOverlay(); - public final com.mapconductor.mappls.polyline.MapplsPolylineOverlayRenderer getPolylineOverlay(); - public int getZIndex(); - public final kotlin.jvm.functions.Function1 getClickListener(); - public final void setClickListener(kotlin.jvm.functions.Function1); - public java.lang.Object add(java.util.List, kotlin.coroutines.Continuation); - public java.lang.Object update(com.mapconductor.core.polygon.PolygonState, kotlin.coroutines.Continuation); - public final void dispatchClick(com.mapconductor.core.polygon.PolygonEvent); - public com.mapconductor.core.polygon.PolygonEntityInterface find(com.mapconductor.core.features.GeoPointInterface); - public java.lang.Object clear(kotlin.coroutines.Continuation); - public com.mapconductor.core.controller.OverlayKind getKind(); - public boolean has(java.lang.String); - public void setClickListenerAny(java.lang.Object); - public com.mapconductor.core.controller.OverlayHit resolveTap(com.mapconductor.core.features.GeoPointInterface); - public void destroy(); - public java.lang.Object update(java.lang.Object, kotlin.coroutines.Continuation); - public java.lang.Object find(com.mapconductor.core.features.GeoPointInterface); +public final class com.mapconductor.mappls.polygon.MapplsPolygonCompositeRenderer implements com.mapconductor.core.polygon.PolygonOverlayRendererInterface> { + public com.mapconductor.mappls.polygon.MapplsPolygonCompositeRenderer(com.mapconductor.mappls.polygon.MapplsPolygonOverlayRenderer, com.mapconductor.mappls.polyline.MapplsPolylineOverlayRenderer); + public final com.mapconductor.mappls.polygon.MapplsPolygonOverlayRenderer getFill(); + public final com.mapconductor.mappls.polyline.MapplsPolylineOverlayRenderer getOutline(); + public java.lang.Object onAdd(java.util.List, kotlin.coroutines.Continuation>>); + public java.lang.Object onChange(java.util.List>>, kotlin.coroutines.Continuation>>); + public java.lang.Object onRemove(java.util.List>>, kotlin.coroutines.Continuation); + public java.lang.Object onPostProcess(kotlin.coroutines.Continuation); } -public final class com.mapconductor.mappls.polygon.MapplsPolygonConductorKt { +public final class com.mapconductor.mappls.polygon.MapplsPolygonCompositeRendererKt { +} +public final class com.mapconductor.mappls.polygon.MapplsPolygonController extends com.mapconductor.core.polygon.PolygonController> { + public com.mapconductor.mappls.polygon.MapplsPolygonController(com.mapconductor.mappls.polygon.MapplsPolygonCompositeRenderer); + public com.mapconductor.mappls.polygon.MapplsPolygonCompositeRenderer getRenderer(); + public int getZIndex(); + public com.mapconductor.core.polygon.PolygonOverlayRendererInterface getRenderer(); } public final class com.mapconductor.mappls.polygon.MapplsPolygonLayer { public com.mapconductor.mappls.polygon.MapplsPolygonLayer(java.lang.String, java.lang.String); diff --git a/src/main/java/com/mapconductor/mappls/MapplsMapView.kt b/src/main/java/com/mapconductor/mappls/MapplsMapView.kt index 862b41f..22f52a0 100644 --- a/src/main/java/com/mapconductor/mappls/MapplsMapView.kt +++ b/src/main/java/com/mapconductor/mappls/MapplsMapView.kt @@ -33,7 +33,8 @@ import com.mapconductor.mappls.marker.MapplsMarkerController import com.mapconductor.mappls.marker.MapplsMarkerOverlayRenderer import com.mapconductor.mappls.marker.MarkerDragLayer import com.mapconductor.mappls.marker.MarkerLayer -import com.mapconductor.mappls.polygon.MapplsPolygonConductor +import com.mapconductor.mappls.polygon.MapplsPolygonCompositeRenderer +import com.mapconductor.mappls.polygon.MapplsPolygonController import com.mapconductor.mappls.polygon.MapplsPolygonLayer import com.mapconductor.mappls.polygon.MapplsPolygonOverlayRenderer import com.mapconductor.mappls.polyline.MapplsPolylineController @@ -302,7 +303,7 @@ fun getPolylineController(holder: MapplsMapViewHolderInterface): MapplsPolylineC return controller } -fun getPolygonController(holder: MapplsMapViewHolderInterface): MapplsPolygonConductor { +fun getPolygonController(holder: MapplsMapViewHolderInterface): MapplsPolygonController { val polylineLayer = MapplsPolylineLayer( sourceId = "polygon-outline-source", @@ -329,9 +330,12 @@ fun getPolygonController(holder: MapplsMapViewHolderInterface): MapplsPolygonCon holder = holder, ) - return MapplsPolygonConductor( - polygonOverlay = polygonOverlayRenderer, - polylineOverlay = polylineOverlayRenderer, + return MapplsPolygonController( + renderer = + MapplsPolygonCompositeRenderer( + fill = polygonOverlayRenderer, + outline = polylineOverlayRenderer, + ), ) } diff --git a/src/main/java/com/mapconductor/mappls/MapplsViewController.kt b/src/main/java/com/mapconductor/mappls/MapplsViewController.kt index e14a612..c7791b2 100644 --- a/src/main/java/com/mapconductor/mappls/MapplsViewController.kt +++ b/src/main/java/com/mapconductor/mappls/MapplsViewController.kt @@ -25,7 +25,7 @@ import com.mapconductor.mappls.marker.MapplsMarkerController import com.mapconductor.mappls.marker.MapplsMarkerOverlayRenderer import com.mapconductor.mappls.marker.MarkerDragLayer import com.mapconductor.mappls.marker.MarkerLayer -import com.mapconductor.mappls.polygon.MapplsPolygonConductor +import com.mapconductor.mappls.polygon.MapplsPolygonController import com.mapconductor.mappls.polyline.MapplsPolylineController import com.mapconductor.mappls.raster.MapplsRasterLayerController import com.mappls.sdk.gestures.MoveGestureDetector @@ -47,7 +47,7 @@ class MapplsViewController( override val holder: MapplsMapViewHolderInterface, internal val markerController: MapplsMarkerController, internal val polylineController: MapplsPolylineController, - internal val polygonController: MapplsPolygonConductor, + internal val polygonController: MapplsPolygonController, internal val groundImageController: MapplsGroundImageController, internal val circleController: MapplsCircleController, internal val rasterLayerController: MapplsRasterLayerController, diff --git a/src/main/java/com/mapconductor/mappls/MapplsViewControllerStyle.kt b/src/main/java/com/mapconductor/mappls/MapplsViewControllerStyle.kt index 91af46a..74b8d03 100644 --- a/src/main/java/com/mapconductor/mappls/MapplsViewControllerStyle.kt +++ b/src/main/java/com/mapconductor/mappls/MapplsViewControllerStyle.kt @@ -81,8 +81,8 @@ internal fun MapplsViewController.setupStyle(style: Style) { (markerController.renderer as MapplsMarkerOverlayRenderer).ensureDefaultIcon(style) // Polygon sources only (layers will be added per zIndex) - ensureGeoJsonSource(style, polygonController.polylineOverlay.layer.sourceId) - ensureGeoJsonSource(style, polygonController.polygonOverlay.layer.sourceId) + ensureGeoJsonSource(style, polygonController.renderer.outline.layer.sourceId) + ensureGeoJsonSource(style, polygonController.renderer.fill.layer.sourceId) // Circle cts as anchor above polygons ensureGeoJsonSource(style, circleController.renderer.layer.sourceId) @@ -157,7 +157,7 @@ internal fun MapplsViewController.setupStyle(style: Style) { (markerController.renderer as MapplsMarkerOverlayRenderer).redraw() circleController.renderer.redraw() polylineController.renderer.redraw() -// polygonController.polygonOverlay.onPostProcess() +// polygonController.renderer.fill.onPostProcess() mainCoroutine.launch { groundImageController.reapplyStyle() rasterLayerController.reapplyStyle() @@ -165,12 +165,12 @@ internal fun MapplsViewController.setupStyle(style: Style) { } internal fun MapplsViewController.ensurePolygonZLayers(style: Style) { - val fillSourceId = polygonController.polygonOverlay.layer.sourceId - val outlineSourceId = polygonController.polylineOverlay.layer.sourceId + val fillSourceId = polygonController.renderer.fill.layer.sourceId + val outlineSourceId = polygonController.renderer.outline.layer.sourceId val anchorId = polylineController.renderer.layer.layerId val zSet = - polygonController.polygonOverlay.polygonManager + polygonController.polygonManager .allEntities() .map { it.state.zIndex } .toSet() diff --git a/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonCompositeRenderer.kt b/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonCompositeRenderer.kt new file mode 100644 index 0000000..b64ecca --- /dev/null +++ b/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonCompositeRenderer.kt @@ -0,0 +1,78 @@ +package com.mapconductor.mappls.polygon + +import com.mapconductor.core.polygon.PolygonEntityInterface +import com.mapconductor.core.polygon.PolygonOverlayRendererInterface +import com.mapconductor.core.polygon.PolygonState +import com.mapconductor.core.polyline.PolylineEntity +import com.mapconductor.core.polyline.PolylineState +import com.mapconductor.mappls.MapplsActualPolygon +import com.mapconductor.mappls.polyline.MapplsPolylineOverlayRenderer + +/** + * 塗りと輪郭を 1 つのレンダラとして [com.mapconductor.core.polygon.PolygonController] に渡すための合成レンダラ。 + * + * fill レイヤーは幅 1 px の輪郭しか描けないので、`strokeWidth` を守るために輪郭は + * 別のポリライン(`outline-`)として [outline] で描く。差分計算はコアの + * PolygonController に任せ、ここは「塗りへの指示を輪郭にも写す」ことだけをする。 + * + * 塗りのエンティティはコントローラと同じ [fill] の polygonManager に載る。輪郭は + * [outline] の polylineManager に載り、コントローラからは見えない。 + */ +class MapplsPolygonCompositeRenderer( + val fill: MapplsPolygonOverlayRenderer, + val outline: MapplsPolylineOverlayRenderer, +) : PolygonOverlayRendererInterface { + override suspend fun onAdd(data: List): List { + val polygons = fill.onAdd(data) + data.forEachIndexed { index, params -> + if (polygons[index] != null) putOutline(params.state) + } + return polygons + } + + override suspend fun onChange( + data: List>, + ): List { + val polygons = fill.onChange(data) + data.forEachIndexed { index, params -> + if (polygons[index] != null) putOutline(params.current.state) + } + return polygons + } + + override suspend fun onRemove(data: List>) { + data.forEach { outline.polylineManager.removeEntity(outlineId(it.state.id)) } + // clear() は onPostProcess を呼ばないので、消した結果はここで描き直す。 + fill.onRemove(data) + outline.onPostProcess() + } + + override suspend fun onPostProcess() { + fill.onPostProcess() + outline.onPostProcess() + } + + private suspend fun putOutline(state: PolygonState) { + val outlineState = state.toOutlineState() ?: return + outline.createPolyline(outlineState)?.let { polyline -> + outline.polylineManager.registerEntity(PolylineEntity(polyline = polyline, state = outlineState)) + } + } +} + +private fun outlineId(polygonId: String): String = "outline-$polygonId" + +/** 外周だけを閉じたポリラインにする(穴の輪郭は描かない)。 */ +private fun PolygonState.toOutlineState(): PolylineState? { + if (points.isEmpty()) return null + val closedPoints = if (points.first() != points.last()) points + points.first() else points + return PolylineState( + points = closedPoints, + id = outlineId(id), + strokeColor = strokeColor, + strokeWidth = strokeWidth, + geodesic = geodesic, + zIndex = zIndex, + extra = extra, + ) +} diff --git a/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonConductor.kt b/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonConductor.kt deleted file mode 100644 index 25bb1a9..0000000 --- a/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonConductor.kt +++ /dev/null @@ -1,153 +0,0 @@ -package com.mapconductor.mappls.polygon - -import com.mapconductor.core.controller.OverlayHit -import com.mapconductor.core.controller.OverlayKind -import com.mapconductor.core.controller.SlottedOverlayController -import com.mapconductor.core.features.GeoPointInterface -import com.mapconductor.core.polygon.PolygonEntity -import com.mapconductor.core.polygon.PolygonEntityInterface -import com.mapconductor.core.polygon.PolygonEvent -import com.mapconductor.core.polygon.PolygonState -import com.mapconductor.core.polyline.PolylineEntity -import com.mapconductor.core.polyline.PolylineState -import com.mapconductor.mappls.polyline.MapplsPolylineOverlayRenderer - -class MapplsPolygonConductor( - val polygonOverlay: MapplsPolygonOverlayRenderer, - val polylineOverlay: MapplsPolylineOverlayRenderer, -) : SlottedOverlayController< - PolygonState, - PolygonEntityInterface, - > { - override val zIndex: Int = 2 - - var clickListener: ((PolygonEvent) -> Unit)? = null - - override suspend fun add(data: List) { - val nextIds = data.asSequence().map { it.id }.toSet() - val prevIds = - polygonOverlay.polygonManager - .allEntities() - .asSequence() - .map { it.state.id } - .toSet() - val removeIds = prevIds - nextIds - - removeIds.forEach { id -> - polygonOverlay.polygonManager.removeEntity(id) - polylineOverlay.polylineManager.removeEntity("outline-$id") - } - - data.forEach { polygonState -> - - polygonOverlay.createPolygon(polygonState)?.let { polygon -> - val polygonEntity = - PolygonEntity( - polygon = polygon, - state = polygonState, - ) - polygonOverlay.polygonManager.registerEntity(polygonEntity) - } - - val polylineState = polygonState.toPolylineState() - polylineOverlay.createPolyline(polylineState)?.let { polyline -> - val polylineEntity = - PolylineEntity( - polyline = polyline, - state = polylineState, - ) - polylineOverlay.polylineManager.registerEntity(polylineEntity) - } - } - polygonOverlay.onPostProcess() - polylineOverlay.onPostProcess() - } - - override suspend fun update(state: PolygonState) { - polygonOverlay.createPolygon(state)?.let { polygon -> - val polygonEntity = - PolygonEntity( - polygon = polygon, - state = state, - ) - polygonOverlay.polygonManager.registerEntity(polygonEntity) - } - - val polylineState = state.toPolylineState() - polylineOverlay.createPolyline(polylineState)?.let { polyline -> - val polylineEntity = - PolylineEntity( - polyline = polyline, - state = polylineState, - ) - polylineOverlay.polylineManager.registerEntity(polylineEntity) - } - polygonOverlay.onPostProcess() - polylineOverlay.onPostProcess() - } - - fun dispatchClick(event: PolygonEvent) { - // 配送座標の wrap は PolygonEvent の生成時に一元化済み。 - event.state.onClick?.invoke(event) - clickListener?.invoke(event) - } - - @Suppress("UNCHECKED_CAST") - override fun find(position: GeoPointInterface): PolygonEntityInterface? = - polygonOverlay.polygonManager.find(position) as? PolygonEntityInterface - - override suspend fun clear() { - polygonOverlay.polygonManager.clear() - polylineOverlay.polylineManager.clear() - polygonOverlay.onPostProcess() - polylineOverlay.onPostProcess() - } - - // ── Capable ファサードのスロットとクリックカスケードへの参加 ────────── - // - // このコンダクタはコアの PolygonController を継承していない(ポリゴンの輪郭を - // ポリラインとして描くために polygon と polyline の 2 レンダラを束ねている)。 - // それでも扱いは他プロバイダのポリゴンと同じでなければならないので、 - // スロットの契約はここで自前で満たす。 - // - // 実際、Step 4 でこれを実装し忘れて `hasPolygon` が常に false になり、 - // ポリゴン単体の状態更新が黙って捨てられていた。 - - override val kind: OverlayKind = OverlayKind.Polygon - - override fun has(id: String): Boolean = polygonOverlay.polygonManager.hasEntity(id) - - @Suppress("UNCHECKED_CAST") - override fun setClickListenerAny(listener: Any?) { - clickListener = listener as? ((PolygonEvent) -> Unit) - } - - override fun resolveTap(position: GeoPointInterface): OverlayHit? = - find(position)?.let { entity -> - OverlayHit(OverlayKind.Polygon, position) { - dispatchClick(PolygonEvent(entity.state, position)) - } - } - - override fun destroy() { - // No native resources to clean up for polygons - } -} - -private fun PolygonState.toPolylineState(): PolylineState { - val closedPoints = - if (points.first() != points.last()) { - points + points.first() - } else { - points - } - return PolylineState( - points = closedPoints, - id = "outline-${this.id}", - strokeColor = this.strokeColor, - strokeWidth = this.strokeWidth, - geodesic = this.geodesic, - zIndex = this.zIndex, - extra = this.extra, - ) -} diff --git a/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonController.kt b/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonController.kt new file mode 100644 index 0000000..28bbc57 --- /dev/null +++ b/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonController.kt @@ -0,0 +1,17 @@ +package com.mapconductor.mappls.polygon + +import com.mapconductor.core.polygon.PolygonController +import com.mapconductor.mappls.MapplsActualPolygon + +/** + * Mappls 用のポリゴンコントローラ。 + * + * 追加・更新・削除の差分計算、`has`、クリックカスケードはコアの [PolygonController] が担う。 + * 塗りと輪郭(幅のある LineLayer)の 2 系統の描画は [MapplsPolygonCompositeRenderer] が束ねる。 + */ +class MapplsPolygonController( + override val renderer: MapplsPolygonCompositeRenderer, +) : PolygonController(renderer.fill.polygonManager, renderer) { + // 旧 MapplsPolygonConductor と同じ値を保つ。 + override val zIndex: Int = 2 +} diff --git a/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonOverlayRenderer.kt b/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonOverlayRenderer.kt index 15f49de..1d15776 100644 --- a/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/mappls/polygon/MapplsPolygonOverlayRenderer.kt @@ -23,10 +23,13 @@ class MapplsPolygonOverlayRenderer( override val holder: MapplsMapViewHolderInterface, override val coroutine: CoroutineScope = CoroutineScope(Dispatchers.Main), ) : AbstractPolygonOverlayRenderer() { + // 消えた分を除いた残りで描き直す。コントローラはこの呼び出しの後で polygonManager から + // 外すので(clear() では onPostProcess も来ない)、ここで除外しておかないと消えずに残る。 override suspend fun onRemove(data: List>) { - coroutine.launch { - holder.map.style?.let { - layer.draw(getAllPolygonEntities(), it) + val polygons = getRemainingPolygonEntities(data) + holder.map.style?.let { + coroutine.launch { + layer.draw(polygons, it) } } } @@ -79,4 +82,11 @@ class MapplsPolygonOverlayRenderer( private fun getAllPolygonEntities(): List> = polygonManager.allEntities() + + private fun getRemainingPolygonEntities( + removed: List>, + ): List> { + val removedIds = removed.mapTo(HashSet()) { it.state.id } + return polygonManager.allEntities().filter { it.state.id !in removedIds } + } }