iOS SDK でヒート マップ レイヤーを追加する (プレビュー)
Note
Azure Maps iOS SDK の廃止
iOS 用 Azure Maps Native SDK は非推奨となり、2025 年 3 月 31 日に廃止されます。 サービスの中断を回避するには、2025 年 3 月 31 日までに Azure Maps Web SDK に移行します。 詳細については、「Azure Maps iOS SDK 移行ガイド」を参照してください。
点密度マップとも呼ばれるヒート マップは、データ視覚化の 1 つの種類です。 一定の範囲の色を使用して、データの密度を表すために使用され、マップ上にデータの "ホット スポット" を示します。 ヒート マップは、多数の点によってデータセットをレンダリングする優れた方法です。
数万個の点を記号としてレンダリングすると、マップのほとんどの領域が覆われてしまう場合があります。 この場合、多くの記号が重なり合う傾向にあります。 より適正にデータを理解することは、難しくなります。 ただし、これと同じデータセットをヒート マップとして視覚化すると、データの各点の密度と相対密度を簡単に把握できます。
ヒート マップは、次のようなさまざまなシナリオで使用できます。
- 気温データ: 2 つのデータ ポイント間の気温の近似値が提供されます。
- ノイズ センサーのデータ: センサーがある場所のノイズの強度が示されるだけでなく、離れた場所での散逸に対する分析情報も提供できます。 個々の場所のノイズ レベルは高くないかもしれません。 複数のセンサーのノイズ感知領域が重なる場合は、この重なる領域においてノイズ レベルがより高くなる可能性があります。 そのため、ヒート マップ上では重なった領域が可視化されます。
- GPS トレース: 速度を、重み付けされたハイト マップとして含めます。ここで、各データ ポイントの強度は速度に基づいています。 たとえば、この機能により、車両のスピードが速められた場所を確認する方法が提供されます。
ヒント
ヒート マップ レイヤーでは、既定ではデータ ソース内のすべてのジオメトリの座標がレンダリングされます。 ポイント ジオメトリ フィーチャーのみがレンダリングされるようにレイヤーを制限するには、レイヤーの filter
オプションを NSPredicate(format: "%@ == \"Point\"", NSExpression.geometryTypeAZMVariable)
に設定します。 MultiPoint 地物も含める場合は、NSCompoundPredicate
を使います。
モノのインターネットに Azure Maps のヒート マップと画像オーバーレイを表示する
前提条件
必ず、iOS アプリの作成のクイック スタートに関するドキュメントの手順を完了してください。 この記事のコード ブロックは、ViewController
の viewDidLoad
関数に挿入できます。
ヒート マップ レイヤーを追加する
ポイントのデータ ソースをヒート マップとしてレンダリングするには、ご自分のデータ ソースを HeatMapLayer
クラスのインスタンスに渡し、それをマップに追加します。
次のコード サンプルでは、過去 1 週間の地震の GeoJSON フィードを読み込んで、ヒート マップとしてレンダリングします。 各データ ポイントは、すべてのズーム レベルで 10 ポイントの半径でレンダリングされます。 ユーザー エクスペリエンスを向上させるため、ラベルがはっきりと見えるように、ヒート マップはラベル レイヤーの下にあります。 このサンプルのデータは、USGS Earthquake Hazards Program (USGS 地震ハザード プログラム) から引用しています。
// Create a data source.
let source = DataSource()
// Import the geojson data and add it to the data source.
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
source.importData(fromURL: url)
// Add data source to the map.
map.sources.add(source)
// Create a heat map layer.
let layer = HeatMapLayer(
source: source,
options: [
.heatmapRadius(10),
.heatmapOpacity(0.8)
]
)
// Add the layer to the map, below the labels.
map.layers.insertLayer(layer, below: "labels")
次のスクリーンショットは、上のコードを使用してヒート マップが読み込まれているマップを示しています。
ヒート マップ レイヤーをカスタマイズする
前の例では、半径と不透明度のオプションを設定してヒート マップをカスタマイズしました。 ヒート マップ レイヤーには、次のようなカスタマイズのためのオプションがいくつか用意されています。
heatmapRadius
: 各データポイントをレンダリングするポイントの半径を定義します。 この半径は、固定数または式として設定できます。 式を使用することにより、ズーム レベルに基づいて半径をスケーリングし、マップ上の一貫した空間領域 (たとえば、5 マイルの半径) を表すことができます。heatmapColor
:ヒート マップの配色方法を指定します。 色のグラデーションは、ヒート マップの一般的な機能です。NSExpression(forAZMInterpolating:curveType:parameters:stops:)
式を利用して、その効果を実現できます。 また、NSExpression(forAZMStepping:from:stops:)
式を使用してヒート マップを色分けし、密度を、等高線またはレーダー スタイル マップのような範囲に視覚的に分割することもできます。 このようなカラー パレットでは、最小濃度値から最大濃度値の色を定義します。ヒート マップの色の値は、
NSExpression.heatmapDensityAZMVariable
値に対する式として指定します。 "補間" 式のインデックス 0 または "段階" 式の既定の色では、データのない領域の色が定義されます。 この値を使用して、背景色を定義することができます。 多くの場合、この値は透明、または半透明の黒に設定されます。色の式の例を次に示します。
// Interpolated color expression
NSExpression(
forAZMInterpolating: .heatmapDensityAZMVariable,
curveType: .linear,
parameters: nil,
stops: NSExpression(forConstantValue: [
0: UIColor.magenta.withAlphaComponent(0),
0.01: UIColor.magenta,
0.5: UIColor(red: 251/255, green: 0, blue: 251/255, alpha: 1),
1: UIColor(red: 0, green: 195/255, blue: 1, alpha: 1)
])
)
// Stepped color expression
NSExpression(
forAZMStepping: .heatmapDensityAZMVariable,
from: NSExpression(forConstantValue: UIColor.clear),
stops: NSExpression(forConstantValue: [
0.01: UIColor(red: 0, green: 0, blue: 128/255, alpha: 1),
0.25: UIColor.cyan,
0.5: UIColor.green,
0.75: UIColor.yellow,
1: UIColor.red
])
)
heatmapOpacity
:ヒート マップ レイヤーの不透明度または透明度を指定します。heatmapIntensity
:ヒート マップの全体的な強度を高めるために、各データ ポイントの重みに乗数を適用します。 これにより、データ ポイントの重みの違いが示され、視覚化しやすくなります。heatmapWeight
:既定では、データ ポイントはすべて、重みが 1 となり、均等に重み付けされています。 weight オプションは乗数として機能し、数値または式として設定できます。 数値を重みとして設定した場合、各データ ポイントをマップ上に 2 回配置することに相当します。 たとえば、重みが2
の場合、密度は 2 倍になります。 weight オプションを数値に設定すると、intensity オプションを使用する場合と同様にヒート マップがレンダリングされます。ただし、式を使用する場合は、各データ ポイントの重みを、各データ ポイントのプロパティに基づいて決めることができます。 たとえば、各データ ポイントが地震を表しているとします。 マグニチュード値は、各地震データ ポイントの重要なメトリックです。 地震は常に発生していますが、多くはマグニチュードが低く、体感することはありません。 各データ ポイントに重みを割り当てるには、式にマグニチュード値を使用します。 マグニチュード値を使用して重みを割り当てると、地震の深刻さをヒート マップ内でよりわかりやすく表すことができます。
minZoom
およびmaxZoom
:レイヤーを表示するズーム レベルの範囲。filter
: ソースからの取得とレイヤーでのレンダリングを制限するために使用されるフィルター述語。sourceLayer
:レイヤーに接続されているデータ ソースがベクター タイルのソースである場合は、ベクター タイル内のソース レイヤーを指定する必要があります。visible
:レイヤーを表示または非表示にします。
次の例では、滑らかな色のグラデーションを作成するために線形補間式を使用しているヒート マップを示しています。 データに定義されている mag
プロパティは、各データ ポイントの重みまたは関連性を設定するために指数補間と共に使用されます。
let layer = HeatMapLayer(source: source, options: [
.heatmapRadius(10),
// A linear interpolation is used to create a smooth color gradient based on the heat map density.
.heatmapColor(
from: NSExpression(
forAZMInterpolating: .heatmapDensityAZMVariable,
curveType: .linear,
parameters: nil,
stops: NSExpression(forConstantValue: [
0: UIColor.black.withAlphaComponent(0),
0.01: UIColor.black,
0.25: UIColor.magenta,
0.5: UIColor.red,
0.75: UIColor.yellow,
1: UIColor.white
])
)
),
// Using an exponential interpolation since earthquake magnitudes are on an exponential scale.
.heatmapWeight(
from: NSExpression(
forAZMInterpolating: NSExpression(forKeyPath: "mag"),
curveType: .exponential,
parameters: NSExpression(forConstantValue: 2),
stops: NSExpression(forConstantValue: [
0: 0,
// Any earthquake above a magnitude of 6 will have a weight of 1
6: 1
])
)
)
])
次のスクリーンショットは、前のヒート マップ例と同じデータを使用して、上記のカスタム ヒート マップ レイヤーを示しています。
一貫性のあるズーム可能なヒート マップ
既定では、ヒート マップ レイヤーにレンダリングされるデータ ポイントの半径には、すべてのズーム レベルの固定ポイント半径が含まれます。 マップをズームすると、データがまとめて集計され、ヒート マップ レイヤーの外観が変化します。 次のビデオは、マップをズームするときにポイント半径が維持されるヒート マップの既定の動作を示しています。
zoom
式を使用すると、各データ ポイントによってマップの同じ物理領域がカバーされるように、各ズーム レベルの半径をスケーリングできます。 この式により、ヒート マップ レイヤーの外観は、より静的かつ一貫性の高いものになります。 マップの各ズーム レベルは、垂直方向および水平方向のポイント数が前のズーム レベルの 2 倍になっています。
ズーム レベルごとに半径が 2 倍になるようにスケーリングすると、すべてのズーム レベルで外観に一貫性のあるヒート マップが作成されます。 このスケーリングを適用するには、次の例に示すように、最小ズーム レベルに設定されたポイント半径と、最大ズーム レベルでスケーリングされた半径が pow(2, maxZoom - minZoom) * radius
として計算された、基数 2 の exponential interpolation
式で NSExpression.zoomLevelAZMVariable
を使用します。 マップをズームして、ヒート マップがズーム レベルに応じてどのように変化するかを確認してください。
let layer = HeatMapLayer(source: source, options: [
.heatmapOpacity(0.75),
.heatmapRadius(
from: NSExpression(
forAZMInterpolating: .zoomLevelAZMVariable,
curveType: .exponential,
parameters: NSExpression(forConstantValue: 2),
stops: NSExpression(forConstantValue: [
// For zoom level 1 set the radius to 2 points.
1: 2,
// Between zoom level 1 and 19, exponentially scale the radius from 2 points to 2 * 2^(maxZoom - minZoom) points.
19: pow(2, 19 - 1) * 2
])
)
)
])
次のビデオでは、上記のコードが実行されているマップを示します。これは、マップをズームしている間に半径を拡大縮小して、ズーム レベル全体で一貫性のあるヒート マップ レンダリングを作成します。
ヒント
データ ソースに対するクラスタリングを有効にすると、相互に近いポイントはクラスター化されたポイントとしてグループ化されます。 各クラスターのポイント数をヒート マップの重み式として使用できます。 これにより、レンダリングされる点の数を大幅に減らすことができます。 クラスターのポイント数は、ポイント フィーチャーの point_count
プロパティに格納されています。
let layer = HeatMapLayer(source: source, options: [
.heatmapWeight(from: NSExpression(forKeyPath: "point_count"))
])
クラスタリングの半径がわずか数ポイントの場合、レンダリングによる視覚的な違いは小さくなります。 半径が大きいほど各クラスター内でグループ化されるポイントが増えるので、ヒート マップのパフォーマンスは向上します。
関連情報
マップに追加するコード例の詳細については、次の記事を参照してください。