Generate points that lie inside polygonCentroid Point inside wrong PolygonHow to create regular point grid...
Being asked to review a paper in conference one has submitted to
Why is it "take a leak?"
Is divide-by-zero a security vulnerability?
Why do phishing e-mails use faked e-mail addresses instead of the real one?
What do you call the early days of flu recovery
Split a number into equal parts given the number of parts
Is there a limit on the maximum number of future jobs queued in an org?
What is a term for a function that when called repeatedly, has the same effect as calling once?
What is better: yes / no radio, or simple checkbox?
When to use mean vs median
Every subset equal to original set?
Four buttons on a table
How to use math.log10 function on whole pandas dataframe
How to fix my table, centering of columns
Create chunks from an array
How does signal strength relate to bandwidth?
3.5% Interest Student Loan or use all of my savings on Tuition?
Where is this quote about overcoming the impossible said in "Interstellar"?
What is the meaning of "notice to quit at once" and "Lotty points”
The Ohm's law calculations of the parts do not agree with the whole
Should we avoid writing fiction about historical events without extensive research?
Would the melodic leap of the opening phrase of Mozart's K545 be considered dissonant?
Giving a talk in my old university, how prominently should I tell students my salary?
What is the difference between 主菜 and 主食?
Generate points that lie inside polygon
Centroid Point inside wrong PolygonHow to create regular point grid inside a polygon in Postgis?How do I make a heat or Choropleth map that uses polygons in QGis?Generate random points in selected areas forIndian Latitude Longitude valuesDistribute points respect to features using Quantum GisGenerate random points in polygon. Algorithm questionAutomatic generation of equidistant points inside a polygon in QGIS?How do I calculate the distance of a segment of line that is inside a polygon?Generate random points in polygon. Algorithm questionDetermine which points are contained inside a given polygonHow to generate random points that lie on a line in QGIS?Generate random points within a polygon with minimum distances in QGIS 2.14Generating random number of points in each polygon based on polygon area?Keeping polygon's field when generating random points within overlapping polygonsGenerating random points inside polygons that capture values from multiple attribute fieldsCount points in polygon (weighted) for multiple attributes in QGIS 3 in one go
I have polygon feature and want to be able to generate points inside it. I need this for one classification task.
Generating random points until one is inside the polygon wouldn't work because it's really unpredictable the time it takes.
python qgis polygon ogr
|
show 1 more comment
I have polygon feature and want to be able to generate points inside it. I need this for one classification task.
Generating random points until one is inside the polygon wouldn't work because it's really unpredictable the time it takes.
python qgis polygon ogr
2
On the contrary, the time is predictable. It is proportional to the ratio of the polygon's extent area divided by the polygon's area, times the time needed to generate and test a single point. The time varies a little, but the variation is proportional to the square root of the number of points. For largish numbers, this becomes inconsequential. Break tortuous polygons into more compact pieces if necessary to get this area ratio down to a low value. Only fractal polygons will give you trouble, but I doubt you have them!
– whuber♦
Feb 22 '11 at 18:34
2
possible duplicate of Distribute points respect to features using Quantum Gis
– Pablo
Feb 22 '11 at 21:15
1
and also: gis.stackexchange.com/questions/4663/…
– Pablo
Feb 22 '11 at 21:18
@Pablo: good finds. However, both of those questions are software specific and both concern placing regular arrays of points within polygons, not random points
– whuber♦
Feb 22 '11 at 21:29
agree with whuber difference is random points vs regular point generation within a polygon.
– Mapperz♦
Feb 22 '11 at 22:53
|
show 1 more comment
I have polygon feature and want to be able to generate points inside it. I need this for one classification task.
Generating random points until one is inside the polygon wouldn't work because it's really unpredictable the time it takes.
python qgis polygon ogr
I have polygon feature and want to be able to generate points inside it. I need this for one classification task.
Generating random points until one is inside the polygon wouldn't work because it's really unpredictable the time it takes.
python qgis polygon ogr
python qgis polygon ogr
edited Feb 22 '11 at 20:16
whuber♦
60k11156247
60k11156247
asked Feb 22 '11 at 18:06
user2024user2024
134123
134123
2
On the contrary, the time is predictable. It is proportional to the ratio of the polygon's extent area divided by the polygon's area, times the time needed to generate and test a single point. The time varies a little, but the variation is proportional to the square root of the number of points. For largish numbers, this becomes inconsequential. Break tortuous polygons into more compact pieces if necessary to get this area ratio down to a low value. Only fractal polygons will give you trouble, but I doubt you have them!
– whuber♦
Feb 22 '11 at 18:34
2
possible duplicate of Distribute points respect to features using Quantum Gis
– Pablo
Feb 22 '11 at 21:15
1
and also: gis.stackexchange.com/questions/4663/…
– Pablo
Feb 22 '11 at 21:18
@Pablo: good finds. However, both of those questions are software specific and both concern placing regular arrays of points within polygons, not random points
– whuber♦
Feb 22 '11 at 21:29
agree with whuber difference is random points vs regular point generation within a polygon.
– Mapperz♦
Feb 22 '11 at 22:53
|
show 1 more comment
2
On the contrary, the time is predictable. It is proportional to the ratio of the polygon's extent area divided by the polygon's area, times the time needed to generate and test a single point. The time varies a little, but the variation is proportional to the square root of the number of points. For largish numbers, this becomes inconsequential. Break tortuous polygons into more compact pieces if necessary to get this area ratio down to a low value. Only fractal polygons will give you trouble, but I doubt you have them!
– whuber♦
Feb 22 '11 at 18:34
2
possible duplicate of Distribute points respect to features using Quantum Gis
– Pablo
Feb 22 '11 at 21:15
1
and also: gis.stackexchange.com/questions/4663/…
– Pablo
Feb 22 '11 at 21:18
@Pablo: good finds. However, both of those questions are software specific and both concern placing regular arrays of points within polygons, not random points
– whuber♦
Feb 22 '11 at 21:29
agree with whuber difference is random points vs regular point generation within a polygon.
– Mapperz♦
Feb 22 '11 at 22:53
2
2
On the contrary, the time is predictable. It is proportional to the ratio of the polygon's extent area divided by the polygon's area, times the time needed to generate and test a single point. The time varies a little, but the variation is proportional to the square root of the number of points. For largish numbers, this becomes inconsequential. Break tortuous polygons into more compact pieces if necessary to get this area ratio down to a low value. Only fractal polygons will give you trouble, but I doubt you have them!
– whuber♦
Feb 22 '11 at 18:34
On the contrary, the time is predictable. It is proportional to the ratio of the polygon's extent area divided by the polygon's area, times the time needed to generate and test a single point. The time varies a little, but the variation is proportional to the square root of the number of points. For largish numbers, this becomes inconsequential. Break tortuous polygons into more compact pieces if necessary to get this area ratio down to a low value. Only fractal polygons will give you trouble, but I doubt you have them!
– whuber♦
Feb 22 '11 at 18:34
2
2
possible duplicate of Distribute points respect to features using Quantum Gis
– Pablo
Feb 22 '11 at 21:15
possible duplicate of Distribute points respect to features using Quantum Gis
– Pablo
Feb 22 '11 at 21:15
1
1
and also: gis.stackexchange.com/questions/4663/…
– Pablo
Feb 22 '11 at 21:18
and also: gis.stackexchange.com/questions/4663/…
– Pablo
Feb 22 '11 at 21:18
@Pablo: good finds. However, both of those questions are software specific and both concern placing regular arrays of points within polygons, not random points
– whuber♦
Feb 22 '11 at 21:29
@Pablo: good finds. However, both of those questions are software specific and both concern placing regular arrays of points within polygons, not random points
– whuber♦
Feb 22 '11 at 21:29
agree with whuber difference is random points vs regular point generation within a polygon.
– Mapperz♦
Feb 22 '11 at 22:53
agree with whuber difference is random points vs regular point generation within a polygon.
– Mapperz♦
Feb 22 '11 at 22:53
|
show 1 more comment
9 Answers
9
active
oldest
votes
Start by decomposing the polygon into triangles, then generate points inside those. (For a uniform distribution, weight each triangle by its area.)
2
+1 Simple and effective. It's worth pointing out that uniformly random points can be generated within a triangle with no rejection at all, because there are (easily computed) area-preserving mappings between any triangle and an isosceles right triangle, which is half a square, say the half where the y coordinate exceeds the x coordinate. Generate two random coordinates and sort them to obtain a random point in the isosceles triangle, then map that back to the original triangle.
– whuber♦
Feb 22 '11 at 20:19
+1 I really like the discussion of trilinear coordinates referenced by the article you cite. I suppose this would be amenable to sphere whose surface is represented as a tesselation of triangles. On a projected plane, it wouldn't be a truly random distribution, would it?
– Kirk Kuykendall
Feb 22 '11 at 20:42
@whuber -- +1 back at you. Another way (in the link, but they hand-waved over it) is to reflect the rejected points from the uniformly-sampled quadrilateral across the shared edge and back into the triangle.
– Dan S.
Feb 22 '11 at 21:07
@Kirk -- the citation link is a touch anti-helpful in that it lists a bunch of wrong (non-uniform) sampling methods, including trilinear coordinates, before the "right" way. It doesn't look like there's a direct way to get a uniform sampling w/ trilinear coordinates. I'd approach uniform sampling over the entire sphere by converting random unit vectors in 3d to their lat/lon equivalent, but that's just me. (Unsure about sampling constrained to spherical triangles/polygons.) (Also unsure about truly uniform sampling on e.g. wgs84: just picking angles will bias a bit towards the poles, I think.)
– Dan S.
Feb 22 '11 at 21:15
1
@Dan For uniformly sampling the sphere, use a cylindrical equal-area projection (coordinates are longitude and cosine of latitude). If you want to sample without using a projection, there's a beautiful trick: generate three independent standard normal variates (x,y,z) and project them to the point (Rx/n, Ry/n, R*z/n) where n^2 = x^2 + y^2 + z^2 and R is the earth radius. Convert to (lat, lon) if need be (using authalic latitudes when working on a spheroid). It works because this trivariate normal distribution is spherically symmetric. For sampling triangles, stick to a projection.
– whuber♦
Feb 22 '11 at 21:26
|
show 3 more comments
As you put a QGIS tag on this question: Random Points tool can be used with a boundary layer.

