Repository navigation
Draw large polyline sets as raster tiles (PolylineTiler) - #36
Merged
Merged
Conversation
Marker, Circle, Polyline, Polygon, GroundImage and RasterLayer states take an optional onAdded, called on the main thread each time the overlay goes from not on the map to on it: after the provider made its native object, or, for tiled overlays, after the tile template was handed to the map as a raster layer (tile images may still be loading). In-place updates, moves between native drawing and tiles, clear and destroy call nothing; remove then add calls again. A throwing callback is logged and does not stop the others. It is kept by each overlay (OverlayAddedTracker), which asks the map hasXxx after compositionXxx returns, so every provider is covered, including those that add without the core controllers. Old constructors and copy() stay as hidden overloads for binary compatibility. Same as ios-sdk-core and js-sdk-core.
…ge makes it untileable Whether a polygon is tiled was decided only on add. Setting geodesic on a tiled polygon in place, or giving it points that span half the world or fewer than three, kept it in the tiles, drawn with straight edges. update() now checks canTile: a polygon that fails it leaves the tiles (its slot in the renderer is emptied, so only the tiles it was in are drawn again) and is handed to the renderer. It stays on the map, so this is not an add. The reverse is left alone: a native polygon that could now be tiled already looks right. Same as js-sdk-core.
…dded where it is called The move-to-native tests used exactly 2,000 parcels, so re-adding the list dropped below the threshold. onAdded is called by PolygonOverlay, not by the controller, so the no-onAdded-on-move test belongs in OverlayOnAddedDeviceTest.
# Conflicts: # api/android-sdk-core.api
Additions only (this branch had not run apiDump); in core, one member moved.
PolylineTilingOptions / PolylineTileSet / PolylineTiler / POLYLINE_TILE_LAYER_ID / polylineTileRasterLayerState and PolylineController.tiler, the same shape as the polygon tiling: tiled polylines stay in PolylineManager for taps and give the renderer nothing (their entity's polyline is null). The tiles share everything below the polygon ones: ShapeTileSet (route, version in the URL, 16 ms coalescing, removal slots), ShapeTiler (routing), ShapeTileRenderer (grid index, per-zoom simplification, LRU cache and stroke-wide invalidation, pooled scratch bitmaps, PNG, cancellation) and ShapeGridIndex. PolygonTileSet, PolygonTiler and PolygonTileRenderer are thin layers over them now. A polyline tile is an open path: snapped to the zoom's pixel grid, Douglas-Peucker at half a pixel with both ends kept, round caps and joins, the stroke as wide in dp at every zoom, a dot as wide as the line when it collapses to a point. Candidates are taken half the widest stroke beyond the tile and drawn whole, so a line crossing a tile edge is the same on both sides. Taps: tapTolerance + strokeWidth / 2, nearest line, with each line's bounding box (made on registration) checked first. PolylineOverlay takes an optional per-map PolylineTilingOptions flow, applied to the map's tilers before every hand-over.
Contributor
Author
|
向け先を |
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.
なぜ
ポリゴンと同じように、ポリラインも数万本を渡せるようにするためです。ボストン市内の道路(54,645 本・234,765 頂点)をネイティブの線で描くと、iOS の Google で全 onAdded まで 114 秒・1.5 GB、Android の Google は Java ヒープが尽きて落ちます。ポリゴンのタイル化(
feat/polygon-tiling)と同じ仕組みで、多数のポリラインをラスタータイルとして描きます。設計の要点(web・Android・iOS で同じ)
Polylines(states):Polygonsと同じ形のまとめて渡す部品。そのインスタンスが足した id だけを足し引きするので、複数のPolylines/Polylineが同じ地図で共存できます(iOS は既存のPolylines(_:)のまま)。PolylineTilingOptions/PolylineTileSet/PolylineTiler/PolylineController.tiler: 名前と既定値(2,000 本以上または頂点 50,000 以上)はポリゴンと 1 対 1。レイヤー id はmc-polyline-tiles。ShapeTileSet/ShapeTiler/ShapeTileRendererに移し、Polygon*はその上の薄い層になりました。公開 API は追加のみです。polylineTilingOptions、Android は compose のPolylineTiling(options)、iOS はMapViewContent.polylineTilingOptions/PolylineTiling要素。このリポジトリで変えたこと
PolylineTilingOptions/PolylineTileSet/PolylineTiler/POLYLINE_TILE_LAYER_ID/polylineTileRasterLayerStateとPolylineController.tiler。タイルで描く線はPolylineManagerに残り(タップ用)、entity の polyline は null。ShapeTileSet(ルート・URL の版・16 ms のまとめ・削除スロット)/ShapeTiler/ShapeTileRenderer(格子索引・ズームごとの簡略化・LRU と線幅ぶんの無効化・Bitmap のプール・PNG・キャンセル)/ShapeGridIndex。PolygonTileSet/PolygonTiler/PolygonTileRendererはその上の薄い層。tapTolerance + strokeWidth / 2、最も近い線、登録時に作る外接矩形で先に絞る。PolylineOverlayが地図ごとのPolylineTilingOptionsの flow を受け取る(引数の追加。1 引数のコンストラクタは残る)。feat/overlay-on-addedを merge commit で取り込み(その中身は develop の API ベースラインの修正 Record the hole union's EdgeGrid and IntArrayList in the API baseline #34 のみ)。検証(Android、追従後の 158d1ee2)
--rerun): core 375・compose 10・arcgis 18・googlemaps 5・here 6・longdo 6・mapbox 1・mappls 4・maptiler 9・tomtom 3・example-app 13 すべて通過。openmobilemaps は 17 件中 1 件失敗(OpenMobileMapsDriverConformanceTest、develop の 5df7b09 で入ったLog.isLoggableがモックされていないため。このブランチの差分は触れていない)。PolygonTileRenderer$Model/$Simplifiedと、PolylineOverlayの 1 引数コンストラクタの行の位置が動いただけ)。挙動の変わる所
PolylineManager.find、タイルでもネイティブでも同じ)。許容距離 = 既存の指の大きさ(tapTolerance)+ 線幅 / 2。太い線は縁から指の大きさ以内であたります。複数あたれば最も近い線。外接矩形で先に候補を絞るので、5 万本でも毎タップ全点をなめません。返す位置(線上の最近点)は今までどおりです。OverlayStacking.rasterKey(styleLayerId:))。追加の順に関係なく、ポリラインのタイルがネイティブのポリラインの下に入ります。SDK の制約で重なり順を守れないもの
確認できていないもの
OutOfMemoryErrorで落ちます(GoogleMap.addPolyline→PolylineOptions.writeToParcel、Java ヒープが上限 512 MB に到達)。1 本ずつ Parcel に詰めて GMS に渡すためで、タイル化ありなら落ちません。このため Google のタイル化あり/なしの時間は並べられていません。OpenMobileMapsDriverConformanceTest1 件(develop のLog.isLoggableがモックされていない)、iOS ArcGIS・TomTom の単体テスト各 1 件、iOS Google のテストターゲットのビルド(GoogleMaps が iOS 17 を要求)。base について
ポリラインの差分だけをレビューできるように、base は
feat/overlay-on-added(feat/polygon-tiling+ onAdded + ボストンのサンプル。そのリポジトリに無い場合は develop)にしています。feat/polygon-tilingは develop にマージ済みなので、feat/overlay-on-addedが develop に入ったら、この PR の base を develop に付け替えてください。追従は rebase せず merge commit で行いました(
origin/feat/polygon-tiling→feat/overlay-on-added→feat/polyline-tiling)。マージの順番
各リポジトリの
feat/overlay-on-added→(base を develop に付け替えて)android-sdk-core → android-sdk-compose → 各プロバイダ → 親。プロバイダは android-sdk-core のPolylineTiler/ 重なり順を使うので core が先です。マージはレビューのうえで判断してください(この PR はまだマージしていません)。親の PR: MapConductor/android-sdk#119