Skip to content

Commit

Permalink
Merge pull request go-spatial#202 from terranodo/issue-64
Browse files Browse the repository at this point in the history
Issue 64 LGTM+2
  • Loading branch information
gdey authored Nov 30, 2017
2 parents 3de1016 + 58ef582 commit a7f2e6e
Show file tree
Hide file tree
Showing 89 changed files with 9,093 additions and 910 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.DS_Store
.idea
*.toml
tegola
165 changes: 165 additions & 0 deletions atlas/atlas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package atlas

import (
"context"
"sync"

"github.com/terranodo/tegola"
"github.com/terranodo/tegola/cache"
)

// DefaultAtlas is instanitated for convenience
var DefaultAtlas = &Atlas{}

const (
// MaxZoom will not render tile beyond this zoom level
MaxZoom = 22
)

type Atlas struct {
// for managing current access to the map container
sync.RWMutex
// hold maps
maps map[string]Map
// holds a reference to the cache backend
cacher cache.Interface
}

func (a *Atlas) AllMaps() []Map {
a.RLock()
defer a.RUnlock()

var maps []Map
for i := range a.maps {
m := a.maps[i]
// make an explict copy of the layers
layers := make([]Layer, len(m.Layers))
copy(layers, m.Layers)
m.Layers = layers

maps = append(maps, m)
}

return maps
}

// SeedMapTile will generate a tile and persist it to the
// configured cache backend
func (a *Atlas) SeedMapTile(m Map, tile tegola.Tile) error {
// confirm we have a cache backend
if a.cacher == nil {
return ErrMissingCache
}

// encode the tile
b, err := m.Encode(context.Background(), tile)
if err != nil {
return err
}

// cache key
key := cache.Key{
MapName: m.Name,
Z: tile.Z,
X: tile.X,
Y: tile.Y,
}

return a.cacher.Set(&key, b)
}

// PurgeMapTile will purge a map tile from the configured cache backend
func (a *Atlas) PurgeMapTile(m Map, tile tegola.Tile) error {
if a.cacher == nil {
return ErrMissingCache
}

// cache key
key := cache.Key{
MapName: m.Name,
Z: tile.Z,
X: tile.X,
Y: tile.Y,
}

return a.cacher.Purge(&key)
}

// Map looks up a Map by name and returns a copy of the Map
func (a *Atlas) Map(mapName string) (Map, error) {
a.RLock()
defer a.RUnlock()

m, ok := a.maps[mapName]
if !ok {
return Map{}, ErrMapNotFound{
Name: mapName,
}
}

// make an explict copy of the layers
layers := make([]Layer, len(m.Layers))
copy(layers, m.Layers)
m.Layers = layers

return m, nil
}

// AddMap registers a map by name. if the map already exists it will be overwritten
func (a *Atlas) AddMap(m Map) {
a.Lock()
defer a.Unlock()

if a.maps == nil {
a.maps = map[string]Map{}
}

a.maps[m.Name] = m
}

// GetCache returns the registered cache if one is registered, otherwise nil
func (a *Atlas) GetCache() cache.Interface {
return a.cacher
}

// SetCache sets the cache backend
func (a *Atlas) SetCache(c cache.Interface) {
a.cacher = c
}

// AllMaps returns all registered maps in DefaultAtlas
func AllMaps() []Map {
return DefaultAtlas.AllMaps()
}

// GetMap returns a copy of the a map by name from DefaultAtlas. if the map does not exist it will return an error
func GetMap(mapName string) (Map, error) {
return DefaultAtlas.Map(mapName)
}

// AddMap registers a map by name with DefaultAtlas. if the map already exists it will be overwritten
func AddMap(m Map) {
DefaultAtlas.AddMap(m)
}

// GetCache returns the registered cache for DefaultAtlas, if one is registered, otherwise nil
func GetCache() cache.Interface {
return DefaultAtlas.GetCache()
}

// SetCache sets the cache backend for DefaultAtlas
func SetCache(c cache.Interface) {
DefaultAtlas.SetCache(c)
}

