Search code examples
javascriptprojectioncalculationcesiumjs

Cesium JS ellipsoid tangent plane calculation


Problem

I am a bit confused on how Cesium calculates geodetic and geocentric surface normal. Planes, generated from calculated normal do not actually tangent to ellipsoid surface in a given point, more then, the plane created from geodetic surface normal is just the same as one generated from geocentric surface normal.

Example & why do I need this

In this Sandcastle XYZ axis along with planes that should be tangent to ellipsoid are drawn when you click on the globe surface.

What I need is to get an XY plane tangent to Ellipsoid at given point and then project other points onto this plane. The problem is as I see the plane is not tangent to ellipsoid at all.

By the way - when I use built in method: Cesium.EllipsoidTangentPlane(); I also get strange result - plane is still not tangent to ellipsoid and also floating somewhere in space. Here is sandcastle.

Appreciate any help because I do not understand what happens here.


Solution

  • The normal of the plane is defined at the local coordinate system of the plane, of which x, y, and z-axis indicate the east, north, and up direction in the earth(world or ECEF ), respectively. So if the normal vector of a plane is given in the ECEF, you have to convert it at the plane's local coordinate system like this.

        // get the local coordinate system of the plane
        var transform = Cesium.Transforms.eastNorthUpToFixedFrame(clickedPoint);
        // get invert matrix
        var inv = Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4());
        // in this case actually world normal coincide with up direction(z axis of coordinate system)
        // to avoid error we slightly extend it.
        var extendedWordNormal = Cesium.Cartesian3.multiplyByScalar(clickedPoint, 1.001, new Cesium.Cartesian3());
        
        // it will be nearly same as (0, 0, 1)
        var localNormal = Cesium.Matrix4.multiplyByPoint(inv, extendedWordNormal, new Cesium.Cartesian3());
    
        //var localNormal = new Cesium.Cartesian3(0, 0, 1);
    

    Please check this sandcastle and this sample