1+ /*
2+ * Copyright 2025 Google LLC
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ package com.google.maps.android.utils.demo
18+
19+ import android.view.View
20+ import android.widget.AdapterView
21+ import android.widget.ArrayAdapter
22+ import android.widget.Spinner
23+ import com.google.android.gms.maps.CameraUpdateFactory
24+ import com.google.android.gms.maps.MapView
25+ import com.google.android.gms.maps.model.LatLng
26+ import com.google.maps.android.clustering.ClusterManager
27+ import com.google.maps.android.clustering.algo.AbstractAlgorithm
28+ import com.google.maps.android.clustering.algo.CentroidNonHierarchicalDistanceBasedAlgorithm
29+ import com.google.maps.android.clustering.algo.ContinuousZoomEuclideanCentroidAlgorithm
30+ import com.google.maps.android.clustering.algo.GridBasedAlgorithm
31+ import com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm
32+ import com.google.maps.android.clustering.algo.NonHierarchicalViewBasedAlgorithm
33+ import com.google.maps.android.utils.demo.model.MyItem
34+ import kotlin.random.Random
35+
36+ /* *
37+ * A demo activity that showcases the various clustering algorithms
38+ * available in the library.
39+ */
40+ class ClusterAlgorithmsDemoActivity : BaseDemoActivity () {
41+
42+ private var clusterManager: ClusterManager <MyItem >? = null
43+ private lateinit var mapView: MapView
44+
45+ override fun getLayoutId (): Int {
46+ return R .layout.activity_cluster_algorithms_demo
47+ }
48+
49+ override fun startDemo (isRestore : Boolean ) {
50+
51+ if (! isRestore) {
52+ map.moveCamera(
53+ CameraUpdateFactory .newLatLngZoom(
54+ LatLng (51.503186 , - 0.126446 ), 10f
55+ )
56+ )
57+ }
58+
59+ setupSpinner()
60+
61+ setupClusterer(0 )
62+ }
63+
64+ private fun setupSpinner () {
65+ val spinner: Spinner = findViewById(R .id.algorithm_spinner)
66+ val adapter = ArrayAdapter .createFromResource(
67+ this , R .array.clustering_algorithms, android.R .layout.simple_spinner_item
68+ )
69+ adapter.setDropDownViewResource(android.R .layout.simple_spinner_dropdown_item)
70+ spinner.adapter = adapter
71+ spinner.onItemSelectedListener = object : AdapterView .OnItemSelectedListener {
72+ override fun onItemSelected (
73+ parent : AdapterView <* >? , view : View ? , position : Int , id : Long
74+ ) {
75+ setupClusterer(position)
76+ }
77+
78+ override fun onNothingSelected (parent : AdapterView <* >? ) {
79+ // Do nothing
80+ }
81+ }
82+ }
83+
84+ /* *
85+ * Sets up the ClusterManager with the chosen algorithm and populates it with items.
86+ */
87+ private fun setupClusterer (algorithmPosition : Int ) {
88+ // 1. Clear the map and previous cluster manager
89+ map.clear()
90+
91+ // 2. Initialize a new ClusterManager, using getMap() from BaseDemoActivity
92+ clusterManager = ClusterManager (this , map)
93+
94+ // 3. Set the desired algorithm based on the spinner position
95+ clusterManager?.algorithm = when (algorithmPosition) {
96+ 1 -> GridBasedAlgorithm ()
97+ 2 -> NonHierarchicalDistanceBasedAlgorithm ()
98+ 3 -> CentroidNonHierarchicalDistanceBasedAlgorithm ()
99+ 4 -> NonHierarchicalViewBasedAlgorithm (mapView.width, mapView.height)
100+ 5 -> ContinuousZoomEuclideanCentroidAlgorithm ()
101+ else -> error(" Unsupported algorithm position: $algorithmPosition " )
102+ }
103+
104+ // 4. Point the map's listeners to the ClusterManager
105+ map.setOnCameraIdleListener(clusterManager)
106+ map.setOnMarkerClickListener(clusterManager)
107+
108+ // 5. Generate and add cluster items to the manager
109+ val items = generateItems()
110+ clusterManager?.addItems(items)
111+
112+ // 6. Trigger the initial clustering
113+ clusterManager?.cluster()
114+ }
115+
116+ private fun generateItems (): List <MyItem > {
117+ val items = mutableListOf<MyItem >()
118+ // Add 100 random items in the map region
119+ for (i in 0 until 100 ) {
120+ val lat = 51.5145 + (Random .nextDouble() - 0.5 ) / 2.0
121+ val lng = - 0.1245 + (Random .nextDouble() - 0.5 ) / 2.0
122+ items.add(MyItem (lat, lng, " Marker #$i " , " Snippet for marker #$i " ))
123+ }
124+ return items
125+ }
126+ }
0 commit comments