369 lines
13 KiB
Python
369 lines
13 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
AeThex Precision Logo Generator
|
|
Uses exact mathematical calculations for perfect alignment
|
|
"""
|
|
|
|
import math
|
|
from pathlib import Path
|
|
|
|
COLORS = {
|
|
'purple_light': '#A855F7',
|
|
'purple': '#8B5CF6',
|
|
'purple_dark': '#7C3AED',
|
|
'cyan': '#06B6D4',
|
|
'cyan_light': '#22D3EE',
|
|
'white': '#FFFFFF',
|
|
}
|
|
|
|
class PrecisionSVG:
|
|
"""Helper for pixel-perfect SVG generation"""
|
|
|
|
def __init__(self, width=200, height=200):
|
|
self.width = width
|
|
self.height = height
|
|
self.center_x = width / 2
|
|
self.center_y = height / 2
|
|
self.elements = []
|
|
|
|
def add_gradient(self, id, color1, color2, angle=135):
|
|
"""Add linear gradient"""
|
|
rad = math.radians(angle)
|
|
x2 = math.cos(rad) * 100
|
|
y2 = math.sin(rad) * 100
|
|
|
|
return f''' <linearGradient id="{id}" x1="0%" y1="0%" x2="{x2:.1f}%" y2="{y2:.1f}%">
|
|
<stop offset="0%" style="stop-color:{color1}"/>
|
|
<stop offset="100%" style="stop-color:{color2}"/>
|
|
</linearGradient>'''
|
|
|
|
def circle(self, cx, cy, r, fill, **attrs):
|
|
"""Add centered circle"""
|
|
attr_str = ' '.join(f'{k}="{v}"' for k, v in attrs.items())
|
|
self.elements.append(f' <circle cx="{cx:.2f}" cy="{cy:.2f}" r="{r:.2f}" fill="{fill}" {attr_str}/>')
|
|
|
|
def line(self, x1, y1, x2, y2, stroke, width=2, **attrs):
|
|
"""Add line"""
|
|
attr_str = ' '.join(f'{k}="{v}"' for k, v in attrs.items())
|
|
self.elements.append(f' <line x1="{x1:.2f}" y1="{y1:.2f}" x2="{x2:.2f}" y2="{y2:.2f}" stroke="{stroke}" stroke-width="{width}" {attr_str}/>')
|
|
|
|
def path(self, d, fill='none', stroke='none', width=2, **attrs):
|
|
"""Add path"""
|
|
attr_str = ' '.join(f'{k}="{v}"' for k, v in attrs.items())
|
|
attrs_final = f'stroke-width="{width}" {attr_str}' if stroke != 'none' else attr_str
|
|
self.elements.append(f' <path d="{d}" fill="{fill}" stroke="{stroke}" {attrs_final}/>')
|
|
|
|
def polygon(self, points, fill='none', stroke='none', width=2, **attrs):
|
|
"""Add polygon from list of (x,y) tuples"""
|
|
points_str = ' '.join(f'{x:.2f},{y:.2f}' for x, y in points)
|
|
attr_str = ' '.join(f'{k}="{v}"' for k, v in attrs.items())
|
|
attrs_final = f'stroke-width="{width}" {attr_str}' if stroke != 'none' else attr_str
|
|
self.elements.append(f' <polygon points="{points_str}" fill="{fill}" stroke="{stroke}" {attrs_final}/>')
|
|
|
|
def text(self, x, y, content, size=16, fill='#000', **attrs):
|
|
"""Add text"""
|
|
attr_str = ' '.join(f'{k}="{v}"' for k, v in attrs.items())
|
|
self.elements.append(f' <text x="{x:.2f}" y="{y:.2f}" font-size="{size}" fill="{fill}" {attr_str}>{content}</text>')
|
|
|
|
def render(self):
|
|
"""Render complete SVG"""
|
|
header = f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {self.width} {self.height}" width="{self.width}" height="{self.height}">
|
|
<defs>
|
|
{self.add_gradient("grad1", COLORS['purple_light'], COLORS['purple_dark'])}
|
|
{self.add_gradient("grad2", COLORS['cyan'], COLORS['purple'])}
|
|
<filter id="glow">
|
|
<feGaussianBlur stdDeviation="2" result="coloredBlur"/>
|
|
<feMerge>
|
|
<feMergeNode in="coloredBlur"/>
|
|
<feMergeNode in="SourceGraphic"/>
|
|
</feMerge>
|
|
</filter>
|
|
</defs>
|
|
'''
|
|
footer = '</svg>'
|
|
return header + '\n'.join(self.elements) + '\n' + footer
|
|
|
|
|
|
def generate_perfect_letter_a():
|
|
"""Pixel-perfect letter A with connection nodes"""
|
|
svg = PrecisionSVG(200, 200)
|
|
|
|
# Center coordinates
|
|
cx, cy = svg.center_x, svg.center_y
|
|
|
|
# A dimensions (perfectly centered)
|
|
top_y = cy - 50
|
|
bottom_y = cy + 50
|
|
width = 70
|
|
bar_y = cy + 5
|
|
|
|
# Left stroke of A
|
|
left_outer = cx - width/2
|
|
left_inner = cx - 10
|
|
svg.path(
|
|
f'M {cx:.2f} {top_y:.2f} L {left_outer:.2f} {bottom_y:.2f} L {left_outer + 12:.2f} {bottom_y:.2f} L {left_inner:.2f} {bar_y - 15:.2f} Z',
|
|
fill='url(#grad1)'
|
|
)
|
|
|
|
# Right stroke of A
|
|
right_outer = cx + width/2
|
|
right_inner = cx + 10
|
|
svg.path(
|
|
f'M {cx:.2f} {top_y:.2f} L {right_outer:.2f} {bottom_y:.2f} L {right_outer - 12:.2f} {bottom_y:.2f} L {right_inner:.2f} {bar_y - 15:.2f} Z',
|
|
fill='url(#grad1)'
|
|
)
|
|
|
|
# Crossbar (split in middle for cloud/network effect)
|
|
bar_width = 16
|
|
bar_height = 4
|
|
gap = 8
|
|
|
|
# Left bar
|
|
svg.path(
|
|
f'M {cx - bar_width - gap:.2f} {bar_y - bar_height/2:.2f} L {cx - gap:.2f} {bar_y - bar_height/2:.2f} L {cx - gap:.2f} {bar_y + bar_height/2:.2f} L {cx - bar_width - gap:.2f} {bar_y + bar_height/2:.2f} Z',
|
|
fill=COLORS['cyan']
|
|
)
|
|
|
|
# Right bar
|
|
svg.path(
|
|
f'M {cx + gap:.2f} {bar_y - bar_height/2:.2f} L {cx + bar_width + gap:.2f} {bar_y - bar_height/2:.2f} L {cx + bar_width + gap:.2f} {bar_y + bar_height/2:.2f} L {cx + gap:.2f} {bar_y + bar_height/2:.2f} Z',
|
|
fill=COLORS['cyan']
|
|
)
|
|
|
|
# Connection nodes (perfectly centered)
|
|
node_radius = 3
|
|
svg.circle(cx - bar_width - gap, bar_y, node_radius, COLORS['cyan_light'], filter='url(#glow)')
|
|
svg.circle(cx + bar_width + gap, bar_y, node_radius, COLORS['cyan_light'], filter='url(#glow)')
|
|
svg.circle(cx, bar_y - 6, node_radius - 0.5, COLORS['cyan_light'], filter='url(#glow)', opacity='0.8')
|
|
|
|
return svg.render()
|
|
|
|
|
|
def generate_perfect_hexagon():
|
|
"""Perfect hexagon with network nodes"""
|
|
svg = PrecisionSVG(200, 200)
|
|
|
|
cx, cy = svg.center_x, svg.center_y
|
|
radius = 70
|
|
|
|
# Calculate perfect hexagon points
|
|
points = []
|
|
for i in range(6):
|
|
angle = math.pi / 3 * i - math.pi / 2
|
|
x = cx + radius * math.cos(angle)
|
|
y = cy + radius * math.sin(angle)
|
|
points.append((x, y))
|
|
|
|
svg.polygon(points, fill='none', stroke='url(#grad1)', width=3)
|
|
|
|
# Inner network (perfectly distributed)
|
|
inner_radius = 35
|
|
node_positions = []
|
|
for i in range(6):
|
|
angle = math.pi / 3 * i - math.pi / 2
|
|
x = cx + inner_radius * math.cos(angle)
|
|
y = cy + inner_radius * math.sin(angle)
|
|
node_positions.append((x, y))
|
|
|
|
# Center node
|
|
node_positions.append((cx, cy))
|
|
|
|
# Draw connections from center to edges
|
|
for i in range(6):
|
|
svg.line(cx, cy, node_positions[i][0], node_positions[i][1],
|
|
COLORS['cyan'], width=1.5, opacity='0.4')
|
|
|
|
# Draw ring connections
|
|
for i in range(6):
|
|
next_i = (i + 1) % 6
|
|
svg.line(node_positions[i][0], node_positions[i][1],
|
|
node_positions[next_i][0], node_positions[next_i][1],
|
|
COLORS['cyan'], width=1.5, opacity='0.3')
|
|
|
|
# Draw all nodes
|
|
for x, y in node_positions:
|
|
svg.circle(x, y, 3.5, COLORS['cyan_light'], filter='url(#glow)')
|
|
|
|
return svg.render()
|
|
|
|
|
|
def generate_perfect_triangle():
|
|
"""Minimalist triangle with perfect alignment"""
|
|
svg = PrecisionSVG(200, 200)
|
|
|
|
cx, cy = svg.center_x, svg.center_y
|
|
|
|
# Equilateral triangle (perfectly centered)
|
|
height = 100
|
|
width = height * math.sqrt(3)
|
|
|
|
top_x = cx
|
|
top_y = cy - height * 2/3
|
|
left_x = cx - width/2
|
|
left_y = cy + height * 1/3
|
|
right_x = cx + width/2
|
|
right_y = cy + height * 1/3
|
|
|
|
# Triangle outline
|
|
svg.path(
|
|
f'M {top_x:.2f} {top_y:.2f} L {left_x:.2f} {left_y:.2f} L {right_x:.2f} {right_y:.2f} Z',
|
|
fill='none',
|
|
stroke='url(#grad1)',
|
|
width=6,
|
|
**{'stroke-linejoin': 'round'}
|
|
)
|
|
|
|
# Crossbar (centered at 1/3 height)
|
|
bar_y = cy + height * 1/3 - height * 2/3 * 0.6
|
|
bar_width = width * 0.4
|
|
|
|
svg.line(cx - bar_width/2, bar_y, cx + bar_width/2, bar_y,
|
|
COLORS['cyan'], width=6, **{'stroke-linecap': 'round'})
|
|
|
|
# End nodes
|
|
svg.circle(cx - bar_width/2, bar_y, 5, COLORS['cyan_light'])
|
|
svg.circle(cx + bar_width/2, bar_y, 5, COLORS['cyan_light'])
|
|
svg.circle(cx, bar_y - 6, 4, COLORS['white'])
|
|
|
|
return svg.render()
|
|
|
|
|
|
def generate_perfect_circle_nodes():
|
|
"""Circular node constellation"""
|
|
svg = PrecisionSVG(200, 200)
|
|
|
|
cx, cy = svg.center_x, svg.center_y
|
|
|
|
# Main circle
|
|
main_radius = 75
|
|
svg.circle(cx, cy, main_radius, 'none', stroke='url(#grad1)', **{'stroke-width': '3', 'opacity': '0.3'})
|
|
|
|
# Orbiting nodes (perfectly spaced)
|
|
num_nodes = 8
|
|
node_radius = 6
|
|
|
|
for i in range(num_nodes):
|
|
angle = (2 * math.pi / num_nodes) * i - math.pi / 2
|
|
x = cx + main_radius * math.cos(angle)
|
|
y = cy + main_radius * math.sin(angle)
|
|
|
|
# Connection line to center
|
|
svg.line(cx, cy, x, y, COLORS['purple'], width=1.5, opacity='0.2')
|
|
|
|
# Node
|
|
color = COLORS['cyan'] if i % 2 == 0 else COLORS['purple_light']
|
|
svg.circle(x, y, node_radius, color, filter='url(#glow)')
|
|
|
|
# Center node (larger)
|
|
svg.circle(cx, cy, 10, COLORS['cyan_light'], filter='url(#glow)')
|
|
|
|
# Inner ring (smaller radius)
|
|
inner_radius = 35
|
|
for i in range(4):
|
|
angle = (2 * math.pi / 4) * i
|
|
x = cx + inner_radius * math.cos(angle)
|
|
y = cy + inner_radius * math.sin(angle)
|
|
svg.circle(x, y, 4, COLORS['white'], opacity='0.8')
|
|
|
|
return svg.render()
|
|
|
|
|
|
def generate_perfect_abstract():
|
|
"""Abstract geometric design with mathematical precision"""
|
|
svg = PrecisionSVG(200, 200)
|
|
|
|
cx, cy = svg.center_x, svg.center_y
|
|
|
|
# Overlapping circles (golden ratio)
|
|
phi = 1.618
|
|
radius1 = 50
|
|
radius2 = radius1 / phi
|
|
offset = 30
|
|
|
|
# Left circle
|
|
svg.circle(cx - offset, cy, radius1, 'none', stroke='url(#grad1)',
|
|
**{'stroke-width': '4', 'opacity': '0.6'})
|
|
|
|
# Right circle
|
|
svg.circle(cx + offset, cy, radius1, 'none', stroke='url(#grad2)',
|
|
**{'stroke-width': '4', 'opacity': '0.6'})
|
|
|
|
# Center intersection nodes
|
|
# Calculate intersection points mathematically
|
|
d = offset * 2 # distance between centers
|
|
a = (d/2 + (radius1**2 - radius1**2) / (2*d)) if d != 0 else 0
|
|
h = math.sqrt(radius1**2 - a**2) if radius1**2 >= a**2 else 0
|
|
|
|
intersection_y1 = cy - h
|
|
intersection_y2 = cy + h
|
|
|
|
svg.circle(cx, intersection_y1, 6, COLORS['cyan_light'], filter='url(#glow)')
|
|
svg.circle(cx, intersection_y2, 6, COLORS['cyan_light'], filter='url(#glow)')
|
|
|
|
# Center line
|
|
svg.line(cx, intersection_y1, cx, intersection_y2, COLORS['cyan'], width=3)
|
|
|
|
# Small accent circles
|
|
svg.circle(cx - offset, cy, 8, COLORS['purple'], opacity='0.8')
|
|
svg.circle(cx + offset, cy, 8, COLORS['cyan'], opacity='0.8')
|
|
svg.circle(cx, cy, 5, COLORS['white'])
|
|
|
|
return svg.render()
|
|
|
|
|
|
def generate_with_grid(logo_func, show_grid=True):
|
|
"""Generate logo with alignment grid overlay"""
|
|
logo_svg = logo_func()
|
|
|
|
if not show_grid:
|
|
return logo_svg
|
|
|
|
# Add grid overlay
|
|
grid_lines = []
|
|
for i in range(0, 201, 10):
|
|
# Vertical lines
|
|
opacity = '0.3' if i % 50 == 0 else '0.1'
|
|
grid_lines.append(f' <line x1="{i}" y1="0" x2="{i}" y2="200" stroke="#06B6D4" stroke-width="0.5" opacity="{opacity}"/>')
|
|
# Horizontal lines
|
|
grid_lines.append(f' <line x1="0" y1="{i}" x2="200" y2="{i}" stroke="#06B6D4" stroke-width="0.5" opacity="{opacity}"/>')
|
|
|
|
# Center crosshair
|
|
grid_lines.append(' <line x1="100" y1="0" x2="100" y2="200" stroke="#22D3EE" stroke-width="1" opacity="0.5"/>')
|
|
grid_lines.append(' <line x1="0" y1="100" x2="200" y2="100" stroke="#22D3EE" stroke-width="1" opacity="0.5"/>')
|
|
|
|
# Insert grid before closing tag
|
|
logo_with_grid = logo_svg.replace('</svg>', '\n'.join(grid_lines) + '\n</svg>')
|
|
return logo_with_grid
|
|
|
|
|
|
def main():
|
|
output_dir = Path('assets/precision-logos')
|
|
output_dir.mkdir(exist_ok=True)
|
|
|
|
logos = {
|
|
'letter-a-perfect.svg': generate_perfect_letter_a,
|
|
'hexagon-network-perfect.svg': generate_perfect_hexagon,
|
|
'triangle-perfect.svg': generate_perfect_triangle,
|
|
'circle-nodes-perfect.svg': generate_perfect_circle_nodes,
|
|
'abstract-perfect.svg': generate_perfect_abstract,
|
|
}
|
|
|
|
print("🎯 Generating precision-aligned logos...\n")
|
|
|
|
for filename, func in logos.items():
|
|
# Generate without grid
|
|
filepath = output_dir / filename
|
|
filepath.write_text(func())
|
|
print(f"✓ {filename}")
|
|
|
|
# Generate with grid for alignment check
|
|
grid_filename = filename.replace('.svg', '-grid.svg')
|
|
grid_filepath = output_dir / grid_filename
|
|
grid_filepath.write_text(generate_with_grid(func))
|
|
print(f" └─ {grid_filename} (with alignment grid)")
|
|
|
|
print(f"\n✅ Generated {len(logos)} precision logos in {output_dir}/")
|
|
print("\nEach logo has a '-grid.svg' version showing alignment guides!")
|
|
|
|
if __name__ == '__main__':
|
|
main()
|