Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

shape annotations #1655

Closed
wants to merge 91 commits into from
Closed
Show file tree
Hide file tree
Changes from 83 commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
a2c7e00
refactor annotation adding for shapes; move to some unordered_maps
incanus May 20, 2015
b977a57
basic roughing out of shape paints & feature creation
incanus May 20, 2015
ed50422
split out multiple layers in live tiles
incanus May 20, 2015
fb65df2
abstract tile(s) feature creation to handle built-up shapes; move to …
incanus May 22, 2015
450d4b3
abstract zoom
incanus May 22, 2015
6a82560
reserve sizes; fix line accumulation
incanus May 22, 2015
4a06861
better-looking line width
incanus May 22, 2015
c54e00d
move to fill for now
incanus May 22, 2015
1d1eb84
expose & carry along shape annotation style properties
incanus May 26, 2015
1ae97a4
basic working runtime shape styling
incanus May 27, 2015
9722c92
sample point & shape annotation adds at startup
incanus May 27, 2015
e5db77b
add missing include for find_if
incanus May 27, 2015
94f7e2f
track stale annotation tile pre-style load
incanus May 27, 2015
c47f629
apply round line join for annotations
incanus May 28, 2015
b023d8d
support adding multiple shapes at once
incanus May 28, 2015
1297656
fix annotation removal
incanus May 28, 2015
b63b436
proper deletion cleanup
incanus May 28, 2015
15ea397
partial fix to tile-spanning features
incanus May 29, 2015
53b558b
roughing out basic Cocoa types
incanus May 30, 2015
1847681
add shape styling delegate callbacks
incanus May 30, 2015
129159b
tighten up shape delegate methods
incanus May 30, 2015
20a489b
add shape includes to umbrella header
incanus May 30, 2015
f7b7afe
add concrete MGLPointAnnotation
incanus May 31, 2015
a3f32ea
clean up MGLMultiPoint & descendents
incanus May 31, 2015
1c23ac8
flesh out Cocoa shapes API & use in demo app
incanus May 31, 2015
5c3448a
remove todo comment
incanus Jun 1, 2015
bf6be3c
fix annotations bounds search for >+/-85 latitude
incanus Jun 1, 2015
8626f91
avoid dupes in annotations bounds queries
incanus Jun 1, 2015
b51f5e8
fix problems with multiple point annotations
incanus Jun 1, 2015
da01318
allow annotation bounds filtering by type
incanus Jun 1, 2015
376ad5e
extend annotation bounds querying for shapes
incanus Jun 1, 2015
2a0d31c
implement MGLOverlay & bounds intersection
incanus Jun 2, 2015
e25a561
comment out API docs gen for now to try tests
incanus Jun 2, 2015
2862ee4
update GYP for .m -> .mm
incanus Jun 2, 2015
93521b8
fix temp OS X shape add
incanus Jun 2, 2015
9506583
flesh out some basic Cocoa shape API docs
incanus Jun 2, 2015
c3656fd
Revert "comment out API docs gen for now to try tests"
incanus Jun 2, 2015
d135461
Merge remote-tracking branch 'origin/master' into shape-annotations
incanus Jun 2, 2015
b7e26f3
only notify delegate on actual annotation deselection
incanus Jun 2, 2015
820d2da
don't allow Cocoa selection of non-point annotations
incanus Jun 2, 2015
d6ced9e
more proper feature type
incanus Jun 2, 2015
e9eb7dc
add comment about polygon closure
incanus Jun 4, 2015
c6fee9a
add former, untouched GeoJSONVT lib
incanus Jun 4, 2015
3696718
GeoJSONVT: split out GeoJSON parsing to allow direct feature passing
incanus Jun 4, 2015
7e0c53a
GeoJSONVT: expose conversion/projection functions for callers
incanus Jun 4, 2015
1ba430a
GeoJSONVT: temporarily(?) get rid of mutex
incanus Jun 4, 2015
9ba634f
GeoJSONVT: fix rounding bug
incanus Jun 4, 2015
9f25e6f
split out shape handling to GeoJSONVT shape tilers
incanus Jun 4, 2015
3239b84
build up annotation render tiles at point of need
incanus Jun 4, 2015
eefd44c
invalidate all annotation for now
incanus Jun 4, 2015
386567c
add test shapes in iOS demo app
incanus Jun 4, 2015
68e412d
we handle this at the core level
incanus Jun 4, 2015
60ff8e4
add default case to appease pedantic compilers
incanus Jun 4, 2015
f9a1c60
APPARENTLY NOT PEDANTIC ENOUGH
incanus Jun 4, 2015
6d90a8a
cast for more pedantic warnings on Linux
incanus Jun 4, 2015
395a5db
differentiate shapes
incanus Jun 4, 2015
a590995
sort points above shapes
incanus Jun 4, 2015
56b89c5
clean up shape tilers on deletion
incanus Jun 4, 2015
9b86c21
properly query annotation bounds
incanus Jun 4, 2015
d1797dc
fix tile invalidation for shapes addition & deletion
incanus Jun 5, 2015
62f40a1
adjustments to shape tiler structure & locking
incanus Jun 5, 2015
9290460
properly constrain latitude for shape points
incanus Jun 5, 2015
3ce8045
add note about no holes
incanus Jun 5, 2015
f3eb68c
clean up point/shape-only routines
incanus Jun 5, 2015
e9fcb6e
fix polyline parsing error
incanus Jun 5, 2015
0e574c6
spacing
incanus Jun 5, 2015
e92d1ff
remove bad check
incanus Jun 5, 2015
715be6f
preserve detail to max zoom
incanus Jun 5, 2015
9d864ce
simplify constructor
incanus Jun 5, 2015
8161621
use nicer operator overloading
incanus Jun 6, 2015
ee9ab21
properly iterate all shape geometries
incanus Jun 6, 2015
6345fcf
tile points can be (slightly, up to buffer distance) negative
incanus Jun 7, 2015
0d0527e
fix bug with min/max point validity
incanus Jun 7, 2015
43ccb9b
turn off debug logging for GeoJSONVT
incanus Jun 7, 2015
9383dac
Merge remote-tracking branch 'origin/master' into shape-annotations
incanus Jun 7, 2015
fe2d84c
remove OS X test annotations
incanus Jun 8, 2015
333e11a
Merge remote-tracking branch 'origin/master' into shape-annotations
incanus Jun 8, 2015
c638825
rename method
incanus Jun 8, 2015
38927c7
MGLBounds -> MGLCoordinateBounds
incanus Jun 8, 2015
2c9a886
move to annotation style value type getter
incanus Jun 8, 2015
74db485
properly use max zoom
incanus Jun 11, 2015
c39de8a
move to split GeoJSONVT
incanus Jun 11, 2015
a6da538
remove debug log line
incanus Jun 11, 2015
9ed12f4
move to external, submodule geojsonvt
incanus Jun 15, 2015
0d14311
Merge branch 'master' into shape-annotations
1ec5 Jun 15, 2015
e99661f
patch up GeoJSONVT setup
incanus Jun 15, 2015
58661c4
Merge branch 'shape-annotations' of github.com:mapbox/mapbox-gl-nativ…
incanus Jun 15, 2015
77c99f3
add geojsonvt submodule for Android Linux
incanus Jun 16, 2015
82ee46e
Merge remote-tracking branch 'origin/master' into shape-annotations
incanus Jun 16, 2015
e45bacf
move to shared private header
incanus Jun 16, 2015
effd91c
fix missing GYP include
incanus Jun 16, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions gyp/platform-ios.gypi
Expand Up @@ -36,6 +36,17 @@
'../platform/ios/MGLUserLocationAnnotationView.m',
'../include/mbgl/ios/MGLTypes.h',
'../platform/ios/MGLTypes.m',
'../include/mbgl/ios/MGLMultiPoint.h',
'../platform/ios/MGLMultiPoint.mm',
'../include/mbgl/ios/MGLOverlay.h',
'../include/mbgl/ios/MGLPointAnnotation.h',
'../platform/ios/MGLPointAnnotation.m',
'../include/mbgl/ios/MGLPolyline.h',
'../platform/ios/MGLPolyline.m',
'../include/mbgl/ios/MGLPolygon.h',
'../platform/ios/MGLPolygon.m',
'../include/mbgl/ios/MGLShape.h',
'../platform/ios/MGLShape.m',
'../platform/ios/NSBundle+MGLAdditions.h',
'../platform/ios/NSBundle+MGLAdditions.m',
'../platform/ios/NSException+MGLAdditions.h',
Expand Down
2 changes: 1 addition & 1 deletion include/mbgl/ios/MGLAnnotation.h
@@ -1,7 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

