45 lines
1.3 KiB
Python
45 lines
1.3 KiB
Python
import numpy as np
|
|
from PIL import Image, ImageDraw
|
|
|
|
# Parameters
|
|
R = 9.0 # mm
|
|
H = 20.0 # mm
|
|
fov_half = np.radians(75) # 75 degrees half-angle
|
|
pixels_per_mm = 100
|
|
|
|
# Texture dimensions
|
|
width = int(np.pi * 2 * R * pixels_per_mm) # circumference
|
|
height = int(H * pixels_per_mm)
|
|
|
|
# Desired dot pattern in image space (normalized)
|
|
delta_theta = np.radians(10) # 10° azimuth spacing
|
|
delta_r = 0.1 # radial spacing in normalized units
|
|
rho = 0.08 # normalized dot radius (from reference)
|
|
|
|
# Generate dot centers in image space
|
|
r_vals = np.arange(R/H, np.tan(fov_half), delta_r)
|
|
theta_vals = np.arange(0, 2*np.pi, delta_theta)
|
|
|
|
# Create empty texture (white background)
|
|
img = Image.new('L', (width, height), color=255)
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
for r_img in r_vals:
|
|
z = R / r_img
|
|
v = z / H
|
|
# Ellipse axes in texture coordinates
|
|
a_u = (rho * z) / (2 * np.pi * R)
|
|
a_v = (rho * z**2) / (R * H)
|
|
# Convert to pixels
|
|
a_u_px = a_u * width
|
|
a_v_px = a_v * height
|
|
for theta in theta_vals:
|
|
u = theta / (2 * np.pi)
|
|
cx = u * width
|
|
cy = v * height
|
|
# Draw ellipse (bounding box)
|
|
bbox = [cx - a_u_px, cy - a_v_px, cx + a_u_px, cy + a_v_px]
|
|
draw.ellipse(bbox, fill=0) # black dot
|
|
|
|
img.save('cylinder_marker_texture.png')
|