fix(plateau): 取得と描画のズームをそろえ、重なりの判定を建物ごとにする - #57
Merged
Merged
Conversation
動いている画面で 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>
This was referenced Sep 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
「OSM の建物を読み込むまで Plateau の建物を表示しない作りではないか、それでは何も表示できない」という指摘を受けて調べました。
動いている画面で確かめたところ、独立した原因が 2 つありました。
原因 1 ズーム 15 台では Plateau を取得しない
PixiLayerRapid.jsの Plateau の分岐はzoom >= 16のときだけ取得要求を出します。一方でレイヤー自身は
MINZOOM = 15から描画に入ります。この
zoomはMapSystem.effectiveZoom()の値で、緯度で補正されています。東京では地図のズームより 0.299 大きくなります。
東京では地図のズーム 14.7 から 15.7 のあいだ、描画に入るのに取得要求が 1 回も出ません。
待っても出ないため、この範囲では恒久的に何も表示されません。
原因 2 タイル 1 枚の未取得で画面全体が消える
PlateauService.getData()は、視野を覆うタイルを 1 枚でも取得していないと全件を落としていました。恵比寿のズーム 16.5 で、取得済みのタイル 9 枚のうち 1 枚だけを未取得に戻して測った値です。
変更したこと
ズームの物差しを地図のズームにそろえた
Context.jsはviewport.transform.zoom、PixiLayerRapid.jsはeffectiveZoom()と、別の値で比べていました。両方を地図のズームそのものに変えます。
URL の
#map=と同じ値なので閾値を読み違えません。補正値のままだと、同じ「17」が那覇で 16.85、札幌で 16.49 と場所によって変わります。
取得を始めるズームを上げた
視野を覆うズーム 16 のタイルの枚数です。
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=buildingとtype=multipolygonの relation は relation の範囲で判定し、メンバーの way は親の判定に従います。外形だけが出て部分が消える形の不整合は起きません。
タイル番号は緯度経度から直接求めます。
建物 1 棟ごとに視野を作って
Tiler.getTiles()を呼ぶ形では重すぎるためです。Tilerと一致することは試験で固定しています。確かめたこと
試験は 810 件が通り、失敗は 0 件です。
着手前の失敗も 0 件でした。
新しく足した 5 件です。
単体試験は 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.jsのeditable()にズームの条件がありません。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