Repository navigation
feat(map): draw nodes at one spot as one counted chip on both maps - #7762
Conversation
Walkthrough
Priority: Merge Risk:
|
There was a problem hiding this comment.
Actionable comments posted: 1

Review info
-
Run configuration-
- Source mode: Auto
- Repository: meshtastic/Meshtastic-Android
- Branch: feat/map-colocated-nodes
- File: .coderabbit.yaml
- Commit: f7c566d
- Layers: Repository YAML
- Review profile: CHILL
- Plan: Advanced
- Run ID:
4697b97d-ef18-4599-8f7e-91db1a344c70
Files selected for processing: 20-
androidApp/src/google/kotlin/org/meshtastic/app/map/MapView.ktandroidApp/src/google/kotlin/org/meshtastic/app/map/component/NodeClusterMarkers.ktandroidApp/src/google/kotlin/org/meshtastic/app/map/model/NodeClusterItem.ktandroidApp/src/testGoogle/kotlin/org/meshtastic/app/map/MapNodeClusterItemsTest.ktdocs/en/user/map-and-waypoints.mdfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/MapGeometry.ktfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/geojson/ClusterMember.ktfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/geojson/NodeFeatureKeys.ktfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/geojson/NodeFeatures.ktfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/layers/NodeChipLayer.ktfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/layers/NodeLayers.ktfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/layers/StackBadgeLayer.ktfeature/map-maplibre/src/commonTest/kotlin/org/meshtastic/feature/map/maplibre/UnclusteredNodesTest.ktfeature/map-maplibre/src/commonTest/kotlin/org/meshtastic/feature/map/maplibre/geojson/StackFeaturesTest.ktfeature/map-maplibre/src/commonTest/kotlin/org/meshtastic/feature/map/maplibre/layers/ClusterCannotSplitTest.ktfeature/map/src/commonMain/kotlin/org/meshtastic/feature/map/NodeStack.ktfeature/map/src/commonMain/kotlin/org/meshtastic/feature/map/component/ClusterMemberEntry.ktfeature/map/src/commonMain/kotlin/org/meshtastic/feature/map/component/ClusterMembersDialog.ktfeature/map/src/commonTest/kotlin/org/meshtastic/feature/map/NodeStackTest.ktfeature/map/src/commonTest/kotlin/org/meshtastic/feature/map/component/ClusterMemberOrderTest.kt
Files with no reviewable changes: 1-
- feature/map-maplibre/src/commonTest/kotlin/org/meshtastic/feature/map/maplibre/UnclusteredNodesTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
-
There was a problem hiding this comment.
Actionable comments posted: 1

Review info
-
Run configuration-
- Source mode: Auto
- Repository: meshtastic/Meshtastic-Android
- Branch: feat/map-colocated-nodes
- File: .coderabbit.yaml
- Commit: 49fba23
- Layers: Repository YAML
- Review profile: CHILL
- Plan: Advanced
- Run ID:
65527389-5457-4a77-9395-5e071ceed60c
Files selected for processing: 2-
feature/map/src/commonMain/kotlin/org/meshtastic/feature/map/component/ClusterMemberEntry.ktfeature/map/src/commonTest/kotlin/org/meshtastic/feature/map/component/ClusterMemberOrderTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.
-
Nodes sharing a reduced-precision position, or radios a few meters apart at one site, drew as chips piled on one another: there was no sign there were several, only the top one could be tapped, and on MapLibre the "Nodes at this location" list never opened for a cluster of them. Nodes within 5 m now form one stack, the threshold the Apple map uses. Each stack draws its top node's chip (this node or a favorite, then the lowest node number) with a Material 3 count badge, and one precision circle, which stays visible inside a cluster bubble. Tapping a stack lists its nodes, favorites first in natural name order; a single chip opens the node's details on both maps. A Google cluster tap zooms to fit its members, and a MapLibre cluster that cannot split lists them.
…rder Char.isDigit accepts other scripts' digits while the split only takes ASCII ones, so a name with them could break the comparator's ordering. Both now use ASCII digits only.
Every earlier assertion started its run with N, so none reached the digit test. A bare non-ASCII digit now has to sort as text.
main added local display names; stack members and the list order still read the broadcast long name.
7d86fee to
d56154b
Compare
There was a problem hiding this comment.
Actionable comments posted: 1

