6 votos

Crear una cadena de líneas de la geometría de la calle

Actualmente estoy enfrentando tiempos difíciles tratando de crear una línea simplificada de una calle de la geometría.
Los datos que estoy utilizando actualmente proviene de OpenStreetMap, utilizando osm2pgsql.(Lo que significa PostGIS, pero estoy abierto a soluciones que no la use, o uso de código externo, como C, JS, o lo que sea).

El problema: Necesito crear una versión simplificada de la cadena de la línea de calles, sin embargo, la mayoría de las calles tienen varios segmentos, tales como: Line segment example

En este ejemplo, la calle se bifurca y segmentados, la GeoJSON está disponible aquí.

La descarga de los puntos de la calle es útil que podría ser convertido a una cadena de la línea, sin embargo, su pedido está en mal estado, provocando bizzare de la línea de formaciones. Yo podría resolver parcialmente este problema pedidos por lon/lat o lat/lon, pero en varios casos de los puntos en el mismo eje o por la geometría del ángulo, no de orden que les corresponda, y por lo tanto, no funciona para todas las calles.

Points and ordering examples

Algunas soluciones que se me ocurrió:

  • El uso de ST_Buffer en cada segmento, de unión, y ST_ApproximateMedialAxis en la geometría resultante. No funcionaba porque algunas calles, con un generoso búfer de tener a todos los segmentos de tocarse el uno al otro y también ST_ApproximateMedialAxis no son siempre el resultado de una cadena de líneas (No una función de la culpa, es el comportamiento esperado).
  • Ordenar por LAT/LON ~ LON/LAT y la creación de una línea del resultado: Además de no funcionar como se explicó anteriormente.
  • El uso de ST_LineMerge: Nope en las calles no funciona, pero en bifurcada o segmentado calles, se produce un error, como se explica aquí.
  • Iterando sobre los puntos para crear una línea desde cada punto del vecino más cercano: Falla debido a la incapacidad para encontrar el verdadero primer y último puntos.

La tarea más difícil hasta ahora es llegar a los puntos más lejanos del conjunto dado, para definir el primer y el último punto, consiguiendo de esta información podría resolver el problema para mí, pero estoy despistado hasta ahora?

Pensé acerca del uso de ST_VoronoiPolygons, pero no tengo idea de cómo extraer algunos son el resultado de eso?

3voto

A R Puntos 96

He encontrado una solución que se ajusta a mis necesidades:

  1. Volcado de todos los puntos de una calle de la geometría.
  2. Recoger todos los puntos, crear un Diagrama de Voronoi de la colección, y luego Volcar las geometrías que los dividen en individuales, disponible polígonos.
  3. Por último, el fin de los polígonos a partir de su área, de limitar el resultado a 2 (2 mayores polígonos, el primero y el último de los puntos)

Esto es lo que se ve de línea al final:

SELECT *
FROM
  (SELECT (ST_DUMP(St_voronoipolygons(St_collect(dumpedpoints.geometry)))).geom AS polygons
   FROM
     (SELECT (St_dumppoints(geometry)).geom AS geometry
      FROM <your TABLE>
      WHERE <your conditions> ) AS dumpedpoints) AS voronoid
ORDER BY ST_Area(voronoid.polygons) DESC
LIMIT 2

Con eso en la mano, soy capaz de consulta que el punto está en el interior del dado polígonos con ST_Within.

Desde que, teniendo el primer y el último punto, me escribió un JS que, dado un punto, se encuentra con el vecino más cercano, almacenamiento de datos, vaya a la encontró vecino, encontrar a su vecino y repita esto hasta que todos los puntos son iterado.

/** Each point has a index inside, that's created sequentially, apart from the first OR last point, wich is always 0 so the code has the first iteration **/

const linePoints = [];
const copy = [...pointsCollection]; /** We create a iterable copy */

const points = copy.reduce(( Neighbor, Current, Index, Array ) => {

    /** Avoid iterations over nulls */
    if (Neighbor === null ) { return null } 

    /** If it's the last point, he doesn't have any neighbors */
    if(Neighbor.index + 1 === Array.length) { return null }; 

    /** Remove itself from the points list, we do that so he doesn't match with himself */
    pointsCollection.splice(pointsCollection.findIndex(item => item.index === Neighbor.index), 1) 

    /** Your choice function of GeoLib */
    let Nearest = nearestPoint(Neighbor, pointsCollection);
    /** Push to the final list */
    linePoints.push(Nearest);

    /** Set the Neighbor varible of the next iteration as the Neighbor found in this */
    return Nearest;

}, pointsCollection[0]); /** Set the initial value, in our case, the first or last point */

El resultado de esa operación es un proceso secuencial de la matriz que puede ser utilizado para crear una cadena de líneas.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X