If you are looking for code, the underlying plugin source code should be of help.
Even 5 years later, still really helpful!
– Stranded Kid
Jul 12 '16 at 12:29
add a comment |
You could determine the extent of the polygon, then constrain the random number generation for X and Y values within those extents.
Basic process:
1) Determine maxx, maxy, minx, miny of polygon vertices,
2) Generate random points using these values as bounds
3) Test each point for intersection with your polygon,
4) Stop generating when you have enough points satisfying the intersection test
Here is an algorithm (C#) for the intersection test:
bool PointIsInGeometry(PointCollection points, MapPoint point)
{
int i;
int j = points.Count - 1;
bool output = false;
for (i = 0; i < points.Count; i++)
{
if (points[i].X < point.X && points[j].X >= point.X || points[j].X < point.X && points[i].X >= point.X)
{
if (points[i].Y + (point.X - points[i].X) / (points[j].X - points[i].X) * (points[j].Y - points[i].Y) < point.Y)
{
output = !output;
}
}
j = i;
}
return output;
}
add a comment |
There are some good libraries out there that do most of the heavy lifting for you.
Example using shapely in python.
import random
from shapely.geometry import Polygon, Point
def get_random_point_in_polygon(poly):
(minx, miny, maxx, maxy) = poly.bounds
while True:
p = Point(random.uniform(minx, maxx), random.uniform(miny, maxy))
if poly.contains(p):
return p
p = Polygon([(0, 0), (0, 2), (1, 1), (2, 2), (2, 0), (1, 1), (0, 0)])
point_in_poly = get_random_point_in_polygon(mypoly)
2
Shouldn't it be from shapely.geometry import...?
– PyMapr
May 17 '17 at 10:48
add a comment |
If R is an option, see ?spsample in the sp package. The polygons can be read in from any GDAL-supported format built into the rgdal package, and then spsample works directly on imported object with a variety of sampling options.
+1 - Since R is open source if one wants to replicate you can always go into the source to see how they are done. For point patterns one may also be interested in the simulation tools in the spatstat package.
– Andy W
Feb 24 '11 at 14:05
add a comment |
I would like to offer a solution that requires very little in terms of GIS analysis. In particular, it does not require triangulating any polygons.
The following algorithm, given in pseudocode, refers to some simple operations in addition to basic list handling capabilities (create, find length, append, sort, extract sublists, and concatenate) and generation of random floats in the interval [0, 1):
Area: Return the area of a polygon (0 for an empty polygon).
BoundingBox: Return the bounding box (extent) of a polygon.
Width: Return the width of a rectangle.
Height: Return the height of a rectangle.
Left: Split a rectangle into two halves and return the left half.
Right: ... returning the right half.
Top: ... returning the top half.
Bottom: ... returning the bottom half.
Clip: Clip a polygon to a rectangle.
RandomPoint: Return a random point in a rectangle.
Search: Search a sorted list for a target value. Return the index
of the last element less than the target.
In: Test whether a point is inside a polygon.
These are all available in almost any GIS or graphics programming environment (and easy to code if not). Clip must not return degenerate polygons (that is, those with zero area).
Procedure SimpleRandomSample efficiently obtains a list of points randomly distributed within a polygon. It is a wrapper for SRS, which breaks the polygon into smaller pieces until each piece is sufficiently compact to be sampled efficiently. To do this, it uses a precomputed list of random numbers to decide how many points to allocate to each piece.
SRS can be "tuned" by changing the parameter t. This is the maximum bounding box:polygon area ratio that can be tolerated. Making it small (but greater than 1) will cause most polygons to be split into many pieces; making it large can cause many trial points to be rejected for some polygons (sinuous, with slivers, or full of holes). This guarantees that the maximum time to sample the original polygon is predictable.
Procedure SimpleRandomSample(P:Polygon, N:Integer) {
U = Sorted list of N independent uniform values between 0 and 1
Return SRS(P, BoundingBox(P), U)
}
The next procedure calls itself recursively if necessary. The mysterious expression t*N + 5*Sqrt(t*N) conservatively estimates an upper limit on how many points will be needed, accounting for chance variability. The likelihood that this will fail is only 0.3 per million procedure calls. Increase 5 to 6 or even 7 to reduce this likelihood if you like.
Procedure SRS(P:Polygon, B:Rectangle, U:List) {
N = Length(U)
If (N == 0) {Return empty list}
aP = Area(P)
If (aP <= 0) {
Error("Cannot sample degenerate polygons.")
Return empty list
}
t = 2
If (aP*t < Area(B)) {
# Cut P into pieces
If (Width(B) > Height(B)) {
B1 = Left(B); B2 = Right(B)
} Else {
B1 = Bottom(B); B2 = Top(B)
}
P1 = Clip(P, B1); P2 = Clip(P, B2)
K = Search(U, Area(P1) / aP)
V = Concatenate( SRS(P1, B1, U[1::K]), SRS(P2, B2, U[K+1::N]) )
} Else {
# Sample P
V = empty list
maxIter = t*N + 5*Sqrt(t*N)
While(Length(V) < N and maxIter > 0) {
Decrement maxIter
Q = RandomPoint(B)
If (Q In P) {Append Q to V}
}
If (Length(V) < N) {
Error("Too many iterations.")
}
}
Return V
}
add a comment |
If your polygon is convex and you know all the vertices, you might want to consider doing a "random" convex weighting of the vertices to sample a new point which is guaranteed to lie inside the convex hull (polygon in this case).
For example say you have a N sided convex polygon with vertices
V_i, i={1,..,N}
Then generate randomly N convex weights
w_1,w_2,..,w_N such that ∑ w_i = 1; w_i>=0
The randomly sampled point is then given by
Y= ∑ w_i*V_i
There can be different way to sample N convex weights
- Pick N-1 numbers uniformly randomly within a range (without replacement) , sort them and normalize the N intervals between them to get the weights.
- You can also sample from the Dirichlet distribution which is often used as a conjugate prior for the multinomial distribution, which is similar to the convex weights in your case.
When your polygon is not very severely non-convex you might consider first converting it to a convex hull. This should at least limit the number of points lying outside your polygon to a large extent.
add a comment |
The task is very easy to solve in GRASS GIS (one command) using v.random.
Below an example on how to add 3 random points into selected polygons (here ZIP code areas of the city of Raleigh, NC) from the manual page. By modifying the SQL "where" statement the polygon(s) can be selected.

Obligatory reminder that zip codes are lines, not polygons.
– Richard
Mar 8 '18 at 17:25
Can you elaborate? To me also here it refers to areas: en.wikipedia.org/wiki/ZIP_Code#Primary_state_prefixes
– markusN
Mar 12 '18 at 22:49
Sure: zip codes reference particular post offices and their mail delivery routes. As a result, zip codes are lines, not polygons. They can overlap with each other, contain holes, and don't necessarily cover the entire US or any given state. Using them to divide up area is dangerous for this reason. Census units (like block groups) are a better choice. See also: this and this.
– Richard
Mar 12 '18 at 23:14
1
Thanks! It probably also depends on the country, see for example en.wikipedia.org/wiki/Postal_codes_in_Germany - however, ZIP codes are not my core topic, just wanted to illustrate and answer the original question "Generate points that lie inside polygon" rather than discuss ZIP code definitions which is OT here :-)
– markusN
Mar 13 '18 at 13:35
1
Noted on both counts. I should probably make a little blog entry so I can say this all more succinctly next time :-)
– Richard
Mar 13 '18 at 16:19
add a comment |
Answer link
https://gis.stackexchange.com/a/307204/103524
Three algorithms using different approaches.
Git Repo Link
- Here is a simple and best approach, using the actual distance of coordinates from x and y direction.
The internal algorithm use the WGS 1984 (4326) and result transform
to inserted SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION public.I_Grid_Point_Distance(geom public.geometry, x_side decimal, y_side decimal)
RETURNS public.geometry AS $BODY$
DECLARE
x_min decimal;
x_max decimal;
y_max decimal;
x decimal;
y decimal;
returnGeom public.geometry[];
i integer := -1;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
----RAISE NOTICE 'No SRID Found.';
ELSE
----RAISE NOTICE 'SRID Found.';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_min := ST_XMin(geom);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
y := ST_YMin(geom);
x := x_min;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
<<yloop>>
LOOP
IF (y > y_max) THEN
EXIT;
END IF;
CASE i WHEN 0 THEN
y := ST_Y(returnGeom[0]);
ELSE
y := ST_Y(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), y_side, radians(0))::geometry);
END CASE;
x := x_min;
<<xloop>>
LOOP
IF (x > x_max) THEN
EXIT;
END IF;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
x := ST_X(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), x_side, radians(90))::geometry);
END LOOP xloop;
END LOOP yloop;
RETURN
ST_CollectionExtract(st_transform(ST_Intersection(st_collect(returnGeom), geom), input_srid), 1);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
Use the function with a simple query, geometry must be valid and polygon, multi-polygons or envelope
SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;
Result======================================================================

