mirror of
https://github.com/Luzifer/staticmap.git
synced 2025-01-20 19:41:56 +00:00
Update dependencies
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
3c73d0a08c
commit
1abd72dfdc
411 changed files with 85657 additions and 37863 deletions
155
Godeps/Godeps.json
generated
155
Godeps/Godeps.json
generated
|
@ -1,155 +0,0 @@
|
|||
{
|
||||
"ImportPath": "github.com/Luzifer/staticmap",
|
||||
"GoVersion": "go1.8",
|
||||
"GodepVersion": "v79",
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/Luzifer/go_helpers/accessLogger",
|
||||
"Comment": "v2.2.0",
|
||||
"Rev": "e31c3a2659d3f4901f696692cfe98bd0eb5168f9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/Luzifer/go_helpers/http",
|
||||
"Comment": "v2.2.0",
|
||||
"Rev": "e31c3a2659d3f4901f696692cfe98bd0eb5168f9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/Luzifer/rconfig",
|
||||
"Comment": "v1.2.0",
|
||||
"Rev": "7aef1d393c1e2d0758901853b59981c7adc67c7e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/Sirupsen/logrus",
|
||||
"Comment": "v0.10.0-38-g3ec0642",
|
||||
"Rev": "3ec0642a7fb6488f65b06f9040adc67e3990296a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/Wessie/appdirs",
|
||||
"Rev": "6573e894f8e294cbae0c4e45c25ff9f2e2918a4e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/didip/tollbooth",
|
||||
"Rev": "e11ced12e0e0bbfedbc1783fcf0a5ec7f9dc4856"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/didip/tollbooth/config",
|
||||
"Rev": "e11ced12e0e0bbfedbc1783fcf0a5ec7f9dc4856"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/didip/tollbooth/errors",
|
||||
"Rev": "e11ced12e0e0bbfedbc1783fcf0a5ec7f9dc4856"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/didip/tollbooth/libstring",
|
||||
"Rev": "e11ced12e0e0bbfedbc1783fcf0a5ec7f9dc4856"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/flopp/go-coordsparser",
|
||||
"Rev": "845bca739e263e1cd38de25024a47b4d6acbfc1f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/flopp/go-staticmaps",
|
||||
"Rev": "e8779c98399f6efad291d6504990daceeb9940a9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/fogleman/gg",
|
||||
"Comment": "v1.0.0-10-gee8994f",
|
||||
"Rev": "ee8994ff90057955c428a5a949da5d064bf3ce6b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/freetype/raster",
|
||||
"Comment": "release-131-g38b4c39",
|
||||
"Rev": "38b4c392adc5eed94207994c4848fff99f4ac234"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/freetype/truetype",
|
||||
"Comment": "release-131-g38b4c39",
|
||||
"Rev": "38b4c392adc5eed94207994c4848fff99f4ac234"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/geo/r1",
|
||||
"Rev": "f65fe014169924880aa2c95d7707c2da435534b9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/geo/r2",
|
||||
"Rev": "f65fe014169924880aa2c95d7707c2da435534b9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/geo/r3",
|
||||
"Rev": "f65fe014169924880aa2c95d7707c2da435534b9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/geo/s1",
|
||||
"Rev": "f65fe014169924880aa2c95d7707c2da435534b9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/geo/s2",
|
||||
"Rev": "f65fe014169924880aa2c95d7707c2da435534b9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/context",
|
||||
"Rev": "1c83b3eabd45b6d76072b66b746c20815fb2872d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/mux",
|
||||
"Rev": "49c024275504f0341e5a9971eb7ba7fa3dc7af40"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/lucasb-eyer/go-colorful",
|
||||
"Rev": "c900de9dbbc73129068f5af6a823068fc5f2308c"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/patrickmn/go-cache",
|
||||
"Comment": "v2.0.0-9-g7ac1518",
|
||||
"Rev": "7ac151875ffb48b9f3ccce9ea20f020b0c1596c8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "c7e63cf4530bcd3ba943729cee0efeff2ebea63f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/tkrajina/gpxgo/gpx",
|
||||
"Rev": "7848cf26f5a58b4a4e23b89a4b67cfc3d52dd042"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/image/draw",
|
||||
"Rev": "97680175a5267bb8b31f1923e7a66df98013b11a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/image/font",
|
||||
"Rev": "97680175a5267bb8b31f1923e7a66df98013b11a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/image/font/basicfont",
|
||||
"Rev": "97680175a5267bb8b31f1923e7a66df98013b11a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/image/math/f64",
|
||||
"Rev": "97680175a5267bb8b31f1923e7a66df98013b11a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/image/math/fixed",
|
||||
"Rev": "97680175a5267bb8b31f1923e7a66df98013b11a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/context",
|
||||
"Rev": "dfe83d419c9403b40b19d08cdba2afec27b002f7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/sys/unix",
|
||||
"Rev": "8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/time/rate",
|
||||
"Rev": "8be79e1e0910c292df4e79c241bb7e8f7e725959"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/validator.v2",
|
||||
"Rev": "07ffaad256c8e957050ad83d6472eb97d785013d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/yaml.v2",
|
||||
"Rev": "31c299268d302dd0aa9a0dcf765a3d58971ac83f"
|
||||
}
|
||||
]
|
||||
}
|
5
Godeps/Readme
generated
5
Godeps/Readme
generated
|
@ -1,5 +0,0 @@
|
|||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
81
Gopkg.lock
generated
81
Gopkg.lock
generated
|
@ -1,14 +1,21 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Luzifer/go-staticmaps"
|
||||
packages = ["."]
|
||||
revision = "5f69ec7945b506b1d33edd717e84e479818e2365"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Luzifer/go_helpers"
|
||||
packages = [
|
||||
"accessLogger",
|
||||
"http"
|
||||
"http",
|
||||
"str"
|
||||
]
|
||||
revision = "e31c3a2659d3f4901f696692cfe98bd0eb5168f9"
|
||||
version = "v2.2.0"
|
||||
revision = "8fdddb7041fe962e750caa553a0714f94e261c4a"
|
||||
version = "v2.3.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Luzifer/rconfig"
|
||||
|
@ -19,7 +26,8 @@
|
|||
[[projects]]
|
||||
name = "github.com/Sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "3ec0642a7fb6488f65b06f9040adc67e3990296a"
|
||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||
version = "v1.0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -31,11 +39,12 @@
|
|||
name = "github.com/didip/tollbooth"
|
||||
packages = [
|
||||
".",
|
||||
"config",
|
||||
"errors",
|
||||
"libstring"
|
||||
"libstring",
|
||||
"limiter"
|
||||
]
|
||||
revision = "e11ced12e0e0bbfedbc1783fcf0a5ec7f9dc4856"
|
||||
revision = "c95eaa3ddc98f635a91e218b48727fb2e06613ea"
|
||||
version = "v4.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -43,25 +52,23 @@
|
|||
packages = ["."]
|
||||
revision = "845bca739e263e1cd38de25024a47b4d6acbfc1f"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/flopp/go-staticmaps"
|
||||
packages = ["."]
|
||||
revision = "e8779c98399f6efad291d6504990daceeb9940a9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fogleman/gg"
|
||||
packages = ["."]
|
||||
revision = "ee8994ff90057955c428a5a949da5d064bf3ce6b"
|
||||
revision = "6166aa3c1afaee416f384645a81636267aee6d25"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/freetype"
|
||||
packages = [
|
||||
"raster",
|
||||
"truetype"
|
||||
]
|
||||
revision = "38b4c392adc5eed94207994c4848fff99f4ac234"
|
||||
revision = "e2365dfdc4a05e4b8299a783240d4a7d5a65d4e4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/geo"
|
||||
packages = [
|
||||
"r1",
|
||||
|
@ -70,22 +77,25 @@
|
|||
"s1",
|
||||
"s2"
|
||||
]
|
||||
revision = "f65fe014169924880aa2c95d7707c2da435534b9"
|
||||
revision = "fb250ae94fbe10f86b4f1a9b70a19925da3410b9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/context"
|
||||
packages = ["."]
|
||||
revision = "1c83b3eabd45b6d76072b66b746c20815fb2872d"
|
||||
revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
|
||||
version = "v1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/mux"
|
||||
packages = ["."]
|
||||
revision = "49c024275504f0341e5a9971eb7ba7fa3dc7af40"
|
||||
revision = "53c1911da2b537f792e7cafcb446b05ffe33b996"
|
||||
version = "v1.6.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/lucasb-eyer/go-colorful"
|
||||
packages = ["."]
|
||||
revision = "c900de9dbbc73129068f5af6a823068fc5f2308c"
|
||||
revision = "231272389856c976b7500c4fffcc52ddf06ff4eb"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/patrickmn/go-cache"
|
||||
|
@ -95,7 +105,8 @@
|
|||
[[projects]]
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
revision = "c7e63cf4530bcd3ba943729cee0efeff2ebea63f"
|
||||
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -104,45 +115,57 @@
|
|||
revision = "7848cf26f5a58b4a4e23b89a4b67cfc3d52dd042"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "b2aa35443fbc700ab74c586ae79b81c171851023"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/image"
|
||||
packages = [
|
||||
"draw",
|
||||
"font",
|
||||
"font/basicfont",
|
||||
"font/plan9font",
|
||||
"math/f64",
|
||||
"math/fixed"
|
||||
]
|
||||
revision = "97680175a5267bb8b31f1923e7a66df98013b11a"
|
||||
revision = "f315e440302883054d0c2bd85486878cb4f8572c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context"]
|
||||
revision = "dfe83d419c9403b40b19d08cdba2afec27b002f7"
|
||||
revision = "b68f30494add4df6bd8ef5e82803f308e7f7c59c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "378d26f46672a356c46195c28f61bdb4c0a781dd"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/time"
|
||||
packages = ["rate"]
|
||||
revision = "8be79e1e0910c292df4e79c241bb7e8f7e725959"
|
||||
revision = "711ca1cb87636abec28122ef3bc6a77269d433f3"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/validator.v2"
|
||||
packages = ["."]
|
||||
revision = "07ffaad256c8e957050ad83d6472eb97d785013d"
|
||||
revision = "59c90c7046f643cbe0d4e7c8776c42a84ce75910"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "31c299268d302dd0aa9a0dcf765a3d58971ac83f"
|
||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||
version = "v2.2.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "3d56f50ffce992752c5b104c169174827eb4cb480ed07f718d3ce4f84bd1244e"
|
||||
inputs-digest = "7c8497a8311887c02aced01ebdf91a73dc82b48920f8f9ebd5ad643204043ce2"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
30
Gopkg.toml
30
Gopkg.toml
|
@ -25,14 +25,42 @@
|
|||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/Luzifer/go-staticmaps"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Luzifer/go_helpers"
|
||||
version = "2.2.0"
|
||||
version = "2.3.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Luzifer/rconfig"
|
||||
version = "1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Sirupsen/logrus"
|
||||
version = "1.0.5"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/didip/tollbooth"
|
||||
version = "4.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/fogleman/gg"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/geo"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/mux"
|
||||
version = "1.6.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/lucasb-eyer/go-colorful"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
|
9
main.go
9
main.go
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/Luzifer/rconfig"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/didip/tollbooth"
|
||||
"github.com/didip/tollbooth/limiter"
|
||||
"github.com/golang/geo/s2"
|
||||
"github.com/gorilla/mux"
|
||||
colorful "github.com/lucasb-eyer/go-colorful"
|
||||
|
@ -24,7 +25,7 @@ var (
|
|||
ForceCache time.Duration `flag:"force-cache" default:"24h" env:"FORCE_CACHE" description:"Force map to be cached for this duration"`
|
||||
Listen string `flag:"listen" default:":3000" description:"IP/Port to listen on"`
|
||||
MaxSize string `flag:"max-size" default:"1024x1024" env:"MAX_SIZE" description:"Maximum map size requestable"`
|
||||
RateLimit int64 `flag:"rate-limit" default:"1" env:"RATE_LIMIT" description:"How many requests to allow per time"`
|
||||
RateLimit float64 `flag:"rate-limit" default:"1" env:"RATE_LIMIT" description:"How many requests to allow per time"`
|
||||
RateLimitTime time.Duration `flag:"rate-limit-time" default:"1s" env:"RATE_LIMIT_TIME" description:"Time interval to allow N requests in"`
|
||||
VersionAndExit bool `flag:"version" default:"false" description:"Print version information and exit"`
|
||||
}
|
||||
|
@ -51,8 +52,10 @@ func init() {
|
|||
}
|
||||
|
||||
func main() {
|
||||
rateLimit := tollbooth.NewLimiter(cfg.RateLimit, cfg.RateLimitTime)
|
||||
rateLimit.IPLookups = []string{"X-Forwarded-For", "RemoteAddr", "X-Real-IP"}
|
||||
rateLimit := tollbooth.NewLimiter(cfg.RateLimit, &limiter.ExpirableOptions{
|
||||
DefaultExpirationTTL: cfg.RateLimitTime,
|
||||
})
|
||||
rateLimit.SetIPLookups([]string{"X-Forwarded-For", "RemoteAddr", "X-Real-IP"})
|
||||
|
||||
r := mux.NewRouter()
|
||||
r.HandleFunc("/status", func(res http.ResponseWriter, r *http.Request) { http.Error(res, "I'm fine", http.StatusOK) })
|
||||
|
|
6
map.go
6
map.go
|
@ -6,7 +6,7 @@ import (
|
|||
"image/color"
|
||||
"io"
|
||||
|
||||
staticMap "github.com/flopp/go-staticmaps"
|
||||
staticMap "github.com/Luzifer/go-staticmaps"
|
||||
"github.com/fogleman/gg"
|
||||
"github.com/golang/geo/s2"
|
||||
)
|
||||
|
@ -45,6 +45,8 @@ func (m marker) String() string {
|
|||
|
||||
func generateMap(center s2.LatLng, zoom int, marker []marker, x, y int) (io.Reader, error) {
|
||||
ctx := staticMap.NewContext()
|
||||
ctx.SetUserAgent(fmt.Sprintf("Mozilla/5.0+(compatible; staticmap/%s; https://github.com/Luzifer/staticmap)", version))
|
||||
|
||||
ctx.SetSize(x, y)
|
||||
ctx.SetCenter(center)
|
||||
ctx.SetZoom(zoom)
|
||||
|
@ -55,8 +57,6 @@ func generateMap(center s2.LatLng, zoom int, marker []marker, x, y int) (io.Read
|
|||
}
|
||||
}
|
||||
|
||||
staticMap.TileFetcherUserAgent = fmt.Sprintf("Mozilla/5.0+(compatible; staticmap/%s; https://github.com/Luzifer/staticmap)", version)
|
||||
|
||||
img, err := ctx.Render()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
36
vendor/github.com/Luzifer/go-staticmaps/.travis.yml
generated
vendored
Normal file
36
vendor/github.com/Luzifer/go-staticmaps/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.9
|
||||
- master
|
||||
|
||||
install:
|
||||
- go get -t ./...
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: master
|
||||
# Don't wait for tip tests to finish. Mark the test run green if the
|
||||
# tests pass on the stable versions of Go.
|
||||
fast_finish: true
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
# Anything in before_script that returns a nonzero exit code will
|
||||
# flunk the build and immediately stop. It's sorta like having
|
||||
# set -e enabled in bash.
|
||||
before_script:
|
||||
- GO_FILES=$(find . -iname '*.go' -type f) # All the .go files
|
||||
- go get github.com/golang/lint/golint # Linter
|
||||
- go get honnef.co/go/tools/cmd/megacheck # Badass static analyzer/linter
|
||||
- go get github.com/fzipp/gocyclo
|
||||
|
||||
# script always run to completion (set +e). All of these code checks are must haves
|
||||
# in a modern Go project.
|
||||
script:
|
||||
- test -z $(gofmt -s -l $GO_FILES) # Fail if a .go file hasn't been formatted with gofmt
|
||||
- go vet ./... # go vet is the official Go static analyzer
|
||||
- megacheck ./... # "go vet on steroids" + linter
|
||||
- gocyclo -over 19 $GO_FILES # forbid code with huge functions
|
||||
- golint -set_exit_status $(go list ./...) # one last linter
|
|
@ -1,5 +1,6 @@
|
|||
[![GoDoc](https://godoc.org/github.com/flopp/go-staticmaps?status.svg)](https://godoc.org/github.com/flopp/go-staticmaps)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/flopp/go-staticmaps)](https://goreportcard.com/report/flopp/go-staticmaps)
|
||||
[![Build Status](https://travis-ci.org/flopp/go-staticmaps.svg?branch=master)](https://travis-ci.org/flopp/go-staticmaps)
|
||||
[![License MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](https://github.com/flopp/go-staticmaps/)
|
||||
|
||||
# go-staticmaps
|
||||
|
@ -80,9 +81,13 @@ See [GoDoc](https://godoc.org/github.com/flopp/go-staticmaps) for a complete doc
|
|||
Set the bounding box (NW_LATLNG = north-western point of the
|
||||
bounding box, SW_LATLNG = southe-western point of the bounding
|
||||
box)
|
||||
--background=COLOR Background color (default: transparent)
|
||||
-u, --useragent=USERAGENT
|
||||
Overwrite the default HTTP user agent string
|
||||
-m, --marker=MARKER Add a marker to the static map
|
||||
-p, --path=PATH Add a path to the static map
|
||||
-a, --area=AREA Add an area to the static map
|
||||
-C, --circle=CIRCLE Add a circle to the static map
|
||||
|
||||
Help Options:
|
||||
-h, --help Show this help message
|
||||
|
@ -91,6 +96,8 @@ See [GoDoc](https://godoc.org/github.com/flopp/go-staticmaps) for a complete doc
|
|||
The command line interface tries to resemble [Google's Static Maps API](https://developers.google.com/maps/documentation/static-maps/intro).
|
||||
If neither `--bbox`, `--center`, nor `--zoom` are given, the map extent is determined from the specified markers, paths and areas.
|
||||
|
||||
`--background` lets you specify a color used for map areas that are not covered by map tiles (areas north of 85°/south of -85°).
|
||||
|
||||
### Markers
|
||||
The `--marker` option defines one or more map markers of the same style. Use multiple `--marker` options to add markers of different styles.
|
||||
|
||||
|
@ -132,6 +139,21 @@ The `--area` option defines a closed area on the map. Use multiple `--area` opti
|
|||
- `fill:COLOR` - where `COLOR` is either of the form `0xRRGGBB`, `0xRRGGBBAA`, or one of `black`, `blue`, `brown`, `green`, `orange`, `purple`, `red`, `yellow`, `white` (default: none)
|
||||
|
||||
|
||||
### Circles
|
||||
The `--circles` option defines one or more circles of the same style. Use multiple `--circle` options to add circles of different styles.
|
||||
|
||||
--circle CIRCLE_STYLES|LATLNG|LATLNG|...
|
||||
|
||||
`LATLNG` is a comma separated pair of latitude and longitude, e.g. `52.5153,13.3564`.
|
||||
|
||||
`CIRCLE_STYLES` consists of a set of style descriptors separated by the pipe character `|`:
|
||||
|
||||
- `color:COLOR` - where `COLOR` is either of the form `0xRRGGBB`, `0xRRGGBBAA`, or one of `black`, `blue`, `brown`, `green`, `orange`, `purple`, `red`, `yellow`, `white` (default: `red`)
|
||||
- `fill:COLOR` - where `COLOR` is either of the form `0xRRGGBB`, `0xRRGGBBAA`, or one of `black`, `blue`, `brown`, `green`, `orange`, `purple`, `red`, `yellow`, `white` (default: no fill color)
|
||||
- `radius:RADIUS` - where `RADIUS` is te circle radius in meters (default: `100.0`)
|
||||
- `weight:WEIGHT` - where `WEIGHT` is the line width in pixels (defaut: `5`)
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Maps
|
||||
|
@ -217,7 +239,9 @@ Besides the go standard library, go-staticmaps uses
|
|||
- [bcicen](https://github.com/bcicen): reported and fixed *syntax error in examples*
|
||||
- [pshevtsov](https://github.com/pshevtsov): fixed *drawing of empty attribution strings*
|
||||
- [Luzifer](https://github.com/Luzifer): added *overwritable user agent strings* to comply with the OSM tile usage policy
|
||||
|
||||
- [Jason Fox](https://github.com/jasonpfox): added `RenderWithBounds` function
|
||||
- [Alexander A. Kapralov](https://github.com/alnkapa): initial *circles* implementation
|
||||
- [tsukumaru](https://github.com/tsukumaru): added `NewArea` and `NewPath` functions
|
||||
|
||||
## License
|
||||
Copyright 2016, 2017 Florian Pigorsch & Contributors. All rights reserved.
|
|
@ -24,6 +24,17 @@ type Area struct {
|
|||
Weight float64
|
||||
}
|
||||
|
||||
// NewArea creates a new Area
|
||||
func NewArea(positions []s2.LatLng, col color.Color, fill color.Color, weight float64) *Area {
|
||||
a := new(Area)
|
||||
a.Positions = positions
|
||||
a.Color = col
|
||||
a.Fill = fill
|
||||
a.Weight = weight
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// ParseAreaString parses a string and returns an area
|
||||
func ParseAreaString(s string) (*Area, error) {
|
||||
area := new(Area)
|
||||
|
@ -57,7 +68,6 @@ func ParseAreaString(s string) (*Area, error) {
|
|||
}
|
||||
area.Positions = append(area.Positions, s2.LatLngFromDegrees(lat, lng))
|
||||
}
|
||||
|
||||
}
|
||||
return area, nil
|
||||
}
|
128
vendor/github.com/Luzifer/go-staticmaps/circle.go
generated
vendored
Normal file
128
vendor/github.com/Luzifer/go-staticmaps/circle.go
generated
vendored
Normal file
|
@ -0,0 +1,128 @@
|
|||
package sm
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/flopp/go-coordsparser"
|
||||
"github.com/fogleman/gg"
|
||||
"github.com/golang/geo/s1"
|
||||
"github.com/golang/geo/s2"
|
||||
)
|
||||
|
||||
// Circle represents a circle on the map
|
||||
type Circle struct {
|
||||
MapObject
|
||||
Position s2.LatLng
|
||||
Color color.Color
|
||||
Fill color.Color
|
||||
Weight float64
|
||||
Radius float64 // in m.
|
||||
}
|
||||
|
||||
// NewCircle creates a new circle
|
||||
func NewCircle(pos s2.LatLng, col, fill color.Color, radius, weight float64) *Circle {
|
||||
return &Circle{
|
||||
Position: pos,
|
||||
Color: col,
|
||||
Fill: fill,
|
||||
Weight: weight,
|
||||
Radius: radius,
|
||||
}
|
||||
}
|
||||
|
||||
// ParseCircleString parses a string and returns an array of circles
|
||||
func ParseCircleString(s string) (circles []*Circle, err error) {
|
||||
circles = make([]*Circle, 0, 0)
|
||||
|
||||
var col color.Color = color.RGBA{0xff, 0, 0, 0xff}
|
||||
var fill color.Color = color.Transparent
|
||||
radius := 100.0
|
||||
weight := 5.0
|
||||
|
||||
for _, ss := range strings.Split(s, "|") {
|
||||
if ok, suffix := hasPrefix(ss, "color:"); ok {
|
||||
col, err = ParseColorString(suffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if ok, suffix := hasPrefix(ss, "fill:"); ok {
|
||||
fill, err = ParseColorString(suffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if ok, suffix := hasPrefix(ss, "radius:"); ok {
|
||||
if radius, err = strconv.ParseFloat(suffix, 64); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if ok, suffix := hasPrefix(ss, "weight:"); ok {
|
||||
if weight, err = strconv.ParseFloat(suffix, 64); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
lat, lng, err := coordsparser.Parse(ss)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := NewCircle(s2.LatLngFromDegrees(lat, lng), col, fill, radius, weight)
|
||||
circles = append(circles, c)
|
||||
}
|
||||
}
|
||||
return circles, nil
|
||||
}
|
||||
|
||||
func (m *Circle) getLatLng(plus bool) s2.LatLng {
|
||||
const (
|
||||
R = 6371000.0
|
||||
)
|
||||
th := m.Radius / R
|
||||
br := 0 / float64(s1.Degree)
|
||||
if !plus {
|
||||
th *= -1
|
||||
}
|
||||
lat := m.Position.Lat.Radians()
|
||||
lat1 := math.Asin(math.Sin(lat)*math.Cos(th) + math.Cos(lat)*math.Sin(th)*math.Cos(br))
|
||||
lng1 := m.Position.Lng.Radians() +
|
||||
math.Atan2(math.Sin(br)*math.Sin(th)*math.Cos(lat),
|
||||
math.Cos(th)-math.Sin(lat)*math.Sin(lat1))
|
||||
return s2.LatLng{
|
||||
Lat: s1.Angle(lat1),
|
||||
Lng: s1.Angle(lng1),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Circle) extraMarginPixels() float64 {
|
||||
return 0.5 * m.Weight
|
||||
}
|
||||
|
||||
func (m *Circle) bounds() s2.Rect {
|
||||
r := s2.EmptyRect()
|
||||
r = r.AddPoint(m.getLatLng(false))
|
||||
r = r.AddPoint(m.getLatLng(true))
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *Circle) draw(gc *gg.Context, trans *transformer) {
|
||||
if !CanDisplay(m.Position) {
|
||||
log.Printf("Circle coordinates not displayable: %f/%f", m.Position.Lat.Degrees(), m.Position.Lng.Degrees())
|
||||
return
|
||||
}
|
||||
|
||||
ll := m.getLatLng(true)
|
||||
x, y := trans.ll2p(m.Position)
|
||||
x1, y1 := trans.ll2p(ll)
|
||||
radius := math.Sqrt(math.Pow(x1-x, 2) + math.Pow(y1-y, 2))
|
||||
gc.ClearPath()
|
||||
gc.SetLineWidth(m.Weight)
|
||||
gc.SetLineCap(gg.LineCapRound)
|
||||
gc.SetLineJoin(gg.LineJoinRound)
|
||||
gc.DrawCircle(x, y, radius)
|
||||
gc.SetColor(m.Fill)
|
||||
gc.FillPreserve()
|
||||
gc.SetColor(m.Color)
|
||||
gc.Stroke()
|
||||
}
|
|
@ -54,6 +54,8 @@ func ParseColorString(s string) (color.Color, error) {
|
|||
return color.RGBA{0xff, 0xff, 0x00, 0xff}, nil
|
||||
case "white":
|
||||
return color.RGBA{0xff, 0xff, 0xff, 0xff}, nil
|
||||
case "transparent":
|
||||
return color.RGBA{0x00, 0x00, 0x00, 0x00}, nil
|
||||
}
|
||||
return color.Transparent, fmt.Errorf("Cannot parse color string: %s", s)
|
||||
}
|
|
@ -9,6 +9,7 @@ package sm
|
|||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"log"
|
||||
"math"
|
||||
|
@ -31,10 +32,15 @@ type Context struct {
|
|||
hasBoundingBox bool
|
||||
boundingBox s2.Rect
|
||||
|
||||
markers []*Marker
|
||||
paths []*Path
|
||||
areas []*Area
|
||||
background color.Color
|
||||
|
||||
markers []*Marker
|
||||
paths []*Path
|
||||
areas []*Area
|
||||
circles []*Circle
|
||||
overlays []*TileProvider
|
||||
|
||||
userAgent string
|
||||
tileProvider *TileProvider
|
||||
}
|
||||
|
||||
|
@ -46,6 +52,8 @@ func NewContext() *Context {
|
|||
t.hasZoom = false
|
||||
t.hasCenter = false
|
||||
t.hasBoundingBox = false
|
||||
t.background = nil
|
||||
t.userAgent = ""
|
||||
t.tileProvider = NewTileProviderOpenStreetMaps()
|
||||
return t
|
||||
}
|
||||
|
@ -55,6 +63,11 @@ func (m *Context) SetTileProvider(t *TileProvider) {
|
|||
m.tileProvider = t
|
||||
}
|
||||
|
||||
// SetUserAgent sets the HTTP user agent string used when downloading map tiles
|
||||
func (m *Context) SetUserAgent(a string) {
|
||||
m.userAgent = a
|
||||
}
|
||||
|
||||
// SetSize sets the size of the generated image
|
||||
func (m *Context) SetSize(width, height int) {
|
||||
m.width = width
|
||||
|
@ -79,6 +92,11 @@ func (m *Context) SetBoundingBox(bbox s2.Rect) {
|
|||
m.hasBoundingBox = true
|
||||
}
|
||||
|
||||
// SetBackground sets the background color (used as a fallback for areas without map tiles)
|
||||
func (m *Context) SetBackground(col color.Color) {
|
||||
m.background = col
|
||||
}
|
||||
|
||||
// AddMarker adds a marker to the Context
|
||||
func (m *Context) AddMarker(marker *Marker) {
|
||||
m.markers = append(m.markers, marker)
|
||||
|
@ -109,6 +127,26 @@ func (m *Context) ClearAreas() {
|
|||
m.areas = nil
|
||||
}
|
||||
|
||||
// AddCircle adds an circle to the Context
|
||||
func (m *Context) AddCircle(circle *Circle) {
|
||||
m.circles = append(m.circles, circle)
|
||||
}
|
||||
|
||||
// ClearCircles removes all circles from the Context
|
||||
func (m *Context) ClearCircles() {
|
||||
m.circles = nil
|
||||
}
|
||||
|
||||
// AddOverlay adds an overlay to the Context
|
||||
func (m *Context) AddOverlay(overlay *TileProvider) {
|
||||
m.overlays = append(m.overlays, overlay)
|
||||
}
|
||||
|
||||
// ClearOverlays removes all overlays from the Context
|
||||
func (m *Context) ClearOverlays() {
|
||||
m.overlays = nil
|
||||
}
|
||||
|
||||
func (m *Context) determineBounds() s2.Rect {
|
||||
r := s2.EmptyRect()
|
||||
for _, marker := range m.markers {
|
||||
|
@ -120,6 +158,9 @@ func (m *Context) determineBounds() s2.Rect {
|
|||
for _, area := range m.areas {
|
||||
r = r.Union(area.bounds())
|
||||
}
|
||||
for _, circle := range m.circles {
|
||||
r = r.Union(circle.bounds())
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
@ -140,6 +181,11 @@ func (m *Context) determineExtraMarginPixels() float64 {
|
|||
p = pp
|
||||
}
|
||||
}
|
||||
for _, circle := range m.circles {
|
||||
if pp := circle.extraMarginPixels(); pp > p {
|
||||
p = pp
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
|
@ -202,55 +248,91 @@ func (m *Context) determineZoomCenter() (int, s2.LatLng, error) {
|
|||
|
||||
type transformer struct {
|
||||
zoom int
|
||||
tileSize int
|
||||
pWidth, pHeight int
|
||||
pCenterX, pCenterY int
|
||||
tCountX, tCountY int
|
||||
tCenterX, tCenterY float64
|
||||
tOriginX, tOriginY int
|
||||
numTiles float64 // number of tiles per dimension at this zoom level
|
||||
tileSize int // tile size in pixels from this provider
|
||||
pWidth, pHeight int // pixel size of returned set of tiles
|
||||
pCenterX, pCenterY int // pixel location of requested center in set of tiles
|
||||
tCountX, tCountY int // download area in tile units
|
||||
tCenterX, tCenterY float64 // tile index to requested center
|
||||
tOriginX, tOriginY int // bottom left tile to download
|
||||
pMinX, pMaxX int
|
||||
}
|
||||
|
||||
func newTransformer(width int, height int, zoom int, llCenter s2.LatLng, tileSize int) *transformer {
|
||||
t := new(transformer)
|
||||
|
||||
t.zoom = zoom
|
||||
t.numTiles = math.Exp2(float64(t.zoom))
|
||||
t.tileSize = tileSize
|
||||
|
||||
// fractional tile index to center of requested area
|
||||
t.tCenterX, t.tCenterY = t.ll2t(llCenter)
|
||||
|
||||
ww := float64(width) / float64(tileSize)
|
||||
hh := float64(height) / float64(tileSize)
|
||||
|
||||
// origin tile to fulfill request
|
||||
t.tOriginX = int(math.Floor(t.tCenterX - 0.5*ww))
|
||||
t.tOriginY = int(math.Floor(t.tCenterY - 0.5*hh))
|
||||
|
||||
// tiles in each axis to fulfill request
|
||||
t.tCountX = 1 + int(math.Floor(t.tCenterX+0.5*ww)) - t.tOriginX
|
||||
t.tCountY = 1 + int(math.Floor(t.tCenterY+0.5*hh)) - t.tOriginY
|
||||
|
||||
// final pixel dimensions of area returned
|
||||
t.pWidth = t.tCountX * tileSize
|
||||
t.pHeight = t.tCountY * tileSize
|
||||
|
||||
// Pixel location in returned image for center of requested area
|
||||
t.pCenterX = int((t.tCenterX - float64(t.tOriginX)) * float64(tileSize))
|
||||
t.pCenterY = int((t.tCenterY - float64(t.tOriginY)) * float64(tileSize))
|
||||
|
||||
t.pMinX = t.pCenterX - width/2
|
||||
t.pMaxX = t.pMinX + width
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// ll2t returns fractional tile index for a lat/lng points
|
||||
func (t *transformer) ll2t(ll s2.LatLng) (float64, float64) {
|
||||
tiles := math.Exp2(float64(t.zoom))
|
||||
x := tiles * (ll.Lng.Degrees() + 180.0) / 360.0
|
||||
y := tiles * (1 - math.Log(math.Tan(ll.Lat.Radians())+(1.0/math.Cos(ll.Lat.Radians())))/math.Pi) / 2.0
|
||||
x := t.numTiles * (ll.Lng.Degrees() + 180.0) / 360.0
|
||||
y := t.numTiles * (1 - math.Log(math.Tan(ll.Lat.Radians())+(1.0/math.Cos(ll.Lat.Radians())))/math.Pi) / 2.0
|
||||
return x, y
|
||||
}
|
||||
|
||||
func (t *transformer) ll2p(ll s2.LatLng) (float64, float64) {
|
||||
x, y := t.ll2t(ll)
|
||||
if x < float64(t.tOriginX) {
|
||||
x = x + math.Exp2(float64(t.zoom))
|
||||
}
|
||||
x = float64(t.pCenterX) + (x-t.tCenterX)*float64(t.tileSize)
|
||||
y = float64(t.pCenterY) + (y-t.tCenterY)*float64(t.tileSize)
|
||||
|
||||
offset := t.numTiles * float64(t.tileSize)
|
||||
if x < float64(t.pMinX) {
|
||||
for x < float64(t.pMinX) {
|
||||
x = x + offset
|
||||
}
|
||||
} else if x >= float64(t.pMaxX) {
|
||||
for x >= float64(t.pMaxX) {
|
||||
x = x - offset
|
||||
}
|
||||
}
|
||||
return x, y
|
||||
}
|
||||
|
||||
// Rect returns an s2.Rect bounding box around the set of tiles described by transformer
|
||||
func (t *transformer) Rect() (bbox s2.Rect) {
|
||||
// transform from https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Go
|
||||
invNumTiles := 1.0 / t.numTiles
|
||||
// Get latitude bounds
|
||||
n := math.Pi - 2.0*math.Pi*float64(t.tOriginY)*invNumTiles
|
||||
bbox.Lat.Hi = math.Atan(0.5 * (math.Exp(n) - math.Exp(-n)))
|
||||
n = math.Pi - 2.0*math.Pi*float64(t.tOriginY+t.tCountY)*invNumTiles
|
||||
bbox.Lat.Lo = math.Atan(0.5 * (math.Exp(n) - math.Exp(-n)))
|
||||
// Get longtitude bounds, much easier
|
||||
bbox.Lng.Lo = float64(t.tOriginX)*invNumTiles*2.0*math.Pi - math.Pi
|
||||
bbox.Lng.Hi = float64(t.tOriginX+t.tCountX)*invNumTiles*2.0*math.Pi - math.Pi
|
||||
return bbox
|
||||
}
|
||||
|
||||
// Render actually renders the map image including all map objects (markers, paths, areas)
|
||||
func (m *Context) Render() (image.Image, error) {
|
||||
zoom, center, err := m.determineZoomCenter()
|
||||
|
@ -262,28 +344,19 @@ func (m *Context) Render() (image.Image, error) {
|
|||
trans := newTransformer(m.width, m.height, zoom, center, tileSize)
|
||||
img := image.NewRGBA(image.Rect(0, 0, trans.pWidth, trans.pHeight))
|
||||
gc := gg.NewContextForRGBA(img)
|
||||
if m.background != nil {
|
||||
draw.Draw(img, img.Bounds(), &image.Uniform{m.background}, image.ZP, draw.Src)
|
||||
}
|
||||
|
||||
// fetch and draw tiles to img
|
||||
t := NewTileFetcher(m.tileProvider)
|
||||
tiles := (1 << uint(zoom))
|
||||
for xx := 0; xx < trans.tCountX; xx++ {
|
||||
x := trans.tOriginX + xx
|
||||
if x < 0 {
|
||||
x = x + tiles
|
||||
} else if x >= tiles {
|
||||
x = x - tiles
|
||||
}
|
||||
for yy := 0; yy < trans.tCountY; yy++ {
|
||||
y := trans.tOriginY + yy
|
||||
if y < 0 || y >= tiles {
|
||||
log.Printf("Skipping out of bounds tile %d/%d", x, y)
|
||||
} else {
|
||||
if tileImg, err := t.Fetch(zoom, x, y); err == nil {
|
||||
gc.DrawImage(tileImg, xx*tileSize, yy*tileSize)
|
||||
} else {
|
||||
log.Printf("Error downloading tile file: %s", err)
|
||||
}
|
||||
}
|
||||
layers := []*TileProvider{m.tileProvider}
|
||||
if m.overlays != nil {
|
||||
layers = append(layers, m.overlays...)
|
||||
}
|
||||
|
||||
for _, layer := range layers {
|
||||
if err := m.renderLayer(gc, zoom, trans, tileSize, layer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,6 +370,9 @@ func (m *Context) Render() (image.Image, error) {
|
|||
for _, marker := range m.markers {
|
||||
marker.draw(gc, trans)
|
||||
}
|
||||
for _, circle := range m.circles {
|
||||
circle.draw(gc, trans)
|
||||
}
|
||||
|
||||
// crop image
|
||||
croppedImg := image.NewRGBA(image.Rect(0, 0, int(m.width), int(m.height)))
|
||||
|
@ -319,3 +395,94 @@ func (m *Context) Render() (image.Image, error) {
|
|||
|
||||
return croppedImg, nil
|
||||
}
|
||||
|
||||
// RenderWithBounds actually renders the map image including all map objects (markers, paths, areas).
|
||||
// The returned image covers requested area as well as any tiles necessary to cover that area, which may
|
||||
// be larger than the request.
|
||||
//
|
||||
// Specific bounding box of returned image is provided to support image registration with other data
|
||||
func (m *Context) RenderWithBounds() (image.Image, s2.Rect, error) {
|
||||
zoom, center, err := m.determineZoomCenter()
|
||||
if err != nil {
|
||||
return nil, s2.Rect{}, err
|
||||
}
|
||||
|
||||
tileSize := m.tileProvider.TileSize
|
||||
trans := newTransformer(m.width, m.height, zoom, center, tileSize)
|
||||
img := image.NewRGBA(image.Rect(0, 0, trans.pWidth, trans.pHeight))
|
||||
gc := gg.NewContextForRGBA(img)
|
||||
if m.background != nil {
|
||||
draw.Draw(img, img.Bounds(), &image.Uniform{m.background}, image.ZP, draw.Src)
|
||||
}
|
||||
|
||||
// fetch and draw tiles to img
|
||||
layers := []*TileProvider{m.tileProvider}
|
||||
if m.overlays != nil {
|
||||
layers = append(layers, m.overlays...)
|
||||
}
|
||||
|
||||
for _, layer := range layers {
|
||||
if err := m.renderLayer(gc, zoom, trans, tileSize, layer); err != nil {
|
||||
return nil, s2.Rect{}, err
|
||||
}
|
||||
}
|
||||
|
||||
// draw map objects
|
||||
for _, area := range m.areas {
|
||||
area.draw(gc, trans)
|
||||
}
|
||||
for _, path := range m.paths {
|
||||
path.draw(gc, trans)
|
||||
}
|
||||
for _, circle := range m.circles {
|
||||
circle.draw(gc, trans)
|
||||
}
|
||||
for _, marker := range m.markers {
|
||||
marker.draw(gc, trans)
|
||||
}
|
||||
|
||||
// draw attribution
|
||||
if m.tileProvider.Attribution == "" {
|
||||
return img, trans.Rect(), nil
|
||||
}
|
||||
_, textHeight := gc.MeasureString(m.tileProvider.Attribution)
|
||||
boxHeight := textHeight + 4.0
|
||||
gc.SetRGBA(0.0, 0.0, 0.0, 0.5)
|
||||
gc.DrawRectangle(0.0, float64(trans.pHeight)-boxHeight, float64(trans.pWidth), boxHeight)
|
||||
gc.Fill()
|
||||
gc.SetRGBA(1.0, 1.0, 1.0, 0.75)
|
||||
gc.DrawString(m.tileProvider.Attribution, 4.0, float64(m.height)-4.0)
|
||||
|
||||
return img, trans.Rect(), nil
|
||||
}
|
||||
|
||||
func (m *Context) renderLayer(gc *gg.Context, zoom int, trans *transformer, tileSize int, provider *TileProvider) error {
|
||||
t := NewTileFetcher(provider)
|
||||
if m.userAgent != "" {
|
||||
t.SetUserAgent(m.userAgent)
|
||||
}
|
||||
|
||||
tiles := (1 << uint(zoom))
|
||||
for xx := 0; xx < trans.tCountX; xx++ {
|
||||
x := trans.tOriginX + xx
|
||||
if x < 0 {
|
||||
x = x + tiles
|
||||
} else if x >= tiles {
|
||||
x = x - tiles
|
||||
}
|
||||
for yy := 0; yy < trans.tCountY; yy++ {
|
||||
y := trans.tOriginY + yy
|
||||
if y < 0 || y >= tiles {
|
||||
log.Printf("Skipping out of bounds tile %d/%d", x, y)
|
||||
} else {
|
||||
if tileImg, err := t.Fetch(zoom, x, y); err == nil {
|
||||
gc.DrawImage(tileImg, xx*tileSize, yy*tileSize)
|
||||
} else {
|
||||
log.Printf("Error downloading tile file: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -16,3 +16,10 @@ type MapObject interface {
|
|||
extraMarginPixels() float64
|
||||
draw(dc *gg.Context, trans *transformer)
|
||||
}
|
||||
|
||||
// CanDisplay checks if pos is generally displayable (i.e. its latitude is in [-85,85])
|
||||
func CanDisplay(pos s2.LatLng) bool {
|
||||
const minLatitude float64 = -85.0
|
||||
const maxLatitude float64 = 85.0
|
||||
return (minLatitude <= pos.Lat.Degrees()) && (pos.Lat.Degrees() <= maxLatitude)
|
||||
}
|
|
@ -8,6 +8,7 @@ package sm
|
|||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -39,6 +40,7 @@ func NewMarker(pos s2.LatLng, col color.Color, size float64) *Marker {
|
|||
} else {
|
||||
m.LabelColor = color.RGBA{0xff, 0xff, 0xff, 0xff}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
|
@ -121,6 +123,11 @@ func (m *Marker) bounds() s2.Rect {
|
|||
}
|
||||
|
||||
func (m *Marker) draw(gc *gg.Context, trans *transformer) {
|
||||
if !CanDisplay(m.Position) {
|
||||
log.Printf("Marker coordinates not displayable: %f/%f", m.Position.Lat.Degrees(), m.Position.Lng.Degrees())
|
||||
return
|
||||
}
|
||||
|
||||
gc.ClearPath()
|
||||
gc.SetLineJoin(gg.LineJoinRound)
|
||||
gc.SetLineWidth(1.0)
|
|
@ -24,6 +24,16 @@ type Path struct {
|
|||
Weight float64
|
||||
}
|
||||
|
||||
// NewPath creates a new Path
|
||||
func NewPath(positions []s2.LatLng, col color.Color, weight float64) *Path {
|
||||
p := new(Path)
|
||||
p.Positions = positions
|
||||
p.Color = col
|
||||
p.Weight = weight
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// ParsePathString parses a string and returns a path
|
||||
func ParsePathString(s string) ([]*Path, error) {
|
||||
paths := make([]*Path, 0, 0)
|
|
@ -21,13 +21,12 @@ import (
|
|||
"github.com/Wessie/appdirs"
|
||||
)
|
||||
|
||||
var TileFetcherUserAgent = "Mozilla/5.0+(compatible; go-staticmaps/0.1; https://github.com/flopp/go-staticmaps)"
|
||||
|
||||
// TileFetcher downloads map tile images from a TileProvider
|
||||
type TileFetcher struct {
|
||||
tileProvider *TileProvider
|
||||
cacheDir string
|
||||
useCaching bool
|
||||
userAgent string
|
||||
}
|
||||
|
||||
// NewTileFetcher creates a new Tilefetcher struct
|
||||
|
@ -37,9 +36,15 @@ func NewTileFetcher(tileProvider *TileProvider) *TileFetcher {
|
|||
app := appdirs.New("go-staticmaps", "flopp.net", "0.1")
|
||||
t.cacheDir = fmt.Sprintf("%s/%s", app.UserCache(), tileProvider.Name)
|
||||
t.useCaching = true
|
||||
t.userAgent = "Mozilla/5.0+(compatible; go-staticmaps/0.1; https://github.com/flopp/go-staticmaps)"
|
||||
return t
|
||||
}
|
||||
|
||||
// SetUserAgent sets the HTTP user agent string used when downloading map tiles
|
||||
func (t *TileFetcher) SetUserAgent(a string) {
|
||||
t.userAgent = a
|
||||
}
|
||||
|
||||
func (t *TileFetcher) url(zoom, x, y int) string {
|
||||
shard := ""
|
||||
ss := len(t.tileProvider.Shards)
|
||||
|
@ -91,7 +96,7 @@ func (t *TileFetcher) Fetch(zoom, x, y int) (image.Image, error) {
|
|||
|
||||
func (t *TileFetcher) download(url string) ([]byte, error) {
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
req.Header.Set("User-Agent", TileFetcherUserAgent)
|
||||
req.Header.Set("User-Agent", t.userAgent)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
2
vendor/github.com/Luzifer/go_helpers/accessLogger/accessLogger.go
generated
vendored
2
vendor/github.com/Luzifer/go_helpers/accessLogger/accessLogger.go
generated
vendored
|
@ -33,5 +33,5 @@ func (a *AccessLogResponseWriter) WriteHeader(code int) {
|
|||
}
|
||||
|
||||
func (a *AccessLogResponseWriter) HTTPResponseType() string {
|
||||
return fmt.Sprintf("%sxx", strconv.FormatInt(int64(a.StatusCode), 10)[0])
|
||||
return fmt.Sprintf("%cxx", strconv.FormatInt(int64(a.StatusCode), 10)[0])
|
||||
}
|
||||
|
|
55
vendor/github.com/Luzifer/go_helpers/http/digest.go
generated
vendored
Normal file
55
vendor/github.com/Luzifer/go_helpers/http/digest.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Luzifer/go_helpers/str"
|
||||
)
|
||||
|
||||
func GetDigestAuth(resp *http.Response, method, requestPath, user, password string) string {
|
||||
params := map[string]string{}
|
||||
for _, part := range strings.Split(resp.Header.Get("Www-Authenticate"), " ") {
|
||||
if !strings.Contains(part, `="`) {
|
||||
continue
|
||||
}
|
||||
spl := strings.Split(strings.Trim(part, " ,"), "=")
|
||||
if !str.StringInSlice(spl[0], []string{"nonce", "realm", "qop"}) {
|
||||
continue
|
||||
}
|
||||
params[spl[0]] = strings.Trim(spl[1], `"`)
|
||||
}
|
||||
|
||||
b := make([]byte, 8)
|
||||
io.ReadFull(rand.Reader, b)
|
||||
|
||||
params["cnonce"] = fmt.Sprintf("%x", b)
|
||||
params["nc"] = "1"
|
||||
params["uri"] = requestPath
|
||||
params["username"] = user
|
||||
params["response"] = getMD5([]string{
|
||||
getMD5([]string{params["username"], params["realm"], password}),
|
||||
params["nonce"],
|
||||
params["nc"],
|
||||
params["cnonce"],
|
||||
params["qop"],
|
||||
getMD5([]string{method, requestPath}),
|
||||
})
|
||||
|
||||
authParts := []string{}
|
||||
for k, v := range params {
|
||||
authParts = append(authParts, fmt.Sprintf("%s=%q", k, v))
|
||||
}
|
||||
return "Digest " + strings.Join(authParts, ", ")
|
||||
}
|
||||
|
||||
func getMD5(in []string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(strings.Join(in, ":")))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
21
vendor/github.com/Luzifer/go_helpers/str/slice.go
generated
vendored
Normal file
21
vendor/github.com/Luzifer/go_helpers/str/slice.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package str
|
||||
|
||||
// AppendIfMissing adds a string to a slice when it's not present yet
|
||||
func AppendIfMissing(slice []string, s string) []string {
|
||||
for _, e := range slice {
|
||||
if e == s {
|
||||
return slice
|
||||
}
|
||||
}
|
||||
return append(slice, s)
|
||||
}
|
||||
|
||||
// StringInSlice checks for the existence of a string in the slice
|
||||
func StringInSlice(a string, list []string) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
17
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
17
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
|
@ -1,10 +1,15 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- tip
|
||||
env:
|
||||
- GOMAXPROCS=4 GORACE=halt_on_error=1
|
||||
install:
|
||||
- go get -t ./...
|
||||
script: GOMAXPROCS=4 GORACE="halt_on_error=1" go test -race -v ./...
|
||||
- go get github.com/stretchr/testify/assert
|
||||
- go get gopkg.in/gemnasium/logrus-airbrake-hook.v2
|
||||
- go get golang.org/x/sys/unix
|
||||
- go get golang.org/x/sys/windows
|
||||
script:
|
||||
- go test -race -v ./...
|
||||
|
|
57
vendor/github.com/Sirupsen/logrus/CHANGELOG.md
generated
vendored
57
vendor/github.com/Sirupsen/logrus/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,60 @@
|
|||
# 1.0.5
|
||||
|
||||
* Fix hooks race (#707)
|
||||
* Fix panic deadlock (#695)
|
||||
|
||||
# 1.0.4
|
||||
|
||||
* Fix race when adding hooks (#612)
|
||||
* Fix terminal check in AppEngine (#635)
|
||||
|
||||
# 1.0.3
|
||||
|
||||
* Replace example files with testable examples
|
||||
|
||||
# 1.0.2
|
||||
|
||||
* bug: quote non-string values in text formatter (#583)
|
||||
* Make (*Logger) SetLevel a public method
|
||||
|
||||
# 1.0.1
|
||||
|
||||
* bug: fix escaping in text formatter (#575)
|
||||
|
||||
# 1.0.0
|
||||
|
||||
* Officially changed name to lower-case
|
||||
* bug: colors on Windows 10 (#541)
|
||||
* bug: fix race in accessing level (#512)
|
||||
|
||||
# 0.11.5
|
||||
|
||||
* feature: add writer and writerlevel to entry (#372)
|
||||
|
||||
# 0.11.4
|
||||
|
||||
* bug: fix undefined variable on solaris (#493)
|
||||
|
||||
# 0.11.3
|
||||
|
||||
* formatter: configure quoting of empty values (#484)
|
||||
* formatter: configure quoting character (default is `"`) (#484)
|
||||
* bug: fix not importing io correctly in non-linux environments (#481)
|
||||
|
||||
# 0.11.2
|
||||
|
||||