diff --git a/app/src/fdroid/java/org/meshtastic/app/map/cluster/MarkerClusterer.java b/app/src/fdroid/java/org/meshtastic/app/map/cluster/MarkerClusterer.java
deleted file mode 100644
index 38e51da52..000000000
--- a/app/src/fdroid/java/org/meshtastic/app/map/cluster/MarkerClusterer.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2025 Meshtastic LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.meshtastic.app.map.cluster;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Point;
-import android.view.MotionEvent;
-
-import org.meshtastic.app.map.model.MarkerWithLabel;
-
-import org.osmdroid.util.BoundingBox;
-import org.osmdroid.views.MapView;
-import org.osmdroid.views.overlay.Overlay;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.ListIterator;
-
-/**
- * An overlay allowing to perform markers clustering.
- * Usage: put your markers inside with add(Marker), and add the MarkerClusterer to the map overlays.
- * Depending on the zoom level, markers will be displayed separately, or grouped as a single Marker.
- *
- * This abstract class provides the framework. Sub-classes have to implement the clustering algorithm,
- * and the rendering of a cluster.
- *
- * @author M.Kergall
- *
- */
-public abstract class MarkerClusterer extends Overlay {
-
- /** impossible value for zoom level, to force clustering */
- protected static final int FORCE_CLUSTERING = -1;
-
- protected ArrayList mItems = new ArrayList();
- protected Point mPoint = new Point();
- protected ArrayList mClusters = new ArrayList();
- protected int mLastZoomLevel;
- protected Bitmap mClusterIcon;
- protected String mName, mDescription;
-
- // abstract methods:
-
- /** clustering algorithm */
- public abstract ArrayList clusterer(MapView mapView);
- /** Build the marker for a cluster. */
- public abstract MarkerWithLabel buildClusterMarker(StaticCluster cluster, MapView mapView);
- /** build clusters markers to be used at next draw */
- public abstract void renderer(ArrayList clusters, Canvas canvas, MapView mapView);
-
- public MarkerClusterer() {
- super();
- mLastZoomLevel = FORCE_CLUSTERING;
- }
-
- public void setName(String name){
- mName = name;
- }
-
- public String getName(){
- return mName;
- }
-
- public void setDescription(String description){
- mDescription = description;
- }
-
- public String getDescription(){
- return mDescription;
- }
-
- /** Set the cluster icon to be drawn when a cluster contains more than 1 marker.
- * If not set, default will be the default osmdroid marker icon (which is really inappropriate as a cluster icon). */
- public void setIcon(Bitmap icon){
- mClusterIcon = icon;
- }
-
- /** Add the Marker.
- * Important: Markers added in a MarkerClusterer should not be added in the map overlays. */
- public void add(MarkerWithLabel marker){
- mItems.add(marker);
- }
-
- /** Force a rebuild of clusters at next draw, even without a zooming action.
- * Should be done when you changed the content of a MarkerClusterer. */
- public void invalidate(){
- mLastZoomLevel = FORCE_CLUSTERING;
- }
-
- /** @return the Marker at id (starting at 0) */
- public MarkerWithLabel getItem(int id){
- return mItems.get(id);
- }
-
- /** @return the list of Markers. */
- public ArrayList getItems(){
- return mItems;
- }
-
- protected void hideInfoWindows(){
- for (MarkerWithLabel m : mItems){
- if (m.isInfoWindowShown())
- m.closeInfoWindow();
- }
- }
-
- @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) {
- if (shadow)
- return;
- //if zoom has changed and mapView is now stable, rebuild clusters:
- int zoomLevel = mapView.getZoomLevel();
- if (zoomLevel != mLastZoomLevel && !mapView.isAnimating()){
- hideInfoWindows();
- mClusters = clusterer(mapView);
- renderer(mClusters, canvas, mapView);
- mLastZoomLevel = zoomLevel;
- }
-
- for (StaticCluster cluster:mClusters){
- MarkerWithLabel marker = cluster.getMarker();
- marker.draw(canvas, mapView, false);
- }
- }
-
- public Iterable reversedClusters() {
- return new Iterable() {
- @Override
- public Iterator iterator() {
- final ListIterator i = mClusters.listIterator(mClusters.size());
- return new Iterator() {
- @Override
- public boolean hasNext() {
- return i.hasPrevious();
- }
-
- @Override
- public StaticCluster next() {
- return i.previous();
- }
-
- @Override
- public void remove() {
- i.remove();
- }
- };
- }
- };
- }
-
- @Override public boolean onSingleTapConfirmed(final MotionEvent event, final MapView mapView){
- for (final StaticCluster cluster : reversedClusters()) {
- if (cluster.getMarker().onSingleTapConfirmed(event, mapView))
- return true;
- }
- return false;
- }
-
- @Override public boolean onLongPress(final MotionEvent event, final MapView mapView) {
- for (final StaticCluster cluster : reversedClusters()) {
- if (cluster.getMarker().onLongPress(event, mapView))
- return true;
- }
- return false;
- }
-
- @Override public boolean onTouchEvent(final MotionEvent event, final MapView mapView) {
- for (StaticCluster cluster : reversedClusters()) {
- if (cluster.getMarker().onTouchEvent(event, mapView))
- return true;
- }
- return false;
- }
-
- @Override public boolean onDoubleTap(final MotionEvent event, final MapView mapView) {
- for (final StaticCluster cluster : reversedClusters()) {
- if (cluster.getMarker().onDoubleTap(event, mapView))
- return true;
- }
- return false;
- }
-
- @Override public BoundingBox getBounds(){
- if (mItems.size() == 0)
- return null;
- double minLat = Double.MAX_VALUE;
- double minLon = Double.MAX_VALUE;
- double maxLat = -Double.MAX_VALUE;
- double maxLon = -Double.MAX_VALUE;
- for (final MarkerWithLabel item : mItems) {
- final double latitude = item.getPosition().getLatitude();
- final double longitude = item.getPosition().getLongitude();
- minLat = Math.min(minLat, latitude);
- minLon = Math.min(minLon, longitude);
- maxLat = Math.max(maxLat, latitude);
- maxLon = Math.max(maxLon, longitude);
- }
- return new BoundingBox(maxLat, maxLon, minLat, minLon);
- }
-
-}
diff --git a/app/src/fdroid/java/org/meshtastic/app/map/cluster/RadiusMarkerClusterer.java b/app/src/fdroid/java/org/meshtastic/app/map/cluster/RadiusMarkerClusterer.java
deleted file mode 100644
index e2710352a..000000000
--- a/app/src/fdroid/java/org/meshtastic/app/map/cluster/RadiusMarkerClusterer.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2025 Meshtastic LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.meshtastic.app.map.cluster;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.view.MotionEvent;
-
-import org.meshtastic.app.map.model.MarkerWithLabel;
-
-import org.osmdroid.bonuspack.R;
-import org.osmdroid.util.BoundingBox;
-import org.osmdroid.util.GeoPoint;
-import org.osmdroid.views.MapView;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Radius-based Clustering algorithm:
- * create a cluster using the first point from the cloned list.
- * All points that are found within the neighborhood are added to this cluster.
- * Then all the neighbors and the main point are removed from the list of points.
- * It continues until the list is empty.
- *
- * Largely inspired from GridMarkerClusterer by M.Kergall
- *
- * @author sidorovroman92@gmail.com
- */
-
-public class RadiusMarkerClusterer extends MarkerClusterer {
-
- protected int mMaxClusteringZoomLevel = 7;
- protected int mRadiusInPixels = 100;
- protected double mRadiusInMeters;
- protected Paint mTextPaint;
- private ArrayList mClonedMarkers;
- protected boolean mAnimated;
- int mDensityDpi;
-
- /** cluster icon anchor */
- public float mAnchorU = MarkerWithLabel.ANCHOR_CENTER, mAnchorV = MarkerWithLabel.ANCHOR_CENTER;
- /** anchor point to draw the number of markers inside the cluster icon */
- public float mTextAnchorU = MarkerWithLabel.ANCHOR_CENTER, mTextAnchorV = MarkerWithLabel.ANCHOR_CENTER;
-
- public RadiusMarkerClusterer(Context ctx) {
- super();
- mTextPaint = new Paint();
- mTextPaint.setColor(Color.WHITE);
- mTextPaint.setTextSize(15 * ctx.getResources().getDisplayMetrics().density);
- mTextPaint.setFakeBoldText(true);
- mTextPaint.setTextAlign(Paint.Align.CENTER);
- mTextPaint.setAntiAlias(true);
- Drawable clusterIconD = ctx.getResources().getDrawable(R.drawable.marker_cluster);
- Bitmap clusterIcon = ((BitmapDrawable) clusterIconD).getBitmap();
- setIcon(clusterIcon);
- mAnimated = true;
- mDensityDpi = ctx.getResources().getDisplayMetrics().densityDpi;
- }
-
- /** If you want to change the default text paint (color, size, font) */
- public Paint getTextPaint(){
- return mTextPaint;
- }
-
- /** Set the radius of clustering in pixels. Default is 100px. */
- public void setRadius(int radius){
- mRadiusInPixels = radius;
- }
-
- /** Set max zoom level with clustering. When zoom is higher or equal to this level, clustering is disabled.
- * You can put a high value to disable this feature. */
- public void setMaxClusteringZoomLevel(int zoom){
- mMaxClusteringZoomLevel = zoom;
- }
-
- /** Radius-Based clustering algorithm */
- @Override public ArrayList clusterer(MapView mapView) {
-
- ArrayList clusters = new ArrayList();
- convertRadiusToMeters(mapView);
-
- mClonedMarkers = new ArrayList(mItems); //shallow copy
- while (!mClonedMarkers.isEmpty()) {
- MarkerWithLabel m = mClonedMarkers.get(0);
- StaticCluster cluster = createCluster(m, mapView);
- clusters.add(cluster);
- }
- return clusters;
- }
-
- private StaticCluster createCluster(MarkerWithLabel m, MapView mapView) {
- GeoPoint clusterPosition = m.getPosition();
-
- StaticCluster cluster = new StaticCluster(clusterPosition);
- cluster.add(m);
-
- mClonedMarkers.remove(m);
-
- if (mapView.getZoomLevel() > mMaxClusteringZoomLevel) {
- //above max level => block clustering:
- return cluster;
- }
-
- Iterator it = mClonedMarkers.iterator();
- while (it.hasNext()) {
- MarkerWithLabel neighbor = it.next();
- double distance = clusterPosition.distanceToAsDouble(neighbor.getPosition());
- if (distance <= mRadiusInMeters) {
- cluster.add(neighbor);
- it.remove();
- }
- }
-
- return cluster;
- }
-
- @Override public MarkerWithLabel buildClusterMarker(StaticCluster cluster, MapView mapView) {
- MarkerWithLabel m = new MarkerWithLabel(mapView, "", null);
- m.setPosition(cluster.getPosition());
- m.setInfoWindow(null);
- m.setAnchor(mAnchorU, mAnchorV);
-
- Bitmap finalIcon = Bitmap.createBitmap(mClusterIcon.getScaledWidth(mDensityDpi),
- mClusterIcon.getScaledHeight(mDensityDpi), mClusterIcon.getConfig());
- Canvas iconCanvas = new Canvas(finalIcon);
- iconCanvas.drawBitmap(mClusterIcon, 0, 0, null);
- String text = "" + cluster.getSize();
- int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
- iconCanvas.drawText(text,
- mTextAnchorU * finalIcon.getWidth(),
- mTextAnchorV * finalIcon.getHeight() - textHeight / 2,
- mTextPaint);
- m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), finalIcon));
-
- return m;
- }
-
- @Override public void renderer(ArrayList clusters, Canvas canvas, MapView mapView) {
- for (StaticCluster cluster : clusters) {
- if (cluster.getSize() == 1) {
- //cluster has only 1 marker => use it as it is:
- cluster.setMarker(cluster.getItem(0));
- } else {
- //only draw 1 Marker at Cluster center, displaying number of Markers contained
- MarkerWithLabel m = buildClusterMarker(cluster, mapView);
- cluster.setMarker(m);
- }
- }
- }
-
- private void convertRadiusToMeters(MapView mapView) {
-
- Rect mScreenRect = mapView.getIntrinsicScreenRect(null);
-
- int screenWidth = mScreenRect.right - mScreenRect.left;
- int screenHeight = mScreenRect.bottom - mScreenRect.top;
-
- BoundingBox bb = mapView.getBoundingBox();
-
- double diagonalInMeters = bb.getDiagonalLengthInMeters();
- double diagonalInPixels = Math.sqrt(screenWidth * screenWidth + screenHeight * screenHeight);
- double metersInPixel = diagonalInMeters / diagonalInPixels;
-
- mRadiusInMeters = mRadiusInPixels * metersInPixel;
- }
-
- public void setAnimation(boolean animate){
- mAnimated = animate;
- }
-
- public void zoomOnCluster(MapView mapView, StaticCluster cluster){
- BoundingBox bb = cluster.getBoundingBox();
- if (bb.getLatNorth()!=bb.getLatSouth() || bb.getLonEast()!=bb.getLonWest()) {
- bb = bb.increaseByScale(2.3f);
- mapView.zoomToBoundingBox(bb, true);
- } else //all points exactly at the same place:
- mapView.setExpectedCenter(bb.getCenterWithDateLine());
- }
-
- @Override public boolean onSingleTapConfirmed(final MotionEvent event, final MapView mapView){
- for (final StaticCluster cluster : reversedClusters()) {
- if (cluster.getMarker().onSingleTapConfirmed(event, mapView)) {
- if (mAnimated && cluster.getSize() > 1)
- zoomOnCluster(mapView, cluster);
- return true;
- }
- }
- return false;
- }
-
-}
diff --git a/app/src/fdroid/java/org/meshtastic/app/map/cluster/StaticCluster.java b/app/src/fdroid/java/org/meshtastic/app/map/cluster/StaticCluster.java
deleted file mode 100644
index 324a34b52..000000000
--- a/app/src/fdroid/java/org/meshtastic/app/map/cluster/StaticCluster.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2025 Meshtastic LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.meshtastic.app.map.cluster;
-
-import org.meshtastic.app.map.model.MarkerWithLabel;
-
-import org.osmdroid.util.BoundingBox;
-import org.osmdroid.util.GeoPoint;
-
-import java.util.ArrayList;
-
-/**
- * Cluster of Markers.
- * @author M.Kergall
- */
-public class StaticCluster {
- protected final ArrayList mItems = new ArrayList();
- protected GeoPoint mCenter;
- protected MarkerWithLabel mMarker;
-
- public StaticCluster(GeoPoint center) {
- mCenter = center;
- }
-
- public void setPosition(GeoPoint center){
- mCenter = center;
- }
-
- public GeoPoint getPosition() {
- return mCenter;
- }
-
- public int getSize() {
- return mItems.size();
- }
-
- public MarkerWithLabel getItem(int index) {
- return mItems.get(index);
- }
-
- public boolean add(MarkerWithLabel t) {
- return mItems.add(t);
- }
-
- /** set the Marker to be displayed for this cluster */
- public void setMarker(MarkerWithLabel marker){
- mMarker = marker;
- }
-
- /** @return the Marker to be displayed for this cluster */
- public MarkerWithLabel getMarker(){
- return mMarker;
- }
-
- public BoundingBox getBoundingBox(){
- if (getSize()==0)
- return null;
- GeoPoint p = getItem(0).getPosition();
- BoundingBox bb = new BoundingBox(p.getLatitude(), p.getLongitude(), p.getLatitude(), p.getLongitude());
- for (int i=1; i