mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Added methods to calculate optimal map size given a geo boundary.
- From zoom level 20 to 1, once find a size that contains the whole boundary, then the size will be used to retrieve map image from google #story[928]
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
package seng302.models.map;
|
||||
|
||||
/**
|
||||
* The Boundary class represents a square territorial bound on a map. It contains
|
||||
* four extremity double values(N, E, S, W). N and S are represented as latitudes
|
||||
* in radians. E and W are represented as longitudes in radians.
|
||||
* The Boundary class represents a rectangle territorial boundary on a map. It
|
||||
* contains four extremity double values(N, E, S, W). N and S are represented as
|
||||
* latitudes in radians. E and W are represented as longitudes in radians.
|
||||
*
|
||||
* Created by Haoming on 10/5/17
|
||||
*/
|
||||
@@ -18,27 +18,27 @@ public class Boundary {
|
||||
this.westLng = westLng;
|
||||
}
|
||||
|
||||
public double getCentreLat() {
|
||||
double getCentreLat() {
|
||||
return (northLat + southLat) / 2;
|
||||
}
|
||||
|
||||
public double getCentreLng() {
|
||||
double getCentreLng() {
|
||||
return (eastLng + westLng) / 2;
|
||||
}
|
||||
|
||||
public double getNorthLat() {
|
||||
double getNorthLat() {
|
||||
return northLat;
|
||||
}
|
||||
|
||||
public double getEastLng() {
|
||||
double getEastLng() {
|
||||
return eastLng;
|
||||
}
|
||||
|
||||
public double getSouthLat() {
|
||||
double getSouthLat() {
|
||||
return southLat;
|
||||
}
|
||||
|
||||
public double getWestLng() {
|
||||
double getWestLng() {
|
||||
return westLng;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,18 +7,25 @@ import java.net.URL;
|
||||
|
||||
import java.lang.Math;
|
||||
|
||||
/**
|
||||
* CanvasMap retrieves a map image with given geo boundary from Google Map server.
|
||||
* By passing a rectangle like geo boundary, it returns a map image with the
|
||||
* highest resolution. However, due to free quote account usage limit, the maximum
|
||||
* resolution is only 1280 * 1280.
|
||||
*
|
||||
* Created by Haoming on 15/5/2017
|
||||
*/
|
||||
public class CanvasMap {
|
||||
|
||||
private Boundary bound;
|
||||
private double width, height; // desired image size
|
||||
private Boundary boundary;
|
||||
private long width, height; // desired image size
|
||||
private int zoom;
|
||||
|
||||
private String KEY = "AIzaSyC-5oOShMCY5Oy_9L7guYMPUPFHDMr37wE";
|
||||
|
||||
public CanvasMap(Boundary bound, double width, double height) {
|
||||
this.bound = bound;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
public CanvasMap(Boundary boundary) {
|
||||
this.boundary = boundary;
|
||||
calculateOptimalMapSize();
|
||||
}
|
||||
|
||||
public Image getMapImage() {
|
||||
@@ -35,33 +42,64 @@ public class CanvasMap {
|
||||
}
|
||||
|
||||
private String getRequest() {
|
||||
zoom = 15;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("https://maps.googleapis.com/maps/api/staticmap?");
|
||||
sb.append(String.format("center=%f,%f", bound.getCentreLat(), bound.getCentreLng()));
|
||||
sb.append(String.format("center=%f,%f", boundary.getCentreLat(), boundary.getCentreLng()));
|
||||
sb.append(String.format("&zoom=%d", zoom));
|
||||
sb.append(String.format("&size=%.0fx%.0f&scale=2", width / 2, height / 2));
|
||||
sb.append(String.format("&size=%dx%d&scale=2", width, height));
|
||||
sb.append("&style=feature:all|element:labels|visibility:off"); // hide all labels on map
|
||||
// sb.append(String.format("&markers=%f,%f", boundary.getSouthLat(), boundary.getWestLng()));
|
||||
// sb.append(String.format("&key=%s", KEY));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void calculateOptimalMapSize() {
|
||||
for (int z = 20; z > 0; z--) {
|
||||
MapSize mapSize = getMapSize(z, boundary);
|
||||
zoom = z;
|
||||
width = mapSize.width;
|
||||
height = mapSize.height;
|
||||
// if map size is valid, exit the loop as we have the highest resolution
|
||||
if (mapSize.isValid()) break;
|
||||
}
|
||||
}
|
||||
|
||||
private MapSize getMapSize(int zoom, Boundary boundary) {
|
||||
double scale = Math.pow(2, zoom);
|
||||
MapGeo geoSW = new MapGeo(boundary.getSouthLat(), boundary.getWestLng());
|
||||
MapGeo geoNE = new MapGeo(boundary.getNorthLat(), boundary.getEastLng());
|
||||
MapPoint pointSW = MercatorProjection.toMapPoint(geoSW);
|
||||
MapPoint pointNE = MercatorProjection.toMapPoint(geoNE);
|
||||
return new MapSize(Math.abs(pointNE.getX() - pointSW.getX()),
|
||||
Math.abs(pointNE.getY() - pointSW.getY()));
|
||||
return new MapSize(Math.abs(pointNE.getX() - pointSW.getX()) * scale,
|
||||
Math.abs(pointNE.getY() - pointSW.getY()) * scale);
|
||||
}
|
||||
|
||||
class MapSize {
|
||||
long width, height;
|
||||
|
||||
MapSize(double width, double height) {
|
||||
this.width = (long) width;
|
||||
this.height = (long) height;
|
||||
this.width = Math.round(width);
|
||||
this.height = Math.round(height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map size is valid when width and height are both less than 640 pixels
|
||||
* @return true if both dimensions are less than 640px
|
||||
*/
|
||||
boolean isValid() {
|
||||
return Math.max(width, height) <= 640;
|
||||
}
|
||||
}
|
||||
|
||||
public long getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public long getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getZoom() {
|
||||
return zoom;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package seng302.models.map;
|
||||
|
||||
/**
|
||||
* A class represent Geo location (latitude, longitude).
|
||||
* Created by Haoming on 15/5/2017
|
||||
*/
|
||||
class MapGeo {
|
||||
|
||||
private double lat, lng;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package seng302.models.map;
|
||||
|
||||
/**
|
||||
* A class represent euclidean planar point (x, y)
|
||||
* Created by Haoming on 15/5/2017
|
||||
*/
|
||||
class MapPoint {
|
||||
|
||||
private double x, y;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package seng302.models.map;
|
||||
|
||||
/**
|
||||
* An utility class useful to convert between Geo locations and Mercator projection
|
||||
* planar coordinates.
|
||||
* Created by Haoming on 15/5/2017
|
||||
*/
|
||||
public class MercatorProjection {
|
||||
|
||||
private static final double MERCATOR_RANGE = 256;
|
||||
|
||||
@@ -17,7 +17,7 @@ public class TestMapController implements Initializable{
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
GraphicsContext gc = mapCanvas.getGraphicsContext2D();
|
||||
Boundary bound = new Boundary(57.662943, 11.848501, 57.673945, 11.824966);
|
||||
CanvasMap canvasMap = new CanvasMap(bound, 1280, 960);
|
||||
gc.drawImage(canvasMap.getMapImage(), 0, 0, 1280, 960);
|
||||
CanvasMap canvasMap = new CanvasMap(bound);
|
||||
gc.drawImage(canvasMap.getMapImage(), 0, 0, canvasMap.getWidth(), canvasMap.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user