ACE3/addons/xm157/dev/generate_reticle.py

179 lines
7.6 KiB
Python
Raw Normal View History

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import math
# based on vortex razor hd
final_scale = 10
supersample = 4
# supersampling helps make rounded circles, does slighly blur text and straight lines
pixels_per_mrad = supersample * final_scale
image_size = supersample * 4096
image_center = image_size / 2
# create an image
out = Image.new("RGBA", (image_size, image_size), (255, 255, 255, 0))
# get a drawing context
d = ImageDraw.Draw(out)
line_thin = math.floor(0.07 * pixels_per_mrad)
line_thick = math.floor(0.15 * pixels_per_mrad)
font_size = math.floor(0.55 * pixels_per_mrad)
# source https://fonts.google.com/specimen/Electrolize (Open Font License)
fnt = ImageFont.truetype("Electrolize-Regular.ttf", font_size)
# draw center dot
d.ellipse([
(image_center - 0.1 * pixels_per_mrad, image_center - 0.1 * pixels_per_mrad),
(image_center + 0.1 * pixels_per_mrad, image_center + 0.1 * pixels_per_mrad)
], fill=(0, 0, 0))
# draw 3 main axis lines
d.line([
(image_center - 8 * pixels_per_mrad, image_center),
(image_center - 0.5 * pixels_per_mrad, image_center)
], fill=(0, 0, 0), width=line_thin)
d.line([
(0, image_center),
(image_center - 8.5 * pixels_per_mrad, image_center)
], fill=(0, 0, 0), width=line_thick)
d.line([
(image_center + 0.5 * pixels_per_mrad, image_center),
(image_center + 8 * pixels_per_mrad, image_center)
], fill=(0, 0, 0), width=line_thin)
d.line([
(image_center + 8.5 * pixels_per_mrad, image_center),
(image_size, image_center)
], fill=(0, 0, 0), width=line_thick)
d.line([
(image_center, image_center + 0.5 * pixels_per_mrad),
(image_center, image_center + 11 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thin)
d.line([
(image_center, image_center + 11.5 * pixels_per_mrad),
(image_center, image_size)
], fill=(0, 0, 0), width=line_thick)
# draw big triangle bar things
if (image_center - 15 * pixels_per_mrad > 0):
d.polygon([
(0, image_center + 2 * pixels_per_mrad),
(image_center - 20 * pixels_per_mrad, image_center + 2 * pixels_per_mrad),
(image_center - 15 * pixels_per_mrad, image_center),
(image_center - 20 * pixels_per_mrad, image_center - 2 * pixels_per_mrad),
(0, image_center - 2 * pixels_per_mrad),
], fill=(0, 0, 0))
d.polygon([
(image_size, image_center + 2 * pixels_per_mrad),
(image_center + 20 * pixels_per_mrad, image_center + 2 * pixels_per_mrad),
(image_center + 15 * pixels_per_mrad, image_center),
(image_center + 20 * pixels_per_mrad, image_center - 2 * pixels_per_mrad),
(image_size, image_center - 2 * pixels_per_mrad),
], fill=(0, 0, 0))
d.polygon([
(image_center - 2 * pixels_per_mrad, image_size),
(image_center - 2 * pixels_per_mrad, image_center + 20 * pixels_per_mrad),
(image_center, image_center + 15 * pixels_per_mrad),
(image_center + 2 * pixels_per_mrad, image_center + 20 * pixels_per_mrad),
(image_center + 2 * pixels_per_mrad, image_size),
], fill=(0, 0, 0))
# draw windage hash marks and text
for x in range(1, 9):
if (x % 2 == 0):
text = f"{abs(x)}"
# windage odd numbers
d.text((image_center + (x - 0.15) * pixels_per_mrad, image_center - 1.2 * pixels_per_mrad), text, font=fnt, fill=(0, 0, 0))
d.text((image_center - (x + 0.15) * pixels_per_mrad, image_center - 1.2 * pixels_per_mrad), text, font=fnt, fill=(0, 0, 0))
# windage mrad hashs
d.line([
(image_center + x * pixels_per_mrad, image_center + line_thin / 2),
(image_center + x * pixels_per_mrad, image_center - 0.5 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thin)
d.line([
(image_center - x * pixels_per_mrad, image_center + line_thin / 2),
(image_center - x * pixels_per_mrad, image_center - 0.5 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thin)
if (x % 2 == 0):
d.line([
(image_center - x * pixels_per_mrad, image_center + 0.2 * pixels_per_mrad),
(image_center - x * pixels_per_mrad, image_center + 0.7 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thick)
d.line([
(image_center + x * pixels_per_mrad, image_center + 0.2 * pixels_per_mrad),
(image_center + x * pixels_per_mrad, image_center + 0.7 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thick)
else:
d.line([
(image_center - x * pixels_per_mrad, image_center + 0.2 * pixels_per_mrad),
(image_center - x * pixels_per_mrad, image_center + 0.55 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thick)
d.line([
(image_center + x * pixels_per_mrad, image_center + 0.2 * pixels_per_mrad),
(image_center + x * pixels_per_mrad, image_center + 0.55 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thick)
if (x < 8):
# windage half mrad marks
d.line([
(image_center + (x + .5) * pixels_per_mrad, image_center),
(image_center + (x + .5) * pixels_per_mrad, image_center - 0.25 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thin)
d.line([
(image_center - (x + .5) * pixels_per_mrad, image_center),
(image_center - (x + .5) * pixels_per_mrad, image_center - 0.25 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thin)
# handle 10 mrad thick line
d.multiline_text((image_center + (10 - 0.4) * pixels_per_mrad, image_center - 1.2 * pixels_per_mrad), "10", font=fnt, fill=(0, 0, 0))
d.line([
(image_center + 10 * pixels_per_mrad, image_center - 0.5 * pixels_per_mrad),
(image_center + 10 * pixels_per_mrad, image_center + 0.5 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thick)
d.multiline_text((image_center + (-10 - 0.4) * pixels_per_mrad, image_center - 1.2 * pixels_per_mrad), "10", font=fnt, fill=(0, 0, 0))
d.line([
(image_center - 10 * pixels_per_mrad, image_center - 0.5 * pixels_per_mrad),
(image_center - 10 * pixels_per_mrad, image_center + 0.5 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thick)
for y in range(1, 12):
line_y = image_center + y * pixels_per_mrad
# elev hash marks
d.line([
(image_center - 0.5 * pixels_per_mrad, line_y),
(image_center + 0.5 * pixels_per_mrad, line_y)
], fill=(0, 0, 0), width=line_thin)
if (y < 11): # half marks
d.line([
(image_center - 0.1 * pixels_per_mrad, line_y + 0.5 * pixels_per_mrad),
(image_center + 0.1 * pixels_per_mrad, line_y + 0.5 * pixels_per_mrad)
], fill=(0, 0, 0), width=line_thin)
dot_count = 2
if (y > 2): dot_count = 3
if (y > 4): dot_count = 4
if (y > 6): dot_count = 5
for dot in range(1, dot_count + 1):
d.ellipse([
(image_center + (dot - 0.1) * pixels_per_mrad, line_y - 0.1 * pixels_per_mrad),
(image_center + (dot + 0.1) * pixels_per_mrad, line_y + 0.1 * pixels_per_mrad)
], fill=(0, 0, 0))
d.ellipse([
(image_center + (-dot - 0.1) * pixels_per_mrad, line_y - 0.1 * pixels_per_mrad),
(image_center + (-dot + 0.1) * pixels_per_mrad, line_y + 0.1 * pixels_per_mrad)
], fill=(0, 0, 0))
if (y % 2 == 0):
d.text((image_center + (dot_count + 0.85) * pixels_per_mrad, line_y - 0.3 * pixels_per_mrad), f"{y}", font=fnt, fill=(0, 0, 0))
if (y >= 10): dot_count += 0.2
d.text((image_center - (dot_count + 1.15) * pixels_per_mrad, line_y - 0.3 * pixels_per_mrad), f"{y}", font=fnt, fill=(0, 0, 0))
if (supersample > 1):
out = out.resize((4096, 4096))
output_filename = f"mrad_{final_scale}_ca.png"
out.show()
out.save(output_filename)
print(f"written to {output_filename}")