Android SDK kümeleme noktası verileri
Haritada çok sayıda veri noktasını görselleştirirken, veri noktaları birbirleriyle çakışabilir. Çakışma, eşlemenin okunamaz hale gelmesine ve kullanılması zor olmasına neden olabilir. Kümeleme noktası verileri, birbirine yakın olan nokta verisini birleştirme ve bunları haritada tek bir kümelenmiş veri noktası olarak temsil etme işlemidir. Kullanıcı haritada yakınlaştırdıktan sonra, kümeler kendi bireysel veri noktalarıyla kesilir. Çok sayıda veri noktasıyla çalışırken, Kullanıcı deneyiminizi geliştirmek için kümeleme süreçlerini kullanın.
Önkoşullar
Hızlı başlangıç: Android uygulama belgesi oluşturma ' daki adımları tamamladığınızdan emin olun. Bu makaledeki kod blokları haritalar onReady olay işleyicisine eklenebilir.
Veri kaynağında kümeleme etkinleştiriliyor
DataSourceSeçeneğini olarak ayarlayarak sınıfında kümelendirmeyi etkinleştirin cluster true . clusterRadiusYakın noktaları seçmek ve bunları bir kümeyle birleştirmek için ayarlayın. Değeri clusterRadius piksel cinsinden olur. clusterMaxZoomKümeleme mantığının devre dışı bırakılacağı yakınlaştırma düzeyini belirtmek için kullanın. Veri kaynağında kümelemenin nasıl etkinleştirileceği hakkında bir örnek aşağıda verilmiştir.
//Create a data source and enable clustering.
DataSource source = new DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(45),
//The maximum zoom level in which clustering occurs.
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom(15)
);
//Create a data source and enable clustering.
val source = DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(45),
//The maximum zoom level in which clustering occurs.
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom(15)
)
Dikkat
Kümeleme yalnızca özelliklerle birlikte kullanılabilir Point . Veri kaynağınız, veya gibi diğer geometri türlerinin özelliklerini içeriyorsa LineString Polygon , bir hata meydana gelir.
İpucu
İki veri noktası arka planda yakınsa, kullanıcının ne kadar yakın yakınlaştırılmadığına bakılmaksızın kümenin hiçbir şekilde hiçbir şekilde kesintiye uğramaması mümkündür. Bunu çözmek için, clusterMaxZoom kümeleme mantığını devre dışı bırakma ve her şeyi görüntüleme seçeneğini belirleyebilirsiniz.
DataSourceSınıfı, kümeleme ile ilgili aşağıdaki yöntemleri de sağlar.
| Yöntem | Dönüş türü | Description |
|---|---|---|
getClusterChildren(Feature clusterFeature) |
FeatureCollection |
Sonraki yakınlaştırma düzeyinde verilen kümenin alt öğelerini alır. Bu alt öğeler şekil ve alt kümelerin bir birleşimi olabilir. Alt kümeler, ClusteredProperties ile eşleşen özelliklerle özellik olacaktır. |
getClusterExpansionZoom(Feature clusterFeature) |
int |
Kümenin genişlemekte veya parçalanmasına başlayacağı yakınlaştırma düzeyini hesaplar. |
getClusterLeaves(Feature clusterFeature, long limit, long offset) |
FeatureCollection |
Kümedeki tüm noktaları alır. limit' İ, noktaların bir alt kümesini döndürecek şekilde ayarlayın ve ' ı offset noktaları üzerinden kullanın. |
Balon bir katman kullanarak kümeleri görüntüleme
Kabarcık katmanı, kümelenmiş noktaları işlemek için harika bir yoldur. Yarıçapı ölçeklendirmek için ifadeleri kullanın ve kümedeki noktaların sayısına göre rengi değiştirin. Kümeleri bir kabarcık katmanı kullanarak görüntülediğinizde, kümelenmemiş veri noktalarını işlemek için ayrı bir katman kullanmanız gerekir.
Kabarcığun üzerine kümenin boyutunu göstermek için, metinle birlikte bir simge katmanı kullanın ve simge kullanmayın.
Aşağıdaki kod, bir kabarcık katmanı kullanan kümelenmiş noktaları ve bir sembol katmanını kullanan her kümedeki noktaların sayısını görüntüler. Bir küme içinde olmayan ayrı noktaları göstermek için ikinci bir sembol katmanı kullanılır.
//Create a data source and add it to the map.
DataSource source = new DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(45),
//The maximum zoom level in which clustering occurs.
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom(15)
);
//Import the geojson data and add it to the data source.
map.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson");
//Add data source to the map.
map.sources.add(source);
//Create a bubble layer for rendering clustered data points.
map.layers.add(new BubbleLayer(source,
//Scale the size of the clustered bubble based on the number of points in the cluster.
bubbleRadius(
step(
get("point_count"),
20, //Default of 20 pixel radius.
stop(100, 30), //If point_count >= 100, radius is 30 pixels.
stop(750, 40) //If point_count >= 750, radius is 40 pixels.
)
),
//Change the color of the cluster based on the value on the point_cluster property of the cluster.
bubbleColor(
step(
toNumber(get("point_count")),
color(Color.GREEN), //Default to lime green.
stop(100, color(Color.YELLOW)), //If the point_count >= 100, color is yellow.
stop(750, color(Color.RED)) //If the point_count >= 100, color is red.
)
),
bubbleStrokeWidth(0f),
//Only rendered data points which have a point_count property, which clusters do.
BubbleLayerOptions.filter(has("point_count"))
));
//Create a symbol layer to render the count of locations in a cluster.
map.layers.add(new SymbolLayer(source,
iconImage("none"), //Hide the icon image.
textField(get("point_count")), //Display the point count as text.
textOffset(new Float[]{ 0f, 0.4f }),
//Allow clustered points in this layer.
SymbolLayerOptions.filter(has("point_count"))
));
//Create a layer to render the individual locations.
map.layers.add(new SymbolLayer(source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
));
//Create a data source and add it to the map.
val source = DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(45),
//The maximum zoom level in which clustering occurs.
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom(15)
)
//Import the geojson data and add it to the data source.
map.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")
//Add data source to the map.
map.sources.add(source)
//Create a bubble layer for rendering clustered data points.
map.layers.add(
BubbleLayer(
source,
//Scale the size of the clustered bubble based on the number of points in the cluster.
bubbleRadius(
step(
get("point_count"),
20, //Default of 20 pixel radius.
stop(100, 30), //If point_count >= 100, radius is 30 pixels.
stop(750, 40) //If point_count >= 750, radius is 40 pixels.
)
),
//Change the color of the cluster based on the value on the point_cluster property of the cluster.
bubbleColor(
step(
toNumber(get("point_count")),
color(Color.GREEN), //Default to lime green.
stop(100, color(Color.YELLOW)), //If the point_count >= 100, color is yellow.
stop(750, color(Color.RED)) //If the point_count >= 100, color is red.
)
),
bubbleStrokeWidth(0f),
//Only rendered data points which have a point_count property, which clusters do.
BubbleLayerOptions.filter(has("point_count"))
)
)
//Create a symbol layer to render the count of locations in a cluster.
map.layers.add(
SymbolLayer(
source,
iconImage("none"), //Hide the icon image.
textField(get("point_count")), //Display the point count as text.
textOffset(arrayOf(0f, 0.4f)),
//Allow clustered points in this layer.
SymbolLayerOptions.filter(has("point_count"))
)
)
//Create a layer to render the individual locations.
map.layers.add(
SymbolLayer(
source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
)
)
Aşağıdaki görüntüde, yukarıdaki kod, kümelenmiş nokta özelliklerinin küme içindeki nokta sayısına göre ölçeklendirildi ve renklendirilmiş bir kabarcık katmanında gösterildiği gösterilmektedir. Kümelenmemiş noktaları sembol katmanı kullanılarak işlenir.

