Skip to content

Extend core PolygonController for polygons (drop hand-copied conductor) - #12

Merged
wf9a5m75 merged 2 commits into
developfrom
refactor/polygon-controller
Nov 8, 2026
Merged

wf9a5m75 merged 2 commits into
developfrom
refactor/polygon-controller

Conversation

@wf9a5m75

@wf9a5m75 wf9a5m75 commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

なぜ

MapLibre / Mapbox / Mappls の fill レイヤーは幅のない 1 px の輪郭しか描けません。strokeWidth を守るため、これら 3 プロバイダはポリゴンの外周を別のポリライン(outline-<id>)としてポリラインレンダラで描いています。コントローラが 2 つのレンダラを動かす必要があり、コアの PolygonController はレンダラを 1 つしか受け取らないので、MapplsPolygonConductor は SlottedOverlayController を自前で実装していました。

その結果、コアの PolygonController に入った変更はすべて手で写す必要があり、実際に 2 回漏れています。

  • Step 4 で has を写し忘れ、hasPolygon が常に false になってポリゴン単体の状態更新が黙って捨てられていた
  • ポリゴンのタイラーを destroy で解放する変更がこの 3 つに届かなかった

MapTiler はコアの PolygonController を継承しており、これが本来の形です。

何を変えたか

  • MapplsPolygonConductor を削除し、コアの PolygonController を継承する MapplsPolygonController に置き換えました。差分計算(指紋による変更なしのスキップを含む)、has / find、クリックカスケード(resolveTap / dispatchClick / setClickListenerAny)、update、clear、destroy はすべてコアの実装になります。zIndex = 2 は従来の値を維持しています。
  • MapplsPolygonCompositeRenderer を追加しました。既存の MapplsPolygonOverlayRenderer(塗り)と MapplsPolylineOverlayRenderer(輪郭)を包み、コアには 1 つのレンダラとして見せます。onAdd / onChange は塗りに渡したうえで、成功したポリゴンについて輪郭ポリラインを作り直します。onRemove は輪郭を外し、両方のソースを描き直します。onPostProcess は両方を描き直します。輪郭のステート(外周を閉じたもの、id outline-<id>、strokeColor/Width、geodesic、zIndex、extra)は従来と同じです。穴の輪郭を描かない点も同じです。
  • MapplsPolygonOverlayRenderer.onRemove は、消えたポリゴンを除いた残りを描くようにしました。コアの clear() は onPostProcess を呼ばず、onRemove の後でエンティティを忘れます。従来の onRemove(スタイルが有ればマネージャ全体を遅延で描き直す)は描き直しのタイミング次第で消えたポリゴンを描いてしまうことがあり、clear の後に残る可能性がありました。
  • 呼び出し側(getPolygonController、ViewController、スタイル設定)は polygonController.renderer.fill / .renderer.outline / .polygonManager を参照するように変えました。

コアには変更を入れていません(android-sdk-core の PR はありません)。

細かな挙動差(意図したもの)

  • 従来の add() は毎回すべてのポリゴンを作り直していましたが、今後はコアと同じく指紋が変わらないポリゴンを描き直しません(描画結果は同じです)。
  • 塗りの生成に失敗したポリゴン(createMapplsPolygons が空)は輪郭も描きません。従来は輪郭だけが登録され、二度と消えないまま残っていました。

検証

develop の各リポジトリ(core / compose / 他プロバイダ / example-app は origin/develop の worktree)に対して、3 プロバイダだけをこのブランチに差し替えた init script で :example-app をビルドしました。

  • ユニットテスト: 4 件中 4 件成功(develop と同じ)。
  • apiCheck: 下の API 差分のみ。develop の時点で既に apiCheck が MapplsMarkerController$Companion.getTILE_REFRESH_COALESCE の追加(この PR と無関係)で失敗しており、この行は .api に含めていません。それ以外の差分はありません。
  • ktlint: 追加・変更したコードに新しい指摘はありません(既存ファイルの既存の指摘は develop と同じです)。
  • 実機(タブレット HA26Z6JL): 検証専用ページ(コミットしていません)で、develop の APK と このブランチの APK を同じ手順で動かし、各フェーズのスクリーンショットを比較しました。
    • 図形: A(zIndex 1、穴あり、赤 8dp 輪郭、青塗り)、B(zIndex 2、黒 4dp、緑)を A と重ねる、C(zIndex 0、1dp 紫、黄)、それらを横切るポリライン(橙 6dp)、マーカー
    • フェーズ: 0 初期表示 → 1 A の塗り色・輪郭色・幅(14dp)を状態の書き換えで更新(update 経路)→ 2 A の頂点と穴を書き換え → 3 B を外す → 4 全部外す → 5 作り直す
    • タップ: A のみの点 → polygon:A、A∩B → polygon:B(zIndex が上)、A の穴 → 地図クリック、C → polygon:C、外側 → 地図クリック、マーカー → マーカーのクリック。develop / このブランチとも 6 件すべて同じ結果でした
    • プロバイダ切り替え: MapLibre で開始し、同じプロセスのまま Mappls へ切り替えてから同じ手順を実行しました。
    • 結果: 全フェーズ(7 枚)で、図形周辺の領域(950×1000 px)に閾値 40 を超える画素差は 0 px でした。輪郭の幅・色、穴、ポリゴン同士の zIndex(B が A の上)、ポリラインとマーカーがポリゴンの上に描かれる点、更新・削除・全削除・再追加のすべてが develop と同じ描画です。

API 差分(api/android-for-mappls.api)

プロバイダ内部のクラスを置き換えたことによる差分です。

  • 削除: com.mapconductor.mappls.polygon.MapplsPolygonConductor(とメンバー無しの MapplsPolygonConductorKt)
  • 追加: MapplsPolygonController(PolygonController<…> を継承。コンストラクタ引数は MapplsPolygonCompositeRenderer、getRenderer() / getZIndex())、MapplsPolygonCompositeRenderer(PolygonOverlayRendererInterface<…> を実装。getFill() / getOutline() / onAdd / onChange / onRemove / onPostProcess)、メンバー無しの MapplsPolygonCompositeRendererKt
  • 型の変更: getPolygonController(…) の戻り値と、MapplsViewController のコンストラクタの polygonController 引数の型が MapplsPolygonConductor から MapplsPolygonController に変わりました。

いずれもプロバイダ内部の配線用で、アプリが直接使う API(MapplsMapView や PolygonState)には影響しません。

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.
The conductor that develop's teardown change touched is gone here; its
destroy() cleared the polygon and outline managers. Core's PolygonController
now clears the polygon manager on destroy, and this controller clears the
outline renderer's manager on top.
@wf9a5m75
wf9a5m75 merged commit 8e5b8e9 into develop Nov 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant