feat: complete academic symbol lexicon heal, 2-column Cooper extraction, and updated assets
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
import math
|
||||
import numpy as np
|
||||
from PIL import Image, ImageDraw, ImageFilter
|
||||
|
||||
HI_SIZE = 4096
|
||||
OUT_SIZE = 1024
|
||||
CENTER = HI_SIZE / 2.0
|
||||
|
||||
# ==============================================================================
|
||||
# 1. ЖИВОЙ, СОЧНЫЙ КОСМОС: ГАЛАКТИКИ, ГРАДИЕНТЫ И НЕБУЛЫ (КАК В ИНТЕРСТЕЛЛАРЕ)
|
||||
# ==============================================================================
|
||||
bg = Image.new('RGBA', (HI_SIZE, HI_SIZE), (4, 4, 14, 255))
|
||||
|
||||
# Спиральные рукава галактики с богатыми градиентами (маджента, фиолетовый, индиго, циановый)
|
||||
galaxy = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
gdraw = ImageDraw.Draw(galaxy)
|
||||
|
||||
# 2 главных спиральных рукава галактики
|
||||
for arm in range(2):
|
||||
arm_offset = arm * math.pi
|
||||
for step in range(120):
|
||||
t = step / 119.0
|
||||
# Логарифмическая спираль рукава
|
||||
angle = arm_offset + t * math.pi * 1.8
|
||||
radius = 180 + t * (HI_SIZE * 0.48)
|
||||
cx = CENTER + radius * math.cos(angle)
|
||||
cy = CENTER + radius * math.sin(angle)
|
||||
|
||||
# Размеры облаков туманности вдоль рукава
|
||||
spread = 220 + t * 450
|
||||
|
||||
# Цвета переливаются от глубокого ультрамарина через мадженту к бирюзовому
|
||||
if step < 40:
|
||||
col = (65, 20, 95, int(45 * (1 - t*0.5))) # Маджента-фиолетовый в глубине
|
||||
elif step < 80:
|
||||
col = (25, 45, 115, int(50 * (1 - t*0.5))) # Глубокий ультрамарин
|
||||
else:
|
||||
col = (15, 75, 110, int(40 * (1 - t*0.5))) # Бирюзовая вуаль на окраине
|
||||
|
||||
gdraw.ellipse([cx - spread, cy - spread*0.7, cx + spread, cy + spread*0.7], fill=col)
|
||||
|
||||
galaxy = galaxy.filter(ImageFilter.GaussianBlur(280))
|
||||
bg = Image.alpha_composite(bg, galaxy)
|
||||
|
||||
# Золотисто-янтарный аккреционный диск (гравитационное линзирование черной дыры Gargantua)
|
||||
accretion = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
adraw = ImageDraw.Draw(accretion)
|
||||
|
||||
# Наклонный диск аккреции
|
||||
disc_angle = math.radians(-28)
|
||||
cos_a = math.cos(disc_angle)
|
||||
sin_a = math.sin(disc_angle)
|
||||
|
||||
for r in range(25):
|
||||
t = r / 24.0
|
||||
w = 1750 - t * 650
|
||||
h = 600 - t * 250
|
||||
# Внутреннее свечение горячее и ярче
|
||||
alpha = int(70 * (1.0 - t**1.5))
|
||||
col = (int(255 - t*40), int(140 + t*30), int(30 + t*50), alpha)
|
||||
adraw.ellipse([CENTER - w, CENTER - h, CENTER + w, CENTER + h], fill=col)
|
||||
|
||||
# Верхняя и нижняя гравитационные арки (эйнштейновское кольцо)
|
||||
adraw.ellipse([CENTER - 1100, CENTER - 1100, CENTER + 1100, CENTER + 1100], fill=(240, 150, 45, 45))
|
||||
adraw.ellipse([CENTER - 750, CENTER - 750, CENTER + 750, CENTER + 750], fill=(255, 195, 80, 55))
|
||||
|
||||
accretion = accretion.filter(ImageFilter.GaussianBlur(180))
|
||||
bg = Image.alpha_composite(bg, accretion)
|
||||
|
||||
# Мягкое звездное скопление (разноцветные жемчужные звезды с мягким ореолом)
|
||||
np.random.seed(777)
|
||||
stars = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
sdraw = ImageDraw.Draw(stars)
|
||||
for _ in range(650):
|
||||
sx = np.random.uniform(40, HI_SIZE - 40)
|
||||
sy = np.random.uniform(40, HI_SIZE - 40)
|
||||
rad = np.random.uniform(2, 9)
|
||||
alpha = np.random.randint(60, 220)
|
||||
# Звездные классы: золотые, лазурные, белые гиганты
|
||||
tints = [(255, 255, 255), (255, 225, 160), (180, 230, 255), (255, 190, 220)]
|
||||
tint = tints[np.random.randint(len(tints))]
|
||||
sdraw.ellipse([sx - rad, sy - rad, sx + rad, sy + rad], fill=(*tint, alpha))
|
||||
|
||||
stars = stars.filter(ImageFilter.GaussianBlur(3))
|
||||
bg = Image.alpha_composite(bg, stars)
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# 2. МЯГКИЙ ПЕРЕХОД ОТ ШЕСТЕРОК/ДЕВЯТОК: ПЛАВНОЕ ПЕРЕТЕКАНИЕ, БЕЗ РЕЗКИХ СТЫКОВ
|
||||
# ==============================================================================
|
||||
# Центральное кольцо и 3 девятки должны составлять единое бесшовное тело из жидкого света!
|
||||
trisk_glow = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
tgdraw = ImageDraw.Draw(trisk_glow)
|
||||
|
||||
trisk_body = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
tbdraw = ImageDraw.Draw(trisk_body)
|
||||
|
||||
trisk_silk = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
tsdraw = ImageDraw.Draw(trisk_silk)
|
||||
|
||||
R_RING = HI_SIZE * 0.085
|
||||
|
||||
# Отрисовываем 3 девятки как непрерывный вихрь, перетекающий из кольца наружу
|
||||
for k in range(3):
|
||||
base_rot = -math.pi / 2.0 + k * (2.0 * math.pi / 3.0)
|
||||
|
||||
# Траектория от внутренней дуги кольца, плавно перетекающая в хвост
|
||||
# Мы начинаем еще внутри дуги кольца, чтобы стык был абсолютно монолитным
|
||||
curve_pts = []
|
||||
widths = []
|
||||
|
||||
# 1. Дуга кольца, плавно разворачивающаяся в хвост (монолитный переход)
|
||||
total_steps = 90
|
||||
for s in range(total_steps):
|
||||
t = s / float(total_steps - 1)
|
||||
# Угол плавно раскручивается
|
||||
ang = base_rot - 0.4 + t * 2.1
|
||||
# Радиус плавно нарастает от R_RING до внешней зоны
|
||||
# Используем гладкую функцию smoothstep для абсолютной мягкости перехода
|
||||
smooth_t = t * t * (3 - 2 * t)
|
||||
rad = R_RING * (1.0 - 0.15 * (1 - smooth_t)) + smooth_t * (HI_SIZE * 0.185)
|
||||
|
||||
px = CENTER + rad * math.cos(ang)
|
||||
py = CENTER + rad * math.sin(ang)
|
||||
curve_pts.append((px, py))
|
||||
|
||||
# Толщина: широкая на кольце (38px), плавно сужается, но кончик МЯГКИЙ скругленный (12px), НЕ острая игла!
|
||||
w = 40.0 * (1.0 - smooth_t * 0.62)
|
||||
widths.append(w)
|
||||
|
||||
# 2. Мягкая завитушка на конце хвоста (скругляется внутрь, как морская раковина или бутон)
|
||||
tail_tip = curve_pts[-1]
|
||||
tip_ang = base_rot - 0.4 + 2.1
|
||||
flourish_steps = 45
|
||||
for f in range(flourish_steps):
|
||||
ft = f / float(flourish_steps - 1)
|
||||
# Завиток мягкий, не игольчатый
|
||||
f_r = 75.0 * (1.0 - ft * 0.75)
|
||||
f_a = tip_ang + ft * math.pi * 1.75
|
||||
fx = tail_tip[0] + f_r * math.cos(f_a) - 75.0 * math.cos(tip_ang)
|
||||
fy = tail_tip[1] + f_r * math.sin(f_a) - 75.0 * math.sin(tip_ang)
|
||||
curve_pts.append((fx, fy))
|
||||
# Скругленный кончик
|
||||
widths.append(max(8.0, 14.0 * (1.0 - ft * 0.5)))
|
||||
|
||||
# Строим ленту переменной толщины
|
||||
left_edge = []
|
||||
right_edge = []
|
||||
for i in range(len(curve_pts)):
|
||||
p = curve_pts[i]
|
||||
w = widths[i] / 2.0
|
||||
if i == 0:
|
||||
dx = curve_pts[1][0] - p[0]
|
||||
dy = curve_pts[1][1] - p[1]
|
||||
elif i == len(curve_pts) - 1:
|
||||
dx = p[0] - curve_pts[i-1][0]
|
||||
dy = p[1] - curve_pts[i-1][1]
|
||||
else:
|
||||
dx = curve_pts[i+1][0] - curve_pts[i-1][0]
|
||||
dy = curve_pts[i+1][1] - curve_pts[i-1][1]
|
||||
length = math.hypot(dx, dy) + 1e-6
|
||||
nx = -dy / length
|
||||
ny = dx / length
|
||||
left_edge.append((p[0] + nx * w, p[1] + ny * w))
|
||||
right_edge.append((p[0] - nx * w, p[1] - ny * w))
|
||||
|
||||
# Скругленная верхушка завитушки
|
||||
ribbon = left_edge + right_edge[::-1]
|
||||
|
||||
# Наслаиваем свечение ленты
|
||||
tgdraw.polygon(ribbon, fill=(255, 170, 30, 210))
|
||||
tbdraw.polygon(ribbon, fill=(255, 235, 120, 250))
|
||||
|
||||
# Шелковистый центральный световод
|
||||
for p in range(len(curve_pts) - 1):
|
||||
tsdraw.line([curve_pts[p], curve_pts[p+1]], fill=(255, 255, 255, 255), width=8)
|
||||
|
||||
# Центральное кольцо сливается с основаниями девяток в один монолит
|
||||
tgdraw.ellipse([CENTER - R_RING, CENTER - R_RING, CENTER + R_RING, CENTER + R_RING], outline=(255, 175, 30, 230), width=48)
|
||||
tbdraw.ellipse([CENTER - R_RING, CENTER - R_RING, CENTER + R_RING, CENTER + R_RING], outline=(255, 238, 125, 255), width=26)
|
||||
tsdraw.ellipse([CENTER - R_RING, CENTER - R_RING, CENTER + R_RING, CENTER + R_RING], outline=(255, 255, 255, 255), width=8)
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# 3. РОВНО 13 ЛУЧЕЙ: МЯГКИЕ СКРУГЛЕННЫЕ ВОЛНЫ СВЕТА ВМЕСТО ОСТРЫХ ИГЛ И ЧЕРТЕЖА
|
||||
# ==============================================================================
|
||||
# Пользователь отметил: "бесит что острые линии и резко".
|
||||
# Делаем 13 лучей не колючими стрелами, а мягкими светящимися языками небесного пламени / северного сияния,
|
||||
# со скругленными вершинами и плавными синусоидальными переходами!
|
||||
|
||||
waves_glow = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
wgdraw = ImageDraw.Draw(waves_glow)
|
||||
|
||||
waves_body = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
wbdraw = ImageDraw.Draw(waves_body)
|
||||
|
||||
N_POINTS = 13
|
||||
R_MAX = HI_SIZE * 0.430 # Внешний радиус гребня волны
|
||||
R_MIN = HI_SIZE * 0.270 # Впадина волны (плавный переход от центра)
|
||||
R_INNER_ZONE = HI_SIZE * 0.170
|
||||
|
||||
# 13-лучевой непрерывный органический лотос / плазменная корона
|
||||
# Мы строим непрерывную замкнутую плавную кривую с 13 гармониками (суперэллипс / гладкая полярная волна)
|
||||
corona_pts = []
|
||||
for deg in range(360 * 4):
|
||||
theta = math.radians(deg / 4.0) - math.pi / 2.0
|
||||
|
||||
# 13 гармонических волн с мягким закруглением (через cos(13 * theta) с округлением вершины)
|
||||
harm = math.cos(13.0 * (theta + math.pi / 2.0))
|
||||
# Смягчаем пики, чтобы они были куполообразными, а не острыми иглами!
|
||||
soft_harm = math.copysign(abs(harm) ** 0.75, harm)
|
||||
|
||||
r_wave = R_MIN + (R_MAX - R_MIN) * 0.5 * (1.0 + soft_harm)
|
||||
|
||||
cx = CENTER + r_wave * math.cos(theta)
|
||||
cy = CENTER + r_wave * math.sin(theta)
|
||||
corona_pts.append((cx, cy))
|
||||
|
||||
# Заполняем тело короны мягким градиентным светом
|
||||
wgdraw.polygon(corona_pts, fill=(255, 180, 40, 50))
|
||||
wbdraw.polygon(corona_pts, fill=(255, 220, 85, 80))
|
||||
|
||||
# Внешняя мягкая светящаяся кайма 13-лучевой короны
|
||||
for p in range(len(corona_pts)):
|
||||
p1 = corona_pts[p]
|
||||
p2 = corona_pts[(p + 1) % len(corona_pts)]
|
||||
wgdraw.line([p1, p2], fill=(255, 185, 45, 180), width=24)
|
||||
wbdraw.line([p1, p2], fill=(255, 240, 140, 230), width=10)
|
||||
tsdraw.line([p1, p2], fill=(255, 255, 255, 255), width=4)
|
||||
|
||||
# 13 мягких световых лучей-хребтов от центра к куполам (без резких стыков!)
|
||||
angles = [(-math.pi / 2.0) + (2.0 * math.pi * i / N_POINTS) for i in range(N_POINTS)]
|
||||
for i in range(N_POINTS):
|
||||
a = angles[i]
|
||||
p_tip = (CENTER + R_MAX * math.cos(a), CENTER + R_MAX * math.sin(a))
|
||||
p_start = (CENTER + R_INNER_ZONE * math.cos(a), CENTER + R_INNER_ZONE * math.sin(a))
|
||||
|
||||
# Широкий мягкий луч пламени
|
||||
wgdraw.line([p_start, p_tip], fill=(255, 180, 40, 160), width=42)
|
||||
wbdraw.line([p_start, p_tip], fill=(255, 230, 110, 220), width=16)
|
||||
tsdraw.line([p_start, p_tip], fill=(255, 255, 255, 255), width=6)
|
||||
|
||||
# Плавные переливающиеся дуги между лучами (бирюзово-золотое сопряжение)
|
||||
arc_layer = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
ardraw = ImageDraw.Draw(arc_layer)
|
||||
for i in range(N_POINTS):
|
||||
p1 = (CENTER + R_MAX * math.cos(angles[i]), CENTER + R_MAX * math.sin(angles[i]))
|
||||
p2 = (CENTER + R_MAX * math.cos(angles[(i + 4) % N_POINTS]), CENTER + R_MAX * math.sin(angles[(i + 4) % N_POINTS]))
|
||||
|
||||
mid_a = (angles[i] + angles[(i + 4) % N_POINTS]) / 2.0
|
||||
if abs(angles[(i + 4) % N_POINTS] - angles[i]) > math.pi:
|
||||
mid_a += math.pi
|
||||
ctrl = (CENTER + R_MIN * 1.1 * math.cos(mid_a), CENTER + R_MIN * 1.1 * math.sin(mid_a))
|
||||
|
||||
arc_curve = []
|
||||
for st in range(35):
|
||||
t = st / 34.0
|
||||
ax = (1-t)**2 * p1[0] + 2*(1-t)*t * ctrl[0] + t**2 * p2[0]
|
||||
ay = (1-t)**2 * p1[1] + 2*(1-t)*t * ctrl[1] + t**2 * p2[1]
|
||||
arc_curve.append((ax, ay))
|
||||
for p in range(len(arc_curve) - 1):
|
||||
ardraw.line([arc_curve[p], arc_curve[p+1]], fill=(120, 225, 255, 130), width=12)
|
||||
tsdraw.line([arc_curve[p], arc_curve[p+1]], fill=(255, 255, 255, 180), width=3)
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# 4. ЦЕНТРАЛЬНОЕ ФОТОННОЕ ЯДРО (БЕЗ РЕЗКОСТИ, МЯГКАЯ СВЕТОВАЯ СФЕРА)
|
||||
# ==============================================================================
|
||||
core = Image.new('RGBA', (HI_SIZE, HI_SIZE), (0, 0, 0, 0))
|
||||
cdraw = ImageDraw.Draw(core)
|
||||
|
||||
# Мягкое сферическое ядро с экспоненциальным спадом
|
||||
for r_c in range(160, 0, -4):
|
||||
alpha = int(255 * (1.0 - (r_c / 160.0)**1.2))
|
||||
cdraw.ellipse([CENTER - r_c, CENTER - r_c, CENTER + r_c, CENTER + r_c], fill=(255, 252, 235, alpha))
|
||||
|
||||
# Кинематографическая горизонтальная вспышка
|
||||
for dx in range(-700, 700, 2):
|
||||
fade = 1.0 - (abs(dx) / 700.0)**2
|
||||
alpha = int(175 * fade)
|
||||
h_w = int(14 * (1.0 - abs(dx) / 700.0) + 2)
|
||||
cdraw.ellipse([CENTER + dx - 2, CENTER - h_w, CENTER + dx + 2, CENTER + h_w], fill=(185, 240, 255, alpha))
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# 5. СБОРКА, МНОГОСЛОЙНЫЙ ГАУССОВ БЛУМ И LANCZOS СУПЕРСЕМПЛИНГ
|
||||
# ==============================================================================
|
||||
comp = Image.alpha_composite(bg, waves_glow.filter(ImageFilter.GaussianBlur(55)))
|
||||
comp = Image.alpha_composite(comp, trisk_glow.filter(ImageFilter.GaussianBlur(40)))
|
||||
comp = Image.alpha_composite(comp, arc_layer.filter(ImageFilter.GaussianBlur(16)))
|
||||
comp = Image.alpha_composite(comp, waves_body)
|
||||
comp = Image.alpha_composite(comp, trisk_body)
|
||||
comp = Image.alpha_composite(comp, tsdraw._image if hasattr(tsdraw, '_image') else trisk_silk)
|
||||
comp = Image.alpha_composite(comp, core)
|
||||
|
||||
# Глобальный кинематографический блум
|
||||
bloom = comp.filter(ImageFilter.GaussianBlur(32))
|
||||
comp = Image.blend(comp, bloom, 0.22)
|
||||
|
||||
# 16-кратный антиалиасинг (4096 -> 1024 через Lanczos)
|
||||
final_1024 = comp.resize((OUT_SIZE, OUT_SIZE), Image.Resampling.LANCZOS)
|
||||
|
||||
out_file = '/home/alexives/.gemini/antigravity-ide/brain/4ff924d9-3d7f-4202-9066-3ac5c3088b8e/star_13_living_galaxy_flow.png'
|
||||
final_1024.save(out_file, 'PNG')
|
||||
print("Successfully generated living galaxy flow at:", out_file)
|
||||
Reference in New Issue
Block a user