ios - Function to spread MapView annotation such that none are overlapping -
ios - Function to spread MapView annotation such that none are overlapping -
it seems many have touched on issue of overlapping mkannotation views, , gracefully spreading them out @ end of zoom, , @ viewdidload. think going bite bullet , dev out solution, before wanted inquire advice on algo implement. previous posts topic had no viable solution offered:
ios sdk mkmapview overlapping pins? laying out overlapping rectangles
and many more...
so function thinking of this: (note cgrects same size)
-(nsarray *)spreadouttheseviews:(nsarray *)arrayofcgrects{ //////////////////////////////////// //find out overlaps who.. //////////////////////////////////// nsmutablearray *arrayofarraysofrects = [[nsmutablearray alloc] init]; // 1. create array allow know rects have been added 1 of sets int n = (int)[arrayofcgrects count]; nsmutablearray *addedalready = [[nsmutablearray alloc] init]; (id obj in arrayofcgrects ) { [addedalready addobject:@0]; } // 2. go through , add together them if overlap (int i=0; i<[arrayofcgrects count]; i++) { if ([[addedalready objectatindex:i] isequaltovalue:@(0)]) { cgrect rect1 = [[arrayofarraysofrects objectatindex:i] cgrectvalue]; [arrayofarraysofrects addobject:[[nsmutablearray alloc] initwithobjects:@(i), nil]]; [addedalready insertobject:@(1) atindex:i]; (int j=0; j<[arrayofcgrects count]; j++){ if (i!=j && [[addedalready objectatindex:j] isequaltovalue:@(0)] ) { cgrect rect2 = [[arrayofarraysofrects objectatindex:j] cgrectvalue]; if (cgrectintersectsrect(rect1,rect2)){ // check if overlapping, if so, add together [[arrayofarraysofrects lastobject] addobject:@(j)]; [addedalready insertobject:@(1) atindex:j]; } } } } } nsmutablearray *arrayofcgpoints = [[nsmutablearray alloc] init]; //3. have "clusters" of overlapping rects.. force them away each other.. for(nsarray *indexarray in arrayofarraysofrects){ if ([indexarray count]==1){ // add together cgpoint cgrect rect = [[arrayofcgrects objectatindex:(nsinteger)[indexarray firstobject]] cgrectvalue]; [arrayofcgpoints addobject:[nsvalue valuewithcgpoint:rect.origin] ]; }else{ // heart of algo.. // thought 1: average of cgpoints find center of of them, find ring specific radius can set them on. note packing problem dont have improve solution for.. } } homecoming arrayofcgpoints; } any help here appreciated..
well not prettiest of solutions.. got working in case finds useful.. please still post if have more elegant solution!
-(nsarray *)spreadouttheseviews:(nsarray *)arrayofcgrects{ bool doanyoverlapstill = true; int counter=0; nsmutablearray *newarrayofcgrects = [[nsmutablearray alloc] initwitharray:arrayofcgrects]; while (doanyoverlapstill) { nslog([nsstring stringwithformat:@"number of iters %d",counter]); (int i=0; i<[arrayofcgrects count]; i++) { cgrect rect1 = [[newarrayofcgrects objectatindex:i] cgrectvalue]; (int j=0; j<=i; j++){ if (i!=j) { cgrect rect2 = [[newarrayofcgrects objectatindex:j] cgrectvalue]; bool intersect = cgrectintersectsrect(rect1,rect2); if (intersect){ if (counter%4==0) { // left nslog(@"left"); // ever 1 on left, move farther left double neededdistanceadjustment = 5+max(rect1.size.width,rect2.size.width) - fabsf(rect2.origin.x - rect1.origin.x); if (rect1.origin.x < rect2.origin.x) { // move rect 1 left (subtract) rect1.origin.x -= neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:i]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect1] atindex:i]; }else{ // move rect 2 left (subtract) rect2.origin.x -= neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:j]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect2] atindex:j]; } }else if (counter%4==1) { // nslog(@"up"); double neededdistanceadjustment = 5+max(rect1.size.height,rect2.size.height) - fabsf(rect2.origin.y - rect1.origin.y); if (rect1.origin.y < rect2.origin.y) { // move rect 1 (subtract) rect1.origin.y -= neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:i]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect1] atindex:i]; }else{ // move rect 2 (subtract) rect2.origin.y -= neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:j]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect2] atindex:j]; } }else if (counter%4==2) { //right nslog(@"right"); double neededdistanceadjustment = 5+max(rect1.size.width,rect2.size.width) - fabsf(rect2.origin.x - rect1.origin.x); if (rect1.origin.x > rect2.origin.x) { // move rect 1 right (add) rect1.origin.y += neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:i]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect1] atindex:i]; }else{ // move rect 2 right (add) rect2.origin.y += neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:j]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect2] atindex:j]; } }else if (counter%4==3) { // downwards nslog(@"down"); double neededdistanceadjustment = 5+max(rect1.size.height,rect2.size.height) - fabsf(rect2.origin.y - rect1.origin.y); if (rect1.origin.y > rect2.origin.y) { // move rect 1 downwards (add) rect1.origin.y += neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:i]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect1] atindex:i]; }else{ // move rect 2 downwards (add) rect2.origin.y += neededdistanceadjustment; [newarrayofcgrects removeobjectatindex:j]; [newarrayofcgrects insertobject:[nsvalue valuewithcgrect:rect2] atindex:j]; } } // update newarrayofcgrects counter++; } } } } if (counter>100) { nslog(@"error!!"); homecoming arrayofcgrects; } doanyoverlapstill = [self dorectsoverlap:newarrayofcgrects]; if (!doanyoverlapstill) { homecoming newarrayofcgrects; } } homecoming arrayofcgrects; } ios algorithm geometry mapkit graph-algorithm
Comments
Post a Comment