diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 95759a2f9b7..e44e04d74ce 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -35,6 +35,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Fixed an issue preventing `MGLAnnotationImage.image` from being updated. ([#10372](https://github.com/mapbox/mapbox-gl-native/pull/10372)) * Improved performance of `MGLAnnotationView`-backed annotations that have `scalesWithViewingDistance` enabled. ([#10951](https://github.com/mapbox/mapbox-gl-native/pull/10951)) +* Fix an issue where a wrong annotation may selected if annotations were set close together. ([#11438](https://github.com/mapbox/mapbox-gl-native/pull/11438)) ### Map snapshots diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 5a68736ec55..18a69a34cd4 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -4148,51 +4148,48 @@ - (MGLAnnotationTag)annotationTagAtPoint:(CGPoint)point persistingResults:(BOOL) MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound; if (nearbyAnnotations.size()) { - // The annotation tags need to be stable in order to compare them with - // the remembered tags. - std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end()); - + // The first selection in the cycle should be the one nearest to the + // tap. Also the annotation tags need to be stable in order to compare them with + // the remembered tags _annotationsNearbyLastTap. + CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self]; + std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) { + CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate]; + CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate]; + CLLocationDegrees deltaA = hypot(coordinateA.latitude - currentCoordinate.latitude, + coordinateA.longitude - currentCoordinate.longitude); + CLLocationDegrees deltaB = hypot(coordinateB.latitude - currentCoordinate.latitude, + coordinateB.longitude - currentCoordinate.longitude); + return deltaA < deltaB; + }); + if (nearbyAnnotations == _annotationsNearbyLastTap) { - // The first selection in the cycle should be the one nearest to the - // tap. - CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self]; - std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) { - CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate]; - CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate]; - CLLocationDegrees deltaA = hypot(coordinateA.latitude - currentCoordinate.latitude, - coordinateA.longitude - currentCoordinate.longitude); - CLLocationDegrees deltaB = hypot(coordinateB.latitude - currentCoordinate.latitude, - coordinateB.longitude - currentCoordinate.longitude); - return deltaA < deltaB; - }); - // The last time we persisted a set of annotations, we had the same // set of annotations as we do now. Cycle through them. if (_selectedAnnotationTag == MGLAnnotationTagNotFound - || _selectedAnnotationTag == _annotationsNearbyLastTap.back()) + || _selectedAnnotationTag == nearbyAnnotations.back()) { // Either no annotation is selected or the last annotation in // the set was selected. Wrap around to the first annotation in // the set. - hitAnnotationTag = _annotationsNearbyLastTap.front(); + hitAnnotationTag = nearbyAnnotations.front(); } else { - auto result = std::find(_annotationsNearbyLastTap.begin(), - _annotationsNearbyLastTap.end(), + auto result = std::find(nearbyAnnotations.begin(), + nearbyAnnotations.end(), _selectedAnnotationTag); - if (result == _annotationsNearbyLastTap.end()) + if (result == nearbyAnnotations.end()) { // An annotation from this set hasn’t been selected before. // Select the first (nearest) one. - hitAnnotationTag = _annotationsNearbyLastTap.front(); + hitAnnotationTag = nearbyAnnotations.front(); } else { // Step to the next annotation in the set. - auto distance = std::distance(_annotationsNearbyLastTap.begin(), result); - hitAnnotationTag = _annotationsNearbyLastTap[distance + 1]; + auto distance = std::distance(nearbyAnnotations.begin(), result); + hitAnnotationTag = nearbyAnnotations[distance + 1]; } } } @@ -4204,7 +4201,7 @@ - (MGLAnnotationTag)annotationTagAtPoint:(CGPoint)point persistingResults:(BOOL) { _annotationsNearbyLastTap = nearbyAnnotations; } - + // Choose the first nearby annotation. if (nearbyAnnotations.size()) { diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 872612aec15..6de2a4e87e6 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -23,6 +23,9 @@ * Improved the sharpness of raster tiles on Retina displays. ([#10984](https://github.com/mapbox/mapbox-gl-native/pull/10984)) * Fixed a crash parsing a malformed style. ([#11001](https://github.com/mapbox/mapbox-gl-native/pull/11001)) +### Annotations +* Fix an issue where a wrong annotation may selected if annotations were set close together. ([#11438](https://github.com/mapbox/mapbox-gl-native/pull/11438)) + ### Map snapshots * Fixed a memory leak that occurred when creating a map snapshot. ([#10585](https://github.com/mapbox/mapbox-gl-native/pull/10585)) diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 7902fb5b644..353b2bf2f10 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -2099,44 +2099,41 @@ - (MGLAnnotationTag)annotationTagAtPoint:(NSPoint)point persistingResults:(BOOL) MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound; if (nearbyAnnotations.size()) { - // The annotation tags need to be stable in order to compare them with - // the remembered tags. - std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end()); - + // The first selection in the cycle should be the one nearest to the + // tap. Also the annotation tags need to be stable in order to compare them with + // the remembered tags _annotationsNearbyLastClick. + CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self]; + std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) { + CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate]; + CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate]; + CLLocationDegrees deltaA = hypot(coordinateA.latitude - currentCoordinate.latitude, + coordinateA.longitude - currentCoordinate.longitude); + CLLocationDegrees deltaB = hypot(coordinateB.latitude - currentCoordinate.latitude, + coordinateB.longitude - currentCoordinate.longitude); + return deltaA < deltaB; + }); + if (nearbyAnnotations == _annotationsNearbyLastClick) { - // The first selection in the cycle should be the one nearest to the - // click. - CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self]; - std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) { - CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate]; - CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate]; - CLLocationDegrees distanceA = hypot(coordinateA.latitude - currentCoordinate.latitude, - coordinateA.longitude - currentCoordinate.longitude); - CLLocationDegrees distanceB = hypot(coordinateB.latitude - currentCoordinate.latitude, - coordinateB.longitude - currentCoordinate.longitude); - return distanceA < distanceB; - }); - // The last time we persisted a set of annotations, we had the same // set of annotations as we do now. Cycle through them. if (_lastSelectedAnnotationTag == MGLAnnotationTagNotFound - || _lastSelectedAnnotationTag == _annotationsNearbyLastClick.back()) { + || _lastSelectedAnnotationTag == nearbyAnnotations.back()) { // Either no annotation is selected or the last annotation in // the set was selected. Wrap around to the first annotation in // the set. - hitAnnotationTag = _annotationsNearbyLastClick.front(); + hitAnnotationTag = nearbyAnnotations.front(); } else { - auto result = std::find(_annotationsNearbyLastClick.begin(), - _annotationsNearbyLastClick.end(), + auto result = std::find(nearbyAnnotations.begin(), + nearbyAnnotations.end(), _lastSelectedAnnotationTag); - if (result == _annotationsNearbyLastClick.end()) { + if (result == nearbyAnnotations.end()) { // An annotation from this set hasn’t been selected before. // Select the first (nearest) one. - hitAnnotationTag = _annotationsNearbyLastClick.front(); + hitAnnotationTag = nearbyAnnotations.front(); } else { // Step to the next annotation in the set. - auto distance = std::distance(_annotationsNearbyLastClick.begin(), result); - hitAnnotationTag = _annotationsNearbyLastClick[distance + 1]; + auto distance = std::distance(nearbyAnnotations.begin(), result); + hitAnnotationTag = nearbyAnnotations[distance + 1]; } } } else {