#postgis #openstreetmap
#postgis #openstreetmap
Вопрос:
Мне нужно получить длину фрагмента геометрического объекта linestring внутри круга (точка радиус).
В настоящее время я использую ST_DWithin
функцию, но, к сожалению, она возвращает полный объект, а не часть объекта внутри области. Действительно, изменение радиуса (от 100 до 70) не изменяет полученную длину.
osm_data=# select highway, st_length(way) from planet_osm_line where ST_DWITHIN(ST_Transform(way,4326),ST_GeomFromText('POINT(4.1884918 51.144580)',4326)::geography,100) and highway is not null;
highway | st_length
-------------- ------------------
motorway | 5079.24632083105
unclassified | 1110.56834915499
motorway | 1499.83459080537
(3 rows)
osm_data=# select highway, st_length(way) from planet_osm_line where ST_DWITHIN(ST_Transform(way,4326),ST_GeomFromText('POINT(4.1884918 51.144580)',4326)::geography,70) and highway is not null;
highway | st_length
-------------- ------------------
motorway | 5079.24632083105
unclassified | 1110.56834915499
motorway | 1499.83459080537
(3 rows)
Ответ №1:
ST_DWithin
используется для выбора геометрий, которые по крайней мере частично находятся на указанном расстоянии от контрольной точки.
Чтобы вычислить фактическую длину (или площадь для полигонов) внутри, вам нужно будет вычислить пересечение.
select highway,
st_length(way) full_length,
st_length(
ST_INTERSECTION(
ST_Transform(way,4326)::geography,
ST_BUFFER(
ST_GeomFromText('POINT(4.1884918 51.144580)',4326)::geography,
100)
)
)
from planet_osm_line
where
ST_DWITHIN(
ST_Transform(way,4326)::geography,
ST_GeomFromText('POINT(4.1884918 51.144580)',4326)::geography,100)
and highway is not null;
Чтобы оптимизировать этот запрос, вы бы использовали
WITH buff as (
SELECT ST_BUFFER(
ST_GeomFromText('POINT(4.1884918 51.144580)',4326)::geography,
1000) as geog)
select highway,
st_length(way) full_length,
st_length(
ST_INTERSECTION(
ST_Transform(way,4326)::geography,
buff.geog
)
)
from osm.osm_line
INNER JOIN buff
ON ST_DWITHIN(
ST_Transform(way,4326),
buff.geog,
1000)
where highway is not null;
Пожалуйста, обратите внимание, что буфер является лишь приближением к окружности, поэтому результат может быть немного отклонен