package stadia import ( "context" "fmt" "math" "strconv" "github.com/rs/zerolog/log" ) type RequestTileRasterLatLng struct { Latitude float64 Longitude float64 //Style string Zoom uint } func (s *StadiaMaps) TileRaster(ctx context.Context, z, y, x uint) ([]byte, error) { // https://docs.stadiamaps.com/raster/ //url := "https://{urlBase}/tiles/{style}/{z}/{x}/{y}{r}.png" //url := "https://{urlBase}/data/imagery/{z}/{x}/{y}{r}.png" url := "https://{urlBase}/tiles/alidade_satellite/{z}/{x}/{y}.jpg" //var api_error Error resp, err := s.client.R(). SetContext(ctx). //SetPathParam("style", req.Style). //SetPathParam("r", ""). SetPathParam("x", strconv.Itoa(int(x))). SetPathParam("y", strconv.Itoa(int(y))). SetPathParam("z", strconv.Itoa(int(z))). SetPathParam("urlBase", s.urlBaseTiles). SetQueryParam("api_key", s.APIKey). Get(url) if err != nil { return nil, fmt.Errorf("autocomplete get: %w", err) } if !resp.IsSuccess() { return nil, parseError(resp) } content_type := resp.Header().Get("Content-Type") log.Debug().Str("content_type", content_type).Send() return resp.Bytes(), nil } func (s *StadiaMaps) TileRasterLatLng(ctx context.Context, req RequestTileRasterLatLng) ([]byte, error) { y, x := LatLngToTile(req.Zoom, req.Latitude, req.Longitude) return s.TileRaster(ctx, req.Zoom, y, x) } // LatLngToTile converts GPS coordinates to ArcGIS tile coordinates func LatLngToTile(level uint, lat, lng float64) (row, column uint) { // Get number of tiles per dimension at this zoom level numTiles := math.Pow(2, float64(level)) // Convert longitude to tile column // Range: -180 to 180 degrees maps to 0 to numTiles column = uint(math.Floor((lng + 180.0) / 360.0 * numTiles)) // Convert latitude to tile row using Mercator projection // First convert lat to radians latRad := lat * math.Pi / 180.0 // Apply Mercator projection formula // This maps latitude from -85.0511 to 85.0511 degrees to 0 to numTiles mercatorY := 0.5 - math.Log(math.Tan(latRad)+1/math.Cos(latRad))/(2*math.Pi) row = uint(math.Floor(mercatorY * numTiles)) // Ensure values are within valid range if column < 0 { column = 0 } else if column >= uint(numTiles) { column = uint(numTiles) - 1 } if row < 0 { row = 0 } else if row >= uint(numTiles) { row = uint(numTiles) - 1 } return row, column }