summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-05-23 08:47:10 -0700
committerMinh Nguyễn <mxn@1ec5.org>2016-05-27 21:42:31 -0700
commitc6683ee1d3baebf46f3397e7ed2e44e8a23dc8ed (patch)
tree3962b9433647f91436b0cb70344e272132935f80
parentc9520713ca5cc5352dada77de87aede97e7947f2 (diff)
downloadqtlocation-mapboxgl-c6683ee1d3baebf46f3397e7ed2e44e8a23dc8ed.tar.gz
[ios, osx] Feature querying; complex geometry classes
Added methods to MGLMapView that return the rendered features at a visible point or within a visible rectangle on the map, optionally restricted to a set of layers, plus voluminous documentation. Added several new geometry classes corresponding to distinct geometry types supported by geometry.hpp. Added parallel “feature” classes to represent these geometries along with tags (IDs) and attributes (properties) from the source. Grouped classes in the Foundation and SDK groups by theme. In iosapp, dropped pins’ callout views now display the name of the topmost named feature at that point. In osxapp, a long press on the map highlights the features under the cursor. Dropping a pin via the menu or context menu item shows the usual dropped pin, but the pin’s title is now the name of a feature under the cursor, if available, rather than “Dropped Pin”. Fixes the iOS/OS X side of #352.
-rw-r--r--platform/darwin/src/MGLFeature.h164
-rw-r--r--platform/darwin/src/MGLFeature.mm244
-rw-r--r--platform/darwin/src/MGLFeature_Private.h7
-rw-r--r--platform/darwin/src/MGLPolygon.h24
-rw-r--r--platform/darwin/src/MGLPolygon.mm37
-rw-r--r--platform/darwin/src/MGLPolyline.h24
-rw-r--r--platform/darwin/src/MGLPolyline.mm37
-rw-r--r--platform/darwin/src/MGLShapeCollection.h32
-rw-r--r--platform/darwin/src/MGLShapeCollection.m21
-rw-r--r--platform/ios/CHANGELOG.md1
-rw-r--r--platform/ios/app/MBXViewController.m19
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj198
-rw-r--r--platform/ios/jazzy.yml13
-rw-r--r--platform/ios/src/MGLMapView.h127
-rw-r--r--platform/ios/src/MGLMapView.mm68
-rw-r--r--platform/ios/src/Mapbox.h4
-rw-r--r--platform/osx/CHANGELOG.md1
-rw-r--r--platform/osx/app/MapDocument.m17
-rw-r--r--platform/osx/jazzy.yml13
-rw-r--r--platform/osx/osx.xcodeproj/project.pbxproj135
-rw-r--r--platform/osx/src/MGLMapView.h127
-rw-r--r--platform/osx/src/MGLMapView.mm60
-rw-r--r--platform/osx/src/Mapbox.h2
23 files changed, 1265 insertions, 110 deletions
diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
new file mode 100644
index 0000000000..389b8ab67f
--- /dev/null
+++ b/platform/darwin/src/MGLFeature.h
@@ -0,0 +1,164 @@
+#import <Foundation/Foundation.h>
+
+#import "MGLPolyline.h"
+#import "MGLPolygon.h"
+#import "MGLPointAnnotation.h"
+#import "MGLShapeCollection.h"
+
+#import "MGLTypes.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ The `MGLFeature` protocol is used to provide details about geographic features
+ contained in a map view’s
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>.
+ Each concrete subclass of `MGLShape` in turn has a subclass that conforms to
+ this protocol.
+
+ Typically, you do not create feature objects yourself but rather obtain them
+ using `-[MGLMapView visibleFeaturesAtPoint:]` and related methods. Each feature
+ object associates a shape with an identifier and attributes as specified by the
+ source. Like any `MGLAnnotation` object, an `MGLFeature` object can be added to
+ a map view using `-[MGLMapView addAnnotations:]` and related methods.
+ */
+@protocol MGLFeature <MGLAnnotation>
+
+/**
+ An object that uniquely identifies the feature in its containing
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+
+ The value of this property is currently always an `NSNumber` object but may in
+ the future be an instance of another class, such as `NSString`.
+
+ The identifier corresponds to the
+ <a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#42-features">feature identifier</a>
+ (`id`) in the tile source. If the source does not specify the feature’s
+ identifier, the value of this property is `nil`.
+
+ For details about the identifiers used in most Mapbox-provided styles, consult
+ the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets</a>
+ layer reference.
+ */
+@property (nonatomic, copy, nullable, readonly) id identifier;
+
+/**
+ A dictionary of attributes for this feature specified by the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+
+ The keys and values of this dictionary are determined by the tile source. In
+ the tile source, each attribute name is a string, while each attribute value
+ may be a null value, Boolean value, integer, floating-point number, or string.
+ These data types are mapped to instances of the following Foundation classes:
+
+ <table>
+ <thead>
+ <tr><th>In the tile source</th><th>In this dictionary</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>Null</td> <td><code>NSNull</code></td></tr>
+ <tr><td>Boolean</td> <td><code>NSNumber</code> (use the <code>boolValue</code> property)</td></tr>
+ <tr><td>Integer</td> <td><code>NSNumber</code> (use the <code>unsignedLongLongValue</code> or <code>longLongValue</code> property)</td></tr>
+ <tr><td>Floating-point number</td> <td><code>NSNumber</code> (use the <code>doubleValue</code> property)</td></tr>
+ <tr><td>String</td> <td><code>NSString</code></td></tr>
+ </tbody>
+ </table>
+
+ For details about the attribute names and values found in Mapbox-provided
+ vector tile sources, consult the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets</a>
+ and
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-terrain/">Mapbox Terrain</a>
+ layer references.
+ */
+@property (nonatomic, copy, readonly) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+/**
+ Returns the feature attribute for the given attribute name.
+
+ See the `attributes` property’s documentation for details on keys and values
+ associated with this method.
+ */
+- (nullable id)attributeForKey:(NSString *)key;
+
+@end
+
+/**
+ The `MGLPointFeature` class represents a point in a
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+ */
+@interface MGLPointFeature : MGLPointAnnotation <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+/**
+ The `MGLPolylineFeature` class represents a polyline in a
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+ */
+@interface MGLPolylineFeature : MGLPolyline <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+/**
+ The `MGLPolygonFeature` class represents a polygon in a
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+ */
+@interface MGLPolygonFeature : MGLPolygon <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+/**
+ The `MGLMultiPointFeature` class represents a multipoint in a
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+ */
+@interface MGLMultiPointFeature : MGLMultiPoint <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+/**
+ The `MGLMultiPolylineFeature` class represents a multipolyline in a
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+ */
+@interface MGLMultiPolylineFeature : MGLMultiPolyline <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+/**
+ The `MGLMultiPolygonFeature` class represents a multipolygon in a
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+ */
+@interface MGLMultiPolygonFeature : MGLMultiPolygon <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+/**
+ The `MGLShapeCollectionFeature` class represents a shape collection in a
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile source</a>.
+ */
+@interface MGLShapeCollectionFeature : MGLShapeCollection <MGLFeature>
+
+@property (nonatomic, copy, nullable, readwrite) id identifier;
+@property (nonatomic, copy, readwrite) NS_DICTIONARY_OF(NSString *, id) *attributes;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
new file mode 100644
index 0000000000..68c57a193a
--- /dev/null
+++ b/platform/darwin/src/MGLFeature.mm
@@ -0,0 +1,244 @@
+#import "MGLFeature_Private.h"
+
+#import "MGLPointAnnotation.h"
+#import "MGLPolyline.h"
+#import "MGLPolygon.h"
+
+#import "MGLMultiPoint_Private.h"
+
+class PropertyValueEvaluator {
+public:
+ PropertyValueEvaluator() {}
+
+ id operator()(const std::nullptr_t &) const {
+ return [NSNull null];
+ }
+
+ id operator()(const bool &value) const {
+ return value ? @YES : @NO;
+ }
+
+ id operator()(const uint64_t &value) const {
+ return @(value);
+ }
+
+ id operator()(const int64_t &value) const {
+ return @(value);
+ }
+
+ id operator()(const double &value) const {
+ return @(value);
+ }
+
+ id operator()(const std::string &value) const {
+ return @(value.c_str());
+ }
+
+ id operator()(const std::vector<mbgl::Value> &values) const {
+ std::vector<id> objects;
+ objects.reserve(values.size());
+ std::transform(values.begin(), values.end(), std::back_inserter(objects), ^id (const mbgl::Value &value) {
+ PropertyValueEvaluator evaluator;
+ return mbgl::Value::visit(value, evaluator);
+ });
+ return [NSArray arrayWithObjects:&objects[0] count:objects.size()];
+ }
+
+ id operator()(const std::unordered_map<std::string, mbgl::Value> &items) const {
+ std::vector<NSString *> keys;
+ keys.reserve(items.size());
+ std::vector<id> objects;
+ objects.reserve(items.size());
+ for (auto &item : items) {
+ keys.push_back(@(item.first.c_str()));
+ PropertyValueEvaluator evaluator;
+ objects.push_back(mbgl::Value::visit(item.second, evaluator));
+ }
+ return [NSDictionary dictionaryWithObjects:&objects[0] forKeys:&keys[0] count:keys.size()];
+ }
+};
+
+template <typename T>
+class GeometryEvaluator {
+public:
+ GeometryEvaluator()
+ : attributes([NSMutableDictionary dictionary]) {}
+
+ GeometryEvaluator(const mbgl::Feature &feature)
+ : tag(feature.id ? @(*feature.id) : nullptr),
+ attributes([NSMutableDictionary dictionaryWithCapacity:feature.properties.size()]) {
+ for (auto &pair : feature.properties) {
+ auto &value = pair.second;
+ PropertyValueEvaluator evaluator;
+ attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator);
+ }
+ }
+
+ MGLShape <MGLFeature> * operator()(const mapbox::geometry::point<T> &geometry) const {
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ feature.coordinate = coordinateFromPoint(geometry);
+ feature.identifier = tag;
+ feature.attributes = attributes;
+ return feature;
+ }
+
+ MGLShape <MGLFeature> * operator()(const mapbox::geometry::line_string<T> &geometry) const {
+ std::vector<CLLocationCoordinate2D> coordinates;
+ coordinates.reserve(geometry.size());
+ std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPoint);
+
+ MGLPolylineFeature *feature = [[MGLPolylineFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
+ feature.identifier = tag;
+ feature.attributes = attributes;
+ return feature;
+ }
+
+ MGLShape <MGLFeature> * operator()(const mapbox::geometry::polygon<T> &geometry) const {
+ // TODO: MGLPolygon doesn’t support holes, so what to do?
+ auto &linearRing = geometry.front();
+
+ std::vector<CLLocationCoordinate2D> coordinates;
+ coordinates.reserve(linearRing.size());
+ std::transform(linearRing.begin(), linearRing.end(), std::back_inserter(coordinates), coordinateFromPoint);
+
+ MGLPolygonFeature *feature = [[MGLPolygonFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
+ feature.identifier = tag;
+ feature.attributes = attributes;
+ return feature;
+ }
+
+ MGLShape <MGLFeature> * operator()(const mapbox::geometry::multi_point<T> &geometry) const {
+ std::vector<CLLocationCoordinate2D> coordinates;
+ coordinates.reserve(geometry.size());
+ std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPoint);
+
+ MGLMultiPointFeature *feature = [[MGLMultiPointFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
+ feature.identifier = tag;
+ feature.attributes = attributes;
+ return feature;
+ }
+
+ MGLShape <MGLFeature> * operator()(const mapbox::geometry::multi_line_string<T> &geometry) const {
+ NSMutableArray *polylines = [NSMutableArray arrayWithCapacity:geometry.size()];
+ for (auto &lineString : geometry) {
+ std::vector<CLLocationCoordinate2D> coordinates;
+ coordinates.reserve(lineString.size());
+ std::transform(lineString.begin(), lineString.end(), std::back_inserter(coordinates), coordinateFromPoint);
+
+ MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:&coordinates[0] count:coordinates.size()];
+ [polylines addObject:polyline];
+ }
+
+ MGLMultiPolylineFeature *feature = [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
+ feature.identifier = tag;
+ feature.attributes = attributes;
+ return feature;
+ }
+
+ MGLShape <MGLFeature> * operator()(const mapbox::geometry::multi_polygon<T> &geometry) const {
+ NSMutableArray *polygons = [NSMutableArray arrayWithCapacity:geometry.size()];
+ for (auto &polygon : geometry) {
+ // TODO: MGLPolygon doesn’t support holes, so what to do?
+ auto &linearRing = polygon.front();
+
+ std::vector<CLLocationCoordinate2D> coordinates;
+ coordinates.reserve(linearRing.size());
+ std::transform(linearRing.begin(), linearRing.end(), std::back_inserter(coordinates), coordinateFromPoint);
+
+ MGLPolygon *polygonObject = [MGLPolygon polygonWithCoordinates:&coordinates[0] count:coordinates.size()];
+ [polygons addObject:polygonObject];
+ }
+
+ MGLMultiPolygonFeature *feature = [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
+ feature.identifier = tag;
+ feature.attributes = attributes;
+ return feature;
+ }
+
+ MGLShape <MGLFeature> * operator()(const mapbox::geometry::geometry_collection<T> &collection) const {
+ NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()];
+ for (auto &geometry : collection) {
+ GeometryEvaluator<T> evaluator;
+ id <MGLFeature> feature = mapbox::geometry::geometry<T>::visit(geometry, evaluator);
+ [shapes addObject:feature];
+ }
+ MGLShapeCollectionFeature *feature = [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes];
+ feature.identifier = tag;
+ feature.attributes = attributes;
+ return feature;
+ }
+
+private:
+ NSNumber *tag = nullptr;
+ NS_MUTABLE_DICTIONARY_OF(NSString *, id) *attributes;
+
+ static CLLocationCoordinate2D coordinateFromPoint(const mapbox::geometry::point<T> &point) {
+ return CLLocationCoordinate2DMake(point.y, point.x);
+ }
+};
+
+NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features) {
+ std::vector<MGLShape <MGLFeature> *> shapes;
+ shapes.reserve(features.size());
+ std::transform(features.begin(), features.end(), std::back_inserter(shapes), ^MGLShape <MGLFeature> * (const mbgl::Feature &feature) {
+ GeometryEvaluator<double> evaluator(feature);
+ return mapbox::geometry::geometry<double>::visit(feature.geometry, evaluator);
+ });
+ return [NSArray arrayWithObjects:&shapes[0] count:shapes.size()];
+}
+
+@implementation MGLPointFeature
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@implementation MGLPolylineFeature
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@implementation MGLPolygonFeature
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@implementation MGLMultiPointFeature
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@implementation MGLMultiPolylineFeature
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@implementation MGLMultiPolygonFeature
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
+
+@implementation MGLShapeCollectionFeature
+
+- (id)attributeForKey:(NSString *)key {
+ return self.attributes[key];
+}
+
+@end
diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h
new file mode 100644
index 0000000000..837461871e
--- /dev/null
+++ b/platform/darwin/src/MGLFeature_Private.h
@@ -0,0 +1,7 @@
+#import "MGLFeature.h"
+#import "MGLShape.h"
+
+#import <mbgl/util/geo.hpp>
+#import <mbgl/util/feature.hpp>
+
+NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features);
diff --git a/platform/darwin/src/MGLPolygon.h b/platform/darwin/src/MGLPolygon.h
index 1a158874bb..a12e62b106 100644
--- a/platform/darwin/src/MGLPolygon.h
+++ b/platform/darwin/src/MGLPolygon.h
@@ -30,4 +30,28 @@ NS_ASSUME_NONNULL_BEGIN
@end
+/**
+ The `MGLMultiPolygon` class represents a shape consisting of one or more
+ polygons that do not overlap. For example, you would use an `MGLMultiPolygon`
+ object to represent an atoll together with an island in the atoll’s lagoon:
+ the atoll itself would be one `MGLPolygon` object, while the inner island would
+ be another.
+ */
+@interface MGLMultiPolygon : MGLShape <MGLOverlay>
+
+/**
+ An array of polygons forming the multipolygon.
+ */
+@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLPolygon *) *polygons;
+
+/**
+ Creates and returns a multipolygon object consisting of the given polygons.
+
+ @param polygons The array of polygons defining the shape.
+ @return A new multipolygon object.
+ */
++ (instancetype)multiPolygonWithPolygons:(NS_ARRAY_OF(MGLPolygon *) *)polygons;
+
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm
index 5019385cb2..6febf6d81b 100644
--- a/platform/darwin/src/MGLPolygon.mm
+++ b/platform/darwin/src/MGLPolygon.mm
@@ -1,6 +1,7 @@
#import "MGLPolygon.h"
#import "MGLMultiPoint_Private.h"
+#import "MGLGeometry_Private.h"
@implementation MGLPolygon
@@ -26,3 +27,39 @@
}
@end
+
+@interface MGLMultiPolygon ()
+
+@property (nonatomic, copy, readwrite) NS_ARRAY_OF(MGLPolygon *) *polygons;
+
+@end
+
+@implementation MGLMultiPolygon {
+ MGLCoordinateBounds _overlayBounds;
+}
+
+@synthesize overlayBounds = _overlayBounds;
+
++ (instancetype)multiPolygonWithPolygons:(NS_ARRAY_OF(MGLPolygon *) *)polygons {
+ return [[self alloc] initWithPolygons:polygons];
+}
+
+- (instancetype)initWithPolygons:(NS_ARRAY_OF(MGLPolygon *) *)polygons {
+ if (self = [super init]) {
+ _polygons = polygons;
+
+ mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
+
+ for (MGLPolygon *polygon in _polygons) {
+ bounds.extend(MGLLatLngBoundsFromCoordinateBounds(polygon.overlayBounds));
+ }
+ _overlayBounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
+ }
+ return self;
+}
+
+- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
+ return MGLLatLngBoundsFromCoordinateBounds(_overlayBounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
+}
+
+@end
diff --git a/platform/darwin/src/MGLPolyline.h b/platform/darwin/src/MGLPolyline.h
index 5e45513735..a453a43a41 100644
--- a/platform/darwin/src/MGLPolyline.h
+++ b/platform/darwin/src/MGLPolyline.h
@@ -30,4 +30,28 @@ NS_ASSUME_NONNULL_BEGIN
@end
+/**
+ The `MGLMultiPolyline` class represents a shape consisting of one or more
+ polylines. For example, you could use an `MGLMultiPolyline` object to represent
+ both sides of a divided highway (dual carriageway), excluding the median
+ (central reservation): each carriageway would be a distinct `MGLPolyline`
+ object.
+ */
+@interface MGLMultiPolyline : MGLShape <MGLOverlay>
+
+/**
+ An array of polygons forming the multipolyline.
+ */
+@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLPolyline *) *polylines;
+
+/**
+ Creates and returns a multipolyline object consisting of the given polylines.
+
+ @param polylines The array of polylines defining the shape.
+ @return A new multipolyline object.
+ */
++ (instancetype)multiPolylineWithPolylines:(NS_ARRAY_OF(MGLPolyline *) *)polylines;
+
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index f560a571bc..810b359bb0 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -1,6 +1,7 @@
#import "MGLPolyline.h"
#import "MGLMultiPoint_Private.h"
+#import "MGLGeometry_Private.h"
@implementation MGLPolyline
@@ -26,3 +27,39 @@
}
@end
+
+@interface MGLMultiPolyline ()
+
+@property (nonatomic, copy, readwrite) NS_ARRAY_OF(MGLPolyline *) *polylines;
+
+@end
+
+@implementation MGLMultiPolyline {
+ MGLCoordinateBounds _overlayBounds;
+}
+
+@synthesize overlayBounds = _overlayBounds;
+
++ (instancetype)multiPolylineWithPolylines:(NS_ARRAY_OF(MGLPolyline *) *)polylines {
+ return [[self alloc] initWithPolylines:polylines];
+}
+
+- (instancetype)initWithPolylines:(NS_ARRAY_OF(MGLPolyline *) *)polylines {
+ if (self = [super init]) {
+ _polylines = polylines;
+
+ mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
+
+ for (MGLPolyline *polyline in _polylines) {
+ bounds.extend(MGLLatLngBoundsFromCoordinateBounds(polyline.overlayBounds));
+ }
+ _overlayBounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
+ }
+ return self;
+}
+
+- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
+ return MGLLatLngBoundsFromCoordinateBounds(_overlayBounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
+}
+
+@end
diff --git a/platform/darwin/src/MGLShapeCollection.h b/platform/darwin/src/MGLShapeCollection.h
new file mode 100644
index 0000000000..f4dc226228
--- /dev/null
+++ b/platform/darwin/src/MGLShapeCollection.h
@@ -0,0 +1,32 @@
+#import <Foundation/Foundation.h>
+
+#import "MGLShape.h"
+
+#import "MGLTypes.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ The `MGLShapeCollection` class represents a shape consisting of one or more
+ distinct but related shapes that are instances of `MGLShape`. The constituent
+ shapes can be a mixture of different kinds of shapes.
+ */
+@interface MGLShapeCollection : MGLShape
+
+/**
+ An array of shapes forming the shape collection.
+ */
+@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLShape <MGLAnnotation> *) *shapes;
+
+/**
+ Creates and returns a shape collection consisting of the given shapes.
+
+ @param shapes The array of shapes defining the shape collection. The data in
+ this array is copied to the new object.
+ @return A new shape collection object.
+ */
++ (instancetype)shapeCollectionWithShapes:(NS_ARRAY_OF(MGLShape <MGLAnnotation> *) *)shapes;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLShapeCollection.m b/platform/darwin/src/MGLShapeCollection.m
new file mode 100644
index 0000000000..3fc4cdda75
--- /dev/null
+++ b/platform/darwin/src/MGLShapeCollection.m
@@ -0,0 +1,21 @@
+#import "MGLShapeCollection.h"
+
+@implementation MGLShapeCollection
+
++ (instancetype)shapeCollectionWithShapes:(NS_ARRAY_OF(MGLShape <MGLAnnotation> *) *)shapes {
+ return [[self alloc] initWithShapes:shapes];
+}
+
+- (instancetype)initWithShapes:(NS_ARRAY_OF(MGLShape <MGLAnnotation> *) *)shapes {
+ if (self = [super init]) {
+ NSAssert(shapes.count, @"Cannot create an empty shape collection");
+ _shapes = shapes.copy;
+ }
+ return self;
+}
+
+- (CLLocationCoordinate2D)coordinate {
+ return _shapes.firstObject.coordinate;
+}
+
+@end
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index 012688ab17..0754aa2a0d 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -10,6 +10,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CON
- The user dot now moves smoothly between user location updates while user location tracking is disabled. ([#1582](https://github.com/mapbox/mapbox-gl-native/pull/1582))
- An MGLAnnotation can be relocated by changing its `coordinate` property in a KVO-compliant way. An MGLMultiPoint cannot be relocated. ([#3835](https://github.com/mapbox/mapbox-gl-native/pull/3835))
- Setting the `image` property of an MGLAnnotationImage to `nil` resets it to the default red pin image and reclaims resources that can be used to customize additional annotations. ([#3835](https://github.com/mapbox/mapbox-gl-native/pull/3835))
+- Added methods to MGLMapView for obtaining the underlying map data rendered by the current style. ([#5110](https://github.com/mapbox/mapbox-gl-native/pull/5110))
- `MGLOfflinePackProgress` now indicates how many tiles have been downloaded and how much space they take up. ([#4874](https://github.com/mapbox/mapbox-gl-native/pull/4874))
- The compass, user dot, and visible annotations are now accessible to VoiceOver users. ([#1496](https://github.com/mapbox/mapbox-gl-native/pull/1496))
- The SDK is now localizable. No localizations are currently provided, other than English, but if you need a particular localization, you can install the SDK manually and drop a .lproj folder into the framework. ([#4783](https://github.com/mapbox/mapbox-gl-native/pull/4783))
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 13b4fbffec..2f5aacfe6c 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -395,13 +395,22 @@ static NSString * const MBXViewControllerAnnotationViewReuseIdentifer = @"MBXVie
{
if (longPress.state == UIGestureRecognizerStateBegan)
{
- MBXDroppedPinAnnotation *point = [[MBXDroppedPinAnnotation alloc] init];
- point.coordinate = [self.mapView convertPoint:[longPress locationInView:longPress.view]
+ CGPoint point = [longPress locationInView:longPress.view];
+ NSArray *features = [self.mapView visibleFeaturesAtPoint:point];
+ NSString *title;
+ for (id <MGLFeature> feature in features) {
+ if (!title) {
+ title = [feature attributeForKey:@"name_en"] ?: [feature attributeForKey:@"name"];
+ }
+ }
+
+ MBXDroppedPinAnnotation *pin = [[MBXDroppedPinAnnotation alloc] init];
+ pin.coordinate = [self.mapView convertPoint:point
toCoordinateFromView:self.mapView];
- point.title = @"Dropped Pin";
- point.subtitle = [[[MGLCoordinateFormatter alloc] init] stringFromCoordinate:point.coordinate];
+ pin.title = title ?: @"Dropped Pin";
+ pin.subtitle = [[[MGLCoordinateFormatter alloc] init] stringFromCoordinate:pin.coordinate];
// Calling `addAnnotation:` on mapView is not required since `selectAnnotation:animated` has the side effect of adding the annotation if required
- [self.mapView selectAnnotation:point animated:YES];
+ [self.mapView selectAnnotation:pin animated:YES];
}
}
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index cf48b869e3..3f233441f7 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -228,6 +228,15 @@
DABFB8731CBE9A9900D62B32 /* Mapbox.h in Headers */ = {isa = PBXBuildFile; fileRef = DA88485E1CBAFC2E00AB86E3 /* Mapbox.h */; settings = {ATTRIBUTES = (Public, ); }; };
DAC49C5C1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DAC49C5F1CD02BC9009E1AA3 /* Localizable.stringsdict */; };
DAC49C5D1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DAC49C5F1CD02BC9009E1AA3 /* Localizable.stringsdict */; };
+ DAD1656C1CF41981001FF4B9 /* MGLFeature.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165691CF41981001FF4B9 /* MGLFeature.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DAD1656D1CF41981001FF4B9 /* MGLFeature.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165691CF41981001FF4B9 /* MGLFeature.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DAD1656E1CF41981001FF4B9 /* MGLFeature_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD1656A1CF41981001FF4B9 /* MGLFeature_Private.h */; };
+ DAD165701CF41981001FF4B9 /* MGLFeature.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */; };
+ DAD165711CF41981001FF4B9 /* MGLFeature.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */; };
+ DAD165781CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DAD165791CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */; };
+ DAD1657B1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -474,6 +483,11 @@
DABCABC01CB80717000A7C39 /* locations.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = locations.hpp; sourceTree = "<group>"; };
DAC07C961CBB2CD6000CB309 /* mbgl.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = mbgl.xcconfig; path = ../../build/ios/mbgl.xcconfig; sourceTree = "<group>"; };
DAC49C621CD07D74009E1AA3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
+ DAD165691CF41981001FF4B9 /* MGLFeature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature.h; sourceTree = "<group>"; };
+ DAD1656A1CF41981001FF4B9 /* MGLFeature_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature_Private.h; sourceTree = "<group>"; };
+ DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFeature.mm; sourceTree = "<group>"; };
+ DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeCollection.h; sourceTree = "<group>"; };
+ DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLShapeCollection.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -654,56 +668,19 @@
DA8847DE1CBAFA3E00AB86E3 /* Foundation */ = {
isa = PBXGroup;
children = (
+ DAD165831CF4CFED001FF4B9 /* Categories */,
+ DAD165801CF4CF9A001FF4B9 /* Formatters */,
+ DAD165811CF4CFC4001FF4B9 /* Geometry */,
+ DAD165821CF4CFE3001FF4B9 /* Offline Maps */,
DA8847DF1CBAFA5100AB86E3 /* MGLAccountManager.h */,
DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */,
DA8848001CBAFA6200AB86E3 /* MGLAccountManager.m */,
- DA8847E01CBAFA5100AB86E3 /* MGLAnnotation.h */,
- DA35A2BA1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h */,
- DA35A2B71CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m */,
- DA35A2AF1CCA141D00E826B2 /* MGLCompassDirectionFormatter.h */,
- DA35A2B01CCA141D00E826B2 /* MGLCompassDirectionFormatter.m */,
- DA35A29D1CC9E94C00E826B2 /* MGLCoordinateFormatter.h */,
- DA35A2A01CC9E95F00E826B2 /* MGLCoordinateFormatter.m */,
- DA8847E11CBAFA5100AB86E3 /* MGLGeometry.h */,
- DA8848011CBAFA6200AB86E3 /* MGLGeometry_Private.h */,
- DA8848021CBAFA6200AB86E3 /* MGLGeometry.mm */,
DA8847E21CBAFA5100AB86E3 /* MGLMapCamera.h */,
DA8848031CBAFA6200AB86E3 /* MGLMapCamera.mm */,
- DA8847E31CBAFA5100AB86E3 /* MGLMultiPoint.h */,
- DA8848041CBAFA6200AB86E3 /* MGLMultiPoint_Private.h */,
- DA8848051CBAFA6200AB86E3 /* MGLMultiPoint.mm */,
- DA8847E41CBAFA5100AB86E3 /* MGLOfflinePack.h */,
- DA8848061CBAFA6200AB86E3 /* MGLOfflinePack_Private.h */,
- DA8848071CBAFA6200AB86E3 /* MGLOfflinePack.mm */,
- DA8847E51CBAFA5100AB86E3 /* MGLOfflineRegion.h */,
- DA8848081CBAFA6200AB86E3 /* MGLOfflineRegion_Private.h */,
- DA8847E61CBAFA5100AB86E3 /* MGLOfflineStorage.h */,
- DA8848091CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h */,
- DA88480A1CBAFA6200AB86E3 /* MGLOfflineStorage.mm */,
- DA8847E71CBAFA5100AB86E3 /* MGLOverlay.h */,
- DA8847E81CBAFA5100AB86E3 /* MGLPointAnnotation.h */,
- DA88480B1CBAFA6200AB86E3 /* MGLPointAnnotation.m */,
- DA8847E91CBAFA5100AB86E3 /* MGLPolygon.h */,
- DA88480C1CBAFA6200AB86E3 /* MGLPolygon.mm */,
- DA8847EA1CBAFA5100AB86E3 /* MGLPolyline.h */,
- DA88480D1CBAFA6200AB86E3 /* MGLPolyline.mm */,
- DA8847EB1CBAFA5100AB86E3 /* MGLShape.h */,
- DA88480E1CBAFA6200AB86E3 /* MGLShape.m */,
DA8847EC1CBAFA5100AB86E3 /* MGLStyle.h */,
DA88480F1CBAFA6200AB86E3 /* MGLStyle.mm */,
- DA8847ED1CBAFA5100AB86E3 /* MGLTilePyramidOfflineRegion.h */,
- DA8848101CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm */,
DA8847EE1CBAFA5100AB86E3 /* MGLTypes.h */,
DA8848111CBAFA6200AB86E3 /* MGLTypes.m */,
- DA8848121CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h */,
- DA8848131CBAFA6200AB86E3 /* NSBundle+MGLAdditions.m */,
- DA8848141CBAFA6200AB86E3 /* NSException+MGLAdditions.h */,
- DA8848151CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.h */,
- DA8848161CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m */,
- DA8848171CBAFA6200AB86E3 /* NSString+MGLAdditions.h */,
- DA8848181CBAFA6200AB86E3 /* NSString+MGLAdditions.m */,
- DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */,
- DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */,
DA8848911CBB049300AB86E3 /* reachability */,
);
name = Foundation;
@@ -713,31 +690,13 @@
DA8848331CBAFB2A00AB86E3 /* Kit */ = {
isa = PBXGroup;
children = (
- 4018B1C31CDC277F00F666AF /* MGLAnnotationView_Private.h */,
- 4018B1C41CDC277F00F666AF /* MGLAnnotationView.mm */,
- 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */,
- DA8848341CBAFB8500AB86E3 /* MGLAnnotationImage.h */,
- DA8848401CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h */,
- DA8848411CBAFB9800AB86E3 /* MGLAnnotationImage.m */,
- DA8848421CBAFB9800AB86E3 /* MGLAPIClient.h */,
- DA8848431CBAFB9800AB86E3 /* MGLAPIClient.m */,
- DA8848351CBAFB8500AB86E3 /* MGLCalloutView.h */,
- DA8848441CBAFB9800AB86E3 /* MGLCompactCalloutView.h */,
- DA8848451CBAFB9800AB86E3 /* MGLCompactCalloutView.m */,
- DA8848461CBAFB9800AB86E3 /* MGLLocationManager.h */,
- DA8848471CBAFB9800AB86E3 /* MGLLocationManager.m */,
- DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */,
- DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */,
+ DAD165841CF4D06B001FF4B9 /* Annotations */,
+ DAD165851CF4D08B001FF4B9 /* Telemetry */,
DA8848361CBAFB8500AB86E3 /* MGLMapView.h */,
DA17BE2F1CC4BAC300402C41 /* MGLMapView_Internal.h */,
DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */,
DA8848381CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h */,
DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */,
- DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */,
- DA88484B1CBAFB9800AB86E3 /* MGLUserLocation_Private.h */,
- DA88484C1CBAFB9800AB86E3 /* MGLUserLocation.m */,
- DA88484D1CBAFB9800AB86E3 /* MGLUserLocationAnnotationView.h */,
- DA88484E1CBAFB9800AB86E3 /* MGLUserLocationAnnotationView.m */,
DA88487F1CBB033F00AB86E3 /* Fabric */,
DA8848881CBB036000AB86E3 /* SMCalloutView */,
);
@@ -858,6 +817,114 @@
name = Configuration;
sourceTree = "<group>";
};
+ DAD165801CF4CF9A001FF4B9 /* Formatters */ = {
+ isa = PBXGroup;
+ children = (
+ DA35A2BA1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h */,
+ DA35A2B71CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m */,
+ DA35A2AF1CCA141D00E826B2 /* MGLCompassDirectionFormatter.h */,
+ DA35A2B01CCA141D00E826B2 /* MGLCompassDirectionFormatter.m */,
+ DA35A29D1CC9E94C00E826B2 /* MGLCoordinateFormatter.h */,
+ DA35A2A01CC9E95F00E826B2 /* MGLCoordinateFormatter.m */,
+ );
+ name = Formatters;
+ sourceTree = "<group>";
+ };
+ DAD165811CF4CFC4001FF4B9 /* Geometry */ = {
+ isa = PBXGroup;
+ children = (
+ DA8847E01CBAFA5100AB86E3 /* MGLAnnotation.h */,
+ DAD165691CF41981001FF4B9 /* MGLFeature.h */,
+ DAD1656A1CF41981001FF4B9 /* MGLFeature_Private.h */,
+ DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */,
+ DA8847E11CBAFA5100AB86E3 /* MGLGeometry.h */,
+ DA8848011CBAFA6200AB86E3 /* MGLGeometry_Private.h */,
+ DA8848021CBAFA6200AB86E3 /* MGLGeometry.mm */,
+ DA8847E31CBAFA5100AB86E3 /* MGLMultiPoint.h */,
+ DA8848041CBAFA6200AB86E3 /* MGLMultiPoint_Private.h */,
+ DA8848051CBAFA6200AB86E3 /* MGLMultiPoint.mm */,
+ DA8847E71CBAFA5100AB86E3 /* MGLOverlay.h */,
+ DA8847E81CBAFA5100AB86E3 /* MGLPointAnnotation.h */,
+ DA88480B1CBAFA6200AB86E3 /* MGLPointAnnotation.m */,
+ DA8847E91CBAFA5100AB86E3 /* MGLPolygon.h */,
+ DA88480C1CBAFA6200AB86E3 /* MGLPolygon.mm */,
+ DA8847EA1CBAFA5100AB86E3 /* MGLPolyline.h */,
+ DA88480D1CBAFA6200AB86E3 /* MGLPolyline.mm */,
+ DA8847EB1CBAFA5100AB86E3 /* MGLShape.h */,
+ DA88480E1CBAFA6200AB86E3 /* MGLShape.m */,
+ DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */,
+ DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */,
+ );
+ name = Geometry;
+ sourceTree = "<group>";
+ };
+ DAD165821CF4CFE3001FF4B9 /* Offline Maps */ = {
+ isa = PBXGroup;
+ children = (
+ DA8847E41CBAFA5100AB86E3 /* MGLOfflinePack.h */,
+ DA8848061CBAFA6200AB86E3 /* MGLOfflinePack_Private.h */,
+ DA8848071CBAFA6200AB86E3 /* MGLOfflinePack.mm */,
+ DA8847E51CBAFA5100AB86E3 /* MGLOfflineRegion.h */,
+ DA8848081CBAFA6200AB86E3 /* MGLOfflineRegion_Private.h */,
+ DA8847E61CBAFA5100AB86E3 /* MGLOfflineStorage.h */,
+ DA8848091CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h */,
+ DA88480A1CBAFA6200AB86E3 /* MGLOfflineStorage.mm */,
+ DA8847ED1CBAFA5100AB86E3 /* MGLTilePyramidOfflineRegion.h */,
+ DA8848101CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm */,
+ );
+ name = "Offline Maps";
+ sourceTree = "<group>";
+ };
+ DAD165831CF4CFED001FF4B9 /* Categories */ = {
+ isa = PBXGroup;
+ children = (
+ DA8848121CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h */,
+ DA8848131CBAFA6200AB86E3 /* NSBundle+MGLAdditions.m */,
+ DA8848141CBAFA6200AB86E3 /* NSException+MGLAdditions.h */,
+ DA8848151CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.h */,
+ DA8848161CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m */,
+ DA8848171CBAFA6200AB86E3 /* NSString+MGLAdditions.h */,
+ DA8848181CBAFA6200AB86E3 /* NSString+MGLAdditions.m */,
+ DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */,
+ DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */,
+ );
+ name = Categories;
+ sourceTree = "<group>";
+ };
+ DAD165841CF4D06B001FF4B9 /* Annotations */ = {
+ isa = PBXGroup;
+ children = (
+ 4018B1C31CDC277F00F666AF /* MGLAnnotationView_Private.h */,
+ 4018B1C41CDC277F00F666AF /* MGLAnnotationView.mm */,
+ 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */,
+ DA8848341CBAFB8500AB86E3 /* MGLAnnotationImage.h */,
+ DA8848401CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h */,
+ DA8848411CBAFB9800AB86E3 /* MGLAnnotationImage.m */,
+ DA8848351CBAFB8500AB86E3 /* MGLCalloutView.h */,
+ DA8848441CBAFB9800AB86E3 /* MGLCompactCalloutView.h */,
+ DA8848451CBAFB9800AB86E3 /* MGLCompactCalloutView.m */,
+ DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */,
+ DA88484B1CBAFB9800AB86E3 /* MGLUserLocation_Private.h */,
+ DA88484C1CBAFB9800AB86E3 /* MGLUserLocation.m */,
+ DA88484D1CBAFB9800AB86E3 /* MGLUserLocationAnnotationView.h */,
+ DA88484E1CBAFB9800AB86E3 /* MGLUserLocationAnnotationView.m */,
+ );
+ name = Annotations;
+ sourceTree = "<group>";
+ };
+ DAD165851CF4D08B001FF4B9 /* Telemetry */ = {
+ isa = PBXGroup;
+ children = (
+ DA8848421CBAFB9800AB86E3 /* MGLAPIClient.h */,
+ DA8848431CBAFB9800AB86E3 /* MGLAPIClient.m */,
+ DA8848461CBAFB9800AB86E3 /* MGLLocationManager.h */,
+ DA8848471CBAFB9800AB86E3 /* MGLLocationManager.m */,
+ DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */,
+ DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */,
+ );
+ name = Telemetry;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -894,6 +961,7 @@
DA88483F1CBAFB8500AB86E3 /* MGLUserLocation.h in Headers */,
DA88483D1CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h in Headers */,
DA17BE301CC4BAC300402C41 /* MGLMapView_Internal.h in Headers */,
+ DAD165781CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */,
DA88481E1CBAFA6200AB86E3 /* MGLMultiPoint_Private.h in Headers */,
DA35A29E1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */,
DA8847F71CBAFA5100AB86E3 /* MGLOverlay.h in Headers */,
@@ -905,6 +973,7 @@
DA8847F91CBAFA5100AB86E3 /* MGLPolygon.h in Headers */,
DA8847F81CBAFA5100AB86E3 /* MGLPointAnnotation.h in Headers */,
DA8847F31CBAFA5100AB86E3 /* MGLMultiPoint.h in Headers */,
+ DAD1656C1CF41981001FF4B9 /* MGLFeature.h in Headers */,
DA88484F1CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h in Headers */,
DA8847F21CBAFA5100AB86E3 /* MGLMapCamera.h in Headers */,
DA8847F51CBAFA5100AB86E3 /* MGLOfflineRegion.h in Headers */,
@@ -917,6 +986,7 @@
DA88482F1CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.h in Headers */,
DA8848601CBAFC2E00AB86E3 /* Mapbox.h in Headers */,
DA8847F61CBAFA5100AB86E3 /* MGLOfflineStorage.h in Headers */,
+ DAD1656E1CF41981001FF4B9 /* MGLFeature_Private.h in Headers */,
DA88483C1CBAFB8500AB86E3 /* MGLMapView.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -928,6 +998,7 @@
DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */,
DABFB85E1CBE99E500D62B32 /* MGLAnnotation.h in Headers */,
DABFB8641CBE99E500D62B32 /* MGLOfflineStorage.h in Headers */,
+ DAD165791CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */,
DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */,
DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */,
DABFB8611CBE99E500D62B32 /* MGLMultiPoint.h in Headers */,
@@ -935,6 +1006,7 @@
DABFB8721CBE9A0F00D62B32 /* MGLUserLocation.h in Headers */,
DABFB8661CBE99E500D62B32 /* MGLPointAnnotation.h in Headers */,
DABFB8621CBE99E500D62B32 /* MGLOfflinePack.h in Headers */,
+ DAD1656D1CF41981001FF4B9 /* MGLFeature.h in Headers */,
DA17BE311CC4BDAA00402C41 /* MGLMapView_Internal.h in Headers */,
DABFB86C1CBE99E500D62B32 /* MGLTypes.h in Headers */,
DABFB8691CBE99E500D62B32 /* MGLShape.h in Headers */,
@@ -1270,12 +1342,14 @@
buildActionMask = 2147483647;
files = (
DA88485D1CBAFB9800AB86E3 /* MGLUserLocationAnnotationView.m in Sources */,
+ DAD165701CF41981001FF4B9 /* MGLFeature.mm in Sources */,
DA8848541CBAFB9800AB86E3 /* MGLCompactCalloutView.m in Sources */,
DA8848251CBAFA6200AB86E3 /* MGLPointAnnotation.m in Sources */,
DA88482D1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.m in Sources */,
DA88485B1CBAFB9800AB86E3 /* MGLUserLocation.m in Sources */,
DA88488C1CBB037E00AB86E3 /* SMCalloutView.m in Sources */,
DA35A2B81CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */,
+ DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */,
DA8848901CBB048E00AB86E3 /* reachability.m in Sources */,
DA8848211CBAFA6200AB86E3 /* MGLOfflinePack.mm in Sources */,
DA8848591CBAFB9800AB86E3 /* MGLMapView.mm in Sources */,
@@ -1308,12 +1382,14 @@
buildActionMask = 2147483647;
files = (
DAA4E4221CBB730400178DFB /* MGLPointAnnotation.m in Sources */,
+ DAD165711CF41981001FF4B9 /* MGLFeature.mm in Sources */,
DAA4E4291CBB730400178DFB /* NSBundle+MGLAdditions.m in Sources */,
DAA4E42E1CBB730400178DFB /* MGLAPIClient.m in Sources */,
DAA4E4201CBB730400178DFB /* MGLOfflinePack.mm in Sources */,
DAA4E4331CBB730400178DFB /* MGLUserLocation.m in Sources */,
DAA4E4351CBB730400178DFB /* SMCalloutView.m in Sources */,
DA35A2B91CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */,
+ DAD1657B1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */,
DAA4E4251CBB730400178DFB /* MGLShape.m in Sources */,
DAA4E42B1CBB730400178DFB /* NSString+MGLAdditions.m in Sources */,
DAA4E4261CBB730400178DFB /* MGLStyle.mm in Sources */,
diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml
index f6a5cfba4b..61570994d5 100644
--- a/platform/ios/jazzy.yml
+++ b/platform/ios/jazzy.yml
@@ -33,12 +33,25 @@ custom_categories:
- MGLCalloutView
- MGLCalloutViewDelegate
- MGLMultiPoint
+ - MGLMultiPolygon
+ - MGLMultiPolyline
- MGLPointAnnotation
- MGLPolygon
- MGLPolyline
- MGLOverlay
- MGLShape
+ - MGLShapeCollection
- MGLUserLocation
+ - name: Map Data
+ children:
+ - MGLFeature
+ - MGLMultiPointFeature
+ - MGLMultiPolygonFeature
+ - MGLMultiPolylineFeature
+ - MGLPointFeature
+ - MGLPolygonFeature
+ - MGLPolylineFeature
+ - MGLShapeCollectionFeature
- name: Offline Maps
children:
- MGLOfflineRegion
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h
index 3f54b07f41..725677a65b 100644
--- a/platform/ios/src/MGLMapView.h
+++ b/platform/ios/src/MGLMapView.h
@@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
@protocol MGLAnnotation;
@protocol MGLOverlay;
@protocol MGLCalloutView;
+@protocol MGLFeature;
/** The vertical alignment of an annotation within a map view. */
typedef NS_ENUM(NSUInteger, MGLAnnotationVerticalAlignment) {
@@ -1021,6 +1022,132 @@ IB_DESIGNABLE
*/
- (void)removeOverlays:(NS_ARRAY_OF(id <MGLOverlay>) *)overlays;
+#pragma mark Accessing the Underlying Map Data
+
+/**
+ Returns an array of rendered map features that intersect with a given point.
+
+ This method may return features from any of the map’s style layers. To restrict
+ the search to a particular layer or layers, use the
+ `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:` method. For more
+ information about searching for map features, see that method’s documentation.
+
+ @param point A point expressed in the map view’s coordinate system.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point NS_SWIFT_NAME(visibleFeatures(at:));
+
+/**
+ Returns an array of rendered map features that intersect with a given point,
+ restricted to the given style layers.
+
+ Each object in the returned array represents a feature rendered by the
+ current style and provides access to attributes specified by the relevant
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>.
+ The returned array includes features specified in vector and GeoJSON tile
+ sources but does not include anything from raster, image, or video sources.
+
+ Only visible features are returned. For example, suppose the current style uses
+ the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets source</a>,
+ but none of the specified style layers includes features that have the `maki`
+ property set to `bus`. If you pass a point corresponding to the location of a
+ bus stop into this method, the bus stop feature does not appear in the
+ resulting array. On the other hand, if the style does include bus stops, an
+ `MGLFeature` object representing that bus stop is returned and its
+ `featureAttributes` dictionary has the `maki` key set to `bus` (along with
+ other attributes). The dictionary contains only the attributes provided by the
+ tile source; it does not include computed attribute values or rules about how
+ the feature is rendered by the current style.
+
+ The returned array is sorted by z-order, starting with the topmost rendered
+ feature and ending with the bottommost rendered feature. A feature that is
+ rendered multiple times due to wrapping across the antimeridian at low zoom
+ levels is included only once, subject to the caveat that follows.
+
+ Features come from tiled vector data or GeoJSON data that is converted to tiles
+ internally, so feature geometries are clipped at tile boundaries and features
+ may appear duplicated across tiles. For example, suppose the specified point
+ lies along a road that spans the screen. The resulting array includes those
+ parts of the road that lie within the map tile that contain the specified
+ point, even if the road extends into other tiles.
+
+ To find out the layer names in a particular style, view the style in
+ <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+
+ @param point A point expressed in the map view’s coordinate system.
+ @param styleLayerIdentifiers A set of strings that correspond to the names of
+ layers defined in the current style. Only the features contained in these
+ layers are included in the returned array.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(at:styleLayerIdentifiers:));
+
+/**
+ Returns an array of rendered map features that intersect with the given
+ rectangle.
+
+ This method may return features from any of the map’s style layers. To restrict
+ the search to a particular layer or layers, use the
+ `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:` method. For more
+ information about searching for map features, see that method’s documentation.
+
+ @param rect A rectangle expressed in the map view’s coordinate system.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect NS_SWIFT_NAME(visibleFeatures(in:));
+
+/**
+ Returns an array of rendered map features that intersect with the given
+ rectangle, restricted to the given style layers.
+
+ Each object in the returned array represents a feature rendered by the
+ current style and provides access to attributes specified by the relevant
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>.
+ The returned array includes features specified in vector and GeoJSON tile
+ sources but does not include anything from raster, image, or video sources.
+
+ Only visible features are returned. For example, suppose the current style uses
+ the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets source</a>,
+ but none of the specified style layers includes features that have the `maki`
+ property set to `bus`. If you pass a rectangle containing the location of a bus
+ stop into this method, the bus stop feature does not appear in the resulting
+ array. On the other hand, if the style does include bus stops, an `MGLFeature`
+ object representing that bus stop is returned and its `featureAttributes`
+ dictionary has the `maki` key set to `bus` (along with other attributes). The
+ dictionary contains only the attributes provided by the tile source; it does
+ not include computed attribute values or rules about how the feature is
+ rendered by the current style.
+
+ The returned array is sorted by z-order, starting with the topmost rendered
+ feature and ending with the bottommost rendered feature. A feature that is
+ rendered multiple times due to wrapping across the antimeridian at low zoom
+ levels is included only once, subject to the caveat that follows.
+
+ Features come from tiled vector data or GeoJSON data that is converted to tiles
+ internally, so feature geometries are clipped at tile boundaries and features
+ may appear duplicated across tiles. For example, suppose the specified
+ rectangle intersects with a road that spans the screen. The resulting array
+ includes those parts of the road that lie within the map tiles covering the
+ specified rectangle, even if the road extends into other tiles. The portion of
+ the road within each map tile is included individually.
+
+ To find out the layer names in a particular style, view the style in
+ <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+
+ @param rect A rectangle expressed in the map view’s coordinate system.
+ @param styleLayerIdentifiers A set of strings that correspond to the names of
+ layers defined in the current style. Only the features contained in these
+ layers are included in the returned array.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(in:styleLayerIdentifiers:));
+
#pragma mark Debugging the Map
/**
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index b9acdfb1d5..44a3cbc4c8 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -26,6 +26,7 @@
#include <mbgl/util/chrono.hpp>
#import "Mapbox.h"
+#import "MGLFeature_Private.h"
#import "MGLGeometry_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLOfflineStorage_Private.h"
@@ -2814,6 +2815,22 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
[(MGLMultiPoint *)annotation addShapeAnnotationObjectToCollection:shapes withDelegate:self];
[userShapes addObject:annotation];
}
+ else if ([annotation isKindOfClass:[MGLMultiPolyline class]])
+ {
+ // TODO: Add real support for these types down in mbgl instead of breaking the annotation apart.
+ NS_ARRAY_OF(MGLPolyline *) *polylines = [(MGLMultiPolyline *)annotation polylines];
+ [self addAnnotations:polylines];
+ }
+ else if ([annotation isKindOfClass:[MGLMultiPolygon class]])
+ {
+ NS_ARRAY_OF(MGLPolygon *) *polygons = [(MGLMultiPolygon *)annotation polygons];
+ [self addAnnotations:polygons];
+ }
+ else if ([annotation isKindOfClass:[MGLShapeCollection class]])
+ {
+ NS_ARRAY_OF(MGLShape <MGLAnnotation> *) *shapes = [(MGLShapeCollection *)annotation shapes];
+ [self addAnnotations:shapes];
+ }
else
{
MGLAnnotationView *annotationView;
@@ -4184,6 +4201,57 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
}
}
+#pragma mark Data
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point
+{
+ return [self visibleFeaturesAtPoint:point inStyleLayersWithIdentifiers:nil];
+}
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers
+{
+ mbgl::ScreenCoordinate screenCoordinate = { point.x, point.y };
+
+ mbgl::optional<std::vector<std::string>> optionalLayerIDs;
+ if (styleLayerIdentifiers)
+ {
+ __block std::vector<std::string> layerIDs;
+ layerIDs.reserve(styleLayerIdentifiers.count);
+ [styleLayerIdentifiers enumerateObjectsUsingBlock:^(NSString * _Nonnull identifier, BOOL * _Nonnull stop)
+ {
+ layerIDs.push_back(identifier.UTF8String);
+ }];
+ optionalLayerIDs = layerIDs;
+ }
+
+ std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs);
+ return MGLFeaturesFromMBGLFeatures(features);
+}
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect {
+ return [self visibleFeaturesInRect:rect inStyleLayersWithIdentifiers:nil];
+}
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers {
+ mbgl::ScreenBox screenBox = {
+ { CGRectGetMinX(rect), CGRectGetMinY(rect) },
+ { CGRectGetMaxX(rect), CGRectGetMaxY(rect) },
+ };
+
+ mbgl::optional<std::vector<std::string>> optionalLayerIDs;
+ if (styleLayerIdentifiers) {
+ __block std::vector<std::string> layerIDs;
+ layerIDs.reserve(styleLayerIdentifiers.count);
+ [styleLayerIdentifiers enumerateObjectsUsingBlock:^(NSString * _Nonnull identifier, BOOL * _Nonnull stop) {
+ layerIDs.push_back(identifier.UTF8String);
+ }];
+ optionalLayerIDs = layerIDs;
+ }
+
+ std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs);
+ return MGLFeaturesFromMBGLFeatures(features);
+}
+
#pragma mark - Utility -
- (void)animateWithDelay:(NSTimeInterval)delay animations:(void (^)(void))animations
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index 3b7361a756..013bb81614 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -14,8 +14,9 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
#import "MGLClockDirectionFormatter.h"
#import "MGLCompassDirectionFormatter.h"
#import "MGLCoordinateFormatter.h"
-#import "MGLMapCamera.h"
+#import "MGLFeature.h"
#import "MGLGeometry.h"
+#import "MGLMapCamera.h"
#import "MGLMapView.h"
#import "MGLMapView+IBAdditions.h"
#import "MGLMapView+MGLCustomStyleLayerAdditions.h"
@@ -28,6 +29,7 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
#import "MGLPolygon.h"
#import "MGLPolyline.h"
#import "MGLShape.h"
+#import "MGLShapeCollection.h"
#import "MGLStyle.h"
#import "MGLTilePyramidOfflineRegion.h"
#import "MGLTypes.h"
diff --git a/platform/osx/CHANGELOG.md b/platform/osx/CHANGELOG.md
index 67bdce1e6c..0e4da04545 100644
--- a/platform/osx/CHANGELOG.md
+++ b/platform/osx/CHANGELOG.md
@@ -3,6 +3,7 @@
## master
* Fixed an issue in which Mapbox.framework was nested inside another folder named Mapbox.framework. ([#4998](https://github.com/mapbox/mapbox-gl-native/pull/4998))
+* Added methods to MGLMapView for obtaining the underlying map data rendered by the current style. ([#5110](https://github.com/mapbox/mapbox-gl-native/pull/5110))
* Fixed a crash passing a mixture of point and shape annotations into `-[MGLMapView addAnnotations:]`. ([#5097](https://github.com/mapbox/mapbox-gl-native/pull/5097))
* Added new options to `MGLMapDebugMaskOptions` that show wireframes and the stencil buffer instead of the color buffer. ([#4359](https://github.com/mapbox/mapbox-gl-native/pull/4359))
* Fixed a memory leak when using raster resources. ([#5141](https://github.com/mapbox/mapbox-gl-native/pull/5141))
diff --git a/platform/osx/app/MapDocument.m b/platform/osx/app/MapDocument.m
index 9bff4603e4..6fcfc7ce5d 100644
--- a/platform/osx/app/MapDocument.m
+++ b/platform/osx/app/MapDocument.m
@@ -420,7 +420,8 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
if (!NSPointInRect([gestureRecognizer locationInView:self.mapView.compass], self.mapView.compass.bounds)
&& !NSPointInRect([gestureRecognizer locationInView:self.mapView.zoomControls], self.mapView.zoomControls.bounds)
&& !NSPointInRect([gestureRecognizer locationInView:self.mapView.attributionView], self.mapView.attributionView.bounds)) {
- [self dropPinAtPoint:location];
+ NSArray *features = [self.mapView visibleFeaturesAtPoint:location];
+ [self.mapView addAnnotations:features];
}
}
}
@@ -436,9 +437,17 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
}
- (DroppedPinAnnotation *)pinAtPoint:(NSPoint)point {
+ NSArray *features = [self.mapView visibleFeaturesAtPoint:point];
+ NSString *title;
+ for (id <MGLFeature> feature in features) {
+ if (!title) {
+ title = [feature attributeForKey:@"name_en"] ?: [feature attributeForKey:@"name"];
+ }
+ }
+
DroppedPinAnnotation *annotation = [[DroppedPinAnnotation alloc] init];
annotation.coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
- annotation.title = @"Dropped Pin";
+ annotation.title = title ?: @"Dropped Pin";
_spellOutNumberFormatter.numberStyle = NSNumberFormatterSpellOutStyle;
if (_showsToolTipsOnDroppedPins) {
NSString *formattedNumber = [_spellOutNumberFormatter stringFromNumber:@(++_droppedPinCounter)];
@@ -706,6 +715,10 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
}
}
+- (CGFloat)mapView:(MGLMapView *)mapView alphaForShapeAnnotation:(MGLShape *)annotation {
+ return 0.8;
+}
+
@end
@interface ValidatedToolbarItem : NSToolbarItem
diff --git a/platform/osx/jazzy.yml b/platform/osx/jazzy.yml
index b1aca9bb45..9e160d050f 100644
--- a/platform/osx/jazzy.yml
+++ b/platform/osx/jazzy.yml
@@ -29,11 +29,24 @@ custom_categories:
- MGLAnnotation
- MGLAnnotationImage
- MGLMultiPoint
+ - MGLMultiPolygon
+ - MGLMultiPolyline
- MGLPointAnnotation
- MGLPolygon
- MGLPolyline
- MGLOverlay
- MGLShape
+ - MGLShapeCollection
+ - name: Map Data
+ children:
+ - MGLFeature
+ - MGLMultiPointFeature
+ - MGLMultiPolygonFeature
+ - MGLMultiPolylineFeature
+ - MGLPointFeature
+ - MGLPolygonFeature
+ - MGLPolylineFeature
+ - MGLShapeCollectionFeature
- name: Offline Maps
children:
- MGLOfflineRegion
diff --git a/platform/osx/osx.xcodeproj/project.pbxproj b/platform/osx/osx.xcodeproj/project.pbxproj
index 270b2e33d2..762cd39fa1 100644
--- a/platform/osx/osx.xcodeproj/project.pbxproj
+++ b/platform/osx/osx.xcodeproj/project.pbxproj
@@ -31,6 +31,11 @@
DA8933B81CCD2C2D00E68420 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DA8933B61CCD2C2D00E68420 /* Foundation.stringsdict */; };
DAB6924A1CC75A31005AAB54 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; };
DAC2ABC51CC6D343006D18C4 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */; };
+ DACC22141CF3D3E200D220D9 /* MGLFeature.h in Headers */ = {isa = PBXBuildFile; fileRef = DACC22121CF3D3E200D220D9 /* MGLFeature.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */ = {isa = PBXBuildFile; fileRef = DACC22131CF3D3E200D220D9 /* MGLFeature.mm */; };
+ DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */; };
+ DAD165741CF4CD7A001FF4B9 /* MGLShapeCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DAD165751CF4CD7A001FF4B9 /* MGLShapeCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.m */; };
DAE6C2E21CC304F900DB3429 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = DAE6C2E11CC304F900DB3429 /* Credits.rtf */; };
DAE6C2ED1CC3050F00DB3429 /* DroppedPinAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */; };
DAE6C2EE1CC3050F00DB3429 /* LocationCoordinate2DTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2E61CC3050F00DB3429 /* LocationCoordinate2DTransformer.m */; };
@@ -167,6 +172,11 @@
DA8933B41CCD2C2500E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Foundation.strings; sourceTree = "<group>"; };
DA8933B71CCD2C2D00E68420 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationImage_Private.h; sourceTree = "<group>"; };
+ DACC22121CF3D3E200D220D9 /* MGLFeature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature.h; sourceTree = "<group>"; };
+ DACC22131CF3D3E200D220D9 /* MGLFeature.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFeature.mm; sourceTree = "<group>"; };
+ DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature_Private.h; sourceTree = "<group>"; };
+ DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeCollection.h; sourceTree = "<group>"; };
+ DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLShapeCollection.m; sourceTree = "<group>"; };
DAE6C2E11CC304F900DB3429 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
DAE6C2E31CC3050F00DB3429 /* DroppedPinAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DroppedPinAnnotation.h; sourceTree = "<group>"; };
DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DroppedPinAnnotation.m; sourceTree = "<group>"; };
@@ -359,6 +369,80 @@
path = ../../darwin/resources;
sourceTree = "<group>";
};
+ DAD1657C1CF4CE6B001FF4B9 /* Formatters */ = {
+ isa = PBXGroup;
+ children = (
+ DA35A2BD1CCA9B1A00E826B2 /* MGLClockDirectionFormatter.h */,
+ DA35A2BE1CCA9B1A00E826B2 /* MGLClockDirectionFormatter.m */,
+ DA35A2AB1CCA091800E826B2 /* MGLCompassDirectionFormatter.h */,
+ DA35A2AC1CCA091800E826B2 /* MGLCompassDirectionFormatter.m */,
+ DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */,
+ DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */,
+ );
+ name = Formatters;
+ sourceTree = "<group>";
+ };
+ DAD1657D1CF4CECB001FF4B9 /* Geometry */ = {
+ isa = PBXGroup;
+ children = (
+ DAE6C34B1CC31E0400DB3429 /* MGLAnnotation.h */,
+ DACC22121CF3D3E200D220D9 /* MGLFeature.h */,
+ DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */,
+ DACC22131CF3D3E200D220D9 /* MGLFeature.mm */,
+ DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */,
+ DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */,
+ DAE6C36D1CC31E2A00DB3429 /* MGLGeometry.mm */,
+ DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */,
+ DAE6C36F1CC31E2A00DB3429 /* MGLMultiPoint_Private.h */,
+ DAE6C3701CC31E2A00DB3429 /* MGLMultiPoint.mm */,
+ DAE6C3521CC31E0400DB3429 /* MGLOverlay.h */,
+ DAE6C3531CC31E0400DB3429 /* MGLPointAnnotation.h */,
+ DAE6C3761CC31E2A00DB3429 /* MGLPointAnnotation.m */,
+ DAE6C3541CC31E0400DB3429 /* MGLPolygon.h */,
+ DAE6C3771CC31E2A00DB3429 /* MGLPolygon.mm */,
+ DAE6C3551CC31E0400DB3429 /* MGLPolyline.h */,
+ DAE6C3781CC31E2A00DB3429 /* MGLPolyline.mm */,
+ DAE6C3561CC31E0400DB3429 /* MGLShape.h */,
+ DAE6C3791CC31E2A00DB3429 /* MGLShape.m */,
+ DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */,
+ DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.m */,
+ );
+ name = Geometry;
+ sourceTree = "<group>";
+ };
+ DAD1657E1CF4CF04001FF4B9 /* Offline Maps */ = {
+ isa = PBXGroup;
+ children = (
+ DAE6C34F1CC31E0400DB3429 /* MGLOfflinePack.h */,
+ DAE6C3711CC31E2A00DB3429 /* MGLOfflinePack_Private.h */,
+ DAE6C3721CC31E2A00DB3429 /* MGLOfflinePack.mm */,
+ DAE6C3501CC31E0400DB3429 /* MGLOfflineRegion.h */,
+ DAE6C3731CC31E2A00DB3429 /* MGLOfflineRegion_Private.h */,
+ DAE6C3511CC31E0400DB3429 /* MGLOfflineStorage.h */,
+ DAE6C3741CC31E2A00DB3429 /* MGLOfflineStorage_Private.h */,
+ DAE6C3751CC31E2A00DB3429 /* MGLOfflineStorage.mm */,
+ DAE6C3581CC31E0400DB3429 /* MGLTilePyramidOfflineRegion.h */,
+ DAE6C37B1CC31E2A00DB3429 /* MGLTilePyramidOfflineRegion.mm */,
+ );
+ name = "Offline Maps";
+ sourceTree = "<group>";
+ };
+ DAD1657F1CF4CF50001FF4B9 /* Categories */ = {
+ isa = PBXGroup;
+ children = (
+ DAE6C37D1CC31E2A00DB3429 /* NSBundle+MGLAdditions.h */,
+ DAE6C37E1CC31E2A00DB3429 /* NSBundle+MGLAdditions.m */,
+ DAE6C37F1CC31E2A00DB3429 /* NSException+MGLAdditions.h */,
+ DAE6C3801CC31E2A00DB3429 /* NSProcessInfo+MGLAdditions.h */,
+ DAE6C3811CC31E2A00DB3429 /* NSProcessInfo+MGLAdditions.m */,
+ DAE6C3821CC31E2A00DB3429 /* NSString+MGLAdditions.h */,
+ DAE6C3831CC31E2A00DB3429 /* NSString+MGLAdditions.m */,
+ DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */,
+ DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */,
+ );
+ name = Categories;
+ sourceTree = "<group>";
+ };
DAE6C31E1CC308BC00DB3429 /* Frameworks */ = {
isa = PBXGroup;
children = (
@@ -404,56 +488,19 @@
DAE6C3491CC31DF500DB3429 /* Foundation */ = {
isa = PBXGroup;
children = (
+ DAD1657F1CF4CF50001FF4B9 /* Categories */,
+ DAD1657C1CF4CE6B001FF4B9 /* Formatters */,
+ DAD1657D1CF4CECB001FF4B9 /* Geometry */,
+ DAD1657E1CF4CF04001FF4B9 /* Offline Maps */,
DAE6C34A1CC31E0400DB3429 /* MGLAccountManager.h */,
DAE6C36A1CC31E2A00DB3429 /* MGLAccountManager_Private.h */,
DAE6C36B1CC31E2A00DB3429 /* MGLAccountManager.m */,
- DAE6C34B1CC31E0400DB3429 /* MGLAnnotation.h */,
- DA35A2BD1CCA9B1A00E826B2 /* MGLClockDirectionFormatter.h */,
- DA35A2BE1CCA9B1A00E826B2 /* MGLClockDirectionFormatter.m */,
- DA35A2AB1CCA091800E826B2 /* MGLCompassDirectionFormatter.h */,
- DA35A2AC1CCA091800E826B2 /* MGLCompassDirectionFormatter.m */,
- DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */,
- DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */,
- DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */,
- DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */,
- DAE6C36D1CC31E2A00DB3429 /* MGLGeometry.mm */,
DAE6C34D1CC31E0400DB3429 /* MGLMapCamera.h */,
DAE6C36E1CC31E2A00DB3429 /* MGLMapCamera.mm */,
- DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */,
- DAE6C36F1CC31E2A00DB3429 /* MGLMultiPoint_Private.h */,
- DAE6C3701CC31E2A00DB3429 /* MGLMultiPoint.mm */,
- DAE6C34F1CC31E0400DB3429 /* MGLOfflinePack.h */,
- DAE6C3711CC31E2A00DB3429 /* MGLOfflinePack_Private.h */,
- DAE6C3721CC31E2A00DB3429 /* MGLOfflinePack.mm */,
- DAE6C3501CC31E0400DB3429 /* MGLOfflineRegion.h */,
- DAE6C3731CC31E2A00DB3429 /* MGLOfflineRegion_Private.h */,
- DAE6C3511CC31E0400DB3429 /* MGLOfflineStorage.h */,
- DAE6C3741CC31E2A00DB3429 /* MGLOfflineStorage_Private.h */,
- DAE6C3751CC31E2A00DB3429 /* MGLOfflineStorage.mm */,
- DAE6C3521CC31E0400DB3429 /* MGLOverlay.h */,
- DAE6C3531CC31E0400DB3429 /* MGLPointAnnotation.h */,
- DAE6C3761CC31E2A00DB3429 /* MGLPointAnnotation.m */,
- DAE6C3541CC31E0400DB3429 /* MGLPolygon.h */,
- DAE6C3771CC31E2A00DB3429 /* MGLPolygon.mm */,
- DAE6C3551CC31E0400DB3429 /* MGLPolyline.h */,
- DAE6C3781CC31E2A00DB3429 /* MGLPolyline.mm */,
- DAE6C3561CC31E0400DB3429 /* MGLShape.h */,
- DAE6C3791CC31E2A00DB3429 /* MGLShape.m */,
DAE6C3571CC31E0400DB3429 /* MGLStyle.h */,
DAE6C37A1CC31E2A00DB3429 /* MGLStyle.mm */,
- DAE6C3581CC31E0400DB3429 /* MGLTilePyramidOfflineRegion.h */,
- DAE6C37B1CC31E2A00DB3429 /* MGLTilePyramidOfflineRegion.mm */,
DAE6C3591CC31E0400DB3429 /* MGLTypes.h */,
DAE6C37C1CC31E2A00DB3429 /* MGLTypes.m */,
- DAE6C37D1CC31E2A00DB3429 /* NSBundle+MGLAdditions.h */,
- DAE6C37E1CC31E2A00DB3429 /* NSBundle+MGLAdditions.m */,
- DAE6C37F1CC31E2A00DB3429 /* NSException+MGLAdditions.h */,
- DAE6C3801CC31E2A00DB3429 /* NSProcessInfo+MGLAdditions.h */,
- DAE6C3811CC31E2A00DB3429 /* NSProcessInfo+MGLAdditions.m */,
- DAE6C3821CC31E2A00DB3429 /* NSString+MGLAdditions.h */,
- DAE6C3831CC31E2A00DB3429 /* NSString+MGLAdditions.m */,
- DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */,
- DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */,
);
name = Foundation;
path = ../darwin/src;
@@ -506,6 +553,7 @@
DAE6C3611CC31E0400DB3429 /* MGLOfflineStorage.h in Headers */,
DAE6C35E1CC31E0400DB3429 /* MGLMultiPoint.h in Headers */,
DAE6C3971CC31E2A00DB3429 /* NSBundle+MGLAdditions.h in Headers */,
+ DAD165741CF4CD7A001FF4B9 /* MGLShapeCollection.h in Headers */,
DAE6C3631CC31E0400DB3429 /* MGLPointAnnotation.h in Headers */,
DAC2ABC51CC6D343006D18C4 /* MGLAnnotationImage_Private.h in Headers */,
DAE6C35F1CC31E0400DB3429 /* MGLOfflinePack.h in Headers */,
@@ -528,6 +576,7 @@
DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */,
DAE6C3A61CC31E9400DB3429 /* MGLMapViewDelegate.h in Headers */,
DAE6C38B1CC31E2A00DB3429 /* MGLOfflinePack_Private.h in Headers */,
+ DACC22141CF3D3E200D220D9 /* MGLFeature.h in Headers */,
DAE6C35C1CC31E0400DB3429 /* MGLGeometry.h in Headers */,
DAE6C35A1CC31E0400DB3429 /* MGLAccountManager.h in Headers */,
DAE6C35D1CC31E0400DB3429 /* MGLMapCamera.h in Headers */,
@@ -536,6 +585,7 @@
DAE6C3891CC31E2A00DB3429 /* MGLMultiPoint_Private.h in Headers */,
DAE6C3A51CC31E9400DB3429 /* MGLMapView+IBAdditions.h in Headers */,
DA35A2AD1CCA091800E826B2 /* MGLCompassDirectionFormatter.h in Headers */,
+ DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */,
DAE6C3671CC31E0400DB3429 /* MGLStyle.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -718,6 +768,7 @@
DAE6C3B71CC31EF300DB3429 /* MGLMapView.mm in Sources */,
DAE6C38C1CC31E2A00DB3429 /* MGLOfflinePack.mm in Sources */,
DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */,
+ DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */,
DAE6C3B31CC31EF300DB3429 /* MGLAttributionButton.m in Sources */,
DAE6C3931CC31E2A00DB3429 /* MGLShape.m in Sources */,
DAE6C39D1CC31E2A00DB3429 /* NSString+MGLAdditions.m in Sources */,
@@ -738,6 +789,7 @@
DAE6C3851CC31E2A00DB3429 /* MGLAccountManager.m in Sources */,
DAE6C3921CC31E2A00DB3429 /* MGLPolyline.mm in Sources */,
DAE6C3B51CC31EF300DB3429 /* MGLCompassCell.m in Sources */,
+ DAD165751CF4CD7A001FF4B9 /* MGLShapeCollection.m in Sources */,
DA35A2AE1CCA091800E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1094,6 +1146,7 @@
DAAA17981CE13BAE00731EFE /* Release */,
);
defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
};
DAE6C3431CC30DB200DB3429 /* Build configuration list for PBXNativeTarget "dynamic" */ = {
isa = XCConfigurationList;
diff --git a/platform/osx/src/MGLMapView.h b/platform/osx/src/MGLMapView.h
index 749b3561d2..c08a257bea 100644
--- a/platform/osx/src/MGLMapView.h
+++ b/platform/osx/src/MGLMapView.h
@@ -35,6 +35,7 @@ typedef NS_OPTIONS(NSUInteger, MGLMapDebugMaskOptions) {
@protocol MGLAnnotation;
@protocol MGLMapViewDelegate;
@protocol MGLOverlay;
+@protocol MGLFeature;
/**
An interactive, customizable map view with an interface similar to the one
@@ -687,6 +688,132 @@ IB_DESIGNABLE
*/
- (void)removeOverlays:(NS_ARRAY_OF(id <MGLOverlay>) *)overlays;
+#pragma mark Accessing the Underlying Map Data
+
+/**
+ Returns an array of rendered map features that intersect with a given point.
+
+ This method may return features from any of the map’s style layers. To restrict
+ the search to a particular layer or layers, use the
+ `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:` method. For more
+ information about searching for map features, see that method’s documentation.
+
+ @param point A point expressed in the map view’s coordinate system.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point NS_SWIFT_NAME(visibleFeatures(_:));
+
+/**
+ Returns an array of rendered map features that intersect with a given point,
+ restricted to the given style layers.
+
+ Each object in the returned array represents a feature rendered by the
+ current style and provides access to attributes specified by the relevant
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>.
+ The returned array includes features specified in vector and GeoJSON tile
+ sources but does not include anything from raster, image, or video sources.
+
+ Only visible features are returned. For example, suppose the current style uses
+ the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets source</a>,
+ but none of the specified style layers includes features that have the `maki`
+ property set to `bus`. If you pass a point corresponding to the location of a
+ bus stop into this method, the bus stop feature does not appear in the
+ resulting array. On the other hand, if the style does include bus stops, an
+ `MGLFeature` object representing that bus stop is returned and its
+ `attributes` dictionary has the `maki` key set to `bus` (along with other
+ attributes). The dictionary contains only the attributes provided by the
+ tile source; it does not include computed attribute values or rules about how
+ the feature is rendered by the current style.
+
+ The returned array is sorted by z-order, starting with the topmost rendered
+ feature and ending with the bottommost rendered feature. A feature that is
+ rendered multiple times due to wrapping across the antimeridian at low zoom
+ levels is included only once, subject to the caveat that follows.
+
+ Features come from tiled vector data or GeoJSON data that is converted to tiles
+ internally, so feature geometries are clipped at tile boundaries and features
+ may appear duplicated across tiles. For example, suppose the specified point
+ lies along a road that spans the screen. The resulting array includes those
+ parts of the road that lie within the map tile that contain the specified
+ point, even if the road extends into other tiles.
+
+ To find out the layer names in a particular style, view the style in
+ <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+
+ @param point A point expressed in the map view’s coordinate system.
+ @param styleLayerIdentifiers A set of strings that correspond to the names of
+ layers defined in the current style. Only the features contained in these
+ layers are included in the returned array.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(_:styleLayerIdentifiers:));
+
+/**
+ Returns an array of rendered map features that intersect with the given
+ rectangle.
+
+ This method may return features from any of the map’s style layers. To restrict
+ the search to a particular layer or layers, use the
+ `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:` method. For more
+ information about searching for map features, see that method’s documentation.
+
+ @param rect A rectangle expressed in the map view’s coordinate system.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect NS_SWIFT_NAME(visibleFeatures(_:));
+
+/**
+ Returns an array of rendered map features that intersect with the given
+ rectangle, restricted to the given style layers.
+
+ Each object in the returned array represents a feature rendered by the
+ current style and provides access to attributes specified by the relevant
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>.
+ The returned array includes features specified in vector and GeoJSON tile
+ sources but does not include anything from raster, image, or video sources.
+
+ Only visible features are returned. For example, suppose the current style uses
+ the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets source</a>,
+ but none of the specified style layers includes features that have the `maki`
+ property set to `bus`. If you pass a rectangle containing the location of a bus
+ stop into this method, the bus stop feature does not appear in the resulting
+ array. On the other hand, if the style does include bus stops, an `MGLFeature`
+ object representing that bus stop is returned and its `attributes` dictionary
+ has the `maki` key set to `bus` (along with other attributes). The dictionary
+ contains only the attributes provided by the tile source; it does not include
+ computed attribute values or rules about how the feature is rendered by the
+ current style.
+
+ The returned array is sorted by z-order, starting with the topmost rendered
+ feature and ending with the bottommost rendered feature. A feature that is
+ rendered multiple times due to wrapping across the antimeridian at low zoom
+ levels is included only once, subject to the caveat that follows.
+
+ Features come from tiled vector data or GeoJSON data that is converted to tiles
+ internally, so feature geometries are clipped at tile boundaries and features
+ may appear duplicated across tiles. For example, suppose the specified
+ rectangle intersects with a road that spans the screen. The resulting array
+ includes those parts of the road that lie within the map tiles covering the
+ specified rectangle, even if the road extends into other tiles. The portion of
+ the road within each map tile is included individually.
+
+ To find out the layer names in a particular style, view the style in
+ <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+
+ @param rect A rectangle expressed in the map view’s coordinate system.
+ @param styleLayerIdentifiers A set of strings that correspond to the names of
+ layers defined in the current style. Only the features contained in these
+ layers are included in the returned array.
+ @return An array of objects conforming to the `MGLFeature` protocol that
+ represent features in the sources used by the current style.
+ */
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(_:styleLayerIdentifiers:));
+
#pragma mark Converting Geographic Coordinates
/**
diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm
index 5b85ff7ec2..20e59505b4 100644
--- a/platform/osx/src/MGLMapView.mm
+++ b/platform/osx/src/MGLMapView.mm
@@ -5,6 +5,7 @@
#import "MGLOpenGLLayer.h"
#import "MGLStyle.h"
+#import "MGLFeature_Private.h"
#import "MGLGeometry_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLOfflineStorage_Private.h"
@@ -1616,6 +1617,16 @@ public:
// The multipoint knows how to style itself (with the map view’s help).
[(MGLMultiPoint *)annotation addShapeAnnotationObjectToCollection:shapes withDelegate:self];
[userShapes addObject:annotation];
+ } else if ([annotation isKindOfClass:[MGLMultiPolyline class]]) {
+ // TODO: Add real support for these types down in mbgl instead of breaking the annotation apart.
+ NS_ARRAY_OF(MGLPolyline *) *polylines = [(MGLMultiPolyline *)annotation polylines];
+ [self addAnnotations:polylines];
+ } else if ([annotation isKindOfClass:[MGLMultiPolygon class]]) {
+ NS_ARRAY_OF(MGLPolygon *) *polygons = [(MGLMultiPolygon *)annotation polygons];
+ [self addAnnotations:polygons];
+ } else if ([annotation isKindOfClass:[MGLShapeCollection class]]) {
+ NS_ARRAY_OF(MGLShape <MGLAnnotation> *) *shapes = [(MGLShapeCollection *)annotation shapes];
+ [self addAnnotations:shapes];
} else {
MGLAnnotationImage *annotationImage = nil;
if (delegateHasImagesForAnnotations) {
@@ -2246,6 +2257,55 @@ public:
}
}
+#pragma mark Data
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point {
+ return [self visibleFeaturesAtPoint:point inStyleLayersWithIdentifiers:nil];
+}
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers {
+ // Cocoa origin is at the lower-left corner.
+ mbgl::ScreenCoordinate screenCoordinate = { point.x, NSHeight(self.bounds) - point.y };
+
+ mbgl::optional<std::vector<std::string>> optionalLayerIDs;
+ if (styleLayerIdentifiers) {
+ __block std::vector<std::string> layerIDs;
+ layerIDs.reserve(styleLayerIdentifiers.count);
+ [styleLayerIdentifiers enumerateObjectsUsingBlock:^(NSString * _Nonnull identifier, BOOL * _Nonnull stop) {
+ layerIDs.push_back(identifier.UTF8String);
+ }];
+ optionalLayerIDs = layerIDs;
+ }
+
+ std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs);
+ return MGLFeaturesFromMBGLFeatures(features);
+}
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect {
+ return [self visibleFeaturesInRect:rect inStyleLayersWithIdentifiers:nil];
+}
+
+- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers {
+ // Cocoa origin is at the lower-left corner.
+ mbgl::ScreenBox screenBox = {
+ { NSMinX(rect), NSHeight(self.bounds) - NSMaxY(rect) },
+ { NSMaxX(rect), NSHeight(self.bounds) - NSMinY(rect) },
+ };
+
+ mbgl::optional<std::vector<std::string>> optionalLayerIDs;
+ if (styleLayerIdentifiers) {
+ __block std::vector<std::string> layerIDs;
+ layerIDs.reserve(styleLayerIdentifiers.count);
+ [styleLayerIdentifiers enumerateObjectsUsingBlock:^(NSString * _Nonnull identifier, BOOL * _Nonnull stop) {
+ layerIDs.push_back(identifier.UTF8String);
+ }];
+ optionalLayerIDs = layerIDs;
+ }
+
+ std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs);
+ return MGLFeaturesFromMBGLFeatures(features);
+}
+
#pragma mark Interface Builder methods
- (void)prepareForInterfaceBuilder {
diff --git a/platform/osx/src/Mapbox.h b/platform/osx/src/Mapbox.h
index a98aea9bcf..e4545e04bc 100644
--- a/platform/osx/src/Mapbox.h
+++ b/platform/osx/src/Mapbox.h
@@ -12,6 +12,7 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
#import "MGLClockDirectionFormatter.h"
#import "MGLCompassDirectionFormatter.h"
#import "MGLCoordinateFormatter.h"
+#import "MGLFeature.h"
#import "MGLGeometry.h"
#import "MGLMapCamera.h"
#import "MGLMapView.h"
@@ -26,6 +27,7 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
#import "MGLPolygon.h"
#import "MGLPolyline.h"
#import "MGLShape.h"
+#import "MGLShapeCollection.h"
#import "MGLStyle.h"
#import "MGLTilePyramidOfflineRegion.h"
#import "MGLTypes.h"