]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Avoid crashes with fully direct-routed connections release/1.35.3
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 25 Nov 2022 11:55:12 +0000 (13:55 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 25 Nov 2022 12:03:03 +0000 (14:03 +0200)
Also avoids eternal looping in connection path rendering

gitlab #885

(cherry picked from commit 6b2f5a6be2bd75df3cc12fa875174b2d117b8563)

Change-Id: I18f251d9e430f7477332b97e6677a936bd429852

bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/DegeneratedRoutePoint.java [new file with mode: 0644]
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java

diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/DegeneratedRoutePoint.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/DegeneratedRoutePoint.java
new file mode 100644 (file)
index 0000000..57b73e1
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.connection;
+
+import gnu.trove.map.hash.THashMap;
+
+/**
+ * Route point that is connected to two direct terminals.
+ * 
+ * @author Hannu Niemisto
+ */
+public class DegeneratedRoutePoint extends RoutePoint {
+
+    public DegeneratedRoutePoint() {
+        super();
+    }
+
+    public DegeneratedRoutePoint(double x, double y) {
+        super(x, y);
+    }
+
+    @Override
+    DegeneratedRoutePoint copy(THashMap<Object, Object> map) {
+        DegeneratedRoutePoint copy = (DegeneratedRoutePoint) map.get(this);
+        if (copy == null) {
+            copy = new DegeneratedRoutePoint(x, y);
+            map.put(this, copy);
+        }
+        return copy;
+    }
+
+}
\ No newline at end of file
index 62d3de68fae5f110a6b08eb80dcc7558ca34df80..da1fc702a67d7d39e8d7662c77d95a135768d98b 100644 (file)
@@ -302,6 +302,11 @@ public class RouteGraph implements Serializable {
         needsUpdate = true;
     }
 
+    private boolean isDirectDirectConnection() {
+        return !isSimpleConnection && terminals.size() == 2 && terminals.get(0).hasDirectConnection()
+                && terminals.get(1).hasDirectConnection() && lines.size() <= 1;
+    }
+
     /**
      * Updates transient route lines, route link positions
      * and sorts route points of each route line.
@@ -375,6 +380,10 @@ public class RouteGraph implements Serializable {
             }
             }
         }
+        else if(isFullyDirectConnectionCase()) {
+            routeDirectDirectOneLineCase();
+            return;
+        }
         else {
             caseId = SimpleConnectionUtility.COMPLEX_CONNECTION;
             routeFromTerminals(false);
@@ -394,7 +403,36 @@ public class RouteGraph implements Serializable {
             line.sortPoints();
         }
     }
-    
+
+    private boolean isFullyDirectConnectionCase() {
+        if (lines.size() != 1 && terminals.size() > 0)
+            return false;
+        for (RouteTerminal t : terminals) {
+            if (!t.hasDirectConnection())
+                return false;
+        }
+        return true;
+    }
+
+       private void routeDirectDirectOneLineCase() {
+        RouteLine line = lines.get(0);
+        double x = 0, y = 0;
+        double scale = 1 / terminals.size();
+        if(line.isHorizontal) {
+            y = line.position;
+            for (RouteTerminal t : terminals)
+                x += t.x;
+            x *= scale;
+        }
+        else {
+            x = line.position;
+            for (RouteTerminal t : terminals)
+                y += t.y;
+            y *= scale;
+        }
+        line.addPoint(new DegeneratedRoutePoint(x, y));
+    }
+
     static class Interval {
         public final double min;
         public final double max;
@@ -471,7 +509,7 @@ public class RouteGraph implements Serializable {
     public RouteLine pickLine(double x, double y, double tolerance, int mask) {
         if(needsUpdate)
             update();
-        if(isSimpleConnection && transientLines.isEmpty()) {
+        if( (isSimpleConnection && transientLines.isEmpty()) || isDirectDirectConnection() ) {
             if(terminals.size() == 2) {
                 if((mask & PICK_TRANSIENT_LINES) == 0)
                     return null;
@@ -1383,16 +1421,14 @@ public class RouteGraph implements Serializable {
     public void getPath2D(Path2D path) {
         if(needsUpdate)
             update();
-        
-        if(isSimpleConnection && transientLines.isEmpty()) {
-            if(terminals.size() == 2) {
-                RouteTerminal a = terminals.get(0);
-                RouteTerminal b = terminals.get(1);
-                if(a.hasDirectConnection() || b.hasDirectConnection()) {
-                    path.moveTo(a.x, a.y);
-                    path.lineTo(b.x, b.y);
-                    return;
-                }
+
+        if((isSimpleConnection && transientLines.isEmpty() && terminals.size() == 2) || isDirectDirectConnection()) {
+            RouteTerminal a = terminals.get(0);
+            RouteTerminal b = terminals.get(1);
+            if(a.hasDirectConnection() || b.hasDirectConnection()) {
+                path.moveTo(a.x, a.y);
+                path.lineTo(b.x, b.y);
+                return;
             }
         }
 
@@ -1428,8 +1464,14 @@ public class RouteGraph implements Serializable {
         while(true) {
             if(cur != curLine.getEnd())                    
                 cur = curLine.getEnd();
-            else
-                cur = curLine.getBegin();
+            else {
+                RoutePoint next = curLine.getBegin();
+                // Break if stuck at the same RoutePoint.
+                // This can happen with fully direct-routed connections.
+                if (next == cur)
+                    return;
+                cur = next;
+            }
             if(begins.remove(cur) != null || !(cur instanceof RouteLink)) {
                 addPathEnd(path, cur, curLine);
                 return;