Skip to content

Trace a polygon's fill and outline on one line, closing edge included - #11

Merged
wf9a5m75 merged 2 commits into
developfrom
fix/geodesic-polygon-fill
Nov 8, 2026
Merged

wf9a5m75 merged 2 commits into
developfrom
fix/geodesic-polygon-fill

Conversation

@wf9a5m75

@wf9a5m75 wf9a5m75 commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

なぜ

ポリゴンの点は開いたリング(末尾 ≠ 先頭)で渡されます。WGS84Geodesic.createInterpolatePoints も Planar.createInterpolatePoints も隣り合う点の間しか補間しないので、そのまま渡すと閉じる辺(末尾 → 先頭)だけが補間されず、描画側で閉じたときに 1 本の直線(弦)になっていました。一方、輪郭はリングを閉じてからポリラインとして密度化するので、閉じる辺も他の辺と同じ形になります。

Boston (42.36N, 71.06W) → London (51.5N, 0.12W) → Iceland (64.1N, 21.9W) の三角形(閉じる辺は Iceland → Boston)での数値:

  • geodesic=true: 大圏の中点は 55.6N / 53.2W。同じ経度で Web メルカトルの弦は 51.6N を通ります(約 4° のずれ)。MapLibre などでは「輪郭は曲線、塗りの一辺だけ直線」、Google のように塗りと輪郭を 1 つのネイティブポリゴンで描くプロバイダでは輪郭まで直線でした。
  • geodesic=false: 緯度経度の線形補間の中点は 53.2N / 46.5W、同じ経度で弦は 54.7N(約 1.4° のずれ)。ポリラインの geodesic=false は緯度経度の線形補間なので、輪郭はメルカトル上でわずかに曲がり、塗りの閉じる辺だけ直線でした。

どの補間を正とするか(geodesic=false)

プロバイダ 輪郭(false) 塗りの閉じる辺(false、修正前)
GL 系(MapLibre / Mapbox / Mappls / MapTiler / Longdo)・OMM ポリラインとして線形補間 補間なし(弦)
Google / MapKit / HERE iOS / Longdo iOS / web HERE 塗りと同じネイティブポリゴン 補間なし(弦)。他の辺は線形補間
HERE Android / TomTom(Android・iOS) 塗りと同じネイティブポリゴン 全辺が補間なし(生の頂点)
ArcGIS(web) 塗りと同じ 閉じてから線形補間(済)
Cesium GEODESIC のポリライン RHUMB の 1 本

ポリラインの geodesic=false(全プロバイダで緯度経度の線形補間)と、既に閉じてから密度化している web の ArcGIS に合わせ、閉じる辺も含めて緯度経度で線形補間する方に統一しました。「密度化しない(メルカトルの直線)」に寄せると、ポリラインの false と形が変わり、ArcGIS・Cesium のように辺を測地線でつなぐ SDK では直線を表せないためです。

何を変えたか

  • 外周・穴を、geodesic / false とも js-sdk-core の densifyPolygonRing で閉じる辺まで密度化します(geodesic は 100 km、false は 10 km 刻み。従来どおり)。
  • 輪郭(ground polyline)の arcType を塗りと同じ RHUMB にしました。以前は輪郭が GEODESIC、塗りが RHUMB で、閉じる辺のような長い 1 本の辺では両者が離れていました(三角形の Iceland → Boston の 53.2W で輪郭 55.6N、塗り 51.6N)。密度化した頂点の間では、どちらでも塗りと輪郭が同じ線になります。
  • test/PolygonClosingEdge.test.mjs を追加しました。Cesium をスタブに差し替えてレンダラが作るグラフィックスを記録し、true / false とも塗りと輪郭が同じ頂点・同じ arcType で、閉じる辺が補間されていることを確かめます。

関連 PR(同じ修正の一式)

fix/geodesic-polygon-fill は次の 16 リポジトリにまたがります。

1. core(3 本は互いに独立。先にマージ・公開してください)

core だけで直るプロバイダ(共通パイプライン buildPolygonRings / buildUnwrappedPolygonRings を使うもの)には PR がありません: Android の MapLibre / Mapbox / Mappls / MapTiler / Longdo / OpenMobileMaps、iOS の MapLibre / Mapbox / Mappls / MapTiler / OpenMobileMaps、web の MapLibre / Mapbox / Mappls / MapTiler / TomTom / Longdo / Leaflet / OpenLayers / Azure Maps / deck.gl / MapKit JS / ArcGIS。

2. Android プロバイダ(android-sdk-core の公開後。densifyPolygonRing を使うのでそれまでビルドできません。ArcGIS だけは core に依存しません)

3. iOS プロバイダ(ios-sdk-core の公開後。ArcGIS だけは core に依存しません)

4. web プロバイダ(js-sdk-core の新しい版を npm に公開し、依存(今は ^0.3.1)を引き上げてから。npm の公開はまだ行いません)

マージの順番: core 3 本 → core の公開 → Android / iOS プロバイダ → js-sdk-core の npm 公開と依存の引き上げ → web プロバイダ。

見た目が変わるもの: ArcGIS(Android / iOS)の geodesic=false の閉じる辺は、以前は補間されず ArcGIS が測地線として描いていましたが、他の辺と同じ緯度経度の線形補間になります(web の react-for-arcgis と同じ形で、3 プラットフォームがそろう方向。承認済み)。ほかのプロバイダも geodesic=false の閉じる辺がわずかに曲がるようになります。

検証

  • npm test(7 本通過)。追加した 4 本は develop のレンダラでは落ちることを確かめました。
  • tsc --noEmit 通過。
  • ブラウザ(Playwright)で三角形を表示し、false でも輪郭と塗りが重なることを確かめました。

確認できていないもの

  • 世界マスク級の大きなポリゴンでの描画(特に TomTom の geodesic=false)は実機で確かめていません。
  • npm 公開前なので、web プロバイダは公開版の js-sdk-core では動きません(集約リポジトリ内でソースを差し替えて確認しました)。

他の PR との関係

  • このリポジトリに OPEN な PR はありません。

The geodesic ring was densified with createInterpolatePoints, which only
interpolates between neighbouring points. The closing edge (last vertex ->
first) was left to the RHUMB fill as a single chord while the GEODESIC
outline polyline curved, so fill and outline disagreed there. Use
js-sdk-core's densifyGeodesicRing. geodesic=false is unchanged.

Requires the js-sdk-core release that adds densifyGeodesicRing.
geodesic=false rings went through Planar.createInterpolatePoints, which
only interpolates between neighbouring points, so the closing edge (last
vertex -> first) was a single long segment: the RHUMB fill drew it as a
loxodrome and the GEODESIC outline as a great circle, which visibly parted
(Boston -> London -> Iceland: at 53.2W on Iceland -> Boston the outline
passes 55.6N, the fill 51.6N). Densify every ring with js-sdk-core's
densifyPolygonRing in both modes (it replaces the unreleased
densifyGeodesicRing), and give the outline the fill's RHUMB arc type so
the two take the same segment between the densified vertices.

A test renders a polygon against a stubbed Cesium and checks that fill
and outline share their vertices and arc type in both modes.

Requires the js-sdk-core release that adds densifyPolygonRing.
@wf9a5m75
wf9a5m75 merged commit 228c9f6 into develop Nov 8, 2026
1 check 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