Move a Cartographic by a distance in meters?

I have a lat/lon point and would like to create a new point a fixed distance away, at a given angle along the Earth’s surface. Let’s assume I’m using the default (WGS84) ellipsoid. It seems like it should be dead simple math but the fact that it’s on the ellipsoid surface complicates things, and I’d rather use an existing Cesium function/class than reinvent the wheel and probably miss an edge case (or six). Ideally, I’d have a method like newPoint = Cartographic.add(oldPoint, distance, angle).

Is this more or less what this RhumbLine method does? Are there any gotchas to trying to use it the way I described? Is there a simpler way to do this if the angle is a right angle (i.e. moving strictly N/S/E/W)?

Is this kind of what you’re trying to do: Finding a point on the surface at a given distance ?

Rhumblines aren’t straight lines (with 2 exceptions) so you’d definitely want to travel along a geodesic / great circle. Latitude lines (except the equator) appear to be straight but are curved ) The 2 exceptions traveling along constant headings (Rhumblines) are along the equator and the meridians.

Cesium geodesic methods lack the ability to determine a geodesic if given a point, distance, and initial heading. https://cesium.com/docs/cesiumjs-ref-doc/EllipsoidGeodesic.html
-You can feed it 2 points to get initial and final headings.
-You can interpolate,extrapolate a geodesic to get another point along the geodesic.

On this thread
Ellipsoid Geodesic methods
There’s a link to formulas that’ll give you the formula you need

I transcribed the one for spheres from LatLon site. For most purpose it will be close enough when applied to ellipsoid Earth. The one for ellipsoids is alot more involved (but very accurate), I might transcribe that one at a later date.

(removed code from here as I have it on my next post)

What you could do is get the destination point using the transcribed function I placed here, create a geodesic with the original start point and use this to get the end point. Then compare the initial heading. I bet it will be close enough.

Here’s an example you can try in Sandcastle. This formula is for a spherical Earth, but if you don’t need extreme precision it’ll work OK. Initial heading is off 0.06 deg over a distance of 10,000 meters. (with distance off by 1.7 meters). This is likely due to the difference between geodetic and geocentric latitudes (which is what makes Earth not a perfect sphere thanks to the bulge caused by spinning.)

var viewer = new Cesium.Viewer("cesiumContainer");

function destGivenBearingStartDistance(bearingDeg, distance, latRad, lonRad, radius=6371e3)
{
	let bearingRad=bearingDeg*Math.PI/180;
	let angDisRad = distance / radius;
	let sinLat2 = Math.sin(latRad) * Math.cos(angDisRad) + Math.cos(latRad) * Math.sin(angDisRad) * Math.cos(bearingRad);
	let lat2Rad = Math.asin(sinLat2);
	let y = Math.sin(bearingRad) * Math.sin(angDisRad) * Math.cos(latRad);
	let x = Math.cos(angDisRad) - Math.sin(latRad) * sinLat2;
	let lon2Rad = lonRad + Math.atan2(y, x);

	return new Cesium.Cartographic.fromRadians(lon2Rad,lat2Rad);
}

  let startLonDeg = 10;let startLatDeg = 45;
  let bearingDeg = 20;let distance = 10000;
  let start = new Cesium.Cartographic.fromDegrees(startLonDeg,startLatDeg);
  let end = new Cesium.Cartographic();
  end = destGivenBearingStartDistance(bearingDeg, distance, start.latitude, start.longitude);
  let myGeodesic = new Cesium.EllipsoidGeodesic(start,end,viewer.scene.globe.ellipsoid);
  console.log(myGeodesic.startHeading*180/Math.PI);
  console.log(myGeodesic.surfaceDistance);
1 Like

Omar, the post you linked to presumes that I have a “direction point”, but I need to start with a heading angle, so I don’t think it would work.

Thanks for the function, Hyper_Sonic, that will probably fit the bill! The margin of error is likely fine, this is for drawing shapes that I wouldn’t expect to have inspected at a super-zoomed-in scale.

Just to double check, the rhumb-line method is accurate along meridians and the equator – does that mean it would not work on other lines of latitude for “travel” at +/- 90 degrees heading? It sounded like it would because the definition I found said a rhumb line is the path you get by holding the same heading, and if you keep the north pole at 90 degrees and go forward, you’re making a parallel around the ellipsoid, right? (3D trig was, uh, a very long time ago for me.)

ETA: I also filed an issue in hopes that somebody takes pity and solves this “right”, eventually.