Sembol katmanı kullanarak kümeleri görüntüleme
Veri noktalarını görselleştirirken sembol katmanı, temizleyici bir kullanıcı arabirimi sağlamak için birbirleriyle çakışan sembolleri otomatik olarak gizler. Haritada veri noktaları yoğunluğunu göstermek istiyorsanız bu varsayılan davranış istenmeyen bir durum olabilir. Ancak, bu ayarlar değiştirilebilir. Tüm sembolleri göstermek için, iconAllowOverlap sembol katmanının seçeneğini olarak ayarlayın true .
Temiz bir kullanıcı arabirimi tutarken veri noktaları yoğunluğunu göstermek için kümeleme kullanın. Aşağıdaki örnekte, sembol katmanını kullanarak özel semboller ekleme ve kümeleri ve bireysel veri noktalarını temsil etme adımları gösterilmektedir.
//Load all the custom image icons into the map resources.
map.images.add("earthquake_icon", R.drawable.earthquake_icon);
map.images.add("warning_triangle_icon", R.drawable.warning_triangle_icon);
//Create a data source and add it to the map.
DataSource source = new DataSource(
//Tell the data source to cluster point data.
cluster(true)
);
//Import the geojson data and add it to the data source.
map.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson");
//Add data source to the map.
map.sources.add(source);
//Create a symbol layer to render the clusters.
map.layers.add(new SymbolLayer(source,
iconImage("warning_triangle_icon"),
textField(get("point_count")),
textOffset(new Float[]{ 0f, -0.4f }),
//Allow clustered points in this layer.
filter(has("point_count"))
));
//Create a layer to render the individual locations.
map.layers.add(new SymbolLayer(source,
iconImage("earthquake_icon"),
//Filter out clustered points from this layer.
filter(not(has("point_count")))
));
//Load all the custom image icons into the map resources.
map.images.add("earthquake_icon", R.drawable.earthquake_icon)
map.images.add("warning_triangle_icon", R.drawable.warning_triangle_icon)
//Create a data source and add it to the map.
val source = DataSource(
//Tell the data source to cluster point data.
cluster(true)
)
//Import the geojson data and add it to the data source.
map.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")
//Add data source to the map.
map.sources.add(source)
//Create a symbol layer to render the clusters.
map.layers.add(
SymbolLayer(
source,
iconImage("warning_triangle_icon"),
textField(get("point_count")),
textOffset(arrayOf(0f, -0.4f)),
//Allow clustered points in this layer.
filter(has("point_count"))
)
)
//Create a layer to render the individual locations.
map.layers.add(
SymbolLayer(
source,
iconImage("earthquake_icon"),
//Filter out clustered points from this layer.
filter(not(has("point_count")))
)
)
Bu örnekte, aşağıdaki görüntü uygulamanın çizilebilir klasörüne yüklenir.
| earthquake_icon.png | warning_triangle_icon.png |
Aşağıdaki görüntüde, yukarıdaki kod işleme kümelenmiş ve kümelenmemiş nokta özellikleri özel simgeler kullanılarak gösterilmektedir.

