Skip to content

fix(plateau): 取得と描画のズームをそろえ、重なりの判定を建物ごとにする - #57

Merged
nyampire merged 2 commits into
mainfrom
fix/plateau-render-timing
Sep 12, 2026
Merged

nyampire merged 2 commits into
mainfrom
fix/plateau-render-timing

Conversation

@nyampire

Copy link
Copy Markdown
Owner

背景

「OSM の建物を読み込むまで Plateau の建物を表示しない作りではないか、それでは何も表示できない」という指摘を受けて調べました。
動いている画面で確かめたところ、独立した原因が 2 つありました。

原因 1 ズーム 15 台では Plateau を取得しない

PixiLayerRapid.js の Plateau の分岐は zoom >= 16 のときだけ取得要求を出します。
一方でレイヤー自身は MINZOOM = 15 から描画に入ります。

この zoomMapSystem.effectiveZoom() の値で、緯度で補正されています。
東京では地図のズームより 0.299 大きくなります。

地図のズーム 補正後 レイヤーが描くか Plateau を取得するか
15.0 15.299 はい いいえ
15.5 15.799 はい いいえ
15.7 15.999 はい いいえ
16.0 16.299 はい はい

東京では地図のズーム 14.7 から 15.7 のあいだ、描画に入るのに取得要求が 1 回も出ません。
待っても出ないため、この範囲では恒久的に何も表示されません。

原因 2 タイル 1 枚の未取得で画面全体が消える

PlateauService.getData() は、視野を覆うタイルを 1 枚でも取得していないと全件を落としていました。

恵比寿のズーム 16.5 で、取得済みのタイル 9 枚のうち 1 枚だけを未取得に戻して測った値です。

状態 未取得タイル 読み込み済みの建物 表示される件数
全部取得済み 0 / 9 9,307 8,099
1 枚を外した 1 / 9 9,307 0
元に戻した 0 / 9 9,307 8,099

変更したこと

ズームの物差しを地図のズームにそろえた

Context.jsviewport.transform.zoomPixiLayerRapid.jseffectiveZoom() と、別の値で比べていました。
両方を地図のズームそのものに変えます。
URL の #map= と同じ値なので閾値を読み違えません。
補正値のままだと、同じ「17」が那覇で 16.85、札幌で 16.49 と場所によって変わります。

取得を始めるズームを上げた

視野を覆うズーム 16 のタイルの枚数です。

地図のズーム 1440x900 1920x1080
15.00 96 枚 137 から 144 枚
16.00 24 から 35 枚 40 から 45 枚
17.00 6 から 12 枚 12 から 15 枚

OSM の取得を地図のズーム 16 から、Plateau の取得と描画を 17 からにします。
ズーム 15 台の 96 枚以上の取得がなくなります。
Plateau は東京でズーム 15.70 から始まっていたので、60 枚前後から 12 枚前後に減ります。

Plateau が出るズーム 17 の時点で、OSM はズーム 16 で 4 倍広い範囲を取得済みです。

都市の範囲の上限を建物の下限に合わせた

PixiLayerPlateauCoverage の上限は補正後のズーム 15 でした。
建物を 17 からにすると、そのあいだは範囲も建物も出ません。

閾値を PLATEAU_BUILDINGS_MINZOOM として 1 か所に置き、両方のレイヤーが読みます。
17 未満では範囲を描き、17 以上では建物を描きます。

重なりの判定を建物ごとにした

視野全体に対する判定をやめ、建物ごとにその建物を覆うタイルが取得済みかを見ます。
取得済みの建物だけを判定に進めるので、読み込めた範囲から順に候補が出ます。

type=buildingtype=multipolygon の relation は relation の範囲で判定し、メンバーの way は親の判定に従います。
外形だけが出て部分が消える形の不整合は起きません。

タイル番号は緯度経度から直接求めます。
建物 1 棟ごとに視野を作って Tiler.getTiles() を呼ぶ形では重すぎるためです。
Tiler と一致することは試験で固定しています。

