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

2167 mgl circle #3343

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gyp/platform-ios.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
'../platform/ios/MGLPolygon.m',
'../include/mbgl/ios/MGLShape.h',
'../platform/ios/MGLShape.m',
'../include/mbgl/ios/MGLCircle.h',
'../platform/ios/MGLCircle.mm',
'../include/mbgl/ios/MGLAnnotationImage.h',
'../platform/ios/MGLAnnotationImage.m',
'../platform/ios/NSBundle+MGLAdditions.h',
Expand Down
22 changes: 22 additions & 0 deletions include/mbgl/annotation/circle_annotation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef MBGL_ANNOTATION_CIRCLE_ANNOTATION
#define MBGL_ANNOTATION_CIRCLE_ANNOTATION

#include <mbgl/util/geo.hpp>

#include <string>

namespace mbgl {

class CircleAnnotation {
public:
inline CircleAnnotation(const LatLng& position_, const double radius_)
: position(position_), radius(radius_) {
}

const LatLng position;
const double radius;
};

}

#endif
7 changes: 4 additions & 3 deletions include/mbgl/annotation/shape_annotation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ using AnnotationSegments = std::vector<AnnotationSegment>;
class ShapeAnnotation {
public:
using Properties = mapbox::util::variant<
FillPaintProperties, // creates a fill annotation
LinePaintProperties, // creates a line annotation
std::string>; // creates an annotation whose type and properties are sourced from a style layer
FillPaintProperties, // creates a fill annotation
LinePaintProperties, // creates a line annotation
CirclePaintProperties, // creates a circle annotation
std::string>; // creates an annotation whose type and properties are sourced from a style layer

ShapeAnnotation(const AnnotationSegments& segments_, const Properties& properties_)
: segments(segments_), properties(properties_) {
Expand Down
22 changes: 22 additions & 0 deletions include/mbgl/ios/MGLCircle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLShape.h"
#import "MGLOverlay.h"

NS_ASSUME_NONNULL_BEGIN

@interface MGLCircle : MGLShape <MGLOverlay>

@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, readonly) CLLocationDistance radius;
@property (nonatomic, readonly) MGLCoordinateBounds overlayBounds;

+ (instancetype)circleWithCenterCoordinate:(CLLocationCoordinate2D)coordinate
radius:(CLLocationDistance)radius;

+ (instancetype)circleWithOverlayBounds:(MGLCoordinateBounds)overlayBounds;

@end

NS_ASSUME_NONNULL_END
6 changes: 6 additions & 0 deletions include/mbgl/ios/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,12 @@ IB_DESIGNABLE
* @return A color to use for the polygon interior. */
- (UIColor *)mapView:(MGLMapView *)mapView fillColorForPolygonAnnotation:(MGLPolygon *)annotation;

/** Returns the fill color to use when rendering a circle annotation. Defaults to red.
* @param mapView The map view rendering the circle annotation.
* @param annotation The annotation being rendered.
* @return A color to use for the circle interior. */
- (UIColor *)mapView:(MGLMapView *)mapView fillColorForCircleAnnotation:(MGLCircle *)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.
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/ios/Mapbox.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "MGLAccountManager.h"
#import "MGLAnnotation.h"
#import "MGLAnnotationImage.h"
#import "MGLCircle.h"
#import "MGLMapCamera.h"
#import "MGLGeometry.h"
#import "MGLMapView.h"
Expand Down
17 changes: 14 additions & 3 deletions ios/app/MBXViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSIn

MGLPolygon *triangle = [MGLPolygon polygonWithCoordinates:triangleCoordinates count:3];

[self.mapView addAnnotation:triangle];
[self.mapView addOverlay:triangle];

// Orcas Island hike
//
Expand All @@ -222,7 +222,7 @@ - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSIn
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:polylineCoordinates
count:[hikeCoordinatePairs count]];

[self.mapView addAnnotation:polyline];
[self.mapView addOverlay:polyline];

free(polylineCoordinates);

Expand All @@ -249,10 +249,16 @@ - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSIn

MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:polygonCoordinates count:[stateCoordinatePairs count]];

[self.mapView addAnnotation:polygon];
[self.mapView addOverlay:polygon];

free(polygonCoordinates);
}

// Rabat circle
//
MGLCircle *circle = [MGLCircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(34.020882, -6.84165) radius:100000];

[self.mapView addOverlay:circle];
}
else if (buttonIndex == actionSheet.firstOtherButtonIndex + 8)
{
Expand Down Expand Up @@ -437,6 +443,11 @@ - (UIColor *)mapView:(__unused MGLMapView *)mapView fillColorForPolygonAnnotatio
return (annotation.pointCount > 3 ? [UIColor greenColor] : [UIColor redColor]);
}

//- (UIColor *)mapView:(__unused MGLMapView *)mapView fillColorForCircleAnnotation:(__unused MGLCircle *)annotation
//{
// return [UIColor greenColor];
//}

