Reputation: 592
I have the following code to generate random points on a given map. I want to avoid having points in the lake area (top right corner). I sort of divided the lake into a rectangle and a triangle. For the rectangle, I could figure out how to avoid having points in there. But, for the triangle (shown with the red line), I couldn't find a solution. Any suggestion? You can find the "Map.png" below the code.
import numpy as np
import matplotlib.pyplot as plt
def point_generator(number):
xlist,ylist = [], []
for i in range(number):
x = np.random.uniform(BBox[0],BBox[1])
y = np.random.uniform(BBox[2],BBox[3])
while x>-87.8 and y>42.25:
x = np.random.uniform(BBox[0],BBox[1])
y = np.random.uniform(BBox[2],BBox[3])
xlist.append(x); ylist.append(y)
return(xlist,ylist)
BBox = ((-89.541239, -87.541239,
40.773460, 42.498943))
im = plt.imread('Map.png')
fig, ax = plt.subplots(figsize = (15,15))
ax.set_xlim(BBox[0],BBox[1])
ax.set_ylim(BBox[2],BBox[3])
plt.plot([-87.8,-87.8],[42.25,42.498943],'-k')
plt.plot([-87.8,-87.541239],[42.25,42.25],'-k')
plt.plot([-87.8,-87.541239],[42.25,41.75],'-r')
xs,ys = point_generator(1500)
plt.plot(xs,ys, '.b')
ax.imshow(im, zorder=0, extent = BBox, aspect= 'equal',alpha=0.5)
Upvotes: -1
Views: 345
Reputation: 11100
You can use the underlying color from the image to check if your points are legit.
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
def bBoxPointToColor(px,w,h,BBox,point):
row = int(((BBox[3]-point[1])/(BBox[3]-BBox[2]))*h)
col = int(((point[0]-BBox[0])/(BBox[1]-BBox[0]))*w)
return sum(abs(k[0]-k[1]) for k in zip(px[col,row],(159, 214, 255))) < 10
def point_generator(number,BBox):
img = Image.open('Chicago.jpg')
px = img.load()
xlist,ylist = [], []
for i in range(number):
x = np.random.uniform(BBox[0],BBox[1])
y = np.random.uniform(BBox[2],BBox[3])
while bBoxPointToColor(px,img.width,img.height,BBox,[x,y]):
x = np.random.uniform(BBox[0],BBox[1])
y = np.random.uniform(BBox[2],BBox[3])
xlist.append(x); ylist.append(y)
return(xlist,ylist)
BBox = ((-89.541239, -87.541239,
40.773460, 42.498943))
im = plt.imread('Chicago.jpg')
fig, ax = plt.subplots(figsize = (15,15))
ax.set_xlim(BBox[0],BBox[1])
ax.set_ylim(BBox[2],BBox[3])
xs,ys = point_generator(1500,BBox)
plt.plot(xs,ys, '.b')
ax.imshow(im, zorder=0, extent = BBox, aspect= 'equal',alpha=0.5)
plt.show()
you can see the issue is that where there is a label on top of the water the point get's drawn on the label... But the benefit is that with this approach you don't have to do custom geometry for new map sections.
Upvotes: 1
Reputation: 7591
A simple yet correct way of achieving this is by generating random points in the entire surface and then removing the random points that fell in the undesired areas. This way, given that the distribution is uniform in all areas, the remaining distribution is still uniform.
Upvotes: 0
Reputation: 926
I don't really know pandas, but maybe you could get the coordinates (x1, y1)
of the start point you want the dots to be removed, and then the coordinates of the end point you want (x2, y2)
and then create a rectangle with the rectangle you created, like (x1, y1)-(x2, y2)
is one side times (x2, y2)-(x2, y1)
is the other side you multiply with so you get a rectangle. Half that and you got the coast line showed in your image. The hypotenuse is the actual coastline
Rectangle: ((x2, y1) - (x1, y1)) * ((x2, y1) - (x2, y2)) = E(rect)
Triangle: E(rect) / 2 = E(triangle)
Coastline: ((x2, y1) - (x1, y1)) ** 2 + ((x2, y1) - (x2, y2)) ** 2 = Hypotenuse (Coastline)
So now you have the surface that you don't want points to appear inside, and the coordinates that make up that surface.
Upvotes: 0