Browse Source

Fix drawing for very small graph and add new projection for fake maps.

Holt59 3 years ago
parent
commit
80b4b1c7fc

+ 25
- 0
src/main/org/insa/graph/GraphStatistics.java View File

@@ -81,6 +81,31 @@ public class GraphStatistics {
81 81
             return this.extend(size, size, size, size);
82 82
         }
83 83
 
84
+        /**
85
+         * @param point Point to check
86
+         * 
87
+         * @return true if this box contains the given point.
88
+         */
89
+        public boolean contains(Point point) {
90
+            return this.bottomRight.getLatitude() <= point.getLatitude()
91
+                    && this.topLeft.getLatitude() >= point.getLatitude()
92
+                    && this.topLeft.getLongitude() <= point.getLongitude()
93
+                    && this.bottomRight.getLongitude() >= point.getLongitude();
94
+        }
95
+
96
+        /**
97
+         * @return true if this box contains the given box.
98
+         */
99
+        public boolean contains(BoundingBox other) {
100
+            return this.contains(other.bottomRight) && this.contains(other.topLeft);
101
+        }
102
+
103
+        @Override
104
+        public String toString() {
105
+            return "BoundingBox(topLeft=" + this.topLeft + ", bottomRight=" + this.bottomRight
106
+                    + ")";
107
+        }
108
+
84 109
     }
85 110
 
86 111
     // Bounding box for this graph.

+ 15
- 43
src/main/org/insa/graphics/drawing/MercatorProjection.java View File

@@ -4,7 +4,7 @@ import java.awt.Dimension;
4 4
 
5 5
 import org.insa.graph.GraphStatistics.BoundingBox;
6 6
 
