66 lines
2.8 KiB
Python
66 lines
2.8 KiB
Python
import math
|
||
import numpy as np
|
||
from PIL import Image, ImageDraw
|
||
|
||
SIZE = 1024
|
||
CENTER = SIZE / 2.0
|
||
R_RING = SIZE * 0.082
|
||
W_RING = 24.0 # Толщина кольца
|
||
|
||
img = Image.new('RGBA', (SIZE, SIZE), (10, 10, 20, 255))
|
||
draw = ImageDraw.Draw(img)
|
||
|
||
# Проверяем строгое касательное совпадение:
|
||
# В точке старта внешняя кромка ленты СТРОГО совпадает с внешней кромкой кольца (R_RING + W_RING/2)
|
||
# Внутренность круга АБСОЛЮТНО чистая (ни единой линии внутрь круга не заходит)
|
||
for k in range(3):
|
||
rot = -math.pi / 2.0 + k * (2.0 * math.pi / 3.0)
|
||
spine = []
|
||
widths = []
|
||
|
||
num_steps = 80
|
||
for s in range(num_steps):
|
||
t = s / float(num_steps - 1)
|
||
ang = rot + t * 1.70
|
||
# В точке t=0: rad = R_RING ровно по окружности кольца
|
||
# dRad/dt при t=0 строго равно 0 (t^1.8)
|
||
rad = R_RING + (t**1.8) * (SIZE * 0.155)
|
||
px = CENTER + rad * math.cos(ang)
|
||
py = CENTER + rad * math.sin(ang)
|
||
spine.append((px, py))
|
||
|
||
# В точке t=0 толщина ленты в точности равна толщине кольца W_RING (24px)!
|
||
# Внешняя граница: R_RING + 12px (ровно край кольца!)
|
||
# Внутренняя граница: R_RING - 12px (ровно внутренний край кольца!)
|
||
# Ни одного пикселя внутрь круга, ни одного пикселя выступа наружу!
|
||
w = W_RING * (1.0 - (t**0.85) * 0.88)
|
||
widths.append(max(2.0, w))
|
||
|
||
left = []
|
||
right = []
|
||
for i in range(len(spine)):
|
||
p = spine[i]
|
||
w = widths[i] / 2.0
|
||
if i == 0:
|
||
dx = spine[1][0] - p[0]
|
||
dy = spine[1][1] - p[1]
|
||
elif i == len(spine) - 1:
|
||
dx = p[0] - spine[i-1][0]
|
||
dy = p[1] - spine[i-1][1]
|
||
else:
|
||
dx = spine[i+1][0] - spine[i-1][0]
|
||
dy = spine[i+1][1] - spine[i-1][1]
|
||
length = math.hypot(dx, dy) + 1e-6
|
||
nx = -dy / length
|
||
ny = dx / length
|
||
left.append((p[0] + nx * w, p[1] + ny * w))
|
||
right.append((p[0] - nx * w, p[1] - ny * w))
|
||
|
||
poly = left + right[::-1]
|
||
draw.polygon(poly, fill=(255, 220, 80, 255))
|
||
|
||
# Центральное кольцо ложится встык с точностью до микропикселя
|
||
draw.ellipse([CENTER - R_RING, CENTER - R_RING, CENTER + R_RING, CENTER + R_RING], outline=(255, 220, 80, 255), width=int(W_RING))
|
||
img.save('/home/alexives/.gemini/antigravity-ide/brain/4ff924d9-3d7f-4202-9066-3ac5c3088b8e/scratch/test_flush.png')
|
||
print("Saved test_flush.png successfully!")
|