none
QuadKey: Point mapping to wrong tile?

    Question

  • Hey guys! In my current project, I am extensively working with QuadKeys and now I'm facing the following problem. Please take a look at the illustrating code example below. I have a point and map it to a tile on "precision" 16. However, the resulting tile seems to be off and does not even contain the point, while another tile would be a better fit. Can you please help me figure out my mistake?

    I'm using the reference code from https://msdn.microsoft.com/en-us/library/bb259689.aspx?f=255&MSPPError=-2147217396

    using System;
    using Microsoft.MapPoint;
    
    namespace QuadKeys
    {
        class Program
        {
            static void Main(string[] args)
            {
                int lvl = 16;
                int pixelX, pixelY;
                int tileX, tileY;
                double lat, lon;
    
                // Point to QuadKey: (37.522942111, -122.266098111) -> 0230102300203310
                TileSystem.LatLongToPixelXY(37.522942111, -122.266098111, lvl, out pixelX, out pixelY);
                TileSystem.PixelXYToTileXY(pixelX, pixelY, out tileX, out tileY);
                string quad = TileSystem.TileXYToQuadKey(tileX, tileY, lvl);
                Console.WriteLine(quad);
    
                // QuadKey back to point (tile center): 0230102300203310 -> (37.5271536172338, -122.266845703125)
                TileSystem.QuadKeyToTileXY(quad, out tileX, out tileY, out lvl);
                TileSystem.TileXYToPixelXY(tileX, tileY, out pixelX, out pixelY);
                TileSystem.PixelXYToLatLong(pixelX, pixelY, lvl, out lat, out lon);
                Console.WriteLine(lat + ", " + lon);
    
                // Now let's take the QuadKey of the tile which is exactly below the one we just got as a result, which is 0230102300203312
                // QuadKey (one tile below) to point: 0230102300203312 -> (37.5271536172338, -122.261352539062)
                // Visualize all three points on a map to see the problem. This tile is very close to the original point, but instead, the above one 
                // is computed, although it's vertically off.
                TileSystem.QuadKeyToTileXY("0230102300203312", out tileX, out tileY, out lvl);
                TileSystem.TileXYToPixelXY(tileX, tileY, out pixelX, out pixelY);
                TileSystem.PixelXYToLatLong(pixelX, pixelY, lvl, out lat, out lon);
                Console.WriteLine(lat + ", " + lon);
            }
        }
    }

    EDIT: Is it possible that my assumption, that PixelXYToLatLon() puts out the center point of a tile is wrong, but instead, it returns the north-west corner?


    Thursday, December 13, 2018 8:17 PM

All replies

  • Hi Ferdinand,

    Here are the two sample routines you are discussing:

            /// <summary>
            /// Converts pixel XY coordinates into tile XY coordinates of the tile containing
            /// the specified pixel.
            /// </summary>
            /// <param name="pixelX">Pixel X coordinate.</param>
            /// <param name="pixelY">Pixel Y coordinate.</param>
            /// <param name="tileX">Output parameter receiving the tile X coordinate.</param>
            /// <param name="tileY">Output parameter receiving the tile Y coordinate.</param>
            public static void PixelXYToTileXY(int pixelX, int pixelY, out int tileX, out int tileY)
            {
                tileX = pixelX / 256;
                tileY = pixelY / 256;
            }
    
            /// <summary>
            /// Converts tile XY coordinates into pixel XY coordinates of the upper-left pixel
            /// of the specified tile.
            /// </summary>
            /// <param name="tileX">Tile X coordinate.</param>
            /// <param name="tileY">Tile Y coordinate.</param>
            /// <param name="pixelX">Output parameter receiving the pixel X coordinate.</param>
            /// <param name="pixelY">Output parameter receiving the pixel Y coordinate.</param>
            public static void TileXYToPixelXY(int tileX, int tileY, out int pixelX, out int pixelY)
            {
                pixelX = tileX * 256;
                pixelY = tileY * 256;
            }

    The Pixel version will return a lat long for the specific pixel on the tile you give it while the tile version will return the corner as you suggest. (https://msdn.microsoft.com/en-us/library/bb259689.aspx)

    Sincerely,

    IoTGirl

    Sunday, December 16, 2018 4:58 PM
    Owner
  • The PixelXY To LatLon function is relative to the top left corner (all tile calculations are). 
    • Proposed as answer by Ricky_Brundritt Saturday, December 29, 2018 12:29 AM
    Saturday, December 29, 2018 12:29 AM