]> gerrit.simantics Code Review - simantics/district.git/commitdiff
Improve picking to prefer vertices and with a more useful pick area 14/3814/1
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 24 Jan 2020 12:52:53 +0000 (14:52 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 24 Jan 2020 12:52:53 +0000 (14:52 +0200)
gitlab #74

Change-Id: I6577a35f99523bcf9264bd3a12d48bbfde96beb2

org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DNPickSorter.java [new file with mode: 0644]
org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DNPointerInteractor.java

index e5ce207e51af69f3760724a92c5697aa3748d591..4ff231034935f30c3da0d694cde4debc56198e4e 100644 (file)
@@ -6,7 +6,6 @@ import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 
 import org.simantics.db.Resource;
@@ -15,6 +14,7 @@ import org.simantics.district.network.ui.adapters.DistrictNetworkEdgeElement;
 import org.simantics.district.network.ui.adapters.DistrictNetworkVertexElement;
 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
 import org.simantics.district.network.ui.nodes.NetworkDrawingNode;
+import org.simantics.district.network.ui.participants.DNPickSorter;
 import org.simantics.district.network.ui.participants.DynamicVisualisationContributionsParticipant;
 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
@@ -43,7 +43,7 @@ public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
 
     /**
      * Holds the current element for which hover information is shown.
-     * This is just to optimize the 
+     * This exists only to optimize the hover updating procedure.
      */
     private IElement currentHoverElement;
 
@@ -68,31 +68,8 @@ public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
         PickRequest req = new PickRequest(getPickRect(canvasPos, viewTransform)).context(getContext());
         List<IElement> pickables = new ArrayList<>();
         pick.pick(diagram, req, pickables);
-        
-
-        Comparator<IElement> nearestVerticesFirst = (IElement e1, IElement e2) -> {
-            // If there are any vertices in the elements, prefer those primarily.
-            DistrictNetworkVertexNode v1 = e1.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
-            DistrictNetworkVertexNode v2 = e2.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
-
-            // Don't reorder edges
-            if ((v1 == null && v2 == null))
-                return 0;
-
-            // Sort vertices in nearest first order
-            if (v1 != null && v2 != null) {
-                Rectangle2D b1 = v1.getBounds();
-                Rectangle2D b2 = v2.getBounds();
-                double dist1 = canvasPos.distanceSq(b1.getCenterX(), b1.getCenterY());
-                double dist2 = canvasPos.distanceSq(b2.getCenterX(), b2.getCenterY());
-                return dist1 < dist2 ? -1 : dist1 > dist2 ? 1 : 0;
-            }
-
-            // Always vertices before edges
-            return v1 != null && v2 == null ? -1 : 1;
-        };
 
-        Collections.sort(pickables, nearestVerticesFirst);
+        Collections.sort(pickables, DNPickSorter.nearestVerticesFirst(false, DNPickSorter.centerDistSq(canvasPos.getX(), canvasPos.getY())));
 
         updateHoveredElement(pickables, true, isConnectionTool, viewTransform);
         // Will repaint once the async hover info calculation is ready, no need to do it here
diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DNPickSorter.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DNPickSorter.java
new file mode 100644 (file)
index 0000000..82cd725
--- /dev/null
@@ -0,0 +1,105 @@
+package org.simantics.district.network.ui.participants;
+
+import java.awt.geom.Rectangle2D;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.ToDoubleFunction;
+
+import org.simantics.district.network.ui.adapters.DistrictNetworkEdgeElement;
+import org.simantics.district.network.ui.adapters.DistrictNetworkVertexElement;
+import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
+import org.simantics.g2d.diagram.handler.PickRequest;
+import org.simantics.g2d.diagram.handler.PickRequest.PickSorter;
+import org.simantics.g2d.element.ElementHints;
+import org.simantics.g2d.element.IElement;
+import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+
+/**
+ * @author Jani Simomaa
+ * @author Tuukka Lehtonen
+ */
+public class DNPickSorter implements PickSorter {
+
+    public static ToDoubleFunction<Rectangle2D> centerDistSq(double x, double y) {
+        return r -> {
+            double dx = r.getCenterX() - x;
+            double dy = r.getCenterY() - y;
+            return dx * dx + dy * dy;
+        };
+    }
+
+    public static ToDoubleFunction<Rectangle2D> centerDistSq(Rectangle2D r1) {
+        return centerDistSq(r1.getCenterX(), r1.getCenterY());
+    }
+
+    /**
+     * @param nearestLast      if <code>true</code> the nearest elements are sorted
+     *                         into the tail of the list, if <code>false</code>
+     *                         nearest elements are at the beginning of the list
+     * @param distanceFunction function used for calculating the distance of each
+     *                         element's bounding box
+     * @return comparator implementing the requested diagram element comparison
+     */
+    public static Comparator<IElement> nearestVerticesFirst(boolean nearestLast, ToDoubleFunction<Rectangle2D> distanceFunction) {
+        int sign = nearestLast ? 1 : -1;
+        return (IElement e1, IElement e2) -> {
+            // If there are any vertices in the elements, prefer those primarily.
+            DistrictNetworkVertexNode v1 = e1.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+            DistrictNetworkVertexNode v2 = e2.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+
+            // Don't reorder edges
+            if ((v1 == null && v2 == null))
+                return 0;
+
+            // Sort vertices in nearest first order
+            if (v1 != null && v2 != null) {
+                double dist1 = distanceFunction.applyAsDouble(v1.getBounds());
+                double dist2 = distanceFunction.applyAsDouble(v2.getBounds());
+                return dist1 < dist2 ? sign : dist1 > dist2 ? -sign : 0;
+            }
+
+            // Always vertices before edges
+            return v1 != null && v2 == null ? sign : -sign;
+        };
+    }
+
+    private static IG2DNode getNode(IElement element) {
+        IG2DNode node = element.getHint(DistrictNetworkEdgeElement.KEY_DN_EDGE_NODE);
+        if (node == null)
+            node = element.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+        if (node == null) {
+            node = element.getHint(ElementHints.KEY_SG_NODE);
+            if (node instanceof SingleElementNode) {
+                SingleElementNode snode = (SingleElementNode) node;
+                node = snode.getNodes().iterator().next();
+            }
+        }
+        return node;
+    }
+
+    private static Comparator<IElement> zSorter() {
+        return (e1, e2) -> {
+            IG2DNode e1node = getNode(e1);
+            IG2DNode e2node = getNode(e2);
+            if (e1node.getZIndex() < e2node.getZIndex())
+                return -1;
+            else if (e1node.getZIndex() > e2node.getZIndex())
+                return 1;
+            return 0;
+        };
+    };
+
+    @Override
+    public void sort(List<IElement> elements) {
+        Collections.sort(elements, zSorter());
+    }
+
+    @Override
+    public void sort(PickRequest req, List<IElement> elements) {
+        Collections.sort(elements, zSorter());
+        Collections.sort(elements, nearestVerticesFirst( true, centerDistSq( req.pickArea.getBounds2D() ) ));
+    }
+
+}
\ No newline at end of file
index 9df6e5efbc2646a67fd165b43d90c1d436f44937..770a3b4ef4b4f309929fbddf8248f17eeef0a5ed 100644 (file)
@@ -1,59 +1,21 @@
 package org.simantics.district.network.ui.participants;
 
 import java.awt.geom.Point2D;
-import java.util.Collections;
-import java.util.List;
 import java.util.Set;
 
-import org.simantics.district.network.ui.adapters.DistrictNetworkEdgeElement;
-import org.simantics.district.network.ui.adapters.DistrictNetworkVertexElement;
 import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.canvas.ICanvasParticipant;
-import org.simantics.g2d.diagram.handler.PickRequest.PickSorter;
 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;
 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;
-import org.simantics.g2d.element.ElementHints;
 import org.simantics.g2d.element.IElement;
-import org.simantics.scenegraph.g2d.IG2DNode;
 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
-import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent;
 import org.simantics.scenegraph.g2d.events.KeyEvent;
-import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent;
 
 public class DNPointerInteractor extends PointerInteractor {
 
     private RoutingMode routingMode;
 
-    private static class DNPickSorter implements PickSorter {
-
-        @Override
-        public void sort(List<IElement> elements) {
-            Collections.sort(elements, (e1, e2) -> {
-                IG2DNode e1node = getNode(e1);
-                IG2DNode e2node = getNode(e2);
-                if (e1node.getZIndex() < e2node.getZIndex())
-                    return -1;
-                else if (e1node.getZIndex() > e2node.getZIndex())
-                    return 1;
-                return 0;
-            });
-        }
-
-        private static IG2DNode getNode(IElement element) {
-            IG2DNode node = element.getHint(DistrictNetworkEdgeElement.KEY_DN_EDGE_NODE);
-            if (node == null)
-                node = element.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
-            if (node == null) {
-                node = element.getHint(ElementHints.KEY_SG_NODE);
-                if (node instanceof SingleElementNode) {
-                    SingleElementNode snode = (SingleElementNode) node;
-                    node = snode.getNodes().iterator().next();
-                }
-            }
-            return node;
-        }
-    }
-
     public DNPointerInteractor() {
         super(new DNPickSorter());
     }
@@ -83,6 +45,6 @@ public class DNPointerInteractor extends PointerInteractor {
 
     @Override
     public double getPickDistance() {
-        return 0.00001;
+        return 4;
     }
 }