Changes between Initial Version and Version 1 of UserWikiRandomPoints


Ignore:
Timestamp:
Jun 7, 2011, 5:10:21 AM (13 years ago)
Author:
Mike Taves
Comment:

add set-returning function

Legend:

Unmodified
Added
Removed
Modified
  • UserWikiRandomPoints

    v1 v1  
     1= Random Points in Polygon =
     2This set-returning function generates {{{num_points}}} uniform random points within a polygon geometry {{{geom}}}. See examples below.
     3{{{
     4#!sql
     5CREATE OR REPLACE FUNCTION RandomPointsInPolygon(geom geometry, num_points integer)
     6  RETURNS SETOF geometry AS
     7$BODY$DECLARE
     8  target_proportion numeric;
     9  n_ret integer := 0;
     10  loops integer := 0;
     11  x_min float8;
     12  y_min float8;
     13  x_max float8;
     14  y_max float8;
     15  srid integer;
     16  rpoint geometry;
     17BEGIN
     18  -- Get envelope and SRID of source polygon
     19  SELECT ST_XMin(geom), ST_YMin(geom), ST_XMax(geom), ST_YMax(geom), ST_SRID(geom)
     20    INTO x_min, y_min, x_max, y_max, srid;
     21  -- Get the area proportion of envelope size to determine if a
     22  -- result can be returned in a reasonable amount of time
     23  SELECT ST_Area(geom)/ST_Area(ST_Envelope(geom)) INTO target_proportion;
     24  RAISE DEBUG 'geom: SRID %, NumGeometries %, NPoints %, area proportion within envelope %',
     25                srid, ST_NumGeometries(geom), ST_NPoints(geom),
     26                round(100.0*target_proportion, 2) || '%';
     27  IF target_proportion < 0.0001 THEN
     28    RAISE EXCEPTION 'Target area proportion of geometry is too low (%)',
     29                    100.0*target_proportion || '%';
     30  END IF;
     31  RAISE DEBUG 'bounds: % % % %', x_min, y_min, x_max, y_max;
     32 
     33  WHILE n_ret < num_points LOOP
     34    loops := loops + 1;
     35    SELECT ST_SetSRID(ST_MakePoint(random()*(x_max - x_min) + x_min,
     36                                   random()*(y_max - y_min) + y_min),
     37                      srid) INTO rpoint;
     38    IF ST_Contains(geom, rpoint) THEN
     39      n_ret := n_ret + 1;
     40      RETURN NEXT rpoint;
     41    END IF;
     42  END LOOP;
     43  RAISE DEBUG 'determined in % loops (% efficiency)', loops, round(100.0*num_points/loops, 2) || '%';
     44END$BODY$
     45  LANGUAGE plpgsql VOLATILE
     46  COST 100
     47  ROWS 1000;
     48ALTER FUNCTION RandomPointsInPolygon(geometry, integer) OWNER TO postgres;
     49}}}
     50
     51== Examples ==
     52{{{
     53#!sql
     54-- Return 10 random points/rows
     55SELECT ST_AsText(RandomPointsInPolygon('POLYGON ((10 20, 30 60, 50 20, 10 20))', 10));
     56
     57-- Or 10 random points as a single MultiPoint
     58SELECT ST_AsText(ST_Union(geom))
     59FROM RandomPointsInPolygon('POLYGON ((10 20, 30 60, 50 20, 10 20))', 10) AS geom
     60}}}
     61
     62Now for a more complicated and practical example using a geopolitical polygon of the [http://www.aprsworld.net/gisdata/world/uncompressed/ world] table, create 10000 random points in India:
     63{{{
     64#!sql
     65CREATE TABLE india_random_points
     66(
     67  gid serial NOT NULL,
     68  CONSTRAINT india_random_points_pkey PRIMARY KEY (gid)
     69);
     70SELECT AddGeometryColumn('india_random_points', 'geom', 4326, 'POINT', 2);
     71
     72# Populate table with 10000 random points within India
     73INSERT INTO india_random_points(geom)
     74SELECT RandomPointsInPolygon(geom, 10000)
     75FROM world WHERE name='INDIA';
     76}}}
     77
     78== See also ==
     79 * UserWikiRandomPoint : create one random point