summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Rex <julian.rex@gmail.com>2019-01-14 15:17:13 -0500
committerGitHub <noreply@github.com>2019-01-14 15:17:13 -0500
commitc8c664fbf376b615b3f1e4b2a4d7f1c99b6097be (patch)
tree414451567862d1bca08bcff1798ebb6b6501ad8d
parent2342b8ee936b9ecce33e152d109a091e505488e6 (diff)
downloadqtlocation-mapboxgl-c8c664fbf376b615b3f1e4b2a4d7f1c99b6097be.tar.gz
[ios, macos] Support getLeaves (and related) clustering methods (#12952) following feature extension API (#13382)
-rw-r--r--platform/darwin/docs/guides/Predicates and Expressions.md12
-rw-r--r--platform/darwin/src/MGLCluster.h53
-rw-r--r--platform/darwin/src/MGLFeature.h18
-rw-r--r--platform/darwin/src/MGLFeature.mm60
-rw-r--r--platform/darwin/src/MGLFeature_Private.h1
-rw-r--r--platform/darwin/src/MGLFoundation_Private.h6
-rw-r--r--platform/darwin/src/MGLShapeSource.h42
-rw-r--r--platform/darwin/src/MGLShapeSource.mm105
-rw-r--r--platform/darwin/src/MGLShapeSource_Private.h16
-rw-r--r--platform/darwin/test/MGLCodingTests.mm (renamed from platform/darwin/test/MGLCodingTests.m)33
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift57
-rw-r--r--platform/darwin/test/MGLFeatureTests.mm21
-rw-r--r--platform/ios/CHANGELOG.md2
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj30
-rw-r--r--platform/ios/jazzy.yml2
-rw-r--r--platform/ios/sdk-files.json1
-rw-r--r--platform/ios/src/Mapbox.h1
-rw-r--r--platform/macos/CHANGELOG.md2
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj42
-rw-r--r--platform/macos/sdk-files.json1
-rw-r--r--platform/macos/src/Mapbox.h1
21 files changed, 470 insertions, 36 deletions
diff --git a/platform/darwin/docs/guides/Predicates and Expressions.md b/platform/darwin/docs/guides/Predicates and Expressions.md
index 71c869f7fe..0bb26b3bfd 100644
--- a/platform/darwin/docs/guides/Predicates and Expressions.md
+++ b/platform/darwin/docs/guides/Predicates and Expressions.md
@@ -120,7 +120,7 @@ dictionary contains the `floorCount` key, then the key path `floorCount` refers
to the value of the `floorCount` attribute when evaluating that particular
polygon.
-The following special attribute is also available on features that are produced
+The following special attributes are also available on features that are produced
as a result of clustering multiple point features together in a shape source:
<table>
@@ -129,6 +129,16 @@ as a result of clustering multiple point features together in a shape source:
</thead>
<tbody>
<tr>
+ <td><code>cluster</code></td>
+ <td>Bool</td>
+ <td>True if the feature is a point cluster. If the attribute is false (or not present) then the feature should not be considered a cluster.</td>
+</tr>
+<tr>
+ <td><code>cluster_id</code></td>
+ <td>Number</td>
+ <td>Identifier for the point cluster.</td>
+</tr>
+<tr>
<td><code>point_count</code></td>
<td>Number</td>
<td>The number of point features in a given cluster.</td>
diff --git a/platform/darwin/src/MGLCluster.h b/platform/darwin/src/MGLCluster.h
new file mode 100644
index 0000000000..2b99119b26
--- /dev/null
+++ b/platform/darwin/src/MGLCluster.h
@@ -0,0 +1,53 @@
+#import "MGLFoundation.h"
+
+@protocol MGLFeature;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ An `NSUInteger` constant used to indicate an invalid cluster identifier.
+ This indicates a missing cluster feature.
+ */
+FOUNDATION_EXTERN MGL_EXPORT const NSUInteger MGLClusterIdentifierInvalid;
+
+/**
+ A protocol that feature subclasses (i.e. those already conforming to
+ the `MGLFeature` protocol) conform to if they represent clusters.
+
+ Currently the only class that conforms to `MGLCluster` is
+ `MGLPointFeatureCluster` (a subclass of `MGLPointFeature`).
+
+ To check if a feature is a cluster, check conformity to `MGLCluster`, for
+ example:
+
+ ```swift
+ let shape = try! MGLShape(data: clusterShapeData, encoding: String.Encoding.utf8.rawValue)
+
+ guard let pointFeature = shape as? MGLPointFeature else {
+ throw ExampleError.unexpectedFeatureType
+ }
+
+ // Check for cluster conformance
+ guard let cluster = pointFeature as? MGLCluster else {
+ throw ExampleError.featureIsNotACluster
+ }
+
+ // Currently the only supported class that conforms to `MGLCluster` is
+ // `MGLPointFeatureCluster`
+ guard cluster is MGLPointFeatureCluster else {
+ throw ExampleError.unexpectedFeatureType
+ }
+ ```
+ */
+MGL_EXPORT
+@protocol MGLCluster <MGLFeature>
+
+/** The identifier for the cluster. */
+@property (nonatomic, readonly) NSUInteger clusterIdentifier;
+
+/** The number of points within this cluster */
+@property (nonatomic, readonly) NSUInteger clusterPointCount;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
index 8886c8df55..51901d73c0 100644
--- a/platform/darwin/src/MGLFeature.h
+++ b/platform/darwin/src/MGLFeature.h
@@ -6,6 +6,7 @@
#import "MGLPointAnnotation.h"
#import "MGLPointCollection.h"
#import "MGLShapeCollection.h"
+#import "MGLCluster.h"
NS_ASSUME_NONNULL_BEGIN
@@ -186,13 +187,28 @@ MGL_EXPORT
#### Related examples
See the <a href="https://www.mapbox.com/ios-sdk/maps/examples/runtime-multiple-annotations/">
Dynamically style interactive points</a> example to learn how to initialize
- `MGLPointFeature` objects and add it them your map.
+ `MGLPointFeature` objects and add them to your map.
*/
MGL_EXPORT
@interface MGLPointFeature : MGLPointAnnotation <MGLFeature>
@end
/**
+ An `MGLPointFeatureCluster` object associates a point shape (with an optional
+ identifier and attributes) and represents a point cluster.
+
+ @see `MGLCluster`
+
+ #### Related examples
+ See the <a href="https://www.mapbox.com/ios-sdk/maps/examples/clustering/">
+ Clustering point data</a> example to learn how to initialize
+ clusters and add them to your map.
+ */
+MGL_EXPORT
+@interface MGLPointFeatureCluster : MGLPointFeature <MGLCluster>
+@end
+
+/**
An `MGLPolylineFeature` object associates a polyline shape with an optional
identifier and attributes.
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
index d24c807625..fbf262af29 100644
--- a/platform/darwin/src/MGLFeature.mm
+++ b/platform/darwin/src/MGLFeature.mm
@@ -1,4 +1,6 @@
+#import "MGLFoundation_Private.h"
#import "MGLFeature_Private.h"
+#import "MGLCluster.h"
#import "MGLPointAnnotation.h"
#import "MGLPolyline.h"
@@ -19,6 +21,11 @@
#import <mbgl/style/conversion/geojson.hpp>
#import <mapbox/feature.hpp>
+// Cluster constants
+static NSString * const MGLClusterIdentifierKey = @"cluster_id";
+static NSString * const MGLClusterCountKey = @"point_count";
+const NSUInteger MGLClusterIdentifierInvalid = NSUIntegerMax;
+
@interface MGLEmptyFeature ()
@end
@@ -92,6 +99,31 @@ MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER();
@end
+@implementation MGLPointFeatureCluster
+
+- (NSUInteger)clusterIdentifier {
+ NSNumber *clusterNumber = MGL_OBJC_DYNAMIC_CAST([self attributeForKey:MGLClusterIdentifierKey], NSNumber);
+ MGLAssert(clusterNumber, @"Clusters should have a cluster_id");
+
+ if (!clusterNumber) {
+ return MGLClusterIdentifierInvalid;
+ }
+
+ NSUInteger clusterIdentifier = [clusterNumber unsignedIntegerValue];
+ MGLAssert(clusterIdentifier <= UINT32_MAX, @"Cluster identifiers are 32bit");
+
+ return clusterIdentifier;
+}
+
+- (NSUInteger)clusterPointCount {
+ NSNumber *count = MGL_OBJC_DYNAMIC_CAST([self attributeForKey:MGLClusterCountKey], NSNumber);
+ MGLAssert(count, @"Clusters should have a point_count");
+
+ return [count unsignedIntegerValue];
+}
+@end
+
+
@interface MGLPolylineFeature ()
@end
@@ -318,14 +350,38 @@ MGL_DEFINE_FEATURE_ATTRIBUTES_GETTER();
*/
template <typename T>
class GeometryEvaluator {
+private:
+ const mbgl::PropertyMap *shared_properties;
+
public:
+ GeometryEvaluator(const mbgl::PropertyMap *properties = nullptr):
+ shared_properties(properties)
+ {}
+
MGLShape <MGLFeature> * operator()(const mbgl::EmptyGeometry &) const {
MGLEmptyFeature *feature = [[MGLEmptyFeature alloc] init];
return feature;
}
MGLShape <MGLFeature> * operator()(const mbgl::Point<T> &geometry) const {
- MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ Class pointFeatureClass = [MGLPointFeature class];
+
+ // If we're dealing with a cluster, we should change the class type.
+ // This could be generic and build the subclass at runtime if it turns
+ // out we need to support more than point clusters.
+ if (shared_properties) {
+ auto clusterIt = shared_properties->find("cluster");
+ if (clusterIt != shared_properties->end()) {
+ auto clusterValue = clusterIt->second;
+ if (clusterValue.template is<bool>()) {
+ if (clusterValue.template get<bool>()) {
+ pointFeatureClass = [MGLPointFeatureCluster class];
+ }
+ }
+ }
+ }
+
+ MGLPointFeature *feature = [[pointFeatureClass alloc] init];
feature.coordinate = toLocationCoordinate2D(geometry);
return feature;
}
@@ -443,7 +499,7 @@ id <MGLFeature> MGLFeatureFromMBGLFeature(const mbgl::Feature &feature) {
ValueEvaluator evaluator;
attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator);
}
- GeometryEvaluator<double> evaluator;
+ GeometryEvaluator<double> evaluator(&feature.properties);
MGLShape <MGLFeature> *shape = mapbox::geometry::geometry<double>::visit(feature.geometry, evaluator);
if (!feature.id.is<mapbox::feature::null_value_t>()) {
shape.identifier = mbgl::FeatureIdentifier::visit(feature.id, ValueEvaluator());
diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h
index 9fb1f91820..9b0e16f4b9 100644
--- a/platform/darwin/src/MGLFeature_Private.h
+++ b/platform/darwin/src/MGLFeature_Private.h
@@ -18,6 +18,7 @@ NSArray<MGLShape <MGLFeature> *> *MGLFeaturesFromMBGLFeatures(const std::vector<
/**
Returns an `MGLFeature` object converted from the given mbgl::Feature
*/
+MGL_EXPORT
id <MGLFeature> MGLFeatureFromMBGLFeature(const mbgl::Feature &feature);
/**
diff --git a/platform/darwin/src/MGLFoundation_Private.h b/platform/darwin/src/MGLFoundation_Private.h
index 71737c2cf9..db81bde3de 100644
--- a/platform/darwin/src/MGLFoundation_Private.h
+++ b/platform/darwin/src/MGLFoundation_Private.h
@@ -11,3 +11,9 @@ void MGLInitializeRunLoop();
(type *)([temp##__LINE__ isKindOfClass:[type class]] ? temp##__LINE__ : nil); \
})
+#define MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(object, proto) \
+ ({ \
+ __typeof__( object ) temp##__LINE__ = (object); \
+ (id< proto >)([temp##__LINE__ conformsToProtocol:@protocol( proto )] ? temp##__LINE__ : nil); \
+ })
+
diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h
index edf8c0a174..b910fb02ce 100644
--- a/platform/darwin/src/MGLShapeSource.h
+++ b/platform/darwin/src/MGLShapeSource.h
@@ -5,6 +5,8 @@
NS_ASSUME_NONNULL_BEGIN
@protocol MGLFeature;
+@class MGLPointFeature;
+@class MGLPointFeatureCluster;
@class MGLShape;
/**
@@ -321,6 +323,46 @@ MGL_EXPORT
*/
- (NSArray<id <MGLFeature>> *)featuresMatchingPredicate:(nullable NSPredicate *)predicate;
+/**
+ Returns an array of map features that are the leaves of the specified cluster.
+ ("Leaves" are the original points that belong to the cluster.)
+
+ This method supports pagination; you supply an offset (number of features to skip)
+ and a maximum number of features to return.
+
+ @param cluster An object of type `MGLPointFeatureCluster` (that conforms to the `MGLCluster` protocol).
+ @param offset Number of features to skip.
+ @param limit The maximum number of features to return
+
+ @return An array of objects that conform to the `MGLFeature` protocol.
+ */
+- (NSArray<id <MGLFeature>> *)leavesOfCluster:(MGLPointFeatureCluster *)cluster offset:(NSUInteger)offset limit:(NSUInteger)limit;
+
+/**
+ Returns an array of map features that are the immediate children of the specified
+ cluster *on the next zoom level*. The may include features that also conform to
+ the `MGLCluster` protocol (currently only objects of type `MGLPointFeatureCluster`).
+
+ @param cluster An object of type `MGLPointFeatureCluster` (that conforms to the `MGLCluster` protocol).
+
+ @return An array of objects that conform to the `MGLFeature` protocol.
+
+ @note The returned array may contain the `cluster` that was passed in, if the next
+ zoom level doesn't match the zoom level for expanding that cluster. See
+ `-[MGLShapeSource zoomLevelForExpandingCluster:]`.
+ */
+- (NSArray<id<MGLFeature>> *)childrenOfCluster:(MGLPointFeatureCluster *)cluster;
+
+/**
+ Returns the zoom level at which the given cluster expands.
+
+ @param cluster An object of type `MGLPointFeatureCluster` (that conforms to the `MGLCluster` protocol).
+
+ @return Zoom level. This should be >= 0; any negative return value should be
+ considered an error.
+ */
+- (double)zoomLevelForExpandingCluster:(MGLPointFeatureCluster *)cluster;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm
index c960f2a4a7..fc526f9850 100644
--- a/platform/darwin/src/MGLShapeSource.mm
+++ b/platform/darwin/src/MGLShapeSource.mm
@@ -1,10 +1,13 @@
+#import "MGLFoundation_Private.h"
#import "MGLShapeSource_Private.h"
+#import "MGLLoggingConfiguration_Private.h"
#import "MGLStyle_Private.h"
#import "MGLMapView_Private.h"
#import "MGLSource_Private.h"
#import "MGLFeature_Private.h"
#import "MGLShape_Private.h"
+#import "MGLCluster.h"
#import "NSPredicate+MGLPrivateAdditions.h"
#import "NSURL+MGLAdditions.h"
@@ -184,4 +187,106 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary<MGLShap
return MGLFeaturesFromMBGLFeatures(features);
}
+#pragma mark - MGLCluster management
+
+- (mbgl::optional<mbgl::FeatureExtensionValue>)featureExtensionValueOfCluster:(MGLShape<MGLCluster> *)cluster extension:(std::string)extension options:(const std::map<std::string, mbgl::Value>)options {
+ mbgl::optional<mbgl::FeatureExtensionValue> extensionValue;
+
+ // Check parameters
+ if (!self.rawSource || !self.mapView || !cluster) {
+ return extensionValue;
+ }
+
+ auto geoJSON = [cluster geoJSONObject];
+
+ if (!geoJSON.is<mbgl::Feature>()) {
+ MGLAssert(0, @"cluster geoJSON object is not a feature.");
+ return extensionValue;
+ }
+
+ auto clusterFeature = geoJSON.get<mbgl::Feature>();
+
+ extensionValue = self.mapView.renderer->queryFeatureExtensions(self.rawSource->getID(),
+ clusterFeature,
+ "supercluster",
+ extension,
+ options);
+ return extensionValue;
+}
+
+- (NSArray<id <MGLFeature>> *)leavesOfCluster:(MGLPointFeatureCluster *)cluster offset:(NSUInteger)offset limit:(NSUInteger)limit {
+ const std::map<std::string, mbgl::Value> options = {
+ { "limit", static_cast<uint64_t>(limit) },
+ { "offset", static_cast<uint64_t>(offset) }
+ };
+
+ auto featureExtension = [self featureExtensionValueOfCluster:cluster extension:"leaves" options:options];
+
+ if (!featureExtension) {
+ return @[];
+ }
+
+ if (!featureExtension->is<mbgl::FeatureCollection>()) {
+ return @[];
+ }
+
+ std::vector<mbgl::Feature> leaves = featureExtension->get<mbgl::FeatureCollection>();
+ return MGLFeaturesFromMBGLFeatures(leaves);
+}
+
+- (NSArray<id <MGLFeature>> *)childrenOfCluster:(MGLPointFeatureCluster *)cluster {
+ auto featureExtension = [self featureExtensionValueOfCluster:cluster extension:"children" options:{}];
+
+ if (!featureExtension) {
+ return @[];
+ }
+
+ if (!featureExtension->is<mbgl::FeatureCollection>()) {
+ return @[];
+ }
+
+ std::vector<mbgl::Feature> leaves = featureExtension->get<mbgl::FeatureCollection>();
+ return MGLFeaturesFromMBGLFeatures(leaves);
+}
+
+- (double)zoomLevelForExpandingCluster:(MGLPointFeatureCluster *)cluster {
+ auto featureExtension = [self featureExtensionValueOfCluster:cluster extension:"expansion-zoom" options:{}];
+
+ if (!featureExtension) {
+ return -1.0;
+ }
+
+ if (!featureExtension->is<mbgl::Value>()) {
+ return -1.0;
+ }
+
+ auto value = featureExtension->get<mbgl::Value>();
+ if (value.is<uint64_t>()) {
+ auto zoom = value.get<uint64_t>();
+ return static_cast<double>(zoom);
+ }
+
+ return -1.0;
+}
+
+- (void)debugRecursiveLogForFeature:(id <MGLFeature>)feature indent:(NSUInteger)indent {
+ NSString *description = feature.description;
+
+ // Want our recursive log on a single line
+ NSString *log = [description stringByReplacingOccurrencesOfString:@"\\s+"
+ withString:@" "
+ options:NSRegularExpressionSearch
+ range:NSMakeRange(0, description.length)];
+
+ printf("%*s%s\n", (int)indent, "", log.UTF8String);
+
+ MGLPointFeatureCluster *cluster = MGL_OBJC_DYNAMIC_CAST(feature, MGLPointFeatureCluster);
+
+ if (cluster) {
+ for (id <MGLFeature> child in [self childrenOfCluster:cluster]) {
+ [self debugRecursiveLogForFeature:child indent:indent + 4];
+ }
+ }
+}
+
@end
diff --git a/platform/darwin/src/MGLShapeSource_Private.h b/platform/darwin/src/MGLShapeSource_Private.h
index fb5b3b3c0d..c7eaf3d0a8 100644
--- a/platform/darwin/src/MGLShapeSource_Private.h
+++ b/platform/darwin/src/MGLShapeSource_Private.h
@@ -12,4 +12,20 @@ namespace mbgl {
MGL_EXPORT
mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NSDictionary<MGLShapeSourceOption, id> *options);
+@interface MGLShapeSource (Private)
+
+/**
+ :nodoc:
+ Debug log showing structure of an `MGLFeature`. This method recurses in the case
+ that the feature conforms to `MGLCluster`. This method is used for testing and
+ should be considered experimental, likely to be removed or changed in future
+ releases.
+
+ @param feature An object that conforms to the `MGLFeature` protocol.
+ @param indent Used during recursion. Specify 0.
+ */
+
+- (void)debugRecursiveLogForFeature:(id<MGLFeature>)feature indent:(NSUInteger)indent;
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.mm
index ac61672b76..e6417c99f5 100644
--- a/platform/darwin/test/MGLCodingTests.m
+++ b/platform/darwin/test/MGLCodingTests.mm
@@ -1,6 +1,9 @@
#import <Mapbox/Mapbox.h>
#import <XCTest/XCTest.h>
+#import "MGLFoundation_Private.h"
+#import "MGLCluster.h"
+
#if TARGET_OS_IPHONE
#import "MGLUserLocation_Private.h"
#endif
@@ -41,6 +44,36 @@
XCTAssertEqualObjects(pointFeature, unarchivedPointFeature);
}
+- (void)testPointFeatureCluster {
+ MGLPointFeature *pointFeature = [[MGLPointFeatureCluster alloc] init];
+ pointFeature.title = @"title";
+ pointFeature.subtitle = @"subtitle";
+ pointFeature.identifier = @(123);
+ pointFeature.attributes = @{
+ @"cluster" : @(YES),
+ @"cluster_id" : @(456),
+ @"point_count" : @(2),
+ };
+
+ XCTAssert([pointFeature isKindOfClass:[MGLPointFeature class]], @"");
+
+ NSString *filePath = [self temporaryFilePathForClass:MGLPointFeature.class];
+ [NSKeyedArchiver archiveRootObject:pointFeature toFile:filePath];
+ MGLPointFeature *unarchivedPointFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
+
+ XCTAssertEqualObjects(pointFeature, unarchivedPointFeature);
+
+ // Unarchive process should ensure we still have a cluster
+ XCTAssert([unarchivedPointFeature isMemberOfClass:[MGLPointFeatureCluster class]]);
+
+ id<MGLCluster> cluster = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(unarchivedPointFeature, MGLCluster);
+
+ XCTAssert(cluster);
+ XCTAssert(cluster.clusterIdentifier == 456);
+ XCTAssert(cluster.clusterPointCount == 2);
+}
+
+
- (void)testPolyline {
CLLocationCoordinate2D coordinates[] = {
CLLocationCoordinate2DMake(0.129631234123, 1.7812739312551),
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 028ee2e856..b59d297f97 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -374,7 +374,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
return MGLDocumentationExampleTests.styleURL
}
}
-
+
//#-example-code
let camera = MGLMapCamera(lookingAtCenter: CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365), altitude: 100, pitch: 20, heading: 0)
@@ -394,6 +394,61 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
wait(for: [expectation], timeout: 5)
}
+ func testMGLCluster() {
+
+ enum ExampleError: Error {
+ case unexpectedFeatureType
+ case featureIsNotACluster
+ }
+
+ let geoJSON: [String: Any] = [
+ "type" : "Feature",
+ "geometry" : [
+ "coordinates" : [
+ -77.00896639534831,
+ 38.87031006108791,
+ 0.0
+ ],
+ "type" : "Point"
+ ],
+ "properties" : [
+ "cluster" : true,
+ "cluster_id" : 123,
+ "point_count" : 4567,
+ ]
+ ]
+
+ let clusterShapeData = try! JSONSerialization.data(withJSONObject: geoJSON, options: [])
+
+ do {
+ //#-example-code
+ let shape = try! MGLShape(data: clusterShapeData, encoding: String.Encoding.utf8.rawValue)
+
+ guard let pointFeature = shape as? MGLPointFeature else {
+ throw ExampleError.unexpectedFeatureType
+ }
+
+ // Check for cluster conformance
+ guard let cluster = pointFeature as? MGLCluster else {
+ throw ExampleError.featureIsNotACluster
+ }
+
+ // Currently the only supported class that conforms to `MGLCluster` is
+ // `MGLPointFeatureCluster`
+ guard cluster is MGLPointFeatureCluster else {
+ throw ExampleError.unexpectedFeatureType
+ }
+
+ //#-end-example-code
+
+ XCTAssert(cluster.clusterIdentifier == 123)
+ XCTAssert(cluster.clusterPointCount == 4567)
+ }
+ catch let error {
+ XCTFail("Example failed with thrown error: \(error)")
+ }
+ }
+
// For testMGLMapView().
func myCustomFunction() {}
}
diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm
index 67f2a9a45e..edc105bca4 100644
--- a/platform/darwin/test/MGLFeatureTests.mm
+++ b/platform/darwin/test/MGLFeatureTests.mm
@@ -2,6 +2,7 @@
#import <XCTest/XCTest.h>
#import <mbgl/util/geometry.hpp>
+#import "MGLFoundation_Private.h"
#import "../../darwin/src/MGLFeature_Private.h"
@interface MGLFeatureTests : XCTestCase
@@ -85,6 +86,26 @@
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(3, 2)]);
}
+- (void)testClusterGeometryConversion {
+ mbgl::Point<double> point = { -90.066667, 29.95 };
+ mbgl::Feature pointFeature { point };
+ pointFeature.id = { UINT64_MAX };
+ pointFeature.properties["cluster"] = true;
+ pointFeature.properties["cluster_id"] = 1ULL;
+ pointFeature.properties["point_count"] = 5ULL;
+
+ id<MGLFeature> feature = MGLFeatureFromMBGLFeature(pointFeature);
+
+ XCTAssert([feature conformsToProtocol:@protocol(MGLFeature)]);
+
+ id<MGLCluster> cluster = MGL_OBJC_DYNAMIC_CAST_AS_PROTOCOL(feature, MGLCluster);
+ XCTAssert(cluster);
+ XCTAssert(cluster.clusterIdentifier == 1);
+ XCTAssert(cluster.clusterPointCount == 5);
+
+ XCTAssert([cluster isMemberOfClass:[MGLPointFeatureCluster class]]);
+}
+
- (void)testPropertyConversion {
std::vector<mbgl::Feature> features;
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index eac21f7dfa..bcd54800c8 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -8,6 +8,8 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Fixed a crash when casting large numbers in `NSExpression`. ([#13580](https://github.com/mapbox/mapbox-gl-native/pull/13580))
* Fixed a bug where the `animated` parameter to `-[MGLMapView selectAnnotation:animated:]` was being ignored. ([#13689](https://github.com/mapbox/mapbox-gl-native/pull/13689))
* Reinstates version 11 as the default Mapbox Streets style (as introduced in 4.7.0). ([#13690](https://github.com/mapbox/mapbox-gl-native/pull/13690))
+* Added the `-[MGLShapeSource leavesOfCluster:offset:limit:]`, `-[MGLShapeSource childrenOfCluster:]`, `-[MGLShapeSource zoomLevelForExpandingCluster:]` methods for inspecting a cluster in an `MGLShapeSource`s created with the `MGLShapeSourceOptionClustered` option. Feature querying now returns clusters represented by `MGLPointFeatureCluster` objects (that conform to the `MGLCluster` protocol). ([#12952](https://github.com/mapbox/mapbox-gl-native/pull/12952)
+
## 4.7.1 - December 21, 2018
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 45c42e65b9..2c4d7f2eab 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -170,7 +170,7 @@
35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */; };
35D3A1E61E9BE7EB002B38EE /* MGLScaleBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 355ADFFB1E9281DA00F3939D /* MGLScaleBar.h */; };
35D3A1E71E9BE7EC002B38EE /* MGLScaleBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 355ADFFB1E9281DA00F3939D /* MGLScaleBar.h */; };
- 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */; };
+ 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.mm */; };
35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; };
35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; };
35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */; };
@@ -477,6 +477,8 @@
CA4EB8C720863487006AB465 /* MGLStyleLayerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */; };
CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ CA65C4F821E9BB080068B0D4 /* MGLCluster.h in Headers */ = {isa = PBXBuildFile; fileRef = CA65C4F721E9BB080068B0D4 /* MGLCluster.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ CA65C4F921E9BB080068B0D4 /* MGLCluster.h in Headers */ = {isa = PBXBuildFile; fileRef = CA65C4F721E9BB080068B0D4 /* MGLCluster.h */; settings = {ATTRIBUTES = (Public, ); }; };
CA6914B520E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA6914B420E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m */; };
CA88DC3021C85D900059ED5A /* MGLStyleURLIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CA88DC2F21C85D900059ED5A /* MGLStyleURLIntegrationTest.m */; };
CA8FBC0921A47BB100D1203C /* MGLRendererConfigurationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA8FBC0821A47BB100D1203C /* MGLRendererConfigurationTests.mm */; };
@@ -935,7 +937,7 @@
35D13AB61D3D15E300AFB4E0 /* MGLStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleLayer.mm; sourceTree = "<group>"; };
35D13AC11D3D19DD00AFB4E0 /* MGLFillStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFillStyleLayer.h; sourceTree = "<group>"; };
35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFillStyleLayer.mm; sourceTree = "<group>"; };
- 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCodingTests.m; path = ../../darwin/test/MGLCodingTests.m; sourceTree = "<group>"; };
+ 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLCodingTests.mm; path = ../../darwin/test/MGLCodingTests.mm; sourceTree = "<group>"; };
35DE35531EB7CBA8004917C5 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sv; path = sv.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
35E0CFE51D3E501500188327 /* MGLStyle_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyle_Private.h; sourceTree = "<group>"; };
35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = "<group>"; };
@@ -1049,7 +1051,7 @@
40FDA7691CCAAA6800442548 /* MBXAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXAnnotationView.h; sourceTree = "<group>"; };
40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAnnotationView.m; sourceTree = "<group>"; };
554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
- 556660C91E1BF3A900E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; };
+ 556660C91E1BF3A900E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; wrapsLines = 0; };
556660D71E1D085500E2C41B /* MGLVersionNumber.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLVersionNumber.m; path = ../../darwin/test/MGLVersionNumber.m; sourceTree = "<group>"; };
558DE79E1E5615E400C7916D /* MGLFoundation_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFoundation_Private.h; sourceTree = "<group>"; };
558DE79F1E5615E400C7916D /* MGLFoundation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFoundation.mm; sourceTree = "<group>"; };
@@ -1143,6 +1145,7 @@
CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLStyleLayerIntegrationTests.m; sourceTree = "<group>"; };
CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChangeReason.h; sourceTree = "<group>"; };
CA5E5042209BDC5F001A8A81 /* MGLTestUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MGLTestUtility.h; path = ../../darwin/test/MGLTestUtility.h; sourceTree = "<group>"; };
+ CA65C4F721E9BB080068B0D4 /* MGLCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCluster.h; sourceTree = "<group>"; };
CA6914B420E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLAnnotationViewIntegrationTests.m; path = "Annotation Tests/MGLAnnotationViewIntegrationTests.m"; sourceTree = "<group>"; };
CA88DC2F21C85D900059ED5A /* MGLStyleURLIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLStyleURLIntegrationTest.m; sourceTree = "<group>"; };
CA8FBC0821A47BB100D1203C /* MGLRendererConfigurationTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLRendererConfigurationTests.mm; path = ../../darwin/test/MGLRendererConfigurationTests.mm; sourceTree = "<group>"; };
@@ -1982,7 +1985,7 @@
353D23951D0B0DFE002BE09D /* MGLAnnotationViewTests.m */,
DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */,
DA35A2C31CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m */,
- 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */,
+ 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.mm */,
DA35A2C41CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m */,
DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */,
3598544C1E1D38AA00B29F84 /* MGLDistanceFormatterTests.m */,
@@ -2207,30 +2210,31 @@
DAD165811CF4CFC4001FF4B9 /* Geometry */ = {
isa = PBXGroup;
children = (
+ CA65C4F721E9BB080068B0D4 /* MGLCluster.h */,
DA8847E01CBAFA5100AB86E3 /* MGLAnnotation.h */,
- DAD165691CF41981001FF4B9 /* MGLFeature.h */,
DAD1656A1CF41981001FF4B9 /* MGLFeature_Private.h */,
+ DAD165691CF41981001FF4B9 /* MGLFeature.h */,
DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */,
- DA8847E11CBAFA5100AB86E3 /* MGLGeometry.h */,
DA8848011CBAFA6200AB86E3 /* MGLGeometry_Private.h */,
+ DA8847E11CBAFA5100AB86E3 /* MGLGeometry.h */,
DA8848021CBAFA6200AB86E3 /* MGLGeometry.mm */,
- DA8847E31CBAFA5100AB86E3 /* MGLMultiPoint.h */,
DA8848041CBAFA6200AB86E3 /* MGLMultiPoint_Private.h */,
+ DA8847E31CBAFA5100AB86E3 /* MGLMultiPoint.h */,
DA8848051CBAFA6200AB86E3 /* MGLMultiPoint.mm */,
DA8847E71CBAFA5100AB86E3 /* MGLOverlay.h */,
DA8847E81CBAFA5100AB86E3 /* MGLPointAnnotation.h */,
DA88480B1CBAFA6200AB86E3 /* MGLPointAnnotation.mm */,
- 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */,
4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */,
+ 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */,
4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */,
- DA8847E91CBAFA5100AB86E3 /* MGLPolygon.h */,
9654C1271FFC1CC000DB6A19 /* MGLPolygon_Private.h */,
+ DA8847E91CBAFA5100AB86E3 /* MGLPolygon.h */,
DA88480C1CBAFA6200AB86E3 /* MGLPolygon.mm */,
- DA8847EA1CBAFA5100AB86E3 /* MGLPolyline.h */,
9654C1251FFC1AB900DB6A19 /* MGLPolyline_Private.h */,
+ DA8847EA1CBAFA5100AB86E3 /* MGLPolyline.h */,
DA88480D1CBAFA6200AB86E3 /* MGLPolyline.mm */,
- DA8847EB1CBAFA5100AB86E3 /* MGLShape.h */,
40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */,
+ DA8847EB1CBAFA5100AB86E3 /* MGLShape.h */,
DA88480E1CBAFA6200AB86E3 /* MGLShape.mm */,
DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */,
DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.mm */,
@@ -2351,6 +2355,7 @@
DA88483A1CBAFB8500AB86E3 /* MGLAnnotationImage.h in Headers */,
74CB5EBD219B280400102936 /* MGLFillStyleLayer_Private.h in Headers */,
DAF2571B201901E200367EF5 /* MGLHillshadeStyleLayer.h in Headers */,
+ CA65C4F821E9BB080068B0D4 /* MGLCluster.h in Headers */,
DA35A2BB1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h in Headers */,
353933FE1D3FB7DD003F57D7 /* MGLSymbolStyleLayer.h in Headers */,
DA8848201CBAFA6200AB86E3 /* MGLOfflinePack_Private.h in Headers */,
@@ -2571,6 +2576,7 @@
071BBB041EE76147001FB02A /* MGLImageSource.h in Headers */,
74CB5EC0219B280400102936 /* MGLHeatmapStyleLayer_Private.h in Headers */,
74CB5ECB219B285000102936 /* MGLLineStyleLayer_Private.h in Headers */,
+ CA65C4F921E9BB080068B0D4 /* MGLCluster.h in Headers */,
DABFB8611CBE99E500D62B32 /* MGLMultiPoint.h in Headers */,
74CB5ECD219B285000102936 /* MGLOpenGLStyleLayer_Private.h in Headers */,
74CB5ECF219B285000102936 /* MGLRasterStyleLayer_Private.h in Headers */,
@@ -3080,7 +3086,7 @@
170C437D2029D97900863DF0 /* MGLHeatmapStyleLayerTests.mm in Sources */,
170C437C2029D96F00863DF0 /* MGLHeatmapColorTests.mm in Sources */,
357579801D501E09000B822E /* MGLFillStyleLayerTests.mm in Sources */,
- 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */,
+ 35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.mm in Sources */,
DA1F8F3D1EBD287B00367E42 /* MGLDocumentationGuideTests.swift in Sources */,
076171C32139C70900668A35 /* MGLMapViewTests.m in Sources */,
3598544D1E1D38AA00B29F84 /* MGLDistanceFormatterTests.m in Sources */,
diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml
index 184d7cbd76..31381650da 100644
--- a/platform/ios/jazzy.yml
+++ b/platform/ios/jazzy.yml
@@ -69,12 +69,14 @@ custom_categories:
children:
- MGLFeature
- MGLPointFeature
+ - MGLPointFeatureCluster
- MGLPolygonFeature
- MGLPolylineFeature
- MGLMultiPolygonFeature
- MGLMultiPolylineFeature
- MGLPointCollectionFeature
- MGLShapeCollectionFeature
+ - MGLEmptyFeature
- name: Style Content
children:
- MGLSource
diff --git a/platform/ios/sdk-files.json b/platform/ios/sdk-files.json
index 31eebb0980..0bf09e48fa 100644
--- a/platform/ios/sdk-files.json
+++ b/platform/ios/sdk-files.json
@@ -136,6 +136,7 @@
"MGLFillStyleLayer.h": "platform/darwin/src/MGLFillStyleLayer.h",
"MGLAnnotationImage.h": "platform/ios/src/MGLAnnotationImage.h",
"MGLHillshadeStyleLayer.h": "platform/darwin/src/MGLHillshadeStyleLayer.h",
+ "MGLCluster.h": "platform/darwin/src/MGLCluster.h",
"MGLClockDirectionFormatter.h": "platform/darwin/src/MGLClockDirectionFormatter.h",
"MGLSymbolStyleLayer.h": "platform/darwin/src/MGLSymbolStyleLayer.h",
"MGLAttributionInfo.h": "platform/darwin/src/MGLAttributionInfo.h",
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index 38da38c47f..829583be6a 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -14,6 +14,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLAnnotationImage.h"
#import "MGLCalloutView.h"
#import "MGLClockDirectionFormatter.h"
+#import "MGLCluster.h"
#import "MGLCompassDirectionFormatter.h"
#import "MGLCoordinateFormatter.h"
#import "MGLDistanceFormatter.h"
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 11908f0f18..28ff0fc453 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -4,6 +4,8 @@
* Added an `MGLStyle.performsPlacementTransitions` property to control how long it takes for colliding labels to fade out. ([#13565](https://github.com/mapbox/mapbox-gl-native/pull/13565))
* Fixed a crash when casting large numbers in `NSExpression`. ([#13580](https://github.com/mapbox/mapbox-gl-native/pull/13580))
+* Added the `-[MGLShapeSource leavesOfCluster:offset:limit:]`, `-[MGLShapeSource childrenOfCluster:]`, `-[MGLShapeSource zoomLevelForExpandingCluster:]` methods for inspecting a cluster in an `MGLShapeSource`s created with the `MGLShapeSourceOptionClustered` option. Feature querying now returns clusters represented by `MGLPointFeatureCluster` objects (that conform to the `MGLCluster` protocol). ([#12952](https://github.com/mapbox/mapbox-gl-native/pull/12952)
+
## 0.13.0 - December 20, 2018
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 3cd807be7e..4773ae8249 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -31,7 +31,7 @@
1FC481852098F323000D09B4 /* NSPredicate+MGLPrivateAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC481842098F323000D09B4 /* NSPredicate+MGLPrivateAdditions.h */; };
3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
3508EC651D749D39009B0EE4 /* NSExpression+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3508EC631D749D39009B0EE4 /* NSExpression+MGLAdditions.mm */; };
- 3526EABD1DF9B19800006B43 /* MGLCodingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3526EABC1DF9B19800006B43 /* MGLCodingTests.m */; };
+ 3526EABD1DF9B19800006B43 /* MGLCodingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3526EABC1DF9B19800006B43 /* MGLCodingTests.mm */; };
352742781D4C220900A1ECE6 /* MGLStyleValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742771D4C220900A1ECE6 /* MGLStyleValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
352742811D4C243B00A1ECE6 /* MGLSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3527427F1D4C243B00A1ECE6 /* MGLSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
352742821D4C243B00A1ECE6 /* MGLSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742801D4C243B00A1ECE6 /* MGLSource.mm */; };
@@ -119,6 +119,7 @@
9654C12B1FFC38E000DB6A19 /* MGLPolyline_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C12A1FFC38E000DB6A19 /* MGLPolyline_Private.h */; };
9654C12D1FFC394700DB6A19 /* MGLPolygon_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C12C1FFC394700DB6A19 /* MGLPolygon_Private.h */; };
96E027311E57C9A7004B8E66 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 96E027331E57C9A7004B8E66 /* Localizable.strings */; };
+ CA4045C7216720D700B356E1 /* MGLCluster.h in Headers */ = {isa = PBXBuildFile; fileRef = CA4045C4216720D700B356E1 /* MGLCluster.h */; settings = {ATTRIBUTES = (Public, ); }; };
CA8FBC0D21A4A74300D1203C /* MGLRendererConfigurationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA8FBC0C21A4A74300D1203C /* MGLRendererConfigurationTests.mm */; };
CA9461A620884CCB0015EB12 /* MGLAnnotationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9461A520884CCB0015EB12 /* MGLAnnotationTests.m */; };
DA00FC8A1D5EEAC3009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -342,7 +343,7 @@
1FC481842098F323000D09B4 /* NSPredicate+MGLPrivateAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPredicate+MGLPrivateAdditions.h"; sourceTree = "<group>"; };
3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSExpression+MGLAdditions.h"; sourceTree = "<group>"; };
3508EC631D749D39009B0EE4 /* NSExpression+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSExpression+MGLAdditions.mm"; sourceTree = "<group>"; };
- 3526EABC1DF9B19800006B43 /* MGLCodingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCodingTests.m; path = ../../darwin/test/MGLCodingTests.m; sourceTree = "<group>"; };
+ 3526EABC1DF9B19800006B43 /* MGLCodingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLCodingTests.mm; path = ../../darwin/test/MGLCodingTests.mm; sourceTree = "<group>"; };
352742771D4C220900A1ECE6 /* MGLStyleValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleValue.h; sourceTree = "<group>"; };
3527427F1D4C243B00A1ECE6 /* MGLSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSource.h; sourceTree = "<group>"; };
352742801D4C243B00A1ECE6 /* MGLSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLSource.mm; sourceTree = "<group>"; };
@@ -444,6 +445,7 @@
96E027391E57C9B9004B8E66 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
96E0273A1E57C9BB004B8E66 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
96E0273B1E57C9BC004B8E66 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ CA4045C4216720D700B356E1 /* MGLCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCluster.h; sourceTree = "<group>"; };
CA8FBC0C21A4A74300D1203C /* MGLRendererConfigurationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLRendererConfigurationTests.mm; path = ../../darwin/test/MGLRendererConfigurationTests.mm; sourceTree = "<group>"; };
CA9461A520884CCB0015EB12 /* MGLAnnotationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLAnnotationTests.m; path = test/MGLAnnotationTests.m; sourceTree = SOURCE_ROOT; };
DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = "<group>"; };
@@ -1025,29 +1027,30 @@
isa = PBXGroup;
children = (
DAE6C34B1CC31E0400DB3429 /* MGLAnnotation.h */,
- DACC22121CF3D3E200D220D9 /* MGLFeature.h */,
+ CA4045C4216720D700B356E1 /* MGLCluster.h */,
DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */,
+ DACC22121CF3D3E200D220D9 /* MGLFeature.h */,
DACC22131CF3D3E200D220D9 /* MGLFeature.mm */,
- DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */,
DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */,
+ DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */,
DAE6C36D1CC31E2A00DB3429 /* MGLGeometry.mm */,
- DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */,
DAE6C36F1CC31E2A00DB3429 /* MGLMultiPoint_Private.h */,
+ DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */,
DAE6C3701CC31E2A00DB3429 /* MGLMultiPoint.mm */,
DAE6C3521CC31E0400DB3429 /* MGLOverlay.h */,
DAE6C3531CC31E0400DB3429 /* MGLPointAnnotation.h */,
DAE6C3761CC31E2A00DB3429 /* MGLPointAnnotation.mm */,
- 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */,
DAF0D80D1DFE0E5D00B28378 /* MGLPointCollection_Private.h */,
+ 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */,
4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */,
- DAE6C3541CC31E0400DB3429 /* MGLPolygon.h */,
9654C12C1FFC394700DB6A19 /* MGLPolygon_Private.h */,
+ DAE6C3541CC31E0400DB3429 /* MGLPolygon.h */,
DAE6C3771CC31E2A00DB3429 /* MGLPolygon.mm */,
- DAE6C3551CC31E0400DB3429 /* MGLPolyline.h */,
9654C12A1FFC38E000DB6A19 /* MGLPolyline_Private.h */,
+ DAE6C3551CC31E0400DB3429 /* MGLPolyline.h */,
DAE6C3781CC31E2A00DB3429 /* MGLPolyline.mm */,
- DAE6C3561CC31E0400DB3429 /* MGLShape.h */,
408AA85A1DAEECF100022900 /* MGLShape_Private.h */,
+ DAE6C3561CC31E0400DB3429 /* MGLShape.h */,
DAE6C3791CC31E2A00DB3429 /* MGLShape.mm */,
DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */,
DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.mm */,
@@ -1152,7 +1155,7 @@
DAEDC4311D6033F1000224FF /* MGLAttributionInfoTests.m */,
DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */,
DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */,
- 3526EABC1DF9B19800006B43 /* MGLCodingTests.m */,
+ 3526EABC1DF9B19800006B43 /* MGLCodingTests.mm */,
DA35A2B51CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m */,
DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */,
DA2987591E1A4290002299F5 /* MGLDocumentationExampleTests.swift */,
@@ -1348,6 +1351,7 @@
DAE6C3A61CC31E9400DB3429 /* MGLMapViewDelegate.h in Headers */,
DAE6C38B1CC31E2A00DB3429 /* MGLOfflinePack_Private.h in Headers */,
558DE7A61E56161C00C7916D /* MGLFoundation_Private.h in Headers */,
+ CA4045C7216720D700B356E1 /* MGLCluster.h in Headers */,
DACC22141CF3D3E200D220D9 /* MGLFeature.h in Headers */,
3538AA231D542685008EC33D /* MGLStyleLayer.h in Headers */,
DAE6C35C1CC31E0400DB3429 /* MGLGeometry.h in Headers */,
@@ -1712,7 +1716,7 @@
DAE7DEC41E24549F007505A6 /* MGLNSStringAdditionsTests.m in Sources */,
DA87A9981DC9D88400810D09 /* MGLShapeSourceTests.mm in Sources */,
55E2AD111E5B0A6900E8C587 /* MGLOfflineStorageTests.mm in Sources */,
- 3526EABD1DF9B19800006B43 /* MGLCodingTests.m in Sources */,
+ 3526EABD1DF9B19800006B43 /* MGLCodingTests.mm in Sources */,
DA87A9A21DC9DCF100810D09 /* MGLFillStyleLayerTests.mm in Sources */,
DA57D4B11EBC699800793288 /* MGLDocumentationGuideTests.swift in Sources */,
DAEDC4321D6033F1000224FF /* MGLAttributionInfoTests.m in Sources */,
@@ -2144,10 +2148,10 @@
"$(geometry_cflags)",
"$(geojson_cflags)",
);
- OTHER_LDFLAGS = (
- "$(mbgl_core_LINK_LIBRARIES)",
- "$(mbgl_filesource_LINK_LIBRARIES)",
- );
+ OTHER_LDFLAGS = (
+ "$(mbgl_core_LINK_LIBRARIES)",
+ "$(mbgl_filesource_LINK_LIBRARIES)",
+ );
OTHER_SWIFT_FLAGS = "-warnings-as-errors";
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -2176,10 +2180,10 @@
"$(geometry_cflags)",
"$(geojson_cflags)",
);
- OTHER_LDFLAGS = (
- "$(mbgl_core_LINK_LIBRARIES)",
- "$(mbgl_filesource_LINK_LIBRARIES)",
- );
+ OTHER_LDFLAGS = (
+ "$(mbgl_core_LINK_LIBRARIES)",
+ "$(mbgl_filesource_LINK_LIBRARIES)",
+ );
OTHER_SWIFT_FLAGS = "-warnings-as-errors";
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test;
PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/platform/macos/sdk-files.json b/platform/macos/sdk-files.json
index 884a925217..f7d2fd3426 100644
--- a/platform/macos/sdk-files.json
+++ b/platform/macos/sdk-files.json
@@ -118,6 +118,7 @@
"MGLTilePyramidOfflineRegion.h": "platform/darwin/src/MGLTilePyramidOfflineRegion.h",
"NSValue+MGLAdditions.h": "platform/darwin/src/NSValue+MGLAdditions.h",
"MGLMapViewDelegate.h": "platform/macos/src/MGLMapViewDelegate.h",
+ "MGLCluster.h": "platform/darwin/src/MGLCluster.h",
"MGLFeature.h": "platform/darwin/src/MGLFeature.h",
"MGLStyleLayer.h": "platform/darwin/src/MGLStyleLayer.h",
"MGLGeometry.h": "platform/darwin/src/MGLGeometry.h",
diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h
index 88ed0acb7a..0fd81a4df7 100644
--- a/platform/macos/src/Mapbox.h
+++ b/platform/macos/src/Mapbox.h
@@ -12,6 +12,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLAnnotation.h"
#import "MGLAnnotationImage.h"
#import "MGLClockDirectionFormatter.h"
+#import "MGLCluster.h"
#import "MGLCompassDirectionFormatter.h"
#import "MGLCoordinateFormatter.h"
#import "MGLDistanceFormatter.h"