Tuesday 16 May 2023

What is the system behind wrong offset of latitude mapped to svg?

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?



from What is the system behind wrong offset of latitude mapped to svg?

No comments:

Post a Comment