Second function based on Nicklas Avén algorithm. Have tried to handle any SRID.
I have applied following changes in the algorithm.
- Separate variable for x and y direction for pixel size,
- New variable for calculates the distance in spheroid or ellipsoid.
- Input any SRID, function transform Geom to the working environment of
Spheroid or Ellipsoid Datum, then apply the distance to each side, get
the result and transform to input SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
srid := 4326;
x_side := x_side / 100000;
y_side := y_side / 100000;
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
RETURN QUERY
WITH res as (SELECT ST_SetSRID(ST_MakePoint(x, y), srid) point FROM
generate_series(x_min, x_max, x_side) as x,
generate_series(y_min, y_max, y_side) as y
WHERE st_intersects(geom, ST_SetSRID(ST_MakePoint(x, y), srid))
) select ST_TRANSFORM(ST_COLLECT(point), input_srid) from res;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point(geom, 22, 15, false) from polygons;
Result===================================================================
- Function based on series generator.
Function==================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point_Series(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
x_series DECIMAL;
y_series DECIMAL;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
x_series := CEIL ( @( x_max - x_min ) / x_side);
y_series := CEIL ( @( y_max - y_min ) / y_side );
RETURN QUERY
SELECT st_collect(st_setsrid(ST_MakePoint(x * x_side + x_min, y*y_side + y_min), srid)) FROM
generate_series(0, x_series) as x,
generate_series(0, y_series) as y
WHERE st_intersects(st_setsrid(ST_MakePoint(x*x_side + x_min, y*y_side + y_min), srid), geom);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons;
Result==========================================================================

add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "79"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f6412%2fgenerate-points-that-lie-inside-polygon%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
9 Answers
9
active
oldest
votes
9 Answers
9
active
oldest
votes
active
oldest
votes
active
oldest
votes
Start by decomposing the polygon into triangles, then generate points inside those. (For a uniform distribution, weight each triangle by its area.)
2
+1 Simple and effective. It's worth pointing out that uniformly random points can be generated within a triangle with no rejection at all, because there are (easily computed) area-preserving mappings between any triangle and an isosceles right triangle, which is half a square, say the half where the y coordinate exceeds the x coordinate. Generate two random coordinates and sort them to obtain a random point in the isosceles triangle, then map that back to the original triangle.
– whuber♦
Feb 22 '11 at 20:19
+1 I really like the discussion of trilinear coordinates referenced by the article you cite. I suppose this would be amenable to sphere whose surface is represented as a tesselation of triangles. On a projected plane, it wouldn't be a truly random distribution, would it?
– Kirk Kuykendall
Feb 22 '11 at 20:42
@whuber -- +1 back at you. Another way (in the link, but they hand-waved over it) is to reflect the rejected points from the uniformly-sampled quadrilateral across the shared edge and back into the triangle.
– Dan S.
Feb 22 '11 at 21:07
@Kirk -- the citation link is a touch anti-helpful in that it lists a bunch of wrong (non-uniform) sampling methods, including trilinear coordinates, before the "right" way. It doesn't look like there's a direct way to get a uniform sampling w/ trilinear coordinates. I'd approach uniform sampling over the entire sphere by converting random unit vectors in 3d to their lat/lon equivalent, but that's just me. (Unsure about sampling constrained to spherical triangles/polygons.) (Also unsure about truly uniform sampling on e.g. wgs84: just picking angles will bias a bit towards the poles, I think.)
– Dan S.
Feb 22 '11 at 21:15
1
@Dan For uniformly sampling the sphere, use a cylindrical equal-area projection (coordinates are longitude and cosine of latitude). If you want to sample without using a projection, there's a beautiful trick: generate three independent standard normal variates (x,y,z) and project them to the point (Rx/n, Ry/n, R*z/n) where n^2 = x^2 + y^2 + z^2 and R is the earth radius. Convert to (lat, lon) if need be (using authalic latitudes when working on a spheroid). It works because this trivariate normal distribution is spherically symmetric. For sampling triangles, stick to a projection.
– whuber♦
Feb 22 '11 at 21:26
|
show 3 more comments
Start by decomposing the polygon into triangles, then generate points inside those. (For a uniform distribution, weight each triangle by its area.)
2
+1 Simple and effective. It's worth pointing out that uniformly random points can be generated within a triangle with no rejection at all, because there are (easily computed) area-preserving mappings between any triangle and an isosceles right triangle, which is half a square, say the half where the y coordinate exceeds the x coordinate. Generate two random coordinates and sort them to obtain a random point in the isosceles triangle, then map that back to the original triangle.
– whuber♦
Feb 22 '11 at 20:19
+1 I really like the discussion of trilinear coordinates referenced by the article you cite. I suppose this would be amenable to sphere whose surface is represented as a tesselation of triangles. On a projected plane, it wouldn't be a truly random distribution, would it?
– Kirk Kuykendall
Feb 22 '11 at 20:42
@whuber -- +1 back at you. Another way (in the link, but they hand-waved over it) is to reflect the rejected points from the uniformly-sampled quadrilateral across the shared edge and back into the triangle.
– Dan S.
Feb 22 '11 at 21:07
@Kirk -- the citation link is a touch anti-helpful in that it lists a bunch of wrong (non-uniform) sampling methods, including trilinear coordinates, before the "right" way. It doesn't look like there's a direct way to get a uniform sampling w/ trilinear coordinates. I'd approach uniform sampling over the entire sphere by converting random unit vectors in 3d to their lat/lon equivalent, but that's just me. (Unsure about sampling constrained to spherical triangles/polygons.) (Also unsure about truly uniform sampling on e.g. wgs84: just picking angles will bias a bit towards the poles, I think.)
– Dan S.
Feb 22 '11 at 21:15
1
@Dan For uniformly sampling the sphere, use a cylindrical equal-area projection (coordinates are longitude and cosine of latitude). If you want to sample without using a projection, there's a beautiful trick: generate three independent standard normal variates (x,y,z) and project them to the point (Rx/n, Ry/n, R*z/n) where n^2 = x^2 + y^2 + z^2 and R is the earth radius. Convert to (lat, lon) if need be (using authalic latitudes when working on a spheroid). It works because this trivariate normal distribution is spherically symmetric. For sampling triangles, stick to a projection.
– whuber♦
Feb 22 '11 at 21:26
|
show 3 more comments
Start by decomposing the polygon into triangles, then generate points inside those. (For a uniform distribution, weight each triangle by its area.)
Start by decomposing the polygon into triangles, then generate points inside those. (For a uniform distribution, weight each triangle by its area.)
answered Feb 22 '11 at 19:23
Dan S.Dan S.
2,8191017
2,8191017
2
+1 Simple and effective. It's worth pointing out that uniformly random points can be generated within a triangle with no rejection at all, because there are (easily computed) area-preserving mappings between any triangle and an isosceles right triangle, which is half a square, say the half where the y coordinate exceeds the x coordinate. Generate two random coordinates and sort them to obtain a random point in the isosceles triangle, then map that back to the original triangle.
– whuber♦
Feb 22 '11 at 20:19
+1 I really like the discussion of trilinear coordinates referenced by the article you cite. I suppose this would be amenable to sphere whose surface is represented as a tesselation of triangles. On a projected plane, it wouldn't be a truly random distribution, would it?
– Kirk Kuykendall
Feb 22 '11 at 20:42
@whuber -- +1 back at you. Another way (in the link, but they hand-waved over it) is to reflect the rejected points from the uniformly-sampled quadrilateral across the shared edge and back into the triangle.
– Dan S.
Feb 22 '11 at 21:07
@Kirk -- the citation link is a touch anti-helpful in that it lists a bunch of wrong (non-uniform) sampling methods, including trilinear coordinates, before the "right" way. It doesn't look like there's a direct way to get a uniform sampling w/ trilinear coordinates. I'd approach uniform sampling over the entire sphere by converting random unit vectors in 3d to their lat/lon equivalent, but that's just me. (Unsure about sampling constrained to spherical triangles/polygons.) (Also unsure about truly uniform sampling on e.g. wgs84: just picking angles will bias a bit towards the poles, I think.)
– Dan S.
Feb 22 '11 at 21:15
1
@Dan For uniformly sampling the sphere, use a cylindrical equal-area projection (coordinates are longitude and cosine of latitude). If you want to sample without using a projection, there's a beautiful trick: generate three independent standard normal variates (x,y,z) and project them to the point (Rx/n, Ry/n, R*z/n) where n^2 = x^2 + y^2 + z^2 and R is the earth radius. Convert to (lat, lon) if need be (using authalic latitudes when working on a spheroid). It works because this trivariate normal distribution is spherically symmetric. For sampling triangles, stick to a projection.
– whuber♦
Feb 22 '11 at 21:26
|
show 3 more comments
2
+1 Simple and effective. It's worth pointing out that uniformly random points can be generated within a triangle with no rejection at all, because there are (easily computed) area-preserving mappings between any triangle and an isosceles right triangle, which is half a square, say the half where the y coordinate exceeds the x coordinate. Generate two random coordinates and sort them to obtain a random point in the isosceles triangle, then map that back to the original triangle.
– whuber♦
Feb 22 '11 at 20:19
+1 I really like the discussion of trilinear coordinates referenced by the article you cite. I suppose this would be amenable to sphere whose surface is represented as a tesselation of triangles. On a projected plane, it wouldn't be a truly random distribution, would it?
– Kirk Kuykendall
Feb 22 '11 at 20:42
@whuber -- +1 back at you. Another way (in the link, but they hand-waved over it) is to reflect the rejected points from the uniformly-sampled quadrilateral across the shared edge and back into the triangle.
– Dan S.
Feb 22 '11 at 21:07
@Kirk -- the citation link is a touch anti-helpful in that it lists a bunch of wrong (non-uniform) sampling methods, including trilinear coordinates, before the "right" way. It doesn't look like there's a direct way to get a uniform sampling w/ trilinear coordinates. I'd approach uniform sampling over the entire sphere by converting random unit vectors in 3d to their lat/lon equivalent, but that's just me. (Unsure about sampling constrained to spherical triangles/polygons.) (Also unsure about truly uniform sampling on e.g. wgs84: just picking angles will bias a bit towards the poles, I think.)
– Dan S.
Feb 22 '11 at 21:15
1
@Dan For uniformly sampling the sphere, use a cylindrical equal-area projection (coordinates are longitude and cosine of latitude). If you want to sample without using a projection, there's a beautiful trick: generate three independent standard normal variates (x,y,z) and project them to the point (Rx/n, Ry/n, R*z/n) where n^2 = x^2 + y^2 + z^2 and R is the earth radius. Convert to (lat, lon) if need be (using authalic latitudes when working on a spheroid). It works because this trivariate normal distribution is spherically symmetric. For sampling triangles, stick to a projection.
– whuber♦
Feb 22 '11 at 21:26
2
2
+1 Simple and effective. It's worth pointing out that uniformly random points can be generated within a triangle with no rejection at all, because there are (easily computed) area-preserving mappings between any triangle and an isosceles right triangle, which is half a square, say the half where the y coordinate exceeds the x coordinate. Generate two random coordinates and sort them to obtain a random point in the isosceles triangle, then map that back to the original triangle.
– whuber♦
Feb 22 '11 at 20:19
+1 Simple and effective. It's worth pointing out that uniformly random points can be generated within a triangle with no rejection at all, because there are (easily computed) area-preserving mappings between any triangle and an isosceles right triangle, which is half a square, say the half where the y coordinate exceeds the x coordinate. Generate two random coordinates and sort them to obtain a random point in the isosceles triangle, then map that back to the original triangle.
– whuber♦
Feb 22 '11 at 20:19
+1 I really like the discussion of trilinear coordinates referenced by the article you cite. I suppose this would be amenable to sphere whose surface is represented as a tesselation of triangles. On a projected plane, it wouldn't be a truly random distribution, would it?
– Kirk Kuykendall
Feb 22 '11 at 20:42
+1 I really like the discussion of trilinear coordinates referenced by the article you cite. I suppose this would be amenable to sphere whose surface is represented as a tesselation of triangles. On a projected plane, it wouldn't be a truly random distribution, would it?
– Kirk Kuykendall
Feb 22 '11 at 20:42
@whuber -- +1 back at you. Another way (in the link, but they hand-waved over it) is to reflect the rejected points from the uniformly-sampled quadrilateral across the shared edge and back into the triangle.
– Dan S.
Feb 22 '11 at 21:07
@whuber -- +1 back at you. Another way (in the link, but they hand-waved over it) is to reflect the rejected points from the uniformly-sampled quadrilateral across the shared edge and back into the triangle.
– Dan S.
Feb 22 '11 at 21:07
@Kirk -- the citation link is a touch anti-helpful in that it lists a bunch of wrong (non-uniform) sampling methods, including trilinear coordinates, before the "right" way. It doesn't look like there's a direct way to get a uniform sampling w/ trilinear coordinates. I'd approach uniform sampling over the entire sphere by converting random unit vectors in 3d to their lat/lon equivalent, but that's just me. (Unsure about sampling constrained to spherical triangles/polygons.) (Also unsure about truly uniform sampling on e.g. wgs84: just picking angles will bias a bit towards the poles, I think.)
– Dan S.
Feb 22 '11 at 21:15
@Kirk -- the citation link is a touch anti-helpful in that it lists a bunch of wrong (non-uniform) sampling methods, including trilinear coordinates, before the "right" way. It doesn't look like there's a direct way to get a uniform sampling w/ trilinear coordinates. I'd approach uniform sampling over the entire sphere by converting random unit vectors in 3d to their lat/lon equivalent, but that's just me. (Unsure about sampling constrained to spherical triangles/polygons.) (Also unsure about truly uniform sampling on e.g. wgs84: just picking angles will bias a bit towards the poles, I think.)
– Dan S.
Feb 22 '11 at 21:15
1
1
@Dan For uniformly sampling the sphere, use a cylindrical equal-area projection (coordinates are longitude and cosine of latitude). If you want to sample without using a projection, there's a beautiful trick: generate three independent standard normal variates (x,y,z) and project them to the point (Rx/n, Ry/n, R*z/n) where n^2 = x^2 + y^2 + z^2 and R is the earth radius. Convert to (lat, lon) if need be (using authalic latitudes when working on a spheroid). It works because this trivariate normal distribution is spherically symmetric. For sampling triangles, stick to a projection.
– whuber♦
Feb 22 '11 at 21:26
@Dan For uniformly sampling the sphere, use a cylindrical equal-area projection (coordinates are longitude and cosine of latitude). If you want to sample without using a projection, there's a beautiful trick: generate three independent standard normal variates (x,y,z) and project them to the point (Rx/n, Ry/n, R*z/n) where n^2 = x^2 + y^2 + z^2 and R is the earth radius. Convert to (lat, lon) if need be (using authalic latitudes when working on a spheroid). It works because this trivariate normal distribution is spherically symmetric. For sampling triangles, stick to a projection.
– whuber♦
Feb 22 '11 at 21:26
|
show 3 more comments
As you put a QGIS tag on this question: Random Points tool can be used with a boundary layer.

If you are looking for code, the underlying plugin source code should be of help.
Even 5 years later, still really helpful!
– Stranded Kid
Jul 12 '16 at 12:29
add a comment |
As you put a QGIS tag on this question: Random Points tool can be used with a boundary layer.

If you are looking for code, the underlying plugin source code should be of help.
Even 5 years later, still really helpful!
– Stranded Kid
Jul 12 '16 at 12:29
add a comment |
As you put a QGIS tag on this question: Random Points tool can be used with a boundary layer.

If you are looking for code, the underlying plugin source code should be of help.
As you put a QGIS tag on this question: Random Points tool can be used with a boundary layer.

If you are looking for code, the underlying plugin source code should be of help.
answered Feb 24 '11 at 12:50
underdark♦underdark
68.7k13178344
68.7k13178344
Even 5 years later, still really helpful!
– Stranded Kid
Jul 12 '16 at 12:29
add a comment |
Even 5 years later, still really helpful!
– Stranded Kid
Jul 12 '16 at 12:29
Even 5 years later, still really helpful!
– Stranded Kid
Jul 12 '16 at 12:29
Even 5 years later, still really helpful!
– Stranded Kid
Jul 12 '16 at 12:29
add a comment |
You could determine the extent of the polygon, then constrain the random number generation for X and Y values within those extents.
Basic process:
1) Determine maxx, maxy, minx, miny of polygon vertices,
2) Generate random points using these values as bounds
3) Test each point for intersection with your polygon,
4) Stop generating when you have enough points satisfying the intersection test
Here is an algorithm (C#) for the intersection test:
bool PointIsInGeometry(PointCollection points, MapPoint point)
{
int i;
int j = points.Count - 1;
bool output = false;
for (i = 0; i < points.Count; i++)
{
if (points[i].X < point.X && points[j].X >= point.X || points[j].X < point.X && points[i].X >= point.X)
{
if (points[i].Y + (point.X - points[i].X) / (points[j].X - points[i].X) * (points[j].Y - points[i].Y) < point.Y)
{
output = !output;
}
}
j = i;
}
return output;
}
add a comment |
You could determine the extent of the polygon, then constrain the random number generation for X and Y values within those extents.
Basic process:
1) Determine maxx, maxy, minx, miny of polygon vertices,
2) Generate random points using these values as bounds
3) Test each point for intersection with your polygon,
4) Stop generating when you have enough points satisfying the intersection test
Here is an algorithm (C#) for the intersection test:
bool PointIsInGeometry(PointCollection points, MapPoint point)
{
int i;
int j = points.Count - 1;
bool output = false;
for (i = 0; i < points.Count; i++)
{
if (points[i].X < point.X && points[j].X >= point.X || points[j].X < point.X && points[i].X >= point.X)
{
if (points[i].Y + (point.X - points[i].X) / (points[j].X - points[i].X) * (points[j].Y - points[i].Y) < point.Y)
{
output = !output;
}
}
j = i;
}
return output;
}
add a comment |
You could determine the extent of the polygon, then constrain the random number generation for X and Y values within those extents.
Basic process:
1) Determine maxx, maxy, minx, miny of polygon vertices,
2) Generate random points using these values as bounds
3) Test each point for intersection with your polygon,
4) Stop generating when you have enough points satisfying the intersection test
Here is an algorithm (C#) for the intersection test:
bool PointIsInGeometry(PointCollection points, MapPoint point)
{
int i;
int j = points.Count - 1;
bool output = false;
for (i = 0; i < points.Count; i++)
{
if (points[i].X < point.X && points[j].X >= point.X || points[j].X < point.X && points[i].X >= point.X)
{
if (points[i].Y + (point.X - points[i].X) / (points[j].X - points[i].X) * (points[j].Y - points[i].Y) < point.Y)
{
output = !output;
}
}
j = i;
}
return output;
}
You could determine the extent of the polygon, then constrain the random number generation for X and Y values within those extents.
Basic process:
1) Determine maxx, maxy, minx, miny of polygon vertices,
2) Generate random points using these values as bounds
3) Test each point for intersection with your polygon,
4) Stop generating when you have enough points satisfying the intersection test
Here is an algorithm (C#) for the intersection test:
bool PointIsInGeometry(PointCollection points, MapPoint point)
{
int i;
int j = points.Count - 1;
bool output = false;
for (i = 0; i < points.Count; i++)
{
if (points[i].X < point.X && points[j].X >= point.X || points[j].X < point.X && points[i].X >= point.X)
{
if (points[i].Y + (point.X - points[i].X) / (points[j].X - points[i].X) * (points[j].Y - points[i].Y) < point.Y)
{
output = !output;
}
}
j = i;
}
return output;
}
edited Feb 24 '11 at 4:45
answered Feb 22 '11 at 18:10
Dan WaltonDan Walton
1213
1213
add a comment |
add a comment |
There are some good libraries out there that do most of the heavy lifting for you.
Example using shapely in python.
import random
from shapely.geometry import Polygon, Point
def get_random_point_in_polygon(poly):
(minx, miny, maxx, maxy) = poly.bounds
while True:
p = Point(random.uniform(minx, maxx), random.uniform(miny, maxy))
if poly.contains(p):
return p
p = Polygon([(0, 0), (0, 2), (1, 1), (2, 2), (2, 0), (1, 1), (0, 0)])
point_in_poly = get_random_point_in_polygon(mypoly)
2
Shouldn't it be from shapely.geometry import...?
– PyMapr
May 17 '17 at 10:48
add a comment |
There are some good libraries out there that do most of the heavy lifting for you.
Example using shapely in python.
import random
from shapely.geometry import Polygon, Point
def get_random_point_in_polygon(poly):
(minx, miny, maxx, maxy) = poly.bounds
while True:
p = Point(random.uniform(minx, maxx), random.uniform(miny, maxy))
if poly.contains(p):
return p
p = Polygon([(0, 0), (0, 2), (1, 1), (2, 2), (2, 0), (1, 1), (0, 0)])
point_in_poly = get_random_point_in_polygon(mypoly)
2
Shouldn't it be from shapely.geometry import...?
– PyMapr
May 17 '17 at 10:48
add a comment |
There are some good libraries out there that do most of the heavy lifting for you.
Example using shapely in python.
import random
from shapely.geometry import Polygon, Point
def get_random_point_in_polygon(poly):
(minx, miny, maxx, maxy) = poly.bounds
while True:
p = Point(random.uniform(minx, maxx), random.uniform(miny, maxy))
if poly.contains(p):
return p
p = Polygon([(0, 0), (0, 2), (1, 1), (2, 2), (2, 0), (1, 1), (0, 0)])
point_in_poly = get_random_point_in_polygon(mypoly)
There are some good libraries out there that do most of the heavy lifting for you.
Example using shapely in python.
import random
from shapely.geometry import Polygon, Point
def get_random_point_in_polygon(poly):
(minx, miny, maxx, maxy) = poly.bounds
while True:
p = Point(random.uniform(minx, maxx), random.uniform(miny, maxy))
if poly.contains(p):
return p
p = Polygon([(0, 0), (0, 2), (1, 1), (2, 2), (2, 0), (1, 1), (0, 0)])
point_in_poly = get_random_point_in_polygon(mypoly)
edited Jan 29 at 11:39
sdcbr
1034
1034
answered Oct 3 '13 at 5:26
monkutmonkut
392211
392211
2
Shouldn't it be from shapely.geometry import...?
– PyMapr
May 17 '17 at 10:48
add a comment |
2
Shouldn't it be from shapely.geometry import...?
– PyMapr
May 17 '17 at 10:48
2
2
Shouldn't it be from shapely.geometry import...?
– PyMapr
May 17 '17 at 10:48
Shouldn't it be from shapely.geometry import...?
– PyMapr
May 17 '17 at 10:48
add a comment |
If R is an option, see ?spsample in the sp package. The polygons can be read in from any GDAL-supported format built into the rgdal package, and then spsample works directly on imported object with a variety of sampling options.
+1 - Since R is open source if one wants to replicate you can always go into the source to see how they are done. For point patterns one may also be interested in the simulation tools in the spatstat package.
– Andy W
Feb 24 '11 at 14:05
add a comment |
If R is an option, see ?spsample in the sp package. The polygons can be read in from any GDAL-supported format built into the rgdal package, and then spsample works directly on imported object with a variety of sampling options.
+1 - Since R is open source if one wants to replicate you can always go into the source to see how they are done. For point patterns one may also be interested in the simulation tools in the spatstat package.
– Andy W
Feb 24 '11 at 14:05
add a comment |
If R is an option, see ?spsample in the sp package. The polygons can be read in from any GDAL-supported format built into the rgdal package, and then spsample works directly on imported object with a variety of sampling options.
If R is an option, see ?spsample in the sp package. The polygons can be read in from any GDAL-supported format built into the rgdal package, and then spsample works directly on imported object with a variety of sampling options.
answered Feb 24 '11 at 10:01
mdsumnermdsumner
6,18211624
6,18211624
+1 - Since R is open source if one wants to replicate you can always go into the source to see how they are done. For point patterns one may also be interested in the simulation tools in the spatstat package.
– Andy W
Feb 24 '11 at 14:05
add a comment |
+1 - Since R is open source if one wants to replicate you can always go into the source to see how they are done. For point patterns one may also be interested in the simulation tools in the spatstat package.
– Andy W
Feb 24 '11 at 14:05
+1 - Since R is open source if one wants to replicate you can always go into the source to see how they are done. For point patterns one may also be interested in the simulation tools in the spatstat package.
– Andy W
Feb 24 '11 at 14:05
+1 - Since R is open source if one wants to replicate you can always go into the source to see how they are done. For point patterns one may also be interested in the simulation tools in the spatstat package.
– Andy W
Feb 24 '11 at 14:05
add a comment |
I would like to offer a solution that requires very little in terms of GIS analysis. In particular, it does not require triangulating any polygons.
The following algorithm, given in pseudocode, refers to some simple operations in addition to basic list handling capabilities (create, find length, append, sort, extract sublists, and concatenate) and generation of random floats in the interval [0, 1):
Area: Return the area of a polygon (0 for an empty polygon).
BoundingBox: Return the bounding box (extent) of a polygon.
Width: Return the width of a rectangle.
Height: Return the height of a rectangle.
Left: Split a rectangle into two halves and return the left half.
Right: ... returning the right half.
Top: ... returning the top half.
Bottom: ... returning the bottom half.
Clip: Clip a polygon to a rectangle.
RandomPoint: Return a random point in a rectangle.
Search: Search a sorted list for a target value. Return the index
of the last element less than the target.
In: Test whether a point is inside a polygon.
These are all available in almost any GIS or graphics programming environment (and easy to code if not). Clip must not return degenerate polygons (that is, those with zero area).
Procedure SimpleRandomSample efficiently obtains a list of points randomly distributed within a polygon. It is a wrapper for SRS, which breaks the polygon into smaller pieces until each piece is sufficiently compact to be sampled efficiently. To do this, it uses a precomputed list of random numbers to decide how many points to allocate to each piece.
SRS can be "tuned" by changing the parameter t. This is the maximum bounding box:polygon area ratio that can be tolerated. Making it small (but greater than 1) will cause most polygons to be split into many pieces; making it large can cause many trial points to be rejected for some polygons (sinuous, with slivers, or full of holes). This guarantees that the maximum time to sample the original polygon is predictable.
Procedure SimpleRandomSample(P:Polygon, N:Integer) {
U = Sorted list of N independent uniform values between 0 and 1
Return SRS(P, BoundingBox(P), U)
}
The next procedure calls itself recursively if necessary. The mysterious expression t*N + 5*Sqrt(t*N) conservatively estimates an upper limit on how many points will be needed, accounting for chance variability. The likelihood that this will fail is only 0.3 per million procedure calls. Increase 5 to 6 or even 7 to reduce this likelihood if you like.
Procedure SRS(P:Polygon, B:Rectangle, U:List) {
N = Length(U)
If (N == 0) {Return empty list}
aP = Area(P)
If (aP <= 0) {
Error("Cannot sample degenerate polygons.")
Return empty list
}
t = 2
If (aP*t < Area(B)) {
# Cut P into pieces
If (Width(B) > Height(B)) {
B1 = Left(B); B2 = Right(B)
} Else {
B1 = Bottom(B); B2 = Top(B)
}
P1 = Clip(P, B1); P2 = Clip(P, B2)
K = Search(U, Area(P1) / aP)
V = Concatenate( SRS(P1, B1, U[1::K]), SRS(P2, B2, U[K+1::N]) )
} Else {
# Sample P
V = empty list
maxIter = t*N + 5*Sqrt(t*N)
While(Length(V) < N and maxIter > 0) {
Decrement maxIter
Q = RandomPoint(B)
If (Q In P) {Append Q to V}
}
If (Length(V) < N) {
Error("Too many iterations.")
}
}
Return V
}
add a comment |
I would like to offer a solution that requires very little in terms of GIS analysis. In particular, it does not require triangulating any polygons.
The following algorithm, given in pseudocode, refers to some simple operations in addition to basic list handling capabilities (create, find length, append, sort, extract sublists, and concatenate) and generation of random floats in the interval [0, 1):
Area: Return the area of a polygon (0 for an empty polygon).
BoundingBox: Return the bounding box (extent) of a polygon.
Width: Return the width of a rectangle.
Height: Return the height of a rectangle.
Left: Split a rectangle into two halves and return the left half.
Right: ... returning the right half.
Top: ... returning the top half.
Bottom: ... returning the bottom half.
Clip: Clip a polygon to a rectangle.
RandomPoint: Return a random point in a rectangle.
Search: Search a sorted list for a target value. Return the index
of the last element less than the target.
In: Test whether a point is inside a polygon.
These are all available in almost any GIS or graphics programming environment (and easy to code if not). Clip must not return degenerate polygons (that is, those with zero area).
Procedure SimpleRandomSample efficiently obtains a list of points randomly distributed within a polygon. It is a wrapper for SRS, which breaks the polygon into smaller pieces until each piece is sufficiently compact to be sampled efficiently. To do this, it uses a precomputed list of random numbers to decide how many points to allocate to each piece.
SRS can be "tuned" by changing the parameter t. This is the maximum bounding box:polygon area ratio that can be tolerated. Making it small (but greater than 1) will cause most polygons to be split into many pieces; making it large can cause many trial points to be rejected for some polygons (sinuous, with slivers, or full of holes). This guarantees that the maximum time to sample the original polygon is predictable.
Procedure SimpleRandomSample(P:Polygon, N:Integer) {
U = Sorted list of N independent uniform values between 0 and 1
Return SRS(P, BoundingBox(P), U)
}
The next procedure calls itself recursively if necessary. The mysterious expression t*N + 5*Sqrt(t*N) conservatively estimates an upper limit on how many points will be needed, accounting for chance variability. The likelihood that this will fail is only 0.3 per million procedure calls. Increase 5 to 6 or even 7 to reduce this likelihood if you like.
Procedure SRS(P:Polygon, B:Rectangle, U:List) {
N = Length(U)
If (N == 0) {Return empty list}
aP = Area(P)
If (aP <= 0) {
Error("Cannot sample degenerate polygons.")
Return empty list
}
t = 2
If (aP*t < Area(B)) {
# Cut P into pieces
If (Width(B) > Height(B)) {
B1 = Left(B); B2 = Right(B)
} Else {
B1 = Bottom(B); B2 = Top(B)
}
P1 = Clip(P, B1); P2 = Clip(P, B2)
K = Search(U, Area(P1) / aP)
V = Concatenate( SRS(P1, B1, U[1::K]), SRS(P2, B2, U[K+1::N]) )
} Else {
# Sample P
V = empty list
maxIter = t*N + 5*Sqrt(t*N)
While(Length(V) < N and maxIter > 0) {
Decrement maxIter
Q = RandomPoint(B)
If (Q In P) {Append Q to V}
}
If (Length(V) < N) {
Error("Too many iterations.")
}
}
Return V
}
add a comment |
I would like to offer a solution that requires very little in terms of GIS analysis. In particular, it does not require triangulating any polygons.
The following algorithm, given in pseudocode, refers to some simple operations in addition to basic list handling capabilities (create, find length, append, sort, extract sublists, and concatenate) and generation of random floats in the interval [0, 1):
Area: Return the area of a polygon (0 for an empty polygon).
BoundingBox: Return the bounding box (extent) of a polygon.
Width: Return the width of a rectangle.
Height: Return the height of a rectangle.
Left: Split a rectangle into two halves and return the left half.
Right: ... returning the right half.
Top: ... returning the top half.
Bottom: ... returning the bottom half.
Clip: Clip a polygon to a rectangle.
RandomPoint: Return a random point in a rectangle.
Search: Search a sorted list for a target value. Return the index
of the last element less than the target.
In: Test whether a point is inside a polygon.
These are all available in almost any GIS or graphics programming environment (and easy to code if not). Clip must not return degenerate polygons (that is, those with zero area).
Procedure SimpleRandomSample efficiently obtains a list of points randomly distributed within a polygon. It is a wrapper for SRS, which breaks the polygon into smaller pieces until each piece is sufficiently compact to be sampled efficiently. To do this, it uses a precomputed list of random numbers to decide how many points to allocate to each piece.
SRS can be "tuned" by changing the parameter t. This is the maximum bounding box:polygon area ratio that can be tolerated. Making it small (but greater than 1) will cause most polygons to be split into many pieces; making it large can cause many trial points to be rejected for some polygons (sinuous, with slivers, or full of holes). This guarantees that the maximum time to sample the original polygon is predictable.
Procedure SimpleRandomSample(P:Polygon, N:Integer) {
U = Sorted list of N independent uniform values between 0 and 1
Return SRS(P, BoundingBox(P), U)
}
The next procedure calls itself recursively if necessary. The mysterious expression t*N + 5*Sqrt(t*N) conservatively estimates an upper limit on how many points will be needed, accounting for chance variability. The likelihood that this will fail is only 0.3 per million procedure calls. Increase 5 to 6 or even 7 to reduce this likelihood if you like.
Procedure SRS(P:Polygon, B:Rectangle, U:List) {
N = Length(U)
If (N == 0) {Return empty list}
aP = Area(P)
If (aP <= 0) {
Error("Cannot sample degenerate polygons.")
Return empty list
}
t = 2
If (aP*t < Area(B)) {
# Cut P into pieces
If (Width(B) > Height(B)) {
B1 = Left(B); B2 = Right(B)
} Else {
B1 = Bottom(B); B2 = Top(B)
}
P1 = Clip(P, B1); P2 = Clip(P, B2)
K = Search(U, Area(P1) / aP)
V = Concatenate( SRS(P1, B1, U[1::K]), SRS(P2, B2, U[K+1::N]) )
} Else {
# Sample P
V = empty list
maxIter = t*N + 5*Sqrt(t*N)
While(Length(V) < N and maxIter > 0) {
Decrement maxIter
Q = RandomPoint(B)
If (Q In P) {Append Q to V}
}
If (Length(V) < N) {
Error("Too many iterations.")
}
}
Return V
}
I would like to offer a solution that requires very little in terms of GIS analysis. In particular, it does not require triangulating any polygons.
The following algorithm, given in pseudocode, refers to some simple operations in addition to basic list handling capabilities (create, find length, append, sort, extract sublists, and concatenate) and generation of random floats in the interval [0, 1):
Area: Return the area of a polygon (0 for an empty polygon).
BoundingBox: Return the bounding box (extent) of a polygon.
Width: Return the width of a rectangle.
Height: Return the height of a rectangle.
Left: Split a rectangle into two halves and return the left half.
Right: ... returning the right half.
Top: ... returning the top half.
Bottom: ... returning the bottom half.
Clip: Clip a polygon to a rectangle.
RandomPoint: Return a random point in a rectangle.
Search: Search a sorted list for a target value. Return the index
of the last element less than the target.
In: Test whether a point is inside a polygon.
These are all available in almost any GIS or graphics programming environment (and easy to code if not). Clip must not return degenerate polygons (that is, those with zero area).
Procedure SimpleRandomSample efficiently obtains a list of points randomly distributed within a polygon. It is a wrapper for SRS, which breaks the polygon into smaller pieces until each piece is sufficiently compact to be sampled efficiently. To do this, it uses a precomputed list of random numbers to decide how many points to allocate to each piece.
SRS can be "tuned" by changing the parameter t. This is the maximum bounding box:polygon area ratio that can be tolerated. Making it small (but greater than 1) will cause most polygons to be split into many pieces; making it large can cause many trial points to be rejected for some polygons (sinuous, with slivers, or full of holes). This guarantees that the maximum time to sample the original polygon is predictable.
Procedure SimpleRandomSample(P:Polygon, N:Integer) {
U = Sorted list of N independent uniform values between 0 and 1
Return SRS(P, BoundingBox(P), U)
}
The next procedure calls itself recursively if necessary. The mysterious expression t*N + 5*Sqrt(t*N) conservatively estimates an upper limit on how many points will be needed, accounting for chance variability. The likelihood that this will fail is only 0.3 per million procedure calls. Increase 5 to 6 or even 7 to reduce this likelihood if you like.
Procedure SRS(P:Polygon, B:Rectangle, U:List) {
N = Length(U)
If (N == 0) {Return empty list}
aP = Area(P)
If (aP <= 0) {
Error("Cannot sample degenerate polygons.")
Return empty list
}
t = 2
If (aP*t < Area(B)) {
# Cut P into pieces
If (Width(B) > Height(B)) {
B1 = Left(B); B2 = Right(B)
} Else {
B1 = Bottom(B); B2 = Top(B)
}
P1 = Clip(P, B1); P2 = Clip(P, B2)
K = Search(U, Area(P1) / aP)
V = Concatenate( SRS(P1, B1, U[1::K]), SRS(P2, B2, U[K+1::N]) )
} Else {
# Sample P
V = empty list
maxIter = t*N + 5*Sqrt(t*N)
While(Length(V) < N and maxIter > 0) {
Decrement maxIter
Q = RandomPoint(B)
If (Q In P) {Append Q to V}
}
If (Length(V) < N) {
Error("Too many iterations.")
}
}
Return V
}
edited Feb 23 '11 at 20:54
answered Feb 23 '11 at 20:40
whuber♦whuber
60k11156247
60k11156247
add a comment |
add a comment |
If your polygon is convex and you know all the vertices, you might want to consider doing a "random" convex weighting of the vertices to sample a new point which is guaranteed to lie inside the convex hull (polygon in this case).
For example say you have a N sided convex polygon with vertices
V_i, i={1,..,N}
Then generate randomly N convex weights
w_1,w_2,..,w_N such that ∑ w_i = 1; w_i>=0
The randomly sampled point is then given by
Y= ∑ w_i*V_i
There can be different way to sample N convex weights
- Pick N-1 numbers uniformly randomly within a range (without replacement) , sort them and normalize the N intervals between them to get the weights.
- You can also sample from the Dirichlet distribution which is often used as a conjugate prior for the multinomial distribution, which is similar to the convex weights in your case.
When your polygon is not very severely non-convex you might consider first converting it to a convex hull. This should at least limit the number of points lying outside your polygon to a large extent.
add a comment |
If your polygon is convex and you know all the vertices, you might want to consider doing a "random" convex weighting of the vertices to sample a new point which is guaranteed to lie inside the convex hull (polygon in this case).
For example say you have a N sided convex polygon with vertices
V_i, i={1,..,N}
Then generate randomly N convex weights
w_1,w_2,..,w_N such that ∑ w_i = 1; w_i>=0
The randomly sampled point is then given by
Y= ∑ w_i*V_i
There can be different way to sample N convex weights
- Pick N-1 numbers uniformly randomly within a range (without replacement) , sort them and normalize the N intervals between them to get the weights.
- You can also sample from the Dirichlet distribution which is often used as a conjugate prior for the multinomial distribution, which is similar to the convex weights in your case.
When your polygon is not very severely non-convex you might consider first converting it to a convex hull. This should at least limit the number of points lying outside your polygon to a large extent.
add a comment |
If your polygon is convex and you know all the vertices, you might want to consider doing a "random" convex weighting of the vertices to sample a new point which is guaranteed to lie inside the convex hull (polygon in this case).
For example say you have a N sided convex polygon with vertices
V_i, i={1,..,N}
Then generate randomly N convex weights
w_1,w_2,..,w_N such that ∑ w_i = 1; w_i>=0
The randomly sampled point is then given by
Y= ∑ w_i*V_i
There can be different way to sample N convex weights
- Pick N-1 numbers uniformly randomly within a range (without replacement) , sort them and normalize the N intervals between them to get the weights.
- You can also sample from the Dirichlet distribution which is often used as a conjugate prior for the multinomial distribution, which is similar to the convex weights in your case.
When your polygon is not very severely non-convex you might consider first converting it to a convex hull. This should at least limit the number of points lying outside your polygon to a large extent.
If your polygon is convex and you know all the vertices, you might want to consider doing a "random" convex weighting of the vertices to sample a new point which is guaranteed to lie inside the convex hull (polygon in this case).
For example say you have a N sided convex polygon with vertices
V_i, i={1,..,N}
Then generate randomly N convex weights
w_1,w_2,..,w_N such that ∑ w_i = 1; w_i>=0
The randomly sampled point is then given by
Y= ∑ w_i*V_i
There can be different way to sample N convex weights
- Pick N-1 numbers uniformly randomly within a range (without replacement) , sort them and normalize the N intervals between them to get the weights.
- You can also sample from the Dirichlet distribution which is often used as a conjugate prior for the multinomial distribution, which is similar to the convex weights in your case.
When your polygon is not very severely non-convex you might consider first converting it to a convex hull. This should at least limit the number of points lying outside your polygon to a large extent.
answered May 12 '17 at 23:50
algoseeralgoseer
211
211
add a comment |
add a comment |
The task is very easy to solve in GRASS GIS (one command) using v.random.
Below an example on how to add 3 random points into selected polygons (here ZIP code areas of the city of Raleigh, NC) from the manual page. By modifying the SQL "where" statement the polygon(s) can be selected.

Obligatory reminder that zip codes are lines, not polygons.
– Richard
Mar 8 '18 at 17:25
Can you elaborate? To me also here it refers to areas: en.wikipedia.org/wiki/ZIP_Code#Primary_state_prefixes
– markusN
Mar 12 '18 at 22:49
Sure: zip codes reference particular post offices and their mail delivery routes. As a result, zip codes are lines, not polygons. They can overlap with each other, contain holes, and don't necessarily cover the entire US or any given state. Using them to divide up area is dangerous for this reason. Census units (like block groups) are a better choice. See also: this and this.
– Richard
Mar 12 '18 at 23:14
1
Thanks! It probably also depends on the country, see for example en.wikipedia.org/wiki/Postal_codes_in_Germany - however, ZIP codes are not my core topic, just wanted to illustrate and answer the original question "Generate points that lie inside polygon" rather than discuss ZIP code definitions which is OT here :-)
– markusN
Mar 13 '18 at 13:35
1
Noted on both counts. I should probably make a little blog entry so I can say this all more succinctly next time :-)
– Richard
Mar 13 '18 at 16:19
add a comment |
The task is very easy to solve in GRASS GIS (one command) using v.random.
Below an example on how to add 3 random points into selected polygons (here ZIP code areas of the city of Raleigh, NC) from the manual page. By modifying the SQL "where" statement the polygon(s) can be selected.

