python 生成随机星座图

python 生成随机星座图(2020年5月7日)


原理

在一个矩形区域内随机取一些点,遍历每个点,使得每个点与距离它自己最近的点相连。最后以一张图片的形式展现出来

(由于只是看起来像星座,所以就命名随机星座了)

制作背景

大一上学期疫情时代在家所作。有了一定的Python基础,以及了解了一点PIL第三方图像处理库。

这个“星座线”纯粹是自己在高中的时候想到的,现在由于可以用编程实现可视化了,于是想做个程序来看看具体的效果。

效果图

starSky_40_1588789159.7254107.png

同时还可以调整参数来修改图片大小和星星数量
其实看起来不是很像星座了,像散落一地的毛。这可能也是和这些点的分布比较均匀有关。


starSky_4000_1588789625.7141373.png

当然还可以修改一个大于小于号来改变原理,变成“每个点和距离自己最远的点相连”,这样图片就彻底变样了。


starSky_1024_1588791031.3317997.png

源代码

"""
生成座线图片
生成星座线图片的程序,星座线原理:每个点连向距离它最近的点成一条线段,遍历所有点
2020年5月7日
by littlefean
"""
from random import randint
from PIL import Image
from time import time


def sky_randomly(number, width, height):
    """
    生成一片星空,返回一个列表
    :param number: 星星数量
    :param width: 图片宽度
    :param height: 图片高度
    :return: 所有星星位置列表
    """
    stars = []  # 此列表中存放所有的星星位置信息
    for i in range(number):
        if i >= width * height:
            exit("错误,星星挤满了图片")
        else:
            starLoc = (randint(0, width - 1), randint(0, height - 1))
            if starLoc not in stars:
                stars.append(starLoc)
    return stars


def connect(pic, p1, p2):
    """
    在图片中画一条直线段
    :param pic: 图片
    :param p1: 端点1,元组
    :param p2: 端点2,元组
    :return:
    """
    color = (255, 255, 255)
    pic.putpixel((p1[0], p1[1]), color)
    if (p1[0] == p2[0]) and (p1[1] == p2[1]):
        pic.putpixel(p1, color)
    else:
        if abs(p2[0] - p1[0]) >= abs(p2[1] - p1[1]):
            step = abs(p2[0] - p1[0])
        else:
            step = abs(p2[1] - p1[1])
        for i in range(step):
            x = round(p1[0] + (p2[0] - p1[0]) / step * (i + 1))
            y = round(p1[1] + (p2[1] - p1[1]) / step * (i + 1))
            pic.putpixel((x, y), color)


def get_img(starList, width, height):
    """
    根据星空列表生成图片并返回
    :param starList: 星空列表
    :param width: 图片宽度
    :param height: 图片高度
    :return: 图片
    """
    im = Image.new('RGB', (width, height), 'black')

    StarsWays = []  # 此列表存放所有星星和所有星星之间的距离信息
    # 遍历每一个星星i,在遍历i时遍历每一个星星,计算所有星与星之间的距离
    for i in range(len(starList) - 1):
        Ways = []  # 此列表存放第i个星星和其余星星之间的距离信息,其素是“ (距离, 星星1, 星星2) ” 元组数
        for j in range(len(starList) - 1):
            if i != j:
                distance = ((starList[i][0] - starList[j][0]) ** 2 + (starList[i][1] - starList[j][1]) ** 2) ** 0.5
                Ways.append((distance, starList[i], starList[j]))
        StarsWays.append(Ways)
    # 找出列中距离最近的
    for k in range(len(StarsWays) - 1):
        # 遍历每一个星
        d = StarsWays[k][0][0]
        for m in range(len(StarsWays[k]) - 1):
            # 遍历一个星中的所有距离 d是最近的距离
            if d > StarsWays[k][m][0]:
                d = StarsWays[k][m][0]
        for m in range(len(StarsWays[k]) - 1):
            # 把距离对应的两点找出来 并在图上连线
            if d == StarsWays[k][m][0]:
                connect(im, StarsWays[k][m][1], StarsWays[k][m][2])
    return im


if __name__ == '__main__':
    X = 4096
    Y = 4096
    numbers = 1024
    sk = sky_randomly(numbers, X, Y)
    print("生成完毕")
    img = get_img(sk, X, Y)
    img.save(f'starSky_{numbers}_{time()}.png')

说明

大半年过去了,现在看到当时的代码感觉算法的时间复杂度和空间复杂度都很大,我自己都并不是很满意。因此此文章待更新,算法待优化。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容