# Clustering markers on Google map on zoom

I have a method that is getting called when someone zooms camera on the map (Google map). I recalculate the positions of markers of map and the code is clunky and not effective. I iterate over arrays three times per method call and that is really slow. When I have 600 markers the performance is really lacking.

What could I improve to make it faster?

I use following local variables:

float lastZoomLevel_; // last zoom value on last zoom
BOOL forceRecalculateMap; // when new data arrives I use this to force repositioning
NSArray *pointsArrayV_; // Array of BankPoint instances, object that holds location and description of marker

- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position
{
float currentZoomLevel = mapView.camera.zoom;
float diff = fabs(currentZoomLevel - lastZoomLevel_);

if (diff > 0.3 || self.forceRecalculateMap){

self.forceRecalculateMap = NO;

lastZoomLevel_ = currentZoomLevel;

markersGroupArray_ = [[NSMutableArray alloc] init];

for (BankPoint *bpoint in pointsArrayV_) {

CLLocationCoordinate2D coord = bpoint.coordinates.coordinate;

CGPoint currentPoint = [mapView.projection pointForCoordinate:coord];

if ([markersGroupArray_ count] == 0){

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:bpoint, nil];

}

else {

int counter= 0;
for (NSMutableArray *array in markersGroupArray_){

for (BankPoint *bbpoint in array){

CLLocationCoordinate2D mcoord = bbpoint.coordinates.coordinate;
CGPoint mpt = [mapView.projection pointForCoordinate:mcoord];

if ([self distance:mpt point:currentPoint] < 20){
break;
}
}

break;
}
counter++;

}

if ([markersGroupArray_ count] > counter){
NSMutableArray *groupArray = [markersGroupArray_ objectAtIndex:counter];
[groupArray insertObject:bpoint atIndex:0];
[markersGroupArray_ replaceObjectAtIndex:counter withObject:groupArray];
}
}

NSMutableArray * array = [[NSMutableArray alloc]initWithObjects:bpoint, nil];
}
}
}

[mapView clear];

for (NSArray *array in markersGroupArray_){

BankPoint *item = [array objectAtIndex:0];

CLLocationCoordinate2D coord = item.coordinates.coordinate;

GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = coord;
marker.map = mapView;
marker.userData = item;
}
}
}

- (float)distance :(CGPoint)pointA point:(CGPoint) pointB
{
return sqrt( (pow((pointA.x - pointB.x),2) + pow((pointA.y-pointB.y),2)));
}


The postfix underscore is quite strange to me, and I don't understand it at all. It matches no convention I've ever seen or heard of, and it's just not obvious to me what's gained by sticking out there. What's it for?

In your 93 lines of code, the only comments to be found are on the first 3 lines:

float lastZoomLevel_; // last zoom value on last zoom
BOOL forceRecalculateMap; // when new data arrives I use this to force repositioning
NSArray *pointsArrayV_; // Array of BankPoint instances, object that holds location and description of marker


And these comments are almost completely unnecessary. And if they are to be considered necessary, then we easily make them unnecessary by improving the naming of the variables.

CGFloat _lastZoomLevel;


Needs no comment.

BOOL forceRecalculateMap;


Probably needs no comment. Worst case scenario, we might leave a comment on any line that sets this variable. Though the implications of this being set to YES should be pretty clear based on the variable name.

NSArray *pointsArrayV_;


This "needs" a comment, and therefore, it probably simply needs a better variable name. Why not just call it _bankPoints? This should make it sufficiently clear what sorts of objects the array is intended to contain. And we needn't comment here about what those objects do. If someone wants to know what a BankPoint instance does, they can go to BankPoint.h or BankPoint.m, or any documentation you've provided about the BankPoint class.

The bigger crime though is that there are no comments at all in this method:

- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position


That wouldn't be so terrible if the method were simpler. But it's a complicated method, and it's hard to understand what it's trying to do--which makes it hard to optimize.

You say you iterate over arrays three times per method call. That's not actually true. One over your fast iteration loops is nested. You run the nested loop once per iteration of the outer loop.

A better plain-English description of exactly what this method is trying to do along with some embedded comments will already make this method significantly better even if it still performs exactly the same. Single lines of code don't generally need comments. I can read a single line of code and know what that line does.

What we need comments for are the bigger picture things. What does that specific line do in context of the current scope? In context of the method as a whole? In context of the class as a whole? Use comments to give your code more clear context. This way, when we get lost in the line-by-line details, there's always a helpful comment to re-orient us to the context.