<a name="clustering-and-the-heat-maps-layer">Kümeleme ve ısı haritaları katmanı
Isı haritaları haritadaki verilerin yoğunluğunu görüntülemenin harika bir yoludur. Bu görselleştirme yöntemi, kendi başına çok sayıda veri noktasını işleyebilir. Veri noktaları kümelenir ve küme boyutu ısı haritasının ağırlığı olarak kullanılıyorsa, ısı haritası daha da fazla veri işleyebilir. Bu seçeneği başarmak için, heatmapWeight ısı haritası katmanının seçeneğini olarak ayarlayın get("point_count") . Küme yarıçapı küçük olduğunda, ısı haritası kümelenmemiş veri noktalarını kullanarak bir ısı haritası ile neredeyse özdeş olacaktır, ancak çok daha iyi işlem yapar. Ancak, küme yarıçapı ne kadar küçükse, ısı haritası daha doğru olacaktır, ancak daha az performans avantajları olur.
//Create a data source and add it to the map.
DataSource source = new DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(10)
);
//Import the geojson data and add it to the data source.
map.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson");
//Add data source to the map.
map.sources.add(source);
//Create a heat map and add it to the map.
map.layers.add(new HeatMapLayer(source,
//Set the weight to the point_count property of the data points.
heatmapWeight(get("point_count")),
//Optionally adjust the radius of each heat point.
heatmapRadius(20f)
), "labels");
//Create a data source and add it to the map.
val source = DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(10)
)
//Import the geojson data and add it to the data source.
map.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")
//Add data source to the map.
map.sources.add(source)
//Create a heat map and add it to the map.
map.layers.add(
HeatMapLayer(
source,
//Set the weight to the point_count property of the data points.
heatmapWeight(get("point_count")),
//Optionally adjust the radius of each heat point.
heatmapRadius(20f)
), "labels"
)
Aşağıdaki görüntüde, yukarıdaki kod, kümelenmiş nokta özellikleri kullanılarak en iyi duruma getirilmiş bir ısı haritasını ve ısı eşlemesindeki ağırlık olarak küme sayısını gösterir.

