summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
authorJustin R. Miller <incanus@users.noreply.github.com>2016-10-04 18:42:12 -0700
committerGitHub <noreply@github.com>2016-10-04 18:42:12 -0700
commit105673efc1c59e19f5352fb770405aa591cdebeb (patch)
tree7b57c89ad346a4e62c60c404338d0b34853ad02b /platform/darwin
parent07315711d6b191a5812065bb76ab5beb33d995d9 (diff)
downloadqtlocation-mapboxgl-105673efc1c59e19f5352fb770405aa591cdebeb.tar.gz
[ios, macos] fixes #6160: allow updating multipoint coordinates (#6565)
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/src/MGLMultiPoint.h26
-rw-r--r--platform/darwin/src/MGLMultiPoint.mm109
2 files changed, 96 insertions, 39 deletions
diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h
index 59d9cd9429..69c7295842 100644
--- a/platform/darwin/src/MGLMultiPoint.h
+++ b/platform/darwin/src/MGLMultiPoint.h
@@ -15,7 +15,15 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface MGLMultiPoint : MGLShape
-/** The array of coordinates associated with the shape. */
+/**
+ The array of coordinates associated with the shape.
+
+ This C array is a pointer to a structure inside the multipoint object,
+ which may have a lifetime shorter than the multipoint object and will
+ certainly not have a longer lifetime. Therefore, you should copy the C
+ array if it needs to be stored outside of the memory context in which you
+ use this property.
+ */
@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates NS_RETURNS_INNER_POINTER;
/** The number of coordinates associated with the shape. (read-only) */
@@ -35,6 +43,22 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range;
+/**
+ Updates one or more coordinates for the shape, which will instantaneously
+ cause the shape to be redrawn if it is currently visible on the map.
+
+ @param range The range of points to update. The `location` field indicates the
+ first point you are replacing, with `0` being the first point, `1` being
+ the second point, and so on. The `length` field indicates the number of
+ points to update. You can append to an existing array of coordinates
+ by specifying a range with a `location` at the end of the existing array
+ and/or a `length` which extends past the end of the existing array. The array
+ in _`coords`_ must be equal in number to the length of the range.
+ @param coords The array of coordinates defining the shape. The data in this
+ array is copied to the object.
+ */
+- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(CLLocationCoordinate2D *)coords;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm
index a5b9eb8efc..17a61ed081 100644
--- a/platform/darwin/src/MGLMultiPoint.mm
+++ b/platform/darwin/src/MGLMultiPoint.mm
@@ -1,12 +1,12 @@
#import "MGLMultiPoint_Private.h"
#import "MGLGeometry_Private.h"
+#import "MGLTypes.h"
#import <mbgl/util/geo.hpp>
-mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
- if (!cgColor) {
- return { 0, 0, 0, 0 };
- }
+mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor)
+{
+ if (!cgColor) return { 0, 0, 0, 0 };
NSCAssert(CGColorGetNumberOfComponents(cgColor) >= 4, @"Color must have at least 4 components");
const CGFloat *components = CGColorGetComponents(cgColor);
return { (float)components[0], (float)components[1], (float)components[2], (float)components[3] };
@@ -18,28 +18,34 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
MGLCoordinateBounds _bounds;
}
-- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords
- count:(NSUInteger)count
+- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
{
self = [super init];
if (self)
{
- _count = count;
- _coordinates = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D));
+ [self setupWithCoordinates:coords count:count];
+ }
- mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
+ return self;
+}
- for (NSUInteger i = 0; i < _count; i++)
- {
- _coordinates[i] = coords[i];
- bounds.extend(mbgl::LatLng(coords[i].latitude, coords[i].longitude));
- }
+- (void)setupWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
+{
+ if (_coordinates) free(_coordinates);
+
+ _count = count;
+ _coordinates = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D));
- _bounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
+ mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
+
+ for (NSUInteger i = 0; i < _count; i++)
+ {
+ _coordinates[i] = coords[i];
+ bounds.extend(mbgl::LatLng(coords[i].latitude, coords[i].longitude));
}
- return self;
+ _bounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
}
- (void)dealloc
@@ -49,13 +55,6 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
- (CLLocationCoordinate2D)coordinate
{
- if ([self isMemberOfClass:[MGLMultiPoint class]])
- {
- [[NSException exceptionWithName:@"MGLAbstractClassException"
- reason:@"MGLMultiPoint is an abstract class"
- userInfo:nil] raise];
- }
-
assert(_count > 0);
return CLLocationCoordinate2DMake(_coordinates[0].latitude, _coordinates[0].longitude);
@@ -63,27 +62,23 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
- (NSUInteger)pointCount
{
- if ([self isMemberOfClass:[MGLMultiPoint class]])
- {
- [[NSException exceptionWithName:@"MGLAbstractClassException"
- reason:@"MGLMultiPoint is an abstract class"
- userInfo:nil] raise];
- }
-
return _count;
}
++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingPointCount
+{
+ return [NSSet setWithObjects:@"coordinates", nil];
+}
+
- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range
{
- if ([self isMemberOfClass:[MGLMultiPoint class]])
+ if (range.location + range.length > _count)
{
- [[NSException exceptionWithName:@"MGLAbstractClassException"
- reason:@"MGLMultiPoint is an abstract class"
- userInfo:nil] raise];
+ [NSException raise:NSRangeException
+ format:@"Invalid coordinate range %@ extends beyond current coordinate count of %zu",
+ NSStringFromRange(range), _count];
}
- assert(range.location + range.length <= _count);
-
NSUInteger index = 0;
for (NSUInteger i = range.location; i < range.location + range.length; i++)
@@ -93,6 +88,43 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
}
}
+- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(CLLocationCoordinate2D *)coords
+{
+ if ((coords >= _coordinates && coords < _coordinates + _count) ||
+ (coords + range.length >= _coordinates && coords + range.length < _coordinates + _count))
+ {
+ [NSException raise:NSRangeException format:@"Reuse of existing coordinates array %p not supported", coords];
+ }
+ else if (range.length == 0)
+ {
+ [NSException raise:NSRangeException format:@"Empty coordinate range %@", NSStringFromRange(range)];
+ }
+ else if (range.location > _count)
+ {
+ [NSException raise:NSRangeException
+ format:@"Invalid range %@ for existing coordinate count %zu",
+ NSStringFromRange(range), _count];
+ }
+
+ [self willChangeValueForKey:@"coordinates"];
+ if (NSMaxRange(range) <= _count)
+ {
+ // replacing existing coordinate(s)
+ memcpy(_coordinates + range.location, coords, range.length * sizeof(CLLocationCoordinate2D));
+ }
+ else
+ {
+ // appending new coordinate(s)
+ NSUInteger newCount = NSMaxRange(range);
+ CLLocationCoordinate2D *newCoordinates = (CLLocationCoordinate2D *)malloc(newCount * sizeof(CLLocationCoordinate2D));
+ memcpy(newCoordinates, _coordinates, fmin(_count, range.location) * sizeof(CLLocationCoordinate2D));
+ memcpy(newCoordinates + range.location, coords, range.length * sizeof(CLLocationCoordinate2D));
+ [self setupWithCoordinates:newCoordinates count:newCount];
+ free(newCoordinates);
+ }
+ [self didChangeValueForKey:@"coordinates"];
+}
+
- (MGLCoordinateBounds)overlayBounds
{
return _bounds;
@@ -103,7 +135,8 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
return MGLLatLngBoundsFromCoordinateBounds(_bounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds));
}
-- (mbgl::Annotation)annotationObjectWithDelegate:(__unused id <MGLMultiPointDelegate>)delegate {
+- (mbgl::Annotation)annotationObjectWithDelegate:(__unused id <MGLMultiPointDelegate>)delegate
+{
NSAssert(NO, @"Cannot add an annotation from an instance of %@", NSStringFromClass([self class]));
return mbgl::SymbolAnnotation({mbgl::Point<double>()});
}
@@ -111,7 +144,7 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) {
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; count = %lu; bounds = %@>",
- NSStringFromClass([self class]), (void *)self, (unsigned long)_count, MGLStringFromCoordinateBounds(_bounds)];
+ NSStringFromClass([self class]), (void *)self, (unsigned long)_count, MGLStringFromCoordinateBounds(_bounds)];
}
@end