{"id":2904,"date":"2019-03-27T08:42:13","date_gmt":"2019-03-27T07:42:13","guid":{"rendered":"http:\/\/www.capri-soft.de\/blog\/?p=2904"},"modified":"2019-04-23T10:00:14","modified_gmt":"2019-04-23T08:00:14","slug":"sparx-systems-enterprise-architect-sql-interpretation-der-linkdarstellung-link-layout-eines-diagrams-ueber-das-relationale-ea-datenmodell","status":"publish","type":"post","link":"https:\/\/www.capri-soft.de\/blog\/?p=2904","title":{"rendered":"Sparx Systems Enterprise Architect + SQL : Interpretation der  Linkdarstellung \/ Link Layout eines Diagrams \u00fcber das relationale EA Datenmodell"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Problem<\/h2>\n\n\n\n<p>\u00dcber das relationale Datenmodell des Enterprise Architects soll die Geometrie von Links auf Diagrammen rekonstruiert werden. Die n\u00f6tigen Felder sind in den Tiefen der Datenstrukturen aus Tabellen und Attributen in einem Memo-\/Freitext-Feld versteckt. <\/p>\n\n\n\n<p>Ich entwickle zur Zeit eine eigene Interpretation des EA-Renderers mit GoJS, wo ich auf das Problem gesto\u00dfen bin, dass ich aufgrund der unterschiedlichen Connectorstyles, welche f\u00fcr einen Link auf unterschiedlichen Diagrammen eine andere Geometrie vorweisen kann, den Endpunkt nicht ermitteln kann. Eine L\u00f6sung hierzu m\u00f6chte ich hier ausarbeiten.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Analyse<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Relationen<\/h3>\n\n\n\n<p>Ein Link\/Connector (Tabelle &#8222;<strong>t_connector<\/strong>&#8222;) kann auf mehreren Diagrammen unterschiedliche Darstellungen haben. Die Geometrie des Links<em> auf einem Diagramm<\/em> wird \u00fcber das Attribut &#8222;<strong>Geometry<\/strong>&#8220; der Tabelle &#8222;<strong>t_diagramlinks<\/strong>&#8220; bestimmt.  Das Attribut &#8222;Geometry&#8220; ist ein Langtext-\/Memo-Feld und wird im folgenden einer Analyse unterzogen, da sich im Internet nur sehr sp\u00e4rlich Informationen \u00fcber den Aufbau und die Bedeutung des Doppelpunkt-separierten Strings finden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Die Tabelle &#8222;t_diagramlinks&#8220;<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p> &#8220; A DiagramLink is an object that holds display information on a connector between two elements in a specific diagram. It includes, for example, the custom points and display appearance. It can be accessed from the Diagram DiagramLinks collection. &#8220; <\/p><cite>https:\/\/sparxsystems.com\/enterprise_architect_user_guide\/<br>14.0\/automation\/diagramlinks.html<\/cite><\/blockquote>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td><strong><u>Attribute<\/u><\/strong><\/td><td><strong><u>Remarks<\/u><\/strong> <\/td><\/tr><tr><td> <br>ConnectorID <\/td><td><strong>Long<\/strong><br>Notes: Read\/Write<br>The ID of the associated connector. <\/td><\/tr><tr><td> <br>DiagramID <\/td><td><strong>Long<\/strong><br>Notes: Read\/Write<br>The local ID for the associated diagram. <\/td><\/tr><tr><td> <br><em><strong><u>Geometry <\/u><\/strong><\/em><\/td><td><strong>String (Memo-Field)<\/strong><br>Notes: Read\/Write<br><strong><em>The geometry associated with the current connector in this diagram. <\/em><\/strong><\/td><\/tr><tr><td> <br>HiddenLabels <\/td><td><strong>Boolean<\/strong><br>Notes: Indicates if this connector&#8217;s labels are hidden on the diagram. <\/td><\/tr><tr><td> <br>InstanceID <\/td><td><strong>Long<\/strong><br>Notes: Read only<br>The connector identifier for the current model. <\/td><\/tr><tr><td> <br>IsHidden <\/td><td><strong>Boolean<\/strong><br>Notes: Read\/Write<br>Indicates if this item is hidden or not. <\/td><\/tr><tr><td> <br>LineColor <\/td><td> <strong>Long<\/strong><br>Notes: Sets the line color of the connector.<br>Set to -1 to reset to the default color in the model. <\/td><\/tr><tr><td> <br>LineStyle <\/td><td><strong>Long<\/strong><br>Notes: Sets the line style of the connector.<br>1 = Direct<br>2 = Auto Routing<br>3 = Custom Line<br>4 = Tree Vertical<br>5 = Tree Horizontal<br>6 = Lateral Vertical<br>7 = Lateral Horizontal<br>8 = Orthogonal Square<br>9 = Orthogonal Rounded <\/td><\/tr><tr><td> <br>LineWidth <\/td><td> <br><strong>Long<\/strong><br>Notes: Sets the line width of the connector. <\/td><\/tr><tr><td> <br>ObjectType <\/td><td><strong>ObjectType<\/strong><br>Notes: Read only<br>Distinguishes objects referenced through a Dispatch interface. <\/td><\/tr><tr><td> <br>Path <\/td><td><strong>String<\/strong><br>Notes: Read\/Write<br>The path of the connector in this diagram. <\/td><\/tr><tr><td> <br>SourceInstanceUID <\/td><td><strong>String<\/strong><br>Notes: Read only<br>Returns the Unique Identifier of the source object. <\/td><\/tr><tr><td> <br>SuppressSegment <\/td><td><strong>Boolean<\/strong><br>Notes: Indicates whether the connector segments are suppressed. <\/td><\/tr><tr><td> <br>Style <\/td><td><strong>String<\/strong><br>Notes: Read\/Write<br>Additional style information; for example, color or thickness. <\/td><\/tr><tr><td> <br>TargetInstanceUID <\/td><td><strong>String<\/strong><br>Notes: Read only<br>Returns the Unique Identifier of the target object. <\/td><\/tr><\/tbody><\/table>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?ssl=1\"><img loading=\"lazy\" decoding=\"async\" width=\"1114\" height=\"850\" data-attachment-id=\"2909\" data-permalink=\"https:\/\/www.capri-soft.de\/blog\/?attachment_id=2909\" data-orig-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?fit=1114%2C850&amp;ssl=1\" data-orig-size=\"1114,850\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?fit=474%2C362&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?fit=640%2C488\" alt=\"\" class=\"wp-image-2909\" srcset=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?w=1114&amp;ssl=1 1114w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?resize=300%2C229&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?resize=768%2C586&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?resize=1024%2C781&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/image.png?w=948&amp;ssl=1 948w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><figcaption>Der String &#8222;Geometry&#8220; wird in MDB Viewer Plus als (MEMO) dargestellt, das MemoFeld kann allerdings rechts eingeblendet werden. Dort tauchen einige weitere versteckte Attribute f\u00fcr die Geometry der Linie auf, welche im nachfolgendem Analysiert werden<br><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"211\" data-attachment-id=\"2936\" data-permalink=\"https:\/\/www.capri-soft.de\/blog\/?attachment_id=2936\" data-orig-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?fit=512%2C228&amp;ssl=1\" data-orig-size=\"512,228\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?fit=474%2C211&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?resize=474%2C211&#038;ssl=1\" alt=\"\" class=\"wp-image-2936\" srcset=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?w=512&amp;ssl=1 512w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?resize=300%2C134&amp;ssl=1 300w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><figcaption>Die Auswahl des LineStyles f\u00fcr einen Connector, wie oben im Screenshot dargestellt, bestimmt die Darstellung.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"110\" data-attachment-id=\"2934\" data-permalink=\"https:\/\/www.capri-soft.de\/blog\/?attachment_id=2934\" data-orig-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image.png?fit=809%2C187&amp;ssl=1\" data-orig-size=\"809,187\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image.png?fit=474%2C110&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=474%2C110&#038;ssl=1\" alt=\"\" class=\"wp-image-2934\" srcset=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image.png?w=809&amp;ssl=1 809w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=300%2C69&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=768%2C178&amp;ssl=1 768w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><figcaption>Die LineStyles werden in der Tabelle [t_diagramlinks] und \u00fcber<strong> Mode={1,2,3}<\/strong> und dem optionalen Zusatz <strong>TREE={V,H,OS,OR,LV,LH}:Mode=3 <\/strong>f\u00fcr Mode &#8222;3&#8220; gespeichert.<\/figcaption><\/figure>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"392\" data-attachment-id=\"2941\" data-permalink=\"https:\/\/www.capri-soft.de\/blog\/?attachment_id=2941\" data-orig-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_mit_rechteck.jpg?fit=500%2C413&amp;ssl=1\" data-orig-size=\"500,413\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"schnittpunkt_mit_rechteck\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_mit_rechteck.jpg?fit=474%2C392&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_mit_rechteck.jpg?resize=474%2C392&#038;ssl=1\" alt=\"\" class=\"wp-image-2941\" srcset=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_mit_rechteck.jpg?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_mit_rechteck.jpg?resize=300%2C248&amp;ssl=1 300w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><figcaption>Das Hauptproblem: Das Datenmodell besitzt nicht die Information, an welcher Seite der End-Knoten\/das Ziel-Rechteck geschnitten wird. Lediglich \u00fcber das Attribut t_diagrammlinks.Geometry l\u00e4sst sich \u00fcber den CSV-Value &#8222;Edge&#8220; die Startseite des Startknotens bestimmen.<\/figcaption><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Fremdmeinungen einholen &#8211; ein Ausflug in die Forenwelt<\/h2>\n\n\n\n<p>Ich habe mich aus Gr\u00fcnden der Kollaboration entschieden, die Analysen in Stackoverflow und EA fortzuf\u00fchren. Hier finden sich die Links zu meinem Beitrag:<\/p>\n\n\n\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/55341368\/enterprise-architect-how-to-get-the-edge-of-the-end-node-using-a-sql-query-on\">https:\/\/stackoverflow.com\/questions\/55341368\/enterprise-architect-how-to-get-the-edge-of-the-end-node-using-a-sql-query-on <\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.sparxsystems.com\/forums\/smf\/index.php\/topic,42536.0.html\">https:\/\/www.sparxsystems.com\/forums\/smf\/index.php\/topic,42536.0.html<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/matheplanet.de\/matheplanet\/nuke\/html\/viewtopic.php?topic=241211\">https:\/\/matheplanet.de\/matheplanet\/nuke\/html\/viewtopic.php?topic=241211<\/a><\/p>\n\n\n\n<p><strong>Fazit: <\/strong>Obwohl mir kein Forum eine nutzbare L\u00f6sung angeboten hat, lohnt es sich sich neue Anregungen zu dem Problem einzuholen<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">L\u00f6sung f\u00fcr das Problem mit der fehlenden Ecke des Zielknoten (Target Edge) &#8211; Rechteckschnitt <\/h2>\n\n\n\n<p>Im Datenmodell wird die Mouse-Release Position \u00fcber Geometry EX\/EY (Geometry) gespeichert, was allerdings nicht der Schnittpunkt mit dem Rechteck ist.<\/p>\n\n\n\n<p>Mit 4 Geraden l\u00e4sst sich das Rechteck bestimmen (obgleich nat\u00fcrlich auch Punkte existieren, die nicht auf dem Rechteck liegen).<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"632\" data-attachment-id=\"2942\" data-permalink=\"https:\/\/www.capri-soft.de\/blog\/?attachment_id=2942\" data-orig-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite1.jpg?fit=908%2C1210&amp;ssl=1\" data-orig-size=\"908,1210\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"schnittpunkt_seite1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite1.jpg?fit=474%2C632&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite1.jpg?resize=474%2C632&#038;ssl=1\" alt=\"\" class=\"wp-image-2942\" srcset=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite1.jpg?resize=768%2C1024&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite1.jpg?resize=225%2C300&amp;ssl=1 225w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite1.jpg?w=908&amp;ssl=1 908w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><figcaption>Seite 1 der L\u00f6sung<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"632\" data-attachment-id=\"2943\" data-permalink=\"https:\/\/www.capri-soft.de\/blog\/?attachment_id=2943\" data-orig-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite2.jpg?fit=908%2C1210&amp;ssl=1\" data-orig-size=\"908,1210\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"schnittpunkt_seite2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite2.jpg?fit=474%2C632&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite2.jpg?resize=474%2C632&#038;ssl=1\" alt=\"\" class=\"wp-image-2943\" srcset=\"https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite2.jpg?resize=768%2C1024&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite2.jpg?resize=225%2C300&amp;ssl=1 225w, https:\/\/i0.wp.com\/www.capri-soft.de\/blog\/wp-content\/uploads\/2019\/03\/schnittpunkt_seite2.jpg?w=908&amp;ssl=1 908w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Erzeuge eine eigene Link-Klasse f\u00fcr das Routing der Pfeile, die von Hand gezogen wurden \n\/\/ und \u00fcber spezielle Attribute in der EAP-Datei definiert werden\n\/\/ Ruft die Superklasse von go.Link im Konstruktor auf\nfunction MultiNodePathLink() {\n    go.Link.call(this);\n}\ngo.Diagram.inherit(MultiNodePathLink, go.Link); \/\/ Erben von go.Link\n\n\/\/ ignores this.routing, this.adjusting, this.corner, this.smoothness, this.curviness\n\/** @override *\/\nMultiNodePathLink.prototype.computePoints = function () {\n\n    \/\/ Die this Referenz ist hier ist ein geerbter ein go.Link. der bei Links\n    var startNode = this.fromNode;\n    var startNodeX = startNode.location.M;  \/\/ X-Koordinate vom Startknoten\n    var startNodeY = startNode.location.N; \/\/ Y-Koordinate vom Startknoten\n\n    var endNode = this.toNode;\n    var endNodeX = endNode.location.M;  \/\/ X-Koordinate vom Startknoten\n    var endNodeY = endNode.location.N; \/\/ Y-Koordinate vom Startknoten\n   \n    var startNodeData = startNode.data; \/\/ Das sind die Daten\n    var endNodeData = endNode.data; \/\/ Das sind die Daten\n\n    \/\/ Die Link-Daten\n    var linkProperties = this.data;\n    \/\/** Das Feld Style in &#x5B;t_diagramlink] bestimmt die Connector-Darstellung  **\/\n    \/\/ https:\/\/www.capri-soft.de\/blog\/?p=2904\n    \/*\n     *  1 = Direct                    Mode=1\n     *  2 = Auto Routing              Mode=2\n     *  3 = Custom Line               Mode=3\n     *  4 = Tree Vertical             Mode=3;TREE=V\n     *  5 = Tree Horizontal           Mode=3;TREE=H\n     *  6 = Lateral Vertical          Mode=3;TREE=LV\n     *  7 = Lateral Horizontal        Mode=3;TREE=LH\n     *  8 = Orthogonal Square         Mode=3;TREE=OS\n     *  9 = Orthogonal Rounded        Mode=3;TREE=OR\n     *\/\n    var styleStringArray = linkProperties.style.split(&quot;;&quot;);\n    var mode = -1;\n    var tree = &#039;&#039;;\n    for (var i = 0; i &lt; styleStringArray.length; i++) {\n        if (styleStringArray&#x5B;i].trim().indexOf(&#039;Mode=&#039;) &gt; -1) {\n            mode = styleStringArray&#x5B;i].replace(&#039;Mode=&#039;, &#039;&#039;);\n        }\n\n        if (styleStringArray&#x5B;i].trim().indexOf(&#039;TREE=&#039;) &gt; -1) {\n            tree = styleStringArray&#x5B;i].replace(&#039;TREE=&#039;, &#039;&#039;);\n        }\n    }\n\n\n\n    \/\/ In der Tabelle t_diagramlinks in der Freitextspalte &quot;Geometry&quot; wird in einem CSV-String \n    \/\/ gespeichert, wie der Link letztendlich auf dem Diagram gezogen wurde\n    var geometryString = linkProperties.geometry.split(&quot;;&quot;);\n    var sx, sy, ex, ey, edge;\n    for (var i = 0; i &lt; geometryString.length; i++) {\n        \/\/ SX and SY are relative to the centre of the start object \n        if (geometryString&#x5B;i].trim().indexOf(&#039;SX=&#039;) &gt; -1) sx = geometryString&#x5B;i].replace(&#039;SX=&#039;, &#039;&#039;);\n        if (geometryString&#x5B;i].trim().indexOf(&#039;SY=&#039;) &gt; -1) sy = geometryString&#x5B;i].replace(&#039;SY=&#039;, &#039;&#039;);\n\n        \/\/ EX and EY are relative to the centre of the end object\n        if (geometryString&#x5B;i].trim().indexOf(&#039;EX=&#039;) &gt; -1) ex = geometryString&#x5B;i].replace(&#039;EX=&#039;, &#039;&#039;);\n        if (geometryString&#x5B;i].trim().indexOf(&#039;EY=&#039;) &gt; -1) ey = geometryString&#x5B;i].replace(&#039;EY=&#039;, &#039;&#039;);\n\n        \/\/ EDGE ranges in value from 1-4, with 1=Top, 2=Right, 3=Bottom, 4=Left (Outgoing Point of the Start Object)\n        if (geometryString&#x5B;i].trim().indexOf(&#039;EDGE=&#039;) &gt; -1) edge = geometryString&#x5B;i].replace(&#039;EDGE=&#039;, &#039;&#039;);\n    }\n    \n\n\n    \/\/ Hier beginnt das Custom-Routing\n    if (typeof (sx) === &quot;undefined&quot; || typeof (sy) === &quot;undefined&quot; || typeof (ex) === &quot;undefined&quot; || typeof (ey) === &quot;undefined&quot; || typeof (edge) === &quot;undefined&quot;) {\n        return;\n    }\n       \n    this.clearPoints();\n\n    if (linkProperties.start_object_name == &#039;System Verification Test Reports&#039; &amp;&amp; linkProperties.end_object_name == &#039;System test specifications&#039;) {\n        var test = &#039;irrsinn&#039;;\n    }\n    \/\/ Hier werden die Wege definiert f\u00fcr das gecustomizte Link Routing\n    \/\/ Geht der Link nach oben oder unten wird die Y-Koordinate des Startknotens genutzt (Weil Orthogonales Routing)\n    var startConnX = null;\n    var startConnY = null;\n    if (edge == 1) { \/\/ Ecke oben\n        startConnX = Math.abs(startNodeX) + Math.abs((startNode.actualBounds.width \/ 2) + new Number(sx));\n        startConnY = Math.abs(startNodeY);\n    }\n    else if (edge == 3) { \/\/ Ecke unten\n        startConnX = Math.abs(startNodeX) + Math.abs((startNode.actualBounds.width \/ 2) + new Number(sx));\n        startConnY = Math.abs(startNodeY) + new Number(startNode.actualBounds.height);\n    }\n    else if (edge == 2) { \/\/ Ecke rechts\n        startConnX = Math.abs(startNodeX) + startNode.actualBounds.width;\n        startConnY = Math.abs(startNodeY) + Math.abs((startNode.actualBounds.height \/ 2) - new Number(sy));\n    }\n    else if (edge == 4) { \/\/ Ecke links\n        startConnX = new Number(Math.abs(startNodeX));\n        startConnY = Math.round(startNodeY) + Math.round((startNode.actualBounds.height \/ 2) - new Number(sy));\n    }\n    else {\n        alert(&#039;Die Edge konnte nicht entdeckt werden! Ist der Geometry String in der EAP Datei richtig?&#039;);\n    }\n\n    this.addPoint(new go.Point(Math.round(startConnX), Math.round(startConnY)));\n\n    \/\/ Abfrage: Gibt es einen letzten Path Punkt?\n    var lastPathPunkt=false;\n    var lastPathPunktX, lastPathPunktY;\n\n    if (mode != 1)\n    {\n        \/\/ Routing \u00fcber die Zwischenwege\n        if (typeof linkProperties.conn_path !== &quot;undefined&quot; &amp;&amp; linkProperties.conn_path !== &quot;&quot;) {\n            var splittedArray = linkProperties.conn_path.split(&quot;;&quot;);\n            if (splittedArray.length &gt; 1) {\n                \/\/ Hier ist mindestens ein Wert vorhanden da auch der erste mit Semikolon abgeschlossen wird im Path vom EA\n                for (var i = 0; i &lt; splittedArray.length - 1; i++) {\n                    var einMittelPunkt = splittedArray&#x5B;i];\n                    var mittelPunktArray = einMittelPunkt.split(&quot;:&quot;);\n                    this.addPoint(new go.Point(Math.abs(new Number(mittelPunktArray&#x5B;0])), Math.abs(new Number(mittelPunktArray&#x5B;1]))))\n                    lastPathPunktX = Math.abs(new Number(mittelPunktArray&#x5B;0]));\n                    lastPathPunktY = Math.abs(new Number(mittelPunktArray&#x5B;1]));\n                    lastPathPunkt = true;\n                }\n            }\n        }\n    }\n\n    \/\/ Wenn es keinen Pfad gab,muss der letzte Punkt mit dem Startknoten identisch sein\n    if (lastPathPunkt == false) {\n        lastPathPunktX = Math.abs(Math.round(startConnX));\n        lastPathPunktY = Math.abs(Math.round(startConnY));\n    }\n\n    \/\/ End-Routing\n    \/\/ Der Endpunkt in EA in Document Coordinates\n    var endConnX = Math.abs(endNodeX) + Math.abs((endNode.actualBounds.width \/ 2) + new Number(ex));\n    var endConnY = Math.abs(endNodeY) + Math.abs((endNode.actualBounds.height \/ 2) - new Number(ey));\n\n    \/\/ Spezialf\u00e4lle bei horizontalen und vertikalen Linien:\n    if (endConnX == lastPathPunktX) {\n        \/\/ Es liegt eine vertikale Gerade (z.B. von oben nach unten) vor\n        this.addPoint(new go.Point(Math.round(lastPathPunktX), Math.round(lastPathPunktY)));\n        this.addPoint(new go.Point(Math.round(endConnX), Math.round(endConnY)));\n\n    } else if (endConnY == lastPathPunktY) {\n        \/\/ Es liegt eine horizontale Gerade (z.B. von rechts nach links) vor\n        this.addPoint(new go.Point(Math.round(lastPathPunktX), Math.round(lastPathPunktY)));\n        this.addPoint(new go.Point(Math.round(endConnX), Math.round(endConnY)));\n    } else {\n        \/\/ Es ist keine Gerade sondern ein Gerade, die mit y=m*x+b beschrieben werden kann\n\n        \/\/ 1.) Gerade zwischen Start- und Endpunkt ermittelnhn\n        \/\/      Ye-Ys\n        \/\/  m = -----    b=Ys-m*Xs oder b=Ye-m*Xe\n        \/\/      Xe-Xs\n        var m = (endConnY - lastPathPunktY) \/ (endConnX - lastPathPunktX);\n        var b = lastPathPunktY - m * lastPathPunktX\n\n        \/\/ 2.) Ermittlung der horizontalen und vertikalen Geraden des Rechteckes und dem Schnittpunkten\n        \/\/ Die Geraden, die das Rechteck definieren:\n        var rY1 = endNodeY;\n        var rY2 = endNodeY + endNode.actualBounds.height;\n        var rX1 = endNodeX;\n        var rX2 = endNodeX + endNode.actualBounds.width;\n        \/\/ (rX1, rY1) -zu-&gt; (rX2, rY2)\n        \n        \/\/ Horizontale Geraden: \n        \/\/     y - b\n        \/\/ x = -----\n        \/\/       m\n\n\n        var lengthToPoint = &#x5B;];\n\n        var sX1 = (rY1 - b) \/ m; \/\/ S1(sX1|rY1)\n        if (sX1 &gt;= rX1 &amp;&amp; sX1 &lt;= rX2) {\n            \/\/ Der Schnittpunkt sX1 ist am Rechteck\n            \/\/ Distanz: d=SQRT((y2-y1)^2+(x2-x1)^2)\n            var dS1 = Math.sqrt(Math.pow(rY1 - lastPathPunktY, 2) + Math.pow(sX1 - lastPathPunktX, 2));\n\n            lengthToPoint.push({\n                &quot;distanz&quot;: dS1,\n                &quot;x&quot;: sX1,\n                &quot;y&quot;: rY1\n            });\n\n        }\n\n        var sX2 = (rY2 - b) \/ m; \/\/ S2(sX2|rY2)\n        if (sX2 &gt;= rX1 &amp;&amp; sX2 &lt;= rX2) {\n            \/\/ Der Schnittpunkt sX2 ist am Rechteck\n            \/\/ Distanz: d=SQRT((y2-y1)^2+(x2-x1)^2)\n            var dS2 = Math.sqrt(Math.pow(rY2 - lastPathPunktY, 2) + Math.pow(sX2 - lastPathPunktX, 2));\n\n            lengthToPoint.push({\n                &quot;distanz&quot;: dS2,\n                &quot;x&quot;: sX2,\n                &quot;y&quot;: rY2\n            });\n        }\n\n        \/\/ Vertikale Geraden:\n        \/\/\n        \/\/ y = m*x + b\n\n        var sY1 = m * rX1 + b; \/\/ S3(rX1|sY1)\n        if (sY1 &gt;= rY1 &amp;&amp; sY1 &lt;= rY2) {\n            \/\/ Der Schnittpunkt sY1 ist am Rechteck\n            \/\/ Distanz: d=SQRT((y2-y1)^2+(x2-x1)^2)\n            var dS3 = Math.sqrt(Math.pow(sY1 - lastPathPunktY, 2) + Math.pow(rX1 - lastPathPunktX, 2));\n\n            lengthToPoint.push({\n                &quot;distanz&quot;: dS3,\n                &quot;x&quot;: rX1,\n                &quot;y&quot;: sY1\n            });\n        }\n\n        var sY2 = m * rX2 + b; \/\/ S4(rX2|sY2)\n        if (sY2 &gt;= rY1 &amp;&amp; sY2 &lt;= rY2) {\n            \/\/ Der Schnittpunkt sY2 ist am Rechteck\n            \/\/ Distanz: d=SQRT((y2-y1)^2+(x2-x1)^2)\n            var dS4 = Math.sqrt(Math.pow(sY2 - lastPathPunktY, 2) + Math.pow(rX2 - lastPathPunktX, 2));\n\n            lengthToPoint.push({\n                &quot;distanz&quot;: dS4,\n                &quot;x&quot;: rX2,\n                &quot;y&quot;: sY2\n            });\n        }\n\n        \/\/ Sortiere alle Punkte nach Distanz - der mit der kleinsten Entfernung isses\n        lengthToPoint.sort(function (a, b) { return a.distanz - b.distanz });\n\n        if (lengthToPoint.length &gt; 0)\n        {\n            this.addPoint(new go.Point(Math.round(lengthToPoint&#x5B;0].x), Math.round(lengthToPoint&#x5B;0].y)));\n        }\n        else\n        {\n            this.addPoint(new go.Point(Math.round(lastPathPunktX), Math.round(lastPathPunktY)));\n        }\n\n        \n    }\n\n    return true;\n};\n\/\/ end MultiNodePathLink class\n<\/pre><\/div><iframe src=\"http:\/\/www.facebook.com\/plugins\/like.php?href=https%3A%2F%2Fwww.capri-soft.de%2Fblog%2F%3Fp%3D2904&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light\" scrolling=\"no\" frameborder=\"0\" allowTransparency=\"true\" style=\"border:none; overflow:hidden; width:450px;margin-top:5px;\"><\/iframe>","protected":false},"excerpt":{"rendered":"<p>Problem \u00dcber das relationale Datenmodell des Enterprise Architects soll die Geometrie von Links auf Diagrammen rekonstruiert werden. Die n\u00f6tigen Felder sind in den Tiefen der Datenstrukturen aus Tabellen und Attributen in einem Memo-\/Freitext-Feld versteckt. Ich entwickle zur Zeit eine eigene Interpretation des EA-Renderers mit GoJS, wo ich auf das Problem gesto\u00dfen bin, dass ich aufgrund &hellip; <a href=\"https:\/\/www.capri-soft.de\/blog\/?p=2904\" class=\"more-link\"><span class=\"screen-reader-text\">Sparx Systems Enterprise Architect + SQL : Interpretation der  Linkdarstellung \/ Link Layout eines Diagrams \u00fcber das relationale EA Datenmodell<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-2904","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p4yGeN-KQ","jetpack_likes_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2904","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2904"}],"version-history":[{"count":14,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2904\/revisions"}],"predecessor-version":[{"id":2945,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2904\/revisions\/2945"}],"wp:attachment":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2904"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2904"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2904"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}