Changes between Version 1 and Version 2 of UserWikiRandomPoints


Ignore:
Timestamp:
06/07/11 05:11:04 (14 years ago)
Author:
mwtoews
Comment:

redirect

Legend:

Unmodified
Added
Removed
Modified
  • UserWikiRandomPoints

    v1 v2  
    1 = Random Points in Polygon =
    2 This set-returning function generates {{{num_points}}} uniform random points within a polygon geometry {{{geom}}}. See examples below.
    3 {{{
    4 #!sql
    5 CREATE 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;
    17 BEGIN
    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) || '%';
    44 END$BODY$
    45   LANGUAGE plpgsql VOLATILE
    46   COST 100
    47   ROWS 1000;
    48 ALTER FUNCTION RandomPointsInPolygon(geometry, integer) OWNER TO postgres;
    49 }}}
    50 
    51 == Examples ==
    52 {{{
    53 #!sql
    54 -- Return 10 random points/rows
    55 SELECT ST_AsText(RandomPointsInPolygon('POLYGON ((10 20, 30 60, 50 20, 10 20))', 10));
    56 
    57 -- Or 10 random points as a single MultiPoint
    58 SELECT ST_AsText(ST_Union(geom))
    59 FROM RandomPointsInPolygon('POLYGON ((10 20, 30 60, 50 20, 10 20))', 10) AS geom
    60 }}}
    61 
    62 Now 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
    65 CREATE TABLE india_random_points
    66 (
    67   gid serial NOT NULL,
    68   CONSTRAINT india_random_points_pkey PRIMARY KEY (gid)
    69 );
    70 SELECT AddGeometryColumn('india_random_points', 'geom', 4326, 'POINT', 2);
    71 
    72 # Populate table with 10000 random points within India
    73 INSERT INTO india_random_points(geom)
    74 SELECT RandomPointsInPolygon(geom, 10000)
    75 FROM world WHERE name='INDIA';
    76 }}}
    77 
    78 == See also ==
    79  * UserWikiRandomPoint : create one random point
     1UserWikiRandomPoint