Obligatory reminder that zip codes are lines, not polygons.
– Richard
Mar 8 '18 at 17:25
Can you elaborate? To me also here it refers to areas: en.wikipedia.org/wiki/ZIP_Code#Primary_state_prefixes
– markusN
Mar 12 '18 at 22:49
Sure: zip codes reference particular post offices and their mail delivery routes. As a result, zip codes are lines, not polygons. They can overlap with each other, contain holes, and don't necessarily cover the entire US or any given state. Using them to divide up area is dangerous for this reason. Census units (like block groups) are a better choice. See also: this and this.
– Richard
Mar 12 '18 at 23:14
1
Thanks! It probably also depends on the country, see for example en.wikipedia.org/wiki/Postal_codes_in_Germany - however, ZIP codes are not my core topic, just wanted to illustrate and answer the original question "Generate points that lie inside polygon" rather than discuss ZIP code definitions which is OT here :-)
– markusN
Mar 13 '18 at 13:35
1
Noted on both counts. I should probably make a little blog entry so I can say this all more succinctly next time :-)
– Richard
Mar 13 '18 at 16:19
add a comment |
The task is very easy to solve in GRASS GIS (one command) using v.random.
Below an example on how to add 3 random points into selected polygons (here ZIP code areas of the city of Raleigh, NC) from the manual page. By modifying the SQL "where" statement the polygon(s) can be selected.

