Die Code zur automatischen Erzeungung der SVG für OFWeiche wurde funitoniert.

This commit is contained in:
2025-07-16 15:52:47 +02:00
parent 489eaac2c5
commit 352f6b89be
98 changed files with 1895 additions and 1152 deletions
@@ -6,22 +6,22 @@
</clipPath>
</defs>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,0,0)" stroke-width="0.1" >
<polyline points="234.221,411.135 234.221,423.963 " />
<polyline points="441.683,203.67 454.511,203.67 " />
<polyline points="448.097,232.966 448.097,203.67 " />
<polyline points="661.974,417.549 234.221,417.549 " />
<polyline points="529.124,346.218 529.124,341.979 " />
<polyline points="460.574,414.768 456.335,414.768 " />
<polyline points="458.454,405.088 458.454,414.768 " />
<polyline points="387.785,344.098 529.124,344.098 " />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,255,255)" stroke-width="0.1" >
<path d="M348.443,382.21 A122.175,122.175 0 0,0 412.764,317.89 " stroke-dasharray="8.988326,0.998703,1.997406,0.998703,1.997406,0.998703" />
<path d="M483.431,317.89 A122.175,122.175 0 0,0 547.751,382.21 " stroke-dasharray="8.988326,0.998703,1.997406,0.998703,1.997406,0.998703" />
<path d="M491.382,355.775 A40.3692,40.3692 0 0,0 470.129,377.028 " stroke-dasharray="2.969937,0.329993,0.659986,0.329993,0.659986,0.329993" />
<path d="M446.779,377.028 A40.3692,40.3692 0 0,0 425.526,355.775 " stroke-dasharray="2.969937,0.329993,0.659986,0.329993,0.659986,0.329993" />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,0,0)" stroke-width="0.1" >
<polyline points="412.764,317.89 448.097,232.966 " />
<polyline points="348.443,382.21 263.508,417.549 " />
<polyline points="483.431,317.89 448.097,232.966 " />
<polyline points="547.751,382.21 632.686,417.549 " />
<polyline points="661.974,411.135 661.974,423.963 " />
<polyline points="238.933,433.903 238.933,417.549 " />
<polyline points="657.261,433.903 657.261,417.549 " />
<polyline points="470.129,377.028 458.454,405.088 " />
<polyline points="491.382,355.775 519.447,344.098 " />
<polyline points="446.779,377.028 458.454,405.088 " />
<polyline points="425.526,355.775 397.462,344.098 " />
<polyline points="387.785,346.218 387.785,341.979 " />
<polyline points="527.567,338.694 527.567,344.098 " />
<polyline points="389.342,338.694 389.342,344.098 " />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -6,34 +6,34 @@
</clipPath>
</defs>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,0,0)" stroke-width="0.1" >
<polyline points="362.45,379.299 685.686,379.299 " stroke-dasharray="4.953036,0.990607,0.990607,0.990607" />
<polyline points="643.608,362.609 395.402,362.609 " stroke-dasharray="3.803322,0.760664,0.760664,0.760664" />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,255,255)" stroke-width="0.1" >
<polyline points="610.154,355.939 608.335,355.185 " stroke-dasharray="5.943643,0.660405,1.320810,0.660405,1.320810,0.660405" />
<polyline points="453.401,380.547 454.798,381.125 " stroke-dasharray="4.563987,0.507110,1.014219,0.507110,1.014219,0.507110" />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,0,0)" stroke-width="0.1" >
<polyline points="524.081,217.666 524.081,237.01 " stroke-dasharray="4.953036,0.990607,0.990607,0.990607" />
<polyline points="519.494,486.723 519.494,471.87 " stroke-dasharray="3.803322,0.760664,0.760664,0.760664" />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,255,255)" stroke-width="0.1" >
<polyline points="437.981,355.912 439.847,355.139 " stroke-dasharray="5.943643,0.660405,1.320810,0.660405,1.320810,0.660405" />
<polyline points="547.442,293.199 548.216,295.066 " stroke-dasharray="5.943643,0.660405,1.320810,0.660405,1.320810,0.660405" />
<polyline points="500.72,293.199 499.966,295.019 " stroke-dasharray="5.943643,0.660405,1.320810,0.660405,1.320810,0.660405" />
<polyline points="585.609,380.568 584.176,381.161 " stroke-dasharray="4.563987,0.507110,1.014219,0.507110,1.014219,0.507110" />
<polyline points="501.556,428.723 500.962,427.289 " stroke-dasharray="4.563987,0.507110,1.014219,0.507110,1.014219,0.507110" />
<polyline points="537.433,428.723 538.012,427.325 " stroke-dasharray="4.563987,0.507110,1.014219,0.507110,1.014219,0.507110" />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,0,0)" stroke-width="0.1" >
<polyline points="528.323,217.666 519.84,217.666 " />
<polyline points="516.238,486.723 522.751,486.723 " />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,255,255)" stroke-width="0.1" >
<path d="M548.216,295.066 A111.086,111.086 0 0,0 608.335,355.185 " stroke-dasharray="5.943643,0.660405,1.320810,0.660405,1.320810,0.660405" />
<path d="M439.847,355.139 A111.086,111.086 0 0,0 499.966,295.019 " stroke-dasharray="5.943643,0.660405,1.320810,0.660405,1.320810,0.660405" />
<path d="M500.962,427.289 A85.3002,85.3002 0 0,0 454.798,381.125 " stroke-dasharray="4.563987,0.507110,1.014219,0.507110,1.014219,0.507110" />
<path d="M584.176,381.161 A85.3002,85.3002 0 0,0 538.012,427.325 " stroke-dasharray="4.563987,0.507110,1.014219,0.507110,1.014219,0.507110" />
</g>
<g clip-path="url(#clipId0)" fill="none" stroke="rgb(0,0,0)" stroke-width="0.1" >
<polyline points="500.72,293.199 524.081,237.01 " />
<polyline points="547.442,293.199 524.081,237.01 " />
<polyline points="362.45,375.057 362.45,383.54 " />
<polyline points="685.686,375.196 685.686,383.679 " />
<polyline points="437.981,355.912 381.73,379.299 " />
<polyline points="610.154,355.939 666.341,379.299 " />
<polyline points="365.566,390.113 365.566,379.299 " />
<polyline points="682.568,390.14 682.57,379.326 " />
<polyline points="537.433,428.723 519.494,471.87 " />
<polyline points="501.556,428.723 519.494,471.87 " />
<polyline points="643.608,365.866 643.608,359.352 " />
<polyline points="395.402,365.759 395.402,359.246 " />
<polyline points="585.609,380.568 628.803,362.609 " />
<polyline points="453.401,380.547 410.257,362.609 " />
<polyline points="641.215,354.305 641.215,362.609 " />
<polyline points="397.796,354.284 397.795,362.588 " />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,25 @@
@echo off
call setenv.bat
setlocal
:: Check if Python is available
where python >nul 2>&1
if %ERRORLEVEL% neq 0 (
echo Error: Python is not found in your PATH
pause
exit /b 1
)
:: Run the Python script
echo Running omnfilo weichen 2D...
echo calculations to standardize the dimensions and add connection points...
echo update dimensions_and_connection_points_in_props...
echo "[DEBUG] OFWeiche_PATH: %OFWeiche_PATH%"
echo "[DEBUG] PROPS_PATH: %PROPS_PATH%"
echo "[DEBUG] JSON_PATH: %JSON_PATH%"
python %OFWeiche_PATH%\01_props_step1_omniflo_weichen.py
python %OFWeiche_PATH%\01_props_step2_calculations_to_standardize_the_dimensions_and_add_connection_points.py
python %OFWeiche_PATH%\01_props_step3_update_dimensions_and_connection_points_in_props.py
pause
@@ -34,10 +34,14 @@ if %ERRORLEVEL% equ 2 set "arg=--tefbogen"
if %ERRORLEVEL% equ 3 set "arg=--weichen"
if %ERRORLEVEL% equ 4 set "arg=--tefweichen"
REM Execute Python script with selected argument
python %RD_CONF_LIB%\3_svg_optimizer_Step1.py %*
python %RD_CONF_LIB%\3_svg_scaler_Step2.py %*
python %RD_CONF_LIB%\3_svg_scaler_Step3.py %*
python %OFWeiche_PATH%\02_svg_step1_convert_polylines_to_lines.py %arg%
python %OFWeiche_PATH%\02_svg_step2_find_and_mark_auxiliary_lines.py %*
python %OFWeiche_PATH%\02_svg_step3_scaler.py %*
python %OFWeiche_PATH%\02_svg_step4_format_optimization.py %*
python %OFWeiche_PATH%\02_svg_step5_automatic_svg_generation_for_P_switches.py %*
REM Check execution status
if %ERRORLEVEL% equ 0 (
echo SVG optimization completed successfully!
@@ -13,9 +13,11 @@ if %ERRORLEVEL% neq 0 (
:: Run the Python script
echo Running SVG optimizer...
python %RD_CONF_LIB%\3_svg_optimizer_Step1.py %*
python %RD_CONF_LIB%\3_svg_scaler_Step2.py %*
python %RD_CONF_LIB%\3_svg_scaler_Step3.py %*
python %OFWeiche_PATH%\02_svg_step1_convert_polylines_to_lines.py %arg%
python %OFWeiche_PATH%\02_svg_step2_find_and_mark_auxiliary_lines.py %*
python %OFWeiche_PATH%\02_svg_step3_scaler.py %*
python %OFWeiche_PATH%\02_svg_step4_format_optimization.py %*
python %OFWeiche_PATH%\02_svg_step5_automatic_svg_generation_for_P_switches.py %*
:: Check if Python script succeeded
if %ERRORLEVEL% equ 0 (
echo SVG optimization completed successfully
@@ -0,0 +1,23 @@
@echo off
call setenv.bat
setlocal
:: Check if Python is available
where python >nul 2>&1
if %ERRORLEVEL% neq 0 (
echo Error: Python is not found in your PATH
pause
exit /b 1
)
:: Run the Python script
echo Running convert svgs to xml and update xml path in Props...
echo "[DEBUG] OFWeiche_PATH: %OFWeiche_PATH%"
echo "[DEBUG] PROPS_PATH: %PROPS_PATH%"
echo "[DEBUG] SVG_PATH: %SVG_PATH%"
echo "[DEBUG] RD_CONF_OUTPUT: %RD_CONF_OUTPUT%"
python %OFWeiche_PATH%\03_convert_svgs_to_xml_and_update_xml_path_in_props.py
pause
@@ -0,0 +1,13 @@
@echo off
setlocal
echo Copy operation:
echo Source folder: C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG
echo Destination folder: C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\Editor2DLibrary\SSG
echo/
choice /c YN /m "Confirm overwrite? (Y/N)"
if errorlevel 2 exit /b
robocopy "C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG" "C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\Editor2DLibrary\SSG" /E /COPY:DAT /IS /NP
echo Operation complete!
pause
+8 -1
View File
@@ -6,10 +6,17 @@ set RD_CONF=%cd%
set RD_CONF_BIN=%RD_CONF%\bin
set RD_CONF_CFG=%RD_CONF%\cfg
set RD_CONF_WORK=%RD_CONF%\work
set RD_CONF_OUTPUT=%RD_CONF%\Weichen\outputdir
set RD_CONF_OUTPUT_OFWEICHEN=%RD_CONF%\Weichen\outputdir
set RD_CONF_LIB=%RD_CONF%\lib
set "OFWeiche_PATH=%RD_CONF%\lib\OFWeiche"
set "PROPS_PATH=C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\props"
set "SVG_PATH=C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\svg"
set "JSON_PATH=%OFWeiche_PATH%\json"
set RD_CONF_BOGEN=%RD_CONF%\Bogen
set RD_CONF_TEFBOGEN=%RD_CONF%\TEFBogen
set RD_CONF_WEICHEN=%RD_CONF%\Weichen\neu_original_backup
@@ -16,7 +16,7 @@ def modify_json_values(json_file):
process_einzelweiche_items(data, WeichenKoerperWidth, WeichenkProfileWidth, BogenProfileWidth, WeichenGerade)
process_doppelweiche_items(data, BogenProfileWidth, WeichenGerade)
process_deltaweiche_items(data, WeichenkProfileWidth)
process_sternweiche_items(data)
# Save changes without confirmation
with open(json_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
@@ -219,9 +219,7 @@ def process_doppelweiche_items(data, BogenProfileWidth, WeichenGerade):
item["OFWeiche_CP1_y_mm"] = round(item["Objekt_height_mm"], 3)
item["OFWeiche_CP2_x_mm"] = round(BogenProfileWidth/2 * math.cos(angle_rad), 3)
item["OFWeiche_CP2_y_mm"] = round(BogenProfileWidth/2 * math.sin(angle_rad), 3)
item["OFWeiche_CP3_x_mm"] = round(
BogenProfileWidth/2 * math.cos(angle_rad) +
item["OFWeiche_center_line_width_mm"], 3)
item["OFWeiche_CP3_x_mm"] = round(BogenProfileWidth/2 * math.cos(angle_rad) + item["OFWeiche_center_line_width_mm"], 3)
item["OFWeiche_CP3_y_mm"] = item["OFWeiche_CP2_y_mm"]
# Update items with identical ProfilTyp
@@ -368,10 +366,10 @@ def process_deltaweiche_items(data, WeichenkProfileWidth):
# Calculate control points
item["OFWeiche_CP1_x_mm"] = round(item["Objekt_width_mm"]/2, 3)
item["OFWeiche_CP1_y_mm"] = 0
item["OFWeiche_CP1_y_mm"] = round(item["Objekt_height_mm"], 3)
item["OFWeiche_CP2_x_mm"] = 0
item["OFWeiche_CP2_y_mm"] = round(item["OFWeiche_center_line_height_mm"], 3)
item["OFWeiche_CP3_x_mm"] = round(item["OFWeiche_center_line_width_mm"], 3)
item["OFWeiche_CP2_y_mm"] = round(WeichenkProfileWidth/2+32.5437 , 3)
item["OFWeiche_CP3_x_mm"] = round(item["Objekt_width_mm"], 3)
item["OFWeiche_CP3_y_mm"] = item["OFWeiche_CP2_y_mm"]
# Update items with identical ProfilTyp
@@ -423,7 +421,91 @@ def process_deltaweiche_items(data, WeichenkProfileWidth):
for field in fields_to_copy:
similar[field] = item[field]
def process_sternweiche_items(data):
# Filter sternweiche type items
filtered_items = [
item for item in data
if (item.get("WeichenTyp") == "Sternweiche" and
item.get("Schaltungstyp") == "M" and
item.get("SivasnrTEF") is None and
str(item.get("Sivasnr", "")).isdigit())
]
print(f"\nFound {len(filtered_items)} sternweiche type records")
for item in filtered_items:
# Calculate related values
if (item["OFWeiche_center_line_width_mm"] is not None and
item["OFWeiche_center_line_height_mm"] is not None):
# Calculate basic dimensions
item["Objekt_width_mm"] = round(item["OFWeiche_center_line_width_mm"], 3)
item["Objekt_height_mm"] = round(item["OFWeiche_center_line_height_mm"], 3)
# Calculate control points
item["OFWeiche_CP1_x_mm"] = round(item["Objekt_width_mm"]/2, 3)
item["OFWeiche_CP1_y_mm"] = round(item["Objekt_height_mm"], 3)
item["OFWeiche_CP2_x_mm"] = 0
item["OFWeiche_CP2_y_mm"] = round(item["OFWeiche_center_line_height_mm"]/2, 3)
item["OFWeiche_CP3_x_mm"] = round(item["OFWeiche_center_line_width_mm"], 3)
item["OFWeiche_CP3_y_mm"] = item["OFWeiche_CP2_y_mm"]
item["OFWeiche_CP4_x_mm"] = item["OFWeiche_CP1_x_mm"]
item["OFWeiche_CP4_y_mm"] = 0
# Update items with identical ProfilTyp
current_profil = item["ProfilTyp"]
exact_matches = [x for x in data
if x["ProfilTyp"] == current_profil and
x is not item and
x.get("SivasnrTEF") is None]
if exact_matches:
for match in exact_matches:
fields_to_copy = [
"OFWeiche_center_line_width_mm",
"OFWeiche_center_line_height_mm",
"Objekt_width_mm",
"Objekt_height_mm",
"OFWeiche_CP1_x_mm",
"OFWeiche_CP1_y_mm",
"OFWeiche_CP2_x_mm",
"OFWeiche_CP2_y_mm",
"OFWeiche_CP3_x_mm",
"OFWeiche_CP3_y_mm",
"OFWeiche_CP4_x_mm",
"OFWeiche_CP4_y_mm"
]
for field in fields_to_copy:
match[field] = item[field]
# Find similar items (P-type)
if "WEICHE S C STERN" in item["ProfilTyp"]:
similar_profil = item["ProfilTyp"].replace("KPL. MIT M", "KPL. MIT P")
similar_items = [x for x in data
if x["ProfilTyp"] == similar_profil and
x.get("SivasnrTEF") is None]
for similar in similar_items:
fields_to_copy = [
"OFWeiche_center_line_width_mm",
"OFWeiche_center_line_height_mm",
"Objekt_width_mm",
"Objekt_height_mm",
"OFWeiche_CP1_x_mm",
"OFWeiche_CP1_y_mm",
"OFWeiche_CP2_x_mm",
"OFWeiche_CP2_y_mm",
"OFWeiche_CP3_x_mm",
"OFWeiche_CP3_y_mm",
"OFWeiche_CP4_x_mm",
"OFWeiche_CP4_y_mm"
]
for field in fields_to_copy:
similar[field] = item[field]
if __name__ == "__main__":
json_path = os.environ.get("JSON_PATH", "JSON")
input_filename = os.path.join(json_path, "omniflo_weichen.json")
@@ -68,7 +68,7 @@ def process_json_file(input_file, output_file):
cp2_dir = 180.0
if "-L-" in profil_typ:
cp3_dir = round(360 - kurven_winkel, 1)
elif "--" in profil_typ:
elif "-R-" in profil_typ:
cp3_dir = round(kurven_winkel, 1)
else:
cp3_dir = 0.0 # Default if pattern not found
@@ -76,6 +76,11 @@ def process_json_file(input_file, output_file):
cp1_dir = 180.0
cp2_dir = round(360 - kurven_winkel, 1)
cp3_dir = round(kurven_winkel, 1)
elif weichen_typ == "Dreifachweiche":
cp1_dir = 180.0
cp2_dir = round(360 - kurven_winkel, 1)
cp3_dir = round(kurven_winkel, 1)
elif weichen_typ == "Dreiwegeweiche":
cp1_dir = 180.0
cp2_dir = round(360 - kurven_winkel, 1)
@@ -91,11 +96,24 @@ def process_json_file(input_file, output_file):
"y": cp4_y,
"direction": cp4_dir
})
elif weichen_typ == "Dreifachweiche":
cp1_dir = 0
# Add common connection points
elif weichen_typ == "Sternweiche":
cp1_dir = 180
cp2_dir = round(360 - kurven_winkel, 1)
cp3_dir = round(kurven_winkel, 1)
# Add common connection points
# CP4 exists for Dreiwegeweiche
cp4_x = round(item["OFWeiche_CP4_x_mm"] * scale*scale_RD_W, 3)
cp4_y = round(item["OFWeiche_CP4_y_mm"] * scale*scale_RD_H, 3)
cp4_dir = 0
connection_points.append({
"id": "cp4",
"x": cp4_x,
"y": cp4_y,
"direction": cp4_dir
})
connection_points.extend([
{
"id": "cp1",
@@ -186,6 +186,6 @@ if __name__ == "__main__":
json_path = os.environ.get("JSON_PATH", "JSON")
json_file_path = os.path.join(json_path, "omniflo_weichen_output.json")
txt_files_dir = r"C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\props"
# txt_files_dir = r"C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\props"
txt_files_dir= os.environ.get("PROPS_PATH", "props")
process_files(json_file_path, txt_files_dir)
@@ -177,69 +177,7 @@ def analyze_and_normalize_path(d, path_type, path_id=""):
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.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
normalized.append(f"{cmd} {' '.join(map(str, params))}")
normalized_path = ' '.join(normalized)
return normalized_path if changed else original_d, report, changed '''
def optimize_svg(input_path, output_path):
"""Process single SVG file with all optimizations"""
try:
@@ -443,21 +381,32 @@ if __name__ == '__main__':
args = parser.parse_args()
in_dir = None
if args.bogen:
in_dir = os.environ.get('RD_CONF_BOGEN')
if args.tefbogen:
in_dir = os.environ.get('RD_CONF_TEFBOGEN')
if args.weichen:
in_dir = os.environ.get('RD_CONF_WEICHEN')
if args.tefweichen:
in_dir = os.environ.get('RD_CONF_TEFWEICHEN')
if args.inputdir:
in_dir = args.inputdir
else:
if args.bogen:
in_dir = os.environ.get('RD_CONF_BOGEN')
elif args.tefbogen:
in_dir = os.environ.get('RD_CONF_TEFBOGEN')
elif args.weichen:
in_dir = os.environ.get('RD_CONF_WEICHEN')
elif args.tefweichen:
in_dir = os.environ.get('RD_CONF_TEFWEICHEN')
out_dir = os.environ.get('RD_CONF_WORK')
if args.outputdir:
out_dir = args.outputdir
if not out_dir:
print("Error: RD_CONF_WORK environment variable must be set as output directory")
exit(1)
# Check if input directory exists
if not os.path.exists(in_dir):
print(f"Error: Input directory does not exist - {in_dir}")
exit(1)
# Ensure output directory exists (create if doesn't exist, ignore if already exists)
os.makedirs(out_dir, exist_ok=True)
# Processing logic
if args.file:
filename = args.file
input_path = os.path.join(in_dir, filename)
@@ -469,5 +418,8 @@ if __name__ == '__main__':
if in_dir:
"""Batch process SVG files"""
batch_process_svgs(in_dir, out_dir)
else:
parser.print_help()
print("Error: No input directory specified")
parser.print_help()
exit(1)
@@ -0,0 +1,247 @@
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
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 'DeltaWeiche' 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
straight_lines = find_straight_lines(root)
print(f" 📊 Found {len(straight_lines)} straight paths")
# 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
straight_lines = find_straight_lines(root)
print(f" 📊 Found {len(straight_lines)} straight paths")
# 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(root):
"""Find all straight line paths"""
lines = []
paths = root.xpath('.//svg:path|.//svg:g//svg:path',
namespaces={'svg': 'http://www.w3.org/2000/svg'})
for i, path in enumerate(paths, 1):
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': i,
'element': path,
'length': round(length, 4), # Keep 4 decimal places
'p1': (round(p1[0], 2), round(p1[1], 2)), # Coordinates rounded to 2 decimals
'p2': (round(p2[0], 2), round(p2[1], 2))
})
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]) # Length rounded to 4 decimals
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)
@@ -68,15 +68,15 @@ def normalize_stroke_widths2(root, scale):
# 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}mm')
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':
# 强制设置 stroke-width=1无单位
# set stroke-width=1no unit
elem.set('stroke-width', '1')
# 确保 vector-effect 生效
# set vector-effect
elem.set('vector-effect', 'non-scaling-stroke')
def scale_svg_file(input_path: str, output_path: str):
@@ -99,7 +99,7 @@ def scale_svg_file(input_path: str, output_path: str):
if width > height:
scale = 1000.0 / width
new_width = 1000.0
new_height = round(height * scale)
new_height = round(height * scale,3)
print(f"Scaling base: Width (larger dimension)")
else:
scale = 1000.0 / height
@@ -110,8 +110,8 @@ def scale_svg_file(input_path: str, output_path: str):
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)
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}')
@@ -155,6 +155,6 @@ def batch_process_svgs(input_dir: str, output_dir: str):
if __name__ == '__main__':
input_dir = os.environ.get('RD_CONF_WORK')
output_dir = os.environ.get('RD_CONF_OUTPUT')
output_dir = os.environ.get('RD_CONF_OUTPUT_OFWEICHEN')
# Example usage:
batch_process_svgs(input_dir, output_dir)
@@ -107,8 +107,8 @@ def process_svg_files(svg_folder, json_file_path):
if __name__ == "__main__":
# Configure paths (update these with your actual paths)
svg_folder =r"C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\Weichen\outputdir_Kopie"
json_file_path =r"C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\python\OFWeiche\JSON\omniflo_weichen_output.json"
process_svg_files(svg_folder, json_file_path)
svg_folder = os.environ.get('RD_CONF_OUTPUT_OFWEICHEN')
json_path = os.environ.get("JSON_PATH", "JSON")
input_filename = os.path.join(json_path, "omniflo_weichen_output.json")
process_svg_files(svg_folder, input_filename)
print("Processing complete")
@@ -0,0 +1,194 @@
import os
import re
import json
from xml.etree import ElementTree as ET
from xml.dom import minidom
def extract_sivasnr(filename):
"""Extract numeric ID from filename"""
match = re.search(r'(\d+)\.svg$', 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") 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_OFWEICHEN') # 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.")
@@ -1575,13 +1575,13 @@
"Objekt_width_mm": 1400.462,
"Objekt_height_mm": 753.781,
"OFWeiche_CP1_x_mm": 700.231,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 753.781,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.237,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1400.462,
"OFWeiche_CP3_y_mm": 700.237
"OFWeiche_CP3_y_mm": 53.544
},
{
"Sivasnr": "OFDeltaWeiche",
@@ -1594,13 +1594,13 @@
"Objekt_width_mm": 1400.462,
"Objekt_height_mm": 753.781,
"OFWeiche_CP1_x_mm": 700.231,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 753.781,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.237,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1400.462,
"OFWeiche_CP3_y_mm": 700.237
"OFWeiche_CP3_y_mm": 53.544
},
{
"Sivasnr": 834372401,
@@ -1613,13 +1613,13 @@
"Objekt_width_mm": 1400.462,
"Objekt_height_mm": 753.781,
"OFWeiche_CP1_x_mm": 700.231,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 753.781,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.237,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1400.462,
"OFWeiche_CP3_y_mm": 700.237
"OFWeiche_CP3_y_mm": 53.544
},
{
"Sivasnr": 834372403,
@@ -1632,13 +1632,13 @@
"Objekt_width_mm": 1600.384,
"Objekt_height_mm": 853.81,
"OFWeiche_CP1_x_mm": 800.192,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 853.81,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 800.266,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1600.384,
"OFWeiche_CP3_y_mm": 800.266
"OFWeiche_CP3_y_mm": 53.544
},
{
"Sivasnr": 834372404,
@@ -1651,13 +1651,13 @@
"Objekt_width_mm": 1600.384,
"Objekt_height_mm": 853.81,
"OFWeiche_CP1_x_mm": 800.192,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 853.81,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 800.266,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1600.384,
"OFWeiche_CP3_y_mm": 800.266
"OFWeiche_CP3_y_mm": 53.544
},
{
"Sivasnr": "0_BG071090+834372404+0_BG071090",
@@ -1727,15 +1727,15 @@
"Objekt_width_mm": 1400.442,
"Objekt_height_mm": 1400.442,
"OFWeiche_CP1_x_mm": 700.221,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 1400.442,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 1400.442,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.221,
"OFWeiche_CP3_x_mm": 700.221,
"OFWeiche_CP3_y_mm": 1400.442,
"OFWeiche_CP4_x_mm": 0,
"OFWeiche_CP4_y_mm": 700.221
"OFWeiche_CP3_x_mm": 1400.442,
"OFWeiche_CP3_y_mm": 700.221,
"OFWeiche_CP4_x_mm": 700.221,
"OFWeiche_CP4_y_mm": 0
},
{
"Sivasnr": 834372421,
@@ -1748,15 +1748,15 @@
"Objekt_width_mm": 1400.442,
"Objekt_height_mm": 1400.442,
"OFWeiche_CP1_x_mm": 700.221,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 1400.442,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 1400.442,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.221,
"OFWeiche_CP3_x_mm": 700.221,
"OFWeiche_CP3_y_mm": 1400.442,
"OFWeiche_CP4_x_mm": 0,
"OFWeiche_CP4_y_mm": 700.221
"OFWeiche_CP3_x_mm": 1400.442,
"OFWeiche_CP3_y_mm": 700.221,
"OFWeiche_CP4_x_mm": 700.221,
"OFWeiche_CP4_y_mm": 0
},
{
"Sivasnr": 834342011,
@@ -198,7 +198,7 @@
"id": "cp3",
"x": 964.455,
"y": 20.808,
"direction": 0.0
"direction": 45
}
]
},
@@ -244,7 +244,7 @@
"id": "cp3",
"x": 964.455,
"y": 20.808,
"direction": 0.0
"direction": 45
}
]
},
@@ -420,7 +420,7 @@
"id": "cp3",
"x": 968.24,
"y": 19.451,
"direction": 0.0
"direction": 45
}
]
},
@@ -466,7 +466,7 @@
"id": "cp3",
"x": 968.24,
"y": 19.451,
"direction": 0.0
"direction": 45
}
]
},
@@ -642,7 +642,7 @@
"id": "cp3",
"x": 1000.001,
"y": 33.868,
"direction": 0.0
"direction": 90
}
]
},
@@ -688,7 +688,7 @@
"id": "cp3",
"x": 1000.001,
"y": 33.868,
"direction": 0.0
"direction": 90
}
]
},
@@ -910,7 +910,7 @@
"id": "cp3",
"x": 1000.0,
"y": 29.173,
"direction": 0.0
"direction": 90
}
]
},
@@ -956,7 +956,7 @@
"id": "cp3",
"x": 1000.0,
"y": 29.173,
"direction": 0.0
"direction": 90
}
]
},
@@ -1159,7 +1159,7 @@
"id": "cp3",
"x": 923.377,
"y": 0.0,
"direction": 0.0
"direction": 0
}
]
},
@@ -1205,7 +1205,7 @@
"id": "cp3",
"x": 923.377,
"y": 0.0,
"direction": 0.0
"direction": 0
}
]
},
@@ -2976,13 +2976,13 @@
"Objekt_width_mm": 1400.462,
"Objekt_height_mm": 753.781,
"OFWeiche_CP1_x_mm": 700.231,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 753.781,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.237,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1400.462,
"OFWeiche_CP3_y_mm": 700.237,
"OFWeiche_CP3_y_mm": 53.544,
"Objekt_width_px": 5293.046,
"Objekt_height_px": 2848.915,
"calculated_SVG_width_px": 1000.0,
@@ -2994,19 +2994,19 @@
{
"id": "cp1",
"x": 500.0,
"y": 0.0,
"direction": 0
"y": 1000.001,
"direction": 180.0
},
{
"id": "cp2",
"x": 0.0,
"y": 928.967,
"y": 71.034,
"direction": 270
},
{
"id": "cp3",
"x": 1000.0,
"y": 928.967,
"y": 71.034,
"direction": 90
}
]
@@ -3022,13 +3022,13 @@
"Objekt_width_mm": 1400.462,
"Objekt_height_mm": 753.781,
"OFWeiche_CP1_x_mm": 700.231,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 753.781,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.237,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1400.462,
"OFWeiche_CP3_y_mm": 700.237,
"OFWeiche_CP3_y_mm": 53.544,
"Objekt_width_px": 5293.046,
"Objekt_height_px": 2848.915,
"calculated_SVG_width_px": 1000.0,
@@ -3040,19 +3040,19 @@
{
"id": "cp1",
"x": 500.0,
"y": 0.0,
"direction": 0
"y": 1000.001,
"direction": 180.0
},
{
"id": "cp2",
"x": 0.0,
"y": 928.967,
"y": 71.034,
"direction": 270
},
{
"id": "cp3",
"x": 1000.0,
"y": 928.967,
"y": 71.034,
"direction": 90
}
]
@@ -3068,13 +3068,13 @@
"Objekt_width_mm": 1400.462,
"Objekt_height_mm": 753.781,
"OFWeiche_CP1_x_mm": 700.231,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 753.781,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.237,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1400.462,
"OFWeiche_CP3_y_mm": 700.237,
"OFWeiche_CP3_y_mm": 53.544,
"Objekt_width_px": 5293.046,
"Objekt_height_px": 2848.915,
"calculated_SVG_width_px": 1000.0,
@@ -3086,19 +3086,19 @@
{
"id": "cp1",
"x": 500.0,
"y": 0.0,
"direction": 0
"y": 1000.001,
"direction": 180.0
},
{
"id": "cp2",
"x": 0.0,
"y": 928.967,
"y": 71.034,
"direction": 270
},
{
"id": "cp3",
"x": 1000.0,
"y": 928.967,
"y": 71.034,
"direction": 90
}
]
@@ -3114,13 +3114,13 @@
"Objekt_width_mm": 1600.384,
"Objekt_height_mm": 853.81,
"OFWeiche_CP1_x_mm": 800.192,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 853.81,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 800.266,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1600.384,
"OFWeiche_CP3_y_mm": 800.266,
"OFWeiche_CP3_y_mm": 53.544,
"Objekt_width_px": 6048.651,
"Objekt_height_px": 3226.975,
"calculated_SVG_width_px": 1000.0,
@@ -3132,19 +3132,19 @@
{
"id": "cp1",
"x": 500.0,
"y": 0.0,
"direction": 0
"y": 1000.001,
"direction": 180.0
},
{
"id": "cp2",
"x": 0.0,
"y": 937.289,
"y": 62.712,
"direction": 270
},
{
"id": "cp3",
"x": 1000.0,
"y": 937.289,
"y": 62.712,
"direction": 90
}
]
@@ -3160,13 +3160,13 @@
"Objekt_width_mm": 1600.384,
"Objekt_height_mm": 853.81,
"OFWeiche_CP1_x_mm": 800.192,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 853.81,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 800.266,
"OFWeiche_CP2_y_mm": 53.544,
"OFWeiche_CP3_x_mm": 1600.384,
"OFWeiche_CP3_y_mm": 800.266,
"OFWeiche_CP3_y_mm": 53.544,
"Objekt_width_px": 6048.651,
"Objekt_height_px": 3226.975,
"calculated_SVG_width_px": 1000.0,
@@ -3178,19 +3178,19 @@
{
"id": "cp1",
"x": 500.0,
"y": 0.0,
"direction": 0
"y": 1000.001,
"direction": 180.0
},
{
"id": "cp2",
"x": 0.0,
"y": 937.289,
"y": 62.712,
"direction": 270
},
{
"id": "cp3",
"x": 1000.0,
"y": 937.289,
"y": 62.712,
"direction": 90
}
]
@@ -3263,15 +3263,15 @@
"Objekt_width_mm": 1400.442,
"Objekt_height_mm": 1400.442,
"OFWeiche_CP1_x_mm": 700.221,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 1400.442,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 1400.442,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.221,
"OFWeiche_CP3_x_mm": 700.221,
"OFWeiche_CP3_y_mm": 1400.442,
"OFWeiche_CP4_x_mm": 0,
"OFWeiche_CP4_y_mm": 700.221,
"OFWeiche_CP3_x_mm": 1400.442,
"OFWeiche_CP3_y_mm": 700.221,
"OFWeiche_CP4_x_mm": 700.221,
"OFWeiche_CP4_y_mm": 0,
"Objekt_width_px": 5292.971,
"Objekt_height_px": 5292.971,
"calculated_SVG_width_px": 1000.0,
@@ -3281,22 +3281,28 @@
"scale_factor_RD_Height": 1.0,
"connectionPoints": [
{
"id": "cp1",
"id": "cp4",
"x": 500.0,
"y": 0.0,
"direction": 0
},
{
"id": "cp1",
"x": 500.0,
"y": 1000.0,
"direction": 180
},
{
"id": "cp2",
"x": 1000.0,
"x": 0.0,
"y": 500.0,
"direction": 270
"direction": 360
},
{
"id": "cp3",
"x": 500.0,
"y": 1000.0,
"direction": 90
"x": 1000.0,
"y": 500.0,
"direction": 0
}
]
},
@@ -3311,15 +3317,15 @@
"Objekt_width_mm": 1400.442,
"Objekt_height_mm": 1400.442,
"OFWeiche_CP1_x_mm": 700.221,
"OFWeiche_CP1_y_mm": 0,
"OFWeiche_CP1_y_mm": 1400.442,
"KurvenRichtung": 7,
"SivasnrTEF": null,
"OFWeiche_CP2_x_mm": 1400.442,
"OFWeiche_CP2_x_mm": 0,
"OFWeiche_CP2_y_mm": 700.221,
"OFWeiche_CP3_x_mm": 700.221,
"OFWeiche_CP3_y_mm": 1400.442,
"OFWeiche_CP4_x_mm": 0,
"OFWeiche_CP4_y_mm": 700.221,
"OFWeiche_CP3_x_mm": 1400.442,
"OFWeiche_CP3_y_mm": 700.221,
"OFWeiche_CP4_x_mm": 700.221,
"OFWeiche_CP4_y_mm": 0,
"Objekt_width_px": 5292.971,
"Objekt_height_px": 5292.971,
"calculated_SVG_width_px": 1000.0,
@@ -3329,22 +3335,28 @@
"scale_factor_RD_Height": 1.0,
"connectionPoints": [
{
"id": "cp1",
"id": "cp4",
"x": 500.0,
"y": 0.0,
"direction": 0
},
{
"id": "cp1",
"x": 500.0,
"y": 1000.0,
"direction": 180
},
{
"id": "cp2",
"x": 1000.0,
"x": 0.0,
"y": 500.0,
"direction": 270
"direction": 360
},
{
"id": "cp3",
"x": 500.0,
"y": 1000.0,
"direction": 90
"x": 1000.0,
"y": 500.0,
"direction": 0
}
]
},
@@ -3482,7 +3494,7 @@
"id": "cp3",
"x": 888.596,
"y": 22.367,
"direction": 0.0
"direction": 22.5
}
]
},
@@ -3574,7 +3586,7 @@
"id": "cp3",
"x": 888.596,
"y": 22.367,
"direction": 0.0
"direction": 22.5
}
]
},
@@ -1,69 +0,0 @@
import json
import os
import xml.etree.ElementTree as ET
def process_json_and_modify_xml(json_file_path, xml_folder_path):
# Initialize counter for total modifications
total_modified = 0
# Read JSON file
with open(json_file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# Process each item in JSON data
for item in data:
if isinstance(item, dict) and (item.get("WeichenTyp") == "Einzelweiche" or item.get("WeichenTyp") == "Dreifachweiche") :
sivasnr = item.get("Sivasnr")
if sivasnr:
xml_file_name = f"{sivasnr}.xml"
xml_file_path = os.path.join(xml_folder_path, xml_file_name)
if os.path.exists(xml_file_path):
try:
# Register SVG namespace and parse XML
ET.register_namespace('', 'http://www.w3.org/2000/svg')
tree = ET.parse(xml_file_path)
root = tree.getroot()
file_modified_count = 0
# Find all path elements recursively
for path in root.iter('{http://www.w3.org/2000/svg}path'):
# Check for target attributes
if (path.get('stroke') == "none" and
path.get('stroke-width') == "1px" ):
# Remove original attributes
for attr in ['stroke', 'stroke-width', 'fill']:
if attr in path.attrib:
del path.attrib[attr]
# Set new style attribute
path.set('style', 'stroke:none;fill:none;')
file_modified_count += 1
total_modified += 1
if file_modified_count > 0:
# Save with proper formatting
xml_str = ET.tostring(root, encoding='unicode')
xml_str = xml_str.replace('><', '>\n<')
with open(xml_file_path, 'w', encoding='utf-8') as xml_file:
xml_file.write(xml_str)
print(f"Successfully modified {file_modified_count} path(s) in: {xml_file_name}")
else:
print(f"No target paths found in: {xml_file_name}")
except Exception as e:
print(f"Error processing {xml_file_name}: {str(e)}")
else:
print(f"XML file not found: {xml_file_name}")
# Print total modifications summary
print(f"\nTotal paths modified across all files: {total_modified}")
if __name__ == "__main__":
json_file_path = r"C:\Users\y.wang\Documents\SSG-Ruledesigner-Konfigurator\SVGs\Omniflo\python\OFWeiche\JSON\omniflo_weichen_output.json"
xml_folder_path = r"C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\svg"
process_json_and_modify_xml(json_file_path, xml_folder_path)
@@ -1,15 +0,0 @@
@echo off
set "OFWeiche_PATH=%~dp0"
set PROPS_PATH=C:\Program Files\RuleDesigner\RDConfigurator Fusion\WebApi\Editor2D\SSG\shapes\props
set "JSON_PATH=%OFWeiche_PATH%JSON"
echo "[DEBUG] OFWeiche_PATH: %OFWeiche_PATH%"
echo "[DEBUG] PROPS_PATH: %PROPS_PATH%"
echo "[DEBUG] JSON_PATH: %JSON_PATH%"
python 1_omniflo_weichen.py
python 2_calculations_to_standardize_the_dimensions_and_add_connection_points.py
python 3_update_dimensions_and_connection_points_in_props.py
pause