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

[ios, macos] Fix an issue where a wrong annotation may selected if annotations were set close together #11438

Merged
merged 4 commits into from
Mar 13, 2018
Merged
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
1 change: 1 addition & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
49 changes: 23 additions & 26 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}
}
}
Expand All @@ -4204,7 +4201,7 @@ - (MGLAnnotationTag)annotationTagAtPoint:(CGPoint)point persistingResults:(BOOL)
{
_annotationsNearbyLastTap = nearbyAnnotations;
}

// Choose the first nearby annotation.
if (nearbyAnnotations.size())
{
Expand Down
3 changes: 3 additions & 0 deletions platform/macos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
47 changes: 22 additions & 25 deletions platform/macos/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down