proper/best type for storing latitude and longitude

前端 未结 13 794
天涯浪人
天涯浪人 2020-12-07 11:21

In a system level programming language like C, C++ or D, what is the best type/encoding for storing latitude and longitude?

The options I see are:

  • IEEE
相关标签:
13条回答
  • 2020-12-07 11:59

    The following code packs the WGS84 coordinates losslessly coordinates into an unsigned long (i.e. into 8 bytes):

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Utils
    {
        /// <summary>
        /// Lossless conversion of OSM coordinates to a simple long.
        /// </summary>
        unsafe class CoordinateStore
        {
            private readonly double _lat, _lon;
            private readonly long _encoded;
    
            public CoordinateStore(double lon,double lat)
            {
                // Ensure valid lat/lon
                if (lon < -180.0) lon = 180.0+(lon+180.0); else if (lon > 180.0) lon = -180.0 + (lon-180.0);
                if (lat < -90.0) lat = 90.0 + (lat + 90.0); else if (lat > 90.0) lat = -90.0 + (lat - 90.0);
    
                _lon = lon; _lat = lat;
    
                // Move to 0..(180/90)
                var dlon = (decimal)lon + 180m;
                var dlat = (decimal)lat + 90m;
    
                // Calculate grid
                var grid = (((int)dlat) * 360) + ((int)dlon);
    
                // Get local offset
                var ilon = (uint)((dlon - (int)(dlon))*10000000m);
                var ilat = (uint)((dlat - (int)(dlat))*10000000m);
    
                var encoded = new byte[8];
                fixed (byte* pEncoded = &encoded[0])
                {
                    ((ushort*)pEncoded)[0] = (ushort) grid;
                    ((ushort*)pEncoded)[1] = (ushort)(ilon&0xFFFF);
                    ((ushort*)pEncoded)[2] = (ushort)(ilat&0xFFFF);
                    pEncoded[6] = (byte)((ilon >> 16)&0xFF);
                    pEncoded[7] = (byte)((ilat >> 16)&0xFF);
    
                    _encoded = ((long*) pEncoded)[0];
                }
            }
    
            public CoordinateStore(long source)
            {
                // Extract grid and local offset
                int grid;
                decimal ilon, ilat;
                var encoded = new byte[8];
                fixed(byte *pEncoded = &encoded[0])
                {
                    ((long*) pEncoded)[0] = source;
                    grid = ((ushort*) pEncoded)[0];
                    ilon = ((ushort*)pEncoded)[1] + (((uint)pEncoded[6]) << 16);
                    ilat = ((ushort*)pEncoded)[2] + (((uint)pEncoded[7]) << 16);
                }
    
                // Recalculate 0..(180/90) coordinates
                var dlon = (uint)(grid % 360) + (ilon / 10000000m);
                var dlat = (uint)(grid / 360) + (ilat / 10000000m);
    
                // Returns to WGS84
                _lon = (double)(dlon - 180m);
                _lat = (double)(dlat - 90m);
            }
    
            public double Lon { get { return _lon; } }
            public double Lat { get { return _lat; } }
            public long   Encoded { get { return _encoded; } }
    
    
            public static long PackCoord(double lon,double lat)
            {
                return (new CoordinateStore(lon, lat)).Encoded;
            }
            public static KeyValuePair<double, double> UnPackCoord(long coord)
            {
                var tmp = new CoordinateStore(coord);
                return new KeyValuePair<double, double>(tmp.Lat,tmp.Lon);
            }
        }
    }
    

    Source: http://www.dupuis.me/node/35

    0 讨论(0)
提交回复
热议问题