Reputation: 537
Hello!
I am trying to populate a rectangular domain with shapes that do not touch and I am trying to use shapely to help me do this.
So, for example, you have a square/rectangular domain, and want to fill it with randomly placed smaller squares/rectangles that must not overlap (or touch).
The problem I'm having is that I don't know which coordinates I will need before creating new Polygon objects. I need to generate a random location but how do I test if the random location isn't overlapping with the edges of the domain or other objects already within the domain? To do this, you have to create the object and then compare it to existing objects. Except in shapely (as far as I can tell) there is no way to delete objects once created.
So my first thought was that I can create an object as a "test" and then move it to some other randomly chosen coordinates and try again there. This would have worked except that I may need to delete an object after creating it. For example, if there is no space left for any objects and I place one in, then find out after having done so that it doesn't fit, I can't then "take it out". According to shapely it is there forever now and can only be moved around.
What is my solution here? Is there a way to remove shapes from the coordinate system? Or can I perhaps create shapes on multiple coordinate systems at the same time?
To illustrate the question a bit better (and with some code) I want the following to return False.
from shapely.geometry import Polygon
# create my first polygon
p1 = Polygon([(0, 0), (0, 10), (10, 10), (10, 0)])
# somehow create a second polygon in a new coordinate system
# OR delete the first polygon somehow
p2 = Polygon([(0, 0), (0, 10), (10, 10), (10, 0)])
# then this would return False.
# At the moment it only ever returns True
print(p1.intersects(p2))
I hope that is sufficiently clear! If this isn't possible I'll have to abandon using shapely for this I think as this is a big requirement for my project.
Upvotes: 0
Views: 635
Reputation: 3583
Why not generate a whole polygon. See if it's fine and discard it if it intersects the others.
import numpy as np
from shapely.geometry import Polygon
def get_random_polygon():
n = np.random.randint(3,15)
center = 2*10**4*np.random.random(size=(1,2))
points = center+10**4*np.random.random(size=(n,2))
p = Polygon(points)
if p.is_valid:
return p
return get_random_polygon()
def generate_nonintersecting_polygons(k):
p = get_random_polygon()
i = 1
while i < k:
q = get_random_polygon()
if not p.intersects(q):
p = p.union(q)
i += 1
return p
generate_nonintersecting_polygons(6)
import numpy as np
from shapely.geometry import Polygon
def get_squarre_with_random_position():
center = 50*np.random.random(size=(1,2))
points = center+np.array([(0, 0), (0, 10), (10, 10), (10, 0)])
p = Polygon(points)
if p.is_valid:
return p
return get_random_polygon()
def generate_nonintersecting_polygons(k):
p = get_squarre_with_random_position()
i = 1
while i < k:
q = get_squarre_with_random_position()
if not p.intersects(q):
p = p.union(q)
i += 1
return p
generate_nonintersecting_polygons(6)
Upvotes: 1
Reputation: 26
What about giving every random-generated-polygons coordinates to a list then make the code look "is there any overlapping coordinates here".
Then code will generate another random polygon and if that one overlaps too it will try again ...
Upvotes: 0