Kümelenmiş veri noktalarında fare olayları
Kümelenmiş veri noktaları içeren bir katmanda fare olayları gerçekleştiğinde, kümelenmiş veri noktası olaya GeoJSON Point özellik nesnesi olarak döner. Bu nokta özelliği aşağıdaki özelliklere sahip olacaktır:
| Özellik adı | Tür | Description |
|---|---|---|
cluster |
boolean | Özelliğin bir kümeyi temsil ettiğini belirtir. |
point_count |
sayı | Kümenin içerdiği noktaların sayısı. |
point_count |
sayı | Kümenin içerdiği noktaların sayısı. |
point_count_abbreviated |
string | point_countLong ise değeri abbreviates bir dize. (örneğin, 4.000 4K olur) |
Bu örnek, küme noktalarını işleyen ve bir tıklama olayı ekleyen bir kabarcık katmanı alır. Click olayı tetiklendiğinde, kod, kümenin parçalama yaptığı sonraki yakınlaştırma düzeyine kadar olan eşlemeyi hesaplar ve büyütür. Bu işlev, getClusterExpansionZoom DataSource sınıfının yöntemi ve cluster_id tıklanan kümelenmiş veri noktasının özelliği kullanılarak uygulanır.
//Create a data source and add it to the map.
DataSource source = new DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(45),
//The maximum zoom level in which clustering occurs.
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom(15)
);
//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson");
//Add data source to the map.
map.sources.add(source);
//Create a bubble layer for rendering clustered data points.
BubbleLayer clusterBubbleLayer = new BubbleLayer(source,
//Scale the size of the clustered bubble based on the number of points in the cluster.
bubbleRadius(
step(
get("point_count"),
20f, //Default of 20 pixel radius.
stop(100, 30), //If point_count >= 100, radius is 30 pixels.
stop(750, 40) //If point_count >= 750, radius is 40 pixels.
)
),
//Change the color of the cluster based on the value on the point_cluster property of the cluster.
bubbleColor(
step(
get("point_count"),
color(Color.GREEN), //Default to green.
stop(100, color(Color.YELLOW)), //If the point_count >= 100, color is yellow.
stop(750, color(Color.RED)) //If the point_count >= 100, color is red.
)
),
bubbleStrokeWidth(0f),
//Only rendered data points which have a point_count property, which clusters do.
BubbleLayerOptions.filter(has("point_count"))
);
//Add the clusterBubbleLayer and two additional layers to the map.
map.layers.add(clusterBubbleLayer);
//Create a symbol layer to render the count of locations in a cluster.
map.layers.add(new SymbolLayer(source,
//Hide the icon image.
iconImage("none"),
//Display the 'point_count_abbreviated' property value.
textField(get("point_count_abbreviated")),
//Offset the text position so that it's centered nicely.
textOffset(new Float[] { 0f, 0.4f }),
//Only rendered data points which have a point_count property, which clusters do.
SymbolLayerOptions.filter(has("point_count"))
));
//Create a layer to render the individual locations.
map.layers.add(new SymbolLayer(source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
));
//Add a click event to the cluster layer so we can zoom in when a user clicks a cluster.
map.events.add((OnFeatureClick) (features) -> {
if(features.size() > 0) {
//Get the clustered point from the event.
Feature cluster = features.get(0);
//Get the cluster expansion zoom level. This is the zoom level at which the cluster starts to break apart.
int expansionZoom = source.getClusterExpansionZoom(cluster);
//Update the map camera to be centered over the cluster.
map.setCamera(
//Center the map over the cluster points location.
center((Point)cluster.geometry()),
//Zoom to the clusters expansion zoom level.
zoom(expansionZoom),
//Animate the movement of the camera to the new position.
animationType(AnimationType.EASE),
animationDuration(200)
);
}
//Return true indicating if event should be consumed and not passed further to other listeners registered afterwards, false otherwise.
return true;
}, clusterBubbleLayer);
//Create a data source and add it to the map.
val source = DataSource( //Tell the data source to cluster point data.
//The radius in pixels to cluster points together.
cluster(true),
//The maximum zoom level in which clustering occurs.
clusterRadius(45),
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom(15)
)
//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")
//Add data source to the map.
map.sources.add(source)
//Create a bubble layer for rendering clustered data points.
val clusterBubbleLayer = BubbleLayer(
source,
//Scale the size of the clustered bubble based on the number of points in the cluster.
bubbleRadius(
step(
get("point_count"),
20f, //Default of 20 pixel radius.
stop(100, 30), //If point_count >= 100, radius is 30 pixels.
stop(750, 40) //If point_count >= 750, radius is 40 pixels.
)
),
//Change the color of the cluster based on the value on the point_cluster property of the cluster.
bubbleColor(
step(
get("point_count"),
color(Color.GREEN), //Default to green.
stop(
100,
color(Color.YELLOW)
), //If the point_count >= 100, color is yellow.
stop(750, color(Color.RED)) //If the point_count >= 100, color is red.
)
),
bubbleStrokeWidth(0f),
//Only rendered data points which have a point_count property, which clusters do.
BubbleLayerOptions.filter(has("point_count"))
)
//Add the clusterBubbleLayer and two additional layers to the map.
map.layers.add(clusterBubbleLayer)
//Create a symbol layer to render the count of locations in a cluster.
map.layers.add(
SymbolLayer(
source,
//Hide the icon image.
iconImage("none"),
//Display the 'point_count_abbreviated' property value.
textField(get("point_count_abbreviated")),
//Offset the text position so that it's centered nicely.
textOffset(
arrayOf(
0f,
0.4f
)
),
//Only rendered data points which have a point_count property, which clusters do.
SymbolLayerOptions.filter(has("point_count"))
)
)
//Create a layer to render the individual locations.
map.layers.add(
SymbolLayer(
source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
)
)
//Add a click event to the cluster layer so we can zoom in when a user clicks a cluster.
map.events.add(OnFeatureClick { features: List<Feature?>? ->
if (features.size() > 0) {
//Get the clustered point from the event.
val cluster: Feature = features.get(0)
//Get the cluster expansion zoom level. This is the zoom level at which the cluster starts to break apart.
val expansionZoom: Int = source.getClusterExpansionZoom(cluster)
//Update the map camera to be centered over the cluster.
map.setCamera(
//Center the map over the cluster points location.
center(cluster.geometry() as Point?),
//Zoom to the clusters expansion zoom level.
zoom(expansionZoom),
//Animate the movement of the camera to the new position.
animationType(AnimationType.EASE),
animationDuration(200)
)
}
true
}, clusterBubbleLayer)
Aşağıdaki görüntüde, yukarıdaki kod, tıklandığı zaman bir haritanın bir sonraki yakınlaştırma düzeyine yakınlaştırılmasına ve genişlemesine kadar bir harita üzerinde görüntüsünü gösterir.

