1
0
Fork 0
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:
Knut Ahlers 2018-04-03 21:14:16 +02:00
parent 3c73d0a08c
commit 1abd72dfdc
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
411 changed files with 85657 additions and 37863 deletions

155
Godeps/Godeps.json generated
View file

@ -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
View file

@ -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
View file

@ -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

View file

@ -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

View file

@ -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
View file

@ -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
View 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

View file

@ -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.

View file

@ -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
View 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()
}

View file

@ -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)
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -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)

View file

@ -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)

View file

@ -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 {

View file

@ -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
View 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
View 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
}

View file

@ -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 ./...

View file

@ -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