The task is very easy to solve in GRASS GIS (one command) using v.random.
Below an example on how to add 3 random points into selected polygons (here ZIP code areas of the city of Raleigh, NC) from the manual page. By modifying the SQL "where" statement the polygon(s) can be selected.

answered May 13 '17 at 9:54
markusNmarkusN
11.3k2243
11.3k2243
Obligatory reminder that zip codes are lines, not polygons.
– Richard
Mar 8 '18 at 17:25
Can you elaborate? To me also here it refers to areas: en.wikipedia.org/wiki/ZIP_Code#Primary_state_prefixes
– markusN
Mar 12 '18 at 22:49
Sure: zip codes reference particular post offices and their mail delivery routes. As a result, zip codes are lines, not polygons. They can overlap with each other, contain holes, and don't necessarily cover the entire US or any given state. Using them to divide up area is dangerous for this reason. Census units (like block groups) are a better choice. See also: this and this.
– Richard
Mar 12 '18 at 23:14
1
Thanks! It probably also depends on the country, see for example en.wikipedia.org/wiki/Postal_codes_in_Germany - however, ZIP codes are not my core topic, just wanted to illustrate and answer the original question "Generate points that lie inside polygon" rather than discuss ZIP code definitions which is OT here :-)
– markusN
Mar 13 '18 at 13:35
1
Noted on both counts. I should probably make a little blog entry so I can say this all more succinctly next time :-)
– Richard
Mar 13 '18 at 16:19
add a comment |
Obligatory reminder that zip codes are lines, not polygons.
– Richard
Mar 8 '18 at 17:25
Can you elaborate? To me also here it refers to areas: en.wikipedia.org/wiki/ZIP_Code#Primary_state_prefixes
– markusN
Mar 12 '18 at 22:49
Sure: zip codes reference particular post offices and their mail delivery routes. As a result, zip codes are lines, not polygons. They can overlap with each other, contain holes, and don't necessarily cover the entire US or any given state. Using them to divide up area is dangerous for this reason. Census units (like block groups) are a better choice. See also: this and this.
– Richard
Mar 12 '18 at 23:14
1
Thanks! It probably also depends on the country, see for example en.wikipedia.org/wiki/Postal_codes_in_Germany - however, ZIP codes are not my core topic, just wanted to illustrate and answer the original question "Generate points that lie inside polygon" rather than discuss ZIP code definitions which is OT here :-)
– markusN
Mar 13 '18 at 13:35
1
Noted on both counts. I should probably make a little blog entry so I can say this all more succinctly next time :-)
– Richard
Mar 13 '18 at 16:19
Obligatory reminder that zip codes are lines, not polygons.
– Richard
Mar 8 '18 at 17:25
Obligatory reminder that zip codes are lines, not polygons.
– Richard
Mar 8 '18 at 17:25
Can you elaborate? To me also here it refers to areas: en.wikipedia.org/wiki/ZIP_Code#Primary_state_prefixes
– markusN
Mar 12 '18 at 22:49
Can you elaborate? To me also here it refers to areas: en.wikipedia.org/wiki/ZIP_Code#Primary_state_prefixes
– markusN
Mar 12 '18 at 22:49
Sure: zip codes reference particular post offices and their mail delivery routes. As a result, zip codes are lines, not polygons. They can overlap with each other, contain holes, and don't necessarily cover the entire US or any given state. Using them to divide up area is dangerous for this reason. Census units (like block groups) are a better choice. See also: this and this.
– Richard
Mar 12 '18 at 23:14
Sure: zip codes reference particular post offices and their mail delivery routes. As a result, zip codes are lines, not polygons. They can overlap with each other, contain holes, and don't necessarily cover the entire US or any given state. Using them to divide up area is dangerous for this reason. Census units (like block groups) are a better choice. See also: this and this.
– Richard
Mar 12 '18 at 23:14
1
1
Thanks! It probably also depends on the country, see for example en.wikipedia.org/wiki/Postal_codes_in_Germany - however, ZIP codes are not my core topic, just wanted to illustrate and answer the original question "Generate points that lie inside polygon" rather than discuss ZIP code definitions which is OT here :-)
– markusN
Mar 13 '18 at 13:35
Thanks! It probably also depends on the country, see for example en.wikipedia.org/wiki/Postal_codes_in_Germany - however, ZIP codes are not my core topic, just wanted to illustrate and answer the original question "Generate points that lie inside polygon" rather than discuss ZIP code definitions which is OT here :-)
– markusN
Mar 13 '18 at 13:35
1
1
Noted on both counts. I should probably make a little blog entry so I can say this all more succinctly next time :-)
– Richard
Mar 13 '18 at 16:19
Noted on both counts. I should probably make a little blog entry so I can say this all more succinctly next time :-)
– Richard
Mar 13 '18 at 16:19
add a comment |
Answer link
https://gis.stackexchange.com/a/307204/103524
Three algorithms using different approaches.
Git Repo Link
- Here is a simple and best approach, using the actual distance of coordinates from x and y direction.
The internal algorithm use the WGS 1984 (4326) and result transform
to inserted SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION public.I_Grid_Point_Distance(geom public.geometry, x_side decimal, y_side decimal)
RETURNS public.geometry AS $BODY$
DECLARE
x_min decimal;
x_max decimal;
y_max decimal;
x decimal;
y decimal;
returnGeom public.geometry[];
i integer := -1;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
----RAISE NOTICE 'No SRID Found.';
ELSE
----RAISE NOTICE 'SRID Found.';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_min := ST_XMin(geom);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
y := ST_YMin(geom);
x := x_min;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
<<yloop>>
LOOP
IF (y > y_max) THEN
EXIT;
END IF;
CASE i WHEN 0 THEN
y := ST_Y(returnGeom[0]);
ELSE
y := ST_Y(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), y_side, radians(0))::geometry);
END CASE;
x := x_min;
<<xloop>>
LOOP
IF (x > x_max) THEN
EXIT;
END IF;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
x := ST_X(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), x_side, radians(90))::geometry);
END LOOP xloop;
END LOOP yloop;
RETURN
ST_CollectionExtract(st_transform(ST_Intersection(st_collect(returnGeom), geom), input_srid), 1);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
Use the function with a simple query, geometry must be valid and polygon, multi-polygons or envelope
SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;
Result======================================================================