/** The MGLAnnotation protocol is used to provide annotation-related information to a map view. To use this protocol, you adopt it in any custom objects that store or represent annotation data. Each object then serves as the source of information about a single map annotation and provides critical information, such as the annotation’s location on the map. Annotation objects do not provide the visual representation of the annotation but typically coordinate (in conjunction with the map view’s delegate) the creation of an appropriate objects to handle the display.
/** The `MGLAnnotation` protocol is used to provide annotation-related information to a map view. To use this protocol, you adopt it in any custom objects that store or represent annotation data. Each object then serves as the source of information about a single map annotation and provides critical information, such as the annotation’s location on the map. Annotation objects do not provide the visual representation of the annotation but typically coordinate (in conjunction with the map view’s delegate) the creation of an appropriate objects to handle the display.
*
* An object that adopts this protocol must implement the `coordinate` property. The other methods of this protocol are optional. */
@protocol MGLAnnotation <NSObject>
Expand Down
29 changes: 29 additions & 0 deletions include/mbgl/ios/MGLMapView.h
Expand Up @@ -4,6 +4,9 @@
#import <CoreLocation/CoreLocation.h>

@class MGLUserLocation;
@class MGLPolyline;
@class MGLPolygon;
@class MGLShape;

@protocol MGLMapViewDelegate;
@protocol MGLAnnotation;
Expand Down Expand Up @@ -302,6 +305,30 @@ IB_DESIGNABLE
* @return The marker symbol to display for the specified annotation or `nil` if you want to display the default symbol. */
- (NSString *)mapView:(MGLMapView *)mapView symbolNameForAnnotation:(id <MGLAnnotation>)annotation;

