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')
说明
大半年过去了,现在看到当时的代码感觉算法的时间复杂度和空间复杂度都很大,我自己都并不是很满意。因此此文章待更新,算法待优化。