Review info
-
Run configuration-
- Source mode: Auto
- Repository: meshtastic/Meshtastic-Android
- Branch: feat/map-colocated-nodes
- File: .coderabbit.yaml
- Commit: d56154b
- Layers: Repository YAML
- Review profile: CHILL
- Plan: Advanced
- Run ID:
5bdfa474-c8fc-4fa8-a090-9dafe23d7a9d
Files selected for processing: 4-
androidApp/src/google/kotlin/org/meshtastic/app/map/MapView.ktfeature/map-maplibre/src/commonMain/kotlin/org/meshtastic/feature/map/maplibre/geojson/NodeFeatures.ktfeature/map/src/commonMain/kotlin/org/meshtastic/feature/map/component/ClusterMemberEntry.ktfeature/map/src/commonTest/kotlin/org/meshtastic/feature/map/component/ClusterMemberOrderTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
-
| cluster.items.forEach { bounds.include(it.position) } | ||
| // Fit the members, as the Apple map does, rather than step one zoom level and leave a tight cluster | ||
| // needing several taps to break. | ||
| val fitted = bounds.build().atLeastSpan(CLUSTER_FIT_MIN_SPAN_METERS) |
There was a problem hiding this comment.
🔎 Supported by static analysis
-
Script executed:
set -o pipefail printf '%s\n' '--- diff ---' git diff --unified=80 bf7e1155a69585b4190d774b3e93eba6d374ea8c d56154bf1079cadb79e44a38308f0d75202a73d1 -- androidApp/src/google/kotlin/org/meshtastic/app/map/MapView.kt printf '%s\n' '--- relevant symbols ---' rg -n -F -- 'CLUSTER_FIT_MIN_SPAN_METERS' androidApp/src/google/kotlin/org/meshtastic/app/map/MapView.kt rg -n -F -e 'ClusterManager' -e 'ClusterItem' -e 'clusterClick' -e 'onClusterClick' -e 'atLeastSpan' -e 'allSameLocation' -e 'setOnCameraIdleListener' androidApp/src/google/kotlin/org/meshtastic/app/map/MapView.kt printf '%s\n' '--- dependency/config references ---' rg -n -F -e 'maps-compose-utils' -e 'maps-utils' -e 'cluster' gradle* androidApp build-logic gradle 2>/dev/null || true
Repository: meshtastic/Meshtastic-Android
Length of output: 38972
Script executed:
set -o pipefail printf '%s\n' '--- NodeClusterMarkers.kt ---' nl -ba androidApp/src/google/kotlin/org/meshtastic/app/map/component/NodeClusterMarkers.kt printf '%s\n' '--- NodeClusterItem.kt ---' nl -ba androidApp/src/google/kotlin/org/meshtastic/app/map/model/NodeClusterItem.kt printf '%s\n' '--- relevant dependency declarations ---' nl -ba gradle/libs.versions.toml | sed -n '60,80p;210,245p' nl -ba androidApp/build.gradle.kts | sed -n '260,295p' printf '%s\n' '--- clustering tests and related helpers ---' rg -n -F -e 'NonHierarchicalDistanceBasedAlgorithm' -e 'NonHierarchicalViewBasedAlgorithm' -e 'NodeClusterMarkers' -e 'CLUSTER_FIT_MIN_SPAN_METERS' -e '140' androidApp/src/testGoogle androidApp/src/google feature 2>/dev/null || true
Repository: meshtastic/Meshtastic-Android
Length of output: 42967
Web query:
official GitHub source com.google.maps.android android-maps-utils 6.1.0 NonHierarchicalDistanceBasedAlgorithm max distance clusteringResult:
<source_evidence> <source kind="search"> <title>NonHierarchicalDistanceBasedAlgorithm (library API)</title> <location>https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.html</location> <excerpt>citeturn0search0 [wordlim: 200] Published: 6.7 years ago; Crawled: 3 weeks ago; * * com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm<T> ... `protected java.util.Collection<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>>` | `getClusteringItems(PointQuadTree<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> quadTree, float zoom)` ... `int` | `getMaxDistanceBetweenClusteredItems()` com.google.maps.android.clustering.algo ## Class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> * java.lang.Object * * com.google.maps.android.clustering.algo.AbstractAlgorithm<T> * * com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm<T> * All Implemented Interfaces: Algorithm<T> Direct Known Subclasses: NonHierarchicalViewBasedAlgorithm * * * public class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> extends AbstractAlgorithm<T> A simple clustering algorithm with O(nlog n) performance. Resulting clusters are not hierarchical. High level algorithm: 1. Iterate over items in the order they were added (candidate clusters). 2. Create a cluster with the center of the item. 3. Add all items that are within a certain distance to the cluster. 4. Move any items out of an existing cluster if they are closer to another cluster. 5. Remove those items from the list of candidate clusters. Clusters have the center of the first element (not the centroid of the items within it). * * ### Nested Class Summary Nested Classes Modifier and Type | Class and Description --- | --- `protected static class ` | `NonHierarchicalDistanceBasedAlgorithm.QuadItem<T extends ClusterItem>` * ### Constructor Summary Constructors Constructor and Description --- `NonHierarchicalDistanceBasedAlgorithm()` * ### Method Summary All Methods Instance Methods Concrete Methods Modifier and Type | Method and Description --- | --- `boolean` | `addItem(T item)` Adds an item to the algorithm `boolean` | `addItems(java.util.Collection<T> items)` Adds a collection of items to the algorithm `void` | `clearItems()` `protected java.util.Collection<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>>` | `getClusteringItems(PointQuadTree<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> quadTree, float zoom)` `java.util.Set<? extends Cluster<T>>` | `getClusters(float zoom)` `java.util.Collection<T>` | `getItems()` `int` | `getMaxDistanceBetweenClusteredItems()` `boolean` | `removeItem(T item)` Removes an item from the algorithm `boolean` | `removeItems(java.util.Collection<T> items)` Removes a collection of items from the algorithm `void` | `setMaxDistanceBetweenClusteredItems(int maxDistance)` `boolean` | `updateItem(T item)` Updates the provided item in the algorithm * * ### Constructor Detail * #### NonHierarchicalDistanceBasedAlgorithm public NonHierarchicalDistanceBasedAlgorithm() * ### Method Detail * #### addItem public boolean addItem(T item) Adds an item to the algorithm Parameters: `item` - the item to be added Returns: true if the algorithm contents changed as a result of the call * #### addItems public boolean addItems(java.util.Collection<T> items) Adds a collection of items to the algorithm Parameters: `items` - the items to be added Returns: true if the algorithm contents changed as a result of the call * #### clearItems public void clearItems() * #### removeItem public boolean removeItem(T item) Removes an item from the algorithm Parameters: `item` - the item to be removed Returns: true if this algorithm contained the specified element (or equivalently, if this al…[truncated]</excerpt> </source> <source kind="search"> <title>GitHub - googlemaps/android-maps-utils: Maps SDK for Android Utility Library · GitHub</title> <location>https://github.com/googlemaps/android-maps-utils</location> <excerpt>citeturn0search5 [wordlim: 200] Crawled: 3 weeks ago; Required for demos using Advanced Markers or Cloud-based Map Styling. ... 1. `secrets.properties`: Add a line to your `secrets.properties` file with your Map ID: ... android:name="com.google.maps.android.utils.attribution.AttributionIdInitializer" ... Accordingly, while the library is in version 0.x, backwards-incompatible changes may be introduced at any time.If you find a bug, or have a feature request, please file an issue on GitHub. You can learn more about map IDs in the official documentation. You can set the Map ID in one of the following ways: 1. `secrets.properties`: Add a line to your `secrets.properties` file with your Map ID: MAP_ID=YOUR_MAP_ID 2. `strings.xml`: Alternatively, you can set the Map ID in the `demo/src/main/res/values/strings.xml` file: <string name="map_id">YOUR_MAP_ID</string> 3. XML Layout Files: You can also hardcode the Map ID directly in the XML layout files where a map is defined, by setting the `map:mapId` attribute: <androidx.fragment.app.FragmentContainerView map:mapId="YOUR_MAP_ID" /> ## Documentation See the documentation for a full list of classes and their methods. Full guides for using the utilities are published in Google Maps Platform documentation. ## Usage Marker utilities ### Marker utilities * Marker animation source, sample code * Marker clustering source, guide * Advanced Markers clustering source, sample code * Marker icons source, sample code Data visualization utilities ### Data visualization utilities * Display heat maps source, guide * Import GeoJSON source, guide * Import KML source, guide Polyline and spherical geometry utilities ### Additional utilities * Polyline encoding and decoding source, encoding sample, decoding sample * Spherical geometry source, compute distance sample Street View metadata utility ### Street View metadata utility The StreetViewUtil class provides functionality to check whether a location is supported in StreetView. You can avoid errors when adding a Street View panorama to an Android app by calling this metadata utility and only adding a Street View panorama if the response is `OK`. StreetViewUtils.fetchStreetViewData(LatLng(8.1425918, 11.5386121), BuildConfig.MAPS_API_KEY,Source.DEFAULT) `fetchStreetViewData` will return `NOT_FOUND`, `OK`, `ZERO_RESULTS` or `REQUEST_DENIED`, depending on the response. By default, the `Source` is set to `Source.DEFAULT`, but you can also specify `Source.OUTDOOR` to request outdoor Street View panoramas. ## Internal usage attribution ID This library calls the `addInternalUsageAttributionId` method, which helps Google understand which libraries and samples are helpful to developers and is optional. Instructions for opting out of the identifier are provided below. If you wish to disable this, you can do so by removing the initializer in your `AndroidManifest.xml` using the `tools:node="remove"` attribute: <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <meta-data android:name="com.google.maps.android.utils.attribution.AttributionIdInitializer" tools:node="remove" /> </provider> ## Contributing Contributions are welcome and encouraged! If you'd like to contribute, send us a pull request and refer to our code of conduct and contributing guide. ### Using AI This repository provides an official Gemini Skill and an `llm-integration-prompt.md` to help AI agents navigate the codebase and provide assistance. Refer to the contributing guide for more details on AI usage. ## Terms of Service This library uses Goog…[truncated]</excerpt> </source> <source kind="search"> <title>NonHierarchicalDistanceBasedAlgorithm (library API)</title> <location>https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.html</location> <excerpt>citeturn2search0 [wordlim: 200] Published: 6.7 years ago; Crawled: 3 weeks ago; `protected java.util.Collection<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>>` | `getClusteringItems(PointQuadTree<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> quadTree, float zoom)` ... `void` | `setMaxDistanceBetweenClusteredItems(int maxDistance)` com.google.maps.android.clustering.algo ## Class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> * java.lang.Object * * com.google.maps.android.clustering.algo.AbstractAlgorithm<T> * * com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm<T> * All Implemented Interfaces: Algorithm<T> Direct Known Subclasses: NonHierarchicalViewBasedAlgorithm * * * public class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> extends AbstractAlgorithm<T> A simple clustering algorithm with O(nlog n) performance. Resulting clusters are not hierarchical. High level algorithm: 1. Iterate over items in the order they were added (candidate clusters). 2. Create a cluster with the center of the item. 3. Add all items that are within a certain distance to the cluster. 4. Move any items out of an existing cluster if they are closer to another cluster. 5. Remove those items from the list of candidate clusters. Clusters have the center of the first element (not the centroid of the items within it). * * ### Nested Class Summary Nested Classes Modifier and Type | Class and Description --- | --- `protected static class ` | `NonHierarchicalDistanceBasedAlgorithm.QuadItem<T extends ClusterItem>` * ### Constructor Summary Constructors Constructor and Description --- `NonHierarchicalDistanceBasedAlgorithm()` * ### Method Summary All Methods Instance Methods Concrete Methods Modifier and Type | Method and Description --- | --- `boolean` | `addItem(T item)` Adds an item to the algorithm `boolean` | `addItems(java.util.Collection<T> items)` Adds a collection of items to the algorithm `void` | `clearItems()` `protected java.util.Collection<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>>` | `getClusteringItems(PointQuadTree<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> quadTree, float zoom)` `java.util.Set<? extends Cluster<T>>` | `getClusters(float zoom)` `java.util.Collection<T>` | `getItems()` `int` | `getMaxDistanceBetweenClusteredItems()` `boolean` | `removeItem(T item)` Removes an item from the algorithm `boolean` | `removeItems(java.util.Collection<T> items)` Removes a collection of items from the algorithm `void` | `setMaxDistanceBetweenClusteredItems(int maxDistance)` `boolean` | `updateItem(T item)` Updates the provided item in the algorithm * * ### Constructor Detail * #### NonHierarchicalDistanceBasedAlgorithm public NonHierarchicalDistanceBasedAlgorithm() * ### Method Detail * #### addItem public boolean addItem(T item) Adds an item to the algorithm Parameters: `item` - the item to be added Returns: true if the algorithm contents changed as a result of the call * #### addItems public boolean addItems(java.util.Collection<T> items) Adds a collection of items to the algorithm Parameters: `items` - the items to be added Returns: true if the algorithm contents changed as a result of the call * #### clearItems public void clearItems() * #### removeItem public boolean removeItem(T item) Removes an item from the algorithm Parameters: `item` - the item to be removed Returns: true if this algorithm contained the specified element (or equivalently, if this algorithm changed as a result of the call). * #### removeItems …[truncated]</excerpt> </source> <source kind="search"> <title>GitHub - googlemaps/android-maps-utils: Maps SDK for Android Utility Library · GitHub</title> <location>https://github.com/googlemaps/android-maps-utils</location> <excerpt>citeturn2search6 [wordlim: 200] Crawled: 3 weeks ago; 1. `secrets.properties`: Add a line to your `secrets.properties` file with your Map ID: ... <string name="map_id">YOUR_MAP_ID</string> ... android:name="com.google.maps.android.utils.attribution.AttributionIdInitializer" ... If you find a bug, or have a feature request, please file an issue on GitHub. * Marker clustering source, guide * Advanced Markers clustering source, sample code * Marker icons source, sample code Data visualization utilities ### Data visualization utilities * Display heat maps source, guide * Import GeoJSON source, guide * Import KML source, guide Polyline and spherical geometry utilities ### Additional utilities * Polyline encoding and decoding source, encoding sample, decoding sample * Spherical geometry source, compute distance sample Street View metadata utility ### Street View metadata utility The StreetViewUtil class provides functionality to check whether a location is supported in StreetView. You can avoid errors when adding a Street View panorama to an Android app by calling this metadata utility and only adding a Street View panorama if the response is `OK`. StreetViewUtils.fetchStreetViewData(LatLng(8.1425918, 11.5386121), BuildConfig.MAPS_API_KEY,Source.DEFAULT) `fetchStreetViewData` will return `NOT_FOUND`, `OK`, `ZERO_RESULTS` or `REQUEST_DENIED`, depending on the response. By default, the `Source` is set to `Source.DEFAULT`, but you can also specify `Source.OUTDOOR` to request outdoor Street View panoramas. Refer to the contributing guide for more details on AI usage. ## Terms of Service This library uses Google Maps Platform services. Use of Google Maps Platform services through this library is subject to the Google Maps Platform Terms of Service. If your billing address is in the European Economic Area, effective on 8 July 2025, the Google Maps Platform EEA Terms of Service will apply to your use of the Services. Functionality varies by region. Learn more. This library is not a Google Maps Platform Core Service. Therefore, the Google Maps Platform Terms of Service (e.g. Technical Support Services, Service Level Agreements, and Deprecation Policy) do not apply to the code in this library. ## Support This library is offered via an open source license. It is not governed by the Google Maps Platform Support Technical Support Services Guidelines, the SLA, or the Deprecation Policy. However, any Google Maps Platform services used by the library remain subject to the Google Maps Platform Terms of Service. This library adheres to semantic versioning to indicate when backwards-incompatible changes are introduced. Accordingly, while the library is in version 0.x, backwards-incompatible changes may be introduced at any time. If you find a bug, or have a feature request, please file an issue on GitHub. If you would like to get answers to technical questions from other Google Maps Platform developers, ask through one of our developer community channels. If you'd like to contribute, please check the contributing guide. You can also discuss this library on our Discord server. </excerpt> </source> <source kind="search"> <title>com.google.maps.android.clustering.algo (library API)</title> <location>https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/package-summary.html</location> <excerpt>citeturn0search1 [wordlim: 200] Published: 6.7 years ago; Crawled: 3 weeks ago; # Package com.google.maps.android.clustering.algo ... NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> | A simple clustering algorithm with O(nlog n) performance. # Package com.google.maps.android.clustering.algo * Interface Summary Interface | Description --- | --- Algorithm<T extends ClusterItem> | Logic for computing clusters ScreenBasedAlgorithm<T extends ClusterItem> | This algorithm uses map position for clustering, and should be reclustered on map movement * Class Summary Class | Description --- | --- AbstractAlgorithm<T extends ClusterItem> | Base Algorithm class that implements lock/unlock functionality. GridBasedAlgorithm<T extends ClusterItem> | Groups markers into a grid. NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> | A simple clustering algorithm with O(nlog n) performance. NonHierarchicalDistanceBasedAlgorithm.QuadItem<T extends ClusterItem> | NonHierarchicalViewBasedAlgorithm<T extends ClusterItem> | This algorithm works the same way as `NonHierarchicalDistanceBasedAlgorithm` but works, only in visible area. PreCachingAlgorithmDecorator<T extends ClusterItem> | Optimistically fetch clusters for adjacent zoom levels, caching them as necessary. ScreenBasedAlgorithmAdapter<T extends ClusterItem> | StaticCluster<T extends ClusterItem> | A cluster whose center is determined upon creation.</excerpt> </source> <omitted_sources count="37">Additional source records were omitted from this bounded result.</omitted_sources> </source_evidence> Citations: - 1: https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.html?utm_source=openai - 2: https://github.com/googlemaps/android-maps-utils?utm_source=openai
Web query:
official GitHub source com.google.maps.android maps-compose 9.0.1 Clustering default algorithmResult:
<source_evidence> <source kind="find_in_page"> <title>android-maps-compose/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt at v9.0.1 · googlemaps/android-maps-compose · GitHub</title> <location>https://github.com/googlemaps/android-maps-compose/blob/v9.0.1/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt</location> <excerpt>citeturn3view2 [wordlim: 200] Crawled: today; Content type: text/html; Source: find({"ref_id":"turn2view0","pattern":"Algorithm"}); Total lines: 2457 L1586: * @param clusterItemContentRotation the rotation of the non-clustered item in degrees clockwise about the marker's anchor point L1587: L1588: * @param clusterRenderer an optional ClusterRenderer that can be used to specify the algorithm used by the rendering. L1589: L1590: */ L1591: L1592: @Composable L1593: L1594: @GoogleMapComposable L1595: L1596: @MapsComposeExperimentalApi L1597: L1598: @Deprecated( L1599: L1600: message = "If clusterRenderer is specified, clusterContent and clusterItemContent are not used; use a function that takes ClusterManager as an argument instead.", L1987: * @param items all items to show L1988: L1989: * @param clusterManager a [ClusterManager] that can be used to specify the algorithm used by the rendering. L1990: L1991: */ L1992: L1993: @Composable L1994: L1995: @GoogleMapComposable L1996: L1997: @MapsComposeExperimentalApi L1998: L1999: public fun <T : ClusterItem> Clustering( L2000: L2001: items: Collection<T>, L2002: L2003: clusterManager: ClusterManager<T>, L2004: L2005: clusterItemDecoration: @Composable @GoogleMapComposable (T) -> Unit = {}, L2006: L2007: ) { L2008: L2009: Clustering( L2010: L2011: items = items, L2012: L2013: clusterManager = clusterManager, L2014: L2015: clusterItemDecoration = clusterItemDecoration, </excerpt> </source> <source kind="open_page"> <title>android-maps-compose/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt at v9.0.1 · googlemaps/android-maps-compose · GitHub</title> <location>https://github.com/googlemaps/android-maps-compose/blob/v9.0.1/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt</location> <excerpt>citeturn2view0 [wordlim: 200] Crawled: today; Content type: text/html; Source: open({"ref_id":"https://github.com/googlemaps/android-maps-compose/blob/v9.0.1/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt","lineno":null}); Total lines: 2457 L0: 【0†Skip to content】 L1: ## Navigation Menu L2: L3: 【1†Sign in】 L4: L5: Appearance settings L6: L7: * Platform L8: L9: * AI CODE CREATION L10: * 【2†GitHub CopilotWrite better code with AI】 L11: * 【3†GitHub Copilot appDirect agents from issue to merge】 L12: * 【4†MCP RegistryIntegrate external tools】 L13: L14: * DEVELOPER WORKFLOWS L15: * 【5†ActionsAutomate any workflow】 L16: * 【6†CodespacesInstant dev environments】 L17: * 【7†IssuesPlan and track work】 L18: * 【8†Code ReviewManage code changes】 L19: * 【9†Code QualityEnforce quality at merge】 L20: * APPLICATION SECURITY L21: * 【10†GitHub Advanced SecurityFind and fix vulnerabilities】 L22: * 【11†Code securitySecure your code as you build】 L23: * 【12†Secret protectionStop leaks before they start】 L24: L25: * EXPLORE L26: * 【13†Why GitHub】 L27: * 【14†Documentation†docs.github.com】 L28: * 【15†Blog†github.blog】 L29: * 【16†Changelog†github.blog】 L30: * 【17†Marketplace】 L31: L32: 【18†View all features】 L33: L34: * Solutions L35: * BY COMPANY SIZE L36: * 【19†Enterprises】 L37: * 【20†Small and medium teams】 L38: * 【21†Startups】 L39: * 【22†Nonprofits】 L40: L41: * BY USE CASE L42: * 【23†App Modernization】 L43: * 【24†DevSecOps】 L44: * 【25†DevOps】 L45: * 【26†CI/CD】 L46: * 【27†View all use cases】 L47: L48: * BY INDUSTRY L49: * 【28†Healthcare】 L50: * 【29†Financial services】 L51: * 【30†Manufacturing】 L52: * 【31†Government】 L53: * 【32†See all industries】 L54: L55: 【33†View all solutions】 L56: L57: * Resources L58: * EXPLORE BY TOPIC L59: * 【34†AI】 L60: * 【35†Software Development】 L61: * 【36†DevOps】 L62: * 【37†Security】 L63: * 【38†View all topics】 L64: L65: * EXPLORE BY TYPE L66: * 【39†Customer stories】 L67: * 【40†Events & webinars】 L68: * 【41†Ebooks & reports】 L69: * 【42†Business insights】 L70: * 【43†GitHub Skills†skills.github.com】 L71: * SUPPORT & SERVICES L72: * 【14†Documentation†docs.github.com】 L73: * 【44†Customer support†support.github.com】 L74: * 【45†Community forum】 L75: * 【46†Trust center】 L76: * 【47†Partners】 L77: L78: 【48†View all resources】 L79: L80: * Open Source L81: L82: * COMMUNITY L83: * 【49†GitHub SponsorsFund open source developers】 L84: * PROGRAMS L85: * 【50†Security Lab†securitylab.github.com】 L86: * 【51†Maintainer Community†maintainers.github.com】 L87: * 【52†GitHub Stars†stars.github.com】 L88: * 【53†Archive Program†archiveprogram.github.com】 L89: L90: * REPOSITORIES L91: * 【54†Topics】 L92: * 【55†Trending】 L93: * 【56†Collections】 L94: L95: * Enterprise L96: L97: * ENTERPRISE SOLUTIONS L98: * 【19†Enterprise platformAI-powered developer platform】 L99: * AVAILABLE ADD-ONS L100: * 【10†GitHub Advanced SecurityEnterprise-grade security features】 L101: * 【57†Copilot for BusinessEnterprise-grade AI features】 L102: * 【58†Premium SupportEnterprise-grade 24/7 support】 L103: L104: * 【59†Pricing】 L105: L106: Search`/` L107: L108: 【1†Sign in】 L109: L110: 【60†Sign up】 L111: L112: Appearance settings L113: You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert L114: L115: 1. 【61†googlemaps】 L116: 2. 【62†android-maps-compose】 L117: ## Repos…[truncated]</excerpt> </source> <source kind="search"> <title>GitHub - googlemaps/android-maps-compose: Jetpack Compose composables for the Maps SDK for Android · GitHub</title> <location>https://github.com/googlemaps/android-maps-compose</location> <excerpt>citeturn0search0 [wordlim: 200] Crawled: yesterday; implementation 'com.google.maps.android:maps-compose:9.0.1' // {x-release-please-version} // Optionally, you can include the Compose utils library for Clustering, ... This library also provides optional composable widgets in the `maps-compose-widgets` library that you can use alongside the `GoogleMap` composable. ... If you find a bug, or have a feature request, please file an issue on GitHub. # Maps Compose 🗺 ## Description This repository contains Jetpack Compose components for the Maps SDK for Android. ## Requirements * Android API level 21+ * Kotlin-enabled project * Jetpack Compose-enabled project (see releases for the required version of Jetpack Compose) * Sign up with Google Maps Platform * A Google Maps Platform project with the Maps SDK for Android enabled * An API key associated with the project above ... follow the API key instructions if you're new to the process ## Installation You no longer need to specify the Maps SDK for Android or its Utility Library as separate dependencies, since `maps-compose` and `maps-compose-utils` pull in the appropriate versions of these respectively. dependencies { implementation 'com.google.maps.android:maps-compose:9.0.1' // {x-release-please-version} // Optionally, you can include the Compose utils library for Clustering, // Street View metadata checks, etc. implementation 'com.google.maps.android:maps-compose-utils:9.0.1' // {x-release-please-version} // Optionally, you can include the widgets library for ScaleBar, etc. implementation 'com.google.maps.android:maps-compose-widgets:9.0.1' // {x-release-please-version} } ## Sample App This repository includes a sample app. To run the demo app, ensure you've met the requirements above then: 1. Open the `secrets.properties` file in your top-level directory, and then add the following code. Replace YOUR_API_KEY with your API key. Store your key in this file because secrets.properties is excluded from being checked into a version control system. If the `secrets.properties` file does not exist, create it in the same folder as the `local.default.properties` file. `MAPS_API_KEY=YOUR_API_KEY ` 2. Build and run ## Documentation See the documentation for a full list of classes and their methods. ## Maps Compose Utility Library This library provides optional utilities in the `maps-compose-utils` library from the Maps SDK for Android Utility Library. ### Clustering The marker clustering utility helps you manage multiple markers at different zoom levels. When a user views the map at a high zoom level, the individual markers show on the map. When the user zooms out, the markers gather together into clusters, to make viewing the map easier. The MarkerClusteringActivity demonstrates usage. Clustering( items = items, // Optional: Handle clicks on clusters, cluster items, and cluster item info windows onClusterClick = null, onClusterItemClick = null, onClusterItemInfoWindowClick = null, // Optional: Custom rendering for clusters clusterContent = null, // Optional: Custom rendering for non-clustered items clusterItemContent = null, ) ### Street View metadata utility The `fetchStreetViewData` method provides functionality to check whether a location is supported in StreetView. </excerpt> </source> <source kind="search"> <title>android-maps-compose/CHANGELOG.md at main · googlemaps/android-maps-compose · GitHub</title> <location>https://github.com/googlemaps/android-maps-compose/blob/main/CHANGELOG.md</location> <excerpt>citeturn0search1 [wordlim: 200] Crawled: yesterday; * migrate from android-maps-ktx to android-maps-utils (v9.0.0) (#1002) ... * maps-compose: default mapColorScheme to FOLLOW_SYSTEM in GoogleMap (#986) (5f1d438) ... * avoid zero-size crash in rememberComposeBitmapDescriptor when used inside Clustering (#963) (11a2430) # Changelog ## 9.0.1 (2026-10-08) ### Bug Fixes * maps-compose: do not apply mapColorScheme to Lite mode maps (#1029) (114aaa5) ## 9.0.0 (2026-10-01) ### ⚠ BREAKING CHANGES * migrate from android-maps-ktx to android-maps-utils (v9.0.0) (#1002) ### Features * ci: publish an instrumented coverage badge (#1009) (b0d6420) * migrate from android-maps-ktx to android-maps-utils (v9.0.0) (#1002) (0c49e8d) ## 8.6.0 (2026-09-03) ### Features * expose map zoom limits (#949) (e0d4572) * maps-compose: default mapColorScheme to FOLLOW_SYSTEM in GoogleMap (#986) (5f1d438) ### Bug Fixes * guard against null in StreetView panorama change listeners (#970) (6147f75) * maps-compose: apply mapColorScheme to GoogleMapOptions during MapView creation (#976) (7dec2b7) * pin ViewTreeLifecycleOwner/SavedStateRegistryOwner on MapView to prevent info window crash (#972) (4024515) ## 8.5.0 (2026-08-17) ### Features * expose info window customization for advanced markers (#965) (4c65f8c) ### Bug Fixes * avoid re-parenting crash for MarkerInfoWindowContent/MarkerInfoWindowComposable (#953) (12f35a4) * avoid zero-size crash in rememberComposeBitmapDescriptor when used inside Clustering (#963) (11a2430) * rename InvalidatingComposeView getRotation param to avoid View shadowing (#952) (1d971cd) </excerpt> </source> <source kind="search"> <title>Clustering</title> <location>https://googlemaps.github.io/android-maps-compose/maps-compose-utils/com.google.maps.android.compose.clustering/-clustering.html</location> <excerpt>citeturn0search2 [wordlim: 200] Crawled: last month; @MapsComposeExperimentalApifun <T : ClusterItem> Clustering(items: Collection<T>, onClusterClick: (Cluster<T>) -> Boolean = { false }, onClusterItemClick: (T) -> Boolean = { false }, onClusterItemInfoWindowClick: (T) -> Unit = { }, onClusterItemInfoWindowLongClick: (T) -> Unit = { }, clusterContent: @Composable (Cluster<T>) -> Unit? ... = null, clusterContentAnchor: Offset = Offset(0.5f, 1.0f), clusterItemContentAnchor: Offset = Offset(0.5f, 1.0f), clusterContentZIndex: Float = 0.0f, clusterItemContentZIndex: Float = 0.0f, clusterContentRotation: Float = 0.0f, clusterItemContentRotation: Float = 0.0f, clusterItemDecoration: @Composable (T) -> Unit = {})Groups many items on a map based on zoom level. </excerpt> </source> <omitted_sources count="33">Additional source records were omitted from this bounded result.</omitted_sources> </source_evidence> Citations: - 1: https://github.com/googlemaps/android-maps-compose/blob/v9.0.1/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt
Web query:
site:github.com/googlemaps/android-maps-utils/blob v6.1.0 NonHierarchicalDistanceBasedAlgorithm DEFAULT_MAX_DISTANCE_BETWEEN_CLUSTERED_ITEMS 100Result:
<source_evidence> <source kind="search"> <title>NonHierarchicalDistanceBasedAlgorithm.java example</title> <location>https://www.javatips.net/api/android-maps-utils-master/library/src/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.java</location> <excerpt>citeturn2search0 [wordlim: 200] Crawled: 4 months ago; import java.util.Map; ... import com.google.android.gms.maps.model.LatLng; ... public class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> implements Algorithm<T> { public static final int MAX_DISTANCE_AT_ZOOM = 100; // essentially 100 dp. import com.google.maps.android.clustering.Cluster; import com.google.maps.android.clustering.ClusterItem; import com.google.maps.android.geometry.Bounds; import com.google.maps.android.geometry.Point; import com.google.maps.android.projection.SphericalMercatorProjection; import com.google.maps.android.quadtree.PointQuadTree; /** * A simple clustering algorithm with O(nlog n) performance. Resulting clusters are not * hierarchical. * <p/> * High level algorithm:<br> * 1. Iterate over items in the order they were added (candidate clusters).<br> * 2. Create a cluster with the center of the item. <br> * 3. Add all items that are within a certain distance to the cluster. <br> * 4. Move any items out of an existing cluster if they are closer to another cluster. <br> * 5. Remove those items from the list of candidate clusters. * <p/> * Clusters have the center of the first element (not the centroid of the items within it). */ public class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> implements Algorithm<T> { public static final int MAX_DISTANCE_AT_ZOOM = 100; // essentially 100 dp. /** * Any modifications should be synchronized on mQuadTree. */ private final Collection<QuadItem<T>> mItems = new ArrayList<QuadItem<T>>(); /** * Any modifications should be synchronized on mQuadTree. */ private final PointQuadTree<QuadItem<T>> mQuadTree = new PointQuadTree<QuadItem<T>>(0, 1, 0, 1); private static final SphericalMercatorProjection PROJECTION = new SphericalMercatorProjection(1); @Override public void addItem(T item) { final QuadItem<T> quadItem = new QuadItem<T>(item); synchronized (mQuadTree) { mItems.add(quadItem); mQuadTree.add(quadItem); } } @Override public void addItems(Collection<T> items) { for (T item : items) { addItem(item); } } @Override public void clearItems() { synchronized (mQuadTree) { mItems.clear(); mQuadTree.clear(); } } @Override public void removeItem(T item) { // QuadItem delegates hashcode() and equals() to its item so, // removing any QuadItem to that item will remove the item final QuadItem<T> quadItem = new QuadItem<T>(item); synchronized (mQuadTree) { mItems.remove(quadItem); mQuadTree.remove(quadItem); } } @Override public Set<? extends Cluster<T>> getClusters(double zoom) { final int discreteZoom = (int) zoom; final double zoomSpecificSpan = MAX_DISTANCE_AT_ZOOM / Math.pow(2, discreteZoom) / 256; final Set<QuadItem<T>> visitedCandidates = new HashSet<QuadItem<T>>(); final Set<Cluster<T>> results = new HashSet<Cluster<T>>(); final Map<QuadItem<T>, Double> distanceToCluster = new HashMap<QuadItem<T>, Double>(); final Map<QuadItem<T>, StaticCluster<T>> itemToCluster = new HashMap<QuadItem<T>, StaticCluster<T>>(); synchronized…[truncated]</excerpt> </source> <source kind="search"> <title>android-maps-utils/CHANGELOG.md at main · googlemaps/android-maps-utils · GitHub</title> <location>https://github.com/googlemaps/android-maps-utils/blob/main/CHANGELOG.md</location> <excerpt>citeturn0search0 [wordlim: 200] Crawled: last month; * restore isLayerOnMap() as abstract member of Layer (#1748) (ddc283c), closes #1746## 5.1.0 (2026-08-05) ... * stale QuadItem removal after ClusterItem position updates (#1730) (c39ba07) ... * rewrite android maps utils (#1658) (eeb0156) 143 lines (68 loc) · 9.11 KB Raw Copy raw file Download raw file Outline Edit and raw actions # Changelog ## 5.2.0 (2026-08-28) ### Features * clustering: make ClusterManager and its public API open with JvmSuppressWildcards (#1759) (bbb66c4) * collections,clustering: complete Kotlin migration for core modules and apply optimizations (#1766) (ca97025) ### Bug Fixes * ci: stop failing external PRs on missing coverage token (#1765) (09030dc) * data: prevent SSRF from untrusted KML/GeoJSON icon and GroundOverlay href (#1758) (9078c33) ## 5.1.1 (2026-08-11) ### Bug Fixes * restore isLayerOnMap() as abstract member of Layer (#1748) (ddc283c), closes #1746 ## 5.1.0 (2026-08-05) ### Features * data: add support for parsing GroundOverlay with LatLonQuad bounds (#1739) (c2a165d) ### Bug Fixes * apply polygon styling to GeoJSON MultiPolygon features (#1727) (67d7252) * bound untrusted GeoJSON input to prevent parser resource exhaustion (#1733) (1e41aa4) * remove MultiGeometry features from the map in removeFeature (#1725) (4f796ca) * render legacy bridge point markers visible (#1726) (fe802a4) * stale QuadItem removal after ClusterItem position updates (#1730) (c39ba07) * visual-testing: add UiScrollable chip scroll support for robust chip selection (#1735) (6104d93) ## 5.0.0 (2026-07-15) ### ⚠ BREAKING CHANGES * rewrite android maps utils (#1658) ### Features * rewrite android maps utils (#1658) (eeb0156) ### Bug Fixes * prevent StackOverflowError from deeply nested GeometryCollection in GeoJsonParser (#1699) (f513807) ## 4.5.2 (2026-07-07) ### Bug Fixes * prevent StackOverflowError when parsing deeply nested KML containers and multi-geometries (#1710) (1463cc5) ## 4.5.1 (2026-06-17) ### Bug Fixes * enable filterTouchesWhenObscured on WebView layouts (#1705) (3e59470) ## 4.5.0 (2026-06-16) ### Features * add manual RC release workflow (#1695) (688fc83) ### Bug Fixes * change model name from gemini-2.5-flash to gemini-3.5-flash (#1696) (838a2bf) * enable filterTouchesWhenObscured on WebView (#1703) (0674d75) ## 4.4.1 (2026-05-26) ### Bug Fixes * address lint, compiler, and Error Prone warnings (#1692) (ce809c7) ## 4.4.0 (2026-05-20) ### Features * add navigation flavor to demo for SDK 7.x reproduction (#1680) (12ac29a) ## 4.3.0 (2026-04-24) ### Features * add constructor parameter for custom Executor in cluster renderers (#1682) (b803dc0) ## 4.2.0 (2026-04-22) ### Features * KML URL Sanitizer API (#1678) (43855e9) ### Bug Fixes * disable XML external entities in KML parser (#1673) (4516be3) * KMZ zip bomb mitigation by adding entry and size limits (#1677) (bae3455) * prevent NPE in LatLngBounds.contains by adding null checks for positions (#1675) (6b5a2d3) * restrict KML image downloads to http/https schemes (#1674) (898ae8f) ## 4.1.1 (2026-03-11) ### Bug Fixes * trigger release for PR #1661 (#1662) (8a96267) ## 4.1.0 (2026-02-20) ### Features * Transit Layer Demo & Quality Improvements (#1653) (cb074f9) ## 4.0.0 (2026-01-23) ### ⚠ BREAKING CHANGES * update to maps 20.0.0 (#1644) ### Features * update to maps 20.0.0 (#1644) (60adcde)</excerpt> </source> <source kind="search"> <title>GitHub - googlemaps/android-maps-utils: Maps SDK for Android Utility Library · GitHub</title> <location>https://github.com/googlemaps/android-maps-utils</location> <excerpt>citeturn0search1 [wordlim: 200] Crawled: 3 weeks ago; Required for demos using Advanced Markers or Cloud-based Map Styling. ... StreetViewUtils.fetchStreetViewData(LatLng(8.1425918, 11.5386121), BuildConfig.MAPS_API_KEY,Source.DEFAULT) ... Accordingly, while the library is in version 0.x, backwards-incompatible changes may be introduced at any time.If you find a bug, or have a feature request, please file an issue on GitHub. ... android geojson google-maps heat-maps kml maps marker-clustering utility-library Refer to the contributing guide for more details on AI usage. ## Terms of Service This library uses Google Maps Platform services. Use of Google Maps Platform services through this library is subject to the Google Maps Platform Terms of Service. If your billing address is in the European Economic Area, effective on 8 July 2025, the Google Maps Platform EEA Terms of Service will apply to your use of the Services. Functionality varies by region. Learn more. This library is not a Google Maps Platform Core Service. Therefore, the Google Maps Platform Terms of Service (e.g. Technical Support Services, Service Level Agreements, and Deprecation Policy) do not apply to the code in this library. ## Support This library is offered via an open source license. It is not governed by the Google Maps Platform Support Technical Support Services Guidelines, the SLA, or the Deprecation Policy. However, any Google Maps Platform services used by the library remain subject to the Google Maps Platform Terms of Service. This library adheres to semantic versioning to indicate when backwards-incompatible changes are introduced. Accordingly, while the library is in version 0.x, backwards-incompatible changes may be introduced at any time. If you find a bug, or have a feature request, please file an issue on GitHub. If you would like to get answers to technical questions from other Google Maps Platform developers, ask through one of our developer community channels. If you'd like to contribute, please check the contributing guide. You can also discuss this library on our Discord server. </excerpt> </source> <source kind="search"> <title>android-maps-utils/README.md at main · googlemaps/android-maps-utils · GitHub</title> <location>https://github.com/googlemaps/android-maps-utils/blob/main/README.md</location> <excerpt>citeturn0search2 [wordlim: 200] Crawled: last month; * Heatmaps — display a large number of points as a heat map ... implementation("com.google.maps.android:android-maps-utils-clustering:5.2.0") // x-release-please-version Edit and raw actions # Maps SDK for Android Utility Library ## Description This open-source library contains utilities that are useful for a wide range of applications using the Google Maps SDK for Android. As of version 5.0.0, the library has been rewritten in Kotlin and split into focused submodules so you can depend only on what you need. If you are upgrading from 4.x, see the migration guide. * Marker animation - animates a marker from one position to another * Marker clustering — handles the display of a large number of points * Marker icons — display text on your Markers * Heatmaps — display a large number of points as a heat map * Import KML — displays KML data on the map * Import GeoJSON — displays and styles GeoJSON data on the map * Polyline encoding and decoding — compact encoding for paths, interoperability with Maps API web services * Spherical geometry — for example: computeDistance, computeHeading, computeArea * Street View metadata — checks if a Street View panorama exists at a given location You can also find Kotlin extensions for this library in Maps Android KTX. ## Requirements * Android API level 23+ * Sign up with Google Maps Platform * A Google Maps Platform project with the Maps SDK for Android enabled * An API key associated with the project above ... follow the API key instructions if you're new to the process ## Installation dependencies { // Utilities for Maps SDK for Android (requires Google Play Services) // You do not need to add a separate dependency for the Maps SDK for Android // since this library builds in the compatible version of the Maps SDK. // The aggregator artifact transitively pulls in all submodules below. implementation("com.google.maps.android:android-maps-utils:5.2.0") // x-release-please-version } Alternatively, depend only on the submodules your app needs: dependencies { // Base utilities: PolyUtil, SphericalUtil, collection managers, Street View metadata implementation("com.google.maps.android:android-maps-utils-core:5.2.0") // x-release-please-version // Marker clustering implementation("com.google.maps.android:android-maps-utils-clustering:5.2.0") // x-release-please-version // KML and GeoJSON import implementation("com.google.maps.android:android-maps-utils-data:5.2.0") // x-release-please-version // Heatmaps implementation("com.google.maps.android:android-maps-utils-heatmaps:5.2.0") // x-release-please-version // Marker icons and animation implementation("com.google.maps.android:android-maps-utils-ui:5.2.0") // x-release-please-version } ### Compatibility with Google Navigation SDK for Android If your project integrates the Google Navigation SDK for Android, you must exclude the transitive `play-services-maps` dependency to prevent duplicate class conflicts: configurations.all { if (name.contains("navigation", ignoreCase = true)) { exclude(group = "com.google.android.gms", module = "play-services-maps") } } </excerpt> </source> <source kind="search"> <title>Releases · googlemaps/android-maps-ktx · GitHub</title> <location>https://github.com/googlemaps/android-maps-ktx/releases</location> <excerpt>citeturn0search3 [wordlim: 200] Crawled: 2 months ago; # Releases: googlemaps/android-maps-ktx ... * v6.1.0 ... This commit was created on GitHub.com and signed with GitHub’s verified signature. </excerpt> </source> <omitted_sources count="20">Additional source records were omitted from this bounded result.</omitted_sources> </source_evidence> Citations: - 1: https://www.javatips.net/api/android-maps-utils-master/library/src/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.java?utm_source=openai
Web query:
github googlemaps android-maps-utils NonHierarchicalDistanceBasedAlgorithm "maxDistanceBetweenClusteredItems" sourceResult:
<source_evidence> <source kind="open_page"> <title>NonHierarchicalDistanceBasedAlgorithm (library API)</title> <location>https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.html</location> <excerpt>citeturn1view1 [wordlim: 200] Crawled: last month; Content type: text/html; Source: open({"ref_id":"turn0search0","lineno":null}); Total lines: 194 L0: JavaScript is disabled on your browser. L1: L2: 【0†Skip navigation links】 L3: L4: * 【1†Overview】 L5: * 【2†Package】 L6: * Class L7: * 【3†Tree】 L8: * 【4†Deprecated】 L9: * 【5†Index】 L10: * 【6†Help】 L11: L12: * 【7†Prev Class】 L13: * 【8†Next Class】 L14: L15: * 【9†Frames】 L16: * 【10†No Frames】 L17: L18: * 【11†All Classes】 L19: L20: * Summary: L21: * 【12†Nested】 | L22: * Field | L23: * 【13†Constr】 | L24: * 【14†Method】 L25: L26: * Detail: L27: * Field | L28: * 【15†Constr】 | L29: * 【16†Method】 L30: L31: com.google.maps.android.clustering.algo L32: ## Class NonHierarchicalDistanceBasedAlgorithm<T extends 【17†ClusterItem】> L33: L34: * java.lang.Object L35: * * 【18†com.google.maps.android.clustering.algo.AbstractAlgorithm】<T> L36: * * com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm<T> L37: L38: * All Implemented Interfaces: L39: 【19†Algorithm】<T> L40: L41: Direct Known Subclasses: L42: 【20†NonHierarchicalViewBasedAlgorithm】 L43: * * * L44: L45: public class NonHierarchicalDistanceBasedAlgorithm<T extends 【17†ClusterItem】> L46: extends 【18†AbstractAlgorithm】<T> L47: L48: A simple clustering algorithm with O(nlog n) performance. Resulting clusters are not hierarchical. L49: High level algorithm: L50: 1. Iterate over items in the order they were added (candidate clusters). L51: 2. Create a cluster with the center of the item. L52: 3. Add all items that are within a certain distance to the cluster. L53: 4. Move any items out of an existing cluster if they are closer to another cluster. L54: 5. Remove those items from the list of candidate clusters. L55: L56: Clusters have the center of the first element (not the centroid of the items within it). L57: L58: * * ### Nested Class Summary L59: Nested Classes L60: Modifier and Type | Class and Description L61: --- | --- L62: `protected static class ` | `【8†NonHierarchicalDistanceBasedAlgorithm.QuadItem】<【8†T】 extends 【17†ClusterItem】>` L63: * ### Constructor Summary L64: L65: Constructors L66: Constructor and Description L67: --- L68: `【21†NonHierarchicalDistanceBasedAlgorithm】()` L69: * ### Method Summary L70: All Methods Instance Methods Concrete Methods L71: Modifier and Type | Method and Description L72: --- | --- L73: `boolean` | `【22†addItem】(【10†T】 item)` Adds an item to the algorithm L74: `boolean` | `【23†addItems】(java.util.Collection<【10†T】> items)` Adds a collection of items to the algorithm L75: `void` | `【24†clearItems】()` L76: `protected java.util.Collection<【8†NonHierarchicalDistanceBasedAlgorithm.QuadItem】<【10†T】>>` | `【25†getClusteringItems】(【26†PointQuadTree】<【8†NonHierarchicalDistanceBasedAlgorithm.QuadItem】<【10†T】>> quadTree, float zoom)` L77: `java.util.Set<? extends 【27†Cluster】<【10†T】>>` | `【28†getClusters】(float zoom)` L78: `java.util.Collection<【10†T】>` | `【29†getItems】()` L79: `int` | `【30†getMaxDistanceBetweenClusteredItems】()` L80: `boolean` | `【31†removeItem】(【10†T】 item)` Removes an item from the algorithm L81: `boolean` | `【32†removeItems】(java.util.Collection<【10†T】> items)` Removes a collection of items from the algorithm L82: `void` | `【33†setMaxDistanceBetweenClusteredItems】(int maxDistance)` L83: `boolean` | `【34†updateItem】(【10†T】 item)` Updates the provided item in the algorithm L84: * ### Methods inherited from class com.google.maps.android.clustering.algo.【18†AbstractAlgorithm】 L85: `【35†lock】, 【36†unlock】` L86: * ### Methods inherited from class java.lang.Object L87: L88: `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait` L89: L90: * * ### Constructor Detail L9…[truncated]</excerpt> </source> <source kind="search"> <title>NonHierarchicalDistanceBasedAlgorithm (library API)</title> <location>https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.html</location> <excerpt>citeturn0search0 [wordlim: 200] Published: 6.7 years ago; Crawled: 3 weeks ago; * * com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm<T> ... `protected java.util.Collection<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>>` | `getClusteringItems(PointQuadTree<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> quadTree, float zoom)` ... `int` | `getMaxDistanceBetweenClusteredItems()` com.google.maps.android.clustering.algo ## Class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> * java.lang.Object * * com.google.maps.android.clustering.algo.AbstractAlgorithm<T> * * com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm<T> * All Implemented Interfaces: Algorithm<T> Direct Known Subclasses: NonHierarchicalViewBasedAlgorithm * * * public class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> extends AbstractAlgorithm<T> A simple clustering algorithm with O(nlog n) performance. Resulting clusters are not hierarchical. High level algorithm: 1. Iterate over items in the order they were added (candidate clusters). 2. Create a cluster with the center of the item. 3. Add all items that are within a certain distance to the cluster. 4. Move any items out of an existing cluster if they are closer to another cluster. 5. Remove those items from the list of candidate clusters. `java.util.Set<? extends Cluster<T>>` | `getClusters(float zoom)` `java.util.Collection<T>` | `getItems()` `int` | `getMaxDistanceBetweenClusteredItems()` `boolean` | `removeItem(T item)` Removes an item from the algorithm `boolean` | `removeItems(java.util.Collection<T> items)` Removes a collection of items from the algorithm `void` | `setMaxDistanceBetweenClusteredItems(int maxDistance)` `boolean` | `updateItem(T item)` Updates the provided item in the algorithm * * ### Constructor Detail * #### NonHierarchicalDistanceBasedAlgorithm public NonHierarchicalDistanceBasedAlgorithm() * ### Method Detail * #### addItem public boolean addItem(T item) Adds an item to the algorithm Parameters: `item` - the item to be added Returns: true if the algorithm contents changed as a result of the call Updates the provided item in the algorithm Parameters: `item` - the item to be updated Returns: true if the item existed in the algorithm and was updated, or false if the item did not exist in the algorithm and the algorithm contents remain unchanged. * #### getClusters public java.util.Set<? extends Cluster<T>> getClusters(float zoom) * #### getClusteringItems protected java.util.Collection<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> getClusteringItems(PointQuadTree<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> quadTree, float zoom) * #### getItems public java.util.Collection<T> getItems() * #### setMaxDistanceBetweenClusteredItems public void setMaxDistanceBetweenClusteredItems(int maxDistance) * #### getMaxDistanceBetweenClusteredItems public int getMaxDistanceBetweenClusteredItems()</excerpt> </source> <source kind="search"> <title>Algorithm (library API)</title> <location>https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/Algorithm.html</location> <excerpt>citeturn0search1 [wordlim: 200] Published: 6.7 years ago; Crawled: 3 weeks ago; com.google.maps.android.clustering.algo## Interface Algorithm<T extends ClusterItem> ... AbstractAlgorithm, GridBasedAlgorithm, NonHierarchicalDistanceBasedAlgorithm, NonHierarchicalViewBasedAlgorithm, PreCachingAlgorithmDecorator, ScreenBasedAlgorithmAdapter ... `int` | `getMaxDistanceBetweenClusteredItems()` `int` | `getMaxDistanceBetweenClusteredItems()` `void` | `lock()` `boolean` | `removeItem(T item)` Removes an item from the algorithm `boolean` | `removeItems(java.util.Collection<T> items)` Removes a collection of items from the algorithm `void` | `setMaxDistanceBetweenClusteredItems(int maxDistance)` `void` | `unlock()` `boolean` | `updateItem(T item)` Updates the provided item in the algorithm * * ### Method Detail * #### addItem boolean addItem(T item) Adds an item to the algorithm Parameters: `item` - the item to be added Returns: true if the algorithm contents changed as a result of the call * #### addItems boolean addItems(java.util.Collection<T> items) Adds a collection of items to the algorithm Parameters: `items` - the items to be added Returns: true if the algorithm contents changed as a result of the call </excerpt> </source> <source kind="search"> <title>NonHierarchicalViewBasedAlgorithm</title> <location>https://googlemaps.github.io/android-maps-utils/android-maps-utils%20/com.google.maps.android.clustering.algo/-non-hierarchical-view-based-algorithm/index.html</location> <excerpt>citeturn0search2 [wordlim: 200] Crawled: 3 months ago; open class NonHierarchicalViewBasedAlgorithm<T : ClusterItem? ... It requires shouldReclusterOnMapMovement to be true in order to re-render clustering when camera movement changes the visible area. ... open fun getMaxDistanceBetweenClusteredItems(): Int </excerpt> </source> <source kind="search"> <title>GitHub - googlemaps/android-maps-utils: Maps SDK for Android Utility Library · GitHub</title> <location>https://github.com/googlemaps/android-maps-utils</location> <excerpt>citeturn0search3 [wordlim: 200] Crawled: 3 weeks ago; Required for demos using Advanced Markers or Cloud-based Map Styling. ... * Spherical geometry source, compute distance sample ... android:name="com.google.maps.android.utils.attribution.AttributionIdInitializer" ... If you find a bug, or have a feature request, please file an issue on GitHub. ... android geojson google-maps heat-maps kml maps marker-clustering utility-library </excerpt> </source> <omitted_sources count="15">Additional source records were omitted from this bounded result.</omitted_sources> </source_evidence> Citations: - 1: https://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.html
Script executed:
set -o pipefail base="${HOME}/.gradle/caches/modules-2/files-2.1/com.google.maps.android" printf '%s\n' '--- cached maps-utils artifacts ---' find "$base" -maxdepth 4 -type f \( -name '*android-maps-utils*6.1.0*.jar' -o -name '*android-maps-utils*6.1.0*.aar' -o -name '*android-maps-utils*6.1.0*.pom' -o -name '*android-maps-utils*6.1.0*.module' \) -print 2>/dev/null printf '%s\n' '--- cached clustering source/class candidates ---' find "$base" -type f \( -name '*sources.jar' -o -name '*.jar' -o -name '*.aar' \) -print 2>/dev/null | grep -E 'android-maps-utils|maps-compose' | head -80
Repository: meshtastic/Meshtastic-Android
Length of output: 253
Script executed:
set -o pipefail printf '%s\n' '--- stackCoincident definition and callers ---' rg -n -F -e 'fun stackCoincident' -e 'stackCoincident(' feature androidApp printf '%s\n' '--- implementation ---' file=$(rg -l -F 'fun stackCoincident' feature androidApp | head -1) if [ -n "$file" ]; then nl -ba "$file" fi printf '%s\n' '--- stack tests ---' rg -n -F -e 'stackCoincident' -e '5 m' -e '5m' feature/*/src/*Test androidApp/src 2>/dev/null || true
Repository: meshtastic/Meshtastic-Android
Length of output: 44003
Ensure a cluster tap can split distinct stack tops.
A cluster containing at least 10 distinct stack tops can remain clustered after the 140 m minimum fit. The distance-based algorithm groups items by a zoom-dependent screen distance, and a 140 m geographic floor does not guarantee that a 6 m separation exceeds that distance. A second tap then recomputes the same bounds because allSameLocation is false, so the cluster does not open its member list. Fit closer, or open the member list when a cluster remains unchanged after fitting.
Nodes sharing a reduced-precision position, or radios a few meters apart at one site, drew as chips piled on one another. Nothing showed there were several, only the top one could be tapped, and on MapLibre the "Nodes at this location" list never opened for a cluster of them because supercluster reports
clusterMaxZoom + 1for points that never split.🌟 New Features
MapColocation.spreadMeters). Grouping lives infeature/map(stackCoincident) so both flavors draw the same stacks.BadgedBoxandBadge; MapLibre rasterizes the same large badge since a map layer cannot host a composable.🐛 Bug Fixes
🧹 Chores
map-and-waypoints.mddescribes stacks, the badge and the cluster tap.unclusteredNodes, which only the per-node precision circles used.Testing Performed
NodeStackTest: 5 m grouping, separation past the spread, a stack spanning two latitude bands, top-node rule, badge label cap.StackFeaturesTest: stack count and members on MapLibre features.ClusterCannotSplitTest: expansion zoom past the ceiling and failed-query sentinels list the cluster.ClusterMemberOrderTest: natural order, favorites first, long name over the heard-ago title, a non-ASCII digit sorting as text (fails under the oldisDigitcheck), and a local display name deciding the order over the broadcast long name (fails when sorting onuser.long_name).MapNodeClusterItemsTest: co-located nodes become one Google item carrying every member.-PwarningsAsErrors=trueandkmpSmokeCompile.Summary by CodeRabbit
New Features
Bug Fixes