/** Returns the alpha value to use when rendering a shape annotation. Defaults to `1.0`.
* @param mapView The map view rendering the shape annotation.
* @param annotation The annotation being rendered.
* @return An alpha value between `0` and `1.0`. */
- (CGFloat)mapView:(MGLMapView *)mapView alphaForShapeAnnotation:(MGLShape *)annotation;

/** Returns the stroke color to use when rendering a shape annotation. Defaults to black.
* @param mapView The map view rendering the shape annotation.
* @param annotation The annotation being rendered.
* @return A color to use for the shape outline. */
- (UIColor *)mapView:(MGLMapView *)mapView strokeColorForShapeAnnotation:(MGLShape *)annotation;

/** Returns the fill color to use when rendering a polygon annotation. Defaults to blue.
* @param mapView The map view rendering the polygon annotation.
* @param annotation The annotation being rendered.
* @return A color to use for the polygon interior. */
- (UIColor *)mapView:(MGLMapView *)mapView fillColorForPolygonAnnotation:(MGLPolygon *)annotation;

/** Returns the line width to use when rendering a polyline annotation. Defaults to `3.0`.
* @param mapView The map view rendering the polygon annotation.
* @param annotation The annotation being rendered.
* @return A line width for the polyline. */
- (CGFloat)mapView:(MGLMapView *)mapView lineWidthForPolylineAnnotation:(MGLPolyline *)annotation;