Second function based on Nicklas Avén algorithm. Have tried to handle any SRID.
I have applied following changes in the algorithm.
- Separate variable for x and y direction for pixel size,
- New variable for calculates the distance in spheroid or ellipsoid.
- Input any SRID, function transform Geom to the working environment of
Spheroid or Ellipsoid Datum, then apply the distance to each side, get
the result and transform to input SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
srid := 4326;
x_side := x_side / 100000;
y_side := y_side / 100000;
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
RETURN QUERY
WITH res as (SELECT ST_SetSRID(ST_MakePoint(x, y), srid) point FROM
generate_series(x_min, x_max, x_side) as x,
generate_series(y_min, y_max, y_side) as y
WHERE st_intersects(geom, ST_SetSRID(ST_MakePoint(x, y), srid))
) select ST_TRANSFORM(ST_COLLECT(point), input_srid) from res;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point(geom, 22, 15, false) from polygons;
Result===================================================================
- Function based on series generator.
Function==================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point_Series(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
x_series DECIMAL;
y_series DECIMAL;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
x_series := CEIL ( @( x_max - x_min ) / x_side);
y_series := CEIL ( @( y_max - y_min ) / y_side );
RETURN QUERY
SELECT st_collect(st_setsrid(ST_MakePoint(x * x_side + x_min, y*y_side + y_min), srid)) FROM
generate_series(0, x_series) as x,
generate_series(0, y_series) as y
WHERE st_intersects(st_setsrid(ST_MakePoint(x*x_side + x_min, y*y_side + y_min), srid), geom);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons;
Result==========================================================================

add a comment |
Answer link
https://gis.stackexchange.com/a/307204/103524
Three algorithms using different approaches.
Git Repo Link
- Here is a simple and best approach, using the actual distance of coordinates from x and y direction.
The internal algorithm use the WGS 1984 (4326) and result transform
to inserted SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION public.I_Grid_Point_Distance(geom public.geometry, x_side decimal, y_side decimal)
RETURNS public.geometry AS $BODY$
DECLARE
x_min decimal;
x_max decimal;
y_max decimal;
x decimal;
y decimal;
returnGeom public.geometry[];
i integer := -1;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
----RAISE NOTICE 'No SRID Found.';
ELSE
----RAISE NOTICE 'SRID Found.';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_min := ST_XMin(geom);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
y := ST_YMin(geom);
x := x_min;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
<<yloop>>
LOOP
IF (y > y_max) THEN
EXIT;
END IF;
CASE i WHEN 0 THEN
y := ST_Y(returnGeom[0]);
ELSE
y := ST_Y(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), y_side, radians(0))::geometry);
END CASE;
x := x_min;
<<xloop>>
LOOP
IF (x > x_max) THEN
EXIT;
END IF;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
x := ST_X(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), x_side, radians(90))::geometry);
END LOOP xloop;
END LOOP yloop;
RETURN
ST_CollectionExtract(st_transform(ST_Intersection(st_collect(returnGeom), geom), input_srid), 1);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
Use the function with a simple query, geometry must be valid and polygon, multi-polygons or envelope
SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;
Result======================================================================

