2014-11-09 34 views
0

好像很多人已经涉及这个重叠MKAnnotation视图的问题,并且在缩放结束时以及在viewdidload处优雅地展开它们。所以我认为我只是硬着头皮开发出一个解决方案,但在此之前,我想询问算法的实施。关于这个话题,有没有提出可行的解决方案曾任:传播MapView注释的功能,使得没有任何重叠

ios sdk MKMapView overlapping pins? Laying out overlapping rectangles

还有更多...

所以我想到的功能是这样的:(注意:所有的CGRects是同样大小)

-(NSArray *)spreadOutTheseViews:(NSArray *)arrayofCGRects{ 



    //////////////////////////////////// 
    //find out who overlaps with who.. 
    //////////////////////////////////// 

    NSMutableArray *arrayOfArraysOfRects = [[NSMutableArray alloc] init]; 

    // 1. make an array to let you know which Rects have already been added to one of the sets 
    int n = (int)[arrayofCGRects count]; 
    NSMutableArray *addedAlready = [[NSMutableArray alloc] init]; 
    for (id obj in arrayofCGRects) { 
     [addedAlready addObject:@0]; 
    } 

    // 2. go through and add them if they overlap 
    for (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]; 

      for (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 they are overlapping, if so, add it to 
         [[arrayOfArraysOfRects lastObject] addObject:@(j)]; 
         [addedAlready insertObject:@(1) atIndex:j]; 
        } 
       } 
      } 
     } 
    } 
    NSMutableArray *arrayofCGPoints = [[NSMutableArray alloc] init]; 
    //3. now that we have "clusters" of overlapping rects.. push them away from each other.. 
    for(NSArray *indexArray in arrayOfArraysOfRects){ 

     if ([indexArray count]==1){ 
      // just simply add the CGPoint 
      CGRect rect = [[arrayofCGRects objectAtIndex:(NSInteger)[indexArray firstObject]] CGRectValue]; 
      [arrayofCGPoints addObject:[NSValue valueWithCGPoint:rect.origin] ]; 

     }else{ 

      // heart of the algo.. 
      // Idea 1: get the average of the CGPoints to find the center of all of them, then find a ring with a specific radius that we can put them all on. Note this is a packing problem that I really dont have a better solution for.. 


     } 



    } 

    return arrayofCGPoints; 

} 

这里任何帮助将不胜感激..

回答

0

好它不是最漂亮的解决方案..但我现在有一些工作,以防有人发现这个有用..也请仍然张贴,如果你有一个更优雅的解决方案!

-(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]); 

    for (int i=0; i<[arrayofCGRects count]; i++) { 
     CGRect rect1 = [[newArrayOfCGRects objectAtIndex:i] CGRectValue]; 
     for (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"); 
         // which ever one is on the left, move it further to the 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) { 
         // UP 
         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 up (subtract) 
          rect1.origin.y -= neededDistanceAdjustment; 
          [newArrayOfCGRects removeObjectAtIndex:i]; 
          [newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect1] atIndex:i]; 

         }else{ 
          // move rect 2 up (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) { 
         // DOWN 

         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 down (add) 
          rect1.origin.y += neededDistanceAdjustment; 
          [newArrayOfCGRects removeObjectAtIndex:i]; 
          [newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect1] atIndex:i]; 

         }else{ 
          // move rect 2 down (add) 
          rect2.origin.y += neededDistanceAdjustment; 
          [newArrayOfCGRects removeObjectAtIndex:j]; 
          [newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect2] atIndex:j]; 
         } 
        } 
        // update newArrayOfCGRects 
        counter++; 

       } 
      } 
     } 
    } 
    if (counter>100) { 
     NSLog(@"error!!"); 
     return arrayofCGRects; 


    } 

    doAnyOverlapStill = [self doRectsOverlap:newArrayOfCGRects]; 
    if (!doAnyOverlapStill) { 
     return newArrayOfCGRects; 
    } 
} 

return arrayofCGRects; 

} 
+0

澄清问题:您是在谈论点聚类还是关于注释视图由于美学原因彼此不重叠? – incanus 2014-11-10 18:42:30

+0

是的,后者,在这里更好地演示:http://stackoverflow.com/questions/17710770/ios-sdk-mkmapview-overlapping-pins – fchaubard 2014-11-10 23:58:46