9

I have set values of minimum longitude and latitude of a specific static map image. That map image is a cut of some country.

/**
 * Maximum longitude value of the map
 */
private float mapLongitudeMax;

/**
 * Minimum longitude value of the map
 */
private float mapLongitudeMin;

/**
 * Maximum latitude value of the map
 */
private float mapLatitudeMax;

/**
 * Minimum latitude value of the map
 */
private float mapLatitudeMin;

And I have a BufferedImage called mapImage.

I have a method that I wrote with a friend that receives longitude and latitude and gives you an X and a Y position approximately on the map so you can draw something on the map.

Now if I want to move my mouse around the map, I want it to show longitude/latitude of my mouse position, that means I need to create a method which converts X and Y of the mouse position to longitude and latitude, which should do the opposite of my other method.

This is my method to convert globe coordinates to image X and Y:

protected Location getCoordinatesByGlobe(float latitude, float longitude) {

    /**
     * Work out minimum and maximums, clamp inside map bounds
     */
    latitude = Math.max(mapLatitudeMin, Math.min(mapLatitudeMax, latitude));
    longitude = Math.max(mapLongitudeMin, Math.min(mapLongitudeMax, longitude));

    /**
     * We need the distance from 0 or minimum long/lat
     */
    float adjLon = longitude - mapLongitudeMin;
    float adjLat = latitude - mapLatitudeMin;

    float mapLongWidth = mapLongitudeMax - mapLongitudeMin;
    float mapLatHeight = mapLatitudeMax - mapLatitudeMin;

    float mapWidth = mapImage.getWidth();
    float mapHeight = mapImage.getHeight();

    float longPixelRatio = mapWidth / mapLongWidth;
    float latPixelRatio = mapHeight / mapLatHeight;

    int x = Math.round(adjLon * longPixelRatio) - 3;// these are offsets for the target icon that shows.. eedit laterrr @oz
    int y = Math.round(adjLat * latPixelRatio) + 3; //

    // turn it up
    y = (int) (mapHeight - y);

    return new Location(x, y);
}

Now I tried thinking, the first thought that came into my head is just doing the same in reverse... so I started doing it and I ran into problems like, I can't get the value of adjLon or adjLat without having the longitude or latitude, so this can't be simply done by reversing it. I am all new to coordinates systems so it's all a bit confusing for me but I am starting to catch it up.

Any tips for me?

EDIT (Its not possible?)

According to this answer, you can't really get real results because the earth is not flat, it can't really be converted to a flat map with longitude and latitude without implementing a real mathematical algorithm to make it work with the changes.

There are few reasons in my code why the answer can not be exact:

  1. Because of the reason above
  2. Because my X,Y values are integers and not floats.

So my question now, if it is really impossible with my method?

Community
  • 1
  • 1
Artemkller545
  • 979
  • 3
  • 21
  • 55
  • Possible duplicate of [*Implementing a mouse click event on a tile in a map*](http://stackoverflow.com/q/32170318/230513). – trashgod Aug 07 '16 at 20:27
  • What is your application used for? If you try to use it for estimates it is OK to have some roundings etc. – Hash Aug 11 '16 at 07:45
  • You can get results that are "good enough" for your applications by using a model that has accuracy sufficient for your application. In general, that'll be determined by the pixel:degree ratio of the image you're hovering your mouse over. There are many, many different ways to "Unwrap" the spheroid. The one I mentioned is one of the of the most popular, but there are others. This should get you started: https://en.wikipedia.org/wiki/List_of_map_projections – Benjamin Oct 31 '16 at 16:17

3 Answers3

5

Sadly, there's not an easy answer to this. While you can write the projection routines yourself, the easiest thing to do is probably to get a GIS library, but since I ended up doing this in C# and not Java, I don't know what's available.

The biggest piece of information you need is exactly which projection your map image uses. The Mercator Projection is quite popular, but it's not the only one. You also need to make sure that your chosen projection works for the range of latitudes and longitudes you want. The Mercator projection kind of breaks if you start going above +-70 N, so if you're doing a lot of positions at the poles that might not be the projection for you.

Benjamin
  • 921
  • 5
  • 15
1

From what i read in your code, your image is in longitude/latitude coordinates, and you draw it on a canvas to be display on screen. Then you add your listener on this image is that correct ?

if this is correct the response is trival, as you can retrieve the X/Y position in your image via MouseListener method on Canvas and transform it base on the position of the mouse inside the canvas (methode getX/getY from mouseEvent) and the current dimension of the canvas and then translate this position within the bound of longitude/latitude.

longitude = minLongitude + (MouseEvent.getX/Canvas.Width)*maxLongitude
lalitude = minLaltitude + (MouseEvent.getY/Canvas.Height)*maxLatitude

If not then you will have to know as @ginkner say the projection technique use to pass from long/lat to X/Y and take the inverse transformation knowing that you will lost some information.

0

There is a difference between geography coordinate and geometry coordinate it is quite like the 3D earch surface and a canvas to draw on. The web Mercator projection or other popular projection coordinate systems are used for an abstraction of visualization of the earth surface. So that pixel shift in different location would result in different distances.

If you are looking for a some basic GIS java library to handle this type of problem, Geotools in Java could be one option. GeoTools

Teng Ma
  • 353
  • 2
  • 9