Second function based on Nicklas Avén algorithm. Have tried to handle any SRID.
I have applied following changes in the algorithm.
- Separate variable for x and y direction for pixel size,
- New variable for calculates the distance in spheroid or ellipsoid.
- Input any SRID, function transform Geom to the working environment of
Spheroid or Ellipsoid Datum, then apply the distance to each side, get
the result and transform to input SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
srid := 4326;
x_side := x_side / 100000;
y_side := y_side / 100000;
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
RETURN QUERY
WITH res as (SELECT ST_SetSRID(ST_MakePoint(x, y), srid) point FROM
generate_series(x_min, x_max, x_side) as x,
generate_series(y_min, y_max, y_side) as y
WHERE st_intersects(geom, ST_SetSRID(ST_MakePoint(x, y), srid))
) select ST_TRANSFORM(ST_COLLECT(point), input_srid) from res;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point(geom, 22, 15, false) from polygons;
Result===================================================================
- Function based on series generator.
Function==================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point_Series(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
x_series DECIMAL;
y_series DECIMAL;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
x_series := CEIL ( @( x_max - x_min ) / x_side);
y_series := CEIL ( @( y_max - y_min ) / y_side );
RETURN QUERY
SELECT st_collect(st_setsrid(ST_MakePoint(x * x_side + x_min, y*y_side + y_min), srid)) FROM
generate_series(0, x_series) as x,
generate_series(0, y_series) as y
WHERE st_intersects(st_setsrid(ST_MakePoint(x*x_side + x_min, y*y_side + y_min), srid), geom);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons;
Result==========================================================================

add a comment |
Answer link
https://gis.stackexchange.com/a/307204/103524
Three algorithms using different approaches.
Git Repo Link
- Here is a simple and best approach, using the actual distance of coordinates from x and y direction.
The internal algorithm use the WGS 1984 (4326) and result transform
to inserted SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION public.I_Grid_Point_Distance(geom public.geometry, x_side decimal, y_side decimal)
RETURNS public.geometry AS $BODY$
DECLARE
x_min decimal;
x_max decimal;
y_max decimal;
x decimal;
y decimal;
returnGeom public.geometry[];
i integer := -1;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
----RAISE NOTICE 'No SRID Found.';
ELSE
----RAISE NOTICE 'SRID Found.';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_min := ST_XMin(geom);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
y := ST_YMin(geom);
x := x_min;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
<<yloop>>
LOOP
IF (y > y_max) THEN
EXIT;
END IF;
CASE i WHEN 0 THEN
y := ST_Y(returnGeom[0]);
ELSE
y := ST_Y(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), y_side, radians(0))::geometry);
END CASE;
x := x_min;
<<xloop>>
LOOP
IF (x > x_max) THEN
EXIT;
END IF;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
x := ST_X(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), x_side, radians(90))::geometry);
END LOOP xloop;
END LOOP yloop;
RETURN
ST_CollectionExtract(st_transform(ST_Intersection(st_collect(returnGeom), geom), input_srid), 1);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
Use the function with a simple query, geometry must be valid and polygon, multi-polygons or envelope
SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;
Result======================================================================

