]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java
Use detailed geometry in drawing info labels, symbols and picking.
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / nodes / DistrictNetworkNodeUtils.java
index c9e4a00e19b3be532b23f2d4641590e953bb9524..2cc0ee96ae4ffa89ad97b696c3661944f13146bc 100644 (file)
@@ -1,6 +1,8 @@
 package org.simantics.district.network.ui.nodes;
 
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
@@ -8,8 +10,16 @@ import org.simantics.district.network.ModelledCRS;
 import org.simantics.maps.MapScalingTransform;
 import org.simantics.scenegraph.utils.GeometryUtils;
 
+import gnu.trove.list.array.TDoubleArrayList;
+
 public class DistrictNetworkNodeUtils {
 
+    public static ThreadLocal<AffineTransform> sharedTransform = new ThreadLocal<AffineTransform>() {
+        protected AffineTransform initialValue() {
+            return new AffineTransform();
+        }
+    };
+
     public static Rectangle2D calculateDrawnGeometry(Point2D p, Rectangle2D margin, Rectangle2D result, double scaleRecip) {
         if (result == null)
             result = new Rectangle2D.Double();
@@ -39,20 +49,78 @@ public class DistrictNetworkNodeUtils {
 
     public static double calculateScaleRecip(AffineTransform tr) {
         int zoomLevel = MapScalingTransform.zoomLevel(tr);
-        double t;
-        if (zoomLevel > 15) {
-            int d = zoomLevel - 15; // stop zooming vertices when zoom level > 15
-            t = 1.0 / d / (getScale(tr) * Math.sqrt(zoomLevel));
-        } else {
-            t = 1.0 / (getScale(tr) * Math.sqrt(zoomLevel));
-        }
-        return t;
+        return 1.0 / (getScale(tr) * Math.sqrt(zoomLevel));
     }
 
     static double getScale(AffineTransform tr) {
         double scale;
         scale = GeometryUtils.getScale(tr);
-        scale = Math.max(4096, Math.min(scale, 32768));
+        scale = Math.max(4096, scale); //Math.min(scale, 32768));
         return scale;
     }
-}
+
+    /**
+     * Finds the longest line segment from the provided <code>path</code> and sets
+     * <code>centerPoint</code> to the middle of that line and
+     * <code>direction</code> as the normalized direction vector of that line
+     * segment.
+     * 
+     * <p>
+     * If the path has no points, both <code>centerPoint</code> and
+     * <code>direction</code> are set to ({@link Double#NaN}, {@link Double#NaN}).
+     * If the path has only one point then <code>centerPoint</code> is set to that
+     * single point and <code>direction</code> is set to <code>(1,0)</code>.
+     * 
+     * @param path the path to process
+     * @param centerPoint point for writing the output center point
+     * @param direction point for writing the output direction vector
+     * @return the amount of points in the path
+     */
+    public static int calculateCenterPointAndDirection(Path2D path, Point2D centerPoint, Point2D direction) {
+        PathIterator pi = path.getPathIterator(null);
+        TDoubleArrayList segments = new TDoubleArrayList(20);
+        double[] tmp = new double[6];
+        while (!pi.isDone()) {
+            pi.currentSegment(tmp);
+            segments.add(tmp[0]);
+            segments.add(tmp[1]);
+            pi.next();
+        }
+
+        // Cover corner cases
+        int segCount = segments.size();
+        if (segCount == 0) {
+            centerPoint.setLocation(Double.NaN, Double.NaN);
+            direction.setLocation(Double.NaN, Double.NaN);
+            return 0;
+        } else if (segCount == 2) {
+            centerPoint.setLocation(segments.getQuick(0), segments.getQuick(1));
+            direction.setLocation(1, 0);
+            return 1;
+        }
+
+        int longest = 1;
+        double distance = 0.0;
+        for (int i = 2; i < segCount; i += 2) {
+            double dx = segments.getQuick(i) - segments.getQuick(i-2);
+            double dy = segments.getQuick(i+1) - segments.getQuick(i-1);
+
+            double d = dx * dx + dy * dy;
+            if (d > distance) {
+                distance = d;
+                longest = i;
+            }
+        }
+
+        double x0 = segments.getQuick(longest - 2);
+        double y0 = segments.getQuick(longest - 1);
+        double x1 = segments.getQuick(longest);
+        double y1 = segments.getQuick(longest + 1);
+
+        distance = Math.sqrt(distance);
+        centerPoint.setLocation((x0 + x1) / 2, (y0 + y1) / 2);
+        direction.setLocation((x1 - x0) / distance, (y1 - y0) / distance);
+        return segCount / 2;
+    }
+
+}
\ No newline at end of file