Fix drawing for very small graph and add new projection for fake maps.
This commit is contained in:
		
							parent
							
								
									e2d1d47beb
								
							
						
					
					
						commit
						80b4b1c7fc
					
				
					 5 changed files with 170 additions and 47 deletions
				
			
		|  | @ -81,6 +81,31 @@ public class GraphStatistics { | |||
|             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. | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import java.awt.Dimension; | |||
| 
 | ||||
| import org.insa.graph.GraphStatistics.BoundingBox; | ||||
| 
 | ||||
| public class MercatorProjection { | ||||
| public class MercatorProjection implements Projection { | ||||
| 
 | ||||
|     public static final double MAX_LATITUDE = 82; | ||||
| 
 | ||||
|  | @ -49,20 +49,6 @@ public class MercatorProjection { | |||
|         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. | ||||
|      *  | ||||
|  | @ -93,49 +79,35 @@ public class MercatorProjection { | |||
|                 : new Dimension(maxSize, (int) (maxSize * propHeight / propWidth)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Project the given latitude on the image. | ||||
|      *  | ||||
|      * @param latitude Latitude to project. | ||||
|      *  | ||||
|      * @return Projected position of the latitude on the image. | ||||
|      */ | ||||
|     @Override | ||||
|     public double getImageWidth() { | ||||
|         return this.width; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public double getImageHeight() { | ||||
|         return this.height; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int latitudeToPixelY(float latitude) { | ||||
|         return (int) ((this.maxLatitudeProj - projectY(latitude)) | ||||
|                 / (this.maxLatitudeProj - this.minLatitudeProj) * this.height); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Project the given longitude on the image. | ||||
|      *  | ||||
|      * @param longitude Longitude to project. | ||||
|      *  | ||||
|      * @return Projected position of the longitude on the image. | ||||
|      */ | ||||
|     @Override | ||||
|     public int longitudeToPixelX(float longitude) { | ||||
|         return (int) (width * (longitude - minLongitude) / (maxLongitude - minLongitude)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 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. | ||||
|      */ | ||||
|     @Override | ||||
|     public float pixelYToLatitude(double py) { | ||||
|         float y = (float) (this.maxLatitudeProj | ||||
|                 - (py / this.height) * (this.maxLatitudeProj - this.minLatitudeProj)); | ||||
|         return (float) (180 * (2 * Math.atan(Math.exp(y)) - Math.PI / 2) / Math.PI); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 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. | ||||
|      */ | ||||
|     @Override | ||||
|     public float pixelXToLongitude(double px) { | ||||
|         return (float) ((px / this.width) * (this.maxLongitude - 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.GraphPalette; | ||||
| 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.MarkerUtils; | ||||
| 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). | ||||
|     private static final int MAXIMUM_DRAWING_WIDTH = 2000; | ||||
| 
 | ||||
|     private MercatorProjection projection; | ||||
|     private Projection projection; | ||||
| 
 | ||||
|     // Width and height of the image | ||||
|     private int width, height; | ||||
|  | @ -573,8 +575,13 @@ public class BasicDrawing extends JPanel implements Drawing { | |||
|         float deltaLon = 0.01f * diffLon, deltaLat = 0.01f * diffLat; | ||||
| 
 | ||||
|         // Create the projection and retrieve width and height for the box. | ||||
|         projection = new MercatorProjection(box.extend(deltaLon, deltaLat, deltaLon, deltaLat), | ||||
|                 MAXIMUM_DRAWING_WIDTH); | ||||
|         BoundingBox extendedBox = box.extend(deltaLon, deltaLat, deltaLon, deltaLat); | ||||
|         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.height = (int) projection.getImageHeight(); | ||||
| 
 | ||||
|  | @ -605,7 +612,7 @@ public class BasicDrawing extends JPanel implements Drawing { | |||
| 
 | ||||
|     @Override | ||||
|     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 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue