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:
@@ -118,14 +118,16 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2">
|
<bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2">
|
||||||
<di:waypoint x="400" y="360"/>
|
<di:waypoint x="400" y="360"/>
|
||||||
<di:waypoint x="400" y="310"/>
|
<di:waypoint x="420" y="360"/>
|
||||||
|
<di:waypoint x="420" y="310"/>
|
||||||
<di:waypoint x="515" y="310"/>
|
<di:waypoint x="515" y="310"/>
|
||||||
<di:waypoint x="515" y="335"/>
|
<di:waypoint x="515" y="335"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_3_di" bpmnElement="Flow_3">
|
<bpmndi:BPMNEdge id="Flow_3_di" bpmnElement="Flow_3">
|
||||||
<di:waypoint x="515" y="385"/>
|
<di:waypoint x="515" y="385"/>
|
||||||
<di:waypoint x="515" y="410"/>
|
<di:waypoint x="515" y="410"/>
|
||||||
<di:waypoint x="680" y="410"/>
|
<di:waypoint x="660" y="410"/>
|
||||||
|
<di:waypoint x="660" y="445"/>
|
||||||
<di:waypoint x="680" y="445"/>
|
<di:waypoint x="680" y="445"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="523" y="389.5" width="30" height="14"/>
|
<dc:Bounds x="523" y="389.5" width="30" height="14"/>
|
||||||
@@ -135,6 +137,7 @@
|
|||||||
<di:waypoint x="540" y="360"/>
|
<di:waypoint x="540" y="360"/>
|
||||||
<di:waypoint x="565" y="360"/>
|
<di:waypoint x="565" y="360"/>
|
||||||
<di:waypoint x="565" y="275"/>
|
<di:waypoint x="565" y="275"/>
|
||||||
|
<di:waypoint x="660" y="275"/>
|
||||||
<di:waypoint x="680" y="275"/>
|
<di:waypoint x="680" y="275"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="537.5" y="366" width="30" height="14"/>
|
<dc:Bounds x="537.5" y="366" width="30" height="14"/>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
<bpmndi:BPMNShape id="Gateway_S3_di" bpmnElement="Gateway_S3" isMarkerVisible="true">
|
<bpmndi:BPMNShape id="Gateway_S3_di" bpmnElement="Gateway_S3" isMarkerVisible="true">
|
||||||
<dc:Bounds x="165" y="420" width="50" height="50"/>
|
<dc:Bounds x="165" y="420" width="50" height="50"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="245" y="390.5" width="90" height="42"/>
|
<dc:Bounds x="202.5" y="390.5" width="90" height="42"/>
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="SendTask_S4_di" bpmnElement="SendTask_S4">
|
<bpmndi:BPMNShape id="SendTask_S4_di" bpmnElement="SendTask_S4">
|
||||||
@@ -102,7 +102,8 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2">
|
<bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2">
|
||||||
<di:waypoint x="215" y="330"/>
|
<di:waypoint x="215" y="330"/>
|
||||||
<di:waypoint x="215" y="395"/>
|
<di:waypoint x="215" y="350"/>
|
||||||
|
<di:waypoint x="190" y="350"/>
|
||||||
<di:waypoint x="190" y="395"/>
|
<di:waypoint x="190" y="395"/>
|
||||||
<di:waypoint x="190" y="420"/>
|
<di:waypoint x="190" y="420"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -110,6 +111,7 @@
|
|||||||
<di:waypoint x="190" y="470"/>
|
<di:waypoint x="190" y="470"/>
|
||||||
<di:waypoint x="190" y="495"/>
|
<di:waypoint x="190" y="495"/>
|
||||||
<di:waypoint x="300" y="495"/>
|
<di:waypoint x="300" y="495"/>
|
||||||
|
<di:waypoint x="300" y="570"/>
|
||||||
<di:waypoint x="300" y="590"/>
|
<di:waypoint x="300" y="590"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="198" y="474.5" width="30" height="14"/>
|
<dc:Bounds x="198" y="474.5" width="30" height="14"/>
|
||||||
@@ -118,7 +120,8 @@
|
|||||||
<bpmndi:BPMNEdge id="Flow_4_di" bpmnElement="Flow_4">
|
<bpmndi:BPMNEdge id="Flow_4_di" bpmnElement="Flow_4">
|
||||||
<di:waypoint x="215" y="445"/>
|
<di:waypoint x="215" y="445"/>
|
||||||
<di:waypoint x="240" y="445"/>
|
<di:waypoint x="240" y="445"/>
|
||||||
<di:waypoint x="240" y="590"/>
|
<di:waypoint x="240" y="570"/>
|
||||||
|
<di:waypoint x="130" y="570"/>
|
||||||
<di:waypoint x="130" y="590"/>
|
<di:waypoint x="130" y="590"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="212.5" y="451" width="30" height="14"/>
|
<dc:Bounds x="212.5" y="451" width="30" height="14"/>
|
||||||
@@ -132,7 +135,8 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_6_di" bpmnElement="Flow_6">
|
<bpmndi:BPMNEdge id="Flow_6_di" bpmnElement="Flow_6">
|
||||||
<di:waypoint x="300" y="670"/>
|
<di:waypoint x="300" y="670"/>
|
||||||
<di:waypoint x="300" y="735"/>
|
<di:waypoint x="300" y="690"/>
|
||||||
|
<di:waypoint x="190" y="690"/>
|
||||||
<di:waypoint x="190" y="735"/>
|
<di:waypoint x="190" y="735"/>
|
||||||
<di:waypoint x="190" y="760"/>
|
<di:waypoint x="190" y="760"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -140,6 +144,7 @@
|
|||||||
<di:waypoint x="190" y="810"/>
|
<di:waypoint x="190" y="810"/>
|
||||||
<di:waypoint x="190" y="835"/>
|
<di:waypoint x="190" y="835"/>
|
||||||
<di:waypoint x="130" y="835"/>
|
<di:waypoint x="130" y="835"/>
|
||||||
|
<di:waypoint x="130" y="910"/>
|
||||||
<di:waypoint x="130" y="930"/>
|
<di:waypoint x="130" y="930"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="198" y="814.5" width="30" height="14"/>
|
<dc:Bounds x="198" y="814.5" width="30" height="14"/>
|
||||||
@@ -148,7 +153,8 @@
|
|||||||
<bpmndi:BPMNEdge id="Flow_8_di" bpmnElement="Flow_8">
|
<bpmndi:BPMNEdge id="Flow_8_di" bpmnElement="Flow_8">
|
||||||
<di:waypoint x="215" y="785"/>
|
<di:waypoint x="215" y="785"/>
|
||||||
<di:waypoint x="240" y="785"/>
|
<di:waypoint x="240" y="785"/>
|
||||||
<di:waypoint x="240" y="930"/>
|
<di:waypoint x="240" y="910"/>
|
||||||
|
<di:waypoint x="300" y="910"/>
|
||||||
<di:waypoint x="300" y="930"/>
|
<di:waypoint x="300" y="930"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="212.5" y="791" width="30" height="14"/>
|
<dc:Bounds x="212.5" y="791" width="30" height="14"/>
|
||||||
|
|||||||
@@ -473,14 +473,16 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_5_di" bpmnElement="Flow_5">
|
<bpmndi:BPMNEdge id="Flow_5_di" bpmnElement="Flow_5">
|
||||||
<di:waypoint x="970" y="170"/>
|
<di:waypoint x="970" y="170"/>
|
||||||
<di:waypoint x="970" y="120"/>
|
<di:waypoint x="990" y="170"/>
|
||||||
|
<di:waypoint x="990" y="120"/>
|
||||||
<di:waypoint x="1085" y="120"/>
|
<di:waypoint x="1085" y="120"/>
|
||||||
<di:waypoint x="1085" y="145"/>
|
<di:waypoint x="1085" y="145"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_6_di" bpmnElement="Flow_6">
|
<bpmndi:BPMNEdge id="Flow_6_di" bpmnElement="Flow_6">
|
||||||
<di:waypoint x="1085" y="195"/>
|
<di:waypoint x="1085" y="195"/>
|
||||||
<di:waypoint x="1085" y="220"/>
|
<di:waypoint x="1085" y="220"/>
|
||||||
<di:waypoint x="1250" y="220"/>
|
<di:waypoint x="1230" y="220"/>
|
||||||
|
<di:waypoint x="1230" y="170"/>
|
||||||
<di:waypoint x="1250" y="170"/>
|
<di:waypoint x="1250" y="170"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="1093" y="199.5" width="30" height="14"/>
|
<dc:Bounds x="1093" y="199.5" width="30" height="14"/>
|
||||||
@@ -510,18 +512,21 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_10_di" bpmnElement="Flow_10">
|
<bpmndi:BPMNEdge id="Flow_10_di" bpmnElement="Flow_10">
|
||||||
<di:waypoint x="1730" y="170"/>
|
<di:waypoint x="1730" y="170"/>
|
||||||
|
<di:waypoint x="1750" y="170"/>
|
||||||
<di:waypoint x="1795" y="170"/>
|
<di:waypoint x="1795" y="170"/>
|
||||||
<di:waypoint x="1820" y="170"/>
|
<di:waypoint x="1820" y="170"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_11_di" bpmnElement="Flow_11">
|
<bpmndi:BPMNEdge id="Flow_11_di" bpmnElement="Flow_11">
|
||||||
<di:waypoint x="1845" y="195"/>
|
<di:waypoint x="1845" y="195"/>
|
||||||
<di:waypoint x="1845" y="220"/>
|
<di:waypoint x="1845" y="220"/>
|
||||||
<di:waypoint x="2010" y="220"/>
|
<di:waypoint x="1990" y="220"/>
|
||||||
|
<di:waypoint x="1990" y="170"/>
|
||||||
<di:waypoint x="2010" y="170"/>
|
<di:waypoint x="2010" y="170"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_12_di" bpmnElement="Flow_12">
|
<bpmndi:BPMNEdge id="Flow_12_di" bpmnElement="Flow_12">
|
||||||
<di:waypoint x="2110" y="170"/>
|
<di:waypoint x="2110" y="170"/>
|
||||||
<di:waypoint x="2110" y="120"/>
|
<di:waypoint x="2130" y="170"/>
|
||||||
|
<di:waypoint x="2130" y="120"/>
|
||||||
<di:waypoint x="2225" y="120"/>
|
<di:waypoint x="2225" y="120"/>
|
||||||
<di:waypoint x="2225" y="145"/>
|
<di:waypoint x="2225" y="145"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -540,6 +545,7 @@
|
|||||||
<di:waypoint x="2250" y="170"/>
|
<di:waypoint x="2250" y="170"/>
|
||||||
<di:waypoint x="2275" y="170"/>
|
<di:waypoint x="2275" y="170"/>
|
||||||
<di:waypoint x="2275" y="255"/>
|
<di:waypoint x="2275" y="255"/>
|
||||||
|
<di:waypoint x="2370" y="255"/>
|
||||||
<di:waypoint x="2390" y="255"/>
|
<di:waypoint x="2390" y="255"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="2247.5" y="176" width="30" height="14"/>
|
<dc:Bounds x="2247.5" y="176" width="30" height="14"/>
|
||||||
@@ -548,7 +554,8 @@
|
|||||||
<bpmndi:BPMNEdge id="Flow_15_di" bpmnElement="Flow_15">
|
<bpmndi:BPMNEdge id="Flow_15_di" bpmnElement="Flow_15">
|
||||||
<di:waypoint x="2415" y="110"/>
|
<di:waypoint x="2415" y="110"/>
|
||||||
<di:waypoint x="2415" y="135"/>
|
<di:waypoint x="2415" y="135"/>
|
||||||
<di:waypoint x="2580" y="135"/>
|
<di:waypoint x="2560" y="135"/>
|
||||||
|
<di:waypoint x="2560" y="85"/>
|
||||||
<di:waypoint x="2580" y="85"/>
|
<di:waypoint x="2580" y="85"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="2423" y="114.5" width="30" height="14"/>
|
<dc:Bounds x="2423" y="114.5" width="30" height="14"/>
|
||||||
@@ -566,18 +573,21 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_17_di" bpmnElement="Flow_17">
|
<bpmndi:BPMNEdge id="Flow_17_di" bpmnElement="Flow_17">
|
||||||
<di:waypoint x="2680" y="85"/>
|
<di:waypoint x="2680" y="85"/>
|
||||||
|
<di:waypoint x="2700" y="85"/>
|
||||||
<di:waypoint x="2745" y="85"/>
|
<di:waypoint x="2745" y="85"/>
|
||||||
<di:waypoint x="2770" y="85"/>
|
<di:waypoint x="2770" y="85"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_18_di" bpmnElement="Flow_18">
|
<bpmndi:BPMNEdge id="Flow_18_di" bpmnElement="Flow_18">
|
||||||
<di:waypoint x="2795" y="110"/>
|
<di:waypoint x="2795" y="110"/>
|
||||||
<di:waypoint x="2795" y="135"/>
|
<di:waypoint x="2795" y="135"/>
|
||||||
<di:waypoint x="2960" y="135"/>
|
<di:waypoint x="2940" y="135"/>
|
||||||
|
<di:waypoint x="2940" y="85"/>
|
||||||
<di:waypoint x="2960" y="85"/>
|
<di:waypoint x="2960" y="85"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_19_di" bpmnElement="Flow_19">
|
<bpmndi:BPMNEdge id="Flow_19_di" bpmnElement="Flow_19">
|
||||||
<di:waypoint x="3060" y="85"/>
|
<di:waypoint x="3060" y="85"/>
|
||||||
<di:waypoint x="3060" y="35"/>
|
<di:waypoint x="3080" y="85"/>
|
||||||
|
<di:waypoint x="3080" y="35"/>
|
||||||
<di:waypoint x="3175" y="35"/>
|
<di:waypoint x="3175" y="35"/>
|
||||||
<di:waypoint x="3175" y="60"/>
|
<di:waypoint x="3175" y="60"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -605,7 +615,8 @@
|
|||||||
<bpmndi:BPMNEdge id="Flow_22_di" bpmnElement="Flow_22">
|
<bpmndi:BPMNEdge id="Flow_22_di" bpmnElement="Flow_22">
|
||||||
<di:waypoint x="3365" y="110"/>
|
<di:waypoint x="3365" y="110"/>
|
||||||
<di:waypoint x="3365" y="135"/>
|
<di:waypoint x="3365" y="135"/>
|
||||||
<di:waypoint x="3530" y="135"/>
|
<di:waypoint x="3510" y="135"/>
|
||||||
|
<di:waypoint x="3510" y="625"/>
|
||||||
<di:waypoint x="3530" y="625"/>
|
<di:waypoint x="3530" y="625"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="3373" y="114.5" width="144" height="14"/>
|
<dc:Bounds x="3373" y="114.5" width="144" height="14"/>
|
||||||
@@ -615,6 +626,7 @@
|
|||||||
<di:waypoint x="3390" y="85"/>
|
<di:waypoint x="3390" y="85"/>
|
||||||
<di:waypoint x="3415" y="85"/>
|
<di:waypoint x="3415" y="85"/>
|
||||||
<di:waypoint x="3415" y="805"/>
|
<di:waypoint x="3415" y="805"/>
|
||||||
|
<di:waypoint x="3510" y="805"/>
|
||||||
<di:waypoint x="3530" y="805"/>
|
<di:waypoint x="3530" y="805"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="3387.5" y="91" width="30" height="14"/>
|
<dc:Bounds x="3387.5" y="91" width="30" height="14"/>
|
||||||
@@ -628,13 +640,15 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_25_di" bpmnElement="Flow_25">
|
<bpmndi:BPMNEdge id="Flow_25_di" bpmnElement="Flow_25">
|
||||||
<di:waypoint x="3820" y="85"/>
|
<di:waypoint x="3820" y="85"/>
|
||||||
<di:waypoint x="3820" y="120"/>
|
<di:waypoint x="3840" y="85"/>
|
||||||
|
<di:waypoint x="3840" y="120"/>
|
||||||
<di:waypoint x="3935" y="120"/>
|
<di:waypoint x="3935" y="120"/>
|
||||||
<di:waypoint x="3935" y="145"/>
|
<di:waypoint x="3935" y="145"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_26_di" bpmnElement="Flow_26">
|
<bpmndi:BPMNEdge id="Flow_26_di" bpmnElement="Flow_26">
|
||||||
<di:waypoint x="3630" y="805"/>
|
<di:waypoint x="3630" y="805"/>
|
||||||
<di:waypoint x="3885" y="805"/>
|
<di:waypoint x="3650" y="805"/>
|
||||||
|
<di:waypoint x="3650" y="170"/>
|
||||||
<di:waypoint x="3885" y="170"/>
|
<di:waypoint x="3885" y="170"/>
|
||||||
<di:waypoint x="3910" y="170"/>
|
<di:waypoint x="3910" y="170"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -649,7 +663,8 @@
|
|||||||
<bpmndi:BPMNEdge id="Flow_28_di" bpmnElement="Flow_28">
|
<bpmndi:BPMNEdge id="Flow_28_di" bpmnElement="Flow_28">
|
||||||
<di:waypoint x="3365" y="280"/>
|
<di:waypoint x="3365" y="280"/>
|
||||||
<di:waypoint x="3365" y="305"/>
|
<di:waypoint x="3365" y="305"/>
|
||||||
<di:waypoint x="3530" y="305"/>
|
<di:waypoint x="3510" y="305"/>
|
||||||
|
<di:waypoint x="3510" y="975"/>
|
||||||
<di:waypoint x="3530" y="975"/>
|
<di:waypoint x="3530" y="975"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="3373" y="284.5" width="30" height="14"/>
|
<dc:Bounds x="3373" y="284.5" width="30" height="14"/>
|
||||||
@@ -659,6 +674,7 @@
|
|||||||
<di:waypoint x="3390" y="255"/>
|
<di:waypoint x="3390" y="255"/>
|
||||||
<di:waypoint x="3415" y="255"/>
|
<di:waypoint x="3415" y="255"/>
|
||||||
<di:waypoint x="3415" y="170"/>
|
<di:waypoint x="3415" y="170"/>
|
||||||
|
<di:waypoint x="3510" y="170"/>
|
||||||
<di:waypoint x="3530" y="170"/>
|
<di:waypoint x="3530" y="170"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="3387.5" y="261" width="132" height="14"/>
|
<dc:Bounds x="3387.5" y="261" width="132" height="14"/>
|
||||||
@@ -666,13 +682,15 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_30_di" bpmnElement="Flow_30">
|
<bpmndi:BPMNEdge id="Flow_30_di" bpmnElement="Flow_30">
|
||||||
<di:waypoint x="3630" y="975"/>
|
<di:waypoint x="3630" y="975"/>
|
||||||
<di:waypoint x="3630" y="205"/>
|
<di:waypoint x="3650" y="975"/>
|
||||||
|
<di:waypoint x="3650" y="205"/>
|
||||||
<di:waypoint x="3745" y="205"/>
|
<di:waypoint x="3745" y="205"/>
|
||||||
<di:waypoint x="3745" y="230"/>
|
<di:waypoint x="3745" y="230"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_31_di" bpmnElement="Flow_31">
|
<bpmndi:BPMNEdge id="Flow_31_di" bpmnElement="Flow_31">
|
||||||
<di:waypoint x="3630" y="170"/>
|
<di:waypoint x="3630" y="170"/>
|
||||||
<di:waypoint x="3695" y="170"/>
|
<di:waypoint x="3650" y="170"/>
|
||||||
|
<di:waypoint x="3650" y="255"/>
|
||||||
<di:waypoint x="3695" y="255"/>
|
<di:waypoint x="3695" y="255"/>
|
||||||
<di:waypoint x="3720" y="255"/>
|
<di:waypoint x="3720" y="255"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -697,7 +715,8 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_35_di" bpmnElement="Flow_35">
|
<bpmndi:BPMNEdge id="Flow_35_di" bpmnElement="Flow_35">
|
||||||
<di:waypoint x="2680" y="255"/>
|
<di:waypoint x="2680" y="255"/>
|
||||||
<di:waypoint x="2680" y="205"/>
|
<di:waypoint x="2700" y="255"/>
|
||||||
|
<di:waypoint x="2700" y="205"/>
|
||||||
<di:waypoint x="2795" y="205"/>
|
<di:waypoint x="2795" y="205"/>
|
||||||
<di:waypoint x="2795" y="230"/>
|
<di:waypoint x="2795" y="230"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -715,6 +734,7 @@
|
|||||||
<bpmndi:BPMNEdge id="Flow_37_di" bpmnElement="Flow_37">
|
<bpmndi:BPMNEdge id="Flow_37_di" bpmnElement="Flow_37">
|
||||||
<di:waypoint x="2820" y="255"/>
|
<di:waypoint x="2820" y="255"/>
|
||||||
<di:waypoint x="2845" y="255"/>
|
<di:waypoint x="2845" y="255"/>
|
||||||
|
<di:waypoint x="2940" y="255"/>
|
||||||
<di:waypoint x="2960" y="255"/>
|
<di:waypoint x="2960" y="255"/>
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="2817.5" y="261" width="30" height="14"/>
|
<dc:Bounds x="2817.5" y="261" width="30" height="14"/>
|
||||||
@@ -722,6 +742,7 @@
|
|||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_38_di" bpmnElement="Flow_38">
|
<bpmndi:BPMNEdge id="Flow_38_di" bpmnElement="Flow_38">
|
||||||
<di:waypoint x="3060" y="255"/>
|
<di:waypoint x="3060" y="255"/>
|
||||||
|
<di:waypoint x="3080" y="255"/>
|
||||||
<di:waypoint x="3125" y="255"/>
|
<di:waypoint x="3125" y="255"/>
|
||||||
<di:waypoint x="3150" y="255"/>
|
<di:waypoint x="3150" y="255"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
@@ -735,7 +756,8 @@
|
|||||||
<bpmndi:BPMNEdge id="Flow_40_di" bpmnElement="Flow_40">
|
<bpmndi:BPMNEdge id="Flow_40_di" bpmnElement="Flow_40">
|
||||||
<di:waypoint x="4315" y="195"/>
|
<di:waypoint x="4315" y="195"/>
|
||||||
<di:waypoint x="4315" y="220"/>
|
<di:waypoint x="4315" y="220"/>
|
||||||
<di:waypoint x="4480" y="220"/>
|
<di:waypoint x="4460" y="220"/>
|
||||||
|
<di:waypoint x="4460" y="170"/>
|
||||||
<di:waypoint x="4480" y="170"/>
|
<di:waypoint x="4480" y="170"/>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="Flow_41_di" bpmnElement="Flow_41">
|
<bpmndi:BPMNEdge id="Flow_41_di" bpmnElement="Flow_41">
|
||||||
|
|||||||
@@ -615,6 +615,9 @@ GATEWAY_OUTWARD = {'N': (0, -1), 'S': (0, 1), 'E': (1, 0), 'W': (-1, 0)}
|
|||||||
# Halbe Kantenlaenge der Raute (Standardgroesse 50x50) reicht, um deren Kontur
|
# Halbe Kantenlaenge der Raute (Standardgroesse 50x50) reicht, um deren Kontur
|
||||||
# in jedem Fall sicher zu verlassen, bevor die Kante abbiegt.
|
# in jedem Fall sicher zu verlassen, bevor die Kante abbiegt.
|
||||||
GATEWAY_STUB = 25
|
GATEWAY_STUB = 25
|
||||||
|
# Gerades Stück an einer Aufgabe, wenn das andere Ende eine Raute ist (#23); passt
|
||||||
|
# in den kleinsten Gang (70) zwischen zwei Spalten bzw. Zeilen, auch von beiden Seiten.
|
||||||
|
RECHTECK_STUB = 20
|
||||||
|
|
||||||
|
|
||||||
def _dedupe_consecutive(points):
|
def _dedupe_consecutive(points):
|
||||||
@@ -688,35 +691,30 @@ def orthogonal_points(ox, oy, src_side, tx, ty, tgt_side,
|
|||||||
dieses Schritts (die einzige garantiert freie Koordinate) beim nächsten
|
dieses Schritts (die einzige garantiert freie Koordinate) beim nächsten
|
||||||
Abbiegen zunächst unverändert bleibt. Sonst würde die Kante beim
|
Abbiegen zunächst unverändert bleibt. Sonst würde die Kante beim
|
||||||
Umbiegen zum Ziel auf demselben Weg zurück durch die Raute laufen, den
|
Umbiegen zum Ziel auf demselben Weg zurück durch die Raute laufen, den
|
||||||
sie gerade erst verlassen hat."""
|
sie gerade erst verlassen hat.
|
||||||
|
|
||||||
|
Ist nur ein Ende eine Raute, bekommt auch das andere Ende (Aufgabe) einen
|
||||||
|
kurzen geraden Schritt senkrecht zu seiner Seite (RECHTECK_STUB); danach
|
||||||
|
wird wie zwischen zwei Rauten von Stub zu Stub geführt. Sonst liefe die
|
||||||
|
Kante am Aufgaben-Ende parallel zu dessen Kante, wenn die Anschlusspunkte
|
||||||
|
auf verschiedenen Achsen liegen (#23)."""
|
||||||
|
gemischt = src_is_gateway != tgt_is_gateway
|
||||||
sx, sy = ox, oy
|
sx, sy = ox, oy
|
||||||
if src_is_gateway:
|
if src_is_gateway or gemischt:
|
||||||
dx, dy = GATEWAY_OUTWARD[src_side]
|
dx, dy = GATEWAY_OUTWARD[src_side]
|
||||||
sx, sy = ox + dx * GATEWAY_STUB, oy + dy * GATEWAY_STUB
|
stub = GATEWAY_STUB if src_is_gateway else RECHTECK_STUB
|
||||||
|
sx, sy = ox + dx * stub, oy + dy * stub
|
||||||
ex, ey = tx, ty
|
ex, ey = tx, ty
|
||||||
if tgt_is_gateway:
|
if tgt_is_gateway or gemischt:
|
||||||
dx, dy = GATEWAY_OUTWARD[tgt_side]
|
dx, dy = GATEWAY_OUTWARD[tgt_side]
|
||||||
ex, ey = tx + dx * GATEWAY_STUB, ty + dy * GATEWAY_STUB
|
stub = GATEWAY_STUB if tgt_is_gateway else RECHTECK_STUB
|
||||||
|
ex, ey = tx + dx * stub, ty + dy * stub
|
||||||
|
|
||||||
src_axis = 'v' if src_side in ('N', 'S') else 'h'
|
src_axis = 'v' if src_side in ('N', 'S') else 'h'
|
||||||
tgt_axis = 'v' if tgt_side in ('N', 'S') else 'h'
|
tgt_axis = 'v' if tgt_side in ('N', 'S') else 'h'
|
||||||
|
|
||||||
if not src_is_gateway and not tgt_is_gateway:
|
if not src_is_gateway and not tgt_is_gateway:
|
||||||
points = _orthogonal_middle(ox, oy, src_side, tx, ty, tgt_side)
|
points = _orthogonal_middle(ox, oy, src_side, tx, ty, tgt_side)
|
||||||
elif src_is_gateway and not tgt_is_gateway:
|
|
||||||
# sy/sx (die Stub-Achse) fixieren, solange die andere Koordinate zum
|
|
||||||
# Ziel hin schwenkt - erst danach auf der Stub-Achse zum Ziel.
|
|
||||||
if src_axis == 'v':
|
|
||||||
points = [(ox, oy), (sx, sy), (tx, sy), (tx, ty)]
|
|
||||||
else:
|
|
||||||
points = [(ox, oy), (sx, sy), (sx, ty), (tx, ty)]
|
|
||||||
elif tgt_is_gateway and not src_is_gateway:
|
|
||||||
# Spiegelbildlich: erst auf der Stub-Achse des Ziels ankommen, erst
|
|
||||||
# danach dorthin schwenken.
|
|
||||||
if tgt_axis == 'v':
|
|
||||||
points = [(ox, oy), (ox, ey), (ex, ey), (tx, ty)]
|
|
||||||
else:
|
|
||||||
points = [(ox, oy), (ex, oy), (ex, ey), (tx, ty)]
|
|
||||||
else:
|
else:
|
||||||
# Beide Enden sind Rauten: von der Stub-Achse des Starts direkt auf
|
# Beide Enden sind Rauten: von der Stub-Achse des Starts direkt auf
|
||||||
# die Stub-Achse des Ziels schwenken, jede nur einmal verlassen.
|
# die Stub-Achse des Ziels schwenken, jede nur einmal verlassen.
|
||||||
|
|||||||
@@ -655,6 +655,25 @@ def test_anmerkung_waechst_mit_ihrem_text():
|
|||||||
assert kurz_w == lang_w and lang_h > kurz_h
|
assert kurz_w == lang_w and lang_h > kurz_h
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("src_side, tgt_side, src_gw, tgt_gw", [
|
||||||
|
('E', 'N', False, True), # Aufgabe (Ostseite) -> Gateway (Nordpunkt), Lanes-Layout
|
||||||
|
('S', 'W', True, False), # Gateway (Südpunkt) -> Aufgabe (Westseite), Lanes-Layout
|
||||||
|
('S', 'E', False, True), # Aufgabe (Südseite) -> Gateway (Ostpunkt), Layout ohne Lanes
|
||||||
|
('W', 'N', True, False), # Gateway (Westpunkt) -> Aufgabe (Nordseite), Layout ohne Lanes
|
||||||
|
])
|
||||||
|
def test_kante_zwischen_aufgabe_und_gateway_setzt_an_beiden_enden_rechtwinklig_an(src_side, tgt_side, src_gw, tgt_gw):
|
||||||
|
"""Prüft, dass eine Kante zwischen Aufgabe und Gateway an beiden Enden rechtwinklig zur jeweiligen Seite ansetzt,
|
||||||
|
auch wenn die Seiten auf verschiedenen Achsen liegen (Issue #23)."""
|
||||||
|
punkte = m.orthogonal_points(100, 100, src_side, 400, 300, tgt_side, src_is_gateway=src_gw, tgt_is_gateway=tgt_gw)
|
||||||
|
def achse(seite):
|
||||||
|
return 'waagrecht' if seite in ('E', 'W') else 'senkrecht'
|
||||||
|
def verlauf(a, b):
|
||||||
|
return 'waagrecht' if abs(a[1] - b[1]) < 1e-6 else 'senkrecht'
|
||||||
|
assert verlauf(punkte[0], punkte[1]) == achse(src_side)
|
||||||
|
assert verlauf(punkte[-2], punkte[-1]) == achse(tgt_side)
|
||||||
|
assert all(verlauf(a, b) and (a[0] == b[0] or a[1] == b[1]) for a, b in zip(punkte, punkte[1:]))
|
||||||
|
|
||||||
|
|
||||||
def test_ausgabe_ist_wohlgeformtes_xml(tmp_path):
|
def test_ausgabe_ist_wohlgeformtes_xml(tmp_path):
|
||||||
"""Prüft, dass die erzeugte .bpmn-Datei sich als valides XML parsen laesst."""
|
"""Prüft, dass die erzeugte .bpmn-Datei sich als valides XML parsen laesst."""
|
||||||
src = tmp_path / 'prozess.md'
|
src = tmp_path / 'prozess.md'
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ Skills sind übernommen, alles QGIS- und Plugin-Spezifische ist entfernt. Kern i
|
|||||||
|
|
||||||
## Erledigt
|
## Erledigt
|
||||||
|
|
||||||
|
- 25.09.2026 **Kanten setzen an Aufgaben rechtwinklig an** (#23): Stub am Aufgaben-Ende auch bei Kanten zu
|
||||||
|
bzw. von Gateways; 17 Kantenenden in den Beispielen korrigiert.
|
||||||
|
|
||||||
- 25.09.2026 **Beschriftungen überlappen nicht mehr** (#14): Gateway-Beschriftungen mit fester Position (45°,
|
- 25.09.2026 **Beschriftungen überlappen nicht mehr** (#14): Gateway-Beschriftungen mit fester Position (45°,
|
||||||
sonst nächste freie Stelle), Anmerkungen rechts neben dem Pool in passender Größe, Kantenbeschriftungen
|
sonst nächste freie Stelle), Anmerkungen rechts neben dem Pool in passender Größe, Kantenbeschriftungen
|
||||||
waagrecht aus Gateways unter der Linie.
|
waagrecht aus Gateways unter der Linie.
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik
|
|||||||
|
|
||||||
## BPMN und PICTURE (Skill sn-bpmn, md_to_bpmn.py)
|
## BPMN und PICTURE (Skill sn-bpmn, md_to_bpmn.py)
|
||||||
|
|
||||||
|
- **Auch das Aufgaben-Ende einer Gateway-Kante braucht ein gerades Stück.** Das Gateway-Ende bekommt einen festen
|
||||||
|
Anschlusspunkt (N/O/S/W), das Aufgaben-Ende die Layout-Seite (mit Lanes O/W, ohne Lanes N/S). Liegen beide auf
|
||||||
|
verschiedenen Achsen, lief die Kante früher direkt an der Aufgabenkante entlang. Jetzt bekommt die Aufgabe einen
|
||||||
|
Stub (`RECHTECK_STUB = 20`) senkrecht zu ihrer Seite, danach geht es wie zwischen zwei Rauten von Stub zu Stub.
|
||||||
|
Geprüft mit `test_kanten_setzen_an_aufgaben_rechtwinklig_an` über alle Beispiele. Im Belastungstest aus #12 sind
|
||||||
|
378 schräge Anschlüsse verschwunden. Dafür laufen in 4 künstlichen Fällen mit Querverbindung zwischen Zweigen
|
||||||
|
Kanten durch eine Aufgabe, in 2 anderen nicht mehr (Art von #22). (#23, 25.09.2026)
|
||||||
- **PICTURE übernimmt Beschriftungspositionen und Kästchengrößen aus der Datei.** Ohne `BPMNLabel` setzt es die
|
- **PICTURE übernimmt Beschriftungspositionen und Kästchengrößen aus der Datei.** Ohne `BPMNLabel` setzt es die
|
||||||
Gateway-Beschriftung auf 180° (unter die Raute), wo der südliche Pfad und dessen Beschriftung sie schneiden. Im
|
Gateway-Beschriftung auf 180° (unter die Raute), wo der südliche Pfad und dessen Beschriftung sie schneiden. Im
|
||||||
PICTURE-Editor steht sie auf 45°. Der Konverter setzt die Position deshalb selbst: 45°, sonst 45° rechts vom
|
PICTURE-Editor steht sie auf 45°. Der Konverter setzt die Position deshalb selbst: 45°, sonst 45° rechts vom
|
||||||
|
|||||||
@@ -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}"
|
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():
|
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."""
|
"""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")
|
defs = baue(SKILL / "beispiele" / "beispiel_prozess.md")
|
||||||
|
|||||||
Reference in New Issue
Block a user