Data acquisition

To acquire elevation data for terrain mesh generation, we utilize cURL in conjunction with the provided API key to query the Mapbox Terrain-RGB v1 API. The URL structure used to request this data is as follows:


URL structure for requesting elevation data from Mapbox Terrain-RGB API
"https://api.mapbox.com/v4/mapbox.terrain-rgb/" + std::to_string(zoom) + "/" +
std::to_string(x) + "/" + std::to_string(y) + ".png?access_token=" + api_key;

Explanation of URL components:

  1. Base URL: "https://api.mapbox.com/v4/mapbox.terrain-rgb/" This base URL specifies the Mapbox service and dataset (terrain-rgb) used to retrieve elevation data. It forms the foundation of the request.

  2. Zoom level: std::to_string(zoom) The zoom level determines the detail of the map tile requested. Higher zoom levels provide more detailed data for smaller geographic areas.

  3. Tile coordinates: std::to_string(x) and std::to_string(y) These represent the x and y coordinates of the map tile, corresponding to the specified latitude and longitude. Together with the zoom level, they identify the exact tile to be retrieved.

  4. Image format: ".png" The data is requested in PNG format, which is used by Mapbox to encode elevation data into RGB values.

  5. API key: "access_token=" + api_key The API key is appended to the URL to authenticate the request with the Mapbox API, enabling access to the required data.

Reading and decoding elevation data

Once the correct tile is downloaded, the elevation data is extracted from the PNG image returned by the Mapbox Terrain-RGB v1 API. The following C++ code demonstrates how to read the PNG data using the libpng library:


Function to read PNG data using libpng
std::vector<std::vector<std::tuple<int, int, int>>> readPNG(const std::vector<char> &data)
{
    std::vector<std::vector<std::tuple<int, int, int>>> image;
    png_image image_struct;
    memset(&image_struct, 0, (sizeof image_struct));
    image_struct.version = PNG_IMAGE_VERSION;
    if (png_image_begin_read_from_memory(&image_struct, data.data(), data.size()))
    {
        png_bytep buffer;
        image_struct.format = PNG_FORMAT_RGB;
        buffer = (png_bytep)malloc(PNG_IMAGE_SIZE(image_struct));
        if (buffer != NULL)
        {
            if (png_image_finish_read(&image_struct, NULL, buffer, 0, NULL))
            {
                for (unsigned y = 0; y < image_struct.height; ++y)
                {
                    std::vector<std::tuple<int, int, int>> row;
                    for (unsigned x = 0; x < image_struct.width; ++x)
                    {
                        int r = buffer[3 * (y * image_struct.width + x) + 0];
                        int g = buffer[3 * (y * image_struct.width + x) + 1];
                        int b = buffer[3 * (y * image_struct.width + x) + 2];
                        row.emplace_back(r, g, b);
                    }
                    image.push_back(row);
                }
            }
            free(buffer);
        }
    }
    return image;
}

This function reads the PNG image from memory, parses the RGB values for each pixel, and stores them in a 2D vector of tuples. Each tuple corresponds to a pixel and contains the red, green, and blue color values.

Decoding elevation values

To convert these RGB values into actual elevation data, the decodeElevation function is used:


Function to decode elevation from RGB values
double decodeElevation(int r, int g, int b)
{
    return -10000 + (r * 256 * 256 + g * 256 + b) * 0.1;
}

The decodeElevation function decodes the RGB values into a single elevation value. Mapbox encodes elevation data in the RGB channels, where:

  • Red (r) represents the most significant part of the value.

  • Green (g) represents the middle part.

  • Blue (b) represents the least significant part.

The formula combines these three components into a single value and applies a scale factor of 0.1 to achieve the actual elevation in meters. The result is an accurate representation of the elevation for each pixel in the map tile.

By integrating these functions, the program can efficiently retrieve and decode elevation data from Mapbox, providing detailed topographical information for any specified location.



References