1

I map cities based on their latitude and longitude data on an svg map. The svg map uses the mercator projection (as google maps). The red dots are drawed in Illustrator and represent the correct position. The black dots are dynamically set with Javascript based on my calculation which is obviously flawed. But I can't see a system behind the offsets. The closer the cities are to the bounds of the map, the more exact their positions are. The more centered they are, the more offsetted they are. But not really proportionally: enter image description here

This is what I do for the x coordinates, which works fine:

Math.abs(lon - west) * scale

west represents the longitude of the westernmost point of the map. scale represents the factor I use to multiply the latitude and longitude values to represent them on the map.

Example data for working x coordinate:

const west = 5.866944;
const scale = 100;
const lon = 13.404954 // longitude of Berlin
const x = Math.floor(Math.abs(lon - west) * scale) // 753
Utils:
getMapPosition(lon, lat) {
  return  [
    Math.floor(Math.abs(lon - this.west) * this.scale), 
    Math.floor(Math.abs(lat - this.north) * this.scale * (this.getMercatorScaleFactorY(this.center[1])))
  ]
}
The React Component:
{mapdata.cities.map((city, idx) => {
  const [x, y] = map.getMapPosition(city.lon, city.lat);
    return (<Fragment key={idx}>
      <circle cx={x} cy={y} r="5" />
      <text x={x + 10} y={y}>{city.name}</text>
    </Fragment>)
})}

The rendered circle:
<circle cx="753" cy="404" r="5"></circle>

Difference with latitude:

With the latitude it gets more complicated. The latitude on the northern hemisphere decreases the further south you get while the y coordinates on an svg increases. So I have to revert the output. Additionally, the mercator projection becomes relevant for this area. This is what I do for the y coordinates:

Utils:
function getMercatorScaleFactorY(centerLat) {
        const getRadians = (deg) => deg * Math.PI / 180;
        return 1 / Math.cos(getRadians(centerLat));
}
const centerLat = 51.16497175; // latitude of the center spot on the current map 
Math.floor(Math.abs(lat - north) * scale * getMercatorScaleFactorY(centerLat)))

The mercator factor of the center should do for all cities given the relatively small size of the country. I also tried a calculation where I got the individual mercator factor for each destination. Also to no avail. The offset gets bigger the further south you get and adjusts shortly before the southern border. Does anyone have an idea what's causing this and how it can be solved?

Codesandbox

https://codesandbox.io/p/sandbox/svgmapbuilder-4p4le2

mirja-t
  • 108
  • 1
  • 10
  • Hi, would you mind putting the relevant code in a stack snippet, so we can conveniently edit it? – Mehdi May 16 '23 at 07:01
  • Just added a link to a sandbox. The calculations can be found in utils/svgMapBuilder.ts. In Map.tsx it gets rendered. – mirja-t May 16 '23 at 08:10
  • Is it not that Lon/lat are coordinates on a Sphere and your projection is flat? you need to use the same math that projected the map on your coordinates – NickSlash May 16 '23 at 08:17
  • @NickSlash it is just 876 km airline distance from north to south – so can that have such an effect, especially given the fact that it works fine for the x coordinates (640km)? And the offsets don't really seem to represent that missed spherical aspect because they should be equal in both directions from the center then, I assume. – mirja-t May 16 '23 at 08:42
  • 1
    https://stackoverflow.com/a/27313080/212869 this might be helpful – NickSlash May 16 '23 at 12:38
  • @NickSlash thank you, that function delivers the correct output. – mirja-t May 16 '23 at 14:32

1 Answers1

1

There is no single mercator projection. There are a very very large number of them (transverse mercator, UTM etc.) that are often relative to a country (e.g Irish Transverse Mercator). And there is no such thing as a "correct" x,y coordinate. Every x, y coordinate is relative to a system (e.g. the WGS 84 geo). You need to know waht specific mercator projection your data is from and what specific "correct" coordinate system you are using. Once you establish that, you can use a tool like https://epsg.io/transform to transform one to another.

Michael Mullany
  • 30,283
  • 6
  • 81
  • 105
  • Thanks for the clarification. The red dots match the positions in Google Maps which is using the WGS 84 geo system. In the Wikipedia article [Wikipedia article about Mercator projection](https://en.wikipedia.org/wiki/Mercator_projection) a scale factor for latitudes is mentioned which I used for my projection. Since the total distance is less than 1000km, I did not expect such noticeable offsets and I still don't understand the much stronger distortion at the bottom. The positions are correctly mapped if I use the calculation from the link posted in the comments above. – mirja-t May 19 '23 at 20:01