fix setting of bounding box

This commit is contained in:
flopp 2017-01-28 17:33:19 +01:00
parent 340522f16b
commit 79a46b5d2d
4 changed files with 95 additions and 18 deletions

View File

@ -76,7 +76,10 @@ See [GoDoc](https://godoc.org/github.com/flopp/go-staticmaps) for a complete doc
-t, --type=MAPTYPE Select the map type; list possible map types with '--type list'
-c, --center=LATLNG Center coordinates (lat,lng) of the static map
-z, --zoom=ZOOMLEVEL Zoom factor
-b, --bbox=LATLNG|LATLNG Set the bounding box (the given coordinates pair must be opposite corners of a rectangle)
-b, --bbox=NW_LATLNG|SE_LATLNG
Set the bounding box (NW_LATLNG = north-western point of the
bounding box, SW_LATLNG = southe-western point of the bounding
box)
-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

53
bbox.go Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2016, 2017 Florian Pigorsch. All rights reserved.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package sm
import (
"fmt"
"math"
"github.com/golang/geo/s1"
"github.com/golang/geo/s2"
)
// CreateBBox creates a bounding box from a north-western point
// (lat/lng in degrees) and a south-eastern point (lat/lng in degrees).
// Note that you can create a bounding box wrapping over the antimeridian at
// lng=+-/180° by nwlng > selng.
func CreateBBox(nwlat float64, nwlng float64, selat float64, selng float64) (*s2.Rect, error) {
if nwlat < -90 || nwlat > 90 {
return nil, fmt.Errorf("Out of range nwlat (%f) must be in [-90, 90]", nwlat)
}
if nwlng < -180 || nwlng > 180 {
return nil, fmt.Errorf("Out of range nwlng (%f) must be in [-180, 180]", nwlng)
}
if selat < -90 || selat > 90 {
return nil, fmt.Errorf("Out of range selat (%f) must be in [-90, 90]", selat)
}
if selng < -180 || selng > 180 {
return nil, fmt.Errorf("Out of range selng (%f) must be in [-180, 180]", selng)
}
if nwlat == selat {
return nil, fmt.Errorf("nwlat and selat must not be equal")
}
if nwlng == selng {
return nil, fmt.Errorf("nwlng and selng must not be equal")
}
bbox := new(s2.Rect)
if selat < nwlat {
bbox.Lat.Lo = selat * math.Pi / 180.0
bbox.Lat.Hi = nwlat * math.Pi / 180.0
} else {
bbox.Lat.Lo = nwlat * math.Pi / 180.0
bbox.Lat.Hi = selat * math.Pi / 180.0
}
bbox.Lng = s1.IntervalFromEndpoints(nwlng*math.Pi/180.0, selng*math.Pi/180.0)
return bbox, nil
}

View File

@ -157,7 +157,14 @@ func (m *Context) determineZoom(bounds s2.Rect, center s2.LatLng) int {
maxX := (b.Hi().Lng.Degrees() + 180.0) / 360.0
minY := (1.0 - math.Log(math.Tan(b.Lo().Lat.Radians())+(1.0/math.Cos(b.Lo().Lat.Radians())))/math.Pi) / 2.0
maxY := (1.0 - math.Log(math.Tan(b.Hi().Lat.Radians())+(1.0/math.Cos(b.Hi().Lat.Radians())))/math.Pi) / 2.0
dx := math.Abs(maxX - minX)
dx := maxX - minX
for dx < 0 {
dx = dx + 1
}
for dx > 1 {
dx = dx - 1
}
dy := math.Abs(maxY - minY)
zoom := 1
@ -236,6 +243,9 @@ func (t *transformer) ll2t(ll s2.LatLng) (float64, float64) {
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)
return x, y
@ -255,17 +265,24 @@ func (m *Context) Render() (image.Image, error) {
// 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 + (1 << uint(zoom))
x = x + tiles
} else if x >= tiles {
x = x - tiles
}
for yy := 0; yy < trans.tCountY; yy++ {
y := trans.tOriginY + yy
if tileImg, err := t.Fetch(zoom, x, y); err == nil {
gc.DrawImage(tileImg, xx*tileSize, yy*tileSize)
if y < 0 || y >= tiles {
log.Printf("Skipping out of bounds tile %d/%d", x, y)
} else {
log.Printf("Error downloading tile file: %s", err)
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)
}
}
}
}

View File

@ -55,26 +55,30 @@ func handleCenterOption(ctx *sm.Context, parameter string) {
func handleBboxOption(ctx *sm.Context, parameter string) {
pair := strings.Split(parameter, "|")
if len(pair) != 2 {
log.Fatalf("Bad LATLNG|LATLNG pair: %s", parameter)
log.Fatalf("Bad NW|SE coordinates pair: %s", parameter)
}
bbox := s2.EmptyRect()
lat, lng, err := coordsparser.Parse(pair[0])
var err error
var nwlat float64
var nwlng float64
var selat float64
var selng float64
nwlat, nwlng, err = coordsparser.Parse(pair[0])
if err != nil {
log.Fatal(err)
} else {
bbox = bbox.AddPoint(s2.LatLngFromDegrees(lat, lng))
}
lat, lng, err = coordsparser.Parse(pair[1])
selat, selng, err = coordsparser.Parse(pair[1])
if err != nil {
log.Fatal(err)
} else {
bbox = bbox.AddPoint(s2.LatLngFromDegrees(lat, lng))
}
ctx.SetBoundingBox(bbox)
var bbox s2.Rect
bbox, err = sm.CreateBBox(nwlat, nwlng, selat, selng)
if err != nil {
log.Fatal(err)
}
ctx.SetBoundingBox(*bbox)
}
func handleMarkersOption(ctx *sm.Context, parameters []string) {
@ -124,7 +128,7 @@ func main() {
Type string `short:"t" long:"type" description:"Select the map type; list possible map types with '--type list'" value-name:"MAPTYPE"`
Center string `short:"c" long:"center" description:"Center coordinates (lat,lng) of the static map" value-name:"LATLNG"`
Zoom int `short:"z" long:"zoom" description:"Zoom factor" value-name:"ZOOMLEVEL"`
BBox string `short:"b" long:"bbox" description:"Bounding box of the static map" value-name:"LATLNG|LATLNG"`
BBox string `short:"b" long:"bbox" description:"Bounding box of the static map" value-name:"nwLATLNG|seLATLNG"`
Markers []string `short:"m" long:"marker" description:"Add a marker to the static map" value-name:"MARKER"`
Paths []string `short:"p" long:"path" description:"Add a path to the static map" value-name:"PATH"`
Areas []string `short:"a" long:"area" description:"Add an area to the static map" value-name:"AREA"`