nidus-sync/stadia/map_tile_raster.go

85 lines
2.3 KiB
Go
Raw Permalink Normal View History

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
}