├── 样例.jpg ├── setup.py ├── readme.md └── thyrune └── 碑.py /样例.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RimoChan/thyrune/HEAD/样例.jpg -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | setuptools.setup( 5 | name='thyrune', 6 | version='1.0.1', 7 | author='RimoChan', 8 | author_email='the@librian.net', 9 | description='thyrune', 10 | long_description=open('readme.md', encoding='utf8').read(), 11 | long_description_content_type='text/markdown', 12 | url='https://github.com/RimoChan/thyrune', 13 | packages=[ 14 | 'thyrune', 15 | ], 16 | classifiers=[ 17 | 'Programming Language :: Python :: 3', 18 | 'Operating System :: OS Independent', 19 | ], 20 | install_requires=[ 21 | 'numpy>=1.24.1', 22 | 'numpy-stl>=3.0.1', 23 | ], 24 | ) 25 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 你的纪念碑! 2 | 3 | 事情是这样的,最近好像人类要灭亡了嘛,于是我就想,有没有办法给未来出现在地球上的智慧生物留下什么信息做纪念呢? 4 | 5 | 然后我突然想起来,之前GitHub不是把代码刻在胶片上,埋到北极去了嘛。那我也可以发明1个通用的便宜版,就刻在塑料上,这样1来每个人都可以把纪念埋在家里啦! 6 | 7 | 8 | ## 效果 9 | 10 | 只要输入1串任意的bytes,就可以把它们的2进制数据生成1组3D模型,然后你就可以把它们送到3D打印机里制造纪念碑啦! 11 | 12 | 就像这样—— 13 | 14 | ![样例.jpg](样例.jpg) 15 | 16 | 17 | ## 使用方法 18 | 19 | 首先你需要1个Python,然后: 20 | 21 | ```sh 22 | pip install git+https://github.com/RimoChan/thyrune.git 23 | ``` 24 | 25 | 函数只有1个,是`碑`,定义是这样的: 26 | 27 | ```python 28 | def 碑(data: bytes, X: int = 32, Y: int = 32, S: float = 2) -> List[mesh.Mesh]: ... 29 | ``` 30 | 31 | 其中`data`是你要刻在碑上的数据,`X`和`Y`是每1层的尺寸(不含边框,单位通常是毫米),`S`是模型整体缩放的倍数。 32 | 33 | 返回1组`Mesh`,每个对象表示碑的1层。 34 | 35 | 36 | 使用例: 37 | ```python 38 | import numpy as np 39 | from thyrune.碑 import 碑 40 | 41 | data = np.random.bytes(450) 42 | for i, m in enumerate(碑(data)): 43 | m.save(f'碑{i}.stl') 44 | ``` 45 | 46 | 这样1来450个字节就会生成4个碑层的stl文件,接下来去把它们打印出来,就可以埋进土里等未来的智慧生物来挖啦! 47 | 48 | 49 | ## 注意 50 | 51 | 1. 不要使用可降解的材料打印,1般买打印机送的那个PLA是不行的。尽量使用聚乙烯等难降解的材料打印。 52 | 53 | 2. 但是普通的塑料直接埋在土里好像过1000年就降解了,所以你可以再买1个玻璃罐子放进去再埋。 54 | 55 | 3. 如果人类没有灭亡,也可以把纪念碑放在你的坟墓里。以后未来的考古学家来了,别人的墓碑上只能刻2句话,你可以给考古学家放mp3! 56 | 57 | 58 | ## 结束 59 | 60 | 就这样,我要返回额外卡组了,大家88! 61 | -------------------------------------------------------------------------------- /thyrune/碑.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import numpy as np 4 | from stl import mesh 5 | 6 | 7 | def 矩形分割算法(d: np.array) -> list: 8 | # 我已经忘记了这个算法怎么写了,所以我来写一个奇怪版的 9 | res = [] 10 | for x, _l in enumerate(d): 11 | now = None 12 | for y, h in enumerate(_l): 13 | if h == 0: 14 | if now: 15 | res.append(now) 16 | now = None 17 | continue 18 | assert h == 1 19 | if now is None: 20 | now = [x, y, 1, 1] 21 | else: 22 | now[3] += 1 23 | if now: 24 | res.append(now) 25 | return res 26 | 27 | 28 | def box(x=0, y=0, z=0, sx=1, sy=1, sz=1) -> np.array: 29 | r = [] 30 | for p in range(2): 31 | for q in range(2): 32 | r.append([[0, 1, p], 33 | [1, q, p], 34 | [q, 0, p]]) 35 | r.append([[p, q, q], 36 | [p, 0, 1], 37 | [p, 1, 0]]) 38 | r.append([[0, p, 0], 39 | [q, p, 1-q], 40 | [1, p, 1]]) 41 | data = np.zeros(len(r), dtype=mesh.Mesh.dtype) 42 | for i, l in enumerate(r): 43 | data['vectors'][i] = np.array(l) 44 | data['vectors'][:, :] *= (sx, sy, sz) 45 | data['vectors'][:, :] += (x, y, z) 46 | return data 47 | 48 | 49 | def _碑(data: np.array, X: int, Y: int, S: float) -> mesh.Mesh: 50 | assert len(data) == X * Y 51 | layer = np.ones(shape=(X+4, Y+4), dtype=np.uint8) 52 | layer[1:-1, 1:-1] = 0 53 | layer[-3:-1, -3:-1] = 1 54 | p = 0 55 | for x in range(2, X+2): 56 | for y in range(2, Y+2): 57 | layer[x, y] = data[p] 58 | p += 1 59 | bl = np.concatenate([box(x, y, 0, dx, dy, 1) for x, y, dx, dy in 矩形分割算法(layer)] + [box(0, 0, -1, X+4, Y+4, 1)]) 60 | bl['vectors'] *= S 61 | return mesh.Mesh(bl, remove_empty_areas=False) 62 | 63 | 64 | def 碑(data: bytes, X: int = 32, Y: int = 32, S: float = 2) -> List[mesh.Mesh]: 65 | data = np.unpackbits(np.frombuffer(data, dtype=np.uint8)) 66 | res = [] 67 | while len(data): 68 | if len(data) < X*Y: 69 | data = np.concatenate((data, np.zeros(X*Y-len(data), dtype=np.uint8))) 70 | res.append(_碑(data[:X*Y], X, Y, S)) 71 | data = data[X*Y:] 72 | return res 73 | --------------------------------------------------------------------------------