i created a Random Point Generator in python using the algorithm described here by @whuber. The algorithm is implemented using Shapely, PostGIS and psycopg2. To boost performance pythons multiprocessing and threading libraries are used. The source code can be found in my GitHub Repository. The code generates a total of 57.990.970 Points within 6388 Polygons in ~3517 sec on my Xeon-1231v3 with 16GB Ram.

Procedure SimpleRandomSample(P:Polygon, N:Integer) {
    U = Sorted list of N independent uniform values between 0 and 1
    Return SRS(P, BoundingBox(P), U)

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

But concerning the algorithm I have an open question. It mentions a U = Sorted list of N independent uniform values between 0 and 1 which i could build using numpy.uniform(0, 1, numberOfValues). But then the algorithm will generate weird results, like one part of the polygon will not have any points in it. I work around this issue by weighting the points to be created by the recursive call using k = int(round(n * (p1.area / polygon.area))).

So my question is why this List of uniform values between 0 and 1 should be used in the first place.

  • Bill could answer more completely, but I'd think the discrete set of intervals (randomly chosen) would force the distribution to be more complete in less time. Can you quantify these "weird results" you'd expect?
    – Vince
    Nov 18 '14 at 21:25
  • Well the weird result appeared once t was set so something smaller than 2. It started splitting the Polygon and basicly one part of it had no points in it. The problem was that K becomes a value between 0 and 1, but after splitting U like U[1::K] the max value in U might become smaller than K which forces U[K+1::N] to have a length of 0, thus no points are generated in this recursive call.
    – Benjamin
    Nov 18 '14 at 21:32
  • K is an integer between 0 and N.
    – Vince
    Nov 18 '14 at 22:09
  • Ehm stupid me, I wanted to say the area of the sub-polygon p1 divided by the whole area is something between 0-1. So Search does look in U where the index of the element is which is smaller than the result. But again if U was split before, lets say at 0.5 and the result is 0.7, K will be the last index of U, thus in p2 no points will be created. It only would make sense to search U if you recreate it every time SRS is run. But then also you would not need to pass it to the function. Just the number of points to be generated would be sufficient.
    – Benjamin
    Nov 18 '14 at 22:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.