我一直致力于在1x1网格上生成一层随机旋转并放置的正方形。我已经能够生成一个随机放置并在网格上旋转的单个方块,但我不确定如何改进代码以生成更多不相互交叉的随机方块。目前的代码见下文:
Example of my One Randomized Square
from math import cos, pi, sin
from random import randint
from matplotlib.mlab import frange
from matplotlib.pyplot import plot, axis, show
def flake_position_layer1(): #Determines the initial position of one corner of the square
x0 = randint(0, 100) / 100
y0 = randint(0, 100) / 100
theta = randint(0, 90) * pi / 180 #Angle of rotation for the square
return x0, y0, theta
def flake_shape(): #generates the other 3 corners of the square
x0, y0, z, theta = flake_position_layer1()
x1 = x0 + (0.1 * cos(theta))
x2 = x1 + (0.1 * cos((90 * pi/180) + theta))
x3 = x2 + (0.1 * cos((180 * pi/180) + theta))
y1 = y0 + (0.1 * sin(theta))
y2 = y1 + (0.1 * sin((90 * pi/180) + theta))
y3 = y2 + (0.1 * sin((180 * pi/180) + theta))
return x0, x1, x2, x3, y0, y1, y2, y3
def display(): #connects the 4 corners on a plot
x0, x1, x2, x3, y0, y1, y2, y3 = flake_shape()
return plot([x0, x1, x2, x3, x0], [y0, y1, y2, y3, y0])
display()
axis([0,1,0,1]) #1x1 grid
show()
我没有CS背景(我是环境工程专业),而且我对编码非常缺乏经验。请给我任何建议,让我尝试解决这个问题!
答案 0 :(得分:1)
您需要一个函数来确定两个立方体是否相交。
--http-keepalive
答案 1 :(得分:1)
好的,这是我在shapely软件包的帮助下提出的。安装帮助在这里的底部。最终结果:
distance
是一个辅助函数,它使用Point
类从形状上找到两个坐标之间的距离。只是一个辅助功能,以后再用。Square
实例化一个新的多边形。它有4个角,每个角为(x,y)对,其中心为一个坐标,标量值等于对角线距离的一半。test_overlap
通过标题非常自我解释。但从逻辑上讲,它的作用是:找到两个形状之间从中心到中心的距离。然后找到每个形状的半对角线的总和。如果中心距离大于总和,则方格不能重叠。Squares
从一个空容器(空列表)开始,并尝试向其添加方块。但是对于每一个可能的新增加,它首先测试与现有的正方形没有重叠。import math
import random
from shapely.geometry import Polygon, Point
def distance(a, b):
return Point(a).distance(Point(b))
class Square(object):
def __init__(self):
self.x0, self.y0 = random.random(), random.random()
theta = random.randint(0, 90) * math.pi / 180 # Angle of rotation
self.x1 = self.x0 + (0.1 * math.cos(theta))
self.x2 = self.x1 + (0.1 * math.cos((90 * math.pi/180) + theta))
self.x3 = self.x2 + (0.1 * math.cos((180 * math.pi/180) + theta))
self.y1 = self.y0 + (0.1 * math.sin(theta))
self.y2 = self.y1 + (0.1 * math.sin((90 * math.pi/180) + theta))
self.y3 = self.y2 + (0.1 * math.sin((180 * math.pi/180) + theta))
self.corners = ((self.x0, self.y0), (self.x1, self.y1),
(self.x2, self.y2), (self.x3, self.y3))
@property
def center(self):
"""(x, y) of the center of the polygon."""
return Polygon(self.corners).centroid.coords[0]
@property
def half_diag(self):
"""The distance of 1/2 the shape's diagonal (center-to-corner)."""
p0, p1, p2, p3 = self.corners
return 0.5 * distance(p0, p1) * math.sqrt(2)
def test_overlap(square1, square2):
"""Do two shapes overlap?
Note this is a 'conservative' test. May return True if they do not
(false positive), but will never return False if they do (false negative).
"""
# Distance between two centers
ctc = distance(square1.center, square2.center)
# Sum of half-diagonals
halfdiags = square1.half_diag + square2.half_diag
res = ctc < halfdiags
return res
class Squares(object):
def __init__(self):
self.squares = []
def add_square(self):
new_square = Square()
if not self.squares:
# Initial empty list/container - just add without any tests
self.squares.append(new_square)
else:
while True:
# Test that new_square overlaps with existing
res = [test_overlap(square, new_square) for square in self.squares]
if any(res):
# We have at least 1 case of overlap (1 True)
new_square = Square()
else:
# Safe to add
self.squares.append(new_square)
break
def plot_squares(self):
for square in self.squares:
(x0, y0), (x1, y1), (x2, y2), (x3, y3) = square.corners
plt.plot([x0, x1, x2, x3, x0], [y0, y1, y2, y3, y0])
import itertools
%matplotlib inline
for _ in itertools.repeat(None, 10):
# Add 10 squares; you could also just build this into the class
sqs.add_square()
sqs.plot_squares()
shapely
如果您还没有安装Anaconda发行版。然后只需使用conda-forge
进行整形安装即可。从cmd
运行:
conda config --add channels conda-forge
conda install shapely
在某个时刻,你的方块容器被填满,剩下的空间很小,无法添加新的形状。即使有可用空间,该功能基本上是反复试验,因此在高形状计数时需要很长时间。目前这种情况发生在大约20-25个方格(1.0x1.0方框)中。