PostGIS - zdobądź punkt w linii lub wielokącie

10

Potrzebuję uzyskać punkt środkowy linii lub wielokąta, aby zrobić markerdla mojej aplikacji. Aby po kliknięciu znacznika pojawiła się geometria (linia lub wielokąt). Kiedyś ST_Centroidto działało.

Rezultat jest taki, jak się spodziewałem w przypadku niektórych wielokątów lub linii, których centroidy są poza geometrią. Dla tych linii lub wielokątów chciałbym uzyskać „najbardziej środkowy punkt”, ale wewnątrz geometrii.

W jaki sposób mogę to zrobić? Czy jest jakieś rozwiązanie?

Jose Hermosilla Rodrigo
źródło

Odpowiedzi:

9

Z dokumentu: ST_PointOnSurface - Zwraca PUNKT, który na pewno leży na powierzchni.

WKT
źródło
4
Dla linii ST_LineInterpolatePoint z ułamkiem 0,5 powinno być idealne postgis.net/docs/manual-2.1/ST_LineInterpolatePoint.html
user30184
ST_PointOnSurface () działa z Lines! (dzięki Postgis)
WKT,
Tak! Masz rację @ user30184, ponieważ wydaje się, że dla linii ST_PointOnSurface () ma dowolny punkt, nie jestem pewien, ale w przykładzie doc bierze pierwszy punkt LineString.
Jose Hermosilla Rodrigo,
7

W moim przypadku mam każdą geometrię w tabelach disctint. To co zrobiłem to:

  1. Dla linii -> ST_LineInterpolatePoint()z współczynnikiem 0,5.
  2. W przypadku wielokątów -> Sprawdź, czy ST_Centroid()jest w swojej geometrii. Jeśli tak, ST_Centroid()to najlepszy wybór, jeśli nie ja wybieram PointOnSurface().

Oto zapytanie:

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
źródło
5
Operator && sprawdza tylko bbox. Możesz użyć ST_intersects ().
WKT,
Masz rację. Myliłem się. Zaktualizuję moją odpowiedź. Dzięki!
Jose Hermosilla Rodrigo