Kanten zwischen Gateways umgehen die Ziel-Raute (#8)

- orthogonal_points(): Liegt bei Gateway -> Gateway der Stub des Starts
  schon jenseits des Ziel-Anschlusspunkts (z. B. Südpunkt unten, Ziel
  höher mit Nordpunkt), führt die Kante seitlich an der Ziel-Raute vorbei.
  Gleiches für den waagrechten Spiegelfall (Ost -> West).
- _ausweichachse(): Die Ausweichachse liegt im freien Gang direkt vor der
  Ziel-Spalte (AUSWEICHABSTAND 85), nicht in der Mitte zwischen Quelle und
  Ziel – dort stand im Referenzmodell die Aufgabe S43.
- Referenzmodell neu erzeugt: fünf Kanten korrigiert (vorher liefen alle
  fünf durch ein Gateway, gemeldet war nur S12->S13), dabei verschwindet
  auch die Kreuzung Flow_13/S40. Syntaxbeispiele unverändert.
- xfail für referenz_gewannenfestlegung entfernt; drei neue Tests in
  test_md_to_bpmn.py.
- Fallstricke: Ausweichachse; Strukturtests melden nur die erste Kreuzung.
- Tests: python -m pytest -q -> 92 bestanden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 11:09:43 +02:00
co-authored by Claude Opus 5.5
parent 6050ce3296
commit 30b47a0fd1
6 changed files with 97 additions and 13 deletions
+28 -1
View File
@@ -580,6 +580,21 @@ def _orthogonal_middle(ox, oy, src_side, tx, ty, tgt_side):
return [(ox, oy), (tx, oy), (tx, ty)]
# Abstand der Ausweichachse von der Mitte der Ziel-Spalte bzw. -Zeile: halbe
# Breite der größten Elemente (Aufgabe 100x80) plus halber kleinster Gang
# zwischen zwei Spalten/Zeilen (170 - 100 = 70). Der Gang direkt vor dem Ziel
# ist damit in beiden Layouts frei; die Mitte zwischen Quelle und Ziel nicht,
# dort kann eine Spalte mit einer Aufgabe liegen.
AUSWEICHABSTAND = 85
def _ausweichachse(quelle, ziel):
"""Koordinate im freien Gang vor der Ziel-Spalte (bzw. -Zeile), auf der Seite
der Quelle: dort läuft eine Kante an der Ziel-Raute vorbei, ohne ein anderes
Element zu schneiden."""
return ziel + AUSWEICHABSTAND if quelle > ziel else ziel - AUSWEICHABSTAND
def orthogonal_points(ox, oy, src_side, tx, ty, tgt_side,
src_is_gateway=False, tgt_is_gateway=False):
"""Baut einen rechtwinkligen Kantenverlauf zwischen zwei Anschlusspunkten, der
@@ -627,7 +642,19 @@ def orthogonal_points(ox, oy, src_side, tx, ty, tgt_side,
else:
# Beide Enden sind Rauten: von der Stub-Achse des Starts direkt auf
# die Stub-Achse des Ziels schwenken, jede nur einmal verlassen.
if src_axis == 'v':
# Liegt der Stub des Starts schon jenseits des Ziel-Anschlusspunkts
# (z. B. Ankunft am Nordpunkt eines höher liegenden Ziels), liefe das
# letzte gerade Stück durch die Ziel-Raute - dann seitlich daran
# vorbei über eine freie Ausweichachse (Issue #8).
if src_axis == 'v' and tgt_axis == 'v' and (
(tgt_side == 'N' and sy > ty) or (tgt_side == 'S' and sy < ty)):
mx = _ausweichachse(sx, ex)
points = [(ox, oy), (sx, sy), (mx, sy), (mx, ey), (ex, ey), (tx, ty)]
elif src_axis == 'h' and tgt_axis == 'h' and (
(tgt_side == 'W' and sx > tx) or (tgt_side == 'E' and sx < tx)):
my = _ausweichachse(sy, ey)
points = [(ox, oy), (sx, sy), (sx, my), (ex, my), (ex, ey), (tx, ty)]
elif src_axis == 'v':
points = [(ox, oy), (sx, sy), (ex, sy), (ex, ey), (tx, ty)]
else:
points = [(ox, oy), (sx, sy), (sx, ey), (ex, ey), (tx, ty)]