Мне нужно найти центроид (или точку метки) для полигонов неправильной формы в Картах Google. Я показываю InfoWindows для посылок, и мне нужно место для привязки InfoWindow, которое гарантированно будет на поверхности. Смотрите изображения ниже.
На самом деле мне не нужно ничего специфичного для Google Maps, я просто ищу идею, как автоматически найти эту точку.
Моя первая идея состояла в том, чтобы найти «ложный» центроид, взяв средние значения широты и долготы и случайно расположив точки оттуда, пока я не найду тот, который пересекает многоугольник. У меня уже есть код точки-полигона. Это просто кажется мне ужасно "хакерским".
Я должен отметить, что у меня нет доступа ни к одному из серверных кодов, выводящих геометрию, поэтому я не могу ничего сделать, например ST_PointOnSurface (the_geom).
Вы можете посмотреть на это: http://github.com/tparkin/Google-Maps-Point-in-Polygon
Кажется, он использует алгоритм Ray Casting, который должен соответствовать представленному вами случаю.
Об этом есть запись в блоге. http://appdelegateinc.com/blog/2010/05/16/point-in-polygon-checking/
источник
(Старый) алгоритм ESRI вычисляет центр масс и, после проверки его на включение в многоугольник, перемещает его горизонтально, если это необходимо, до тех пор, пока он не окажется внутри многоугольника. (Это может быть сделано разными способами в зависимости от того, какие фундаментальные операции доступны в вашей среде программирования.) Это имеет тенденцию создавать точки надписей довольно близко к визуальному центру многоугольника: попробуйте это на иллюстрации.
источник
Я решил свою проблему, расширив популярный эпологический код с http://econym.org.uk/gmap . В основном то, что я закончил, было:
Расширенный код эполии ниже:
Все еще немного хакерский, но это, кажется, работает.
источник
Еще один «грязный» алгоритм для этого:
Возьмите ограничивающую рамку геометрии
(Xmax, Ymax, Xmin, Ymin)
Цикл, пока
( Xmin+rand*(Xmax-Xmin), Ymin+rand*(Ymax-Ymin) )
в геометрии не будет найдена случайная точка (используя Google-Maps-Point-in-Polygon )источник
В свете вашего недавнего разъяснения, что вы бы предпочли строго внутреннее расположение, вы можете выбрать любую точку в преобразовании медиальной оси, которая также не находится на границе многоугольника. (Если у вас нет кода для MAT, вы можете аппроксимировать его отрицательной буферизацией многоугольника. Бинарный или секущий поиск быстро создаст небольшой внутренний многоугольник, который приблизительно соответствует части MAT; используйте любую точку на его границе.)
источник
Почему бы не использовать центроид только для вертикального (широтного) положения? Затем вы можете расположить метку по горизонтали, выбрав среднюю долготу на этой широте . (Для этого вам нужно найти значение долготы для ребра многоугольника на определенной широте, что не должно вызывать проблем).
Кроме того, будьте осторожны с U-образными формами и более сложными. :) Возможно, для них выберите среднее значение самой правой пары долгот (каждая пара будет соответствовать срезу многоугольника), так как информационное окно ориентировано таким образом?
Это также дает вам немного больше контроля над позиционированием; например, было бы неплохо расположить информационное окно на 66 или 75% по вертикали, чтобы оставить больше видимого многоугольника. (А может и нет! Но у вас есть ручка для настройки.)
источник
Как насчет того, чтобы просто использовать точку, которую щелкнул пользователь, чтобы выбрать ее, если она выбрана пользователем, который есть.
источник
Я тоже пытаюсь это решить. Я наложил условие на мои полигоны, чтобы они не могли пересекать линии, что входит в то, что я опишу.
Итак, мой подход использует триангуляцию. Возьмите случайную вершину (возможно, взять вершину в крайних N, E, W или S может упростить вещи).
Из этой вершины нарисуйте линии к вершине на одну вершину, т.е. если ваша вершина - вершина 3, посмотрите на вершину 3 + 2.
Постройте линию от вашей исходной вершины до этой вершины. Если построена линия:
Затем вы построили треугольник внутри многоугольника. Если успешной вершиной было n + 2, то ваш треугольник - {n, n + 1, n + 2}, который мы будем называть {v, v1, v2}. Если нет, попробуйте следующую вершину и продолжайте, пока все вершины не будут опробованы.
Когда вы найдете треугольник, найдите его центр, проведя линию от вершины v к средней точке v1 и v2. Середина этой линии гарантированно будет внутри треугольника и внутри многоугольника.
Я еще не закодировал это, но я могу видеть, что полигон с пересекающимися линиями фактически вызовет некоторые экзотические условия, когда это не работает. Если это тип полигонов, который у вас есть, вам нужно проверить каждый отрезок на полигоне и убедиться, что он не пересекается. Пропустите отрезанные отрезки, и я думаю, что это сработает.
источник
https://github.com/mapbox/polylabel может быть полезен (javascript и C ++). Внедрение C # здесь: https://gist.github.com/dfaivre/acfef42cdbf411555956e9eba65dd30d .
Оригинальный ТАК вопрос здесь: /programming//a/38522611/79113
источник