#import "MGLShapeSource_Private.h" #import "MGLAbstractShapeSource_Private.h" #import "MGLStyle_Private.h" #import "MGLMapView_Private.h" #import "MGLSource_Private.h" #import "MGLFeature_Private.h" #import "MGLShape_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSURL+MGLAdditions.h" #include #include #include @interface MGLShapeSource () @property (nonatomic, readwrite) NSDictionary *options; @property (nonatomic, readonly) mbgl::style::GeoJSONSource *rawSource; @end @implementation MGLShapeSource - (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(NS_DICTIONARY_OF(NSString *, id) *)options { auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options); auto source = std::make_unique(identifier.UTF8String, geoJSONOptions); if (self = [super initWithPendingSource:std::move(source)]) { self.URL = url; } return self; } - (instancetype)initWithIdentifier:(NSString *)identifier shape:(nullable MGLShape *)shape options:(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options { auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options); auto source = std::make_unique(identifier.UTF8String, geoJSONOptions); if (self = [super initWithPendingSource:std::move(source)]) { self.shape = shape; } return self; } - (instancetype)initWithIdentifier:(NSString *)identifier features:(NS_ARRAY_OF(MGLShape *) *)features options:(nullable NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options { for (id feature in features) { if (![feature conformsToProtocol:@protocol(MGLFeature)]) { [NSException raise:NSInvalidArgumentException format:@"The object %@ included in the features argument does not conform to the MGLFeature protocol.", feature]; } } MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:features]; return [self initWithIdentifier:identifier shape:shapeCollectionFeature options:options]; } - (instancetype)initWithIdentifier:(NSString *)identifier shapes:(NS_ARRAY_OF(MGLShape *) *)shapes options:(nullable NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options { MGLShapeCollection *shapeCollection = [MGLShapeCollection shapeCollectionWithShapes:shapes]; return [self initWithIdentifier:identifier shape:shapeCollection options:options]; } - (mbgl::style::GeoJSONSource *)rawSource { return (mbgl::style::GeoJSONSource *)super.rawSource; } - (NSURL *)URL { auto url = self.rawSource->getURL(); return url ? [NSURL URLWithString:@(url->c_str())] : nil; } - (void)setURL:(NSURL *)url { if (url) { self.rawSource->setURL(url.mgl_URLByStandardizingScheme.absoluteString.UTF8String); _shape = nil; } else { self.shape = nil; } } - (void)setShape:(MGLShape *)shape { self.rawSource->setGeoJSON({ shape.geoJSONObject }); _shape = shape; } - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; shape = %@>", NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.shape]; } - (NS_ARRAY_OF(id ) *)featuresMatchingPredicate:(nullable NSPredicate *)predicate { mbgl::optional optionalFilter; if (predicate) { optionalFilter = predicate.mgl_filter; } std::vector features; if (self.mapView) { features = self.mapView.renderer->querySourceFeatures(self.rawSource->getID(), { {}, optionalFilter }); } return MGLFeaturesFromMBGLFeatures(features); } @end