Mapboxの非表示シンボルを扱う (2. Featureの解決編)
2022-09-16 (2022-09-24 更新)
Mapbox GL JSの画面上で別のシンボルに隠されたシンボルを扱うユーティリティライブラリを開発中です。 これはライブラリの開発過程を紹介するシリーズのブログ投稿第2弾です。
背景
このシリーズの前回の投稿で、以下の疑問が残りました。
Tile
とSymbolBucket
はどうやって取得するのか?- 再計算した衝突ボックスとシンボルのFeatureをどうやって対応づけるのか?
このブログ投稿では上記の疑問に答え、前回のブログ投稿で見落としていたアイコンの大きさを計算する方法についてもカバーします。
このライブラリはhttps://github.com/codemonger-io/mapbox-collision-boxesで手に入ります。
Mapbox GL JS (mapbox-gl-js
)のバージョン2.9.2*を分析しました。
* このブログを書いている段階で最新バージョンは2.10.0でしたが、一貫性を保つためにバージョン2.9.2で続けます。
TileとSymbolBucketを取得する
前回のブログ投稿で、どのシンボルを画面に表示するかを決定するのにPlacement#placeLayerBucketPart
が重要な役割を果たしていることがわかりました。
このメソッドがどのように呼び出されているかを調べれば、Tile
とSymbolBucket
をどうやって取得するかがわかるかもしれません。
SymbolBucketを解決する
LayerPlacement#continuePlacement
はPlacement#placeLayerBucketPart
を繰り返し呼び出します(style/pauseable_placement.js#L50-L57)。
while this._currentPartIndex < bucketParts.length
Placement#getBucketParts
によって作成されるbucketParts
の各要素は処理の対象となるSymbolBucket
を提供します(BucketPart#parameters
→ TileLayerParameters#bucket
)。
Placement#getBucketParts
は当該メソッド3番目の引数のTile
からSymbolBucket
を取り出します(symbol/placement.js#L233-L234)。
results: Array<BucketPart>, styleLayer: StyleLayer, tile: Tile, sortAcrossTiles: boolean
つまり、StyleLayer
とTile
があれば、SymbolBucket
も手に入ります。
StyleLayerとTileを解決する
LayerPlacement#continuePlacement
はPlacement#getBucketParts
を繰り返し呼び出します(style/pauseable_placement.js#L35-L43)。
while this._currentTileIndex < tiles.length
上記スニペットのtiles
とstyleLayer
はLayerPlacement#continuePlacement
に対する引数です。
PauseablePlacement#continuePlacement
はLayerPlacement#continuePlacement
を繰り返し呼び出します(style/pauseable_placement.js#L97-L123, layerTiles[layer.source]
→ tiles
, layer
→ styleLayer
)。
while this._currentPlacementIndex >= 0
以下の条件判定(style/pauseable_placement.js#L101)からわかるとおり、PausePlacement#continuePlacement
はLayerPlacement#continuePlacement
を"Symbol"レイヤーにのみ適用します。
if layer.type === 'symbol' &&
上記スニペットのorder
, layers
, layerTiles
はPauseablePlacement#continuePlacement
に対する引数です。
Style#_updatePlacement
はPauseablePlacement#continuePlacement
を呼び出します(style/style.js#L1740)。
this._order, this._layers, layerTiles;
Style#_updatePlacement
はstyle/style.js#L1696-L1712でlayerTiles
を用意しています。
;
for of this._order
ということで上記コードを真似すれば、与えたレイヤーIDに対応するStyleLayer
とすべてのTile
を取得することができます。
レイヤーのTileとSymbolBucketをリストする
まとめると、指定したレイヤーのTile
とSymbolBucket
をリストするコードのアウトラインは以下のようになります。
// 仮定 map: mapboxgl.Map, layerId: string
;
;
;
;
for of layerTiles
追加のチェックを含む完成したコードは私のGitHubレポジトリにあります。
シンボルのFeatureを解決する
前回の投稿で、FeatureIndex
はシンボルのFeatureを解決する上で重要であることに軽く触れました。
Map#queryRenderedFeatures
を調べることでそれがわかりました。
概要:Map#queryRenderedFeaturesがどのように機能するか
Map#queryRenderedFeatures
はStyle#queryRenderedFeatures
を呼び出します(ui/map.js#L1719)。
return geometry, options, this.transform;
Style#queryRenderedFeatures
はqueryRenderedSymbols
を呼び出します(style/style.js#L1384-L1391)。
this._layers,
this._serializedLayers,
this,
queryGeometryStruct.screenGeometry,
params,
this.placement.collisionIndex,
this.placement.retainedQueryData
queyrRenderedSymbols
はFeatureIndex#lookupSymbolFeatures
を呼び出し、シンボルに対応するFeatureを取得します(source/query_features.js#L95-L103)。
;
FeatureIndex#lookupSymbolFeatures
は最初のパラメータrenderedSymbols[queryData.bucketInstanceId]
に対応するGeoJSON形式のFeatureを解決し、読み込みます。
なので、FeatureIndex#lookupSymbolFeatures
に適切なパラメータを与えることでFeatureを解決することができます。
FeatureIndex#lookupSymbolFeaturesに対するパラメータを用意する
FeatureIndex#lookupSymbolFeatures
の呼び出し結果(source/query_features.js#L95-L103)を再現するには以下のパラメータを提供する必要があります。
ちなみに最初のパラメータrenderedSymbols[queryData.bucketInstanceId]
を再現する必要はありません。なぜならSymbolBucket
で特定のバウンディングボックスと重なるFeatureではなくすべてのFeatureが必要だからです。
このパラメータをどのように置き換えるかについては節「SymbolBucketのすべてのFeatureのインデックスをリストする」を参照ください。
パラメータ: queryData
queryData
はループ変数でRetainedQueryData
が代入されます(source/query_features.js#L94-L132)。
for of bucketQueryData
bucketQueryData
はRetainedQueryData
の配列でsource/query_features.js#L88-L92で初期化されます。
;
for of renderedSymbolsNumber
sortTilesIn;
retainedQueryData
はPlacement#retainedQueryData
です。
queryRenderedSymbols
はrenderedSymbols
を初期化します(source/query_features.js#L87)。
;
CollisionIndex#queryRenderedSymbols
はbucketInstanceId
をSymbolBucket
内でそのbucketInstanceId
に対応し指定のバウンディングボックスと重なるFeatureのインデックス列にマップするオブジェクトを返します。
表示されているシンボルのみを扱うのでライブラリではCollisionIndex#queryRenderedSymbols
は使いません。
SymbolBucket
のリストは持っているので、各SymbolBucket#bucketInstanceId
に対応するRetainedQueryData
をPlacement#retainedQueryData
から得ることができます。
// 仮定 placement: Placement, bucket: SymbolBucket
;
パラメータ: serializedLayers
このパラメータはStyle#_serializedLayers
です。
パラメータ: params.filter
Map#queryRenderedFeatures
はデフォルトで空のオブジェクトをStyle#queryRenderedFeatures
のparams
引数に指定します(options
→ params
, ui/map.js#L1716-L1719)。
options = options ||;
geometry = geometry ||;
return geometry, options, this.transform;
なのでこのパラメータはundefined
でよいです。
パラメータ: params.layers
params.filter
と同様に、このパラメータもundefined
でよいです。
パラメータ: params.availableImages
Style#queryRenderedFeatures
はStyle#_availableImages
をこのパラメータに指定しています(style/style.js#L1354)。
params.availableImages = this._availableImages;
パラメータ: styleLayers
このパラメータはStyle#_layers
です。
SymbolBucketのすべてのFeatureのインデックスをリストする
FeatureIndex#lookupSymbolFeatures
が最初の引数(symbolFeatureIndexes
)として受け取るFeatureのインデックスとは何でしょうか?
CollisionIndex#queryRenderedSymbols
は使いませんが、それが何をしているのかを調べればFeatureIndex#lookupSymbolFeatures
の正しい入力を理解するのに役立つはずです。
この後に続く分析は大変なので先に結論からお伝えします。
SymbolBucket
のすべてのFeatureのインデックスをリストするには、SymbolBucket#symbolInstances
のすべての要素からfeatureIndex
プロパティを取り出す、もしくはSymbolBucket#collisionArrays
のすべての要素からiconFeatureIndex
プロパティを取り出します。
// 仮定 bucket: SymbolBucket
// SymbolBucket#symbolInstancesは通常の配列ではないので注意
for ; i < bucket.symbolInstances.length; ++i>
Featureを衝突ボックスに対応づけるのは単純です。なぜなら上記コードのfeatureIndex
はbucket.collisionArrays[i]
(衝突ボックス再計算のためのパラメータ)に対応しているからです。
この節の残りは次の節「アイコンの大きさを計算する」まで飛ばして構いません。
CollisionIndex#queryRenderedSymbolsは何をしているのか?
CollisionIndex#queryRenderedSymbols
はGridIndex#query
を呼び出し、指定したバウンディングボックスと重なるFeatureをリストします(symbol/collision_index.js#L360-L361)。
minX, minY, maxX, maxY;
それからfeatures
のすべての要素をsymbol/collision_index.js#L366-L396のループで処理します。
for of features
CollisionIndex#queryRenderedSymbols
は最終的に上記コードで更新されたresult
を返します。
ではGridIndex#query
が返すfeatures
とは何でしょうか?
GridIndex#query
は指定したバウンディングボックスと重なるGridItem
の配列を返します。
GridIndex#query
はこれらのGridItem
をGridIndex
がFeatureキーと一緒に格納しているボックスとサークルの情報(GridIndex#bboxes
, GridIndex#circles
, GridIndex#boxKeys
, GridIndex#circleKeys
)から構築します。
ということで、GridIndex#boxKeys
(サークルのことは忘れましょう)の起源を追跡すれば、SymbolBucket
のすべてのFeatureのインデックスを取得する方法がわかるはずです。
GridIndex#boxKeysの起源
GridIndex#insert
はGridIndex#boxKeys
にkey
を追加します(symbol/grid_index.js#L73)。
key;
CollisionIndex#insertCollisionBox
がkey
を用意しGridIndex#insert
に渡します(symbol/collision_index.js#L401-L406)。
collisionBox: Array<number>, ignorePlacement: boolean, bucketInstanceId: number, featureIndex: number, collisionGroupID: number
ここで上記スニペットのkey
を構成するfeatureIndex
の起源に関心が移ります。
featureIndexの起源
シンボルのアイコンに絞ると、Placement#placeLayerBucketPart.placeSymbol
(placeSymbol
)はsymbol/placement.js#L748-L749でCollisionIndex#insertCollisionBox
を呼び出しています。
placedIconBoxes.box, 'icon-ignore-placement',
bucket.bucketInstanceId, iconFeatureIndex, collisionGroup.ID;
placeSymbol
はsymbol/placement.js#L698でiconFeatureIndex
を設定しています。
iconFeatureIndex = collisionArrays.iconFeatureIndex;
collisionArrays
はCollisionArrays
でありplaceSymbol
の3番目の引数です。
今度はCollisionArrays
の起源を追いかけます。
Placement#placeLayerBucketPart
はplaceSymbol
をsymbol/placement.js#L791またはsymbol/placement.js#L795で呼び出しています。
symbolIndex, symbolIndex, bucket.collisionArrays;
i, i, bucket.collisionArrays;
よってCollisionArrays
はSymbolBucket#collisionArrays
の要素です。
Placement#placeLayerBucketPart
はSymbolBucket#deserializeCollisionBoxes
を呼び出してSymbolBucket#collisionArrays
を初期化して埋めます(symbol/placement.js#L432)。
collisionBoxArray;
SymbolBucket#deserializeCollisionBoxes
はCollisionArrays#iconFeatureIndex
を実際に設定するSymbolBucket#_deserializeCollisionBoxesForSymbol
を呼び出します(data/bucket/symbol_bucket.js#L962-L968)。
for ; k < iconEndIndex; k++
ではSymbolBucket#deserializeCollisionBoxes
に与えるcollisionBoxArray
とは何者でしょうか(symbol/placement.js#L432)?
collisionBoxArrayの起源
collisionBoxArray
はTileLayerParameters
に含まれており、Placement#getBucketParts
はそれをTile#collisionBoxArray
から取得します(symbol/placement.js#L242)。
;
Tile#loadVectorData
はTile#collisionBoxArray
を設定します(source/tile.js#L245)。
this.collisionBoxArray = data.collisionBoxArray;
Tile#loadVectorData
はsource/geojson_source.js#L372とsource/vector_tile_source.js#L320で呼び出されています。
data, this.map.painter, message === 'reloadTile';
data, this.map.painter;
上記呼び出しはVectorTileWorkerSource#loadTile
もしくはVectorTileWorkerSource#reloadTile
の結果として発生します。
VectorTileWorkerSource#loadTile
とVectorTileWorkerSource#reloadTile
のいずれも生のVector Tileデータを解析するのにWorkerTile#parse
を呼び出します。
WorkerTile#parse
は解析したデータをsource/worker_tile.js#L261-L272で出力します。
null, ;
上記コードのcollisionBoxArray
(=WorkerTile#collisionBoxArray
)は結果的にTile#collisionBoxArray
になります。
シンボルのアイコンに絞ると、WorkerTile#parse
はsource/worker_tile.js#L239-L248でperformSymbolLayout
を呼び出し、WorkerTile#collisionBoxArray
を更新します。
bucket,
glyphMap,
glyphAtlas.positions,
iconMap,
imageAtlas.iconPositions,
this.showCollisionBoxes,
availableImages,
this.tileID.canonical,
this.tileZoom,
this.projection;
このコンテキストではbucket
はSymbolBucket
であり、またSymbolBucket#collisionBoxArray
はBucketを生成する関数(source/worker_tile.js#L155-L168)に与えられるWorkerTile#collisionBoxArray
を指していることにご注意ください。
;
performSymbolLayout
はbucket
内のFeatureをリストし、symbol/symbol_layout.js#L322でaddFeature
を呼び出します。
bucket, feature, shapedTextOrientations, shapedIcon, imageMap, sizes, layoutTextSize, layoutIconSize, textOffset, isSDFIcon, availableImages, canonical, projection;
addFeature
(正確にはその内部関数addSymbolAtAnchor
)はaddSymbol
を呼び出します(symbol/symbol_layout.js#L438-L442)。
bucket, anchor, globe, line, shapedTextOrientations, shapedIcon, imageMap, verticallyShapedIcon, bucket.layers,
bucket.collisionBoxArray, feature.index, feature.sourceLayerIndex,
bucket.index, textPadding, textAlongLine, textOffset,
iconBoxScale, iconPadding, iconAlongLine, iconOffset,
feature, sizes, isSDFIcon, availableImages, canonical;
シンボルのアイコンに絞ると、addSymbol
はsymbol/symbol_layout.js#L731でevaluateBoxCollisionFeature
を呼び出します。
iconBoxIndex = collisionBoxArray, collisionFeatureAnchor, anchor, featureIndex, sourceLayerIndex, bucketIndex, shapedIcon, iconPadding, iconRotate;
evaluateBoxCollisionFeature
はcollisionBoxArray
に要素を追加します(symbol/symbol_layout.js#L634)。
projectedAnchor.x, projectedAnchor.y, projectedAnchor.z, tileAnchor.x, tileAnchor.y, x1, y1, x2, y2, padding, featureIndex, sourceLayerIndex, bucketIndex;
ここでcollisionBoxArray
はWorkerTile#collisionBoxArray
と同一であることにご注意ください。
SymbolBucket#symbolInstances vs SymbolBucket#collisionArrays
行symbol/placement.js#L791と行symbol/placement.js#L795によれば、SymbolBucket#symbolInstances
の要素はSymbolBucket#collisionArrays
の要素に対応しています。
symbolIndex, symbolIndex, bucket.collisionArrays;
i, i, bucket.collisionArrays;
addSymbol
はsymbol/symbol_layout.js#L854-L884でSymbolBucket#symbolInstances
にも要素を追加しています。
projectedAnchor.x,
projectedAnchor.y,
projectedAnchor.z,
anchor.x,
anchor.y,
placedTextSymbolIndices.right >= 0 ? placedTextSymbolIndices.right : -1,
placedTextSymbolIndices.center >= 0 ? placedTextSymbolIndices.center : -1,
placedTextSymbolIndices.left >= 0 ? placedTextSymbolIndices.left : -1,
placedTextSymbolIndices.vertical >= 0 ? placedTextSymbolIndices.vertical : -1,
placedIconSymbolIndex,
verticalPlacedIconSymbolIndex,
key,
textBoxIndex !== undefined ? textBoxIndex : bucket.collisionBoxArray.length,
textBoxIndex !== undefined ? textBoxIndex + 1 : bucket.collisionBoxArray.length,
verticalTextBoxIndex !== undefined ? verticalTextBoxIndex : bucket.collisionBoxArray.length,
verticalTextBoxIndex !== undefined ? verticalTextBoxIndex + 1 : bucket.collisionBoxArray.length,
iconBoxIndex !== undefined ? iconBoxIndex : bucket.collisionBoxArray.length,
iconBoxIndex !== undefined ? iconBoxIndex + 1 : bucket.collisionBoxArray.length,
verticalIconBoxIndex ? verticalIconBoxIndex : bucket.collisionBoxArray.length,
verticalIconBoxIndex ? verticalIconBoxIndex + 1 : bucket.collisionBoxArray.length,
featureIndex,
numHorizontalGlyphVertices,
numVerticalGlyphVertices,
numIconVertices,
numVerticalIconVertices,
useRuntimeCollisionCircles,
0,
textOffset0,
textOffset1,
collisionCircleDiameter;
つまり、SymbolBucket#symbolInstances
とSymbolBucket#collisionArrays
の対応する要素は、それぞれ featureIndex
とiconFeatureIndex
に全く同じFeatureのインデックスを持っています。
FeatureIndex#lookupSymbolFeaturesは何をしているのか?
FeatureIndex#lookupSymbolFeatures
は実際には何をしているのでしょうか?
SymbolBucket#symbolInstances
から取り出したFeatureのインデックス(featureIndex
)を最初の引数(symbolFeatureIndexes
)に指定するのは理にかなっているでしょうか?
FeatureIndex#lookupSymbolFeatures
はFeatureIndex#loadMatchingFeature
を繰り返し呼び出しています(data/feature_index.js#L257-L272, symbolFeatureIndex
→ featureIndexData.featureIndex
)。
for of symbolFeatureIndexes
FeatureIndex#loadMatchingFeature
はfeatureIndex
をdata/feature_index.js#L188-L190でFeatureを読み込むのに使っています。
;
;
;
一方で、performSymbolLayout
はSymbolBucket#features
内のFeatureを列挙し、ひとつずつaddFeature
に渡しています(symbol/symbol_layout.js#L197-L324)。
for of bucket.features
ではSymbolBucket#features
はどこから来るのでしょうか?
SymbolBucket#populate
がSymbolBucket#features
を初期化して埋めています(data/bucket/symbol_bucket.js#L475-L626)。
features: Array<IndexedFeature>, options: PopulateParameters, canonical: CanonicalTileID, tileTransform: TileTransform
WorkerTile#parse
はBucketを生成した直後にSymbolBucket#populate
を呼び出しています(source/worker_tile.js#L171)。
features, options, this.tileID.canonical, this.tileTransform;
そしてWorkerTile#parse
は最初の引数のfeatures
をsource/worker_tile.js#L137-L142で用意しています。
;
for ; index < sourceLayer.length; index++
ということで上記コード内のindex
は最終的に他のFeatureに関する情報と併せてSymbolBucket#symbolInstances
のfeatureIndex
となります。
よって SymbolBucket#symbolInstances
のfeatureIndex
プロパティはFeatureIndex#lookupSymbolFeatures
の最初の引数symbolFeatureIndexes
と整合性がとれていることがわかりました。
アイコンの大きさを計算する
前回の投稿で、アイコンのscale
パラメータを再現できると結論づけました。
しかし、partiallyEvaluatedIconSize
を計算するためのevaluateSizeForZoom
関数がmapbox-gl-js
からエクスポートされていないことに後から気づきました。
ということでライブラリを実装するためにはmapbox-gl-js
からevaluateSizeForZoom
の複製を作成しなければなりませんでした。
evaluateSizeForZoom
が機能するために、以下の型や関数も複製しなければなりませんでした。
SizeData
InterpolatedSize
InterpolationType
interpolationFactor
exponentialInterpolation
interpolate
clamp
複製したものは私のGitHubレポジトリにあります。
まとめ
このブログ投稿では、Tile
とSymbolBucket
をリストし、シンボルのFeatureを解決する方法を示しました。
最終的なループは以下のようになります。
// 仮定 map: mapboxgl.Map, layerId: string
;
;
;
;
for of layerTiles
またアイコンのサイズを計算する方法もカバーしました。
ライブラリを実装している途中、mapbox-gl-js
の内部タイプが利用できないというTypeScript特有の課題に直面しました。
今後のブログ投稿で、その課題にどう対処したかを共有するつもりです。
私のGitHubレポジトリでライブラリもご確認ください!
補足
ソースコードレファレンス
Map
Map#queryRenderedFeatures
このメソッドはMap#queryRenderedFeatures
APIを実装します。
Style
Style#_layers
_layers: ;
Style#_serializedLayers
_serializedLayers: ;
Style#_availableImages
_availableImages: Array<string>;
Style#queryRenderedFeatures
定義: style/style.js#L1330-L1396
query_features.queryRenderedSymbols
定義: source/query_features.js#L79-L149
Style#_updatePlacement
定義: src/style/style.js#L1692-L1766
このメソッドはPauseablePlacement#continuePlacement
を呼び出します。
Tile
Tile#tileID
tileID: OverscaledTileID;
Tile#collisionBoxArray
collisionBoxArray: ?CollisionBoxArray;
Tile#loadVectorData
VectorTileWorkerSource
定義: source/vector_tile_worker_source.js#L140-L309
VectorTileWorkerSource#loadTile
定義: source/vector_tile_worker_source.js#L177-L238
このメソッドはWorkerスレッドで実行されます。
VectorTileWorkerSource#reloadTile
定義: source/vector_tile_worker_source.js#L244-L275
このメソッドはWorkerスレッドで実行されます。
WorkerTile
定義: source/worker_tile.js#L36-L277
WorkerTile#collisionBoxArray
collisionBoxArray: CollisionBoxArray;
WorkerTile#parse
定義: source/worker_tile.js#L83-L276
symbol_layout.performSymbolLayout
定義: symbol/symbol_layout.js#L152-L329
WorkerTile#parse
はこの関数を呼び出します(source/worker_tile.js#L239-L248)。
bucket,
glyphMap,
glyphAtlas.positions,
iconMap,
imageAtlas.iconPositions,
this.showCollisionBoxes,
availableImages,
this.tileID.canonical,
this.tileZoom,
this.projection;
symbol_layout.addFeature
定義: symbol/symbol_layout.js#L367-L500
シンボルのアイコンに絞ると、symbol_layout.performSymbolLayout
はsymbol/symbol_layout.js#L322でこの関数を呼び出します。
bucket, feature, shapedTextOrientations, shapedIcon, imageMap, sizes, layoutTextSize, layoutIconSize, textOffset, isSDFIcon, availableImages, canonical, projection;
symbol_layout.addSymbol
定義: symbol/symbol_layout.js#L657-L885
この関数はSymbolBucket#symbolInstances
を更新します(symbol/symbol_layout.js#L854-L884)。
projectedAnchor.x,
projectedAnchor.y,
projectedAnchor.z,
anchor.x,
anchor.y,
placedTextSymbolIndices.right >= 0 ? placedTextSymbolIndices.right : -1,
placedTextSymbolIndices.center >= 0 ? placedTextSymbolIndices.center : -1,
placedTextSymbolIndices.left >= 0 ? placedTextSymbolIndices.left : -1,
placedTextSymbolIndices.vertical >= 0 ? placedTextSymbolIndices.vertical : -1,
placedIconSymbolIndex,
verticalPlacedIconSymbolIndex,
key,
textBoxIndex !== undefined ? textBoxIndex : bucket.collisionBoxArray.length,
textBoxIndex !== undefined ? textBoxIndex + 1 : bucket.collisionBoxArray.length,
verticalTextBoxIndex !== undefined ? verticalTextBoxIndex : bucket.collisionBoxArray.length,
verticalTextBoxIndex !== undefined ? verticalTextBoxIndex + 1 : bucket.collisionBoxArray.length,
iconBoxIndex !== undefined ? iconBoxIndex : bucket.collisionBoxArray.length,
iconBoxIndex !== undefined ? iconBoxIndex + 1 : bucket.collisionBoxArray.length,
verticalIconBoxIndex ? verticalIconBoxIndex : bucket.collisionBoxArray.length,
verticalIconBoxIndex ? verticalIconBoxIndex + 1 : bucket.collisionBoxArray.length,
featureIndex,
numHorizontalGlyphVertices,
numVerticalGlyphVertices,
numIconVertices,
numVerticalIconVertices,
useRuntimeCollisionCircles,
0,
textOffset0,
textOffset1,
collisionCircleDiameter;
symbol_layout.addFeature
の内部関数addSymbolAtAnchor
がこの関数を呼び出します(symbol/symbol_layout.js#L438-L442)。
bucket, anchor, globe, line, shapedTextOrientations, shapedIcon, imageMap, verticallyShapedIcon, bucket.layers,
bucket.collisionBoxArray, feature.index, feature.sourceLayerIndex,
bucket.index, textPadding, textAlongLine, textOffset,
iconBoxScale, iconPadding, iconAlongLine, iconOffset,
feature, sizes, isSDFIcon, availableImages, canonical;
symbol_layout.evaluateBoxCollisionFeature
定義: symbol/symbol_layout.js#L580-L637
この関数はcollisionBoxArray
を更新します(symbol/symbol_layout.js#L634)。
projectedAnchor.x, projectedAnchor.y, projectedAnchor.z, tileAnchor.x, tileAnchor.y, x1, y1, x2, y2, padding, featureIndex, sourceLayerIndex, bucketIndex;
シンボルのアイコンに絞ると、symbol_layout.addSymbol
はsymbol/symbol_layout.js#L731でこの関数を呼び出します。
iconBoxIndex = collisionBoxArray, collisionFeatureAnchor, anchor, featureIndex, sourceLayerIndex, bucketIndex, shapedIcon, iconPadding, iconRotate;
StyleLayer
定義: style/style_layer.js#L39-L323
SymbolBucket
定義: data/bucket/symbol_bucket.js#L352-L1119
SymbolBucket#bucketInstanceId
定義: data/bucket/symbol_bucket.js#L368
bucketInstanceId: number;
SymbolBucket#features
定義: data/bucket/symbol_bucket.js#L378
features: Array<SymbolFeature>;
SymbolBucket#collisionArrays
定義t: data/bucket/symbol_bucket.js#L380
collisionArrays: Array<CollisionArrays>;
このプロパティの要素はSymbolBucket#symbolInstances
の要素に対応します。
SymbolBucket#deserializeCollisionBoxes
はこのプロパティを初期化して埋めます。
SymbolBucket#symbolInstances
定義: data/bucket/symbol_bucket.js#L379
symbolInstances: SymbolInstanceArray;
このプロパティの要素はSymbolBucket#collisionArrays
の要素に対応します。
SymbolBucket#collisionBoxArray
定義: data/bucket/symbol_bucket.js#L356
SymbolBucket#populate
定義: data/bucket/symbol_bucket.js#L475-L626
SymbolBucket#deserializeCollisionBoxes
定義: data/bucket/symbol_bucket.js#L979-L995
このメソッドはSymbolBucket#collisionArrays
を初期化して埋めます。
SymbolBucket#_deserializeCollisionBoxesForSymbol
定義: data/bucket/symbol_bucket.js#L943-L977
FeatureIndex
定義: data/feature_index.js#L54-L312
FeatureIndex#lookupSymbolFeatures
定義: data/feature_index.js#L244-L274
このメソッドはFeatureIndex#loadMatchingFeature
を呼び出します(data/feature_index.js#L258-L270)。
result, ,
filter,
filterLayerIDs,
availableImages,
styleLayers,
serializedLayers
;
FeatureIndex#loadMatchingFeature
定義: data/feature_index.js#L172-L240
このメソッドはシンボルのFeature(GeoJSON形式)をVector Tileデータから読み込みます。
CollisionIndex
定義: symbol/collision_index.js#L64-L465
CollisionIndex#queryRenderedSymbols
定義: symbol/collision_index.js#L341-L399
CollisionIndex#insertCollisionBox
定義: symbol/collision_index.js#L401-L406
collisionBox: Array<number>, ignorePlacement: boolean, bucketInstanceId: number, featureIndex: number, collisionGroupID: number
GridIndex
定義: symbol/grid_index.js#L24-L341
GridIndex#bboxes
bboxes: Array<number>;
GridIndex#boxKeys
もご覧ください。
GridIndex#boxKeys
boxKeys: Array<any>;
このプロパティはGridIndex#bboxes
内の同じインデックスにあるボックスに対応するFeatureのキーを格納します。
GridIndex#insert
はこのプロパティを更新します。
GridIndex#circles
circles: Array<number>;
GridIndex#circleKeys
もご覧ください。
GridIndex#circleKeys
circleKeys: Array<any>;
このプロパティはGridIndex#circles
内の同じインデックスにあるサークルに対応するFeatureのキーを格納します。
GridIndex#insert
定義: symbol/grid_index.js#L71-L78
このメソッドは指定したkey
をGridIndex#boxKeys
に追加します(symbol/grid_index.js#L73)。
key;
GridIndex#query
定義: symbol/grid_index.js#L163-L165
x1: number, y1: number, x2: number, y2: number, predicate?: any : Array<GridItem>
GridIndex#_query
もご覧ください。
GridIndex#_query
定義: symbol/grid_index.js#L98-L137
このメソッドはGridIndex#_forEachCell
を呼び出します(symbol/grid_index.js#L134)。
x1, y1, x2, y2, this._queryCell, result, queryArgs, predicate;
GridIndex#_forEachCell
定義: symbol/grid_index.js#L291-L303
x1: number, y1: number, x2: number, y2: number, fn: any, arg1: any, arg2?: any, predicate?: any
このメソッドは指定したバウンディングボックスと重なるすべてのセルにfn
を適用します。
GridIndex#query
のコンテキストでは、fn
はGridIndex#_queryCell
です。
GridIndex#_queryCell
定義: symbol/grid_index.js#L175-L240
このメソッドは指定したセルで指定したバウンディングボックスと重なるボックスとサークルを集めます。
GridItem
定義: symbol/grid_index.js#L3-L9
;
Placement
定義: symbol/placement.js#L192-L1184
Placement#retainedQueryData
retainedQueryData: ;
RetainedQueryData
もご覧ください。
Placement#getBucketParts
定義: symbol/placement.js#L233-L333
LayerPlacement#continuePlacement
はこのメソッドを呼び出します(style/pauseable_placement.js#L37)。
bucketParts, styleLayer, tile, this._sortAcrossTiles;
前回のブログ投稿の関連する節もご覧ください。
Placement#placeLayerBucketPart
定義: symbol/placement.js#L386-L808
LayerPlacement#continuePlacement
はこのメソッドを呼び出します(style/pauseable_placement.js#L52)。
bucketPart, this._seenCrossTileIDs, showCollisionBoxes, bucketPart.symbolInstanceStart === 0;
前回のブログ投稿の関連する節もご覧ください。
Placement#placeLayerBucketPart.placeSymbol
定義: symbol/placement.js#L439-L784
RetainedQueryData
定義: symbol/placement.js#L87-L105
BucketPart
定義: symbol/placement.js#L183-L188
;
TileLayerParameters
もご覧ください。
TileLayerParameters
定義: symbol/placement.js#L169-L181
;
PauseablePlacement
定義: style/pauseable_placement.js#L62-L132
PauseablePlacement#continuePlacement
定義: style/pauseable_placement.js#L89-L126
このメソッドはLayerPlacement#continuePlacement
を呼び出します。
Style#_updatePlacement
はこのメソッドを呼び出します(style/style.js#L1740)。
this._order, this._layers, layerTiles;
LayerPlacement
定義: style/pauseable_placement.js#L15-L60
LayerPlacement#continuePlacement
定義: style/pauseable_placement.js#L32-L59
このメソッドは以下を呼び出します。
PauseablePlacement#continuePlacement
はこのメソッドを呼び出します(style/pauseable_placement.js#L109)。
;
symbol_size.SizeData
定義: symbol/symbol_size.js#L15-L32
;
symbol_size.InterpolatedSize
定義: symbol/symbol_size.js#L34-L37
;
symbol_size.evaluateSizeForZoom
定義: symbol/symbol_size.js#L92-L118
interpolate.InterpolationType
定義: style-spec/expression/definitions/interpolate.js#L17-L20
;
Interpolate.interpolationFactor
定義: style-spec/expression/definitions/interpolate.js#L45-L57
interpolate.exponentialInterpolation
定義: style-spec/expression/definitions/interpolate.js#L255-L266
util.interpolate
定義: style-spec/util/interpolate.js#L5-L7
util.clamp
SymbolInstanceArray
定義: data/array_types.js#L1188-L1198
この配列の各要素はSymbolInstanceStruct
です。
SymbolInstanceStruct
定義: data/array_types.js#L1146-L1179
CollisionArrays
定義: data/bucket/symbol_bucket.js#L90-L99
;