Second function based on Nicklas Avén algorithm. Have tried to handle any SRID.
I have applied following changes in the algorithm.
- Separate variable for x and y direction for pixel size,
- New variable for calculates the distance in spheroid or ellipsoid.
- Input any SRID, function transform Geom to the working environment of
Spheroid or Ellipsoid Datum, then apply the distance to each side, get
the result and transform to input SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
srid := 4326;
x_side := x_side / 100000;
y_side := y_side / 100000;
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
RETURN QUERY
WITH res as (SELECT ST_SetSRID(ST_MakePoint(x, y), srid) point FROM
generate_series(x_min, x_max, x_side) as x,
generate_series(y_min, y_max, y_side) as y
WHERE st_intersects(geom, ST_SetSRID(ST_MakePoint(x, y), srid))
) select ST_TRANSFORM(ST_COLLECT(point), input_srid) from res;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point(geom, 22, 15, false) from polygons;
Result===================================================================
- Function based on series generator.
Function==================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point_Series(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
x_series DECIMAL;
y_series DECIMAL;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
x_series := CEIL ( @( x_max - x_min ) / x_side);
y_series := CEIL ( @( y_max - y_min ) / y_side );
RETURN QUERY
SELECT st_collect(st_setsrid(ST_MakePoint(x * x_side + x_min, y*y_side + y_min), srid)) FROM
generate_series(0, x_series) as x,
generate_series(0, y_series) as y
WHERE st_intersects(st_setsrid(ST_MakePoint(x*x_side + x_min, y*y_side + y_min), srid), geom);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons;
Result==========================================================================

Answer link
https://gis.stackexchange.com/a/307204/103524
Three algorithms using different approaches.
Git Repo Link
- Here is a simple and best approach, using the actual distance of coordinates from x and y direction.
The internal algorithm use the WGS 1984 (4326) and result transform
to inserted SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION public.I_Grid_Point_Distance(geom public.geometry, x_side decimal, y_side decimal)
RETURNS public.geometry AS $BODY$
DECLARE
x_min decimal;
x_max decimal;
y_max decimal;
x decimal;
y decimal;
returnGeom public.geometry[];
i integer := -1;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
----RAISE NOTICE 'No SRID Found.';
ELSE
----RAISE NOTICE 'SRID Found.';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_min := ST_XMin(geom);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
y := ST_YMin(geom);
x := x_min;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
<<yloop>>
LOOP
IF (y > y_max) THEN
EXIT;
END IF;
CASE i WHEN 0 THEN
y := ST_Y(returnGeom[0]);
ELSE
y := ST_Y(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), y_side, radians(0))::geometry);
END CASE;
x := x_min;
<<xloop>>
LOOP
IF (x > x_max) THEN
EXIT;
END IF;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
x := ST_X(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), x_side, radians(90))::geometry);
END LOOP xloop;
END LOOP yloop;
RETURN
ST_CollectionExtract(st_transform(ST_Intersection(st_collect(returnGeom), geom), input_srid), 1);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
Use the function with a simple query, geometry must be valid and polygon, multi-polygons or envelope
SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;
Result======================================================================

Second function based on Nicklas Avén algorithm. Have tried to handle any SRID.
I have applied following changes in the algorithm.
- Separate variable for x and y direction for pixel size,
- New variable for calculates the distance in spheroid or ellipsoid.
- Input any SRID, function transform Geom to the working environment of
Spheroid or Ellipsoid Datum, then apply the distance to each side, get
the result and transform to input SRID.
Function ===================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
srid := 4326;
x_side := x_side / 100000;
y_side := y_side / 100000;
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
RETURN QUERY
WITH res as (SELECT ST_SetSRID(ST_MakePoint(x, y), srid) point FROM
generate_series(x_min, x_max, x_side) as x,
generate_series(y_min, y_max, y_side) as y
WHERE st_intersects(geom, ST_SetSRID(ST_MakePoint(x, y), srid))
) select ST_TRANSFORM(ST_COLLECT(point), input_srid) from res;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point(geom, 22, 15, false) from polygons;
Result===================================================================
- Function based on series generator.
Function==================================================================
CREATE OR REPLACE FUNCTION I_Grid_Point_Series(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
x_series DECIMAL;
y_series DECIMAL;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
x_series := CEIL ( @( x_max - x_min ) / x_side);
y_series := CEIL ( @( y_max - y_min ) / y_side );
RETURN QUERY
SELECT st_collect(st_setsrid(ST_MakePoint(x * x_side + x_min, y*y_side + y_min), srid)) FROM
generate_series(0, x_series) as x,
generate_series(0, y_series) as y
WHERE st_intersects(st_setsrid(ST_MakePoint(x*x_side + x_min, y*y_side + y_min), srid), geom);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
Use it with a simple query.
SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons;
Result==========================================================================

answered 9 mins ago
Muhammad Imran SiddiqueMuhammad Imran Siddique
817
817
add a comment |
add a comment |
Thanks for contributing an answer to Geographic Information Systems Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f6412%2fgenerate-points-that-lie-inside-polygon%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
On the contrary, the time is predictable. It is proportional to the ratio of the polygon's extent area divided by the polygon's area, times the time needed to generate and test a single point. The time varies a little, but the variation is proportional to the square root of the number of points. For largish numbers, this becomes inconsequential. Break tortuous polygons into more compact pieces if necessary to get this area ratio down to a low value. Only fractal polygons will give you trouble, but I doubt you have them!
– whuber♦
Feb 22 '11 at 18:34
2
possible duplicate of Distribute points respect to features using Quantum Gis
– Pablo
Feb 22 '11 at 21:15
1
and also: gis.stackexchange.com/questions/4663/…
– Pablo
Feb 22 '11 at 21:18
@Pablo: good finds. However, both of those questions are software specific and both concern placing regular arrays of points within polygons, not random points
– whuber♦
Feb 22 '11 at 21:29
agree with whuber difference is random points vs regular point generation within a polygon.
– Mapperz♦
Feb 22 '11 at 22:53