Add working ability to get stadia tiles directly
This commit is contained in:
parent
163b0f9edc
commit
d03c12ffb6
9 changed files with 149 additions and 11 deletions
|
|
@ -37,7 +37,7 @@ func (s *StadiaMaps) BulkGeocode(requests []BulkGeocodeQuery) ([]BulkGeocodeResp
|
|||
resp, err := s.client.R().
|
||||
SetBody(body).
|
||||
SetContentType("application/json").
|
||||
SetPathParam("urlBase", s.urlBase).
|
||||
SetPathParam("urlBase", s.urlBaseApi).
|
||||
SetQueryParam("api_key", s.APIKey).
|
||||
SetError(&api_error).
|
||||
SetResult(&results).
|
||||
|
|
|
|||
55
stadia/cmd/tile-raster/main.go
Normal file
55
stadia/cmd/tile-raster/main.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/Gleipnir-Technology/nidus-sync/stadia"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Define command-line flags
|
||||
lat := flag.Float64("lat", 0, "The latitude of the tile")
|
||||
lng := flag.Float64("lng", 0, "The longitude of the tile")
|
||||
zoom := flag.Uint("zoom", 16, "The zoom level")
|
||||
|
||||
// Parse the flags
|
||||
flag.Parse()
|
||||
|
||||
if *lat == 0 {
|
||||
log.Println("Error: you must specify -lat")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
if *lng == 0 {
|
||||
log.Println("Error: you must specify -lng")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
key := os.Getenv("STADIA_MAPS_API_KEY")
|
||||
if key == "" {
|
||||
log.Println("STADIA_MAPS_API_KEY is empty")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
client := stadia.NewStadiaMaps(key)
|
||||
ctx := context.Background()
|
||||
req := stadia.RequestTileRaster{
|
||||
Latitude: *lat,
|
||||
Longitude: *lng,
|
||||
Zoom: *zoom,
|
||||
}
|
||||
data, err := client.TileRaster(ctx, req)
|
||||
if err != nil {
|
||||
log.Printf("err: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
err = os.WriteFile("tile.raw", data, 0666)
|
||||
if err != nil {
|
||||
log.Printf("err: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
log.Printf("wrote tile.raw")
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ func (s *StadiaMaps) GeocodeAutocomplete(ctx context.Context, req RequestGeocode
|
|||
SetQueryParamsFromValues(query).
|
||||
SetContext(ctx).
|
||||
SetResult(&result).
|
||||
SetPathParam("urlBase", s.urlBase).
|
||||
SetPathParam("urlBase", s.urlBaseApi).
|
||||
SetQueryParam("api_key", s.APIKey).
|
||||
Get("https://{urlBase}/geocoding/v2/autocomplete")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func (s *StadiaMaps) GeocodeByGID(ctx context.Context, req RequestGeocodeByGID)
|
|||
SetQueryParamsFromValues(query).
|
||||
SetContext(ctx).
|
||||
SetResult(&result).
|
||||
SetPathParam("urlBase", s.urlBase).
|
||||
SetPathParam("urlBase", s.urlBaseApi).
|
||||
SetQueryParam("api_key", s.APIKey).
|
||||
Get("https://{urlBase}/geocoding/v2/place_details")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func (s *StadiaMaps) GeocodeRaw(ctx context.Context, req RequestGeocodeRaw) (*Ge
|
|||
SetQueryParamsFromValues(query).
|
||||
SetContext(ctx).
|
||||
SetResult(&result).
|
||||
SetPathParam("urlBase", s.urlBase).
|
||||
SetPathParam("urlBase", s.urlBaseApi).
|
||||
SetQueryParam("api_key", s.APIKey).
|
||||
Get("https://{urlBase}/geocoding/v1/search")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func (s *StadiaMaps) GeocodeStructured(ctx context.Context, req RequestGeocodeSt
|
|||
SetQueryParamsFromValues(query).
|
||||
SetContext(ctx).
|
||||
SetResult(&result).
|
||||
SetPathParam("urlBase", s.urlBase).
|
||||
SetPathParam("urlBase", s.urlBaseApi).
|
||||
SetQueryParam("api_key", s.APIKey).
|
||||
Get("https://{urlBase}/geocoding/v1/search/structured")
|
||||
if err != nil {
|
||||
|
|
|
|||
81
stadia/map_tile_raster.go
Normal file
81
stadia/map_tile_raster.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package stadia
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type RequestTileRaster struct {
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
//Style string
|
||||
Zoom uint
|
||||
}
|
||||
|
||||
func (s *StadiaMaps) TileRaster(ctx context.Context, req RequestTileRaster) ([]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"
|
||||
|
||||
y, x := LatLngToTile(req.Zoom, req.Latitude, req.Longitude)
|
||||
//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(req.Zoom))).
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ func (s *StadiaMaps) ReverseGeocode(ctx context.Context, req RequestReverseGeoco
|
|||
SetQueryParamsFromValues(query).
|
||||
SetContext(ctx).
|
||||
SetResult(&result).
|
||||
SetPathParam("urlBase", s.urlBase).
|
||||
SetPathParam("urlBase", s.urlBaseApi).
|
||||
SetQueryParam("api_key", s.APIKey).
|
||||
Get("https://{urlBase}/geocoding/v2/reverse")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ import (
|
|||
type StadiaMaps struct {
|
||||
APIKey string
|
||||
|
||||
client *resty.Client
|
||||
urlBase string
|
||||
client *resty.Client
|
||||
urlBaseApi string
|
||||
urlBaseTiles string
|
||||
}
|
||||
|
||||
func NewStadiaMaps(api_key string) *StadiaMaps {
|
||||
|
|
@ -26,9 +27,10 @@ func NewStadiaMaps(api_key string) *StadiaMaps {
|
|||
})
|
||||
}
|
||||
return &StadiaMaps{
|
||||
APIKey: api_key,
|
||||
client: r,
|
||||
urlBase: "api.stadiamaps.com",
|
||||
APIKey: api_key,
|
||||
client: r,
|
||||
urlBaseApi: "api.stadiamaps.com",
|
||||
urlBaseTiles: "tiles.stadiamaps.com",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue