I've got a problem with my osm app. I get Set of points from my server side application and than I want to visualise it as some area. So I create a polygon from this points and add it to my mapView object. It works but as the area becomes bigger there occures a problem with scrolling which just lags until I reach the area without my Overlays.
How can I improve map redrawing performance?
I thought about deviding my area polygon into smaller polygons but than they just intersect with each other and the color isn't uniform.
Here is part of my code. Normally I call it everytime I get message with new data from the server in AsyncTask and invalidate mapView on postExecute method but it doesn't really matter since the problem is not with just drawing but scrolling, does it?
List<Overlay> mapOverlays = new ArrayList<>();
Drawable icon = getIcon();
Marker marker = new Marker(mapView);
marker.setPosition(new GeoPoint(newPosition));
marker.setTitle(title);
marker.setIcon(icon);
mapOverlays.add(marker);
List<GeoPoint> listWithAreaPoints = new ArrayList<>();
listWithAreaPoints.addAll(setWithAreaPoints);
Polygon searchedArea = new Polygon(activity.getApplicationContext());
searchedArea.setPoints(listWithAreaPoints);
searchedArea.setFillColor(0x12121212);
searchedArea.setStrokeColor(0x12121212);
searchedArea.setStrokeWidth(0);
mapOverlays.add(searchedArea);
mapView.getOverlays().clear();
mapView.getOverlays().addAll(mapOverlays);
mapView.invalidate();
Thanks for any advice.
I've found out what was wrong.
The data which I was receiving from the server contained a lot of points (hundreds maybe thousands) and I was giving them to Polygon object's method setPoints() in chaotic sequence. In consequence the polygon method draw() drew successive lines without any order what can be seen on my printscreen (blank areas). As the number of points increased the number of polygon's "sides" increased also and redrawing performance decreased.
The solution was to sort List of points by distance so it would represent List of successive corners of the polygon and remove repetitions before giving them as argument to method Polygon.setPoints().
Maybe it will help someone in the future so I'll live here my method to sort GeoPoints as successive polygon's points:
private List<GeoPoint> sortGeoPointsListByDistance(List<GeoPoint> searchedArea){
List<GeoPoint> orderedSearchedArea = new ArrayList<>();
orderedSearchedArea.add(searchedArea.remove(0));
while (searchedArea.size() > 0) {
GeoPoint point = orderedSearchedArea.get(orderedSearchedArea.size() - 1);
int nearestPointIndex = findNearestPointIndex(point, searchedArea);
GeoPoint nearestPoint = searchedArea.get(nearestPointIndex);
if(nearesPointIsTheSamePoint(point, nearestPoint)){
searchedArea.remove(nearestPointIndex);
} else {
orderedSearchedArea.add(searchedArea.remove(nearestPointIndex));
}
}
return orderedSearchedArea;
}
private int findNearestPointIndex(GeoPoint point, List<GeoPoint> listToSearch) {
int index =0;
double dist = 0;
for(int i=0;i<listToSearch.size();i++){
GeoPoint currentPoint = listToSearch.get(i);
double currentPointDist = distFrom( point.getLatitude(), point.getLongitude(), currentPoint.getLatitude(), currentPoint.getLongitude());
if(i==0){
index = i;
dist = currentPointDist;
} else if(currentPointDist<dist){
index = i;
dist = currentPointDist;
}
}
return index;
}
private boolean nearesPointIsTheSamePoint(GeoPoint point, GeoPoint nearestPoint){
if(point.getLatitude()==nearestPoint.getLatitude() && point.getLongitude()==nearestPoint.getLongitude()){
return true;
} else{
return false;
}
}
private double distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 6371000; //meters
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = (earthRadius * c);
return dist;
}