// SeedMapTile will generate a tile and persist it to the
// configured cache backend for the DefaultAtlas
func SeedMapTile(m Map, tile tegola.Tile) error {
return DefaultAtlas.SeedMapTile(m, tile)
}

// PurgeMapTile will purge a map tile from the configured cache backend
// for the DefaultAtlas
func PurgeMapTile(m Map, tile tegola.Tile) error {
return DefaultAtlas.PurgeMapTile(m, tile)
}
91 changes: 91 additions & 0 deletions atlas/atlas_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package atlas_test

import (
"context"

"github.com/terranodo/tegola"
"github.com/terranodo/tegola/atlas"
"github.com/terranodo/tegola/basic"
"github.com/terranodo/tegola/mvt"
)

type testMVTProvider struct{}

func (tp *testMVTProvider) MVTLayer(ctx context.Context, layerName string, tile tegola.Tile, tags map[string]interface{}) (*mvt.Layer, error) {
var layer mvt.Layer

return &layer, nil
}

func (tp *testMVTProvider) Layers() ([]mvt.LayerInfo, error) {
return []mvt.LayerInfo{
layer{
name: "test-layer",
geomType: basic.Polygon{},
srid: tegola.WebMercator,
},
}, nil
}

var testLayer1 = atlas.Layer{
Name: "test-layer",
ProviderLayerName: "test-layer-1",
MinZoom: 4,
MaxZoom: 9,
Provider: &testMVTProvider{},
GeomType: basic.Point{},
DefaultTags: map[string]interface{}{
"foo": "bar",
},
}

var testLayer2 = atlas.Layer{
Name: "test-layer-2-name",
ProviderLayerName: "test-layer-2-provider-layer-name",
MinZoom: 10,
MaxZoom: 20,
Provider: &testMVTProvider{},
GeomType: basic.Line{},
DefaultTags: map[string]interface{}{
"foo": "bar",
},
}

var testLayer3 = atlas.Layer{
Name: "test-layer",
ProviderLayerName: "test-layer-3",
MinZoom: 10,
MaxZoom: 20,
Provider: &testMVTProvider{},
GeomType: basic.Point{},
DefaultTags: map[string]interface{}{},
}

var testMap = atlas.Map{
Name: "test-map",
Attribution: "test attribution",
Center: [3]float64{1.0, 2.0, 3.0},
Layers: []atlas.Layer{
testLayer1,
testLayer2,
testLayer3,
},
}

type layer struct {
name string
geomType tegola.Geometry
srid int
}

func (l layer) Name() string {
return l.name
}

func (l layer) GeomType() tegola.Geometry {
return l.geomType
}

func (l layer) SRID() int {
return l.srid
}
18 changes: 18 additions & 0 deletions atlas/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package atlas

import (
"errors"
"fmt"
)

var (
ErrMissingCache = errors.New("atlas: missing cache")
)

type ErrMapNotFound struct {
Name string
}

func (e ErrMapNotFound) Error() string {
return fmt.Sprintf("atlas: map (%v) not found", e.Name)
}
4 changes: 3 additions & 1 deletion server/layer.go → atlas/layer.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package server
package atlas

import (
"github.com/terranodo/tegola"
Expand All @@ -16,6 +16,8 @@ type Layer struct {
// default tags to include when encoding the layer. provider tags take precedence
DefaultTags map[string]interface{}
GeomType tegola.Geometry
// if true, ignore the layer when encoding
Disabled bool
}

// MVTName will return the value that will be encoded in the Name field when the layer is encoded as MVT
Expand Down
6 changes: 3 additions & 3 deletions server/layer_test.go → atlas/layer_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package server_test
package atlas_test

import (
"testing"

"github.com/terranodo/tegola/server"
"github.com/terranodo/tegola/atlas"
)

func TestLayerMVTName(t *testing.T) {
testcases := []struct {
layer server.Layer
layer atlas.Layer
expected string
}{
{
Expand Down
Loading

0 comments on commit a7f2e6e

Please sign in to comment.