Здравствуйте! Подскажите, пожалуйста, не могу найти ответ на простой, казалось бы, вопрос.
Пишем плагины под axipy (версия 7.0.2). Не можем понять принцип расчета расстояния между объектами, не являющимися точками, например, кратчайшее расстояние между полигонами, или между полигоном и точкой.
В MapInfo все считалось вполне логично, в Аксиоме же метод Geometry.get_distance(), такое ощущение, возвращает расстояние между центроидами. Так же не должно быть, верно? Изучил вдоль и поперек мануал axipy, не нашел подходящего способа найти расстояние. Помогите, пожалуйста.
Расстояние между объектами
Re: Расстояние между объектами
Версии 7.0.2 пока нет, есть только версия 7.0.1
Для точного расчёта кратчайшего расстояния между двумя геометрическими объектами (включая полигоны, линии, точки) рекомендуется использовать модуль Shapely, который поставляется вместе с axipy.
Ниже приведён универсальный пример функции, которая корректно вычисляет кратчайшее расстояние между двумя геометриями с учётом системы координат и режима расчёта
Пример использования:
Для точного расчёта кратчайшего расстояния между двумя геометрическими объектами (включая полигоны, линии, точки) рекомендуется использовать модуль Shapely, который поставляется вместе с axipy.
Ниже приведён универсальный пример функции, которая корректно вычисляет кратчайшее расстояние между двумя геометриями с учётом системы координат и режима расчёта
Code: Select all
import axipy
import shapely
from shapely.ops import nearest_points
def calculate_shortest_distance(
geom1: axipy.Geometry,
geom2: axipy.Geometry,
calc_mode: axipy.CalcMode = axipy.CalcMode.ELLIPSOID,
units: axipy.LinearUnits = axipy.LinearUnits.m
) -> float:
"""
Возвращает длину кратчайшего отрезка между двумя геометриями.
Автоматически согласует системы координат и использует геодезические расчёты.
Параметры:
geom1: первая геометрия.
geom2: вторая геометрия.
calc_mode: режим расчёта (PLANE, SPHERE, ELLIPSOID).
units: единицы измерения (по умолчанию — метры).
Возвращает:
Длина в указанных единицах.
"""
if not geom1 or not geom2:
raise ValueError("Геометрии не должны быть пустыми.")
if not geom1.is_valid or not geom2.is_valid:
raise ValueError("Обе геометрии должны быть валидными.")
cs1 = geom1.coordsystem
cs2 = geom2.coordsystem
if cs1 is None and cs2 is None:
raise RuntimeError("Обе геометрии не имеют системы координат — расчёт невозможен.")
target_cs = cs1 or cs2
if cs1 and cs2 and not cs1.is_equal(cs2, ignore_rect=True):
geom2 = geom2.reproject(target_cs)
# Конвертация в Shapely
try:
s1 = shapely.from_wkb(geom1.to_wkb())
s2 = shapely.from_wkb(geom2.to_wkb())
except Exception as e:
raise RuntimeError(f"Ошибка конвертации в Shapely: {e}")
# Ближайшие точки
try:
pt1, pt2 = nearest_points(s1, s2)
except Exception as e:
raise RuntimeError(f"Ошибка поиска ближайших точек: {e}")
# Линия между точками
line = axipy.Line((pt1.x, pt1.y), (pt2.x, pt2.y), target_cs)
return line.get_length(units, calc_mode)
Code: Select all
point = axipy.Point(1_000_000, 1_000_000, axipy.CoordSystem.from_string('epsg:3395'))
polygon = axipy.Polygon(
(0, 0), (200_000, 700_000), (800_000, 700_000), (700_000, 300_000),
axipy.CoordSystem.from_string('epsg:3857')
)
dist_ell = calculate_shortest_distance(point, polygon, axipy.CalcMode.ELLIPSOID)
dist_sph = calculate_shortest_distance(point, polygon, axipy.CalcMode.SPHERE)
dist_pln = calculate_shortest_distance(point, polygon, axipy.CalcMode.PLANE)
print(f"Эллипсоид: {dist_ell:.2f} м")
print(f"Сфера: {dist_sph:.2f} м")
print(f"Плоскость: {dist_pln:.2f} м")
Re: Расстояние между объектами
Спасибо большое за информацию и вариант решения проблемы! Будем пробовать, надеюсь, массовая конвертация посредством wkb отработает приемлемо быстро.
Честно говоря, меня удивило отсутствие такой функции из коробки, особенно после MapInfo/MapBasic, где расстояние считается именно между ближайшими точками. Мы думали, что что-то делаем не так, потому что в документации Axipy написано, что get_distance "считает расстояние между объектами", а в случае двух полигонов последнее что приходит в голову - это что программа посчитает почему-то расстояние между центроидами. Например, два полигона соприкасаются - очевидно ведь, что расстояние между ними должно быть равно 0. А get_distance выдаст совсем другое число.
Честно говоря, меня удивило отсутствие такой функции из коробки, особенно после MapInfo/MapBasic, где расстояние считается именно между ближайшими точками. Мы думали, что что-то делаем не так, потому что в документации Axipy написано, что get_distance "считает расстояние между объектами", а в случае двух полигонов последнее что приходит в голову - это что программа посчитает почему-то расстояние между центроидами. Например, два полигона соприкасаются - очевидно ведь, что расстояние между ними должно быть равно 0. А get_distance выдаст совсем другое число.
Re: Расстояние между объектами
Конвертация геометрий через WKB работает быстро и эффективно. Этот подход хорошо зарекомендовал себя на практике и позволяет достичь высокой производительности при передаче геометрий между системой и внешними библиотеками.
На данный момент во многих операциях с геометрией в Аксиоме используется библиотека GEOS — мощный и проверенный инструмент для работы с геоданными. Библиотека Shapely также основана на GEOS, что делает её логичным выбором для расширения функциональности.
В настоящее время мы активно обсуждаем возможность отказа от создания собственных Python-обёрток для каждой функции GEOS. Вместо этого рассматривается предоставление простых и удобных методов для конвертации геометрий между внутренним форматом axipy и объектами Shapely (и обратно). Это позволит:
На данный момент во многих операциях с геометрией в Аксиоме используется библиотека GEOS — мощный и проверенный инструмент для работы с геоданными. Библиотека Shapely также основана на GEOS, что делает её логичным выбором для расширения функциональности.
В настоящее время мы активно обсуждаем возможность отказа от создания собственных Python-обёрток для каждой функции GEOS. Вместо этого рассматривается предоставление простых и удобных методов для конвертации геометрий между внутренним форматом axipy и объектами Shapely (и обратно). Это позволит:
- Снизить нагрузку на разработку и сопровождение (не нужно дублировать функциональность GEOS);
- Обеспечить пользователям прямой доступ к полному функционалу Shapely;
- Упростить интеграцию для тех, кто уже знаком с Shapely.