Kanten an Aufgaben rechtwinklig ansetzen (#23)
- orthogonal_points(): Ist nur ein Ende eine Raute, bekommt auch das Aufgaben-Ende einen geraden Stub senkrecht zu seiner Seite (RECHTECK_STUB = 20); danach wie zwischen zwei Rauten von Stub zu Stub. Die beiden Sonderzweige für "nur Quelle/nur Ziel ist Gateway" entfallen. - Beispiele neu erzeugt: 17 Kantenenden (2 + 2 + 13), die parallel zur Aufgabenkante ansetzten, sind korrigiert. - Strukturtest test_kanten_setzen_an_aufgaben_rechtwinklig_an über alle Beispiele und Einzeltest für vier Achsen-Kombinationen. - Belastungstest (126 Fälle): schräge Anschlüsse 378 -> 0; Kreuzungen 22 -> 24, alle in Fällen mit Querverbindung zwischen Zweigen (#22). - Tests: python -m pytest -q -> 124 bestanden, 1 übersprungen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -236,6 +236,45 @@ def test_anmerkung_ist_gross_genug_fuer_ihren_text(md):
|
||||
assert h >= zeilen * 16, f"{anm.get('id')}: {len(text)} Zeichen brauchen etwa {zeilen} Zeilen, Höhe nur {h:g}"
|
||||
|
||||
|
||||
RECHTECKE = HINDERNISSE[len(GATEWAYS + EREIGNISSE):] # Aufgaben, Teilprozesse, Datenelemente
|
||||
|
||||
|
||||
def schraege_anschluesse(defs):
|
||||
"""Alle Kantenenden an Rechteck-Elementen, deren erstes bzw. letztes Stück nicht rechtwinklig zu der Elementkante
|
||||
verläuft, auf der der Anschlusspunkt liegt (Ost/West verlangt waagrecht, Nord/Süd senkrecht)."""
|
||||
art = {el.get("id"): el.tag.rpartition("}")[2] for el in defs.iter() if el.get("id")}
|
||||
enden = {el.get("id"): (el.get("sourceRef"), el.get("targetRef"))
|
||||
for el in defs.iter() if art.get(el.get("id")) in KANTEN}
|
||||
formen = {s.get("bpmnElement"): _box(s) for s in defs.iter(f"{{{m.NS['bpmndi']}}}BPMNShape")}
|
||||
funde = []
|
||||
for edge in defs.iter(f"{{{m.NS['bpmndi']}}}BPMNEdge"):
|
||||
kante = edge.get("bpmnElement")
|
||||
punkte = [(float(wp.get("x")), float(wp.get("y"))) for wp in edge.findall(f"{{{m.NS['di']}}}waypoint")]
|
||||
if kante not in enden or len(punkte) < 2:
|
||||
continue
|
||||
for element, (a, b) in ((enden[kante][0], punkte[:2]), (enden[kante][1], punkte[:-3:-1])):
|
||||
if art.get(element) not in RECHTECKE:
|
||||
continue
|
||||
x, y, w, h = formen[element]
|
||||
if abs(a[0] - x) < 0.5 or abs(a[0] - x - w) < 0.5:
|
||||
rechtwinklig = abs(a[1] - b[1]) < 1e-6 # Ost/West: waagrecht
|
||||
elif abs(a[1] - y) < 0.5 or abs(a[1] - y - h) < 0.5:
|
||||
rechtwinklig = abs(a[0] - b[0]) < 1e-6 # Nord/Süd: senkrecht
|
||||
else:
|
||||
rechtwinklig = False # Anschluss nicht auf dem Rand
|
||||
if not rechtwinklig:
|
||||
funde.append((kante, element))
|
||||
return sorted(funde)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("md", MODELLE, ids=lambda p: p.stem)
|
||||
def test_kanten_setzen_an_aufgaben_rechtwinklig_an(md):
|
||||
"""Prüft, dass jede Kante an einer Aufgabe (bzw. einem anderen Rechteck-Element) rechtwinklig zu der Kante ansetzt,
|
||||
auf der ihr Anschlusspunkt liegt, statt an ihr entlangzulaufen (Issue #23)."""
|
||||
funde = schraege_anschluesse(baue(md))
|
||||
assert funde == [], "nicht rechtwinklig (Kante, Element): " + ", ".join(f"{k} → {e}" for k, e in funde)
|
||||
|
||||
|
||||
def test_kreuzungspruefung_findet_eine_kante_durch_eine_aufgabe():
|
||||
"""Prüft die Prüfung selbst: eine absichtlich durch eine Aufgabe gelegte Kante wird gefunden, eine daneben nicht."""
|
||||
defs = baue(SKILL / "beispiele" / "beispiel_prozess.md")
|
||||
|
||||
Reference in New Issue
Block a user