Jak znaleźć punkt wewnątrz wielokąta w PostGIS?


22

Jak mogę znaleźć punkt, który z pewnością znajdzie się w obrębie danego wielokąta w PostGIS?

Jestem świadomy tej ST_Centroidfunkcji. Środek ciężkości nie zawsze jest jednak w obrębie wielokąta, patrz poniżej:

centroid leżący poza wielokątem

Ponadto chciałbym unikać używania punktu znajdującego się na granicy wielokąta, ale raczej takiego, który znajduje się wewnątrz granicy (a nie w otworze w wielokątach w kształcie pączka).

Odpowiedzi:


17

Jeśli szukasz funkcji PostGIS, która powie ci punkt wewnątrz twojego wielokąta, to funkcja ST_PointOnSurface może ci dać to, czego potrzebujesz.

SELECT 
   ST_AsText(ST_PointOnSurface('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'::geometry));

   st_astext
----------------
 POINT(2.5 2.5)
(1 row)

6

Znalazłem tę funkcję na liście mailingowej PostGIS. Chyba właśnie tego potrzebujesz:

CREATE OR REPLACE FUNCTION point_inside_geometry(param_geom geometry)
  RETURNS geometry AS
$$
  DECLARE
     var_cent geometry := ST_Centroid(param_geom);
     var_result geometry := var_cent;
  BEGIN
  -- If the centroid is outside the geometry then 
  -- calculate a box around centroid that is guaranteed to intersect the geometry
  -- take the intersection of that and find point on surface of intersection
 IF NOT ST_Intersects(param_geom, var_cent) THEN
  var_result := ST_PointOnSurface(ST_Intersection(param_geom, ST_Expand(var_cent, ST_Distance(var_cent,param_geom)*2) ));
 END IF;
 RETURN var_result;
  END;
  $$
  LANGUAGE plpgsql IMMUTABLE STRICT
  COST 100;

Podoba mi się, że to rozwiązanie daje punkt, który jest bliżej środka ciężkości niż sam ST_PointOnSurface, ale tworzy również punkt, który jest bliżej krawędzi wielokąta. ST_PointOnSurface wydaje się wybierać punkt, który jest jak najdalej od jakichkolwiek krawędzi. Podejrzewam, że jest to kwestia gustu, jeśli chodzi o wybór odpowiedniego rozwiązania dla ciebie.
dslh,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.