mirror of
https://github.com/csharpee/Map-Projections.git
synced 2025-12-13 00:00:07 -05:00
Equirectangular and Mercator maps are now fully functional, as is the user interface. Stay tuned for Peirce-Quincuncial.
115 lines
3.6 KiB
Java
115 lines
3.6 KiB
Java
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.Scanner;
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
/**
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @author Justin Kunimune
|
|
*
|
|
*/
|
|
public class MapProjections {
|
|
private static final int QUINCUNCIAL = 1;
|
|
private static final int EQUIRECTANGULAR = 0;
|
|
private static final int MERCATOR = 2;
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) throws IOException {
|
|
Scanner in = new Scanner(System.in);
|
|
String response;
|
|
|
|
System.out.println("Realistic or Simplified? (r or s)");
|
|
response = in.nextLine();
|
|
BufferedImage input;
|
|
if (response.toLowerCase().charAt(0) == 'r') // reads equirectangular from file
|
|
input = ImageIO.read(new File("input/realistic.jpg"));
|
|
else
|
|
input = ImageIO.read(new File("input/simplified.jpg"));
|
|
|
|
System.out.println("And what aspect ratio would you like? (Please enter a decimal)");
|
|
response = in.nextLine();
|
|
double x2y = Double.parseDouble(response);
|
|
System.out.println("Pixel width?");
|
|
response = in.nextLine();
|
|
int w = Integer.parseInt(response);
|
|
BufferedImage output = new BufferedImage(w,(int)(w/x2y),BufferedImage.TYPE_INT_RGB);
|
|
|
|
System.out.println("Finally, pick a projection:\n");
|
|
System.out.println(EQUIRECTANGULAR+" --- Equirectangular");
|
|
System.out.println(QUINCUNCIAL +" --- Peirce Quincuncial");
|
|
System.out.println(MERCATOR +" --- Mercator");
|
|
response = in.nextLine();
|
|
int projection = Integer.parseInt(response);
|
|
map(input,output,projection);
|
|
|
|
saveImage(output);
|
|
|
|
in.close();
|
|
|
|
System.out.println("Done!");
|
|
}
|
|
|
|
|
|
|
|
|
|
/* PROJECTION METHODS: Return RGB at a given pixel based on a reference map and a unique projection method */
|
|
public static int quincuncial(final double lat0, final double lon0, final double orientation,
|
|
final int width, final int height, int x, int y, BufferedImage ref) { // a tessalatable square map
|
|
return 0;
|
|
}
|
|
|
|
|
|
public static int equirectangular(final double lat0, final double lon0, final double orientation,
|
|
final int width, final int height, int x, int y, BufferedImage ref) { // a popular shape-preserving map
|
|
|
|
return ref.getRGB((int)((double)ref.getWidth()*x/width), (int)((double)ref.getHeight()*y/height));
|
|
}
|
|
|
|
|
|
public static int mercator(final double lat0, final double lon0, final double orientation,
|
|
final int width, final int height, int x, int y, BufferedImage ref) { // a popular shape-preserving map
|
|
y -= height/2;
|
|
double phi = Math.atan(Math.sinh((double)y/width*2*Math.PI)) + Math.PI/2; // latitude from 0 to pi
|
|
return ref.getRGB((int)((double)x/width*ref.getWidth()), (int)(phi/Math.PI*ref.getHeight()));
|
|
}
|
|
|
|
|
|
public static void map(BufferedImage input, BufferedImage output, int projection) {
|
|
final int width = output.getWidth();
|
|
final int height = output.getHeight();
|
|
|
|
for (int x = 0; x < output.getWidth(); x ++) {
|
|
for (int y = 0; y < output.getHeight(); y ++) {
|
|
switch (projection) {
|
|
case QUINCUNCIAL:
|
|
output.setRGB(x, y, quincuncial(0,0,0,width,height,x,y,input));
|
|
break;
|
|
case EQUIRECTANGULAR:
|
|
output.setRGB(x, y, equirectangular(0,0,0,width,height,x,y,input));
|
|
break;
|
|
case MERCATOR:
|
|
output.setRGB(x, y, mercator(0,0,0,width,height,x,y,input));
|
|
break;
|
|
default:
|
|
System.err.println("Justin, you forgot to add a projection to the switch case!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private static void saveImage(BufferedImage img) {
|
|
try {
|
|
File outputFile = new File("output/myMap.jpg");
|
|
ImageIO.write(img, "jpg", outputFile);
|
|
} catch (IOException e) {}
|
|
}
|
|
}
|