Küme alanını görüntüle
Bir kümenin temsil ettiği nokta verileri bir alanın üzerine yayılır. Bu örnekte, fare bir kümenin üzerine gelindiğinde iki ana davranış oluşur. İlk olarak, kümede bulunan bireysel veri noktaları, bir convex hull hesaplamak için kullanılacaktır. Ardından, convex kabuk, bir alanı göstermek için haritada görüntülenir. Bir convex kabuk, esnek bant gibi bir dizi noktayı sarmalayan ve yöntemi kullanılarak hesaplanabilecek bir çokgen atlas.math.getConvexHull . Bir kümede yer alan tüm noktaları, yöntemi kullanılarak veri kaynağından alınabilir getClusterLeaves .
//Create a data source and add it to the map.
DataSource source = new DataSource(
//Tell the data source to cluster point data.
cluster(true)
);
//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson");
//Add data source to the map.
map.sources.add(source);
//Create a data source for the convex hull polygon. Since this will be updated frequently it is more efficient to separate this into its own data source.
DataSource polygonDataSource = new DataSource();
//Add data source to the map.
map.sources.add(polygonDataSource);
//Add a polygon layer and a line layer to display the convex hull.
map.layers.add(new PolygonLayer(polygonDataSource));
map.layers.add(new LineLayer(polygonDataSource));
//Create a symbol layer to render the clusters.
SymbolLayer clusterLayer = new SymbolLayer(source,
iconImage("marker-red"),
textField(get("point_count_abbreviated")),
textOffset(new Float[] { 0f, -1.2f }),
textColor(Color.WHITE),
textSize(14f),
//Only rendered data points which have a point_count property, which clusters do.
SymbolLayerOptions.filter(has("point_count"))
);
map.layers.add(clusterLayer);
//Create a layer to render the individual locations.
map.layers.add(new SymbolLayer(source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
));
//Add a click event to the layer so we can calculate the convex hull of all the points within a cluster.
map.events.add((OnFeatureClick) (features) -> {
if(features.size() > 0) {
//Get the clustered point from the event.
Feature cluster = features.get(0);
//Get all points in the cluster. Set the offset to 0 and the max long value to return all points.
FeatureCollection leaves = source.getClusterLeaves(cluster, Long.MAX_VALUE, 0);
//Get the point features from the feature collection.
List<Feature> childFeatures = leaves.features();
//When only two points in a cluster. Render a line.
if(childFeatures.size() == 2){
//Extract the geometry points from the child features.
List<Point> points = new ArrayList();
childFeatures.forEach(f -> {
points.add((Point)f.geometry());
});
//Create a line from the points.
polygonDataSource.setShapes(LineString.fromLngLats(points));
} else {
Polygon hullPolygon = MapMath.getConvexHull(leaves);
//Overwrite all data in the polygon data source with the newly calculated convex hull polygon.
polygonDataSource.setShapes(hullPolygon);
}
}
//Return true indicating if event should be consumed and not passed further to other listeners registered afterwards, false otherwise.
return true;
}, clusterLayer);
//Create a data source and add it to the map.
val source = DataSource(
//Tell the data source to cluster point data.
cluster(true)
)
//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")
//Add data source to the map.
map.sources.add(source)
//Create a data source for the convex hull polygon. Since this will be updated frequently it is more efficient to separate this into its own data source.
val polygonDataSource = DataSource()
//Add data source to the map.
map.sources.add(polygonDataSource)
//Add a polygon layer and a line layer to display the convex hull.
map.layers.add(PolygonLayer(polygonDataSource))
map.layers.add(LineLayer(polygonDataSource))
//Create a symbol layer to render the clusters.
val clusterLayer = SymbolLayer(
source,
iconImage("marker-red"),
textField(get("point_count_abbreviated")),
textOffset(arrayOf(0f, -1.2f)),
textColor(Color.WHITE),
textSize(14f),
//Only rendered data points which have a point_count property, which clusters do.
SymbolLayerOptions.filter(has("point_count"))
)
map.layers.add(clusterLayer)
//Create a layer to render the individual locations.
map.layers.add(
SymbolLayer(
source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
)
)
//Add a click event to the layer so we can calculate the convex hull of all the points within a cluster.
map.events.add(OnFeatureClick { features: List<Feature?>? ->
if (features.size() > 0) {
//Get the clustered point from the event.
val cluster: Feature = features.get(0)
//Get all points in the cluster. Set the offset to 0 and the max long value to return all points.
val leaves: FeatureCollection = source.getClusterLeaves(cluster, Long.MAX_VALUE, 0)
//Get the point features from the feature collection.
val childFeatures = leaves.features()
//When only two points in a cluster. Render a line.
if (childFeatures!!.size == 2) {
//Extract the geometry points from the child features.
val points: MutableList<Point?> = ArrayList()
childFeatures!!.forEach(Consumer { f: Feature ->
points.add(
f.geometry() as Point?
)
})
//Create a line from the points.
polygonDataSource.setShapes(LineString.fromLngLats(points))
} else {
val hullPolygon: Polygon = MapMath.getConvexHull(leaves)
//Overwrite all data in the polygon data source with the newly calculated convex hull polygon.
polygonDataSource.setShapes(hullPolygon)
}
}
true
}, clusterLayer)
Aşağıdaki görüntüde, bir tıklanan kümelenmiş içindeki tüm noktaların alanını görüntüleyen Yukarıdaki kod gösterilmektedir.

