I searched about a day now, but didnt find any example for my problem in Javacode.
I have a worldmap with a size of 2000*1400 Pixels with a 'Mollweide' projection. How can I find out what is the longitude and laltitude of the point (500,300) in my map ? I would like to code this in Java.
I tried to do this with the 'Java Map Projection Library' :
Point2D.Double pointonmap = null;
Point2D.Double latlon = null;
MolleweideProjection molproj=new MolleweideProjection();
pointonmap = new Point2D.Double (1400,1000);
latlon=molproj.inverseTransform(pointonmap,new Point2D.Double ());
System.out.println("latlon: " + latlon.getX() + ", " + latlon.getY());
Could anyone help me with that ? Codeexample or hint.
thanks and regards
In Mollweide projection, the central meridian and the equator are projected as a straight perpendicular line. The equator is twice the length of the projected central meridian. The 90 degrees west and 90 degrees east form a circle, while the rest of the meridian assume the same spacing at the equator.
The Mollweide projection is an equal-area pseudocylindrical map projection displaying the world in a form of an ellipse with axes in a 2:1 ratio. It is also known as Babinet, elliptical, homolographic, or homalographic projection. The projection is appropriate for thematic and other world maps requiring accurate areas.
The Mollweide projection is an equal-area map projection. It preserves the size of figures, but heavily distorts the shapes when getting nearer to the edge of the map. Mollweide maps are especially used for global maps where its equal-area property helps to display global distributions.
Wikipedia has most of the information you need:
These formulas assume a few things, as usual. They speak in projected dimension, which is smaller than the component. [0,0] is at the centre, not top left. Y coordinate goes up rather than goes down. And the result is in radius instead of degree. Fix these and they'll work for you.
Since you didn't provide a link, I assume you are using the Java Map Projection Library on GitHub.
Without documentation and with limited time, I can't understand inverseTransform
well enough to fix your code; but the bundled MapComponent is simpler to code:
map.addMouseListener( new MouseAdapter() { @Override public void mouseClicked( MouseEvent e ) {
double x = e.getX() - map.getWidth() / 2, // Mouse X with [0,0] at centre.
y = e.getY() - map.getHeight() / 2, // Mouse Y with [0,0] at centre.
// Max Y of projected map, in pixel with [0,0] at centre.
maxY = map.getMapExtension().getMaxY() * map.getScaleToShowAll(),
sqrt2 = Math.sqrt( 2 ), // Can be optimised away, but let's be faithful.
R = maxY / sqrt2, // Radius of projection, in pixel.
theta = Math.asin( y / ( R * sqrt2 ) );
int delta_long = -lon0Slider.getValue(); // Longtitude shift from -180 to 180.
// Find lat long in radius and converts to degree.
double latInRad = Math.asin( -( 2 * theta + Math.sin( 2 * theta ) ) / Math.PI ),
latitude = Math.toDegrees( latInRad ),
longInRad = Math.PI * x / ( 2 * R * sqrt2 * Math.cos( theta ) ),
longitude = Math.toDegrees( longInRad ) + delta_long;
System.out.println( "Lat: " + latitude + ", Long: " + longitude );
}
You can paste this code into the constructor of ch.ethz.karto.gui.ProjectionSelectionPanel
.
The IDE should reports that two methods of the map is private, and you need to change them to public first (or use reflection).
Then launch it, select Mollweide, click on the globe and watch the console. Feel free to resize the window.
This answer uses information from the English Wikipedia entry on Mollweide projection. I've pretty much transcribed the formula from there verbatim.
The short answer, so you can write your own code:
Get the map's radius, r:
projectionWidth /(2 * √2)
Get theta, the point's angle along the map:
arcsine(y / (r * √2))
Note: Arcsine is the inverse of sine. Use Math.asin(a) in java
Get the latitude:
arcsine((2 * theta + sine(2 * theta)) / PI)
Get the longitude:
PI * x / (2 * R * √2 * cosine(theta)) + central meridian.
Or you can copyPasta this.
It's not very efficient; x and y are spec as doubles becaus too lazy to write typecast avoid narrowing
no-setters no-getters all-vars public
all-world-one-love Dr. Bronner's TV-dinners solve your problems for you
and stuff
enoj
public class MolleweidePoint
{
public double x, y, latitude, longitude;
public MolleweidePoint(double projectionWidth, double x, double y)
{
double rootTwo = Math.sqrt(2);
double r = projectionWidth / 2 / rootTwo;
double theta = Math.asin(y / r / rootTwo);
this.x = x;
this.y = y;
longitude = Math.PI * x / 2 / r / rootTwo / Math.cos(theta);
latitude = Math.asin(2 * theta + Math.sin(2 * theta) / Math.PI);
}
}
After calling the constructor like
MolleweidePoint ted = new MolleweidePoint(projection.width, 300, 500)
you can get the latitude and longitude from ted.longitude
and ted.latitude
. Also, longitude may have to be adjusted based on where the central meridian is placed on your projection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With