/** Returns a Boolean value indicating whether the annotation is able to display extra information in a callout bubble.
*
* If the value returned is `YES`, a standard callout bubble is shown when the user taps a selected annotation. The callout uses the title and subtitle text from the associated annotation object. If there is no title text, though, the annotation will not show a callout. The callout also displays any custom callout views returned by the delegate for the left and right callout accessory views.
Expand Down Expand Up @@ -369,6 +396,8 @@ IB_DESIGNABLE

#pragma mark - Tracking the User Location

/** @name Tracking the User Location */

/** Tells the delegate that the map view will begin tracking the user’s location.
*
* This method is called when the value of the showsUserLocation property changes to `YES`.
Expand Down
17 changes: 17 additions & 0 deletions include/mbgl/ios/MGLMultiPoint.h
@@ -0,0 +1,17 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLShape.h"

/** The `MGLMultiPoint` class is an abstract superclass used to define shapes composed of multiple points. You should not create instances of this class directly. Instead, you should create instances of the `MGLPolyline` or `MGLPolygon` classes. However, you can use the method and properties of this class to access information about the specific points associated with the line or polygon. */
@interface MGLMultiPoint : MGLShape

/** The number of points associated with the shape. (read-only) */
@property (nonatomic, readonly) NSUInteger pointCount;

/** Retrieves one or more coordinates associated with the shape.
* @param coords On input, you must provide a C array of structures large enough to hold the desired number of coordinates. On output, this structure contains the requested coordinate data.
* @param range The range of points you want. The `location` field indicates the first point you are requesting, with `0` being the first point, `1` being the second point, and so on. The `length` field indicates the number of points you want. The array in _`coords`_ must be large enough to accommodate the number of requested coordinates. */
- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range;

@end
31 changes: 31 additions & 0 deletions include/mbgl/ios/MGLOverlay.h
@@ -0,0 +1,31 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLAnnotation.h"
#import "MGLTypes.h"

/** The `MGLOverlay` protocol defines a specific type of annotation that represents both a point and an area on a map. Overlay objects are essentially data objects that contain the geographic data needed to represent the map area. For example, overlays can take the form of common shapes such as rectangles and circles. They can also describe polygons and other complex shapes.
*
* You use overlays to layer more sophisticated content on top of a map view. For example, you could use an overlay to show the boundaries of a national park or trace a bus route along city streets. Mapbox GL defines several concrete classes that conform to this protocol and define standard shapes.
*
* Because overlays are also annotations, they have similar usage pattern to annotations. When added to a map view using the `addOverlay:` method, that view detects whenever the overlay’s defined region intersects the visible portion of the map. At that point, the map view asks its delegate to provide a special overlay view to draw the visual representation of the overlay. If you add an overlay to a map view as an annotation instead, it is treated as an annotation with a single point. */
@protocol MGLOverlay <MGLAnnotation>

/* The approximate center point of the overlay area. (required) (read-only)
*
* This point is typically set to the center point of the map’s bounding rectangle. It is used as the anchor point for any callouts displayed for the annotation. */
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

/** The cooordinate rectangle that encompasses the overlay. (required) (read-only)
*
* This property contains the smallest rectangle that completely encompasses the overlay. Implementers of this protocol must set this area when implementing their overlay class, and after setting it, you must not change it. */
@property (nonatomic, readonly) MGLCoordinateBounds overlayBounds;

/** Returns a Boolean indicating whether the specified rectangle intersects the receiver’s shape.
*
* You can implement this method to provide more specific bounds checking for an overlay. If you do not implement it, the bounding rectangle is used to detect intersections.
* @param overlayBounds The rectangle to intersect with the receiver’s area.
* @return `YES` if any part of the map rectangle intersects the receiver’s shape or `NO` if it does not. */
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds;