確かめたこと

試験は 810 件が通り、失敗は 0 件です。
着手前の失敗も 0 件でした。

新しく足した 5 件です。

✔ returns only the building whose covering tile is loaded
✔ returns both buildings once both covering tiles are loaded
✔ hides a whole building relation when one of its tiles is not loaded
✔ shows the whole building relation once every tile it spans is loaded
✔ computes the same tile id as the Tiler does

単体試験は 1,209 件すべて通りました。

動いている画面で測った値です。

ズームの入れ替わりは、16.99 で都市の範囲 306 件と建物 0 件、17.00 で範囲 0 件と建物 121 件です。
どちらも出ないズームはありません。

タイルを未取得に戻したときの影響は、恵比寿のズーム 17 で 6 枚のうち 1 枚を戻して 141 件が 116 件になりました。
消えたのは 18 パーセントで、修正前の同じ操作では 100 パーセントが消えていました。
六本木で 3 枚を戻したときは 167 件が 89 件で、半分ほどが残ります。

タイル番号の計算は、東京の緯度でズーム 15 から 18 の 116 通りを照合し、Tiler と全部一致しました。

この変更に入れていないこと

低いズームで編集を止めること

Context.jseditable() にズームの条件がありません。
OSM の取得をズーム 16 からにすると、ズーム 15 台では OSM のデータが読み込まれないまま編集ができます。
画面が空に見えるため、すでにある建物を重ねて描く余地が広がります。

いまも 14 から 15 のあいだは同じ状態で、窓が 1 段広がります。
編集を止める条件を足すと本体の挙動が変わり、上流の取り込みでぶつかる箇所が増えるため、別の Issue にします。

取得に失敗したタイルの取り直し

OsmService.loadTile() は成功したときだけ取得済みに加えます。
loadTiles() は視野が変わらないあいだ取り直しません。

1 枚が失敗すると、地図を動かすまでその範囲の建物が出ません。
建物ごとの判定を入れたことで影響がその範囲だけに収まるため、別の Issue にします。

設計文書

docs/superpowers/specs/2026-09-12-plateau-render-timing-design.ja.md

🤖 Generated with Claude Code

nyampire and others added 2 commits September 12, 2026 09:40
動いている画面で 2 つの原因を確かめた。
ズーム 15 台ではレイヤーが描画に入るのに取得要求が出ない。
視野を覆うタイルが 1 枚未取得だと、読み込み済みの建物 9,307 件が全部隠れる。

ズームの物差しを地図のズームにそろえ、OSM を 16、Plateau を 17 から取得する。
重なりの判定は視野全体ではなく建物ごとに行う。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
原因は 2 つあった。

1 つは、レイヤーが地図のズーム 14.7 から描画に入るのに、
Plateau の取得要求が 15.7 まで出ないことである。
取得と描画で別のズームの物差しを使っていたためで、待っても状態は変わらない。

もう 1 つは、視野を覆うタイルが 1 枚でも未取得だと、
読み込み済みの建物を全部隠していたことである。
恵比寿のズーム 16.5 では、9 枚のうち 1 枚を未取得に戻すと、
手元にある 9,307 件のうち表示が 0 件になった。

閾値を地図のズームにそろえ、OSM を 16、Plateau を 17 から取得する。
ズーム 15 台で毎回 96 枚以上のタイルを取得していたのをやめる。
都市の範囲の上限を建物の下限に合わせ、どちらも出ないズームを作らない。

重なりの判定は視野全体ではなく建物ごとに行う。
建物を覆うタイルが取得済みのものだけを判定に進めるので、
読み込めた範囲から順に候補が出る。
relation とそのメンバーの way は 1 棟として扱い、まとめて出すか隠す。

タイル番号は緯度経度から直接求める。
Tiler と一致することを試験で固定した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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