使用PIL在正方形内画线

问题描述 投票:0回答:1

我正在尝试使用Python和PIL重新创建此图像。

enter image description here

这是我提供的代码:

from PIL import Image, ImageDraw


def draw_lines(draw, points):
    new_points = []
    for idx, point in enumerate(points):
        x, y = point
        if idx != len(points) - 1:
            if idx == 0:
                x = x + 25
            elif idx == 1:
                y = y + 25
            elif idx == 2:
                x = x - 25
            elif idx == 3:
                y = y - 25
        else:
            x = x + 25
        new_points.append((x, y))
    draw.line(new_points, fill="black", width=1)
    return new_points


def main():
    im = Image.new('RGB', (501, 501), color=(255, 255, 255))
    draw = ImageDraw.Draw(im)
    points = [
        (0, 0),
        (500, 0),
        (500, 500),
        (0, 500),
        (0, 0),
    ]
    draw.line(points, fill="black", width=1)
    for i in range(80):
        points = draw_lines(draw, points)
    im.save("out.png")


if __name__ == '__main__':
    main()

这是输出:

enter image description here

还有如何用颜色填充那些形成的三角形?

更新:

通过在此处Rotating a square in PIL修改答案,我能够做到这一点。enter image description here代码:

import math
from PIL import Image, ImageDraw


def distance(ax, ay, bx, by):
    return math.sqrt((by - ay) ** 2 + (bx - ax) ** 2)


def rotated_about(ax, ay, bx, by, angle):
    radius = distance(ax, ay, bx, by)
    angle += math.atan2(ay - by, ax - bx)
    return (
        round(bx + radius * math.cos(angle)),
        round(by + radius * math.sin(angle))
    )


image = Image.new('RGB', (510, 510), color=(255, 255, 255))
draw = ImageDraw.Draw(image)


def draw_sqr(pos, sqlen, rota):
    square_center = pos
    square_length = sqlen

    square_vertices = (
        (square_center[0] + square_length / 2, square_center[1] + square_length / 2),
        (square_center[0] + square_length / 2, square_center[1] - square_length / 2),
        (square_center[0] - square_length / 2, square_center[1] - square_length / 2),
        (square_center[0] - square_length / 2, square_center[1] + square_length / 2)
    )

    square_vertices = [rotated_about(x, y, square_center[0], square_center[1], math.radians(rota)) for x, y in
                       square_vertices]
    draw.polygon(square_vertices, outline="black")


def draw_rot_sqr(pos):
    scale = 500
    rot = 0
    n = 1.1575
    for i in range(10):
        draw_sqr(pos, scale, rot)
        rot = rot * n + 10
        scale = scale / n - 10


draw_rot_sqr((255, 255))

image.show()

现在,如何正确缩放和旋转所有点以任意大小与边相交的正方形?

python python-imaging-library
1个回答
0
投票

这是一个可爱的数学问题。

Cute squares diagram

给出上图,其中L是起始正方形的边长,而L'是新正方形的边长,我们必须找到θ,以便在旋转新正方形时,所有的角都触摸上一个正方形。

L'可以定义为L'=L*f,其中f是缩放因子。例如,如果缩放因子为0.9,则每个新的正方形边将是前一个正方形边的90%。

[使用一些基本三角函数,可以发现a是(calc_a()函数):

“计算<代码一代码>”>

然后,可以使用]计算[C0

我所做的修改产生以下输出。

θ

Cute squares

奖励模因:使用0.98缩放因子进行1000次迭代的输出。

import math from PIL import Image, ImageDraw def calc_a(L, f): return L/2.0*(1-(1-2*(1-f**2))**.5) def calc_theta(L, f): a = calc_a(L, f) return math.atan2(a, L-a) def distance(ax, ay, bx, by): return math.sqrt((by - ay) ** 2 + (bx - ax) ** 2) def rotated_about(ax, ay, bx, by, angle): radius = distance(ax, ay, bx, by) angle += math.atan2(ay - by, ax - bx) return ( round(bx + radius * math.cos(angle)), round(by + radius * math.sin(angle)) ) image = Image.new('RGB', (510, 510), color=(255, 255, 255)) draw = ImageDraw.Draw(image) def draw_sqr(pos, sqlen, rota): square_center = pos square_length = sqlen square_vertices = ( (square_center[0] + square_length / 2, square_center[1] + square_length / 2), (square_center[0] + square_length / 2, square_center[1] - square_length / 2), (square_center[0] - square_length / 2, square_center[1] - square_length / 2), (square_center[0] - square_length / 2, square_center[1] + square_length / 2) ) square_vertices = [rotated_about(x, y, square_center[0], square_center[1], rota) for x, y in square_vertices] draw.polygon(square_vertices, outline="black") def draw_rot_sqr(pos): side = 500 # starting square side length theta = 0 # starting theta (in radians) -- 0 rotation on first square f = 0.9 # scaling factor, should be bigger than sqrt(2)/2, for math reasons (refer to first equation). if over 1, new square will be bigger than previous (still works though!) for i in range(10): draw_sqr(pos, side, theta) # theta is relative to previous square, so we should accumulate it theta += calc_theta(side, f) side *= f draw_rot_sqr((255, 255)) image.show()

© www.soinside.com 2019 - 2024. All rights reserved.