@end
12 changes: 12 additions & 0 deletions include/mbgl/ios/MGLPointAnnotation.h
@@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLShape.h"

/** The `MGLPointAnnotation` class defines a concrete annotation object located at a specified point. You can use this class, rather than define your own, in situations where all you want to do is associate a point on the map with a title. */
@interface MGLPointAnnotation : MGLShape

/** The coordinate point of the annotation, specified as a latitude and longitude. */
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;

@end
17 changes: 17 additions & 0 deletions include/mbgl/ios/MGLPolygon.h
@@ -0,0 +1,17 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLMultiPoint.h"
#import "MGLOverlay.h"

/** The `MGLPolygon` class represents a shape consisting of one or more points that define a closed polygon. The points are connected end-to-end in the order they are provided. The first and last points are connected to each other to create the closed shape. */
@interface MGLPolygon : MGLMultiPoint <MGLOverlay>

/** Creates and returns an `MGLPolygon` object from the specified set of coordinates.
* @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.
* @return A new polygon object. */
+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords
count:(NSUInteger)count;

@end
17 changes: 17 additions & 0 deletions include/mbgl/ios/MGLPolyline.h
@@ -0,0 +1,17 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLMultiPoint.h"
#import "MGLOverlay.h"

/** The `MGLPolyline` class represents a shape consisting of one or more points that define connecting line segments. The points are connected end-to-end in the order they are provided. The first and last points are not connected to each other. */
@interface MGLPolyline : MGLMultiPoint <MGLOverlay>

/** Creates and returns an `MGLPolygon` object from the specified set of coordinates.
* @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.
* @return A new polyline object. */
+ (instancetype)polylineWithCoordinates:(CLLocationCoordinate2D *)coords
count:(NSUInteger)count;

@end
14 changes: 14 additions & 0 deletions include/mbgl/ios/MGLShape.h
@@ -0,0 +1,14 @@
#import <Foundation/Foundation.h>

#import "MGLAnnotation.h"

/** The `MGLShape` class is an abstract class that defines the basic properties for all shape-based annotation objects. This class must be subclassed and cannot be used as is. Subclasses are responsible for defining the geometry of the shape and providing an appropriate value for the coordinate property inherited from the `MGLAnnotation` protocol. */
@interface MGLShape : NSObject <MGLAnnotation>

/** The title of the shape annotation. The default value of this property is `nil`. */
@property (nonatomic, copy) NSString *title;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property should be nonnull when we ultimately merge in #1578. It looks like the MKAnnotation protocol has been audited for nullability but the concrete implementations have not. So -[MKAnnotation title] comes with this note, which implies nonnull:

Although this property is optional, if you support the selection of annotations in your map view, you are expected to provide this property. This string is displayed in the callout for the associated annotation view.

while corresponding properties in MKShape and other subclasses lack this note.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 We can do another once-over to land #1578 in b3?


/** The subtitle of the shape annotation. The default value of this property is `nil`. */
@property (nonatomic, copy) NSString *subtitle;

@end
9 changes: 7 additions & 2 deletions include/mbgl/ios/MGLTypes.h
@@ -1,14 +1,19 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

extern NSString * const MGLErrorDomain;

