mirror of
https://github.com/consbio/mbtileserver.git
synced 2024-09-11 07:15:24 +03:00
72 lines
2.1 KiB
Go
72 lines
2.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
|
|
const (
|
|
earthRadius = 6378137.0
|
|
earthCircumference = math.Pi * earthRadius
|
|
initialResolution = 2 * earthCircumference / 256
|
|
dpi uint8 = 96
|
|
)
|
|
|
|
type tileCoord struct {
|
|
z uint8
|
|
x, y uint64
|
|
}
|
|
|
|
// tileCoordFromString parses and returns tileCoord coordinates and an optional
|
|
// extension from the three parameters. The parameter z is interpreted as the
|
|
// web mercator zoom level, it is supposed to be an unsigned integer that will
|
|
// fit into 8 bit. The parameters x and y are interpreted as longitude and
|
|
// latitude tile indices for that zoom level, both are supposed be integers in
|
|
// the integer interval [0,2^z). Additionally, y may also have an optional
|
|
// filename extension (e.g. "42.png") which is removed before parsing the
|
|
// number, and returned, too. In case an error occurred during parsing or if the
|
|
// values are not in the expected interval, the returned error is non-nil.
|
|
func tileCoordFromString(z, x, y string) (tc tileCoord, ext string, err error) {
|
|
var z64 uint64
|
|
if z64, err = strconv.ParseUint(z, 10, 8); err != nil {
|
|
err = fmt.Errorf("cannot parse zoom level: %v", err)
|
|
return
|
|
}
|
|
tc.z = uint8(z64)
|
|
const (
|
|
errMsgParse = "cannot parse %s coordinate axis: %v"
|
|
errMsgOOB = "%s coordinate (%d) is out of bounds for zoom level %d"
|
|
)
|
|
if tc.x, err = strconv.ParseUint(x, 10, 64); err != nil {
|
|
err = fmt.Errorf(errMsgParse, "first", err)
|
|
return
|
|
}
|
|
if tc.x >= (1 << z64) {
|
|
err = fmt.Errorf(errMsgOOB, "x", tc.x, tc.z)
|
|
return
|
|
}
|
|
s := y
|
|
if l := strings.LastIndex(s, "."); l >= 0 {
|
|
s, ext = s[:l], s[l:]
|
|
}
|
|
if tc.y, err = strconv.ParseUint(s, 10, 64); err != nil {
|
|
err = fmt.Errorf(errMsgParse, "y", err)
|
|
return
|
|
}
|
|
if tc.y >= (1 << z64) {
|
|
err = fmt.Errorf(errMsgOOB, "y", tc.y, tc.z)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func calcScaleResolution(zoomLevel uint8, dpi uint8) (float64, float64) {
|
|
var denom = 1 << zoomLevel
|
|
resolution := initialResolution / float64(denom)
|
|
scale := float64(dpi) * 39.37 * resolution // 39.37 in/m
|
|
return scale, resolution
|
|
}
|