I'm currently implementing 3DTiles into my java application. I know that I will only work with the region BoundingVolume. The BoundingVolume has 6 values: west, south, east, north, minHeight and maxHeight. Min and maxHeight are in meters above the WGS 84 ellipsoid and the other values are given in WGS 84 datum as defined in EPSG 4979 and are in radians. So far so good.

Now my problem is the next step. I am personally working with Point Clouds, so I read in a .pnts file and obtain the position data for every point that is in the Point Cloud. I get x,y and z values. I think the z values are in meters again but I don't know how to use the x and y values. If I try to convert them from radians to degree the values are not correct. I also get the values of an RTC_Center which has 3 values. I guess they are x,y and z but I also don't know how to work with these. I want to display them on a globe and need them as Latitude and Longitude(atleast I think so).

So my question is: how do I work with the obtained position values if I need them as Latitude and Longitude. I have the feeling the RTC_CENTER is important but I don't know for what.

I will leave some links to the 3DTiles specifications that I think will help.

Coordinate reference system

PointCloud point positions

1 Answer 1


So I found an answer to my problem and thought that I would post it here if anyone ever should have the same question :).

private static void CartesianToGeodetic(double x, double y, double z){
   Taken from https://www.movable-type.co.uk/scripts/geodesy/docs/latlon-ellipsoidal.js.html
   by Chris Veness 2005-2019
   //Values for the WGS84 Ellipsoid. a = equatorial radius in meters, b= semi-minor axis, f = flattening
   double a = 6378137;
   double b = 6356752.314245;
   double f = 1/298.257223563;

       double e2 = 2*f - f*f;           // 1st eccentricity squared ≡ (a²−b²)/a²

       double ε2 = e2 / (1-e2);         // 2nd eccentricity squared ≡ (a²−b²)/b²

       double p = Math.sqrt(x*x + y*y); // distance from minor axis

       double R = Math.sqrt(p*p + z*z); // polar radius

   // parametric latitude (Bowring eqn.17, replacing tanß = z·a / p·b)

      double tanß = (b*z)/(a*p) * (1+ε2*b/R);

       double sinß = tanß / Math.sqrt(1+tanß*tanß);

       double cosß = sinß / tanß;

   // geodetic latitude (Bowring eqn.18: tanphi = z+ε²⋅b⋅sin³ß / p−e²⋅cos³ß)

       double phi = Double.isNaN(cosß) ? 0 : Math.atan2(z + ε2*b*sinß*sinß*sinß, p - e2*a*cosß*cosß*cosß);

   // longitude

       double lambda = Math.atan2(y, x);

   // height above ellipsoid (Bowring eqn.7)

       double sinphi = Math.sin(phi), cosphi = Math.cos(phi);

       double ny = a / Math.sqrt(1-e2*sinphi*sinphi); // length of the normal terminated by the minor axis

       double h = p*cosphi + z*sinphi - (a*a/ny);

   //for now just prints the result to the console but you could just return the result ;)
   System.out.println(phi+" "+lambda+" "+h);


As already written in the comments of the code I found this solution here. Maybe this helps someone someday :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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