您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

我怎么能随意放置一些非冲突rects?

我怎么能随意放置一些非冲突rects?

我已经改变了我的回答一点,以解决有关是否可以进行修改,而不是随机生成非冲突的后续问题 的正方形 ,而不是任意矩形。我在我可以将工作的最简单的方法,这是后处理我原来的答复的矩形输出,把它的内容变成方形子区这样做。我还更新了可选的可视化代码,以显示两种输出。显然,这种过滤可以扩展到做其他事情一样insetting每个矩形或方形略,以防止它们彼此接触。

我的回答避免做很多的答案已经发布做 - 这是随机产生的矩形,同时拒绝任何碰撞与任何已创建的 - 因为它听起来固有的缓慢性和计算浪费。我的方法,而不是集中于只产生那些不重叠摆在首位。

这使得有什么需要做的将其变成可以非常快速地进行一个简单的区域划分的问题相对简单。下面是一个实现的如何可以做。它始于限定其中它分成四个较小的非重叠矩形外边界的矩形。这是通过选择一个随机的内部点并将其与外部矩形的四个现有角点一起使用以形成四个子区域来实现的。

大部分的动作发生在quadsect()函数。内部点的选择是决定什么输出看起来象是至关重要的。你可以约束它,你希望的任何方式,比如只选择一个,将导致至少在一定的最小宽度或高度或不超过一定量较大的子矩形。在我的回答样本代码,它的定义为中心点± 1 / 3的宽度和外矩形的高度的,但基本上任何内部点会工作到一定程度。

由于这种算法生成子矩形非常迅速,这是确定的,花一些计算时间确定内部分割点。

为了显示方法的结果,有一些非必要的代码的结尾,它使用PIL(Python图像库)模块来创建一个图像文件显示在一些测试运行我做产生的矩形。

无论如何,这是代码输出示例的最新版本:

import random
from random import randint
random.seed()

NUM_RECTS = 20
REGION = Rect(0, 0, 640, 480)

class Point(object):
    def __init__(self, x, y):
        self.x, self.y = x, y

    @staticmethod
    def from_point(other):
        return Point(other.x, other.y)

class Rect(object):
    def __init__(self, x1, y1, x2, y2):
        minx, maxx = (x1,x2) if x1 < x2 else (x2,x1)
        miny, maxy = (y1,y2) if y1 < y2 else (y2,y1)
        self.min, self.max = Point(minx, miny), Point(maxx, maxy)

    @staticmethod
    def from_points(p1, p2):
        return Rect(p1.x, p1.y, p2.x, p2.y)

    width  = property(lambda self: self.max.x - self.min.x)
    height = property(lambda self: self.max.y - self.min.y)

plus_or_minus = lambda v: v * [-1, 1][(randint(0, 100) % 2)]  # equal chance +/-1

def quadsect(rect, factor):
    """ Subdivide given rectangle into four non-overlapping rectangles.
        'factor' is an integer representing the proportion of the width or
        height the deviatation from the center of the rectangle allowed.
    """
    # pick a point in the interior of given rectangle
    w, h = rect.width, rect.height  # cache properties
    center = Point(rect.min.x + (w // 2), rect.min.y + (h // 2))
    delta_x = plus_or_minus(randint(0, w // factor))
    delta_y = plus_or_minus(randint(0, h // factor))
    interior = Point(center.x + delta_x, center.y + delta_y)

    # create rectangles from the interior point and the corners of the outer one
    return [Rect(interior.x, interior.y, rect.min.x, rect.min.y),
            Rect(interior.x, interior.y, rect.max.x, rect.min.y),
            Rect(interior.x, interior.y, rect.max.x, rect.max.y),
            Rect(interior.x, interior.y, rect.min.x, rect.max.y)]

def square_subregion(rect):
    """ Return a square rectangle centered within the given rectangle """
    w, h = rect.width, rect.height  # cache properties
    if w < h:
        offset = (h - w) // 2
        return Rect(rect.min.x, rect.min.y+offset,
                    rect.max.x, rect.min.y+offset+w)
    else:
        offset = (w - h) // 2
        return Rect(rect.min.x+offset, rect.min.y,
                    rect.min.x+offset+h, rect.max.y)

# call quadsect() until at least the number of rects wanted has been generated
rects = [REGION]   # seed output list
while len(rects) <= NUM_RECTS:
    rects = [subrect for rect in rects
                        for subrect in quadsect(rect, 3)]

random.shuffle(rects)  # mix them up
sample = random.sample(rects, NUM_RECTS)  # select the desired number
print '%d out of the %d rectangles selected' % (NUM_RECTS, len(rects))

#################################################
# extra credit - create an image file showing results

from PIL import Image, ImageDraw

def gray(v): return tuple(int(v*255) for _ in range(3))

BLACK, DARK_GRAY, GRAY = gray(0), gray(.25), gray(.5)
LIGHT_GRAY, WHITE = gray(.75), gray(1)
RED, GREEN, BLUE = (255, 0, 0), (0, 255, 0), (0, 0, 255)
CYAN, MAGENTA, YELLOW = (0, 255, 255), (255, 0, 255), (255, 255, 0)
BACKGR, SQUARE_COLOR, RECT_COLOR = (245, 245, 87), (255, 73, 73), (37, 182, 249)

imgx, imgy = REGION.max.x + 1, REGION.max.y + 1
image = Image.new("RGB", (imgx, imgy), BACKGR)  # create color image
draw = ImageDraw.Draw(image)

def draw_rect(rect, fill=None, outline=WHITE):
    draw.rectangle([(rect.min.x, rect.min.y), (rect.max.x, rect.max.y)],
                   fill=fill, outline=outline)

# first draw outlines of all the non-overlapping rectanges generated
for rect in rects:
    draw_rect(rect, outline=LIGHT_GRAY)

# then draw the random sample of them selected
for rect in sample:
    draw_rect(rect, fill=RECT_COLOR, outline=WHITE)

# and lastly convert those into squares and re-draw them in another color
for rect in sample:
    draw_rect(square_subregion(rect), fill=SQUARE_COLOR, outline=WHITE)

filename = 'square_quadsections.png'
image.save(filename, "PNG")
print repr(filename), 'output image saved'

输出采样1

第一采样输出图像

输出采样2

第二个样本输出图像

其他 2022/1/1 18:50:21 有486人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