mirror of
https://github.com/flopp/go-staticmaps.git
synced 2025-12-08 18:26:36 +00:00
parent
3465b33495
commit
112a0c57b9
4
area.go
4
area.go
@ -84,7 +84,7 @@ func (p *Area) bounds() s2.Rect {
|
||||
return r
|
||||
}
|
||||
|
||||
func (p *Area) draw(gc *gg.Context, trans *transformer) {
|
||||
func (p *Area) draw(gc *gg.Context, trans *Transformer) {
|
||||
if len(p.Positions) <= 1 {
|
||||
return
|
||||
}
|
||||
@ -94,7 +94,7 @@ func (p *Area) draw(gc *gg.Context, trans *transformer) {
|
||||
gc.SetLineCap(gg.LineCapRound)
|
||||
gc.SetLineJoin(gg.LineJoinRound)
|
||||
for _, ll := range p.Positions {
|
||||
gc.LineTo(trans.ll2p(ll))
|
||||
gc.LineTo(trans.LatLngToXY(ll))
|
||||
}
|
||||
gc.ClosePath()
|
||||
gc.SetColor(p.Fill)
|
||||
|
||||
@ -106,15 +106,15 @@ func (m *Circle) bounds() s2.Rect {
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *Circle) draw(gc *gg.Context, trans *transformer) {
|
||||
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)
|
||||
x, y := trans.LatLngToXY(m.Position)
|
||||
x1, y1 := trans.LatLngToXY(ll)
|
||||
radius := math.Sqrt(math.Pow(x1-x, 2) + math.Pow(y1-y, 2))
|
||||
gc.ClearPath()
|
||||
gc.SetLineWidth(m.Weight)
|
||||
|
||||
54
context.go
54
context.go
@ -263,7 +263,8 @@ func (m *Context) determineZoomCenter() (int, s2.LatLng, error) {
|
||||
return 0, s2.LatLngFromDegrees(0, 0), errors.New("cannot determine map extent: no center coordinates given, no bounding box given, no content (markers, paths, areas) given")
|
||||
}
|
||||
|
||||
type transformer struct {
|
||||
// Transformer implements coordinate transformation from latitude longitude to image pixel coordinates.
|
||||
type Transformer struct {
|
||||
zoom int
|
||||
numTiles float64 // number of tiles per dimension at this zoom level
|
||||
tileSize int // tile size in pixels from this provider
|
||||
@ -275,8 +276,18 @@ type transformer struct {
|
||||
pMinX, pMaxX int
|
||||
}
|
||||
|
||||
func newTransformer(width int, height int, zoom int, llCenter s2.LatLng, tileSize int) *transformer {
|
||||
t := new(transformer)
|
||||
// Transformer returns an initialized Transformer instance.
|
||||
func (m *Context) Transformer() (*Transformer, error) {
|
||||
zoom, center, err := m.determineZoomCenter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newTransformer(m.width, m.height, zoom, center, m.tileProvider.TileSize), nil
|
||||
}
|
||||
|
||||
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))
|
||||
@ -311,13 +322,14 @@ func newTransformer(width int, height int, zoom int, llCenter s2.LatLng, tileSiz
|
||||
}
|
||||
|
||||
// ll2t returns fractional tile index for a lat/lng points
|
||||
func (t *transformer) ll2t(ll s2.LatLng) (float64, float64) {
|
||||
func (t *Transformer) ll2t(ll s2.LatLng) (float64, float64) {
|
||||
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) {
|
||||
// LatLngToXY transforms a latitude longitude pair into image x, y coordinates.
|
||||
func (t *Transformer) LatLngToXY(ll s2.LatLng) (float64, float64) {
|
||||
x, y := t.ll2t(ll)
|
||||
x = float64(t.pCenterX) + (x-t.tCenterX)*float64(t.tileSize)
|
||||
y = float64(t.pCenterY) + (y-t.tCenterY)*float64(t.tileSize)
|
||||
@ -335,8 +347,8 @@ func (t *transformer) ll2p(ll s2.LatLng) (float64, float64) {
|
||||
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) {
|
||||
// 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
|
||||
@ -418,15 +430,15 @@ func (m *Context) Render() (image.Image, error) {
|
||||
return croppedImg, nil
|
||||
}
|
||||
|
||||
// RenderWithBounds actually renders the map image including all map objects (markers, paths, areas).
|
||||
// RenderWithTransformer 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) {
|
||||
// A Transformer is returned to support image registration with other data.
|
||||
func (m *Context) RenderWithTransformer() (image.Image, *Transformer, error) {
|
||||
zoom, center, err := m.determineZoomCenter()
|
||||
if err != nil {
|
||||
return nil, s2.Rect{}, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
tileSize := m.tileProvider.TileSize
|
||||
@ -445,7 +457,7 @@ func (m *Context) RenderWithBounds() (image.Image, s2.Rect, error) {
|
||||
|
||||
for _, layer := range layers {
|
||||
if err := m.renderLayer(gc, zoom, trans, tileSize, layer); err != nil {
|
||||
return nil, s2.Rect{}, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +477,7 @@ func (m *Context) RenderWithBounds() (image.Image, s2.Rect, error) {
|
||||
|
||||
// draw attribution
|
||||
if m.tileProvider.Attribution == "" {
|
||||
return img, trans.Rect(), nil
|
||||
return img, trans, nil
|
||||
}
|
||||
_, textHeight := gc.MeasureString(m.tileProvider.Attribution)
|
||||
boxHeight := textHeight + 4.0
|
||||
@ -475,10 +487,24 @@ func (m *Context) RenderWithBounds() (image.Image, s2.Rect, error) {
|
||||
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, 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) {
|
||||
img, trans, err := m.RenderWithTransformer()
|
||||
if err != nil {
|
||||
return nil, s2.Rect{}, err
|
||||
|
||||
}
|
||||
return img, trans.Rect(), nil
|
||||
}
|
||||
|
||||
func (m *Context) renderLayer(gc *gg.Context, zoom int, trans *transformer, tileSize int, provider *TileProvider) error {
|
||||
func (m *Context) renderLayer(gc *gg.Context, zoom int, trans *Transformer, tileSize int, provider *TileProvider) error {
|
||||
t := NewTileFetcher(provider, m.cache)
|
||||
if m.userAgent != "" {
|
||||
t.SetUserAgent(m.userAgent)
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
type MapObject interface {
|
||||
bounds() s2.Rect
|
||||
extraMarginPixels() float64
|
||||
draw(dc *gg.Context, trans *transformer)
|
||||
draw(dc *gg.Context, trans *Transformer)
|
||||
}
|
||||
|
||||
// CanDisplay checks if pos is generally displayable (i.e. its latitude is in [-85,85])
|
||||
|
||||
@ -122,7 +122,7 @@ func (m *Marker) bounds() s2.Rect {
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *Marker) draw(gc *gg.Context, trans *transformer) {
|
||||
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
|
||||
@ -133,7 +133,7 @@ func (m *Marker) draw(gc *gg.Context, trans *transformer) {
|
||||
gc.SetLineWidth(1.0)
|
||||
|
||||
radius := 0.5 * m.Size
|
||||
x, y := trans.ll2p(m.Position)
|
||||
x, y := trans.LatLngToXY(m.Position)
|
||||
gc.DrawArc(x, y-m.Size, radius, (90.0+60.0)*math.Pi/180.0, (360.0+90.0-60.0)*math.Pi/180.0)
|
||||
gc.LineTo(x, y)
|
||||
gc.ClosePath()
|
||||
|
||||
4
path.go
4
path.go
@ -96,7 +96,7 @@ func (p *Path) bounds() s2.Rect {
|
||||
return r
|
||||
}
|
||||
|
||||
func (p *Path) draw(gc *gg.Context, trans *transformer) {
|
||||
func (p *Path) draw(gc *gg.Context, trans *Transformer) {
|
||||
if len(p.Positions) <= 1 {
|
||||
return
|
||||
}
|
||||
@ -106,7 +106,7 @@ func (p *Path) draw(gc *gg.Context, trans *transformer) {
|
||||
gc.SetLineCap(gg.LineCapRound)
|
||||
gc.SetLineJoin(gg.LineJoinRound)
|
||||
for _, ll := range p.Positions {
|
||||
gc.LineTo(trans.ll2p(ll))
|
||||
gc.LineTo(trans.LatLngToXY(ll))
|
||||
}
|
||||
gc.SetColor(p.Color)
|
||||
gc.Stroke()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user