afegit titol al TITOL
This commit is contained in:
@@ -44,8 +44,9 @@ def apply_transform(punto, matrix):
|
||||
|
||||
def parse_svg_path(d_attr):
|
||||
"""
|
||||
Convierte comandos SVG path (M y L) a lista de puntos [(x, y), ...]
|
||||
Ejemplo: "M896,1693L896,1531.23L1219.53,1531.23..." → [(896, 1693), (896, 1531.23), ...]
|
||||
Convierte comandos SVG path (M y L) a lista de polylines separadas.
|
||||
Cada comando M inicia una nueva polyline.
|
||||
Retorna: lista de listas de puntos [[(x,y), ...], [(x,y), ...], ...]
|
||||
"""
|
||||
# Reemplazar comas por espacios para facilitar parsing
|
||||
d_attr = d_attr.replace(',', ' ')
|
||||
@@ -55,7 +56,9 @@ def parse_svg_path(d_attr):
|
||||
d_attr = re.sub(r'([ML])', r'|\1', d_attr)
|
||||
commands = [c.strip() for c in d_attr.split('|') if c.strip()]
|
||||
|
||||
points = []
|
||||
polylines = [] # Lista de polylines
|
||||
current_polyline = [] # Polyline actual
|
||||
|
||||
for cmd in commands:
|
||||
if not cmd:
|
||||
continue
|
||||
@@ -70,18 +73,29 @@ def parse_svg_path(d_attr):
|
||||
# Parsear pares de coordenadas
|
||||
coords = coords_str.split()
|
||||
|
||||
# Si es comando M (MoveTo), empezar nueva polyline
|
||||
if cmd_letter == 'M':
|
||||
# Guardar polyline anterior si tiene puntos
|
||||
if current_polyline:
|
||||
polylines.append(current_polyline)
|
||||
current_polyline = []
|
||||
|
||||
# Procesar en pares (x, y)
|
||||
i = 0
|
||||
while i < len(coords) - 1:
|
||||
try:
|
||||
x = float(coords[i])
|
||||
y = float(coords[i + 1])
|
||||
points.append((x, y))
|
||||
current_polyline.append((x, y))
|
||||
i += 2
|
||||
except (ValueError, IndexError):
|
||||
i += 1
|
||||
|
||||
return points
|
||||
# No olvidar la última polyline
|
||||
if current_polyline:
|
||||
polylines.append(current_polyline)
|
||||
|
||||
return polylines
|
||||
|
||||
|
||||
def rect_to_points(rect_elem):
|
||||
@@ -103,11 +117,22 @@ def rect_to_points(rect_elem):
|
||||
]
|
||||
|
||||
|
||||
def calc_bounding_box(puntos):
|
||||
def calc_bounding_box(polylines):
|
||||
"""
|
||||
Calcula bounding box de una lista de puntos
|
||||
Calcula bounding box de una o varias polylines
|
||||
polylines puede ser:
|
||||
- lista de puntos [(x,y), ...]
|
||||
- lista de polylines [[(x,y), ...], [(x,y), ...]]
|
||||
Retorna: (min_x, max_x, min_y, max_y, ancho, alto)
|
||||
"""
|
||||
# Aplanar si es lista de polylines
|
||||
puntos = []
|
||||
if polylines and isinstance(polylines[0], list):
|
||||
for polyline in polylines:
|
||||
puntos.extend(polyline)
|
||||
else:
|
||||
puntos = polylines
|
||||
|
||||
if not puntos:
|
||||
return (0, 0, 0, 0, 0, 0)
|
||||
|
||||
@@ -125,17 +150,18 @@ def calc_bounding_box(puntos):
|
||||
return (min_x, max_x, min_y, max_y, ancho, alto)
|
||||
|
||||
|
||||
def normalizar_letra(nombre, puntos, altura_objetivo=100.0):
|
||||
def normalizar_letra(nombre, polylines, altura_objetivo=100.0):
|
||||
"""
|
||||
Escala y traslada letra para que tenga altura_objetivo pixels
|
||||
y esté centrada en origen (0, 0) en esquina superior izquierda
|
||||
|
||||
Retorna: dict con puntos normalizados, centro, ancho, alto
|
||||
polylines: lista de polylines [[(x,y), ...], [(x,y), ...]]
|
||||
Retorna: dict con polylines normalizadas, centro, ancho, alto
|
||||
"""
|
||||
if not puntos:
|
||||
if not polylines:
|
||||
return None
|
||||
|
||||
min_x, max_x, min_y, max_y, ancho, alto = calc_bounding_box(puntos)
|
||||
min_x, max_x, min_y, max_y, ancho, alto = calc_bounding_box(polylines)
|
||||
|
||||
if alto == 0:
|
||||
print(f" [WARN] Letra {nombre}: altura cero")
|
||||
@@ -144,14 +170,26 @@ def normalizar_letra(nombre, puntos, altura_objetivo=100.0):
|
||||
# Factor de escala basado en altura
|
||||
escala = altura_objetivo / alto
|
||||
|
||||
# Normalizar puntos:
|
||||
# Normalizar cada polyline:
|
||||
# 1. Trasladar a origen (restar min_x, min_y)
|
||||
# 2. Aplicar escala
|
||||
puntos_norm = []
|
||||
for x, y in puntos:
|
||||
x_norm = (x - min_x) * escala
|
||||
y_norm = (y - min_y) * escala
|
||||
puntos_norm.append((x_norm, y_norm))
|
||||
# 3. Cerrar polyline (último punto = primer punto)
|
||||
polylines_norm = []
|
||||
total_puntos = 0
|
||||
|
||||
for polyline in polylines:
|
||||
polyline_norm = []
|
||||
for x, y in polyline:
|
||||
x_norm = (x - min_x) * escala
|
||||
y_norm = (y - min_y) * escala
|
||||
polyline_norm.append((x_norm, y_norm))
|
||||
|
||||
# Cerrar polyline si no está cerrada
|
||||
if polyline_norm and polyline_norm[0] != polyline_norm[-1]:
|
||||
polyline_norm.append(polyline_norm[0])
|
||||
|
||||
polylines_norm.append(polyline_norm)
|
||||
total_puntos += len(polyline_norm)
|
||||
|
||||
# Calcular dimensiones finales
|
||||
ancho_norm = ancho * escala
|
||||
@@ -162,10 +200,11 @@ def normalizar_letra(nombre, puntos, altura_objetivo=100.0):
|
||||
|
||||
return {
|
||||
'nombre': nombre,
|
||||
'puntos': puntos_norm,
|
||||
'polylines': polylines_norm,
|
||||
'centro': centro,
|
||||
'ancho': ancho_norm,
|
||||
'alto': alto_norm
|
||||
'alto': alto_norm,
|
||||
'total_puntos': total_puntos
|
||||
}
|
||||
|
||||
|
||||
@@ -178,6 +217,7 @@ def generar_shp(letra_norm, output_dir):
|
||||
scale: 1.0
|
||||
center: cx, cy
|
||||
polyline: x1,y1 x2,y2 x3,y3 ...
|
||||
polyline: x1,y1 x2,y2 x3,y3 ... (si hay múltiples formas)
|
||||
"""
|
||||
if not letra_norm:
|
||||
return
|
||||
@@ -198,13 +238,13 @@ def generar_shp(letra_norm, output_dir):
|
||||
f.write(f"center: {letra_norm['centro'][0]:.2f}, {letra_norm['centro'][1]:.2f}\n")
|
||||
f.write(f"\n")
|
||||
|
||||
# Polyline con todos los puntos
|
||||
f.write("polyline: ")
|
||||
puntos_str = " ".join([f"{x:.2f},{y:.2f}" for x, y in letra_norm['puntos']])
|
||||
f.write(puntos_str)
|
||||
f.write("\n")
|
||||
# Generar una línea polyline por cada forma
|
||||
for polyline in letra_norm['polylines']:
|
||||
puntos_str = " ".join([f"{x:.2f},{y:.2f}" for x, y in polyline])
|
||||
f.write(f"polyline: {puntos_str}\n")
|
||||
|
||||
print(f" ✓ {nombre_archivo:20} ({len(letra_norm['puntos']):3} puntos, "
|
||||
print(f" ✓ {nombre_archivo:20} ({len(letra_norm['polylines'])} formas, "
|
||||
f"{letra_norm['total_puntos']:3} puntos, "
|
||||
f"{letra_norm['ancho']:6.2f} x {letra_norm['alto']:6.2f} px)")
|
||||
|
||||
|
||||
@@ -232,14 +272,18 @@ def parse_svg(filepath):
|
||||
|
||||
print(f"[INFO] Transform matrix: {transform_matrix}")
|
||||
|
||||
# Extraer paths y rects
|
||||
paths = group.findall('svg:path', ns)
|
||||
rects = group.findall('svg:rect', ns)
|
||||
# Extraer paths y rects (buscar recursivamente en todos los descendientes)
|
||||
paths = group.findall('.//svg:path', ns)
|
||||
rects = group.findall('.//svg:rect', ns)
|
||||
|
||||
print(f"[INFO] Encontrados {len(paths)} paths y {len(rects)} rects")
|
||||
|
||||
# Nombres de las letras para paths (sin I que es un rect)
|
||||
nombres_paths = ['J', 'A', 'L', 'G', 'A', 'M', 'E', 'S']
|
||||
# Nombres de las letras para "ORNI ATTACK!"
|
||||
# Grupo 1 (top): O, R, N, I (3 paths + 1 rect)
|
||||
# Grupo 2 (bottom): A, T, T, A, C, K, ! (6 paths + 1 path para !)
|
||||
# Total: 9 paths + 1 rect
|
||||
# Asumiendo orden de aparición en SVG:
|
||||
nombres_paths = ['O', 'R', 'N', 'A', 'T', 'T', 'A', 'C', 'K', 'EXCLAMACION']
|
||||
|
||||
letras = []
|
||||
|
||||
@@ -252,15 +296,18 @@ def parse_svg(filepath):
|
||||
if not d_attr:
|
||||
continue
|
||||
|
||||
# Parsear puntos del path
|
||||
puntos = parse_svg_path(d_attr)
|
||||
# Parsear polylines del path (ahora retorna lista de polylines)
|
||||
polylines = parse_svg_path(d_attr)
|
||||
|
||||
# Aplicar transformación
|
||||
puntos = [apply_transform(p, transform_matrix) for p in puntos]
|
||||
# Aplicar transformación a cada polyline
|
||||
polylines_transformed = []
|
||||
for polyline in polylines:
|
||||
polyline_transformed = [apply_transform(p, transform_matrix) for p in polyline]
|
||||
polylines_transformed.append(polyline_transformed)
|
||||
|
||||
letras.append({
|
||||
'nombre': nombres_paths[i],
|
||||
'puntos': puntos
|
||||
'polylines': polylines_transformed
|
||||
})
|
||||
|
||||
# Procesar rects (la letra I es un rect)
|
||||
@@ -268,11 +315,12 @@ def parse_svg(filepath):
|
||||
puntos = rect_to_points(rect)
|
||||
|
||||
# Aplicar transformación
|
||||
puntos = [apply_transform(p, transform_matrix) for p in puntos]
|
||||
puntos_transformed = [apply_transform(p, transform_matrix) for p in puntos]
|
||||
|
||||
# Rect es una sola polyline
|
||||
letras.append({
|
||||
'nombre': 'I',
|
||||
'puntos': puntos
|
||||
'polylines': [puntos_transformed]
|
||||
})
|
||||
|
||||
return letras
|
||||
@@ -326,7 +374,7 @@ def main():
|
||||
|
||||
for nombre in sorted(letras_unicas.keys()):
|
||||
letra = letras_unicas[nombre]
|
||||
letra_norm = normalizar_letra(nombre, letra['puntos'], altura_objetivo=100.0)
|
||||
letra_norm = normalizar_letra(nombre, letra['polylines'], altura_objetivo=100.0)
|
||||
|
||||
if letra_norm:
|
||||
generar_shp(letra_norm, output_dir)
|
||||
|
||||
Reference in New Issue
Block a user