+
+ /*
+ * First use the default sorting if available, then sort successive connections by their distance to cursor.
+ */
+ public static PickSorter connectionSorter(PickSorter sorter, double x, double y) {
+ return new PickSorter() {
+
+ private double getDistanceSqToRouteGraphConnection(RouteGraphNode rgn, double x, double y) {
+ double minDistanceSq = Double.MAX_VALUE;
+ for (RouteLine line : rgn.getRouteGraph().getAllLines()) {
+ ArrayList<Segment> segments = new ArrayList<Segment>();
+ line.collectSegments(segments);
+ for (Segment segment : segments) {
+ RoutePoint p1 = segment.p1;
+ RoutePoint p2 = segment.p2;
+
+ double distanceSq = Line2D.ptSegDistSq(p1.getX(), p1.getY(), p2.getX(), p2.getY(), x, y);
+ if (distanceSq < minDistanceSq) {
+ minDistanceSq = distanceSq;
+ }
+ }
+ }
+ return minDistanceSq;
+ }
+
+ @Override
+ public void sort(List<IElement> elements) {
+ if (sorter != null)
+ sorter.sort(elements);
+
+ List<Pair<Double, IElement>> connections = new ArrayList<>(elements.size());
+ int tail = 0;
+ for (int i = 0; i < elements.size(); i++) {
+ IElement element = elements.get(i);
+ RouteGraphNode rgn = element.getHint(RouteGraphConnectionClass.KEY_RG_NODE);
+ if (rgn != null) {
+ double distanceSq = getDistanceSqToRouteGraphConnection(rgn, x, y);
+ connections.add(new Pair<Double, IElement>(distanceSq, element));
+ }
+
+ if (rgn == null || i == elements.size() - 1) {
+ Collections.sort(connections, new Comparator<Pair<Double, IElement>>() {
+ @Override
+ public int compare(Pair<Double, IElement> connection1, Pair<Double, IElement> connection2) {
+ return Double.compare(connection2.first, connection1.first);
+ }
+ });
+ for (Pair<Double, IElement> connection : connections) {
+ elements.set(tail, connection.second);
+ tail++;
+ }
+ connections.clear();
+ tail = i + 1;
+ }
+ }
+ }
+ };
+ }