24

How can I find a point that is guaranteed to be within a given polygon in PostGIS?

I am aware of the ST_Centroid function. However, the centroid is not always within a polygon, see below:

a centroid lying outside a polygon

Furthermore, I would like to avoid using a point that is on the polygon boundary, but rather want one that is inside the boundary (and not inside a hole in donut shaped polygons).

dbaston
  • 13,048
  • 3
  • 49
  • 81
fmark
  • 9,381
  • 9
  • 39
  • 45

2 Answers2

17

If you're looking for a PostGIS function that will tell you a point that's inside your polygon then the ST_PointOnSurface function may give you what you need.

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)
dbaston
  • 13,048
  • 3
  • 49
  • 81
Ian Dodd
  • 186
  • 1
  • 2
6

Found this function on the PostGIS mailinglist. I guess it is what you require:

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;
Skinkie
  • 123
  • 1
  • 5
  • I like that this solution gives a point which is closer to the centroid than ST_PointOnSurface by itself, but it does also produce a point which is closer to the edge of the polygon. ST_PointOnSurface seems to choose a point which is as far away from any edges as possible. I suppose it's a matter of taste, as far as choosing the solution right for you. – dslh Nov 05 '13 at 23:38