Kümelerdeki verileri toplama
Genellikle kümeler, küme içindeki noktaların sayısıyla birlikte bir sembol kullanılarak temsil edilir. Ancak bazen ek ölçümler içeren kümelerin stilini özelleştirmek tercih edilir. Küme özellikleri ile özel özellikler oluşturulabilir ve bir küme ile her bir noktada bulunan özelliklere göre bir hesaplamaya eşittir. Küme özellikleri clusterProperties , seçeneğinde tanımlanabilir DataSource .
Aşağıdaki kod, bir kümedeki her bir veri noktasının varlık türü özelliğini temel alan bir sayıyı hesaplar. Kullanıcı bir kümeye tıkladığında bir açılan pencerede, kümeyle ilgili ek bilgiler içeren bir açılır pencere görüntülenir.
//An array of all entity type property names in features of the data set.
String[] entityTypes = new String[] { "Gas Station", "Grocery Store", "Restaurant", "School" };
//Create a popup and add it to the map.
Popup popup = new Popup();
map.popups.add(popup);
//Close the popup initially.
popup.close();
//Create a data source and add it to the map.
source = new DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(50),
//Calculate counts for each entity type in a cluster as custom aggregate properties.
clusterProperties(new ClusterProperty[]{
new ClusterProperty("Gas Station", sum(accumulated(), get("Gas Station")), switchCase(eq(get("EntityType"), literal("Gas Station")), literal(1), literal(0))),
new ClusterProperty("Grocery Store", sum(accumulated(), get("Grocery Store")), switchCase(eq(get("EntityType"), literal("Grocery Store")), literal(1), literal(0))),
new ClusterProperty("Restaurant", sum(accumulated(), get("Restaurant")), switchCase(eq(get("EntityType"), literal("Restaurant")), literal(1), literal(0))),
new ClusterProperty("School", sum(accumulated(), get("School")), switchCase(eq(get("EntityType"), literal("School")), literal(1), literal(0)))
})
);
//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://azuremapscodesamples.azurewebsites.net/Common/data/geojson/SamplePoiDataSet.json");
//Add data source to the map.
map.sources.add(source);
//Create a bubble layer for rendering clustered data points.
BubbleLayer clusterBubbleLayer = new BubbleLayer(source,
bubbleRadius(20f),
bubbleColor("purple"),
bubbleStrokeWidth(0f),
//Only rendered data points which have a point_count property, which clusters do.
BubbleLayerOptions.filter(has("point_count"))
);
//Add the clusterBubbleLayer and two additional layers to the map.
map.layers.add(clusterBubbleLayer);
//Create a symbol layer to render the count of locations in a cluster.
map.layers.add(new SymbolLayer(source,
//Hide the icon image.
iconImage("none"),
//Display the 'point_count_abbreviated' property value.
textField(get("point_count_abbreviated")),
textColor(Color.WHITE),
textOffset(new Float[] { 0f, 0.4f }),
//Only rendered data points which have a point_count property, which clusters do.
SymbolLayerOptions.filter(has("point_count"))
));
//Create a layer to render the individual locations.
map.layers.add(new SymbolLayer(source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
));
//Add a click event to the cluster layer and display the aggregate details of the cluster.
map.events.add((OnFeatureClick) (features) -> {
if(features.size() > 0) {
//Get the clustered point from the event.
Feature cluster = features.get(0);
//Create a number formatter that removes decimal places.
NumberFormat nf = DecimalFormat.getInstance();
nf.setMaximumFractionDigits(0);
//Create the popup's content.
StringBuilder sb = new StringBuilder();
sb.append("Cluster size: ");
sb.append(nf.format(cluster.getNumberProperty("point_count")));
sb.append(" entities\n");
for(int i = 0; i < entityTypes.length; i++) {
sb.append("\n");
//Get the entity type name.
sb.append(entityTypes[i]);
sb.append(": ");
//Get the aggregated entity type count from the properties of the cluster by name.
sb.append(nf.format(cluster.getNumberProperty(entityTypes[i])));
}
//Retrieve the custom layout for the popup.
View customView = LayoutInflater.from(this).inflate(R.layout.popup_text, null);
//Access the text view within the custom view and set the text to the title property of the feature.
TextView tv = customView.findViewById(R.id.message);
tv.setText(sb.toString());
//Get the position of the cluster.
Position pos = MapMath.getPosition((Point)cluster.geometry());
//Set the options on the popup.
popup.setOptions(
//Set the popups position.
position(pos),
//Set the anchor point of the popup content.
anchor(AnchorType.BOTTOM),
//Set the content of the popup.
content(customView)
);
//Open the popup.
popup.open();
}
//Return a boolean indicating if event should be consumed or continue bubble up.
return true;
}, clusterBubbleLayer);
//An array of all entity type property names in features of the data set.
val entityTypes = arrayOf("Gas Station", "Grocery Store", "Restaurant", "School")
//Create a popup and add it to the map.
val popup = Popup()
map.popups.add(popup)
//Close the popup initially.
popup.close()
//Create a data source and add it to the map.
val source = DataSource(
//Tell the data source to cluster point data.
cluster(true),
//The radius in pixels to cluster points together.
clusterRadius(50),
//Calculate counts for each entity type in a cluster as custom aggregate properties.
clusterProperties(
arrayOf<ClusterProperty>(
ClusterProperty("Gas Station", sum(accumulated(), get("Gas Station")), switchCase(eq(get("EntityType"), literal("Gas Station")), literal(1), literal(0))),
ClusterProperty("Grocery Store", sum(accumulated(), get("Grocery Store")), switchCase(eq(get("EntityType"), literal("Grocery Store")), literal(1), literal(0))),
ClusterProperty("Restaurant", sum(accumulated(), get("Restaurant")), switchCase(eq(get("EntityType"), literal("Restaurant")), literal(1), literal(0))),
ClusterProperty("School", sum(accumulated(), get("School")), switchCase(eq(get("EntityType"), literal("School")), literal(1), literal(0)))
)
)
)
//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://azuremapscodesamples.azurewebsites.net/Common/data/geojson/SamplePoiDataSet.json")
//Add data source to the map.
map.sources.add(source)
//Create a bubble layer for rendering clustered data points.
val clusterBubbleLayer = BubbleLayer(
source,
bubbleRadius(20f),
bubbleColor("purple"),
bubbleStrokeWidth(0f),
//Only rendered data points which have a point_count property, which clusters do.
BubbleLayerOptions.filter(has("point_count"))
)
//Add the clusterBubbleLayer and two additional layers to the map.
map.layers.add(clusterBubbleLayer)
//Create a symbol layer to render the count of locations in a cluster.
map.layers.add(
SymbolLayer(
source,
//Hide the icon image.
iconImage("none"),
//Display the 'point_count_abbreviated' property value.
textField(get("point_count_abbreviated")),
textColor(Color.WHITE),
textOffset(arrayOf(0f, 0.4f)),
//Only rendered data points which have a point_count property, which clusters do.
SymbolLayerOptions.filter(has("point_count"))
)
)
//Create a layer to render the individual locations.
map.layers.add(
SymbolLayer(
source,
//Filter out clustered points from this layer.
SymbolLayerOptions.filter(not(has("point_count")))
)
)
//Add a click event to the cluster layer and display the aggregate details of the cluster.
map.events.add(OnFeatureClick { features: List<Feature> ->
if (features.size > 0) {
//Get the clustered point from the event.
val cluster = features[0]
//Create a number formatter that removes decimal places.
val nf: NumberFormat = DecimalFormat.getInstance()
nf.setMaximumFractionDigits(0)
//Create the popup's content.
val sb = StringBuilder()
sb.append("Cluster size: ")
sb.append(nf.format(cluster.getNumberProperty("point_count")))
sb.append(" entities\n")
for (i in entityTypes.indices) {
sb.append("\n")
//Get the entity type name.
sb.append(entityTypes[i])
sb.append(": ")
//Get the aggregated entity type count from the properties of the cluster by name.
sb.append(nf.format(cluster.getNumberProperty(entityTypes[i])))
}
//Retrieve the custom layout for the popup.
val customView: View = LayoutInflater.from(this).inflate(R.layout.popup_text, null)
//Access the text view within the custom view and set the text to the title property of the feature.
val tv: TextView = customView.findViewById(R.id.message)
tv.text = sb.toString()
//Get the position of the cluster.
val pos: Position = MapMath.getPosition(cluster.geometry() as Point?)
//Set the options on the popup.
popup.setOptions(
//Set the popups position.
position(pos),
//Set the anchor point of the popup content.
anchor(AnchorType.BOTTOM),
//Set the content of the popup.
content(customView)
)
//Open the popup.
popup.open()
}
//Return a boolean indicating if event should be consumed or continue bubble up.
true
} as OnFeatureClick, clusterBubbleLayer)
Açılan pencere, açılan belgede görüntülenen adımları izler.
Aşağıdaki görüntüde, yukarıdaki kod, tıklatılan kümelenmiş noktasındaki tüm noktaların her bir varlık değeri türünün toplanmış sayımlarını içeren bir açılan pencere görüntülenir.

Sonraki adımlar
Haritanızda daha fazla veri eklemek için: