Created
April 8, 2017 09:34
-
-
Save modestman/508c80435cbcec23089319784b07737c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// GTMapGridDataSource.m | |
// GallopTravel | |
// | |
// Created by Anton Glezman on 08.12.16. | |
// Copyright © 2016 Globus It. All rights reserved. | |
// | |
#import "GTMapGridDataSource.h" | |
#import "GTDataProviderProtocol.h" | |
#import "GTRepositoryManager.h" | |
#import "GTApiManager.h" | |
// количество точек в каждой ячейке | |
static int const requestCount = 6; | |
@interface GTMapGridDataSource () | |
{ | |
NSMutableDictionary<NSString*,NSNumber*> *latDeltaForZoomLevel; | |
GTRequestTask *apiRequestTask; | |
} | |
@end | |
@implementation GTMapGridDataSource | |
-(id)init | |
{ | |
self = [super init]; | |
if (self) | |
{ | |
self.requestCellSize = IS_IPAD ? 180.0 : 120.0; | |
} | |
return self; | |
} | |
-(GTRequestTask*)requestObjectsForRegion:(GTBoundingBox*)region withFilters:(GTMapFilters*)filters zoomLevel:(float)zoom | |
{ | |
GTBoundingBox *_bbox = region; | |
/* | |
* разбиваем регион на сетку с привязкой к географическим координатам (долготам и широтам) | |
* далее для каждой ячейки сетки запрашиваем n точек, чтобы равномерно распределить объекты по поверхности карты | |
*/ | |
// количество ячеек по горизонтали (здесь экранные координаты) | |
int horCount = (int)self.mapFrame.size.width / self.requestCellSize; | |
// количество ячеек по вертикали | |
int verCount = (int)self.mapFrame.size.height / self.requestCellSize; | |
// дельта longitude, ширина ячейки в географических координатах | |
double lonDelta = ABS(_bbox.bottomRight.longitude - _bbox.topLeft.longitude) / horCount; | |
/* | |
* дельта latitude (высота ячеки) будет зависеть от уровня зума. | |
* так как зум вещественный (от 0.0 до 20.0), чтобы не пересчитвыать сетку при каждом мельчайшем изменении, | |
* будем кэшировать величину дельты в зависимости от округленной величины зума (12.365 -> 12.3) | |
*/ | |
// достаем величину дельты из мапы (zoom -> latDelta) | |
NSNumber *latDeltaNumber = latDeltaForZoomLevel[[NSString stringWithFormat:@"%.1f", zoom]]; | |
double latDelta; | |
if (latDeltaNumber == nil) | |
{ | |
// рассчитываем дельту и кладем в мапу | |
latDelta = ABS(_bbox.bottomRight.latitude - _bbox.topLeft.latitude) / verCount; | |
latDeltaNumber = [NSNumber numberWithDouble:latDelta]; | |
[latDeltaForZoomLevel setObject:latDeltaNumber forKey:[NSString stringWithFormat:@"%.1f", zoom]]; | |
} | |
latDelta = [latDeltaNumber doubleValue]; | |
// пересчитываем количество ячеек по вертикали | |
verCount = ABS(_bbox.bottomRight.latitude - _bbox.topLeft.latitude) / latDelta; | |
int startLon = round(_bbox.topLeft.longitude / lonDelta); | |
int startLat = round(_bbox.topLeft.latitude / latDelta); | |
// заполняем коллекцию ячеек (в географических координатах) | |
NSMutableArray *boxes = [NSMutableArray new]; | |
for (int j = startLat; j>startLat-verCount; j--) { | |
for (int i = startLon; i<startLon+horCount; i++) { | |
CLLocationDegrees n = latDelta * j; | |
CLLocationDegrees w = lonDelta * i; | |
CLLocationDegrees s = latDelta * (j-1); | |
CLLocationDegrees e = lonDelta * (i+1); | |
GTBoundingBox *smallBox = [[GTBoundingBox alloc] initWithCoordinatesN:n W:w S:s E:e]; | |
[boxes addObject:smallBox]; | |
} | |
} | |
self.boxes = boxes; // эту коллекцию передаем в запрос | |
/*********/ | |
NSArray *objectTypes = @[[NSNumber numberWithInteger:GeoObjectTypeCity], [NSNumber numberWithInteger:GeoObjectTypePlace]]; | |
if (zoom > cityZoomLevel) // при зуме на уровне города, показываем только объекты-места, скрываем объекты-города | |
{ | |
objectTypes = @[[NSNumber numberWithInteger:GeoObjectTypePlace]]; | |
} | |
GTGeoSearchOptions *searchOptions = [GTGeoSearchOptions new]; | |
searchOptions.grid = boxes; | |
searchOptions.types = objectTypes; | |
searchOptions.tags = filters.geoObjectTags; | |
__weak typeof(self) weakSelf = self; | |
// request geo-objects from local db | |
[[GTRepositoryManager shared] getGeoObjectsGridWithOptions:searchOptions | |
count:requestCount success:^(NSArray<GTGeoObject *> *result) { | |
[[weakSelf delegate] mapDatasource:weakSelf resultObjects:result forRegion:region andFilters:filters zoomLevel:zoom]; | |
} failure:^(NSError *error) { | |
}]; | |
// request geo-objects from server | |
if (apiRequestTask) | |
{ | |
[apiRequestTask cancel]; | |
} | |
apiRequestTask = [[GTApiManager shared] getGeoObjectsGridWithOptions:searchOptions count:requestCount | |
success:^(NSArray<GTGeoObject *> *result) { | |
[[weakSelf delegate] mapDatasource:weakSelf resultObjects:result forRegion:region andFilters:filters zoomLevel:zoom]; | |
} failure:^(NSError *error) { | |
}]; | |
return apiRequestTask; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment