BMKClusterQuadtree.m 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // BMKClusterQuadtree.m
  3. // IphoneMapSdkDemo
  4. //
  5. // Created by wzy on 15/9/15.
  6. // Copyright © 2015年 Baidu. All rights reserved.
  7. //
  8. #import "BMKClusterQuadtree.h"
  9. #define MAX_POINTS_PER_NODE 40
  10. @implementation BMKQuadItem
  11. @synthesize pt = _pt;
  12. @synthesize clusterItem = _clusterItem;
  13. - (void)setClusterItem:(BMKClusterItem *)clusterItem {
  14. _clusterItem = clusterItem;
  15. _pt = [self convertCoordinateToPoint:clusterItem.coor];
  16. }
  17. - (CGPoint)convertCoordinateToPoint:(CLLocationCoordinate2D) coor {
  18. /*
  19. final double x = latLng.longitude / 360 + .5;
  20. final double siny = Math.sin(Math.toRadians(latLng.latitude));
  21. final double y = 0.5 * Math.log((1 + siny) / (1 - siny)) / -(2 * Math.PI) + .5;
  22. return new Point(x * mWorldWidth, y * mWorldWidth);
  23. */
  24. CGFloat x = coor.longitude / 360.f + 0.5;
  25. CGFloat siny = sin(coor.latitude * M_PI / 180.f);
  26. CGFloat y = 0.5 * log((1 + siny) / (1 - siny)) / -(2 * M_PI) + 0.5;
  27. return CGPointMake(x, y);
  28. }
  29. @end
  30. @interface BMKClusterQuadtree () {
  31. NSMutableArray *_childrens;
  32. }
  33. @end
  34. @implementation BMKClusterQuadtree
  35. @synthesize rect = _rect;
  36. - (id)init {
  37. self = [super init];
  38. if (self){
  39. _quadItems = [[NSMutableArray alloc] initWithCapacity:MAX_POINTS_PER_NODE];
  40. }
  41. return self;
  42. }
  43. - (id)initWithRect:(CGRect) rect {
  44. self = [super init];
  45. if (self) {
  46. _quadItems = [[NSMutableArray alloc] initWithCapacity:MAX_POINTS_PER_NODE];
  47. _rect = rect;
  48. }
  49. return self;
  50. }
  51. //四叉树拆分
  52. - (void)subdivide {
  53. _childrens = [[NSMutableArray alloc] initWithCapacity:4];
  54. CGFloat x = _rect.origin.x;
  55. CGFloat y = _rect.origin.y;
  56. CGFloat w = _rect.size.width / 2.f;
  57. CGFloat h = _rect.size.height / 2.f;
  58. [_childrens addObject:[[BMKClusterQuadtree alloc] initWithRect:CGRectMake(x, y, w, h)]];
  59. [_childrens addObject:[[BMKClusterQuadtree alloc] initWithRect:CGRectMake(x + w, y, w, h)]];
  60. [_childrens addObject:[[BMKClusterQuadtree alloc] initWithRect:CGRectMake(x, y + h, w, h)]];
  61. [_childrens addObject:[[BMKClusterQuadtree alloc] initWithRect:CGRectMake(x + w, y + h, w, h)]];
  62. }
  63. //数据插入
  64. - (void)addItem:(BMKQuadItem *)quadItem {
  65. if (quadItem == nil) {
  66. return ;
  67. }
  68. if ([self rect:_rect containsPt:quadItem.pt] == NO) {
  69. return;
  70. }
  71. if(_quadItems.count < MAX_POINTS_PER_NODE) {
  72. [_quadItems addObject:quadItem];
  73. return ;
  74. }
  75. if(_childrens == nil || _childrens.count == 0) {
  76. [self subdivide];
  77. }
  78. for (BMKClusterQuadtree *children in _childrens) {
  79. [children addItem:quadItem];
  80. }
  81. }
  82. - (void)clearItems {
  83. _childrens = nil;
  84. if (_quadItems) {
  85. [_quadItems removeAllObjects];
  86. }
  87. }
  88. ///获取rect范围内的BMKQuadItem
  89. - (NSArray*)searchInRect:(CGRect) searchRect {
  90. //searchrect和四叉树区域rect无交集
  91. if ([self isRect:searchRect intersectsWith:_rect] == NO) {
  92. return [NSArray array];
  93. }
  94. NSMutableArray *array = [NSMutableArray array];
  95. //searchrect包含四叉树区域
  96. if ([self rect:searchRect containsRect:_rect]) {
  97. [array addObjectsFromArray:_quadItems];
  98. } else {
  99. for (BMKQuadItem *item in _quadItems) {
  100. if ([self rect:searchRect containsPt:item.pt]) {
  101. [array addObject:item];
  102. }
  103. }
  104. }
  105. if(_childrens != nil && _childrens.count == 4) {
  106. for (BMKClusterQuadtree *children in _childrens) {
  107. [array addObjectsFromArray:[children searchInRect:searchRect]];
  108. }
  109. }
  110. return array;
  111. }
  112. //rect是否包含pt
  113. - (BOOL)rect:(CGRect) rect containsPt:(CGPoint) pt {
  114. return rect.origin.x <= pt.x && pt.x <= (rect.size.width + rect.origin.x) && rect.origin.y <= pt.y && pt.y <= (rect.size.height + rect.origin.y);
  115. }
  116. //rect是否相交
  117. - (BOOL)isRect:(CGRect) rect1 intersectsWith:(CGRect) rect2 {
  118. CGFloat maxx = MAX(rect1.origin.x, rect2.origin.x);
  119. CGFloat minx = MIN(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width);
  120. if (maxx - minx > 0) {
  121. return NO;
  122. }
  123. CGFloat maxy = MAX(rect1.origin.y, rect2.origin.y);
  124. CGFloat miny = MIN(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height);
  125. if (maxy - miny > 0) {
  126. return NO;
  127. }
  128. return YES;
  129. }
  130. //是否第一个矩形包含了第二个矩形
  131. - (BOOL)rect:(CGRect) r1 containsRect:(CGRect) r2 {
  132. return r1.origin.x <= r2.origin.x && r1.size.width >= r2.size.width && r1.origin.y <= r2.origin.y && r1.size.height >= r2.size.height;
  133. }
  134. @end