[ios] Avoid drawing view annotations across pixel boundaries
This commit is contained in:
@@ -4,6 +4,10 @@
|
||||
|
||||
#import <mbgl/util/projection.hpp>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
|
||||
/** Vertical field of view, measured in degrees, for determining the altitude
|
||||
of the viewpoint.
|
||||
|
||||
@@ -57,3 +61,12 @@ double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLoc
|
||||
CGFloat mapPixelWidthAtZoom = std::cos(MGLRadiansFromDegrees(latitude)) * mbgl::util::M2PI * mbgl::util::EARTH_RADIUS_M / metersPerPixel;
|
||||
return ::log2(mapPixelWidthAtZoom / mbgl::util::tileSize);
|
||||
}
|
||||
|
||||
CGPoint MGLPointRounded(CGPoint point) {
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
CGFloat scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [UIScreen mainScreen].nativeScale : [UIScreen mainScreen].scale;
|
||||
#elif TARGET_OS_MAC
|
||||
CGFloat scaleFactor = [NSScreen mainScreen].backingScaleFactor;
|
||||
#endif
|
||||
return CGPointMake(round(point.x * scaleFactor) / scaleFactor, round(point.y * scaleFactor) / scaleFactor);
|
||||
}
|
||||
|
||||
@@ -138,3 +138,5 @@ NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGL
|
||||
cos(distance) - sin(coordinate.latitude) * sin(otherLatitude));
|
||||
return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude);
|
||||
}
|
||||
|
||||
CGPoint MGLPointRounded(CGPoint point);
|
||||
|
||||
@@ -31,6 +31,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
|
||||
* Selecting an annotation no longer sets the user tracking mode to `MGLUserTrackingModeNone`. ([#10094](https://github.com/mapbox/mapbox-gl-native/pull/10094))
|
||||
* Added `-[MGLMapView cameraThatFitsShape:direction:edgePadding:]` to get a camera with zoom level and center coordinate computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107))
|
||||
* Added support selection of shape and polyline annotations.([#9984](https://github.com/mapbox/mapbox-gl-native/pull/9984))
|
||||
* Fixed an issue where view annotations could be slightly misaligned. View annotation placement is now rounded to the nearest pixel. ([#10219](https://github.com/mapbox/mapbox-gl-native/pull/10219))
|
||||
|
||||
### Other changes
|
||||
|
||||
|
||||
@@ -175,8 +175,8 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
_puckArrow = [CAShapeLayer layer];
|
||||
_puckArrow.path = [[self puckArrow] CGPath];
|
||||
_puckArrow.fillColor = [self.mapView.tintColor CGColor];
|
||||
_puckArrow.bounds = CGRectMake(0, 0, MGLUserLocationAnnotationArrowSize, MGLUserLocationAnnotationArrowSize);
|
||||
_puckArrow.position = CGPointMake(super.bounds.size.width / 2.0, super.bounds.size.height / 2.0);
|
||||
_puckArrow.bounds = CGRectMake(0, 0, round(MGLUserLocationAnnotationArrowSize), round(MGLUserLocationAnnotationArrowSize));
|
||||
_puckArrow.position = CGPointMake(CGRectGetMidX(super.bounds), CGRectGetMidY(super.bounds));
|
||||
_puckArrow.shouldRasterize = YES;
|
||||
_puckArrow.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
_puckArrow.drawsAsynchronously = YES;
|
||||
@@ -306,7 +306,7 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
[CATransaction setDisableActions:shouldDisableActions];
|
||||
|
||||
_accuracyRingLayer.bounds = CGRectMake(0, 0, accuracyRingSize, accuracyRingSize);
|
||||
_accuracyRingLayer.cornerRadius = accuracyRingSize / 2;
|
||||
_accuracyRingLayer.cornerRadius = accuracyRingSize / 2.0;
|
||||
|
||||
// match the halo to the accuracy ring
|
||||
_haloLayer.bounds = _accuracyRingLayer.bounds;
|
||||
@@ -435,9 +435,11 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
|
||||
- (CALayer *)circleLayerWithSize:(CGFloat)layerSize
|
||||
{
|
||||
layerSize = round(layerSize);
|
||||
|
||||
CALayer *circleLayer = [CALayer layer];
|
||||
circleLayer.bounds = CGRectMake(0, 0, layerSize, layerSize);
|
||||
circleLayer.position = CGPointMake(super.bounds.size.width / 2.0, super.bounds.size.height / 2.0);
|
||||
circleLayer.position = CGPointMake(CGRectGetMidX(super.bounds), CGRectGetMidY(super.bounds));
|
||||
circleLayer.cornerRadius = layerSize / 2.0;
|
||||
circleLayer.shouldRasterize = YES;
|
||||
circleLayer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
@@ -460,7 +462,7 @@ const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01;
|
||||
- (CGFloat)calculateAccuracyRingSize
|
||||
{
|
||||
// diameter in screen points
|
||||
return self.userLocation.location.horizontalAccuracy / [self.mapView metersPerPointAtLatitude:self.userLocation.coordinate.latitude] * 2.0;
|
||||
return round(self.userLocation.location.horizontalAccuracy / [self.mapView metersPerPointAtLatitude:self.userLocation.coordinate.latitude] * 2.0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -3379,7 +3379,7 @@ public:
|
||||
{
|
||||
annotationViewsForAnnotation[annotationValue] = annotationView;
|
||||
annotationView.annotation = annotation;
|
||||
annotationView.center = [self convertCoordinate:annotation.coordinate toPointToView:self];
|
||||
annotationView.center = MGLPointRounded([self convertCoordinate:annotation.coordinate toPointToView:self]);
|
||||
[newAnnotationViews addObject:annotationView];
|
||||
|
||||
MGLAnnotationImage *annotationImage = self.invisibleAnnotationImage;
|
||||
@@ -3805,7 +3805,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
CGPoint calloutAnchorPoint = [self convertCoordinate:annotation.coordinate toPointToView:self];
|
||||
CGPoint calloutAnchorPoint = MGLPointRounded([self convertCoordinate:annotation.coordinate toPointToView:self]);
|
||||
CGRect frame = CGRectInset({ calloutAnchorPoint, CGSizeZero }, -CGRectGetWidth(annotationView.frame) / 2, -CGRectGetHeight(annotationView.frame) / 2);
|
||||
annotationRect = UIEdgeInsetsInsetRect(frame, annotationView.alignmentRectInsets);
|
||||
}
|
||||
@@ -4143,7 +4143,7 @@ public:
|
||||
/// image centered at the given coordinate.
|
||||
- (CGRect)frameOfImage:(UIImage *)image centeredAtCoordinate:(CLLocationCoordinate2D)coordinate
|
||||
{
|
||||
CGPoint calloutAnchorPoint = [self convertCoordinate:coordinate toPointToView:self];
|
||||
CGPoint calloutAnchorPoint = MGLPointRounded([self convertCoordinate:coordinate toPointToView:self]);
|
||||
CGRect frame = CGRectInset({ calloutAnchorPoint, CGSizeZero }, -image.size.width / 2, -image.size.height / 2);
|
||||
return UIEdgeInsetsInsetRect(frame, image.alignmentRectInsets);
|
||||
}
|
||||
@@ -4582,7 +4582,6 @@ public:
|
||||
if (_showsUserHeadingIndicator)
|
||||
{
|
||||
self.showsUserLocation = YES;
|
||||
|
||||
}
|
||||
[self validateUserHeadingUpdating];
|
||||
}
|
||||
@@ -5288,7 +5287,7 @@ public:
|
||||
|
||||
if (annotationView)
|
||||
{
|
||||
annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
|
||||
annotationView.center = MGLPointRounded([self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5406,7 +5405,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
userPoint = [self convertCoordinate:self.userLocation.coordinate toPointToView:self];
|
||||
userPoint = MGLPointRounded([self convertCoordinate:self.userLocation.coordinate toPointToView:self]);
|
||||
}
|
||||
|
||||
if ( ! annotationView.superview)
|
||||
|
||||
Reference in New Issue
Block a user