python 打印卷尺
起因
想量一量?围,于是想买一个卷尺.要到?宝上买东西,就得看评论了,可是又有人说那家的卷尺有味道.于是就想自己自己做一个了.打印机其实是个挺好的工具,虽然不是3d打印机,但是2d的打印机打印2d的卷尺其实已经够用了.
经过
思路基本上就是,通过代码将直尺绘制在位图或矢量图上,之后通过图片或者pdf文档的方式打印出来,绘制的时候要注意尺寸比例.
出于编程复杂度方面的考量选择了位图并且直接打印图片的方式.
结果代码如下:
'''
The code generates an image ruler according to the configuration.
Then a printer is used to convert the image to a useable ruler.
'''
'''
Paper mm inches
A3 297 x 420 mm 11.7 x 16.5 inches
A4 210 x 297 mm 8.3 x 11.7 inches
A5 148.5 x 210 mm 5.8 x 8.3 inches
A6 105 x 148.5 mm 4.1 x 5.8 inches
'''
paper_sizes={
'A3': (297,420),
'A4': (210,297),
'A5': (148.5,210),
'A6': (105,148.5)
}
from PIL import Image,ImageDraw,ImageFont
import sys
import math
import json
# parse arguments
with open('config.json') as f:
config=json.load(f)
paper_w,paper_h=paper_sizes[config['paper_type']]
k=config['precision']
ruler_w=config['ruler_w']
ruler_l=config['ruler_h']
ruler_start=config['ruler_start']
overlap_l=config['overlap_l']
scale_l=[3,2,1]
margin_top=10
margin_bot=10
font=ImageFont.truetype(config['font_file'],k*4)
# font=ImageFont.truetype(r'C:\Windows\Fonts\consola.ttf',k*5)
# checking and calculating
seg_l=paper_h-margin_top-margin_bot
# seg_l+n_seg*(seg_l-overlap_l)
n_seg=math.ceil((ruler_l-seg_l)/(seg_l-overlap_l))+1
seg_w=ruler_w
seg_margin=paper_w//n_seg-seg_w
if seg_margin<=0:
print('Not enough space on paper!',file=sys.stderr)
im=Image.new('RGB',(paper_w*k,paper_h*k),(255,255,255))
draw=ImageDraw.Draw(im)
for i in range(n_seg):
lux,luy=(seg_w+seg_margin)*i+seg_margin/2,margin_top
# draw horizontal line
draw.line((lux*k,0*k,lux*k,(im.height-margin_bot)*k),fill=(0,0,0))
draw.line(((lux+seg_w)*k,0*k,(lux+seg_w)*k,(im.height-margin_bot)*k),fill=(0,0,0))
seg_l=paper_h-margin_top-margin_bot
seg_s=i*(seg_l-overlap_l)
if seg_s+overlap_l>=ruler_l:
break
for j in range(seg_l):
if seg_s+j>ruler_l:
break
if (seg_s+j)%10==0:
sl=scale_l[0]
# draw number
s=str((seg_s+j)//10)
size=font.getsize(s)
draw.text(((lux+seg_w/2)*k-size[0]/2,(luy+j)*k-size[1]/2),s,fill=(0,0,0),font=font)
elif (seg_s+j)%5==0:
sl=scale_l[1]
else:
sl=scale_l[2]
# draw scales
draw.line((lux*k,(luy+j)*k,(lux+sl)*k,(luy+j)*k),fill=(0,0,0))
draw.line(((lux+seg_w)*k,(luy+j)*k,(lux+seg_w-sl)*k,(luy+j)*k),fill=(0,0,0))
# draw paper border
draw.line((0*k+1,0*k+1,paper_w*k-1,0*k+1),fill=(0,0,0))
draw.line((paper_w*k-1,0*k+1,paper_w*k-1,paper_h*k-1),fill=(0,0,0))
draw.line((paper_w*k-1,paper_h*k-1,0*k+1,paper_h*k-1),fill=(0,0,0))
draw.line((0*k+1,paper_h*k-1,0*k+1,0*k+1),fill=(0,0,0))
# TODO: draw ruler start and end line
im.save('ruler.png')
{
"paper_type": "A4",
"precision": 10,
"ruler_w": 15,
"ruler_h": 2000,
"overlap_l": 10,
"font_file": "C:\\Windows\\Fonts\\consola.TTF",
"ruler_start": 0,
"scale_l": [3,2,1]
}
show: ruler.png
ruler.png
ruler.png: ruler_gen.py
python ruler_gen.py
clean:
del ruler.png
当然是可以通过配置文件修改参数了,其实也就是使用PIL
画了几条线而已,之后再添加一些数字.不过我觉得还挺好看,自己测试的时候是没问题的.其它的尺寸和参数也没有特别测试过.
结果
结果就是打印完之后还需要自己用裁纸刀才下来,如果需要保证耐用性,可以用胶带把它包裹起来(好累!).还有一个问题就是两次打印出来的结果刻度线的清晰程度不一样,不知道是不是我第二次没有打印原图的原因.