Alle TEFWEICHEN sind eingepflegt.
This commit is contained in:
@@ -385,11 +385,11 @@ if __name__ == '__main__':
|
||||
in_dir = args.inputdir
|
||||
else:
|
||||
if args.bogen:
|
||||
in_dir = os.environ.get('RD_CONF_BOGEN')
|
||||
in_dir = os.environ.get('RD_CONF_OFBOGEN')
|
||||
elif args.tefbogen:
|
||||
in_dir = os.environ.get('RD_CONF_TEFBOGEN')
|
||||
elif args.weichen:
|
||||
in_dir = os.environ.get('RD_CONF_WEICHEN')
|
||||
in_dir = os.environ.get('RD_CONF_OFWEICHEN')
|
||||
elif args.tefweichen:
|
||||
in_dir = os.environ.get('RD_CONF_TEFWEICHEN')
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ def convert_svg_to_xml(svg_path, output_dir):
|
||||
def update_txt_file(txt_path, xml_rel_path):
|
||||
"""Update path in TXT file"""
|
||||
try:
|
||||
with open(txt_path, "r", encoding="UTF-8") as f:
|
||||
with open(txt_path, "r", encoding="UTF-8-sig") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if "srcSVG" not in data:
|
||||
|
||||
@@ -241,7 +241,7 @@ def process_json_file(input_filename, output_filename=None):
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Get JSON_PATH from environment
|
||||
json_path = os.environ.get("JSON_PATH","JSON")
|
||||
json_path = os.environ.get("JSON_PATH_TEFBOGEN","JSON")
|
||||
|
||||
# Default filenames
|
||||
input_filename = "1_TEF_Boegen_input.json"
|
||||
|
||||
@@ -145,7 +145,7 @@ def process_files(json_file_path, txt_files_dir):
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
json_path = os.environ.get("JSON_PATH", "JSON")
|
||||
json_path = os.environ.get("JSON_PATH_TEFBOGEN", "JSON")
|
||||
json_file_path = os.path.join(json_path, "1_TEF_Boegen_output.json")
|
||||
txt_files_dir = os.environ.get("PROPS_PATH", "props")
|
||||
process_files(json_file_path, txt_files_dir)
|
||||
|
||||
@@ -107,9 +107,9 @@ def main():
|
||||
Main processing function
|
||||
"""
|
||||
# Configure paths
|
||||
json_path=os.environ.get("JSON_PATH","JSON")
|
||||
json_path=os.environ.get("JSON_PATH_TEFBOGEN","JSON")
|
||||
json_file_path = os.path.join(json_path,"1_TEF_Boegen_input.json")
|
||||
svg_folder_path = os.environ.get("XML_PATH","svg")
|
||||
svg_folder_path = os.environ.get("SVG_PATH","svg")
|
||||
|
||||
|
||||
try:
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
set TEFBogen_PATH=%~dp0
|
||||
|
||||
set XML_PATH=C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\svg
|
||||
set SVG_PATH=C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\svg
|
||||
|
||||
set JSON_PATH=%TEFBogen_PATH%JSON
|
||||
set JSON_PATH_TEFBOGEN=%TEFBogen_PATH%JSON
|
||||
|
||||
python 4_TEFBogen_SVG_XML_Modifier_Script.py
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set TEFBogen_PATH=%~dp0
|
||||
set PROPS_PATH=C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\props
|
||||
|
||||
set JSON_PATH=%TEFBogen_PATH%JSON
|
||||
set JSON_PATH_TEFBOGEN=%TEFBogen_PATH%JSON
|
||||
|
||||
python 1_process_TEFBogen_json_1.py
|
||||
python 2_update_props_TEF_Boegen_from_json_1.py
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
def process_json_file(input_file, output_file):
|
||||
|
||||
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
||||
|
||||
|
||||
if not os.path.exists(input_file):
|
||||
raise FileNotFoundError(f"输入文件不存在: {input_file}")
|
||||
|
||||
|
||||
with open(input_file, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
|
||||
DIRECTION_RULES = {
|
||||
"CP1": 180,
|
||||
"CPR1": 180,
|
||||
"CPL1": 180,
|
||||
"CP2": lambda kw: round(360 - kw, 1),
|
||||
"CPR2": lambda kw: round(360 - kw, 1),
|
||||
"CPL2": lambda kw: round(360 - kw, 1),
|
||||
"CP3": lambda kw: round(kw, 1),
|
||||
"CPR3": lambda kw: round(kw, 1),
|
||||
"CPL3": lambda kw: round(kw, 1),
|
||||
"CP4": 0
|
||||
}
|
||||
|
||||
# Process each item in the JSON data
|
||||
for item in data:
|
||||
if item.get("SivasnrTEF") is not None:
|
||||
# Step 1: Calculate pixel dimensions
|
||||
width_mm = item["Objekt_width_mm"]
|
||||
height_mm = item["Objekt_height_mm"]
|
||||
|
||||
# Calculate initial pixel values
|
||||
item["Objekt_width_px"] = round(width_mm * 3.7795275, 4)
|
||||
item["Objekt_height_px"] = round(height_mm * 3.7795275, 4)
|
||||
|
||||
# Determine which dimension is larger and calculate scaling factor
|
||||
if width_mm >= height_mm:
|
||||
scale = 1000 / width_mm
|
||||
item["calculated_SVG_width_px"] = 1000.0
|
||||
item["calculated_SVG_height_px"] = round(height_mm * scale, 6)
|
||||
scale_RD_H = round(1000 / item["calculated_SVG_height_px"], 6) if item["calculated_SVG_height_px"] > 0 else 1
|
||||
scale_RD_W = 1
|
||||
else:
|
||||
scale = 1000 / height_mm
|
||||
item["calculated_SVG_width_px"] = round(width_mm * scale, 6)
|
||||
item["calculated_SVG_height_px"] = 1000.0
|
||||
scale_RD_W = round(1000 / item["calculated_SVG_width_px"], 6) if item["calculated_SVG_width_px"] > 0 else 1
|
||||
scale_RD_H = 1
|
||||
|
||||
item["scale_factor"] = round(scale, 6)
|
||||
item["scale_factor_RD_Width"] = round(scale_RD_W, 6)
|
||||
item["scale_factor_RD_Height"] = round(scale_RD_H, 6)
|
||||
|
||||
# Process connection points -
|
||||
connection_points = []
|
||||
kurven_winkel = item["KurvenWinkel"]
|
||||
|
||||
|
||||
cp_fields = {}
|
||||
for key in item.keys():
|
||||
if key.endswith('_x_mm'):
|
||||
base_key = key[:-5]
|
||||
y_key = base_key + '_y_mm'
|
||||
if y_key in item:
|
||||
cp_fields[base_key] = (key, y_key)
|
||||
|
||||
|
||||
for base_key, (x_key, y_key) in cp_fields.items():
|
||||
try:
|
||||
|
||||
if base_key.startswith('OFWeiche_'):
|
||||
cp_type = base_key.replace('OFWeiche_', '')
|
||||
link_class = "Omniflo"
|
||||
elif base_key.startswith('TEFWeiche_'):
|
||||
cp_type = base_key.replace('TEFWeiche_', '')
|
||||
link_class = "TEFOmniflo"
|
||||
else:
|
||||
continue
|
||||
|
||||
|
||||
cp_id = cp_type.lower()
|
||||
|
||||
|
||||
direction_rule = DIRECTION_RULES.get(cp_type)
|
||||
if direction_rule is None:
|
||||
print(f"警告: 未找到连接点 {cp_type} 的方向规则,使用默认值0")
|
||||
direction = 0
|
||||
elif callable(direction_rule):
|
||||
direction = direction_rule(kurven_winkel)
|
||||
else:
|
||||
direction = direction_rule
|
||||
|
||||
|
||||
x_px = round(item[x_key] * scale * scale_RD_W, 3)
|
||||
y_px = round(item[y_key] * scale * scale_RD_H, 3)
|
||||
|
||||
connection_points.append({
|
||||
"id": cp_id,
|
||||
"x": x_px,
|
||||
"y": y_px,
|
||||
"direction": direction,
|
||||
"linkClass": link_class
|
||||
})
|
||||
|
||||
print(f"cp: {cp_id}: x={x_px}, y={y_px}, direction={direction}, linkClass={link_class}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"cp: {base_key} error: {e}")
|
||||
continue
|
||||
|
||||
|
||||
connection_points.sort(key=lambda x: x["id"])
|
||||
item["connectionPoints"] = connection_points
|
||||
|
||||
print(f"Processed {item['Sivasnr']}: find: {len(connection_points)} CPs")
|
||||
|
||||
# Save the processed data
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
if __name__ == "__main__":
|
||||
json_path = os.environ.get("JSON_PATH_TEFWEICHE", "JSON")
|
||||
input_filename = os.path.join(json_path, "omniflo_TEF_weichen.json")
|
||||
output_filename = os.path.join(json_path, "omniflo_TEF_weichen_output.json")
|
||||
|
||||
try:
|
||||
process_json_file(input_filename, output_filename)
|
||||
print(f"completed, saved as: {output_filename}")
|
||||
except Exception as e:
|
||||
print(f"error: {str(e)}")
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
''' Script Analysis
|
||||
|
||||
This Python script processes JSON and TXT files to update dimensions and connection points in SVG-related data, but only for entries where SivasnrTEF is null. Here's the main logic:
|
||||
Input Handling:
|
||||
Reads a JSON file containing reference data
|
||||
Processes all TXT files in a specified directory
|
||||
Data Processing:
|
||||
Creates a mapping between Sivasnr (from filenames) and JSON data (only for entries with SivasnrTEF = null)
|
||||
For each matching TXT file:
|
||||
Updates width and height based on JSON data (converting mm to px)
|
||||
Updates connection points (x, y, direction) from JSON data
|
||||
Preserves the original file structure while updating specific values
|
||||
Reporting:
|
||||
Prints detailed change reports to console
|
||||
Skips files without matching JSON data or where SivasnrTEF is not null '''
|
||||
import json
|
||||
import os
|
||||
import glob
|
||||
|
||||
def process_files(json_file_path, txt_files_dir):
|
||||
if not os.path.exists(json_file_path):
|
||||
print(f"Error: JSON file does not exist at {json_file_path}")
|
||||
exit(1)
|
||||
|
||||
if not os.path.exists(txt_files_dir):
|
||||
print(f"Error: Directory does not exist at {txt_files_dir}")
|
||||
exit(1)
|
||||
|
||||
# Read JSON file
|
||||
with open(json_file_path, 'r', encoding='utf-8') as f:
|
||||
json_data = json.load(f)
|
||||
|
||||
# Create Sivasnr to JSON data mapping ONLY for items with SivasnrTEF is not null
|
||||
sivasnr_mapping = {str(item["Sivasnr"]): item for item in json_data if item["SivasnrTEF"] is not None}
|
||||
|
||||
|
||||
txt_sivasnrs = set()
|
||||
for txt_file_path in glob.glob(os.path.join(txt_files_dir, '*.txt')):
|
||||
filename = os.path.basename(txt_file_path)
|
||||
sivasnr = os.path.splitext(filename)[0]
|
||||
txt_sivasnrs.add(sivasnr)
|
||||
|
||||
|
||||
unmatched_json_items = []
|
||||
for item in json_data:
|
||||
if item["SivasnrTEF"] is not None and str(item["Sivasnr"]) not in txt_sivasnrs:
|
||||
unmatched_json_items.append(item)
|
||||
|
||||
|
||||
print(f"JSON Items: {len(json_data)}")
|
||||
print(f"SivasnrTEF is not null : {len(sivasnr_mapping)}")
|
||||
print(f"SivasnrTEF is null {len([item for item in json_data if item['SivasnrTEF'] is None])}")
|
||||
print(f"SivasnrTEF record exists but no corresponding text file found in folder: {len(unmatched_json_items)}")
|
||||
print("="*50)
|
||||
|
||||
|
||||
if unmatched_json_items:
|
||||
print("\n SivasnrTEF record exists but no corresponding text file found in folder:")
|
||||
print("-" * 50)
|
||||
for item in unmatched_json_items:
|
||||
print(f"Sivasnr: {item['Sivasnr']}")
|
||||
print(f"ProfilTyp: {item.get('ProfilTyp', 'N/A')}")
|
||||
print(f"WeichenTyp: {item.get('WeichenTyp', 'N/A')}")
|
||||
print(f"SivasnrTEF: {item.get('SivasnrTEF', 'N/A')}")
|
||||
print("-" * 30)
|
||||
|
||||
# Initialize counters
|
||||
total_files = 0
|
||||
processed_files = 0
|
||||
matched_files = 0
|
||||
|
||||
# Process all TXT files
|
||||
for txt_file_path in glob.glob(os.path.join(txt_files_dir, '*.txt')):
|
||||
total_files += 1
|
||||
filename = os.path.basename(txt_file_path)
|
||||
sivasnr = os.path.splitext(filename)[0]
|
||||
|
||||
# Check if corresponding JSON data exists and SivasnrTEF is not null
|
||||
if sivasnr in sivasnr_mapping:
|
||||
matched_files += 1
|
||||
json_item = sivasnr_mapping[sivasnr]
|
||||
|
||||
try:
|
||||
# Read TXT file content
|
||||
with open(txt_file_path, 'r', encoding='utf-8-sig') as f:
|
||||
txt_content = json.load(f)
|
||||
|
||||
# Update width and height
|
||||
txt_content["width"] = round(json_item["Objekt_width_px"], 4)
|
||||
txt_content["height"] = round(json_item["Objekt_height_px"], 4)
|
||||
|
||||
|
||||
txt_cp_count = len(txt_content["connectionPoints"])
|
||||
json_cp_count = len(json_item["connectionPoints"])
|
||||
|
||||
if txt_cp_count != json_cp_count:
|
||||
print(f"Warning: Connection point count mismatch in {filename} (TXT: {txt_cp_count}, JSON: {json_cp_count})")
|
||||
|
||||
|
||||
new_connection_points = []
|
||||
|
||||
|
||||
for json_cp in json_item["connectionPoints"]:
|
||||
|
||||
new_cp = {
|
||||
"id": json_cp["id"],
|
||||
"x": json_cp["x"],
|
||||
"y": json_cp["y"],
|
||||
"z": 0.0,
|
||||
"xMin": "",
|
||||
"xMax": "",
|
||||
"xStep": "",
|
||||
"yMin": "",
|
||||
"yMax": "",
|
||||
"yStep": "",
|
||||
"zMin": "",
|
||||
"zMax": "",
|
||||
"zStep": "",
|
||||
"direction": json_cp["direction"],
|
||||
"linkClass": json_cp["linkClass"],
|
||||
"label": "",
|
||||
"isDimension": True
|
||||
}
|
||||
new_connection_points.append(new_cp)
|
||||
print(f" Added {json_cp['id']}: x={json_cp['x']}, y={json_cp['y']}, direction={json_cp['direction']}, linkClass={json_cp['linkClass']}")
|
||||
|
||||
|
||||
txt_content["connectionPoints"] = new_connection_points
|
||||
|
||||
# Write back to TXT file
|
||||
with open(txt_file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(txt_content, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"Successfully processed file: {filename} (替换了 {json_cp_count} 个连接点)")
|
||||
processed_files += 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing file {filename}: {str(e)}")
|
||||
else:
|
||||
|
||||
matching_in_json = any(str(item["Sivasnr"]) == sivasnr for item in json_data)
|
||||
''' if matching_in_json:
|
||||
print(f"Skipped file: {filename} (SivasnrTEF is null)")
|
||||
else:
|
||||
print(f"Skipped file: {filename} (not found in JSON)") '''
|
||||
|
||||
# Print final statistics
|
||||
print("\n" + "="*50)
|
||||
print("Processing Complete - Summary:")
|
||||
print(f"JSON文件总项数: {len(json_data)}")
|
||||
print(f"JSON中 SivasnrTEF 不为 null 的项数: {len(sivasnr_mapping)}")
|
||||
print(f"未匹配的JSON项数: {len(unmatched_json_items)}")
|
||||
print(f"TXT目录中找到的文件数: {total_files}")
|
||||
print(f"在JSON中找到匹配的TXT文件数: {matched_files}")
|
||||
print(f"成功处理的文件数: {processed_files}")
|
||||
|
||||
if matched_files > 0:
|
||||
success_rate = (processed_files / matched_files) * 100
|
||||
print(f"处理成功率: {success_rate:.2f}%")
|
||||
|
||||
# 再次显示未匹配的JSON项统计
|
||||
if unmatched_json_items:
|
||||
print(f"\n注意: 有 {len(unmatched_json_items)} 个JSON项 (SivasnrTEF不为null) 在TXT目录中没有对应的文件")
|
||||
print("这些项可能需要手动检查或创建对应的TXT文件")
|
||||
|
||||
print("="*50)
|
||||
if __name__ == "__main__":
|
||||
json_path = os.environ.get("JSON_PATH_TEFWEICH", "JSON")
|
||||
json_file_path = os.path.join(json_path, "omniflo_TEF_weichen_output.json")
|
||||
|
||||
txt_files_dir = r"C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\props"
|
||||
process_files(json_file_path, txt_files_dir)
|
||||
@@ -0,0 +1,385 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from xml.dom import minidom
|
||||
import argparse
|
||||
|
||||
def analyze_and_normalize_path(d, path_type, path_id=""):
|
||||
"""Strictly normalize path direction and generate detailed report"""
|
||||
original_d = d
|
||||
report = []
|
||||
normalized = []
|
||||
changed = False
|
||||
|
||||
# First check if path contains any arc commands
|
||||
if 'A' in d or 'a' in d:
|
||||
report.append(" Path contains arc commands - leaving unchanged")
|
||||
return original_d, report, False
|
||||
# Ensure path starts with M command
|
||||
if not d.strip().startswith('M'):
|
||||
d = 'M' + d[1:] if d.startswith('L') else 'M ' + d
|
||||
report.append(" Fix: Added M command at path start")
|
||||
changed = True
|
||||
|
||||
# Parse path commands
|
||||
commands = []
|
||||
current_cmd = None
|
||||
for token in re.split('([A-Za-z])', d):
|
||||
if not token:
|
||||
continue
|
||||
if token in 'MLAZHVCSQTa-z':
|
||||
current_cmd = token
|
||||
else:
|
||||
if current_cmd:
|
||||
commands.append((current_cmd, token.strip()))
|
||||
|
||||
prev_x, prev_y = None, None
|
||||
|
||||
for cmd, params in commands:
|
||||
params = [float(p) for p in re.split('[, ]+', params.strip()) if p]
|
||||
|
||||
if cmd == 'M':
|
||||
if len(params) >= 2:
|
||||
x, y = params[0], params[1]
|
||||
normalized.append(f"M {x} {y}")
|
||||
prev_x, prev_y = x, y
|
||||
continue
|
||||
|
||||
if path_type == 'Line segment' and cmd == 'L':
|
||||
if len(params) >= 2 and prev_x is not None:
|
||||
x, y = params[0], params[1]
|
||||
need_swap = x < prev_x or (x == prev_x and y < prev_y)
|
||||
|
||||
if need_swap:
|
||||
new_segment = [f"M {x} {y}", f"L {prev_x} {prev_y}"]
|
||||
report.append(f" Need to swap start/end → New path: {' '.join(new_segment)}")
|
||||
normalized = new_segment
|
||||
changed = True
|
||||
else:
|
||||
normalized.append(f"L {x} {y}")
|
||||
report.append(" Path direction already correct, no changes made")
|
||||
|
||||
prev_x, prev_y = x, y
|
||||
continue
|
||||
|
||||
if path_type == 'Arc' and cmd == 'A':
|
||||
if len(params) >= 7 and prev_x is not None:
|
||||
rx, ry, xrot, large, sweep, x, y = params[0], params[1], params[2], int(params[3]), int(params[4]), params[5], params[6]
|
||||
|
||||
# Force left-to-right clockwise
|
||||
need_swap = x < prev_x
|
||||
new_sweep = 1
|
||||
|
||||
if need_swap:
|
||||
new_segment = [f"M {x} {y}", f"A {rx} {ry} {xrot} {large} {new_sweep} {prev_x} {prev_y}"]
|
||||
report.append(f" Need to swap start/end → New path: {' '.join(new_segment)}")
|
||||
normalized = new_segment
|
||||
changed = True
|
||||
else:
|
||||
if sweep != new_sweep:
|
||||
new_segment = [f"A {rx} {ry} {xrot} {large} {new_sweep} {x} {y}"]
|
||||
report.append(f" Need to adjust sweep to 1 → New path: {' '.join(new_segment)}")
|
||||
normalized.extend(new_segment)
|
||||
changed = True
|
||||
else:
|
||||
normalized.append(f"A {rx} {ry} {xrot} {large} {sweep} {x} {y}")
|
||||
report.append(" Arc direction already correct, no changes made")
|
||||
|
||||
prev_x, prev_y = x, y
|
||||
continue
|
||||
|
||||
normalized.append(f"{cmd} {' '.join(map(str, params))}")
|
||||
|
||||
new_d = ' '.join(normalized)
|
||||
report_header = f"[{path_id}-Analysis] Type: {path_type}"
|
||||
full_report = [report_header, f"Original path: {original_d}"] + report
|
||||
|
||||
if changed:
|
||||
full_report.append(f"Modified path: {new_d}")
|
||||
else:
|
||||
full_report.append("Path not modified")
|
||||
|
||||
return new_d, '\n'.join(full_report)
|
||||
def analyze_and_normalize_path(d, path_type, path_id=""):
|
||||
"""Strictly normalize path direction and generate detailed report"""
|
||||
original_d = d
|
||||
report = []
|
||||
normalized = []
|
||||
changed = False
|
||||
|
||||
# First check if path contains any arc commands
|
||||
if 'A' in d or 'a' in d:
|
||||
report_header = f"[{path_id}-Analysis] Type: {path_type} (contains arcs)"
|
||||
full_report = [report_header,
|
||||
f"Original path: {original_d}",
|
||||
" Path contains arc commands - leaving unchanged",
|
||||
"Path not modified"]
|
||||
return original_d, '\n'.join(full_report)
|
||||
|
||||
# Ensure path starts with M command
|
||||
if not d.strip().startswith('M'):
|
||||
d = 'M' + d[1:] if d.startswith('L') else 'M ' + d
|
||||
report.append(" Fix: Added M command at path start")
|
||||
changed = True
|
||||
|
||||
# Parse path commands
|
||||
commands = []
|
||||
current_cmd = None
|
||||
for token in re.split('([A-Za-z])', d):
|
||||
if not token:
|
||||
continue
|
||||
if token in 'MLAZHVCSQTa-z':
|
||||
current_cmd = token
|
||||
else:
|
||||
if current_cmd:
|
||||
commands.append((current_cmd, token.strip()))
|
||||
|
||||
prev_x, prev_y = None, None
|
||||
|
||||
for cmd, params in commands:
|
||||
params = [float(p) for p in re.split('[, ]+', params.strip()) if p]
|
||||
|
||||
if cmd == 'M':
|
||||
if len(params) >= 2:
|
||||
x, y = params[0], params[1]
|
||||
normalized.append(f"M {x} {y}")
|
||||
prev_x, prev_y = x, y
|
||||
continue
|
||||
|
||||
if path_type == 'Line segment' and cmd == 'L':
|
||||
if len(params) >= 2 and prev_x is not None:
|
||||
x, y = params[0], params[1]
|
||||
need_swap = x < prev_x or (x == prev_x and y < prev_y)
|
||||
|
||||
if need_swap:
|
||||
new_segment = [f"M {x} {y}", f"L {prev_x} {prev_y}"]
|
||||
report.append(f" Need to swap start/end → New path: {' '.join(new_segment)}")
|
||||
normalized = new_segment
|
||||
changed = True
|
||||
else:
|
||||
normalized.append(f"L {x} {y}")
|
||||
report.append(" Path direction already correct, no changes made")
|
||||
|
||||
prev_x, prev_y = x, y
|
||||
continue
|
||||
|
||||
normalized.append(f"{cmd} {' '.join(map(str, params))}")
|
||||
|
||||
new_d = ' '.join(normalized)
|
||||
report_header = f"[{path_id}-Analysis] Type: {path_type}"
|
||||
full_report = [report_header, f"Original path: {original_d}"] + report
|
||||
|
||||
if changed:
|
||||
full_report.append(f"Modified path: {new_d}")
|
||||
else:
|
||||
full_report.append("Path not modified")
|
||||
|
||||
return new_d, '\n'.join(full_report)
|
||||
|
||||
def optimize_svg(input_path, output_path):
|
||||
"""Process single SVG file with all optimizations"""
|
||||
try:
|
||||
# Register namespace
|
||||
ET.register_namespace('', 'http://www.w3.org/2000/svg')
|
||||
|
||||
# Parse SVG file
|
||||
tree = ET.parse(input_path)
|
||||
root = tree.getroot()
|
||||
|
||||
print(f"\nProcessing file: {os.path.basename(input_path)}")
|
||||
print("="*60)
|
||||
|
||||
# Create parent map
|
||||
parent_map = {c: p for p in tree.iter() for c in p}
|
||||
|
||||
# 1. Remove xlink namespace
|
||||
for attr in list(root.attrib):
|
||||
if 'xlink' in attr:
|
||||
del root.attrib[attr]
|
||||
|
||||
# 2. Set standard dimensions
|
||||
root.set('width', '1e3')
|
||||
root.set('height', '1e3')
|
||||
root.set('viewBox', '0 0 1e3 1e3')
|
||||
|
||||
# 3. Remove all clipPath definitions and references
|
||||
defs = root.find('{http://www.w3.org/2000/svg}defs')
|
||||
if defs is not None:
|
||||
clip_paths = defs.findall('{http://www.w3.org/2000/svg}clipPath')
|
||||
for cp in clip_paths:
|
||||
defs.remove(cp)
|
||||
if len(defs) == 0:
|
||||
root.remove(defs)
|
||||
|
||||
# 4. Remove clip-path attributes
|
||||
for elem in tree.iter():
|
||||
if 'clip-path' in elem.attrib:
|
||||
del elem.attrib['clip-path']
|
||||
|
||||
# 5. Force square line caps
|
||||
for g in root.findall('.//{http://www.w3.org/2000/svg}g'):
|
||||
g.set('stroke-linecap', 'butt')
|
||||
|
||||
# 6. Remove dashed line styles
|
||||
for elem in tree.iter():
|
||||
if 'stroke-dasharray' in elem.attrib:
|
||||
del elem.attrib['stroke-dasharray']
|
||||
|
||||
# 7. Completely remove empty groups
|
||||
removed_groups = True
|
||||
while removed_groups:
|
||||
removed_groups = False
|
||||
for g in root.findall('.//{http://www.w3.org/2000/svg}g'):
|
||||
is_empty = (
|
||||
len(g) == 0 and
|
||||
not (g.text or '').strip() and
|
||||
not (g.tail or '').strip() and
|
||||
all(not k.startswith('{') for k in g.attrib))
|
||||
if is_empty:
|
||||
parent = parent_map.get(g)
|
||||
if parent is not None:
|
||||
parent.remove(g)
|
||||
removed_groups = True
|
||||
parent_map = {c: p for p in tree.iter() for c in p}
|
||||
|
||||
# 8. Convert polylines to paths
|
||||
for polyline in root.findall('.//{http://www.w3.org/2000/svg}polyline'):
|
||||
points = polyline.get('points', '').strip()
|
||||
if points:
|
||||
coords = [p for p in re.split(r'[\s,]', points) if p]
|
||||
path_data = []
|
||||
for i in range(0, len(coords), 2):
|
||||
if i == 0:
|
||||
path_data.append(f"M {coords[i]} {coords[i+1]}")
|
||||
else:
|
||||
path_data.append(f"L {coords[i]} {coords[i+1]}")
|
||||
|
||||
path = ET.Element('{http://www.w3.org/2000/svg}path')
|
||||
new_d, analysis_report = analyze_and_normalize_path(
|
||||
' '.join(path_data),
|
||||
'Line segment',
|
||||
"Polyline conversion"
|
||||
)
|
||||
path.set('d', new_d)
|
||||
print(f"\n[Polyline conversion analysis]\n{analysis_report}")
|
||||
|
||||
for attr, value in polyline.attrib.items():
|
||||
if attr not in ('points', 'stroke-dasharray'):
|
||||
path.set(attr, value)
|
||||
|
||||
parent = parent_map.get(polyline)
|
||||
if parent is not None:
|
||||
parent.remove(polyline)
|
||||
parent.append(path)
|
||||
|
||||
# 9. Normalize path directions (final step)
|
||||
group_num = 0
|
||||
for g in root.findall('.//{http://www.w3.org/2000/svg}g'):
|
||||
group_num += 1
|
||||
path_num = 0
|
||||
group_report = []
|
||||
|
||||
for path in g.findall('.//{http://www.w3.org/2000/svg}path'):
|
||||
path_num += 1
|
||||
if 'd' not in path.attrib:
|
||||
continue
|
||||
|
||||
# Auto-detect path type
|
||||
path_type = 'Arc' if 'A' in path.get('d') else 'Line segment'
|
||||
path_id = f"Group{group_num}-Path{path_num}"
|
||||
|
||||
new_d, analysis_report = analyze_and_normalize_path(
|
||||
path.get('d'),
|
||||
path_type,
|
||||
path_id
|
||||
)
|
||||
|
||||
if new_d != path.get('d'):
|
||||
path.set('d', new_d)
|
||||
|
||||
group_report.append(analysis_report)
|
||||
|
||||
# Print all path reports for current group
|
||||
if group_report:
|
||||
print(f"\n=== Group {group_num} Path Analysis ===")
|
||||
print('\n\n'.join(group_report))
|
||||
|
||||
# 10. Update colors and line width
|
||||
for elem in root.findall('.//*[@stroke]'):
|
||||
stroke = elem.get('stroke', '').lower()
|
||||
if stroke == '#0ff' or stroke == 'rgb(0,255,0)':
|
||||
elem.set('stroke', '#1bff38')
|
||||
elif stroke == '#000' or stroke == 'rgb(255,0,0)':
|
||||
elem.set('stroke', '#FF0000')
|
||||
elem.set('stroke-width', f'{1}px')
|
||||
|
||||
# Generate final XML
|
||||
rough_string = ET.tostring(root, encoding='utf-8', xml_declaration=True)
|
||||
rough_string = rough_string.replace(b'standalone="no"', b'')
|
||||
|
||||
# Format output (remove empty lines)
|
||||
reparsed = minidom.parseString(rough_string)
|
||||
pretty_svg = reparsed.toprettyxml(indent=' ', encoding='utf-8')
|
||||
pretty_svg = b'\n'.join(
|
||||
line for line in pretty_svg.splitlines()
|
||||
if line.strip()
|
||||
).replace(b'<?xml version="1.0" ?>', b'<?xml version="1.0" encoding="utf-8"?>')
|
||||
|
||||
with open(output_path, 'wb') as f:
|
||||
f.write(pretty_svg)
|
||||
|
||||
print("\n" + "="*60)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nProcessing error: {str(e)}")
|
||||
print("="*60)
|
||||
return False
|
||||
|
||||
def batch_process_svgs(input_dir, output_dir):
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
success_count = 0
|
||||
failure_count = 0
|
||||
|
||||
for filename in os.listdir(input_dir):
|
||||
if os.path.isdir(os.path.join(input_dir, filename)):
|
||||
continue
|
||||
if filename.lower().endswith('.svg') or '_new.svg' in filename.lower():
|
||||
input_path = os.path.join(input_dir, filename)
|
||||
output_filename = filename.replace('_new.svg', '_optimized.svg')
|
||||
output_path = os.path.join(output_dir, output_filename)
|
||||
|
||||
if optimize_svg(input_path, output_path):
|
||||
success_count += 1
|
||||
print(f"✓ Processed successfully: {filename} → {output_filename}")
|
||||
else:
|
||||
failure_count += 1
|
||||
print(f"✗ Processing failed: {filename}")
|
||||
print("\n" + "="*60 + "\n")
|
||||
|
||||
print("\nProcessing summary:")
|
||||
print(f"Successfully processed: {success_count} files")
|
||||
print(f"Failed to process: {failure_count} files")
|
||||
|
||||
if __name__ == '__main__':
|
||||
input_dir = os.environ.get('RD_CONF_TEFWEICHEN')
|
||||
output_dir = os.environ.get('RD_CONF_WORK')
|
||||
|
||||
if not input_dir or not output_dir:
|
||||
print("Error: Environment variable RD_CONF_WORK is not set")
|
||||
exit(1)
|
||||
|
||||
if not os.path.exists(input_dir):
|
||||
print(f"Error: Input directory '{input_dir}' does not exist")
|
||||
exit(1)
|
||||
|
||||
print(f"Starting SVG file processing, working directory: {input_dir}")
|
||||
print("=" * 50)
|
||||
|
||||
batch_process_svgs(input_dir, output_dir)
|
||||
|
||||
print("Processing completed!")
|
||||
@@ -0,0 +1,276 @@
|
||||
import os
|
||||
from lxml import etree
|
||||
import re
|
||||
from math import sqrt, isclose
|
||||
from collections import defaultdict
|
||||
|
||||
# Constants
|
||||
WEICHEN_PROFILE_WIDTH = 42.000
|
||||
L_R_TARGET_LENGTH = 55.7237
|
||||
DELTA_TARGET_LENGTH = 53.5437
|
||||
MATCH_TOLERANCE = 0.1 # Matching tolerance 0.1mm
|
||||
TARGET_STROKE_COLOR = "#1bff38" # 新增:目标stroke颜色
|
||||
|
||||
def process_svg_files(directory):
|
||||
print(f"🔍 Scanning directory: {directory}")
|
||||
print("-" * 60)
|
||||
|
||||
result_stats = {
|
||||
'total_files': 0,
|
||||
'L_R_files': {'with_pairs': [], 'no_pairs': [], 'excess_pairs': []},
|
||||
'Delta_files': {'with_triples': [], 'no_triples': [], 'excess_triples': []}
|
||||
}
|
||||
|
||||
for filename in os.listdir(directory):
|
||||
if not filename.endswith('.svg'):
|
||||
continue
|
||||
|
||||
filepath = os.path.join(directory, filename)
|
||||
result_stats['total_files'] += 1
|
||||
|
||||
if '_L_' in filename or '_R_' in filename:
|
||||
print(f"\n📄 Processing L/R file: {filename}")
|
||||
process_lr_file(filepath, filename, result_stats)
|
||||
elif '_DELTA_' in filename:
|
||||
print(f"\n📄 Processing DeltaWeiche file: {filename}")
|
||||
process_delta_file(filepath, filename, result_stats)
|
||||
|
||||
# Print final statistics
|
||||
print("\n" + "="*60)
|
||||
print("📊 Final processing statistics:")
|
||||
print(f"Total files processed: {result_stats['total_files']}")
|
||||
|
||||
print("\nL/R type files results:")
|
||||
print(f"✅ Files with matching path pairs: {len(result_stats['L_R_files']['with_pairs'])}")
|
||||
print(f" {result_stats['L_R_files']['with_pairs']}")
|
||||
print(f"⚠️ Files with no matching paths: {len(result_stats['L_R_files']['no_pairs'])}")
|
||||
print(f" {result_stats['L_R_files']['no_pairs']}")
|
||||
print(f"❌ Files with >2 matching paths: {len(result_stats['L_R_files']['excess_pairs'])}")
|
||||
print(f" {result_stats['L_R_files']['excess_pairs']}")
|
||||
|
||||
print("\nDeltaWeiche type files results:")
|
||||
print(f"✅ Files with matching path triples: {len(result_stats['Delta_files']['with_triples'])}")
|
||||
print(f" {result_stats['Delta_files']['with_triples']}")
|
||||
print(f"⚠️ Files with no matching paths: {len(result_stats['Delta_files']['no_triples'])}")
|
||||
print(f" {result_stats['Delta_files']['no_triples']}")
|
||||
print(f"❌ Files with ≠3 matching paths: {len(result_stats['Delta_files']['excess_triples'])}")
|
||||
print(f" {result_stats['Delta_files']['excess_triples']}")
|
||||
|
||||
print("\n✨ Processing complete!")
|
||||
|
||||
def process_lr_file(filepath, filename, stats):
|
||||
try:
|
||||
tree = etree.parse(filepath)
|
||||
root = tree.getroot()
|
||||
|
||||
# Find all straight line paths within target stroke color groups
|
||||
straight_lines = find_straight_lines_in_colored_groups(root)
|
||||
print(f" 📊 Found {len(straight_lines)} straight paths in stroke='{TARGET_STROKE_COLOR}' groups")
|
||||
|
||||
if not straight_lines:
|
||||
print(f" ❌ No paths found in stroke='{TARGET_STROKE_COLOR}' groups")
|
||||
stats['L_R_files']['no_pairs'].append(filename)
|
||||
return
|
||||
|
||||
# Print all straight paths
|
||||
print("\n 🔍 All straight path details:")
|
||||
for line in straight_lines:
|
||||
print(f" Path{line['index']}: ({line['p1'][0]:.2f},{line['p1'][1]:.2f})→"
|
||||
f"({line['p2'][0]:.2f},{line['p2'][1]:.2f}) length={line['length']:.4f}mm")
|
||||
|
||||
# Group by length
|
||||
length_groups = group_lines_by_length(straight_lines)
|
||||
|
||||
# Only print groups with exactly 2 paths
|
||||
print("\n 🔍 Same-length path groups (2 paths):")
|
||||
perfect_pairs = [group for group in length_groups.values() if len(group) == 2]
|
||||
for group in perfect_pairs:
|
||||
print(f" ┌ Length group ({group[0]['length']:.4f}mm, 2 paths)")
|
||||
for line in group:
|
||||
print(f" │ Path{line['index']}: ({line['p1'][0]:.2f},{line['p1'][1]:.2f})→"
|
||||
f"({line['p2'][0]:.2f},{line['p2'][1]:.2f})")
|
||||
print(" └" + "─" * 40)
|
||||
|
||||
if len(perfect_pairs) == 1:
|
||||
pair = perfect_pairs[0]
|
||||
original_length = pair[0]['length']
|
||||
scale_factor = WEICHEN_PROFILE_WIDTH / original_length
|
||||
print(f"\n 🔄 Scaling calculation (based on length {original_length:.4f}mm):")
|
||||
print(f" Scale factor: {scale_factor:.4f}")
|
||||
|
||||
# Print scaled lengths
|
||||
print("\n 🔍 Scaled path lengths:")
|
||||
for line in straight_lines:
|
||||
scaled_len = line['length'] * scale_factor
|
||||
print(f" Path{line['index']}: {line['length']:.4f}mm → {scaled_len:.4f}mm")
|
||||
|
||||
# Find path matching target length (within tolerance)
|
||||
target_path = find_target_path(straight_lines, scale_factor, L_R_TARGET_LENGTH)
|
||||
if target_path:
|
||||
target_path['element'].set('style', 'stroke:none;fill:none;')
|
||||
tree.write(filepath, encoding='utf-8', xml_declaration=True)
|
||||
print(f"\n ✅ Hid path{target_path['index']} matching target length {L_R_TARGET_LENGTH:.4f}mm (±{MATCH_TOLERANCE}mm)")
|
||||
stats['L_R_files']['with_pairs'].append(filename)
|
||||
else:
|
||||
print(f"\n ❌ No path found matching {L_R_TARGET_LENGTH:.4f}mm (±{MATCH_TOLERANCE}mm)")
|
||||
stats['L_R_files']['no_pairs'].append(filename)
|
||||
elif len(perfect_pairs) > 1:
|
||||
print(f"\n ❗ Found multiple same-length path groups: {[len(g) for g in length_groups.values()]}")
|
||||
stats['L_R_files']['excess_pairs'].append(filename)
|
||||
else:
|
||||
print("\n ❌ No same-length path pairs found")
|
||||
stats['L_R_files']['no_pairs'].append(filename)
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Processing failed: {str(e)}")
|
||||
|
||||
def process_delta_file(filepath, filename, stats):
|
||||
try:
|
||||
tree = etree.parse(filepath)
|
||||
root = tree.getroot()
|
||||
|
||||
# Find all straight line paths within target stroke color groups
|
||||
straight_lines = find_straight_lines_in_colored_groups(root)
|
||||
print(f" 📊 Found {len(straight_lines)} straight paths in stroke='{TARGET_STROKE_COLOR}' groups")
|
||||
|
||||
if not straight_lines:
|
||||
print(f" ❌ No paths found in stroke='{TARGET_STROKE_COLOR}' groups")
|
||||
stats['Delta_files']['no_triples'].append(filename)
|
||||
return
|
||||
|
||||
# Print all straight paths
|
||||
print("\n 🔍 All straight path details:")
|
||||
for line in straight_lines:
|
||||
print(f" Path{line['index']}: ({line['p1'][0]:.2f},{line['p1'][1]:.2f})→"
|
||||
f"({line['p2'][0]:.2f},{line['p2'][1]:.2f}) length={line['length']:.4f}mm")
|
||||
|
||||
# Group by length
|
||||
length_groups = group_lines_by_length(straight_lines)
|
||||
|
||||
# Only print groups with exactly 3 paths
|
||||
print("\n 🔍 Same-length path groups (3 paths):")
|
||||
perfect_triples = [group for group in length_groups.values() if len(group) == 3]
|
||||
for group in perfect_triples:
|
||||
print(f" ┌ Length group ({group[0]['length']:.4f}mm, 3 paths)")
|
||||
for line in group:
|
||||
print(f" │ Path{line['index']}: ({line['p1'][0]:.2f},{line['p1'][1]:.2f})→"
|
||||
f"({line['p2'][0]:.2f},{line['p2'][1]:.2f})")
|
||||
print(" └" + "─" * 40)
|
||||
|
||||
if len(perfect_triples) == 1:
|
||||
triple = perfect_triples[0]
|
||||
original_length = triple[0]['length']
|
||||
scale_factor = WEICHEN_PROFILE_WIDTH / original_length
|
||||
print(f"\n 🔄 Scaling calculation (based on length {original_length:.4f}mm):")
|
||||
print(f" Scale factor: {scale_factor:.4f}")
|
||||
|
||||
# Print scaled lengths
|
||||
print("\n 🔍 Scaled path lengths:")
|
||||
for line in straight_lines:
|
||||
scaled_len = line['length'] * scale_factor
|
||||
print(f" Path{line['index']}: {line['length']:.4f}mm → {scaled_len:.4f}mm")
|
||||
|
||||
# Find all paths matching target length (there might be multiple)
|
||||
target_paths = [line for line in straight_lines
|
||||
if abs(line['length'] * scale_factor - DELTA_TARGET_LENGTH) < MATCH_TOLERANCE]
|
||||
|
||||
if target_paths:
|
||||
for target in target_paths:
|
||||
target['element'].set('style', 'stroke:none;fill:none;')
|
||||
tree.write(filepath, encoding='utf-8', xml_declaration=True)
|
||||
print(f"\n ✅ Hid {len(target_paths)} paths matching target length {DELTA_TARGET_LENGTH:.4f}mm (±{MATCH_TOLERANCE}mm):")
|
||||
for target in target_paths:
|
||||
print(f" - Path{target['index']}")
|
||||
stats['Delta_files']['with_triples'].append(filename)
|
||||
else:
|
||||
print(f"\n ❌ No path found matching {DELTA_TARGET_LENGTH:.4f}mm (±{MATCH_TOLERANCE}mm)")
|
||||
stats['Delta_files']['no_triples'].append(filename)
|
||||
elif len(perfect_triples) > 1:
|
||||
print(f"\n ❗ Found multiple same-length path groups: {[len(g) for g in length_groups.values()]}")
|
||||
stats['Delta_files']['excess_triples'].append(filename)
|
||||
else:
|
||||
print("\n ❌ No same-length path groups (3 paths) found")
|
||||
stats['Delta_files']['no_triples'].append(filename)
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Processing failed: {str(e)}")
|
||||
|
||||
def find_straight_lines_in_colored_groups(root):
|
||||
"""Find all straight line paths within groups that have stroke="#1bff38" """
|
||||
lines = []
|
||||
|
||||
# 首先找到所有stroke="#1bff38"的group元素
|
||||
colored_groups = root.xpath('.//svg:g[contains(@stroke, "#1bff38")]',
|
||||
namespaces={'svg': 'http://www.w3.org/2000/svg'})
|
||||
|
||||
# 如果没有找到指定颜色的group,返回空列表
|
||||
if not colored_groups:
|
||||
return lines
|
||||
|
||||
print(f" 🎨 Found {len(colored_groups)} groups with stroke='{TARGET_STROKE_COLOR}'")
|
||||
|
||||
# 在每个符合条件的group中查找路径
|
||||
path_index = 1
|
||||
for group in colored_groups:
|
||||
# 在当前group中查找所有path元素
|
||||
paths = group.xpath('.//svg:path', namespaces={'svg': 'http://www.w3.org/2000/svg'})
|
||||
|
||||
for path in paths:
|
||||
d = path.get('d', '').strip()
|
||||
if not d:
|
||||
continue
|
||||
|
||||
if is_straight_line(d):
|
||||
length, (p1, p2) = calculate_line_length(d)
|
||||
if length > 0:
|
||||
lines.append({
|
||||
'index': path_index,
|
||||
'element': path,
|
||||
'length': round(length, 4),
|
||||
'p1': (round(p1[0], 2), round(p1[1], 2)),
|
||||
'p2': (round(p2[0], 2), round(p2[1], 2))
|
||||
})
|
||||
path_index += 1
|
||||
|
||||
return lines
|
||||
|
||||
def group_lines_by_length(lines):
|
||||
"""Group straight paths by length"""
|
||||
groups = defaultdict(list)
|
||||
for line in lines:
|
||||
groups[line['length']].append(line)
|
||||
return groups
|
||||
|
||||
def find_target_path(lines, scale_factor, target_length):
|
||||
"""Find path that matches target length after scaling (within tolerance)"""
|
||||
for line in lines:
|
||||
scaled_length = line['length'] * scale_factor
|
||||
if abs(scaled_length - target_length) < MATCH_TOLERANCE:
|
||||
return line
|
||||
return None
|
||||
|
||||
def is_straight_line(d):
|
||||
"""Check if path is strictly a straight line"""
|
||||
commands = [cmd[0].upper() for cmd in re.findall('([A-Za-z])', d)]
|
||||
return len(commands) == 2 and commands[0] == 'M' and commands[1] == 'L'
|
||||
|
||||
def calculate_line_length(d):
|
||||
"""Calculate line length and return endpoints"""
|
||||
points = []
|
||||
for cmd, params in re.findall('([A-Za-z])([^A-Za-z]*)', d):
|
||||
if cmd.upper() in ('M', 'L'):
|
||||
coords = [float(p) for p in re.findall('[-+]?\d*\.\d+|[-+]?\d+', params)]
|
||||
points.append((coords[0], coords[1]))
|
||||
|
||||
if len(points) != 2:
|
||||
return 0, ((0,0), (0,0))
|
||||
|
||||
length = sqrt((points[1][0]-points[0][0])**2 + (points[1][1]-points[0][1])**2)
|
||||
return round(length, 4), (points[0], points[1])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Set SVG files directory path
|
||||
# svg_directory = r'C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\work'
|
||||
svg_directory =os.environ.get('RD_CONF_WORK')
|
||||
process_svg_files(svg_directory)
|
||||
@@ -0,0 +1,160 @@
|
||||
import os
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from typing import Tuple, List
|
||||
|
||||
def parse_svg_path(d: str) -> List[Tuple[float, float]]:
|
||||
"""Extract all coordinates from SVG path data (including curve control points)"""
|
||||
points = []
|
||||
commands = re.findall(
|
||||
r'([MmLlCcQqAaHhVvZz])([^MmLlCcQqAaHhVvZz]*)',
|
||||
d.strip().replace(',', ' ')
|
||||
)
|
||||
current_pos = (0.0, 0.0)
|
||||
|
||||
for cmd, args in commands:
|
||||
args = list(map(float, re.findall(r'[-+]?\d*\.?\d+', args)))
|
||||
if cmd in ('M', 'm', 'L', 'l'): # Move/line commands
|
||||
for i in range(0, len(args), 2):
|
||||
x, y = args[i], args[i+1]
|
||||
if cmd.islower(): # Relative coordinates
|
||||
x += current_pos[0]
|
||||
y += current_pos[1]
|
||||
points.append((x, y))
|
||||
current_pos = (x, y)
|
||||
elif cmd in ('C', 'c'): # Cubic Bezier curves
|
||||
for i in range(0, len(args), 6):
|
||||
x1, y1, x2, y2, x, y = args[i:i+6]
|
||||
if cmd.islower():
|
||||
x1 += current_pos[0]; y1 += current_pos[1]
|
||||
x2 += current_pos[0]; y2 += current_pos[1]
|
||||
x += current_pos[0]; y += current_pos[1]
|
||||
points.extend([(x1, y1), (x2, y2), (x, y)])
|
||||
current_pos = (x, y)
|
||||
elif cmd in ('A', 'a'): # Arc commands (start/end points only)
|
||||
for i in range(0, len(args), 7):
|
||||
x, y = args[i+5], args[i+6]
|
||||
if cmd.islower():
|
||||
x += current_pos[0]
|
||||
y += current_pos[1]
|
||||
points.append((x, y))
|
||||
current_pos = (x, y)
|
||||
return points
|
||||
|
||||
def calculate_bounding_box(svg_file: str) -> Tuple[float, float, float, float]:
|
||||
"""Calculate true bounding box of all paths in SVG"""
|
||||
tree = ET.parse(svg_file)
|
||||
root = tree.getroot()
|
||||
all_points = []
|
||||
|
||||
for path in root.findall('.//{http://www.w3.org/2000/svg}path'):
|
||||
d = path.get('d', '')
|
||||
all_points.extend(parse_svg_path(d))
|
||||
|
||||
if not all_points:
|
||||
return (0, 0, 0, 0)
|
||||
|
||||
x_min = min(p[0] for p in all_points)
|
||||
x_max = max(p[0] for p in all_points)
|
||||
y_min = min(p[1] for p in all_points)
|
||||
y_max = max(p[1] for p in all_points)
|
||||
return (x_min, y_min, x_max, y_max)
|
||||
|
||||
|
||||
def normalize_stroke_widths2(root, scale):
|
||||
"""Normalize stroke widths to ensure consistent appearance after scaling"""
|
||||
for elem in root.iter():
|
||||
if 'stroke-width' in elem.attrib:
|
||||
# Remove existing stroke-width
|
||||
del elem.attrib['stroke-width']
|
||||
# Apply scaled stroke width (e.g., 1px → 1/scale)
|
||||
elem.set('stroke-width', f'{1/scale:.6f}px')
|
||||
|
||||
def apply_non_scaling_stroke(root):
|
||||
|
||||
for elem in root.iter():
|
||||
if 'stroke' in elem.attrib and elem.attrib['stroke'] != 'none':
|
||||
# set stroke-width=1(no unit)
|
||||
elem.set('stroke-width', '1')
|
||||
# set vector-effect
|
||||
elem.set('vector-effect', 'non-scaling-stroke')
|
||||
|
||||
def scale_svg_file(input_path: str, output_path: str):
|
||||
"""Scale SVG file with consistent stroke widths"""
|
||||
print(f"\nProcessing: {os.path.basename(input_path)}")
|
||||
|
||||
tree = ET.parse(input_path)
|
||||
root = tree.getroot()
|
||||
|
||||
# Calculate original bounding box
|
||||
x_min, y_min, x_max, y_max = calculate_bounding_box(input_path)
|
||||
width = x_max - x_min
|
||||
height = y_max - y_min
|
||||
|
||||
print(f"Original bounding box: ({x_min:.3f}, {y_min:.3f}) to ({x_max:.3f}, {y_max:.3f})")
|
||||
print(f"Original dimensions: {width:.3f} (w) × {height:.3f} (h)")
|
||||
|
||||
|
||||
# Determine scaling base (larger dimension → 1000px)
|
||||
if width > height:
|
||||
scale = 1000.0 / width
|
||||
new_width = 1000.0
|
||||
new_height = round(height * scale,3)
|
||||
print(f"Scaling base: Width (larger dimension)")
|
||||
else:
|
||||
scale = 1000.0 / height
|
||||
new_height = 1000.0
|
||||
new_width = round(width * scale,3)
|
||||
print(f"Scaling base: Height (larger dimension)")
|
||||
|
||||
print(f"Scale factor: {scale:.6f}")
|
||||
print(f"New dimensions: {new_width:.3f}px × {new_height:.3f}px")
|
||||
print(f"ViewBox: 0 0 {new_width:.3f} {new_height:.3f}")
|
||||
normalize_stroke_widths2(root, scale)
|
||||
#apply_non_scaling_stroke(root)
|
||||
#
|
||||
# Update SVG attributes
|
||||
root.set('viewBox', f'0 0 {new_width:.3f} {new_height:.3f}')
|
||||
root.set('width', f'{new_width:.3f}')
|
||||
root.set('height', f'{new_height:.3f}')
|
||||
|
||||
# Apply translation and scaling
|
||||
for g in root.findall('{http://www.w3.org/2000/svg}g'):
|
||||
transform = g.get('transform', '')
|
||||
new_transform = f'translate({-x_min*scale},{-y_min*scale}) scale({scale})'
|
||||
if transform:
|
||||
new_transform = f'{transform} {new_transform}'
|
||||
g.set('transform', new_transform)
|
||||
|
||||
# Save modified SVG
|
||||
tree.write(output_path, encoding='utf-8', xml_declaration=True)
|
||||
print(f"Finished processing: {os.path.basename(input_path)}")
|
||||
|
||||
def batch_process_svg(input_dir: str, output_dir: str):
|
||||
"""Batch process SVG files in directory (non-recursive)"""
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
svg_files = [
|
||||
f for f in os.listdir(input_dir)
|
||||
if f.lower().endswith('.svg') and os.path.isfile(os.path.join(input_dir, f))
|
||||
]
|
||||
|
||||
if not svg_files:
|
||||
print("No SVG files found in the input directory!")
|
||||
return
|
||||
|
||||
print(f"\nFound {len(svg_files)} SVG files to process")
|
||||
for filename in svg_files:
|
||||
input_path = os.path.join(input_dir, filename)
|
||||
output_path = os.path.join(output_dir, filename)
|
||||
scale_svg_file(input_path, output_path)
|
||||
|
||||
print("\nAll files processed successfully!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
# input_dir = r'C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\work'
|
||||
# output_dir =r"C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\TEFWeichen\output"
|
||||
input_dir = os.environ.get('RD_CONF_WORK')
|
||||
output_dir = os.environ.get('RD_CONF_WORK')
|
||||
batch_process_svg(input_dir, output_dir)
|
||||
@@ -0,0 +1,162 @@
|
||||
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'] = 'butt'
|
||||
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\TEFWeichen\output'
|
||||
# output_dir =r"C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\TEFWeichen\output"
|
||||
input_dir = os.environ.get('RD_CONF_WORK')
|
||||
output_dir = os.environ.get('RD_CONF_OUTPUT_TEFWEICHEN')
|
||||
# Example usage:
|
||||
batch_process_svgs(input_dir, output_dir)
|
||||
@@ -0,0 +1,195 @@
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
from xml.etree import ElementTree as ET
|
||||
from xml.dom import minidom
|
||||
|
||||
def extract_sivasnr(filename):
|
||||
"""Extract content before _WEICHE from filename"""
|
||||
# 匹配模式:提取 _WEICHE 之前的所有内容
|
||||
match = re.search(r'^(.+?)_WEICHE', filename)
|
||||
return match.group(1) if match else None
|
||||
|
||||
def should_skip_stroke_width(element_attrib):
|
||||
"""Check if element should skip stroke-width setting"""
|
||||
# Check style attribute
|
||||
if 'style' in element_attrib:
|
||||
style = element_attrib['style'].lower()
|
||||
if 'stroke:none' in style and 'fill:none' in style:
|
||||
return True
|
||||
|
||||
# Check separate stroke and fill attributes
|
||||
stroke = element_attrib.get('stroke', '').lower()
|
||||
fill = element_attrib.get('fill', '').lower()
|
||||
return stroke == 'none' and fill == 'none'
|
||||
|
||||
def create_xml_structure(svg_root):
|
||||
"""Create target XML structure preserving all elements"""
|
||||
# Create base structure
|
||||
new_root = ET.Element("svg", xmlns="http://www.w3.org/2000/svg")
|
||||
g_layer = ET.SubElement(new_root, "g", transform="rotate(0)")
|
||||
|
||||
# Add inner SVG container
|
||||
inner_svg = ET.SubElement(g_layer, "svg", {
|
||||
"viewBox": svg_root.attrib.get("viewBox", "0 0 1000 1000"),
|
||||
"preserveAspectRatio": "none",
|
||||
"position": "absolute",
|
||||
"overflow": "visible"
|
||||
})
|
||||
|
||||
# Transfer all content
|
||||
for elem in svg_root:
|
||||
if elem.tag.endswith("}g"):
|
||||
# Process group with namespace
|
||||
new_g = ET.SubElement(inner_svg, "g", attrib={
|
||||
k: v for k, v in elem.attrib.items()
|
||||
if not k.startswith("xmlns")
|
||||
})
|
||||
|
||||
# Process all elements within group
|
||||
for child in elem:
|
||||
child_tag = child.tag.split("}")[-1] # Remove namespace
|
||||
child_attrib = {}
|
||||
|
||||
# Preserve all original attributes (except namespace)
|
||||
for k, v in child.attrib.items():
|
||||
if not k.startswith("xmlns"):
|
||||
child_attrib[k] = v
|
||||
|
||||
# Only add stroke-width if not stroke:none;fill:none
|
||||
if not should_skip_stroke_width(child.attrib):
|
||||
child_attrib["stroke-width"] = "1px"
|
||||
|
||||
# Create element with preserved attributes
|
||||
ET.SubElement(new_g, child_tag, attrib=child_attrib)
|
||||
|
||||
else:
|
||||
# Process standalone elements (path, circle, etc.)
|
||||
elem_tag = elem.tag.split("}")[-1] # Remove namespace
|
||||
elem_attrib = {}
|
||||
|
||||
# Preserve all original attributes (except namespace)
|
||||
for k, v in elem.attrib.items():
|
||||
if not k.startswith("xmlns"):
|
||||
elem_attrib[k] = v
|
||||
|
||||
# Only add stroke-width if not stroke:none;fill:none
|
||||
if not should_skip_stroke_width(elem.attrib):
|
||||
elem_attrib["stroke-width"] = "1px"
|
||||
|
||||
ET.SubElement(inner_svg, elem_tag, attrib=elem_attrib)
|
||||
|
||||
return new_root
|
||||
|
||||
def format_xml(element):
|
||||
"""Generate formatted XML string"""
|
||||
# Generate XML with declaration
|
||||
xml_str = ET.tostring(element, encoding="UTF-8", xml_declaration=True)
|
||||
|
||||
# Pretty format with 2-space indent
|
||||
dom = minidom.parseString(xml_str)
|
||||
pretty_xml = dom.toprettyxml(indent=" ", encoding="UTF-8").decode("UTF-8")
|
||||
|
||||
# Remove extra empty lines (preserve structure)
|
||||
lines = []
|
||||
for line in pretty_xml.split("\n"):
|
||||
if line.strip() or line.lstrip().startswith("</"):
|
||||
lines.append(line)
|
||||
return "\n".join(lines)
|
||||
|
||||
def convert_svg_to_xml(svg_path, output_dir):
|
||||
"""Convert SVG to target XML format"""
|
||||
sivasnr = extract_sivasnr(os.path.basename(svg_path))
|
||||
if not sivasnr:
|
||||
raise ValueError(f"Invalid filename format: {os.path.basename(svg_path)}")
|
||||
|
||||
# Parse original SVG
|
||||
try:
|
||||
tree = ET.parse(svg_path)
|
||||
svg_root = tree.getroot()
|
||||
except Exception as e:
|
||||
raise ValueError(f"SVG parsing error: {str(e)}")
|
||||
|
||||
# Build new structure
|
||||
new_xml = create_xml_structure(svg_root)
|
||||
formatted_xml = format_xml(new_xml)
|
||||
|
||||
# Ensure output directory exists
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
output_path = os.path.join(output_dir, f"{sivasnr}.xml")
|
||||
|
||||
# Write file (UTF-8 encoding)
|
||||
with open(output_path, "w", encoding="UTF-8") as f:
|
||||
f.write(formatted_xml)
|
||||
|
||||
return f"SSG/shapes/svg/{sivasnr}.xml"
|
||||
|
||||
def update_txt_file(txt_path, xml_rel_path):
|
||||
"""Update path in TXT file"""
|
||||
try:
|
||||
with open(txt_path, "r", encoding="UTF-8-sig") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if "srcSVG" not in data:
|
||||
raise ValueError("Missing srcSVG field")
|
||||
|
||||
data["srcSVG"] = xml_rel_path
|
||||
|
||||
with open(txt_path, "w", encoding="UTF-8") as f:
|
||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Update failed {os.path.basename(txt_path)}: {str(e)}")
|
||||
return False
|
||||
|
||||
def process_files(svg_dir, txt_dir, output_dir):
|
||||
"""Batch process files"""
|
||||
if not all(map(os.path.exists, [svg_dir, txt_dir])):
|
||||
raise FileNotFoundError("Input directory not found")
|
||||
|
||||
results = {"success": 0, "failed": 0}
|
||||
|
||||
for svg_file in os.listdir(svg_dir):
|
||||
if not svg_file.endswith(".svg"):
|
||||
continue
|
||||
|
||||
svg_path = os.path.join(svg_dir, svg_file)
|
||||
sivasnr = extract_sivasnr(svg_file)
|
||||
|
||||
if not sivasnr:
|
||||
print(f"Skipping invalid file: {svg_file}")
|
||||
results["failed"] += 1
|
||||
continue
|
||||
|
||||
try:
|
||||
# Convert file
|
||||
xml_rel_path = convert_svg_to_xml(svg_path, output_dir)
|
||||
|
||||
# Update TXT
|
||||
txt_path = os.path.join(txt_dir, f"{sivasnr}.txt")
|
||||
if not os.path.exists(txt_path):
|
||||
raise FileNotFoundError(f"Corresponding TXT file not found: {sivasnr}.txt")
|
||||
|
||||
if update_txt_file(txt_path, xml_rel_path):
|
||||
print(f"Success: {svg_file} → {sivasnr}.xml")
|
||||
results["success"] += 1
|
||||
else:
|
||||
results["failed"] += 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"Processing failed {svg_file}: {str(e)}")
|
||||
results["failed"] += 1
|
||||
|
||||
# Output report
|
||||
print(f"\nProcessing complete: {results['success']} succeeded, {results['failed']} failed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Configuration - modify these paths as needed
|
||||
SVG_INPUT_FOLDER = os.environ.get('RD_CONF_OUTPUT_TEFWEICHEN') # Folder containing SVG files
|
||||
SVG_OUTPUT_FOLDER = os.environ.get("SVG_PATH","svg")
|
||||
PRORPS_FOLDER = os.environ.get("PROPS_PATH", "props") # Folder containing txt files
|
||||
|
||||
# Start processing
|
||||
process_files(SVG_INPUT_FOLDER, PRORPS_FOLDER, SVG_OUTPUT_FOLDER)
|
||||
print("\nProcessing complete.")
|
||||
@@ -0,0 +1,196 @@
|
||||
"""
|
||||
SVG XML Batch Modifier Script
|
||||
|
||||
This script:
|
||||
1. Reads a JSON array of items
|
||||
2. For each item, extracts the "Sivasnr" value
|
||||
3. Locates and modifies the corresponding XML file
|
||||
4. Processes only red color groups (#FF0000)
|
||||
5. Provides comprehensive reporting
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
from xml.etree.ElementTree import Element, SubElement, tostring
|
||||
|
||||
def process_xml_file(xml_path):
|
||||
"""
|
||||
Process a single XML file focusing on red color groups only
|
||||
Returns modification statistics
|
||||
"""
|
||||
try:
|
||||
tree = ET.parse(xml_path)
|
||||
root = tree.getroot()
|
||||
|
||||
# Register and handle SVG namespace
|
||||
ET.register_namespace('', 'http://www.w3.org/2000/svg')
|
||||
namespaces = {'svg': 'http://www.w3.org/2000/svg'}
|
||||
|
||||
stats = {
|
||||
'ff0000_groups': 0, # Count of #FF0000 groups processed
|
||||
'other_red_groups': 0, # Count of other red-style groups processed
|
||||
'elements_modified': 0, # Total elements modified
|
||||
'modified': False # Whether file was modified
|
||||
}
|
||||
|
||||
# Process all group elements
|
||||
for g in root.findall('.//svg:g', namespaces):
|
||||
stroke = g.get('stroke', '').upper() # Normalize to uppercase for comparison
|
||||
|
||||
# Process #FF0000 red groups
|
||||
if stroke == "#FF0000":
|
||||
stats['ff0000_groups'] += 1
|
||||
|
||||
# Remove group attributes: stroke, stroke-width, stroke-linejoin
|
||||
for attr in ['stroke', 'stroke-width', 'stroke-linejoin']:
|
||||
if attr in g.attrib:
|
||||
del g.attrib[attr]
|
||||
stats['modified'] = True
|
||||
|
||||
# Modify path children: remove stroke-width, set new style
|
||||
for child in g.findall('.//svg:path', namespaces):
|
||||
if 'stroke-width' in child.attrib:
|
||||
del child.attrib['stroke-width']
|
||||
stats['modified'] = True
|
||||
|
||||
# Set new style for red stroke with 2px width
|
||||
child.set('style', 'stroke:#FF0000;stroke-width:2px')
|
||||
stats['elements_modified'] += 1
|
||||
stats['modified'] = True
|
||||
|
||||
# Process other groups with red color in style attributes
|
||||
else:
|
||||
# Process elements with style="stroke:#FF0000;"
|
||||
red_elements_found = False
|
||||
for child in g.findall('.//svg:*[@style]', namespaces):
|
||||
style = child.get('style', '')
|
||||
if 'stroke:#FF0000;' in style:
|
||||
red_elements_found = True
|
||||
|
||||
# Remove stroke-width attribute if exists
|
||||
if 'stroke-width' in child.attrib:
|
||||
del child.attrib['stroke-width']
|
||||
stats['modified'] = True
|
||||
|
||||
# Update the style attribute with standardized format
|
||||
child.set('style', 'stroke:#FF0000;stroke-width:2px;')
|
||||
stats['elements_modified'] += 1
|
||||
stats['modified'] = True
|
||||
|
||||
if red_elements_found:
|
||||
stats['other_red_groups'] += 1
|
||||
|
||||
# Save changes if modifications were made
|
||||
if stats['modified']:
|
||||
xml_str = ET.tostring(root, encoding='unicode')
|
||||
xml_str = xml_str.replace('><', '>\n<').replace('</svg>', '\n</svg>')
|
||||
|
||||
with open(xml_path, 'w', encoding='utf-8') as f:
|
||||
f.write(xml_str)
|
||||
|
||||
return stats
|
||||
|
||||
except Exception as e:
|
||||
print(f" Error processing file: {str(e)}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main processing function
|
||||
"""
|
||||
# Configure paths from environment variables
|
||||
json_path = os.environ.get("JSON_PATH_TEFWEICHE", "JSON")
|
||||
json_file_path = os.path.join(json_path, "omniflo_TEF_weichen_output.json")
|
||||
svg_folder_path = os.environ.get("SVG_PATH", "svg")
|
||||
|
||||
# Statistics for final report
|
||||
total_stats = {
|
||||
'files_processed': 0,
|
||||
'files_modified': 0,
|
||||
'total_ff0000_groups': 0,
|
||||
'total_other_red_groups': 0,
|
||||
'total_elements_modified': 0
|
||||
}
|
||||
|
||||
try:
|
||||
# Read and parse JSON file
|
||||
with open(json_file_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Verify we have a list of items
|
||||
if not isinstance(data, list):
|
||||
print("Error: JSON data should be an array of items")
|
||||
return
|
||||
|
||||
print(f"\nFound {len(data)} items in JSON file")
|
||||
print("Starting XML file processing...")
|
||||
print("=" * 60)
|
||||
|
||||
# Process each item in the JSON array
|
||||
for index, item in enumerate(data, 1):
|
||||
if not isinstance(item, dict):
|
||||
print(f"\nItem {index}: Not a dictionary, skipping")
|
||||
continue
|
||||
|
||||
sivasnr = item.get("Sivasnr")
|
||||
if not sivasnr:
|
||||
print(f"\nItem {index}: Missing 'Sivasnr' value, skipping")
|
||||
continue
|
||||
|
||||
print(f"\nProcessing item {index}: Sivasnr = {sivasnr}")
|
||||
|
||||
# Build XML filename and path
|
||||
xml_filename = f"{sivasnr}.xml"
|
||||
xml_path = os.path.join(svg_folder_path, xml_filename)
|
||||
|
||||
if not os.path.exists(xml_path):
|
||||
print(f" XML file not found: {xml_path}")
|
||||
continue
|
||||
|
||||
print(f" Found XML file: {xml_path}")
|
||||
total_stats['files_processed'] += 1
|
||||
|
||||
# Process the XML file
|
||||
stats = process_xml_file(xml_path)
|
||||
|
||||
if stats is None:
|
||||
print(" Processing failed")
|
||||
elif stats['modified']:
|
||||
print(" ✓ File successfully modified")
|
||||
total_stats['files_modified'] += 1
|
||||
total_stats['total_ff0000_groups'] += stats['ff0000_groups']
|
||||
total_stats['total_other_red_groups'] += stats['other_red_groups']
|
||||
total_stats['total_elements_modified'] += stats['elements_modified']
|
||||
|
||||
# Print detailed statistics for this file
|
||||
if stats['ff0000_groups'] > 0:
|
||||
print(f" - #FF0000 groups processed: {stats['ff0000_groups']}")
|
||||
if stats['other_red_groups'] > 0:
|
||||
print(f" - Other red style groups: {stats['other_red_groups']}")
|
||||
print(f" - Elements modified: {stats['elements_modified']}")
|
||||
else:
|
||||
print(" - No modifications needed (no red groups found)")
|
||||
|
||||
# Generate final comprehensive report
|
||||
print("\n" + "=" * 60)
|
||||
print("PROCESSING SUMMARY REPORT")
|
||||
print("=" * 60)
|
||||
print(f"Total files processed: {total_stats['files_processed']}")
|
||||
print(f"Total files modified: {total_stats['files_modified']}")
|
||||
print(f"Total #FF0000 groups processed: {total_stats['total_ff0000_groups']}")
|
||||
print(f"Total other red style groups: {total_stats['total_other_red_groups']}")
|
||||
print(f"Total elements modified: {total_stats['total_elements_modified']}")
|
||||
print("=" * 60)
|
||||
|
||||
except FileNotFoundError:
|
||||
print("\nError: JSON file not found at specified path")
|
||||
except json.JSONDecodeError:
|
||||
print("\nError: Invalid JSON format in input file")
|
||||
except Exception as e:
|
||||
print(f"\nUnexpected error: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("SVG XML Batch Modifier - Starting execution")
|
||||
print("Focus: Processing only red color groups (#FF0000)")
|
||||
main()
|
||||
@@ -0,0 +1,725 @@
|
||||
[
|
||||
{
|
||||
"Sivasnr": "834372002+0_BG090090",
|
||||
"ProfilTyp": "WEICHE S 45°-L-350/700, KPL. MIT P mit TEF Innen",
|
||||
"WeichenTyp": "Einzelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 350.129,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 496.396,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 320.7103,
|
||||
"TEFWeiche_center_line_height_mm": 722.5864,
|
||||
"OFWeiche_CP1_x_mm": 442.8527,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP2_x_mm": 92.8502,
|
||||
"OFWeiche_CP2_y_mm": 14.8776,
|
||||
"OFWeiche_CP4_x_mm": 442.8527,
|
||||
"OFWeiche_CP4_y_mm": 355.0010,
|
||||
"TEFWeiche_CPL1_x_mm": 342.8427,
|
||||
"TEFWeiche_CPL1_y_mm": 858.3085,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 85.7221,
|
||||
"KurvenRichtung": 1,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372005+0_BG090090",
|
||||
"ProfilTyp": "WEICHE S 45°-R-350/700, KPL. MIT P mit TEF Innen",
|
||||
"WeichenTyp": "Einzelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 350.129,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 496.396,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 320.7103,
|
||||
"TEFWeiche_center_line_height_mm": 722.5864,
|
||||
"OFWeiche_CP1_x_mm": 53.5437,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP3_x_mm": 403.6727,
|
||||
"OFWeiche_CP3_y_mm": 14.8776,
|
||||
"OFWeiche_CP4_x_mm": 53.5437,
|
||||
"OFWeiche_CP4_y_mm": 355.0010,
|
||||
"TEFWeiche_CPR1_x_mm": 153.5537,
|
||||
"TEFWeiche_CPR1_y_mm": 858.3085,
|
||||
"TEFWeiche_CPR2_x_mm": 474.264,
|
||||
"TEFWeiche_CPR2_y_mm": 85.7221,
|
||||
"KurvenRichtung": 2,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372008+0_BG190090",
|
||||
"ProfilTyp": "WEICHE S 45°-L-400/750, KPL. MIT P mit TEF Ihnen",
|
||||
"WeichenTyp": "Einzelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 400,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 492.626,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 316.9403,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 439.0827,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP2_x_mm": 39.0827,
|
||||
"OFWeiche_CP2_y_mm": 14.8776,
|
||||
"OFWeiche_CP4_x_mm": 439.8627,
|
||||
"OFWeiche_CP4_y_mm": 404.8776,
|
||||
"TEFWeiche_CPL1_x_mm": 339.0727,
|
||||
"TEFWeiche_CPL1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 139.3628,
|
||||
"KurvenRichtung": 1,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372011+0_BG190090",
|
||||
"ProfilTyp": "WEICHE S 45°-R-400/750, KPL. MIT P mit TEF Ihnen",
|
||||
"WeichenTyp": "Einzelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 400,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 492.626,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 316.9403,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 53.5437,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP3_x_mm": 453.5437,
|
||||
"OFWeiche_CP3_y_mm": 14.8776,
|
||||
"OFWeiche_CP4_x_mm": 53.5437,
|
||||
"OFWeiche_CP4_y_mm": 404.8776,
|
||||
"TEFWeiche_CPR1_x_mm": 153.5537,
|
||||
"TEFWeiche_CPR1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPR2_x_mm": 470.4940,
|
||||
"TEFWeiche_CPR2_y_mm": 139.3628,
|
||||
"KurvenRichtung": 2,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372028+0_BG080090",
|
||||
"ProfilTyp": "WEICHE S 90°-L-700/700, KPL. MIT P mit TEF Innen",
|
||||
"WeichenTyp": "Einzelweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.374,
|
||||
"OFWeiche_center_line_height_mm": 700.185,
|
||||
"Objekt_width_mm": 753.917,
|
||||
"Objekt_height_mm": 859.292,
|
||||
"TEFWeiche_center_line_width_mm": 599.685,
|
||||
"TEFWeiche_center_line_height_mm": 738.242,
|
||||
"OFWeiche_CP1_x_mm": 700.374,
|
||||
"OFWeiche_CP1_y_mm": 721.225,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 21.040,
|
||||
"OFWeiche_CP4_x_mm": 700.374,
|
||||
"OFWeiche_CP4_y_mm": 361.225,
|
||||
"TEFWeiche_CPL1_x_mm": 600.364,
|
||||
"TEFWeiche_CPL1_y_mm": 859.292,
|
||||
"TEFWeiche_CPL2_x_mm": 0,
|
||||
"TEFWeiche_CPL2_y_mm": 121.050,
|
||||
"KurvenRichtung": 1,
|
||||
"SivasnrTEF": "0_B10080+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372031+0_BG080090",
|
||||
"ProfilTyp": "WEICHE S 90°-R-700/700, KPL. MIT P mit TEF Innen",
|
||||
"WeichenTyp": "Einzelweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.374,
|
||||
"OFWeiche_center_line_height_mm": 700.185,
|
||||
"Objekt_width_mm": 753.917,
|
||||
"Objekt_height_mm": 859.67,
|
||||
"TEFWeiche_center_line_width_mm": 540.75,
|
||||
"TEFWeiche_center_line_height_mm": 738.62,
|
||||
"OFWeiche_CP1_x_mm": 53.544,
|
||||
"OFWeiche_CP1_y_mm": 721.225,
|
||||
"OFWeiche_CP3_x_mm": 753.9172,
|
||||
"OFWeiche_CP3_y_mm": 21.0400,
|
||||
"OFWeiche_CP4_x_mm": 53.544,
|
||||
"OFWeiche_CP4_y_mm": 361.25,
|
||||
"TEFWeiche_CPR1_x_mm": 153.554,
|
||||
"TEFWeiche_CPR1_y_mm": 859.67,
|
||||
"TEFWeiche_CPR2_x_mm": 694.3037,
|
||||
"TEFWeiche_CPR2_y_mm": 121.050,
|
||||
"KurvenRichtung": 2,
|
||||
"SivasnrTEF": "0_B10080+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG090090+834372101",
|
||||
"ProfilTyp": "WEICHE S D 45°-350/700, KPL. MIT P mit TEF links",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.258,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 807.859,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 320.7103,
|
||||
"TEFWeiche_center_line_height_mm": 772.5864,
|
||||
"OFWeiche_CP1_x_mm": 442.8527,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP2_x_mm": 92.7236,
|
||||
"OFWeiche_CP2_y_mm": 14.8778,
|
||||
"OFWeiche_CP3_x_mm": 792.9823,
|
||||
"OFWeiche_CP3_y_mm": 14.8778,
|
||||
"TEFWeiche_CPL1_x_mm": 342.8427,
|
||||
"TEFWeiche_CPL1_y_mm":858.309,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 85.7221,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372101+0_BG090090",
|
||||
"ProfilTyp": "WEICHE S D 45°-350/700, KPL. MIT P mit TEF rechts",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.258,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 807.859,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 320.7103,
|
||||
"TEFWeiche_center_line_height_mm": 772.5864,
|
||||
"OFWeiche_CP1_x_mm": 365.0067,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP2_x_mm": 14.8778,
|
||||
"OFWeiche_CP2_y_mm": 14.8778,
|
||||
"OFWeiche_CP3_x_mm": 715.1357,
|
||||
"OFWeiche_CP3_y_mm": 14.8778,
|
||||
"TEFWeiche_CPR1_x_mm": 465.0167,
|
||||
"TEFWeiche_CPR1_y_mm": 858.3085,
|
||||
"TEFWeiche_CPR2_x_mm": 785.7270,
|
||||
"TEFWeiche_CPR2_y_mm": 85.7221,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG090090+834372101+0_BG090090",
|
||||
"ProfilTyp": "WEICHE S D 45°-350/700, KPL. MIT P mit TEF beideseitig",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.258,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 885.705,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 841.4406,
|
||||
"TEFWeiche_center_line_height_mm": 772.5864,
|
||||
"OFWeiche_CP1_x_mm": 442.8527,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP2_x_mm": 92.7236,
|
||||
"OFWeiche_CP2_y_mm": 14.8778,
|
||||
"OFWeiche_CP3_x_mm": 792.9823,
|
||||
"OFWeiche_CP3_y_mm": 14.8778,
|
||||
"TEFWeiche_CPL1_x_mm": 342.8427,
|
||||
"TEFWeiche_CPL1_y_mm": 858.309,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 85.7221,
|
||||
"TEFWeiche_CPR1_x_mm": 542.8627,
|
||||
"TEFWeiche_CPR1_y_mm": 858.3085,
|
||||
"TEFWeiche_CPR2_x_mm": 863.5730,
|
||||
"TEFWeiche_CPR2_y_mm": 85.7221,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10090+0_B10090+0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG190090+834372104",
|
||||
"ProfilTyp": "WEICHE S D 45°-400/750, KPL. MIT P mit TEF links",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 800.0,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 853.96,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 316.9403,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 439.0827,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP2_x_mm": 39.0827,
|
||||
"OFWeiche_CP2_y_mm": 14.8775,
|
||||
"OFWeiche_CP3_x_mm": 839.0827,
|
||||
"OFWeiche_CP3_y_mm": 14.8775,
|
||||
"TEFWeiche_CPL1_x_mm": 339.0727,
|
||||
"TEFWeiche_CPL1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 139.3628,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372104+0_BG190090",
|
||||
"ProfilTyp": "WEICHE S D 45°-400/750, KPL. MIT P mit TEF rechts",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 800.0,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 853.96,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 316.9403,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 414.8776,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP2_x_mm": 14.8775,
|
||||
"OFWeiche_CP2_y_mm": 14.8775,
|
||||
"OFWeiche_CP3_x_mm": 814.8776,
|
||||
"OFWeiche_CP3_y_mm": 14.8775,
|
||||
"TEFWeiche_CPR1_x_mm": 414.8776,
|
||||
"TEFWeiche_CPR1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPR2_x_mm": 831.8279,
|
||||
"TEFWeiche_CPR2_y_mm": 139.3628,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG190090+834372104+0_BG190090",
|
||||
"ProfilTyp": "WEICHE S D 45°-400/750, KPL. MIT P mit TEF beideseitig",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 800.0,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 878.165,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 833.9006,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 439.0827,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP2_x_mm": 39.0827,
|
||||
"OFWeiche_CP2_y_mm": 14.8775,
|
||||
"OFWeiche_CP3_x_mm": 839.0827,
|
||||
"OFWeiche_CP3_y_mm": 14.8775,
|
||||
"TEFWeiche_CPL1_x_mm": 339.0727,
|
||||
"TEFWeiche_CPL1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 139.3628,
|
||||
"TEFWeiche_CPR1_x_mm": 539.0927,
|
||||
"TEFWeiche_CPR1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPR2_x_mm": 856.0330,
|
||||
"TEFWeiche_CPR2_y_mm": 139.3628,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10090+0_B10090+0_B10090+0_B10090"
|
||||
},
|
||||
|
||||
{
|
||||
"Sivasnr": "0_BG080090+834372110",
|
||||
"ProfilTyp": "WEICHE S D 90°-700/700, KPL. MIT P mit TEF links",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1400.739,
|
||||
"OFWeiche_center_line_height_mm": 700.176,
|
||||
"Objekt_width_mm": 1400.739,
|
||||
"Objekt_height_mm": 859.292,
|
||||
"TEFWeiche_center_line_width_mm": 599.685,
|
||||
"TEFWeiche_center_line_height_mm": 738.242,
|
||||
"OFWeiche_CP1_x_mm": 700.370,
|
||||
"OFWeiche_CP1_y_mm": 721.216,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 21.040,
|
||||
"OFWeiche_CP3_x_mm": 400.739,
|
||||
"OFWeiche_CP3_y_mm": 21.040,
|
||||
"TEFWeiche_CPL1_x_mm": 600.360,
|
||||
"TEFWeiche_CPL1_y_mm": 859.292,
|
||||
"TEFWeiche_CPL2_x_mm": 0,
|
||||
"TEFWeiche_CPL2_y_mm": 121.050,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10080+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372110+0_BG080090",
|
||||
"ProfilTyp": "WEICHE S D 90°-700/700, KPL. MIT P mit TEF rechts",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1400.739,
|
||||
"OFWeiche_center_line_height_mm": 700.176,
|
||||
"Objekt_width_mm": 1400.739,
|
||||
"Objekt_height_mm": 859.67,
|
||||
"TEFWeiche_center_line_width_mm": 540.750,
|
||||
"TEFWeiche_center_line_height_mm": 738.620,
|
||||
"OFWeiche_CP1_x_mm": 700.370,
|
||||
"OFWeiche_CP1_y_mm": 721.216,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 21.040,
|
||||
"OFWeiche_CP3_x_mm": 400.739,
|
||||
"OFWeiche_CP3_y_mm": 21.040,
|
||||
"TEFWeiche_CPR1_x_mm": 800.380,
|
||||
"TEFWeiche_CPR1_y_mm": 859.67,
|
||||
"TEFWeiche_CPR2_x_mm": 1341.130,
|
||||
"TEFWeiche_CPR2_y_mm": 121.050,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10090+0_B10080"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG080090+834372110+0_BG080090",
|
||||
"ProfilTyp": "WEICHE S D 90°-700/700, KPL. MIT P mit TEF beideseitig",
|
||||
"WeichenTyp": "Doppelweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1400.739,
|
||||
"OFWeiche_center_line_height_mm": 700.176,
|
||||
"Objekt_width_mm": 1400.739,
|
||||
"Objekt_height_mm": 859.67,
|
||||
"TEFWeiche_center_line_width_mm": 1340.4546,
|
||||
"TEFWeiche_center_line_height_mm": 738.6200,
|
||||
"OFWeiche_CP1_x_mm": 700.370,
|
||||
"OFWeiche_CP1_y_mm": 721.216,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 21.040,
|
||||
"OFWeiche_CP3_x_mm": 400.739,
|
||||
"OFWeiche_CP3_y_mm": 21.040,
|
||||
"TEFWeiche_CPL1_x_mm": 600.360,
|
||||
"TEFWeiche_CPL1_y_mm": 859.292,
|
||||
"TEFWeiche_CPL2_x_mm": 0,
|
||||
"TEFWeiche_CPL2_y_mm": 121.050,
|
||||
"TEFWeiche_CPR1_x_mm": 800.380,
|
||||
"TEFWeiche_CPR1_y_mm": 859.67,
|
||||
"TEFWeiche_CPR2_x_mm": 1341.130,
|
||||
"TEFWeiche_CPR2_y_mm": 121.050,
|
||||
"KurvenRichtung": 3,
|
||||
"SivasnrTEF": "0_B10080+0_B10090+0_B10080+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG090090+834372201",
|
||||
"ProfilTyp": "WEICHE S T 45°-350/700, KPL. MIT P mit TEF links",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.258,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 807.859,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 320.7103,
|
||||
"TEFWeiche_center_line_height_mm": 772.5864,
|
||||
"OFWeiche_CP1_x_mm": 442.8527,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP2_x_mm": 92.7236,
|
||||
"OFWeiche_CP2_y_mm": 14.8778,
|
||||
"OFWeiche_CP3_x_mm": 792.9823,
|
||||
"OFWeiche_CP3_y_mm": 14.8778,
|
||||
"TEFWeiche_CPL1_x_mm": 342.8427,
|
||||
"TEFWeiche_CPL1_y_mm":858.309,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 85.7221,
|
||||
"OFWeiche_CP4_x_mm": 442.8527,
|
||||
"OFWeiche_CP4_y_mm": 355.0010,
|
||||
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372201+0_BG090090",
|
||||
"ProfilTyp": "WEICHE S T 45°-350/700, KPL. MIT P mit TEF rechts",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.258,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 807.859,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 320.7103,
|
||||
"TEFWeiche_center_line_height_mm": 772.5864,
|
||||
"OFWeiche_CP1_x_mm": 365.0067,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP2_x_mm": 14.8778,
|
||||
"OFWeiche_CP2_y_mm": 14.8778,
|
||||
"OFWeiche_CP3_x_mm": 715.1357,
|
||||
"OFWeiche_CP3_y_mm": 14.8778,
|
||||
"TEFWeiche_CPR1_x_mm": 465.0167,
|
||||
"TEFWeiche_CPR1_y_mm": 858.3085,
|
||||
"TEFWeiche_CPR2_x_mm": 785.7270,
|
||||
"TEFWeiche_CPR2_y_mm": 85.7221,
|
||||
"OFWeiche_CP4_x_mm": 442.8527,
|
||||
"OFWeiche_CP4_y_mm": 355.0010,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG090090+834372201+0_BG090090",
|
||||
"ProfilTyp": "WEICHE S T 45°-350/700, KPL. MIT P mit TEF beideseitig",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 700.258,
|
||||
"OFWeiche_center_line_height_mm": 700.123,
|
||||
"Objekt_width_mm": 885.705,
|
||||
"Objekt_height_mm": 858.309,
|
||||
"TEFWeiche_center_line_width_mm": 841.4406,
|
||||
"TEFWeiche_center_line_height_mm": 772.5864,
|
||||
"OFWeiche_CP1_x_mm": 442.8527,
|
||||
"OFWeiche_CP1_y_mm": 715.0010,
|
||||
"OFWeiche_CP2_x_mm": 92.7236,
|
||||
"OFWeiche_CP2_y_mm": 14.8778,
|
||||
"OFWeiche_CP3_x_mm": 792.9823,
|
||||
"OFWeiche_CP3_y_mm": 14.8778,
|
||||
"TEFWeiche_CPL1_x_mm": 342.8427,
|
||||
"TEFWeiche_CPL1_y_mm": 858.309,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 85.7221,
|
||||
"TEFWeiche_CPR1_x_mm": 542.8627,
|
||||
"TEFWeiche_CPR1_y_mm": 858.3085,
|
||||
"TEFWeiche_CPR2_x_mm": 863.5730,
|
||||
"TEFWeiche_CPR2_y_mm": 85.7221,
|
||||
"OFWeiche_CP4_x_mm": 442.8527,
|
||||
"OFWeiche_CP4_y_mm": 355.0010,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10090+0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG190090+834372204",
|
||||
"ProfilTyp": "WEICHE S T 45°-400/750, KPL. MIT P mit TEF links",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 800.0,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 853.96,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 316.9403,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 439.0827,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP2_x_mm": 39.0827,
|
||||
"OFWeiche_CP2_y_mm": 14.8775,
|
||||
"OFWeiche_CP3_x_mm": 839.0827,
|
||||
"OFWeiche_CP3_y_mm": 14.8775,
|
||||
"TEFWeiche_CPL1_x_mm": 339.0727,
|
||||
"TEFWeiche_CPL1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 139.3628,
|
||||
"OFWeiche_CP4_x_mm": 439.0827,
|
||||
"OFWeiche_CP4_y_mm": 404.8776,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372204+0_BG190090",
|
||||
"ProfilTyp": "WEICHE S T 45°-400/750, KPL. MIT P mit TEF rechts",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 800.0,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 853.96,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 316.9403,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 414.8776,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP2_x_mm": 14.8775,
|
||||
"OFWeiche_CP2_y_mm": 14.8775,
|
||||
"OFWeiche_CP3_x_mm": 814.8776,
|
||||
"OFWeiche_CP3_y_mm": 14.8775,
|
||||
"TEFWeiche_CPR1_x_mm": 414.8776,
|
||||
"TEFWeiche_CPR1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPR2_x_mm": 831.8279,
|
||||
"TEFWeiche_CPR2_y_mm": 139.3628,
|
||||
"OFWeiche_CP4_x_mm": 414.8776,
|
||||
"OFWeiche_CP4_y_mm": 404.8776,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG190090+834372204+0_BG190090",
|
||||
"ProfilTyp": "WEICHE S T 45°-400/750, KPL. MIT P mit TEF beideseitig",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 45,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 800.0,
|
||||
"OFWeiche_center_line_height_mm": 750,
|
||||
"Objekt_width_mm": 878.165,
|
||||
"Objekt_height_mm": 903.949,
|
||||
"TEFWeiche_center_line_width_mm": 833.9006,
|
||||
"TEFWeiche_center_line_height_mm": 764.5864,
|
||||
"OFWeiche_CP1_x_mm": 439.0827,
|
||||
"OFWeiche_CP1_y_mm": 764.8776,
|
||||
"OFWeiche_CP2_x_mm": 39.0827,
|
||||
"OFWeiche_CP2_y_mm": 14.8775,
|
||||
"OFWeiche_CP3_x_mm": 839.0827,
|
||||
"OFWeiche_CP3_y_mm": 14.8775,
|
||||
"TEFWeiche_CPL1_x_mm": 339.0727,
|
||||
"TEFWeiche_CPL1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPL2_x_mm": 22.1324,
|
||||
"TEFWeiche_CPL2_y_mm": 139.3628,
|
||||
"TEFWeiche_CPR1_x_mm": 539.0927,
|
||||
"TEFWeiche_CPR1_y_mm": 903.9492,
|
||||
"TEFWeiche_CPR2_x_mm": 856.0330,
|
||||
"TEFWeiche_CPR2_y_mm": 139.3628,
|
||||
"OFWeiche_CP4_x_mm": 439.0827,
|
||||
"OFWeiche_CP4_y_mm": 404.8776,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10090+0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG080090+834372210",
|
||||
"ProfilTyp": "WEICHE S T 90°-700/700, KPL. MIT P mit TEF links",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1400.739,
|
||||
"OFWeiche_center_line_height_mm": 700.176,
|
||||
"Objekt_width_mm": 1400.739,
|
||||
"Objekt_height_mm": 859.292,
|
||||
"TEFWeiche_center_line_width_mm": 599.6846,
|
||||
"TEFWeiche_center_line_height_mm": 738.2422,
|
||||
"OFWeiche_CP1_x_mm": 700.370,
|
||||
"OFWeiche_CP1_y_mm": 721.216,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 21.040,
|
||||
"OFWeiche_CP3_x_mm": 400.739,
|
||||
"OFWeiche_CP3_y_mm": 21.040,
|
||||
"OFWeiche_CP4_x_mm": 700.370,
|
||||
"OFWeiche_CP4_y_mm": 361.216,
|
||||
"TEFWeiche_CPL1_x_mm": 600.360,
|
||||
"TEFWeiche_CPL1_y_mm": 859.292,
|
||||
"TEFWeiche_CPL2_x_mm": 0,
|
||||
"TEFWeiche_CPL2_y_mm": 121.050,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10080+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372210+0_BG080090",
|
||||
"ProfilTyp": "WEICHE S T 90°-700/700, KPL. MIT P mit TEF rechts",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1400.739,
|
||||
"OFWeiche_center_line_height_mm": 700.176,
|
||||
"Objekt_width_mm": 1400.739,
|
||||
"Objekt_height_mm": 859.67,
|
||||
"TEFWeiche_center_line_width_mm": 540.750,
|
||||
"TEFWeiche_center_line_height_mm": 738.6200,
|
||||
"OFWeiche_CP1_x_mm": 700.370,
|
||||
"OFWeiche_CP1_y_mm": 721.216,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 21.040,
|
||||
"OFWeiche_CP3_x_mm": 400.739,
|
||||
"OFWeiche_CP3_y_mm": 21.040,
|
||||
"OFWeiche_CP4_x_mm": 700.370,
|
||||
"OFWeiche_CP4_y_mm": 361.216,
|
||||
"TEFWeiche_CPR1_x_mm": 800.380,
|
||||
"TEFWeiche_CPR1_y_mm": 859.67,
|
||||
"TEFWeiche_CPR2_x_mm": 1341.130,
|
||||
"TEFWeiche_CPR2_y_mm": 121.050,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10080"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG080090+834372210+0_BG080090",
|
||||
"ProfilTyp": "WEICHE S T 90°-700/700, KPL. MIT P mit TEF beideseitig",
|
||||
"WeichenTyp": "Dreiwegeweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1400.739,
|
||||
"OFWeiche_center_line_height_mm": 700.176,
|
||||
"Objekt_width_mm": 1400.739,
|
||||
"Objekt_height_mm": 859.67,
|
||||
"TEFWeiche_center_line_width_mm": 1340.4546,
|
||||
"TEFWeiche_center_line_height_mm": 738.6200,
|
||||
"OFWeiche_CP1_x_mm": 700.370,
|
||||
"OFWeiche_CP1_y_mm": 721.216,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 21.040,
|
||||
"OFWeiche_CP3_x_mm": 400.739,
|
||||
"OFWeiche_CP3_y_mm": 21.040,
|
||||
"OFWeiche_CP4_x_mm": 700.370,
|
||||
"OFWeiche_CP4_y_mm": 361.216,
|
||||
"TEFWeiche_CPL1_x_mm": 600.360,
|
||||
"TEFWeiche_CPL1_y_mm": 859.292,
|
||||
"TEFWeiche_CPL2_x_mm": 0,
|
||||
"TEFWeiche_CPL2_y_mm": 121.050,
|
||||
"TEFWeiche_CPR1_x_mm": 800.380,
|
||||
"TEFWeiche_CPR1_y_mm": 859.67,
|
||||
"TEFWeiche_CPR2_x_mm": 1341.130,
|
||||
"TEFWeiche_CPR2_y_mm": 121.050,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10080+0_B10090+0_B10080+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG071090+834372404+0_BG071090",
|
||||
"ProfilTyp": "WEICHE S C DELTA 1600/800, KPL. MIT P mit TEF beideseitig",
|
||||
"WeichenTyp": "Dreifachweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1600.384,
|
||||
"OFWeiche_center_line_height_mm": 800.266,
|
||||
"Objekt_width_mm": 1878.94,
|
||||
"Objekt_height_mm": 994.044,
|
||||
"TEFWeiche_center_line_width_mm": 1878.94,
|
||||
"TEFWeiche_center_line_height_mm": 838.62,
|
||||
"OFWeiche_CP1_x_mm": 938.630,
|
||||
"OFWeiche_CP1_y_mm": 800.266,
|
||||
"OFWeiche_CP2_x_mm": 138.5055,
|
||||
"OFWeiche_CP2_y_mm": 53.5437,
|
||||
"OFWeiche_CP3_x_mm": 1738.8898,
|
||||
"OFWeiche_CP3_y_mm": 53.5437,
|
||||
"TEFWeiche_CPL1_x_mm": 838.6200,
|
||||
"TEFWeiche_CPL1_y_mm": 994.0437,
|
||||
"TEFWeiche_CPL2_x_mm": 0,
|
||||
"TEFWeiche_CPL2_y_mm": 153.5537,
|
||||
"TEFWeiche_CPR1_x_mm": 1038.6400,
|
||||
"TEFWeiche_CPR1_y_mm": 994.0437,
|
||||
"TEFWeiche_CPR2_x_mm": 1878.9400,
|
||||
"TEFWeiche_CPR2_y_mm": 153.5537,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10071+0_B10090+0_B10090+0_B10071+0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "0_BG071090+834372404",
|
||||
"ProfilTyp": "WEICHE S C DELTA 1600/800, KPL. MIT P mit TEF links",
|
||||
"WeichenTyp": "Dreifachweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1600.384,
|
||||
"OFWeiche_center_line_height_mm": 800.266,
|
||||
"Objekt_width_mm": 1878.9400,
|
||||
"Objekt_height_mm": 994.0437,
|
||||
"TEFWeiche_center_line_width_mm": 840.49,
|
||||
"TEFWeiche_center_line_height_mm": 838.62,
|
||||
"OFWeiche_CP1_x_mm": 938.630,
|
||||
"OFWeiche_CP1_y_mm": 853.8099,
|
||||
"OFWeiche_CP2_x_mm": 138.5055,
|
||||
"OFWeiche_CP2_y_mm": 53.5437,
|
||||
"OFWeiche_CP3_x_mm": 1738.8898,
|
||||
"OFWeiche_CP3_y_mm": 53.5437,
|
||||
"TEFWeiche_CPL1_x_mm": 838.6200,
|
||||
"TEFWeiche_CPL1_y_mm": 994.0437,
|
||||
"TEFWeiche_CPL2_x_mm": 0,
|
||||
"TEFWeiche_CPL2_y_mm": 153.5537,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10071+0_B10090+0_B10090"
|
||||
},
|
||||
{
|
||||
"Sivasnr": "834372404+0_BG071090",
|
||||
"ProfilTyp": "WEICHE S C DELTA 1600/800, KPL. MIT P mit TEF rechts",
|
||||
"WeichenTyp": "Dreifachweiche",
|
||||
"KurvenWinkel": 90,
|
||||
"Schaltungstyp": "P",
|
||||
"OFWeiche_center_line_width_mm": 1600.384,
|
||||
"OFWeiche_center_line_height_mm": 800.266,
|
||||
"Objekt_width_mm": 1740.435,
|
||||
"Objekt_height_mm": 992.364,
|
||||
"TEFWeiche_center_line_width_mm": 840.3,
|
||||
"TEFWeiche_center_line_height_mm": 838.81,
|
||||
"OFWeiche_CP1_x_mm": 800.1245,
|
||||
"OFWeiche_CP1_y_mm": 853.8099,
|
||||
"OFWeiche_CP2_x_mm": 0,
|
||||
"OFWeiche_CP2_y_mm": 53.5437,
|
||||
"OFWeiche_CP3_x_mm": 1600.384,
|
||||
"OFWeiche_CP3_y_mm": 53.5437,
|
||||
"TEFWeiche_CPR1_x_mm": 900.1345,
|
||||
"TEFWeiche_CPR1_y_mm": 992.3637,
|
||||
"TEFWeiche_CPR2_x_mm": 1740.435,
|
||||
"TEFWeiche_CPR2_y_mm": 153.5537,
|
||||
"KurvenRichtung": 7,
|
||||
"SivasnrTEF": "0_B10090+0_B10090+0_B10071"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user