Pages

Wednesday, November 20, 2024

Fedora 41 : generated shapes with python !

Today I created this source code in python that generates eight random convex polygons. The idea was to create sprites for a 2D game: snowballs, boulders, or similar objects ... Obviously I also used Sonet 3.5 artificial intelligence. You can find the source code on the pagure account in fedora.
#!/usr/bin/env python3
"""
SVG Polygon Generator

This script generates multiple deformed polygonal shapes and saves them as separate SVG files.
Each polygon maintains convex properties while having controlled random deformations.

Features:
    - Generates 8 unique polygonal shapes
    - Controls deformation through radial and angular factors
    - Maintains convex properties
    - Exports each shape to a separate SVG file
    - Uses random colors for visual distinction

Usage:
    python generate_svgs.py

Output:
    Creates 8 SVG files named 'polygon_1.svg' through 'polygon_8.svg'
"""

from lxml import etree
import random
import math
from pathlib import Path


def create_svg_root():
    """Create and return a base SVG root element with standard attributes."""
    root = etree.Element("svg")
    root.set("width", "500")
    root.set("height", "500")
    root.set("xmlns", "http://www.w3.org/2000/svg")
    return root


def calculate_points(center_x: float, center_y: float, radius: float, 
                    num_sides: int, deform_factor: float) -> list:
    """
    Calculate polygon points with controlled deformation.

    Args:
        center_x: X coordinate of polygon center
        center_y: Y coordinate of polygon center
        radius: Base radius of the polygon
        num_sides: Number of polygon sides
        deform_factor: Maximum allowed deformation factor

    Returns:
        List of tuples containing (x, y) coordinates
    """
    points = []
    angle_step = 2 * math.pi / num_sides
    
    for i in range(num_sides):
        angle = i * angle_step
        radial_deform = random.uniform(-deform_factor, deform_factor)
        angular_deform = random.uniform(-deform_factor/2, deform_factor/2)
        
        modified_angle = angle + angular_deform
        modified_radius = radius * (1 + radial_deform)
        
        x = center_x + modified_radius * math.cos(modified_angle)
        y = center_y + modified_radius * math.sin(modified_angle)
        points.append((x, y))
    
    return points


def generate_deformed_shapes():
    """Generate multiple deformed polygons and save them to separate SVG files."""
    # Base parameters
    num_sides = 8
    center_x = 250
    center_y = 250
    base_radius = 150
    max_deformation = 0.15
    output_dir = Path("generated_polygons")
    
    # Create output directory if it doesn't exist
    output_dir.mkdir(exist_ok=True)

    for i in range(8):
        root = create_svg_root()
        points = calculate_points(center_x, center_y, base_radius, 
                                num_sides, max_deformation)
        
        path = etree.SubElement(root, "path")
        path_data = f"M {points[0][0]} {points[0][1]}"
        path_data += "".join(f" L {p[0]} {p[1]}" for p in points[1:])
        path_data += " Z"
        
        path.set("d", path_data)
        path.set("fill", "none")
        path.set("stroke", f"#{random.randint(0, 16777215):06X}")
        path.set("stroke-width", "2")
        path.set("opacity", "0.7")

        # Save individual SVG file
        output_file = output_dir / f"polygon_{i+1}.svg"
        tree = etree.ElementTree(root)
        tree.write(str(output_file), pretty_print=True, 
                  xml_declaration=True, encoding='utf-8')
    
    print(f"Generated {num_sides} polygons in {output_dir}")

if __name__ == "__main__":
    generate_deformed_shapes()