PostGIS - Obtenha um ponto dentro de uma linha ou polígono

10

Preciso obter o ponto central de uma linha ou polígono para fazer markermeu aplicativo. Assim, quando você clica em um marcador, a geometria aparece (linha ou polígono). Eu costumava ST_Centroidfazer isso funcionar.

O resultado é o que eu esperava, aninhar alguns polígonos ou linhas cujos centróides estão fora da geometria. O que eu gostaria dessas linhas ou polígonos é obter o "ponto mais central", mas dentro da geometria.

Como posso fazer isso? Há uma solução?

Jose Hermosilla Rodrigo
fonte

Respostas:

9

Do doc: ST_PointOnSurface - Retorna um PONTO garantido para ficar na superfície.

WKT
fonte
4
Para as linhas ST_LineInterpolatePoint com fração 0.5, deve ser perfeito postgis.net/docs/manual-2.1/ST_LineInterpolatePoint.html
user30184
ST_PointOnSurface () trabalha com linhas! (thx Postgis)
WKT
Sim! Você está certo @ user30184 porque parece que, para as linhas ST_PointOnSurface (), um ponto é arbitrário, não tenho certeza, mas no exemplo do documento, é o primeiro ponto de um LineString.
Jose Hermosilla Rodrigo
7

No meu caso, tenho cada geometria em tabelas disctint. O que eu fiz foi:

  1. Para linhas -> ST_LineInterpolatePoint()com fator 0,5.
  2. Para polígonos -> Teste se ST_Centroid()está dentro de sua geometria. Se assim ST_Centroid()for , é a melhor escolha, se não eu escolher PointOnSurface().

Aqui está a consulta:

SELECT
    CASE WHEN (SELECT the_geom FROM points WHERE gid = d.gid) IS NOT NULL
    THEN (SELECT the_geom FROM points WHERE gid = d.gid)
    WHEN (SELECT the_geom FROM lines WHERE gid = d.gid) IS NOT NULL
    THEN ST_LineInterpolatePoint((SELECT the_geom FROM lines WHERE gid = d.gid), 0.5)
    WHEN (SELECT the_geom FROM polygons WHERE gid = d.gid AND ST_Intersects(ST_Centroid(the_geom),the_geom)) IS NOT NULL
    THEN ST_Centroid((SELECT the_geom FROM polygons WHERE gid = d.gid))
    ELSE ST_PointOnSurface((SELECT the_geom FROM polygons WHERE gid = d.gid))
    END AS center
FROM someTable d
Jose Hermosilla Rodrigo
fonte
5
O operador && verifica apenas bbox. Você pode querer usar ST_intersects ().
WKT
Você está certo. Eu estava errado. Vou atualizar minha resposta. Obrigado!
Jose Hermosilla Rodrigo