]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java
Diagram element calculateScaleRecip should never return 0
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / nodes / DistrictNetworkNodeUtils.java
1 package org.simantics.district.network.ui.nodes;
2
3 import java.awt.geom.AffineTransform;
4 import java.awt.geom.Path2D;
5 import java.awt.geom.PathIterator;
6 import java.awt.geom.Point2D;
7 import java.awt.geom.Rectangle2D;
8
9 import org.simantics.district.network.ModelledCRS;
10 import org.simantics.maps.MapScalingTransform;
11 import org.simantics.scenegraph.utils.GeometryUtils;
12
13 import gnu.trove.list.array.TDoubleArrayList;
14
15 public class DistrictNetworkNodeUtils {
16
17     public static ThreadLocal<AffineTransform> sharedTransform = new ThreadLocal<AffineTransform>() {
18         protected AffineTransform initialValue() {
19             return new AffineTransform();
20         }
21     };
22
23     public static Rectangle2D calculateDrawnGeometry(Point2D p, Rectangle2D margin, Rectangle2D result, double scaleRecip) {
24         if (result == null)
25             result = new Rectangle2D.Double();
26         double mw = margin.getWidth();
27         double mh = margin.getHeight();
28         result.setFrame(p.getX() - (mw / 2 * scaleRecip), p.getY() - (mh / 2 * scaleRecip), mw * scaleRecip, mh * scaleRecip);
29         return result;
30     }
31
32     public static Point2D calculatePoint2D(Point2D point, Point2D result) {
33         double x = ModelledCRS.longitudeToX(point.getX());
34         double y = ModelledCRS.latitudeToY(-point.getY()); // Inverse because Simantics Diagram is inverted
35         if (result == null)
36             result = new Point2D.Double(x, y);
37         else
38             result.setLocation(x, y);
39         return result;
40     }
41
42     public static AffineTransform getTransformToRectangle(Rectangle2D toDraw, AffineTransform transform) {
43         if (transform == null)
44             transform = new AffineTransform();
45
46         transform.setTransform(toDraw.getWidth(), 0.0, 0.0, toDraw.getHeight(), toDraw.getCenterX(), toDraw.getCenterY());
47         return transform;
48     }
49
50     public static double calculateScaleRecip(AffineTransform tr) {
51         int zoomLevel = MapScalingTransform.zoomLevel(tr);
52         if (zoomLevel == 0)
53             zoomLevel = 1;
54         return 1.0 / (getScale(tr) * Math.sqrt(zoomLevel));
55     }
56
57     static double getScale(AffineTransform tr) {
58         double scale;
59         scale = GeometryUtils.getScale(tr);
60         scale = Math.max(4096, scale); //Math.min(scale, 32768));
61         return scale;
62     }
63
64     /**
65      * Finds the longest line segment from the provided <code>path</code> and sets
66      * <code>centerPoint</code> to the middle of that line and
67      * <code>direction</code> as the normalized direction vector of that line
68      * segment.
69      * 
70      * <p>
71      * If the path has no points, both <code>centerPoint</code> and
72      * <code>direction</code> are set to ({@link Double#NaN}, {@link Double#NaN}).
73      * If the path has only one point then <code>centerPoint</code> is set to that
74      * single point and <code>direction</code> is set to <code>(1,0)</code>.
75      * 
76      * @param path the path to process
77      * @param centerPoint point for writing the output center point
78      * @param direction point for writing the output direction vector
79      * @return the amount of points in the path
80      */
81     public static int calculateCenterPointAndDirection(Path2D path, Point2D centerPoint, Point2D direction) {
82         PathIterator pi = path.getPathIterator(null);
83         TDoubleArrayList segments = new TDoubleArrayList(20);
84         double[] tmp = new double[6];
85         while (!pi.isDone()) {
86             pi.currentSegment(tmp);
87             segments.add(tmp[0]);
88             segments.add(tmp[1]);
89             pi.next();
90         }
91
92         // Cover corner cases
93         int segCount = segments.size();
94         if (segCount == 0) {
95             centerPoint.setLocation(Double.NaN, Double.NaN);
96             direction.setLocation(Double.NaN, Double.NaN);
97             return 0;
98         } else if (segCount == 2) {
99             centerPoint.setLocation(segments.getQuick(0), segments.getQuick(1));
100             direction.setLocation(1, 0);
101             return 1;
102         }
103
104         int longest = 2;
105         double distance = -Double.MAX_VALUE;
106         for (int i = 2; i < segCount; i += 2) {
107             double dx = segments.getQuick(i) - segments.getQuick(i-2);
108             double dy = segments.getQuick(i+1) - segments.getQuick(i-1);
109
110             double d = dx * dx + dy * dy;
111             if (d > distance) {
112                 distance = d;
113                 longest = i;
114             }
115         }
116
117         double x0 = segments.getQuick(longest - 2);
118         double y0 = segments.getQuick(longest - 1);
119         double x1 = segments.getQuick(longest);
120         double y1 = segments.getQuick(longest + 1);
121
122         distance = Math.sqrt(distance);
123         centerPoint.setLocation((x0 + x1) / 2, (y0 + y1) / 2);
124         direction.setLocation((x1 - x0) / distance, (y1 - y0) / distance);
125         return segCount / 2;
126     }
127
128 }