199 lines
6.0 KiB
Plaintext
199 lines
6.0 KiB
Plaintext
#import "MGLGeoJSONSource_Private.h"
|
|
|
|
#import "MGLMapView_Private.h"
|
|
#import "MGLSource_Private.h"
|
|
#import "MGLFeature_Private.h"
|
|
#import "MGLShape_Private.h"
|
|
|
|
#import "NSURL+MGLAdditions.h"
|
|
|
|
#include <mbgl/style/sources/geojson_source.hpp>
|
|
|
|
const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClustered = @"MGLGeoJSONSourceOptionClustered";
|
|
const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClusterRadius = @"MGLGeoJSONSourceOptionClusterRadius";
|
|
const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevelForClustering = @"MGLGeoJSONSourceOptionMaximumZoomLevelForClustering";
|
|
const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevel = @"MGLGeoJSONSourceOptionMaximumZoomLevel";
|
|
const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionBuffer = @"MGLGeoJSONSourceOptionBuffer";
|
|
const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance = @"MGLGeoJSONSourceOptionSimplificationTolerance";
|
|
|
|
@interface MGLGeoJSONSource ()
|
|
|
|
@property (nonatomic, readwrite) NSDictionary *options;
|
|
@property (nonatomic) mbgl::style::GeoJSONSource *rawSource;
|
|
|
|
@end
|
|
|
|
@implementation MGLGeoJSONSource
|
|
{
|
|
std::unique_ptr<mbgl::style::GeoJSONSource> _pendingSource;
|
|
}
|
|
|
|
- (instancetype)initWithIdentifier:(NSString *)identifier geoJSONData:(NSData *)data options:(NS_DICTIONARY_OF(NSString *, id) *)options
|
|
{
|
|
if (self = [super initWithIdentifier:identifier])
|
|
{
|
|
_geoJSONData = data;
|
|
_options = options;
|
|
[self commonInit];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(NS_DICTIONARY_OF(NSString *, id) *)options
|
|
{
|
|
if (self = [super initWithIdentifier:identifier])
|
|
{
|
|
_URL = url;
|
|
_options = options;
|
|
[self commonInit];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithIdentifier:(NSString *)identifier shape:(nullable MGLShape *)shape options:(NSDictionary<MGLGeoJSONSourceOption,id> *)options
|
|
{
|
|
if (self = [super initWithIdentifier:identifier]) {
|
|
_shape = shape;
|
|
_options = options;
|
|
[self commonInit];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)addToMapView:(MGLMapView *)mapView
|
|
{
|
|
if (_pendingSource == nullptr) {
|
|
[NSException raise:@"MGLRedundantSourceException"
|
|
format:@"This instance %@ was already added to %@. Adding the same source instance " \
|
|
"to the style more than once is invalid.", self, mapView.style];
|
|
}
|
|
|
|
mapView.mbglMap->addSource(std::move(_pendingSource));
|
|
}
|
|
|
|
- (void)removeFromMapView:(MGLMapView *)mapView
|
|
{
|
|
auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String);
|
|
|
|
_pendingSource = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::GeoJSONSource> &>(removedSource));
|
|
self.rawSource = _pendingSource.get();
|
|
}
|
|
|
|
- (void)commonInit
|
|
{
|
|
auto source = std::make_unique<mbgl::style::GeoJSONSource>(self.identifier.UTF8String, self.geoJSONOptions);
|
|
|
|
if (self.URL) {
|
|
NSURL *url = self.URL.mgl_URLByStandardizingScheme;
|
|
source->setURL(url.absoluteString.UTF8String);
|
|
_shape = nil;
|
|
} else if (self.geoJSONData) {
|
|
NSString *string = [[NSString alloc] initWithData:self.geoJSONData encoding:NSUTF8StringEncoding];
|
|
const auto geojson = mapbox::geojson::parse(string.UTF8String);
|
|
source->setGeoJSON(geojson);
|
|
_shape = MGLShapeFromGeoJSON(geojson);
|
|
} else {
|
|
const auto geojson = mbgl::GeoJSON{self.shape.geometryObject};
|
|
source->setGeoJSON(geojson);
|
|
}
|
|
|
|
_pendingSource = std::move(source);
|
|
self.rawSource = _pendingSource.get();
|
|
}
|
|
|
|
- (mbgl::style::GeoJSONOptions)geoJSONOptions
|
|
{
|
|
auto mbglOptions = mbgl::style::GeoJSONOptions();
|
|
|
|
if (id value = self.options[MGLGeoJSONSourceOptionMaximumZoomLevel]) {
|
|
[self validateValue:value];
|
|
mbglOptions.maxzoom = [value integerValue];
|
|
}
|
|
|
|
if (id value = self.options[MGLGeoJSONSourceOptionBuffer]) {
|
|
[self validateValue:value];
|
|
mbglOptions.buffer = [value integerValue];
|
|
}
|
|
|
|
if (id value = self.options[MGLGeoJSONSourceOptionSimplificationTolerance]) {
|
|
[self validateValue:value];
|
|
mbglOptions.tolerance = [value doubleValue];
|
|
}
|
|
|
|
if (id value = self.options[MGLGeoJSONSourceOptionClusterRadius]) {
|
|
[self validateValue:value];
|
|
mbglOptions.clusterRadius = [value integerValue];
|
|
}
|
|
|
|
if (id value = self.options[MGLGeoJSONSourceOptionMaximumZoomLevelForClustering]) {
|
|
[self validateValue:value];
|
|
mbglOptions.clusterMaxZoom = [value integerValue];
|
|
}
|
|
|
|
if (id value = self.options[MGLGeoJSONSourceOptionClustered]) {
|
|
[self validateValue:value];
|
|
mbglOptions.cluster = [value boolValue];
|
|
}
|
|
|
|
return mbglOptions;
|
|
}
|
|
|
|
- (void)validateValue:(id)value
|
|
{
|
|
if (! [value isKindOfClass:[NSNumber class]])
|
|
{
|
|
[NSException raise:@"Value not handled" format:@"%@ is not an NSNumber", value];
|
|
}
|
|
}
|
|
|
|
- (void)setGeoJSONData:(NSData *)geoJSONData
|
|
{
|
|
_geoJSONData = geoJSONData;
|
|
|
|
if (self.rawSource == NULL)
|
|
{
|
|
[self commonInit];
|
|
}
|
|
|
|
NSString *string = [[NSString alloc] initWithData:_geoJSONData encoding:NSUTF8StringEncoding];
|
|
const auto geojson = mapbox::geojson::parse(string.UTF8String);
|
|
self.rawSource->setGeoJSON(geojson);
|
|
|
|
_shape = MGLShapeFromGeoJSON(geojson);
|
|
}
|
|
|
|
- (void)setURL:(NSURL *)URL
|
|
{
|
|
_URL = URL;
|
|
|
|
if (self.rawSource == NULL)
|
|
{
|
|
[self commonInit];
|
|
}
|
|
|
|
NSURL *url = self.URL.mgl_URLByStandardizingScheme;
|
|
self.rawSource->setURL(url.absoluteString.UTF8String);
|
|
}
|
|
|
|
|
|
- (void)setShape:(MGLShape *)shape
|
|
{
|
|
if (self.rawSource == NULL)
|
|
{
|
|
[self commonInit];
|
|
}
|
|
|
|
const auto geojson = mbgl::GeoJSON{shape.geometryObject};
|
|
self.rawSource->setGeoJSON(geojson);
|
|
|
|
_shape = shape;
|
|
}
|
|
|
|
- (NSString *)description
|
|
{
|
|
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; geoJSONData = %@; shape = %@>",
|
|
NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.geoJSONData, self.shape];
|
|
}
|
|
|
|
@end
|