- (void)mapView:(__unused MGLMapView *)mapView didChangeUserTrackingMode:(MGLUserTrackingMode)mode animated:(__unused BOOL)animated
{
UIImage *newButtonImage;
Expand Down
101 changes: 101 additions & 0 deletions platform/ios/MGLCircle.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#import "MGLCircle.h"

#import <mbgl/util/geo.hpp>
#import <mbgl/util/projection.hpp>

@implementation MGLCircle
{
CLLocationDistance _radius;
mbgl::LatLngBounds _bounds;
}

@synthesize coordinate=_coordinate;

- (instancetype)initWithCenterCoordinate:(CLLocationCoordinate2D)coordinate
radius:(CLLocationDistance)radius
overlayBounds:(MGLCoordinateBounds)overlayBounds
{
self = [super init];

if (self)
{
_coordinate = coordinate;
_radius = radius;

if (MGLCoordinateBoundsIsEmpty(overlayBounds))
{
using Projection = mbgl::Projection;
using ProjectedMeters = mbgl::ProjectedMeters;

ProjectedMeters projectedCenter = Projection::projectedMetersForLatLng(mbgl::LatLng(coordinate.latitude, coordinate.longitude));

ProjectedMeters projectedWest = ProjectedMeters(projectedCenter.northing, projectedCenter.easting - radius);
ProjectedMeters projectedEast = ProjectedMeters(projectedCenter.northing, projectedCenter.easting + radius);
ProjectedMeters projectedNorth = ProjectedMeters(projectedCenter.northing + radius, projectedCenter.easting);
ProjectedMeters projectedSouth = ProjectedMeters(projectedCenter.northing - radius, projectedCenter.easting);

_bounds.extend(Projection::latLngForProjectedMeters(projectedWest));
_bounds.extend(Projection::latLngForProjectedMeters(projectedEast));
_bounds.extend(Projection::latLngForProjectedMeters(projectedNorth));
_bounds.extend(Projection::latLngForProjectedMeters(projectedSouth));
}
else
{
_bounds.extend(mbgl::LatLng(overlayBounds.sw.latitude, overlayBounds.sw.longitude));
_bounds.extend(mbgl::LatLng(overlayBounds.ne.latitude, overlayBounds.ne.longitude));
}
}

return self;
}

+ (instancetype)circleWithCenterCoordinate:(CLLocationCoordinate2D)coordinate
radius:(CLLocationDistance)radius
{
CLLocationCoordinate2D nullIsland = CLLocationCoordinate2DMake(0, 0);

return [[self alloc] initWithCenterCoordinate:coordinate
radius:radius
overlayBounds:MGLCoordinateBoundsMake(nullIsland, nullIsland)];
}

+ (instancetype)circleWithOverlayBounds:(MGLCoordinateBounds)overlayBounds
{
CLLocation *sw = [[CLLocation alloc] initWithLatitude:overlayBounds.sw.latitude
longitude:overlayBounds.sw.longitude];
CLLocation *ne = [[CLLocation alloc] initWithLatitude:overlayBounds.ne.latitude
longitude:overlayBounds.ne.longitude];

CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(
(sw.coordinate.latitude + ne.coordinate.latitude) / 2,
(sw.coordinate.longitude + ne.coordinate.longitude) / 2);

CLLocation *se = [[CLLocation alloc] initWithLatitude:sw.coordinate.latitude
longitude:ne.coordinate.longitude];

CLLocationDistance radius = [sw distanceFromLocation:se] / 2;

return [[self alloc] initWithCenterCoordinate:centerCoordinate
radius:radius
overlayBounds:overlayBounds];
}

- (MGLCoordinateBounds)overlayBounds
{
return {
CLLocationCoordinate2DMake(_bounds.sw.latitude, _bounds.sw.longitude),
CLLocationCoordinate2DMake(_bounds.ne.latitude, _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
31 changes: 31 additions & 0 deletions platform/ios/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,7 @@ - (void)addAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations
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 delegateImplementsFillColorForCircle = [self.delegate respondsToSelector:@selector(mapView:fillColorForCircleAnnotation:)];
BOOL delegateImplementsLineWidthForPolyline = [self.delegate respondsToSelector:@selector(mapView:lineWidthForPolylineAnnotation:)];

for (id <MGLAnnotation> annotation in annotations)
Expand Down Expand Up @@ -2187,6 +2188,36 @@ - (void)addAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations

shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties);
}
else if ([annotation isKindOfClass:[MGLCircle class]])
{
CGFloat alpha = (delegateImplementsAlphaForShape ?
[self.delegate mapView:self alphaForShapeAnnotation:annotation] :
1.0);

mbgl::ShapeAnnotation::Properties shapeProperties;

UIColor *circleColor = (delegateImplementsFillColorForCircle ?
[self.delegate mapView:self fillColorForCircleAnnotation:(MGLCircle *)annotation] :
[UIColor redColor]);

assert(circleColor);

CGFloat r,g,b,a;
[circleColor getRed:&r green:&g blue:&b alpha:&a];
mbgl::Color circleNativeColor({{ (float)r, (float)g, (float)b, (float)a }});

mbgl::CirclePaintProperties circleProperties;
circleProperties.opacity = alpha;
circleProperties.color = circleNativeColor;
shapeProperties.set<mbgl::CirclePaintProperties>(circleProperties);

mbgl::AnnotationSegment segment = { mbgl::LatLng(
annotation.coordinate.latitude,
annotation.coordinate.longitude)
};

shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties);
}
else
{
MGLAnnotationImage *annotationImage = delegateImplementsImageForPoint ? [self.delegate mapView:self imageForAnnotation:annotation] : nil;
Expand Down
2 changes: 1 addition & 1 deletion platform/ios/MGLMultiPoint.mm
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ - (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range
- (MGLCoordinateBounds)overlayBounds
{
return {
CLLocationCoordinate2DMake(_bounds.sw.latitude, _bounds.sw.longitude),
CLLocationCoordinate2DMake(_bounds.sw.latitude, _bounds.sw.longitude),
CLLocationCoordinate2DMake(_bounds.ne.latitude, _bounds.ne.longitude)
};
}
Expand Down
4 changes: 4 additions & 0 deletions src/mbgl/annotation/annotation_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/annotation/point_annotation_impl.hpp>
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/annotation/circle_annotation_impl.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/noncopyable.hpp>

Expand All @@ -14,6 +15,7 @@ namespace mbgl {

class PointAnnotation;
class ShapeAnnotation;
class CircleAnnotation;
class AnnotationTile;
class Style;

Expand All @@ -24,6 +26,7 @@ class AnnotationManager : private util::noncopyable {

AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&, const uint8_t maxZoom);
AnnotationIDs addShapeAnnotations(const std::vector<ShapeAnnotation>&, const uint8_t maxZoom);
AnnotationIDs addCircleAnnotations(const std::vector<CircleAnnotation>&, const uint8_t maxZoom);
void removeAnnotations(const AnnotationIDs&);

AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&) const;
Expand All @@ -40,6 +43,7 @@ class AnnotationManager : private util::noncopyable {
PointAnnotationImpl::Tree pointTree;
PointAnnotationImpl::Map pointAnnotations;
ShapeAnnotationImpl::Map shapeAnnotations;
CircleAnnotationImpl::Map circleAnnotations;
std::vector<std::string> obsoleteShapeAnnotationLayers;
};

Expand Down
34 changes: 34 additions & 0 deletions src/mbgl/annotation/circle_annotation_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <mbgl/annotation/circle_annotation_impl.hpp>
//#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/util/string.hpp>

namespace mbgl {

CircleAnnotationImpl::CircleAnnotationImpl(const AnnotationID id_, const CircleAnnotation& circle_)
: id(id_),
layerID("com.mapbox.annotations.circle." + util::toString(id)),
circle(circle_) {
}

void CircleAnnotationImpl::updateLayer(const TileID& tileID, AnnotationTileLayer& layer) const {
std::unordered_map<std::string, std::string> featureProperties;
featureProperties.emplace("sprite", point.icon.empty() ? std::string("default_marker") : point.icon);

const uint16_t extent = 4096;
const vec2<double> pp = point.position.project();
const uint32_t z2 = 1 << tileID.z;
const uint32_t x = pp.x * z2;
const uint32_t y = pp.y * z2;
const Coordinate coordinate(extent * (pp.x * z2 - x), extent * (pp.y * z2 - y));

layer.features.emplace_back(
std::make_shared<const AnnotationTileFeature>(FeatureType::Point,
GeometryCollection {{ {{ coordinate }} }},
featureProperties));
}

LatLngBounds CircleAnnotationImpl::bounds() const {
return LatLngBounds(circle.position, circle.position); //
}

}
29 changes: 29 additions & 0 deletions src/mbgl/annotation/circle_annotation_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef MBGL_CIRCLE_ANNOTATION_IMPL
#define MBGL_CIRCLE_ANNOTATION_IMPL

#include <mbgl/annotation/annotation.hpp>
#include <mbgl/annotation/circle_annotation.hpp>
#include <mbgl/util/geo.hpp>

#include <string>

namespace mbgl {

class AnnotationTileLayer;

class CircleAnnotationImpl {
public:
CircleAnnotationImpl(const AnnotationID, const CircleAnnotation&);

LatLngBounds bounds() const;
void updateStyle(Style&);
void updateLayer(const TileID&, AnnotationTile&) const;

const AnnotationID id;
const std::string layerID;
const CircleAnnotation circle;
};

}

#endif
Loading