Ya you would think a constant heading would mean a straight line (likely due to seeing 2D maps of the Earth) but on a globe it does not (the equator and meridians being the only exceptions.) Walking along a line of latitude other than the equator isn’t even a straight line. Copy/Paste this into Sandcastle to see the difference between a straight line (geodesic/great circle) and a Rhumbline. Both lines have the same start and end point.

var czml = [
  {
    id: "document",
    name: "CZML Geometries: Polyline",
    version: "1.0",
  },
  {
    id: "redLine",
    name: "Red line clamped to terain",
    polyline: {
      positions: {
        cartographicDegrees: [-75, 35, 0, -177, 66, 0],
      },
      material: {
        solidColor: {
          color: {
            rgba: [255, 0, 0, 255],
          },
        },
      },
      width: 5,
      arcType: "RHUMB",
      clampToGround: true,
    },
  },

  {
    id: "orangeLine",
    name:
      "Orange line with black outline at height and following the surface",
    polyline: {
      positions: {
        cartographicDegrees: [-75, 35, 0, -177, 66, 0],
      },
      material: {
        polylineOutline: {
          color: {
            rgba: [255, 165, 0, 255],
          },
          outlineColor: {
            rgba: [0, 0, 0, 255],
          },
          outlineWidth: 2,
        },
      },
      width: 5,
    },
  },
];

var viewer = new Cesium.Viewer("cesiumContainer");
var dataSourcePromise = Cesium.CzmlDataSource.load(czml);
viewer.dataSources.add(dataSourcePromise);
viewer.zoomTo(dataSourcePromise);

There should exist a concept of ‘Great Circle/Geodesic’ heading (I’d say define it as the heading where it crosses the equator going north.) Rhumbline heading means the angle you cross each meridian is the same, but that’s curved along the globe (though straight on those 2D Mercator maps.) Oh ya, lines that are straight on globes are curved on 2D maps.

Great circles could be parallel to eachother (but still intersect) or perpendicular to eachother (90deg apart at intersections.) Equator and Meridians are perpendicular to eachother. Meridians are all parallel to eachother.

Ya Cesium Rhumblines have more methods than Geodesics
https://cesium.com/docs/cesiumjs-ref-doc/EllipsoidRhumbLine.html
https://cesium.com/docs/cesiumjs-ref-doc/EllipsoidGeodesic.html

Specifically (what Rhumbline library has that Geodesic doesn’t)
fromStartHeadingDistance
findIntersectionWithLatitude
findIntersectionWithLongitude
Finding intersections with an arbitrary geodesic would be neat as well.

This site demonstrates a method for an Ellipsoid Earth
For geodesic fromStartHeadingDistance
https://www.movable-type.co.uk/scripts/latlong-vincenty.html

I’m trying to get my terminology right. I pasted your example in but it doesn’t directly address my question – I was asking about movement between points at the same latitude, i.e. along a line of latitude. If I change your code to cartographicDegrees: [-75, 35, 0, -177, 35, 0], I can clearly see that the orange line with the default arcType (geodesic) follows a Great Circle path that crosses over Washington state (maybe Canada?) while the rhumb arc passes over southern CA. My question before was, is a rhumb line where the start and end points share a latitude always parallel to the equator, and in this example it looks like the answer is yes. Put another way, if I do rhumb-line arithmetic starting at a heading of +/- 90 degrees, I will stay on a parallel, I think.

So changing the end point latitude of both lines in that example to 35.

Ya the Rhumbline exactly follows the +35deg latitude line. All latitude lines are Rhumblines. Equator and meridians having the unique privilege of being both a Rhumbline and Great Circle

In one sense latitude lines are ‘straight’, you look from the side of the Earth they are all parallel to eachother (can really tell using an orthographic projection.)

However in another sense they are not straight. If you walk along a latitude line you have to keep turning to stay on it (gotta keep turning to keep the same compass heading.) To clearly see this take the example sandcastle code I posted and modify both lines to these start,end points
Quebec City to Olympia, WA:
[-71,47,0,-123,47,0]

Now place the camera directly overhead these lines. By directly overhead I mean make sure a point on the line is exactly in between the camera and the center of the Earth. You’ll notice that the Rhumbline is longer and curved, while the Geodesic is shorter and straight. (might have to a bit of both ctrl-leftbutton drag and shift-leftbutton drag to get the view correct.)

Oh ya, on the top right shift the view to 2D, now the Rhumbline is straight, and the Geodesic is curved. 2D warps everything. (2 2D modes, one orthographic, other perspective)

1 Like