Skip to content

Instantly share code, notes, and snippets.

@modestman
Created April 8, 2017 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save modestman/508c80435cbcec23089319784b07737c to your computer and use it in GitHub Desktop.
Save modestman/508c80435cbcec23089319784b07737c to your computer and use it in GitHub Desktop.
//
// 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