[ios, osx] Holes in polygons
MGLPolygon (and by extension MGLMultiPolygon) now supports interior rings. The data is preserved in feature querying results, and interior rings are respected when adding polygon overlays to the map. Fixes #1729. [ios, osx] Updated changelog
This commit is contained in:
committed by
Minh Nguyễn
parent
4ab98387f1
commit
de905ab64c
@@ -171,33 +171,44 @@ class GeometryEvaluator {
|
||||
public:
|
||||
MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::point<T> &geometry) const {
|
||||
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
|
||||
feature.coordinate = coordinateFromPoint(geometry);
|
||||
feature.coordinate = coordinateFromPointGeometry(geometry);
|
||||
return feature;
|
||||
}
|
||||
|
||||
MGLShape <MGLFeaturePrivate> * 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);
|
||||
std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPointGeometry);
|
||||
|
||||
return [[MGLPolylineFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
return [MGLPolylineFeature polylineWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
}
|
||||
|
||||
MGLShape <MGLFeaturePrivate> * operator()(const mapbox::geometry::polygon<T> &geometry) const {
|
||||
// TODO: MGLPolygon doesn’t support holes, so what to do?
|
||||
auto &linearRing = geometry.front();
|
||||
|
||||
auto &outerRing = geometry.front();
|
||||
std::vector<CLLocationCoordinate2D> coordinates;
|
||||
coordinates.reserve(linearRing.size());
|
||||
std::transform(linearRing.begin(), linearRing.end(), std::back_inserter(coordinates), coordinateFromPoint);
|
||||
coordinates.reserve(outerRing.size());
|
||||
std::transform(outerRing.begin(), outerRing.end(), std::back_inserter(coordinates), coordinateFromPointGeometry);
|
||||
|
||||
return [[MGLPolygonFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
NSMutableArray *innerPolygons;
|
||||
if (geometry.size() > 1) {
|
||||
innerPolygons = [NSMutableArray arrayWithCapacity:geometry.size() - 1];
|
||||
for (auto iter = geometry.begin() + 1; iter != geometry.end(); iter++) {
|
||||
auto &innerRing = *iter;
|
||||
std::vector<CLLocationCoordinate2D> coordinates;
|
||||
coordinates.reserve(innerRing.size());
|
||||
std::transform(innerRing.begin(), innerRing.end(), std::back_inserter(coordinates), coordinateFromPointGeometry);
|
||||
MGLPolygon *innerPolygon = [MGLPolygon polygonWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
[innerPolygons addObject:innerPolygon];
|
||||
}
|
||||
}
|
||||
|
||||
return [MGLPolygonFeature polygonWithCoordinates:&coordinates[0] count:coordinates.size() interiorPolygons:innerPolygons];
|
||||
}
|
||||
|
||||
MGLShape <MGLFeaturePrivate> * 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);
|
||||
std::transform(geometry.begin(), geometry.end(), std::back_inserter(coordinates), coordinateFromPointGeometry);
|
||||
|
||||
return [[MGLMultiPointFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
}
|
||||
@@ -207,7 +218,7 @@ public:
|
||||
for (auto &lineString : geometry) {
|
||||
std::vector<CLLocationCoordinate2D> coordinates;
|
||||
coordinates.reserve(lineString.size());
|
||||
std::transform(lineString.begin(), lineString.end(), std::back_inserter(coordinates), coordinateFromPoint);
|
||||
std::transform(lineString.begin(), lineString.end(), std::back_inserter(coordinates), coordinateFromPointGeometry);
|
||||
|
||||
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
[polylines addObject:polyline];
|
||||
@@ -219,14 +230,25 @@ public:
|
||||
MGLShape <MGLFeaturePrivate> * 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);
|
||||
std::transform(linearRing.begin(), linearRing.end(), std::back_inserter(coordinates), coordinateFromPointGeometry);
|
||||
|
||||
MGLPolygon *polygonObject = [MGLPolygon polygonWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
NSMutableArray *innerPolygons;
|
||||
if (polygon.size() > 1) {
|
||||
innerPolygons = [NSMutableArray arrayWithCapacity:polygon.size() - 1];
|
||||
for (auto iter = polygon.begin() + 1; iter != polygon.end(); iter++) {
|
||||
auto &innerRing = *iter;
|
||||
std::vector<CLLocationCoordinate2D> coordinates;
|
||||
coordinates.reserve(innerRing.size());
|
||||
std::transform(innerRing.begin(), innerRing.end(), std::back_inserter(coordinates), coordinateFromPointGeometry);
|
||||
MGLPolygon *innerPolygon = [MGLPolygon polygonWithCoordinates:&coordinates[0] count:coordinates.size()];
|
||||
[innerPolygons addObject:innerPolygon];
|
||||
}
|
||||
}
|
||||
|
||||
MGLPolygon *polygonObject = [MGLPolygon polygonWithCoordinates:&coordinates[0] count:coordinates.size() interiorPolygons:innerPolygons];
|
||||
[polygons addObject:polygonObject];
|
||||
}
|
||||
|
||||
@@ -245,7 +267,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static CLLocationCoordinate2D coordinateFromPoint(const mapbox::geometry::point<T> &point) {
|
||||
static CLLocationCoordinate2D coordinateFromPointGeometry(const mapbox::geometry::point<T> &point) {
|
||||
return CLLocationCoordinate2DMake(point.y, point.x);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,7 +17,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface MGLMultiPoint : MGLShape
|
||||
|
||||
/** The number of points associated with the shape. (read-only) */
|
||||
/** The array of coordinates associated with the shape. */
|
||||
@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates NS_RETURNS_INNER_POINTER;
|
||||
|
||||
/** The number of coordinates associated with the shape. (read-only) */
|
||||
@property (nonatomic, readonly) NSUInteger pointCount;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,6 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
|
||||
|
||||
@implementation MGLMultiPoint
|
||||
{
|
||||
CLLocationCoordinate2D *_coords;
|
||||
size_t _count;
|
||||
MGLCoordinateBounds _bounds;
|
||||
}
|
||||
@@ -27,13 +26,13 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
|
||||
if (self)
|
||||
{
|
||||
_count = count;
|
||||
_coords = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D));
|
||||
_coordinates = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D));
|
||||
|
||||
mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
|
||||
|
||||
for (NSUInteger i = 0; i < _count; i++)
|
||||
{
|
||||
_coords[i] = coords[i];
|
||||
_coordinates[i] = coords[i];
|
||||
bounds.extend(mbgl::LatLng(coords[i].latitude, coords[i].longitude));
|
||||
}
|
||||
|
||||
@@ -45,7 +44,7 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(_coords);
|
||||
free(_coordinates);
|
||||
}
|
||||
|
||||
- (CLLocationCoordinate2D)coordinate
|
||||
@@ -59,7 +58,7 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
|
||||
|
||||
assert(_count > 0);
|
||||
|
||||
return CLLocationCoordinate2DMake(_coords[0].latitude, _coords[0].longitude);
|
||||
return CLLocationCoordinate2DMake(_coordinates[0].latitude, _coordinates[0].longitude);
|
||||
}
|
||||
|
||||
- (NSUInteger)pointCount
|
||||
@@ -89,7 +88,7 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
|
||||
|
||||
for (NSUInteger i = range.location; i < range.location + range.length; i++)
|
||||
{
|
||||
coords[index] = _coords[i];
|
||||
coords[index] = _coordinates[i];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
@@ -104,24 +103,16 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
|
||||
return MGLLatLngBoundsFromCoordinateBounds(_bounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
|
||||
}
|
||||
|
||||
- (void)addShapeAnnotationObjectToCollection:(std::vector<mbgl::ShapeAnnotation> &)shapes withDelegate:(id <MGLMultiPointDelegate>)delegate {
|
||||
- (mbgl::AnnotationSegments)annotationSegments {
|
||||
NSUInteger count = self.pointCount;
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D *)malloc(count * sizeof(CLLocationCoordinate2D));
|
||||
NSAssert(coordinates, @"Unable to allocate annotation with %lu points", (unsigned long)count);
|
||||
[self getCoordinates:coordinates range:NSMakeRange(0, count)];
|
||||
CLLocationCoordinate2D *coordinates = self.coordinates;
|
||||
|
||||
mbgl::AnnotationSegment segment;
|
||||
segment.reserve(count);
|
||||
for (NSUInteger i = 0; i < count; i++) {
|
||||
segment.push_back(MGLLatLngFromLocationCoordinate2D(coordinates[i]));
|
||||
}
|
||||
free(coordinates);
|
||||
shapes.emplace_back(mbgl::AnnotationSegments {{ segment }},
|
||||
[self shapeAnnotationPropertiesObjectWithDelegate:delegate]);
|
||||
return { segment };
|
||||
}
|
||||
|
||||
- (mbgl::ShapeAnnotation::Properties)shapeAnnotationPropertiesObjectWithDelegate:(__unused id <MGLMultiPointDelegate>)delegate {
|
||||
|
||||
@@ -21,8 +21,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
|
||||
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds;
|
||||
|
||||
/** Adds a shape annotation to the given vector by asking the delegate for style values. */
|
||||
- (void)addShapeAnnotationObjectToCollection:(std::vector<mbgl::ShapeAnnotation> &)shapes withDelegate:(id <MGLMultiPointDelegate>)delegate;
|
||||
/** Returns the shape’s annotation segments. */
|
||||
- (mbgl::AnnotationSegments)annotationSegments;
|
||||
|
||||
/** Constructs a shape annotation properties object by asking the delegate for style values. */
|
||||
- (mbgl::ShapeAnnotation::Properties)shapeAnnotationPropertiesObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate;
|
||||
|
||||
@@ -16,6 +16,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface MGLPolygon : MGLMultiPoint <MGLOverlay>
|
||||
|
||||
/**
|
||||
The array of polygons nested inside the receiver.
|
||||
|
||||
The area occupied by any interior polygons is excluded from the overall shape.
|
||||
Interior polygons should not overlap. An interior polygon should not have
|
||||
interior polygons of its own.
|
||||
|
||||
If there are no interior polygons, the value of this property is `nil`.
|
||||
*/
|
||||
@property (nonatomic, nullable, readonly) NS_ARRAY_OF(MGLPolygon *) *interiorPolygons;
|
||||
|
||||
/**
|
||||
Creates and returns an `MGLPolygon` object from the specified set of
|
||||
coordinates.
|
||||
@@ -25,8 +36,21 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@param count The number of items in the `coords` array.
|
||||
@return A new polygon object.
|
||||
*/
|
||||
+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords
|
||||
count:(NSUInteger)count;
|
||||
+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
|
||||
|
||||
/**
|
||||
Creates and returns an `MGLPolygon` object from the specified set of
|
||||
coordinates and interior polygons.
|
||||
|
||||
@param coords The array of coordinates defining the shape. The data in this
|
||||
array is copied to the new object.
|
||||
@param count The number of items in the `coords` array.
|
||||
@param interiorPolygons An array of `MGLPolygon` objects that define regions
|
||||
excluded from the overall shape. If this array is `nil` or empty, the shape
|
||||
is considered to have no interior polygons.
|
||||
@return A new polygon object.
|
||||
*/
|
||||
+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(nullable NS_ARRAY_OF(MGLPolygon *) *)interiorPolygons;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -7,10 +7,30 @@
|
||||
|
||||
@dynamic overlayBounds;
|
||||
|
||||
+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords
|
||||
count:(NSUInteger)count
|
||||
{
|
||||
return [[self alloc] initWithCoordinates:coords count:count];
|
||||
+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count {
|
||||
return [self polygonWithCoordinates:coords count:count interiorPolygons:nil];
|
||||
}
|
||||
|
||||
+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray<MGLPolygon *> *)interiorPolygons {
|
||||
return [[self alloc] initWithCoordinates:coords count:count interiorPolygons:interiorPolygons];
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray<MGLPolygon *> *)interiorPolygons {
|
||||
if (self = [super initWithCoordinates:coords count:count]) {
|
||||
if (interiorPolygons.count) {
|
||||
_interiorPolygons = interiorPolygons;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (mbgl::AnnotationSegments)annotationSegments {
|
||||
auto segments = super.annotationSegments;
|
||||
for (MGLPolygon *polygon in self.interiorPolygons) {
|
||||
auto interiorSegments = polygon.annotationSegments;
|
||||
segments.push_back(interiorSegments.front());
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
|
||||
- (mbgl::ShapeAnnotation::Properties)shapeAnnotationPropertiesObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
|
||||
|
||||
@@ -23,10 +23,16 @@
|
||||
|
||||
mapbox::geometry::polygon<double> polygon = {
|
||||
{
|
||||
{ -77.0325453144239, 38.9131982 },
|
||||
{ -122.4135302, 37.7757368 },
|
||||
{ 77.6368034, 12.9810816 },
|
||||
{ -74.2178961777998, -13.15589555 },
|
||||
{ 1, 1 },
|
||||
{ 4, 1 },
|
||||
{ 4, 4 },
|
||||
{ 1, 4 },
|
||||
},
|
||||
{
|
||||
{ 2, 2 },
|
||||
{ 3, 2 },
|
||||
{ 3, 3 },
|
||||
{ 2, 3 },
|
||||
},
|
||||
};
|
||||
features.emplace_back(polygon);
|
||||
@@ -52,6 +58,30 @@
|
||||
MGLPolygonFeature *polygonShape = (MGLPolygonFeature *)shapes[2];
|
||||
XCTAssertTrue([polygonShape isKindOfClass:[MGLPolygonFeature class]]);
|
||||
XCTAssertEqual(polygonShape.pointCount, 4);
|
||||
CLLocationCoordinate2D *polygonCoordinates = polygonShape.coordinates;
|
||||
XCTAssertNotEqual(polygonCoordinates, nil);
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:polygonCoordinates[0]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(1, 1)]);
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:polygonCoordinates[1]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(1, 4)]);
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:polygonCoordinates[2]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(4, 4)]);
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:polygonCoordinates[3]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(4, 1)]);
|
||||
NS_ARRAY_OF(MGLPolygon *) *interiorPolygons = polygonShape.interiorPolygons;
|
||||
XCTAssertEqual(interiorPolygons.count, 1);
|
||||
MGLPolygon *interiorPolygon = interiorPolygons.firstObject;
|
||||
XCTAssertEqual(interiorPolygon.pointCount, 4);
|
||||
CLLocationCoordinate2D interiorPolygonCoordinates[4];
|
||||
[interiorPolygon getCoordinates:interiorPolygonCoordinates range:NSMakeRange(0, interiorPolygon.pointCount)];
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:interiorPolygonCoordinates[0]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(2, 2)]);
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:interiorPolygonCoordinates[1]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(2, 3)]);
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:interiorPolygonCoordinates[2]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(3, 3)]);
|
||||
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:interiorPolygonCoordinates[3]],
|
||||
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(3, 2)]);
|
||||
}
|
||||
|
||||
- (void)testPropertyConversion {
|
||||
|
||||
@@ -10,7 +10,8 @@ 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))
|
||||
- Added methods to MGLMapView for obtaining the underlying map data rendered by the current style, along with additional classes to represent complex geometry in that data. ([#5110](https://github.com/mapbox/mapbox-gl-native/pull/5110))
|
||||
- An MGLPolygon can now have interior polygons, representing holes knocked out of the overall shape. ([#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))
|
||||
|
||||
@@ -306,6 +306,22 @@ static NSString * const MBXViewControllerAnnotationViewReuseIdentifer = @"MBXVie
|
||||
|
||||
free(polygonCoordinates);
|
||||
}
|
||||
|
||||
CLLocationCoordinate2D innerCoordinates[] = {
|
||||
CLLocationCoordinate2DMake(-5, -5),
|
||||
CLLocationCoordinate2DMake(-5, 5),
|
||||
CLLocationCoordinate2DMake(5, 5),
|
||||
CLLocationCoordinate2DMake(5, -5),
|
||||
};
|
||||
MGLPolygon *innerPolygon = [MGLPolygon polygonWithCoordinates:innerCoordinates count:sizeof(innerCoordinates) / sizeof(innerCoordinates[0])];
|
||||
CLLocationCoordinate2D outerCoordinates[] = {
|
||||
CLLocationCoordinate2DMake(-10, -20),
|
||||
CLLocationCoordinate2DMake(-10, 10),
|
||||
CLLocationCoordinate2DMake(10, 10),
|
||||
CLLocationCoordinate2DMake(10, -10),
|
||||
};
|
||||
MGLPolygon *outerPolygon = [MGLPolygon polygonWithCoordinates:outerCoordinates count:sizeof(outerCoordinates) / sizeof(outerCoordinates[0]) interiorPolygons:@[innerPolygon]];
|
||||
[self.mapView addAnnotation:outerPolygon];
|
||||
}
|
||||
else if (buttonIndex == actionSheet.firstOtherButtonIndex + 10)
|
||||
{
|
||||
|
||||
@@ -2812,7 +2812,12 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
|
||||
|
||||
if ([annotation isKindOfClass:[MGLMultiPoint class]])
|
||||
{
|
||||
[(MGLMultiPoint *)annotation addShapeAnnotationObjectToCollection:shapes withDelegate:self];
|
||||
// The multipoint knows how to style itself (with the map view’s help).
|
||||
MGLMultiPoint *multiPoint = (MGLMultiPoint *)annotation;
|
||||
if (!multiPoint.pointCount) {
|
||||
continue;
|
||||
}
|
||||
shapes.emplace_back(multiPoint.annotationSegments, [multiPoint shapeAnnotationPropertiesObjectWithDelegate:self]);
|
||||
[userShapes addObject:annotation];
|
||||
}
|
||||
else if ([annotation isKindOfClass:[MGLMultiPolyline class]])
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
## 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))
|
||||
* Added methods to MGLMapView for obtaining the underlying map data rendered by the current style, along with additional classes to represent complex geometry in that data. ([#5110](https://github.com/mapbox/mapbox-gl-native/pull/5110))
|
||||
* An MGLPolygon can now have interior polygons, representing holes knocked out of the overall shape. ([#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))
|
||||
|
||||
@@ -1615,7 +1615,11 @@ public:
|
||||
|
||||
if ([annotation isKindOfClass:[MGLMultiPoint class]]) {
|
||||
// The multipoint knows how to style itself (with the map view’s help).
|
||||
[(MGLMultiPoint *)annotation addShapeAnnotationObjectToCollection:shapes withDelegate:self];
|
||||
MGLMultiPoint *multiPoint = (MGLMultiPoint *)annotation;
|
||||
if (!multiPoint.pointCount) {
|
||||
continue;
|
||||
}
|
||||
shapes.emplace_back(multiPoint.annotationSegments, [multiPoint shapeAnnotationPropertiesObjectWithDelegate: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.
|
||||
|
||||
@@ -88,21 +88,22 @@ void ShapeAnnotationImpl::updateTile(const CanonicalTileID& tileID, AnnotationTi
|
||||
const double tolerance = baseTolerance / (maxAmountOfTiles * util::EXTENT);
|
||||
|
||||
geojsonvt::ProjectedRings rings;
|
||||
std::vector<geojsonvt::LonLat> points;
|
||||
for (auto& segment : shape.segments) {
|
||||
std::vector<geojsonvt::LonLat> points;
|
||||
for (auto& latLng : segment) {
|
||||
const double constrainedLatitude = util::clamp(latLng.latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
|
||||
points.push_back(geojsonvt::LonLat(latLng.longitude, constrainedLatitude));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < shape.segments[0].size(); ++i) { // first segment for now (no holes)
|
||||
const double constrainedLatitude = util::clamp(shape.segments[0][i].latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
|
||||
points.push_back(geojsonvt::LonLat(shape.segments[0][i].longitude, constrainedLatitude));
|
||||
if (type == geojsonvt::ProjectedFeatureType::Polygon &&
|
||||
(points.front().lon != points.back().lon || points.front().lat != points.back().lat)) {
|
||||
points.push_back(geojsonvt::LonLat(points.front().lon, points.front().lat));
|
||||
}
|
||||
|
||||
auto ring = geojsonvt::Convert::projectRing(points, tolerance);
|
||||
rings.push_back(ring);
|
||||
}
|
||||
|
||||
if (type == geojsonvt::ProjectedFeatureType::Polygon &&
|
||||
(points.front().lon != points.back().lon || points.front().lat != points.back().lat)) {
|
||||
points.push_back(geojsonvt::LonLat(points.front().lon, points.front().lat));
|
||||
}
|
||||
|
||||
auto ring = geojsonvt::Convert::projectRing(points, tolerance);
|
||||
rings.push_back(ring);
|
||||
|
||||
std::vector<geojsonvt::ProjectedFeature> features;
|
||||
features.push_back(geojsonvt::Convert::create(geojsonvt::Tags(), type, rings));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user