Я хочу рассчитать угол между двумя линиями, где они пересекаются в PostGIS.
Начальная точка для расчета угла в PostGIS, кажется, ST_Azimuth - но она принимает точки в качестве входных данных. Моей первой мыслью было взять конечные точки пересекающихся линий и выполнить для них азимутальные вычисления. Это недостаточно хорошо, потому что большинство линейных объектов не прямые, и меня интересует угол на пересечении. Итак, я придумал вложенную операцию, которая проходит следующие шаги:
- Определите все пересечения между двумя таблицами линейных объектов.
- Создайте очень маленький буфер вокруг точки пересечения
- Определите точки, где линейные объекты пересекают внешнюю часть буфера (беря первую точку, если их больше одной - меня действительно интересует только, близок ли угол к 0, 90 или 180 градусам)
- Рассчитайте ST_Azimuth для этих двух точек.
Полный SQL довольно долго размещать здесь, но я привел его здесь, если вам интересно. (Кстати, есть ли лучший способ, чем перенести все поля, идущие вниз по операторам WITH?)
Результаты выглядят неправильно, поэтому я явно делаю что-то не так:
РЕДАКТИРОВАТЬ Я переделал расчеты в EPSG: 3785, и результаты немного отличаются, но все еще не правильно:
Мой вопрос, где недостатки в этом процессе. Я неправильно понимаю, что делает ST_Azimuth? Есть ли проблема с CRS? Что-то еще вообще? Или, может быть, есть гораздо более простой способ сделать это?
Ответы:
У меня было прозрение. Это довольно обыденно. Я оставил одну важную информацию для PostGIS, чтобы вычислить правильный угол.
Я рассчитывал угол между двумя точками, пересекающими внешнюю поверхность небольшого буфера. Чтобы вычислить угол пересечения, мне нужно рассчитать оба угла между обеими точками на внешней стороне буфера и точкой пересечения двух линейных объектов и вычесть их.
Я обновил полный SQL , но вот что заметно:
источник
ST_IntersectionAngle(...
?Мне недавно пришлось рассчитывать то же самое, но я выбрал более простой и, вероятно, более быстрый подход.
Чтобы найти дополнительные точки для вычисления азимута, я просто проверяю пермириаду длины за пересечением (или после того, в редком случае, когда это происходит в самом начале линии), используя ST_Line_Locate_Point и ST_Line_Interpolate_Point :
Пермириада была произвольной, и для более последовательных результатов было бы лучше использовать абсолютное смещение. Например, чтобы заранее проверить 20 м, вы должны изменить 0,0001 на
20/ST_Length(line1)
и20/ST_Length(line2)
соответственно.источник