Я решил эту проблему, введя концепцию «совокупной» аннотации, которая представляет аннотации, которые в противном случае были бы слишком близко друг к другу, чтобы их можно было различить.
Я использовал простой (он же наивный) алгоритм, при котором, когда я добавляю новую аннотацию, я проверяю, находится ли она на расстоянии d
от существующей аннотации. Если это так, я создаю новую сводную аннотацию, помещаю под нее существующую аннотацию и новую аннотацию. Затем я удаляю существующую аннотацию и вместо этого добавляю совокупную аннотацию. Агрегированная аннотация имеет координату, которая является средним значением ее членов.
Этот конкретный алгоритм прост в реализации, но имеет довольно ужасную сложность, поскольку он проверяет каждую существующую аннотацию для каждой добавленной аннотации. Оптимизация будет заключаться в использовании kd tree
для сокращения пространства поиска.
В отношении пользовательского интерфейса при нажатии на такую сводную аннотацию будет отображаться сноска, которая показывает количество агрегированных аннотаций и некоторую сводную информацию об агрегированных аннотациях.
Кроме того, в MKAnnotationView
выноски rightCalloutAccessoryView
можно перейти к табличному представлению, в котором перечислены члены сводной аннотации, чтобы пользователь мог выбрать конкретный элемент для проверки.
Еще одно соображение - как вы определяете, когда две аннотации находятся слишком близко. Вы можете сделать это на основе фактического расстояния, и в этом случае, если вы уменьшаете масштаб, аннотации все равно будут перекрываться; или вы можете сделать это на основе логического расстояния на экране, принимая во внимание логический размер ваших аннотаций. Последний может гарантировать, что у вас никогда не будет перекрывающихся аннотаций, но он более затратен в вычислительном отношении, поскольку вам нужно пересчитать агрегации при изменении области карты.