Files
SSG-Ruledesigner-Konfigurator/SVGs/Omniflo/lib/3_svg_scaler-Step3.py
T

160 lines
5.7 KiB
Python

import re
import os
import xml.etree.ElementTree as ET
from typing import List, Dict, Tuple
def process_svg_file(input_path: str, output_path: str) -> bool:
"""Process SVG file while preserving original dimensions and viewBox"""
try:
# Parse SVG file
tree = ET.parse(input_path)
root = tree.getroot()
# Store original dimensions and viewBox
original_attrs = {
'width': root.attrib.get('width', '100%'),
'height': root.attrib.get('height', '100%'),
'viewBox': root.attrib.get('viewBox', '')
}
# Remove namespace prefixes
for elem in root.iter():
if '}' in elem.tag:
elem.tag = elem.tag.split('}', 1)[1]
for attr in list(elem.attrib):
if '}' in attr:
new_attr = attr.split('}', 1)[1]
elem.attrib[new_attr] = elem.attrib[attr]
del elem.attrib[attr]
# Process all groups with transforms
for g in root.findall('g'):
if 'transform' in g.attrib:
# Parse transform and convert to matrix
transform = g.attrib['transform']
matrix_str = convert_transform_to_matrix(transform)
# Update group attributes
g.attrib['transform'] = matrix_str
g.attrib['stroke'] = '#ffe31b' # Force stroke color
g.attrib['fill'] = 'none'
g.attrib['stroke-linecap'] = 'square'
g.attrib['vector-effect'] = 'non-scaling-stroke'
# Format paths within group
for path in g.findall('path'):
path.attrib['d'] = simplify_path_data(path.attrib.get('d', ''))
path.tail = '\n ' # Maintain consistent indentation
# Set root attributes while preserving original dimensions
root.attrib.update({
'version': '1.1',
'xmlns': 'http://www.w3.org/2000/svg',
'width': original_attrs['width'],
'height': original_attrs['height'],
'viewBox': original_attrs['viewBox'],
'fill-rule': 'evenodd',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'space': 'preserve'
})
# Format XML with proper indentation
indent(root)
# Generate XML string
xml_str = ET.tostring(root, encoding='unicode')
xml_str = '<?xml version="1.0" encoding="UTF-8"?>\n' + xml_str
# Clean up formatting
xml_str = re.sub(r'\n\s*\n', '\n', xml_str)
xml_str = re.sub(r'>\s+<', '>\n<', xml_str)
# Write to file
with open(output_path, 'w', encoding='utf-8') as f:
f.write(xml_str)
print(f"Processed: {os.path.basename(input_path)}")
return True
except Exception as e:
print(f"Failed {os.path.basename(input_path)}: {str(e)}")
return False
def convert_transform_to_matrix(transform: str) -> str:
"""Convert transform string to matrix notation with 4 decimal places"""
tx = ty = 0.0
translate_match = re.search(r'translate\(([^,]+),\s*([^)]+)\)', transform)
if translate_match:
tx = float(translate_match.group(1))
ty = float(translate_match.group(2))
scale = 1.0
scale_match = re.search(r'scale\(([^)]+)\)', transform)
if scale_match:
scale = float(scale_match.group(1))
return f"matrix({scale:.4f} 0 0 {scale:.4f} {tx:.2f} {ty:.2f})"
def simplify_path_data(d: str) -> str:
"""Simplify path data while maintaining relative commands"""
d = re.sub(r'\s+', ' ', d.strip())
def format_number(num_str: str) -> str:
try:
num = float(num_str)
if abs(num) < 0.001 and num != 0:
return f"{num:.0e}".replace('e-0', 'e-')
if abs(num - 1000) < 0.1:
return '1e3'
if abs(num - round(num, 3)) < 0.0001:
return f"{round(num, 3):g}"
return num_str
except ValueError:
return num_str
parts = []
for part in re.split(r'([ ,])', d):
if re.match(r'^[-+]?\d*\.?\d+$', part):
parts.append(format_number(part))
else:
parts.append(part)
return ''.join(parts).replace(' ,', ',')
def indent(elem: ET.Element, level: int = 0):
"""Properly indent XML elements"""
indent_str = "\n" + level * " "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = indent_str + " "
if not elem.tail or not elem.tail.strip():
elem.tail = indent_str
for child in elem:
indent(child, level + 1)
if not elem.tail or not elem.tail.strip():
elem.tail = indent_str
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = indent_str
def batch_process_svgs(input_dir: str, output_dir: str):
"""Process all SVG files in a directory"""
if not os.path.exists(output_dir):
os.makedirs(output_dir)
success_count = 0
for filename in sorted(os.listdir(input_dir)):
if filename.lower().endswith('.svg'):
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(output_dir, filename)
if process_svg_file(input_path, output_path):
success_count += 1
print(f"\nCompleted: {success_count} files processed")
if __name__ == '__main__':
input_dir = r'C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\Weichen'
output_dir = r'C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\Weichen\outputdir'
# Example usage:
batch_process_svgs(input_dir, output_dir)