Tengo polígonos almacenados en la base de datos como (Multi)Polígonos usando PostgreSQL (13.1
) y PostGIS (3.0.2
) con un srid de 4326 (también conocido como states
). Una línea generada por el usuario (LineString
) (llamada ruta) se usará para encontrar todas las intersecciones de esos polígonos a lo largo de esa línea.
Puedo obtener todos los puntos de intersección utilizando la siguiente consulta (utilizando esta ruta / línea):
SELECT states.*
, (ST_Dump(ST_Intersection(ST_Boundary(states.boundary_polygon::geometry), :route::geometry))).geom AS punto
FROM states
WHERE ST_Intersects(:route::geometry, states.boundary_polygon::geometry)
El problema es que no puedo encontrar una forma de mantener los puntos de intersección en orden a lo largo de la ruta. He intentado ordenar por distancia desde el punto de inicio, pero el problema es que necesito ambos puntos por cada state
, lo que posiblemente cause que el orden sea incorrecto.
Por ejemplo, tengo una ruta que atraviesa los estados A, B, C. Necesito el punto de inicio al cruce de la frontera de A. Luego necesito el cruce de la frontera de B a C. Luego de C al punto final.
La razón por la que necesito esto es para calcular la distancia, la cual actualmente manejo en una consulta separada ya que todavía no estoy seguro de cómo combinarlas en una sola consulta. Soy totalmente nuevo en PostGIS y mi rol principal no es como administrador de BD.
He intentado:
ORDER BY ST_LineLocatePoint(ST_GeomFromText(:route_str, 4326)::geometry, (ST_Dump(ST_Intersection(ST_Boundary(states.boundary_polygon::geometry),ST_GeomFromText(:route_str, 4326)::geometry))).geom)
y
ORDER BY :start_point <-> point
, :start_point <-> states_with_breakpoints.boundary_polygon::geometry
, :end_point <-> point
, :end_point <-> states_with_breakpoints.boundary_polygon::geometry
pero aún así no obtengo el orden correcto.
Orden esperado: punto de inicio, frontera de A, frontera de B, frontera de C, punto final Orden de salida: punto de inicio, frontera de B, frontera de A, frontera de C, punto final
Soy muy principiante en esto y he estado buscando en la web y utilizando la documentación de PostGIS para llegar hasta donde estoy ahora.
Info del entorno: PostgreSQL 13.1
, POSTGIS="3.0.2 2fb2a18" [EXTENSION] PGSQL="130" GEOS="3.8.1-CAPI-1.13.3" PROJ="7.1.1" LIBXML="2.9.10" LIBJSON="0.15"
, [RoR] Ruby 2.5.3
, Rails 5.2.4.2
(próximamente actualizaré a 5.2.4.4
), rgeo gem 2.1.1
Solo para que lo tengas, esta es la consulta que estoy usando para calcular la distancia:
SELECT ST_Length(
ST_LineSubstring(
route,
LEAST(ST_LineLocatePoint(route, start_point), ST_LineLocatePoint(route, end_point)),
GREATEST(ST_LineLocatePoint(route, end_point), ST_LineLocatePoint(route, start_point))
)::geography
) AS distancia
FROM (
SELECT :route AS route
, :start_point AS start_point
, :end_point AS end_point
) AS subconsulta_distancia
Mi objetivo final es tener una consulta que divida la ruta en cada estado y obtenga la distancia de cada segmento de ruta en ese estado. Puede haber varios segmentos en cada estado. Lo que necesitaré son los puntos de la frontera para cada estado (donde la ruta se cruza) y la longitud de cada segmento.
Estoy abierto a otras ideas o sugerencias si la forma en que estoy abordando esto es incorrecta o imposible. Me gustaría que la consulta se ejecute en menos de 1 segundo si es posible.
Consulta actualizada:
SELECT s.id, s.abv, dmp.geom
FROM states AS s,
LATERAL ST_Dump(ST_Intersection(ST_Boundary(s.geom), :route::GEOMETRY)) AS dmp
WHERE ST_Intersects(s.geom, :route::GEOMETRY)
ORDER BY dmp.path
Resultados:
El orden debería ser: OH -> WV, WV -> PA, PA -> WV, WV -> MD, MD -> PA, PA -> NJ, NJ -> NY
SELECT s.id, s.abv, dmp.geom
FROM states AS s,
LATERAL ST_Dump(ST_Intersection(s.boundary_polygon::geometry, :route::geometry)) AS dmp
WHERE ST_Intersects(s.boundary_polygon::geometry, :route::geometry)
ORDER BY dmp.path
Ahora esto no está devolviendo los puntos de la frontera y sigue fuera de orden.
Actualización 2023-11-16
ENV: POSTGIS="3.1.4 ded6c34" [EXTENSION] PGSQL="140" GEOS="3.9.0-CAPI-1.16.2" PROJ="7.2.1" LIBXML="2.9.10" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)"
0 votos
Si solo deseas la longitud de la ruta en cada estado, puedes simplemente calcular la longitud de la intersección de la ruta con cada polígono de estado.
0 votos
@dr_jts ¿cómo podría hacer esto?
0 votos
Ver respuesta abajo.