Fix drawing for very small graph and add new projection for fake maps.
This commit is contained in:
parent
e2d1d47beb
commit
80b4b1c7fc
@ -81,6 +81,31 @@ public class GraphStatistics {
|
|||||||
return this.extend(size, size, size, size);
|
return this.extend(size, size, size, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param point Point to check
|
||||||
|
*
|
||||||
|
* @return true if this box contains the given point.
|
||||||
|
*/
|
||||||
|
public boolean contains(Point point) {
|
||||||
|
return this.bottomRight.getLatitude() <= point.getLatitude()
|
||||||
|
&& this.topLeft.getLatitude() >= point.getLatitude()
|
||||||
|
&& this.topLeft.getLongitude() <= point.getLongitude()
|
||||||
|
&& this.bottomRight.getLongitude() >= point.getLongitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if this box contains the given box.
|
||||||
|
*/
|
||||||
|
public boolean contains(BoundingBox other) {
|
||||||
|
return this.contains(other.bottomRight) && this.contains(other.topLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BoundingBox(topLeft=" + this.topLeft + ", bottomRight=" + this.bottomRight
|
||||||
|
+ ")";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bounding box for this graph.
|
// Bounding box for this graph.
|
||||||
|
@ -4,7 +4,7 @@ import java.awt.Dimension;
|
|||||||
|
|
||||||
import org.insa.graph.GraphStatistics.BoundingBox;
|
import org.insa.graph.GraphStatistics.BoundingBox;
|
||||||
|
|
||||||
public class MercatorProjection {
|
public class MercatorProjection implements Projection {
|
||||||
|
|
||||||
public static final double MAX_LATITUDE = 82;
|
public static final double MAX_LATITUDE = 82;
|
||||||
|
|
||||||
@ -49,20 +49,6 @@ public class MercatorProjection {
|
|||||||
this.height = imageDimension.getHeight();
|
this.height = imageDimension.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Image width for this projection to work properly.
|
|
||||||
*/
|
|
||||||
public double getImageWidth() {
|
|
||||||
return this.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Image weight for this projection to work properly.
|
|
||||||
*/
|
|
||||||
public double getImageHeight() {
|
|
||||||
return this.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the projection (without scaling) of the given latitude.
|
* Compute the projection (without scaling) of the given latitude.
|
||||||
*
|
*
|
||||||
@ -93,49 +79,35 @@ public class MercatorProjection {
|
|||||||
: new Dimension(maxSize, (int) (maxSize * propHeight / propWidth));
|
: new Dimension(maxSize, (int) (maxSize * propHeight / propWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Project the given latitude on the image.
|
public double getImageWidth() {
|
||||||
*
|
return this.width;
|
||||||
* @param latitude Latitude to project.
|
}
|
||||||
*
|
|
||||||
* @return Projected position of the latitude on the image.
|
@Override
|
||||||
*/
|
public double getImageHeight() {
|
||||||
|
return this.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int latitudeToPixelY(float latitude) {
|
public int latitudeToPixelY(float latitude) {
|
||||||
return (int) ((this.maxLatitudeProj - projectY(latitude))
|
return (int) ((this.maxLatitudeProj - projectY(latitude))
|
||||||
/ (this.maxLatitudeProj - this.minLatitudeProj) * this.height);
|
/ (this.maxLatitudeProj - this.minLatitudeProj) * this.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Project the given longitude on the image.
|
|
||||||
*
|
|
||||||
* @param longitude Longitude to project.
|
|
||||||
*
|
|
||||||
* @return Projected position of the longitude on the image.
|
|
||||||
*/
|
|
||||||
public int longitudeToPixelX(float longitude) {
|
public int longitudeToPixelX(float longitude) {
|
||||||
return (int) (width * (longitude - minLongitude) / (maxLongitude - minLongitude));
|
return (int) (width * (longitude - minLongitude) / (maxLongitude - minLongitude));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Retrieve the latitude associated to the given projected point.
|
|
||||||
*
|
|
||||||
* @param py Projected y-position for which latitude should be retrieved.
|
|
||||||
*
|
|
||||||
* @return The original latitude of the point.
|
|
||||||
*/
|
|
||||||
public float pixelYToLatitude(double py) {
|
public float pixelYToLatitude(double py) {
|
||||||
float y = (float) (this.maxLatitudeProj
|
float y = (float) (this.maxLatitudeProj
|
||||||
- (py / this.height) * (this.maxLatitudeProj - this.minLatitudeProj));
|
- (py / this.height) * (this.maxLatitudeProj - this.minLatitudeProj));
|
||||||
return (float) (180 * (2 * Math.atan(Math.exp(y)) - Math.PI / 2) / Math.PI);
|
return (float) (180 * (2 * Math.atan(Math.exp(y)) - Math.PI / 2) / Math.PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Retrieve the longitude associated to the given projected point.
|
|
||||||
*
|
|
||||||
* @param px Projected x-position for which longitude should be retrieved.
|
|
||||||
*
|
|
||||||
* @return The original longitude of the point.
|
|
||||||
*/
|
|
||||||
public float pixelXToLongitude(double px) {
|
public float pixelXToLongitude(double px) {
|
||||||
return (float) ((px / this.width) * (this.maxLongitude - this.minLongitude)
|
return (float) ((px / this.width) * (this.maxLongitude - this.minLongitude)
|
||||||
+ this.minLongitude);
|
+ this.minLongitude);
|
||||||
|
68
src/main/org/insa/graphics/drawing/PlateCarreProjection.java
Normal file
68
src/main/org/insa/graphics/drawing/PlateCarreProjection.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package org.insa.graphics.drawing;
|
||||||
|
|
||||||
|
import org.insa.graph.GraphStatistics.BoundingBox;
|
||||||
|
|
||||||
|
public class PlateCarreProjection implements Projection {
|
||||||
|
|
||||||
|
// Bounding box
|
||||||
|
private final float minLatitude, minLongitude, maxLatitude, maxLongitude;
|
||||||
|
|
||||||
|
// Dimension of the image
|
||||||
|
private final double width, height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PlateCarreProjection corresponding to the given BoundingBox and
|
||||||
|
* maxSize.
|
||||||
|
*
|
||||||
|
* @param boundingBox Box for this projection.
|
||||||
|
* @param maxSize Maximum size of any side (width / height) of the image to
|
||||||
|
* which this projection should draw.
|
||||||
|
*/
|
||||||
|
public PlateCarreProjection(BoundingBox boundingBox, int maxSize) {
|
||||||
|
// Find minimum/maximum longitude and latitude.
|
||||||
|
this.minLongitude = boundingBox.getTopLeftPoint().getLongitude();
|
||||||
|
this.maxLongitude = boundingBox.getBottomRightPoint().getLongitude();
|
||||||
|
this.minLatitude = boundingBox.getBottomRightPoint().getLatitude();
|
||||||
|
this.maxLatitude = boundingBox.getTopLeftPoint().getLatitude();
|
||||||
|
|
||||||
|
float diffLon = maxLongitude - minLongitude, diffLat = maxLatitude - minLatitude;
|
||||||
|
|
||||||
|
this.width = diffLon < diffLat ? (int) (maxSize * diffLon / diffLat) : maxSize;
|
||||||
|
this.height = diffLon < diffLat ? maxSize : (int) (maxSize * diffLat / diffLon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getImageWidth() {
|
||||||
|
return this.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getImageHeight() {
|
||||||
|
return this.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int latitudeToPixelY(float latitude) {
|
||||||
|
return (int) (this.height * (this.maxLatitude - latitude)
|
||||||
|
/ (this.maxLatitude - this.minLatitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int longitudeToPixelX(float longitude) {
|
||||||
|
return (int) (this.width * (longitude - this.minLongitude)
|
||||||
|
/ (this.maxLongitude - this.minLongitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float pixelYToLatitude(double py) {
|
||||||
|
return (float) (this.maxLatitude
|
||||||
|
- py / this.height * (this.maxLatitude - this.minLatitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float pixelXToLongitude(double px) {
|
||||||
|
return (float) (px / this.width * (this.maxLongitude - this.minLongitude)
|
||||||
|
+ this.minLongitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
51
src/main/org/insa/graphics/drawing/Projection.java
Normal file
51
src/main/org/insa/graphics/drawing/Projection.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package org.insa.graphics.drawing;
|
||||||
|
|
||||||
|
public interface Projection {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Image width for this projection to work properly.
|
||||||
|
*/
|
||||||
|
public double getImageWidth();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Image weight for this projection to work properly.
|
||||||
|
*/
|
||||||
|
public double getImageHeight();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project the given latitude on the image.
|
||||||
|
*
|
||||||
|
* @param latitude Latitude to project.
|
||||||
|
*
|
||||||
|
* @return Projected position of the latitude on the image.
|
||||||
|
*/
|
||||||
|
public int latitudeToPixelY(float latitude);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project the given longitude on the image.
|
||||||
|
*
|
||||||
|
* @param longitude Longitude to project.
|
||||||
|
*
|
||||||
|
* @return Projected position of the longitude on the image.
|
||||||
|
*/
|
||||||
|
public int longitudeToPixelX(float longitude);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the latitude associated to the given projected point.
|
||||||
|
*
|
||||||
|
* @param py Projected y-position for which latitude should be retrieved.
|
||||||
|
*
|
||||||
|
* @return The original latitude of the point.
|
||||||
|
*/
|
||||||
|
public float pixelYToLatitude(double py);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the longitude associated to the given projected point.
|
||||||
|
*
|
||||||
|
* @param px Projected x-position for which longitude should be retrieved.
|
||||||
|
*
|
||||||
|
* @return The original longitude of the point.
|
||||||
|
*/
|
||||||
|
public float pixelXToLongitude(double px);
|
||||||
|
|
||||||
|
}
|
@ -32,6 +32,8 @@ import org.insa.graphics.drawing.Drawing;
|
|||||||
import org.insa.graphics.drawing.DrawingClickListener;
|
import org.insa.graphics.drawing.DrawingClickListener;
|
||||||
import org.insa.graphics.drawing.GraphPalette;
|
import org.insa.graphics.drawing.GraphPalette;
|
||||||
import org.insa.graphics.drawing.MercatorProjection;
|
import org.insa.graphics.drawing.MercatorProjection;
|
||||||
|
import org.insa.graphics.drawing.PlateCarreProjection;
|
||||||
|
import org.insa.graphics.drawing.Projection;
|
||||||
import org.insa.graphics.drawing.overlays.MarkerOverlay;
|
import org.insa.graphics.drawing.overlays.MarkerOverlay;
|
||||||
import org.insa.graphics.drawing.overlays.MarkerUtils;
|
import org.insa.graphics.drawing.overlays.MarkerUtils;
|
||||||
import org.insa.graphics.drawing.overlays.Overlay;
|
import org.insa.graphics.drawing.overlays.Overlay;
|
||||||
@ -301,7 +303,7 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
// Maximum width for the drawing (in pixels).
|
// Maximum width for the drawing (in pixels).
|
||||||
private static final int MAXIMUM_DRAWING_WIDTH = 2000;
|
private static final int MAXIMUM_DRAWING_WIDTH = 2000;
|
||||||
|
|
||||||
private MercatorProjection projection;
|
private Projection projection;
|
||||||
|
|
||||||
// Width and height of the image
|
// Width and height of the image
|
||||||
private int width, height;
|
private int width, height;
|
||||||
@ -573,8 +575,13 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
float deltaLon = 0.01f * diffLon, deltaLat = 0.01f * diffLat;
|
float deltaLon = 0.01f * diffLon, deltaLat = 0.01f * diffLat;
|
||||||
|
|
||||||
// Create the projection and retrieve width and height for the box.
|
// Create the projection and retrieve width and height for the box.
|
||||||
projection = new MercatorProjection(box.extend(deltaLon, deltaLat, deltaLon, deltaLat),
|
BoundingBox extendedBox = box.extend(deltaLon, deltaLat, deltaLon, deltaLat);
|
||||||
MAXIMUM_DRAWING_WIDTH);
|
if (graph.getMapId().startsWith("0x")) {
|
||||||
|
projection = new PlateCarreProjection(extendedBox, MAXIMUM_DRAWING_WIDTH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
projection = new MercatorProjection(extendedBox, MAXIMUM_DRAWING_WIDTH);
|
||||||
|
}
|
||||||
this.width = (int) projection.getImageWidth();
|
this.width = (int) projection.getImageWidth();
|
||||||
this.height = (int) projection.getImageHeight();
|
this.height = (int) projection.getImageHeight();
|
||||||
|
|
||||||
@ -605,7 +612,7 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawGraph(Graph graph, GraphPalette palette) {
|
public void drawGraph(Graph graph, GraphPalette palette) {
|
||||||
int repaintModulo = graph.getNodes().size() / 100;
|
int repaintModulo = Math.max(1, graph.getNodes().size() / 100);
|
||||||
|
|
||||||
// Initialize the buffered image
|
// Initialize the buffered image
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user