/** The mode used to track the user location on the map. */
typedef NS_ENUM(NSUInteger, MGLUserTrackingMode)
{
typedef NS_ENUM(NSUInteger, MGLUserTrackingMode) {
/** The map does not follow the user location. */
MGLUserTrackingModeNone = 0,
/** The map follows the user location. */
MGLUserTrackingModeFollow,
/** The map follows the user location and rotates when the heading changes. */
MGLUserTrackingModeFollowWithHeading
};

typedef struct {
CLLocationCoordinate2D sw;
CLLocationCoordinate2D ne;
} MGLCoordinateBounds;
6 changes: 6 additions & 0 deletions include/mbgl/ios/MapboxGL.h
@@ -1,5 +1,11 @@
#import "MGLAccountManager.h"
#import "MGLAnnotation.h"
#import "MGLMapView.h"
#import "MGLMultiPoint.h"
#import "MGLOverlay.h"
#import "MGLPointAnnotation.h"
#import "MGLPolygon.h"
#import "MGLPolyline.h"
#import "MGLShape.h"
#import "MGLTypes.h"
#import "MGLUserLocation.h"
26 changes: 21 additions & 5 deletions include/mbgl/map/map.hpp
Expand Up @@ -4,6 +4,7 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/map/update.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/style/style_properties.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/vec.hpp>
Expand All @@ -13,6 +14,7 @@
#include <functional>
#include <vector>
#include <memory>
#include <unordered_map>

namespace mbgl {

Expand All @@ -26,6 +28,16 @@ namespace util {
template <class T> class Thread;
}

enum class AnnotationType : uint8_t {
Any = 0,
Point = 1 << 0,
Shape = 1 << 1,
};

using AnnotationIDs = std::vector<uint32_t>;
using AnnotationSegment = std::vector<LatLng>;
using AnnotationSegments = std::vector<AnnotationSegment>;

class Map : private util::noncopyable {
friend class View;

Expand Down Expand Up @@ -112,12 +124,16 @@ class Map : private util::noncopyable {
void setDefaultPointAnnotationSymbol(const std::string&);
double getTopOffsetPixelsForAnnotationSymbol(const std::string&);
uint32_t addPointAnnotation(const LatLng&, const std::string& symbol);
std::vector<uint32_t> addPointAnnotations(const std::vector<LatLng>&,
const std::vector<std::string>& symbols);
AnnotationIDs addPointAnnotations(const AnnotationSegment&,
const std::vector<std::string>& symbols);
uint32_t addShapeAnnotation(const AnnotationSegments&,
const StyleProperties&);
AnnotationIDs addShapeAnnotations(const std::vector<AnnotationSegments>&,
const std::vector<StyleProperties>&);
void removeAnnotation(uint32_t);
void removeAnnotations(const std::vector<uint32_t>&);
std::vector<uint32_t> getAnnotationsInBounds(const LatLngBounds&);
LatLngBounds getBoundsForAnnotations(const std::vector<uint32_t>&);
void removeAnnotations(const AnnotationIDs&);
AnnotationIDs getAnnotationsInBounds(const LatLngBounds&, const AnnotationType& = AnnotationType::Any);
LatLngBounds getBoundsForAnnotations(const AnnotationIDs&);

// Memory
void setSourceTileCacheSize(size_t);
Expand Down
Expand Up @@ -3,7 +3,6 @@

#include <mbgl/util/variant.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/style/piecewisefunction_properties.hpp>

#include <array>
#include <string>
Expand Down
14 changes: 13 additions & 1 deletion include/mbgl/util/geo.hpp
Expand Up @@ -33,12 +33,24 @@ struct LatLngBounds {
if (point.longitude > ne.longitude) ne.longitude = point.longitude;
}

inline bool contains(const LatLng& point) {
inline void extend(const LatLngBounds& bounds) {
extend(bounds.sw);
extend(bounds.ne);
}

inline bool contains(const LatLng& point) const {
return (point.latitude >= sw.latitude &&
point.latitude <= ne.latitude &&
point.longitude >= sw.longitude &&
point.longitude <= ne.longitude);
}

inline bool intersects(const LatLngBounds area) const {
return (area.ne.latitude > sw.latitude &&
area.sw.latitude < ne.latitude &&
area.ne.longitude > sw.longitude &&
area.sw.longitude < ne.longitude);
}
};

}
Expand Down
12 changes: 0 additions & 12 deletions ios/app/MBXAnnotation.h

This file was deleted.

30 changes: 0 additions & 30 deletions ios/app/MBXAnnotation.m

This file was deleted.