7
-public class MercatorProjection {
7
+public class MercatorProjection implements Projection {
8 8
 
9 9
     public static final double MAX_LATITUDE = 82;
10 10
 
@@ -50,20 +50,6 @@ public class MercatorProjection {
50 50
     }
51 51
 
52 52
     /**
53
-     * @return Image width for this projection to work properly.
54
-     */
55
-    public double getImageWidth() {
56
-        return this.width;
57
-    }
58
-
59
-    /**
60
-     * @return Image weight for this projection to work properly.
61
-     */
62
-    public double getImageHeight() {
63
-        return this.height;
64
-    }
65
-
66
-    /**
67 53
      * Compute the projection (without scaling) of the given latitude.
68 54
      * 
69 55
      * @param latitude Latitude to project.
@@ -93,49 +79,35 @@ public class MercatorProjection {
93 79
                 : new Dimension(maxSize, (int) (maxSize * propHeight / propWidth));
94 80
     }
95 81
 
96
-    /**
97
-     * Project the given latitude on the image.
98
-     * 
99
-     * @param latitude Latitude to project.
100
-     * 
101
-     * @return Projected position of the latitude on the image.
102
-     */
82
+    @Override
83
+    public double getImageWidth() {
84
+        return this.width;
85
+    }
86
+
87
+    @Override
88
+    public double getImageHeight() {
89
+        return this.height;
90
+    }
91
+
92
+    @Override
103 93
     public int latitudeToPixelY(float latitude) {
104 94
         return (int) ((this.maxLatitudeProj - projectY(latitude))
105 95
                 / (this.maxLatitudeProj - this.minLatitudeProj) * this.height);
106 96
     }
107 97
 
108
-    /**
109
-     * Project the given longitude on the image.
110
-     * 
111
-     * @param longitude Longitude to project.
112
-     * 
113
-     * @return Projected position of the longitude on the image.
114
-     */
98
+    @Override
115 99
     public int longitudeToPixelX(float longitude) {
116 100
         return (int) (width * (longitude - minLongitude) / (maxLongitude - minLongitude));
117 101
     }
118 102
 
119
-    /**
120
-     * Retrieve the latitude associated to the given projected point.
121
-     * 
122
-     * @param py Projected y-position for which latitude should be retrieved.
123
-     * 
124
-     * @return The original latitude of the point.
125
-     */
103
+    @Override
126 104
     public float pixelYToLatitude(double py) {
127 105
         float y = (float) (this.maxLatitudeProj
128 106
                 - (py / this.height) * (this.maxLatitudeProj - this.minLatitudeProj));
129 107
         return (float) (180 * (2 * Math.atan(Math.exp(y)) - Math.PI / 2) / Math.PI);
130 108
     }
131 109
 
132
-    /**
133
-     * Retrieve the longitude associated to the given projected point.
134
-     * 
135
-     * @param px Projected x-position for which longitude should be retrieved.
136
-     * 
137
-     * @return The original longitude of the point.
138
-     */
110
+    @Override
139 111
     public float pixelXToLongitude(double px) {
140 112
         return (float) ((px / this.width) * (this.maxLongitude - this.minLongitude)
141 113
                 + this.minLongitude);

+ 68
- 0
src/main/org/insa/graphics/drawing/PlateCarreProjection.java View File

@@ -0,0 +1,68 @@
1
+package org.insa.graphics.drawing;
2
+
3
+import org.insa.graph.GraphStatistics.BoundingBox;
4
+
5
+public class PlateCarreProjection implements Projection {
6
+
7
+    // Bounding box
8
+    private final float minLatitude, minLongitude, maxLatitude, maxLongitude;
9
+
10
+    // Dimension of the image
11
+    private final double width, height;
12
+
13
+    /**
14
+     * Create a new PlateCarreProjection corresponding to the given BoundingBox and
15
+     * maxSize.
16
+     * 
17
+     * @param boundingBox Box for this projection.
18
+     * @param maxSize Maximum size of any side (width / height) of the image to
19
+     *        which this projection should draw.
20
+     */
21
+    public PlateCarreProjection(BoundingBox boundingBox, int maxSize) {
22
+        // Find minimum/maximum longitude and latitude.
23
+        this.minLongitude = boundingBox.getTopLeftPoint().getLongitude();
24
+        this.maxLongitude = boundingBox.getBottomRightPoint().getLongitude();
25
+        this.minLatitude = boundingBox.getBottomRightPoint().getLatitude();
26
+        this.maxLatitude = boundingBox.getTopLeftPoint().getLatitude();
27
+
28
+        float diffLon = maxLongitude - minLongitude, diffLat = maxLatitude - minLatitude;
29
+
30
+        this.width = diffLon < diffLat ? (int) (maxSize * diffLon / diffLat) : maxSize;
31
+        this.height = diffLon < diffLat ? maxSize : (int) (maxSize * diffLat / diffLon);
32
+    }
33
+
34
+    @Override
35
+    public double getImageWidth() {
36
+        return this.width;
37
+    }
38
+
39
+    @Override
40
+    public double getImageHeight() {
41
+        return this.height;
42
+    }
43
+
44
+    @Override
45
+    public int latitudeToPixelY(float latitude) {
46
+        return (int) (this.height * (this.maxLatitude - latitude)
47
+                / (this.maxLatitude - this.minLatitude));
48
+    }
49
+
50
+    @Override
51
+    public int longitudeToPixelX(float longitude) {
52
+        return (int) (this.width * (longitude - this.minLongitude)
53
+                / (this.maxLongitude - this.minLongitude));
54
+    }
55
+
56
+    @Override
57
+    public float pixelYToLatitude(double py) {
58
+        return (float) (this.maxLatitude
59
+                - py / this.height * (this.maxLatitude - this.minLatitude));
60
+    }
61
+
62
+    @Override
63
+    public float pixelXToLongitude(double px) {
64
+        return (float) (px / this.width * (this.maxLongitude - this.minLongitude)
65
+                + this.minLongitude);
66
+    }
67
+
68
+}

+ 51
- 0
src/main/org/insa/graphics/drawing/Projection.java View File

@@ -0,0 +1,51 @@
1
+package org.insa.graphics.drawing;
2
+
3
+public interface Projection {
4
+
5
+    /**
6
+     * @return Image width for this projection to work properly.
7
+     */
8
+    public double getImageWidth();
9
+
10
+    /**
11
+     * @return Image weight for this projection to work properly.
12
+     */
13
+    public double getImageHeight();
14
+
15
+    /**
16
+     * Project the given latitude on the image.
17
+     * 
18
+     * @param latitude Latitude to project.
19
+     * 
20
+     * @return Projected position of the latitude on the image.
21
+     */
22
+    public int latitudeToPixelY(float latitude);
23
+
24
+    /**
25
+     * Project the given longitude on the image.
26
+     * 
27
+     * @param longitude Longitude to project.
28
+     * 
29
+     * @return Projected position of the longitude on the image.
30
+     */
31
+    public int longitudeToPixelX(float longitude);
32
+
33
+    /**
34
+     * Retrieve the latitude associated to the given projected point.
35
+     * 
36
+     * @param py Projected y-position for which latitude should be retrieved.
37
+     * 
38
+     * @return The original latitude of the point.
39
+     */
40
+    public float pixelYToLatitude(double py);
41
+
42
+    /**
43
+     * Retrieve the longitude associated to the given projected point.
44
+     * 
45
+     * @param px Projected x-position for which longitude should be retrieved.
46
+     * 
47
+     * @return The original longitude of the point.
48
+     */
49
+    public float pixelXToLongitude(double px);
50
+
51
+}

+ 11
- 4
src/main/org/insa/graphics/drawing/components/BasicDrawing.java View File

@@ -32,6 +32,8 @@ import org.insa.graphics.drawing.Drawing;
32 32
 import org.insa.graphics.drawing.DrawingClickListener;
33 33
 import org.insa.graphics.drawing.GraphPalette;
34 34
 import org.insa.graphics.drawing.MercatorProjection;
35
+import org.insa.graphics.drawing.PlateCarreProjection;
36
+import org.insa.graphics.drawing.Projection;
35 37
 import org.insa.graphics.drawing.overlays.MarkerOverlay;
36 38
 import org.insa.graphics.drawing.overlays.MarkerUtils;
37 39
 import org.insa.graphics.drawing.overlays.Overlay;
@@ -301,7 +303,7 @@ public class BasicDrawing extends JPanel implements Drawing {
301 303
     // Maximum width for the drawing (in pixels).
302 304
     private static final int MAXIMUM_DRAWING_WIDTH = 2000;
303 305
 
304
-    private MercatorProjection projection;
306
+    private Projection projection;
305 307
 
306 308
     // Width and height of the image
307 309
     private int width, height;
@@ -573,8 +575,13 @@ public class BasicDrawing extends JPanel implements Drawing {
573 575
         float deltaLon = 0.01f * diffLon, deltaLat = 0.01f * diffLat;
574 576
 
575 577
         // Create the projection and retrieve width and height for the box.
576
-        projection = new MercatorProjection(box.extend(deltaLon, deltaLat, deltaLon, deltaLat),
577
-                MAXIMUM_DRAWING_WIDTH);
578
+        BoundingBox extendedBox = box.extend(deltaLon, deltaLat, deltaLon, deltaLat);
579
+        if (graph.getMapId().startsWith("0x")) {
580
+            projection = new PlateCarreProjection(extendedBox, MAXIMUM_DRAWING_WIDTH);
581
+        }
582
+        else {
583
+            projection = new MercatorProjection(extendedBox, MAXIMUM_DRAWING_WIDTH);
584
+        }
578 585
         this.width = (int) projection.getImageWidth();
579 586
         this.height = (int) projection.getImageHeight();
580 587
 
@@ -605,7 +612,7 @@ public class BasicDrawing extends JPanel implements Drawing {
605 612
 
606 613
     @Override
607 614
     public void drawGraph(Graph graph, GraphPalette palette) {
608
-        int repaintModulo = graph.getNodes().size() / 100;
615
+        int repaintModulo = Math.max(1, graph.getNodes().size() / 100);
609 616
 
610 617
         // Initialize the buffered image
611 618
 

Loading…
Cancel
Save