diff options
Diffstat (limited to 'platform/ios')
-rw-r--r-- | platform/ios/MGLMapView.mm | 139 | ||||
-rw-r--r-- | platform/ios/MGLMultiPoint.mm | 102 | ||||
-rw-r--r-- | platform/ios/MGLMultiPoint_Private.h | 8 | ||||
-rw-r--r-- | platform/ios/MGLPointAnnotation.m | 7 | ||||
-rw-r--r-- | platform/ios/MGLPolygon.m | 15 | ||||
-rw-r--r-- | platform/ios/MGLPolyline.m | 15 | ||||
-rw-r--r-- | platform/ios/MGLShape.m | 14 |
7 files changed, 280 insertions, 20 deletions
diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 4ef63d4bf8..63e3b516ab 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -1015,7 +1015,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) tapBounds.extend(MGLLatLngFromLocationCoordinate2D(coordinate)); // query for nearby annotations - std::vector<uint32_t> nearbyAnnotations = _mbglMap->getAnnotationsInBounds(tapBounds); + std::vector<uint32_t> nearbyAnnotations = _mbglMap->getAnnotationsInBounds(tapBounds, mbgl::AnnotationType::Point); int32_t newSelectedAnnotationID = -1; @@ -1669,36 +1669,131 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) { if ( ! annotations) return; - std::vector<mbgl::LatLng> latLngs; - latLngs.reserve(annotations.count); - + std::vector<mbgl::LatLng> points; std::vector<std::string> symbols; - symbols.reserve(annotations.count); + + std::vector<mbgl::AnnotationSegments> shapes; + std::vector<mbgl::StyleProperties> shapesProperties; BOOL delegateImplementsSymbolLookup = [self.delegate respondsToSelector:@selector(mapView:symbolNameForAnnotation:)]; + BOOL delegateImplementsAlphaForShape = [self.delegate respondsToSelector:@selector(mapView:alphaForShapeAnnotation:)]; + BOOL delegateImplementsStrokeColorForShape = [self.delegate respondsToSelector:@selector(mapView:strokeColorForShapeAnnotation:)]; + BOOL delegateImplementsFillColorForPolygon = [self.delegate respondsToSelector:@selector(mapView:fillColorForPolygonAnnotation:)]; + BOOL delegateImplementsLineWidthForPolyline = [self.delegate respondsToSelector:@selector(mapView:lineWidthForPolylineAnnotation:)]; for (id <MGLAnnotation> annotation in annotations) { assert([annotation conformsToProtocol:@protocol(MGLAnnotation)]); - latLngs.push_back(MGLLatLngFromLocationCoordinate2D(annotation.coordinate)); + if ([annotation isKindOfClass:[MGLMultiPoint class]]) + { + CGFloat alpha = (delegateImplementsAlphaForShape ? + [self.delegate mapView:self alphaForShapeAnnotation:annotation] : + 1.0); - NSString *symbolName = nil; + UIColor *strokeColor = (delegateImplementsStrokeColorForShape ? + [self.delegate mapView:self strokeColorForShapeAnnotation:annotation] : + [UIColor blackColor]); - if (delegateImplementsSymbolLookup) - { - symbolName = [self.delegate mapView:self symbolNameForAnnotation:annotation]; + assert(strokeColor); + + CGFloat r,g,b,a; + [strokeColor getRed:&r green:&g blue:&b alpha:&a]; + mbgl::Color strokeNativeColor({{ (float)r, (float)g, (float)b, (float)a }}); + + mbgl::StyleProperties shapeProperties; + + if ([annotation isKindOfClass:[MGLPolyline class]]) + { + CGFloat lineWidth = (delegateImplementsLineWidthForPolyline ? + [self.delegate mapView:self lineWidthForPolylineAnnotation:(MGLPolyline *)annotation] : + 3.0); + + mbgl::LineProperties lineProperties; + lineProperties.opacity = alpha; + lineProperties.color = strokeNativeColor; + lineProperties.width = lineWidth; + shapeProperties.set<mbgl::LineProperties>(lineProperties); + + } + else if ([annotation isKindOfClass:[MGLPolygon class]]) + { + UIColor *fillColor = (delegateImplementsFillColorForPolygon ? + [self.delegate mapView:self fillColorForPolygonAnnotation:(MGLPolygon *)annotation] : + [UIColor blueColor]); + + assert(fillColor); + + [fillColor getRed:&r green:&g blue:&b alpha:&a]; + mbgl::Color fillNativeColor({{ (float)r, (float)g, (float)b, (float)a }}); + + mbgl::FillProperties fillProperties; + fillProperties.opacity = alpha; + fillProperties.stroke_color = strokeNativeColor; + fillProperties.fill_color = fillNativeColor; + shapeProperties.set<mbgl::FillProperties>(fillProperties); + } + else + { + [[NSException exceptionWithName:@"MGLUnknownShapeClassException" + reason:[NSString stringWithFormat:@"%@ is an unknown shape class", [annotation class]] + userInfo:nil] raise]; + } + + shapesProperties.push_back(shapeProperties); + + NSUInteger count = [(MGLMultiPoint *)annotation pointCount]; + + CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D *)malloc(count * sizeof(CLLocationCoordinate2D)); + [(MGLMultiPoint *)annotation getCoordinates:coordinates range:NSMakeRange(0, count)]; + + mbgl::AnnotationSegment shape; + shape.reserve(count); + + for (NSUInteger i = 0; i < count; i++) + { + shape.push_back(mbgl::LatLng(coordinates[i].latitude, coordinates[i].longitude)); + } + + free(coordinates); + + shapes.push_back({{ shape }}); } + else + { + points.push_back(MGLLatLngFromLocationCoordinate2D(annotation.coordinate)); + + NSString *symbolName = nil; - symbols.push_back((symbolName ? [symbolName UTF8String] : "")); + if (delegateImplementsSymbolLookup) + { + symbolName = [self.delegate mapView:self symbolNameForAnnotation:annotation]; + } + + symbols.push_back((symbolName ? [symbolName UTF8String] : "")); + } } - std::vector<uint32_t> annotationIDs = _mbglMap->addPointAnnotations(latLngs, symbols); + if (points.size()) + { + std::vector<uint32_t> pointAnnotationIDs = _mbglMap->addPointAnnotations(points, symbols); - for (size_t i = 0; i < annotationIDs.size(); ++i) + for (size_t i = 0; i < pointAnnotationIDs.size(); ++i) + { + [self.annotationIDsByAnnotation setObject:@{ MGLAnnotationIDKey : @(pointAnnotationIDs[i]) } + forKey:annotations[i]]; + } + } + + if (shapes.size()) { - [self.annotationIDsByAnnotation setObject:@{ MGLAnnotationIDKey : @(annotationIDs[i]) } - forKey:annotations[i]]; + std::vector<uint32_t> shapeAnnotationIDs = _mbglMap->addShapeAnnotations(shapes, shapesProperties); + + for (size_t i = 0; i < shapeAnnotationIDs.size(); ++i) + { + [self.annotationIDsByAnnotation setObject:@{ MGLAnnotationIDKey : @(shapeAnnotationIDs[i]) } + forKey:annotations[i]]; + } } } @@ -1750,6 +1845,8 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) assert([firstAnnotation conformsToProtocol:@protocol(MGLAnnotation)]); + if ([firstAnnotation isKindOfClass:[MGLMultiPoint class]]) return; + if ( ! [self viewportBounds].contains(MGLLatLngFromLocationCoordinate2D(firstAnnotation.coordinate))) return; [self selectAnnotation:firstAnnotation animated:NO]; @@ -1759,6 +1856,8 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) { if ( ! annotation) return; + if ([annotation isKindOfClass:[MGLMultiPoint class]]) return; + if ( ! [self viewportBounds].contains(MGLLatLngFromLocationCoordinate2D(annotation.coordinate))) return; if (annotation == self.selectedAnnotation) return; @@ -1865,12 +1964,12 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) // clean up self.selectedAnnotationCalloutView = nil; self.selectedAnnotation = nil; - } - // notify delegate - if ([self.delegate respondsToSelector:@selector(mapView:didDeselectAnnotation:)]) - { - [self.delegate mapView:self didDeselectAnnotation:annotation]; + // notify delegate + if ([self.delegate respondsToSelector:@selector(mapView:didDeselectAnnotation:)]) + { + [self.delegate mapView:self didDeselectAnnotation:annotation]; + } } } diff --git a/platform/ios/MGLMultiPoint.mm b/platform/ios/MGLMultiPoint.mm new file mode 100644 index 0000000000..ef8a18e493 --- /dev/null +++ b/platform/ios/MGLMultiPoint.mm @@ -0,0 +1,102 @@ +#import "MGLMultiPoint.h" +#import "MGLTypes.h" + +#import <mbgl/util/geo.hpp> + +@implementation MGLMultiPoint +{ + CLLocationCoordinate2D *_coords; + size_t _count; + mbgl::LatLngBounds _bounds; +} + +- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords + count:(NSUInteger)count +{ + self = [super init]; + + if (self) + { + _count = count; + _coords = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D)); + + for (NSUInteger i = 0; i < _count; i++) + { + _coords[i] = coords[i]; + _bounds.extend(mbgl::LatLng(coords[i].latitude, coords[i].longitude)); + } + } + + return self; +} + +- (void)dealloc +{ + free(_coords); +} + +- (CLLocationCoordinate2D)coordinate +{ + if ([self isMemberOfClass:[MGLMultiPoint class]]) + { + [[NSException exceptionWithName:@"MGLAbstractClassException" + reason:@"MGLMultiPoint is an abstract class" + userInfo:nil] raise]; + } + + assert(_count > 0); + + return CLLocationCoordinate2DMake(_coords[0].latitude, _coords[0].longitude); +} + +- (NSUInteger)pointCount +{ + if ([self isMemberOfClass:[MGLMultiPoint class]]) + { + [[NSException exceptionWithName:@"MGLAbstractClassException" + reason:@"MGLMultiPoint is an abstract class" + userInfo:nil] raise]; + } + + return _count; +} + +- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range +{ + if ([self isMemberOfClass:[MGLMultiPoint class]]) + { + [[NSException exceptionWithName:@"MGLAbstractClassException" + reason:@"MGLMultiPoint is an abstract class" + userInfo:nil] raise]; + } + + assert(range.location + range.length <= _count); + + NSUInteger index = 0; + + for (NSUInteger i = range.location; i < range.location + range.length; i++) + { + coords[index] = _coords[i]; + index++; + } +} + +- (MGLCoordinateBounds)overlayBounds +{ + return { + CLLocationCoordinate2DMake(_bounds.sw.latitude, _bounds.sw.longitude), + CLLocationCoordinate2DMake(_bounds.ne.longitude, _bounds.ne.longitude) + }; +} + +- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds +{ + mbgl::LatLngBounds area( + mbgl::LatLng(overlayBounds.sw.latitude, overlayBounds.sw.longitude), + mbgl::LatLng(overlayBounds.ne.latitude, overlayBounds.ne.longitude) + ); + + return _bounds.intersects(area); +} + +@end diff --git a/platform/ios/MGLMultiPoint_Private.h b/platform/ios/MGLMultiPoint_Private.h new file mode 100644 index 0000000000..a1a70a6778 --- /dev/null +++ b/platform/ios/MGLMultiPoint_Private.h @@ -0,0 +1,8 @@ +#import "MGLMultiPoint.h" + +@interface MGLMultiPoint (Private) + +- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; +- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds; + +@end diff --git a/platform/ios/MGLPointAnnotation.m b/platform/ios/MGLPointAnnotation.m new file mode 100644 index 0000000000..13fbba1083 --- /dev/null +++ b/platform/ios/MGLPointAnnotation.m @@ -0,0 +1,7 @@ +#import "MGLPointAnnotation.h" + +@implementation MGLPointAnnotation + +@synthesize coordinate; + +@end diff --git a/platform/ios/MGLPolygon.m b/platform/ios/MGLPolygon.m new file mode 100644 index 0000000000..d3b5f2c2a4 --- /dev/null +++ b/platform/ios/MGLPolygon.m @@ -0,0 +1,15 @@ +#import "MGLPolygon.h" + +#import "MGLMultiPoint_Private.h" + +@implementation MGLPolygon + +@synthesize overlayBounds; + ++ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords + count:(NSUInteger)count +{ + return [[self alloc] initWithCoordinates:coords count:count]; +} + +@end diff --git a/platform/ios/MGLPolyline.m b/platform/ios/MGLPolyline.m new file mode 100644 index 0000000000..86d113bd16 --- /dev/null +++ b/platform/ios/MGLPolyline.m @@ -0,0 +1,15 @@ +#import "MGLPolyline.h" + +#import "MGLMultiPoint_Private.h" + +@implementation MGLPolyline + +@synthesize overlayBounds; + ++ (instancetype)polylineWithCoordinates:(CLLocationCoordinate2D *)coords + count:(NSUInteger)count +{ + return [[self alloc] initWithCoordinates:coords count:count]; +} + +@end diff --git a/platform/ios/MGLShape.m b/platform/ios/MGLShape.m new file mode 100644 index 0000000000..e3d92c38c8 --- /dev/null +++ b/platform/ios/MGLShape.m @@ -0,0 +1,14 @@ +#import "MGLShape.h" + +@implementation MGLShape + +- (CLLocationCoordinate2D)coordinate +{ + [[NSException exceptionWithName:@"MGLAbstractClassException" + reason:@"MGLShape is an abstract class" + userInfo:nil] raise]; + + return CLLocationCoordinate2DMake(MAXFLOAT, MAXFLOAT); +} + +@end |