3

I am doing a JavaScript application that requires the movement of a certain element in a real world map, in frames.

For each frame, I have the following positions in latitude and longitude for the element, for example for frame 0:
- Latitude: 49.011213
- Longitude: 8.422885

For frame 1:
- Latitude: 49.01121
- Longitude: 8.422887

Frame (Frame 0) needs to be point (0,0) and I want the following ones to be converted to XY coordinates as well.

Basically, I need a JavaScript script that receives the latitude and longitude of a frame and returns the position (x,y) for that frame (in relation to frame 0 with position (0,0)).

I've tried the following but it doesn't work:

function convertSphericalToCartesian(latitude, longitude)
{
    // Convert from Degrees to Radians
    let latRad = latitude * (Math.PI)/180; 
    let lonRad = longitude * (Math.PI)/180;

    let earthRadius = 6367; // Radius in km
    let posX = earthRadius * Math.cos(latRad) * Math.cos(lonRad);
    let posY = earthRadius * Math.cos(latRad) * Math.sin(lonRad);
    return {x: posX, y: posY};
}

Do you know a better formula for this?

4
  • I feel like this is a very loaded question, that lies at the heart of a lot of GIS. It sounds like you are asking how to project points from 3-D spherical coordinates to a 2-D space - is that correct? You might start by using the haversine formula, but this will only works for very small distances, and will loose accuracy with larger distances. What javascript mapping library are you using? google maps? leaflet? arcgis js? Some of these come with pre-written formulas for getting xy coordinates from latlng coordinates. Mar 11, 2020 at 16:57
  • Yes, actually it is a VR A-frame app, but its based on very small distances. I saw that formula, but it only gives me the distance between the two points, and I want the coordinates of the points. (Or of one point, since the other is (0,0)). I am using this for the map: vrmap.kairo.at
    – Toliveira
    Mar 11, 2020 at 17:08
  • 1
    The XY plane of your formulas is the plane of the equator of a sphere. How would you define, with your words, the XY plane that you want? Mar 11, 2020 at 19:48
  • I'm using any map of around 25m² or less. It can be anywhere on the globe, but in any map, I want to convert any two points in there to XY coordinates.
    – Toliveira
    Mar 12, 2020 at 9:34

1 Answer 1

4

You need the bearing, which is the angle from point 1 point 2 on the surface of the globe. You can get that from turf.js, a powerful GIS calculation library.

Then you need a distance formula, to get the distance on the surface of the globe between the two points. Again, turf.js has a distance function.

Once you have the bearing and the distance, you've basically turned this into a 2D cartesian coordinates problem. Now you need to pick your units of x and y. What is a unit of x / y? 1 meter? 1 km? Lets say we that 1 unit of x or y is equal to 1 meter. If you find that point 2 is 35m away from point 1, with a bearing of 90 degrees, you know that the xy coordinates of point 2 would be (0,35), assuming `(0,0) for point 1. If point 2 is 1.4km away from point 1, with a bearing of 32 degrees, point 2's xy coords can be calculated with some simple trig: ( 1400 * cos(32) , 1400 * sin(32) ).

So a js function might look like this:

function getCoordsOfNextPoint( firstPoint, nextPoint, prevXY = {x: 0, y: 0} ) {

  const bearing = turf.bearing(firstPoint, nextPoint);
  const distance = turf.distance(firstPoint, nextPoint, {units: 'kilometers'});

  const xy = {
    x:  prevXY.x + distance * 1000 * Math.cos(bearing * Math.PI / 180),
    y:  prevXY.y + distance * 1000 * Math.sin(bearing * Math.PI / 180)
  }

  return xy

}

const myFirstPoint = [-75.343, 39.984]
const mySecondPoint = [-75.534, 39.123]
const secondPointXYCoords = getCoordsOfNextPoint(myFirstPoint, mySecondPoint)

You may want to tweak the units or parameters. Also watch out for the conventions on the units of what the bearing function returns, that can trip you up. (I know its tripped me up in the past). Turf is super powerful, definitely worth looking into.

Edit: stringing points together

To get from point 0 to point 1, you won't need the extra parameter prevXY. But every point after that will take the point returned by the function used for the 2 points before it. For example:

// Assuming x0y0 = { x: 0, y: 0}

const x1y1 = secondPointXYCoords = getCoordsOfNextPoint(myFirstPoint, mySecondPoint)
const x2y2 = secondPointXYCoords = getCoordsOfNextPoint(myFirstPoint, mySecondPoint, x1y1)
const x3y3 = vsecondPointXYCoords = getCoordsOfNextPoint(myFirstPoint, mySecondPoint, x2y2)

And you could write a loop to read your latlng points from an array and write to another array of xy points, which will basically translate your latlng points to xy points.

Hopefully that gets your started.

8
  • This is actually not working for me, and I don't understand why, but I believe it's because of the bearing, since the distance is giving right results. I tried tweaking a little bit the units, but I couldn't get any progress.
    – Toliveira
    Mar 12, 2020 at 10:33
  • What issue are you having? Are you getting error, or just incorrect results? Mar 12, 2020 at 16:45
  • Incorrect Results. For example, i have a element that should move forward in a road, but with this function, the element is moving in what it somehow seems a circle.
    – Toliveira
    Mar 12, 2020 at 16:55
  • The function I wrote only returns x2y2 given a pair of latlng points, with the assumption of x1y1 = (0,0). How are you implementing / iterating this function? Mar 12, 2020 at 17:57
  • Mmmmm not as far as I can tell. From the docs, "Returns: number - bearing in decimal degrees, between -180 and 180 degrees (positive clockwise)" Mar 13, 2020 at 20:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.