forked from MTSR/mapserver
working tile stitching
This commit is contained in:
parent
abbf16b4bd
commit
acd2e0c8d0
@ -14,4 +14,5 @@ type DBAccessor interface {
|
||||
Migrate() error
|
||||
GetTile(pos coords.TileCoords) (*Tile, error)
|
||||
SetTile(tile *Tile) error
|
||||
RemoveTile(pos coords.TileCoords) error
|
||||
}
|
||||
|
@ -90,6 +90,17 @@ func (db *Sqlite3Accessor) SetTile(tile *Tile) error {
|
||||
return err
|
||||
}
|
||||
|
||||
const removeTileQuery = `
|
||||
delete from tiles
|
||||
where x = ? and y = ? and zoom = ? and layerid = ?
|
||||
`
|
||||
|
||||
func (db *Sqlite3Accessor) RemoveTile(pos coords.TileCoords) error {
|
||||
_, err := db.db.Exec(removeTileQuery, pos.X, pos.Y, pos.Zoom, pos.LayerId)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
func NewSqliteAccessor(filename string) (*Sqlite3Accessor, error) {
|
||||
db, err := sql.Open("sqlite3", filename)
|
||||
if err != nil {
|
||||
|
@ -1,29 +1,147 @@
|
||||
package tilerenderer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"bytes"
|
||||
"image/png"
|
||||
"image/draw"
|
||||
"mapserver/coords"
|
||||
"mapserver/mapblockrenderer"
|
||||
"mapserver/layerconfig"
|
||||
"mapserver/tiledb"
|
||||
)
|
||||
|
||||
type TileRenderer struct {
|
||||
mapblockrenderer *mapblockrenderer.MapBlockRenderer
|
||||
layers []layerconfig.Layer
|
||||
tdb tiledb.DBAccessor
|
||||
}
|
||||
|
||||
func NewTileRenderer(mapblockrenderer *mapblockrenderer.MapBlockRenderer) *TileRenderer {
|
||||
func NewTileRenderer(mapblockrenderer *mapblockrenderer.MapBlockRenderer,
|
||||
tdb tiledb.DBAccessor,
|
||||
layers []layerconfig.Layer) *TileRenderer {
|
||||
|
||||
return &TileRenderer{
|
||||
mapblockrenderer: mapblockrenderer,
|
||||
layers: layers,
|
||||
tdb: tdb,
|
||||
}
|
||||
}
|
||||
|
||||
//TODO layerConfig
|
||||
func (tr *TileRenderer) Render(tc coords.TileCoords) (*image.NRGBA, error) {
|
||||
const (
|
||||
IMG_SIZE = 256
|
||||
)
|
||||
|
||||
func (tr *TileRenderer) Render(tc coords.TileCoords) ([]byte, error) {
|
||||
|
||||
//Check cache
|
||||
tile, err := tr.tdb.GetTile(tc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tile == nil {
|
||||
//No tile in db
|
||||
img, err := tr.RenderImage(tc)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
png.Encode(buf, img)
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
return tile.Data, nil
|
||||
}
|
||||
|
||||
func (tr *TileRenderer) RenderImage(tc coords.TileCoords) (*image.NRGBA, error) {
|
||||
|
||||
cachedtile, err := tr.tdb.GetTile(tc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cachedtile != nil {
|
||||
reader := bytes.NewReader(cachedtile.Data)
|
||||
cachedimg, err := png.Decode(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cachedimg.(*image.NRGBA), nil
|
||||
}
|
||||
|
||||
var layer *layerconfig.Layer
|
||||
|
||||
for _, l := range(tr.layers) {
|
||||
if l.Id == tc.LayerId {
|
||||
layer = &l
|
||||
}
|
||||
}
|
||||
|
||||
if layer == nil {
|
||||
return nil, errors.New("No layer found")
|
||||
}
|
||||
|
||||
if tc.Zoom == 13 {
|
||||
//max zoomed in on mapblock level
|
||||
//mbr := coords.GetMapBlockRangeFromTile(tc, 0)
|
||||
//return tr.mapblockrenderer.Render()
|
||||
mbr := coords.GetMapBlockRangeFromTile(tc, 0)
|
||||
mbr.Pos1.Y = layer.From
|
||||
mbr.Pos2.Y = layer.To
|
||||
|
||||
return tr.mapblockrenderer.Render(mbr.Pos1, mbr.Pos2)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
if tc.Zoom > 13 || tc.Zoom < 1 {
|
||||
return nil, errors.New("Invalid zoom")
|
||||
}
|
||||
|
||||
//zoom 1-12
|
||||
quads := tc.GetZoomedQuadrantsFromTile()
|
||||
|
||||
upperLeft, err := tr.RenderImage(quads.UpperLeft)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
upperRight, err := tr.RenderImage(quads.UpperRight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lowerLeft, err := tr.RenderImage(quads.LowerLeft)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lowerRight, err := tr.RenderImage(quads.LowerRight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img := image.NewNRGBA(
|
||||
image.Rectangle{
|
||||
image.Point{0, 0},
|
||||
image.Point{IMG_SIZE, IMG_SIZE},
|
||||
},
|
||||
)
|
||||
|
||||
rect := image.Rect(0, 0, 128, 128)
|
||||
draw.Draw(img, rect, upperLeft, image.ZP, draw.Src)
|
||||
|
||||
rect = image.Rect(128, 0, 256, 128)
|
||||
draw.Draw(img, rect, upperRight, image.ZP, draw.Src)
|
||||
|
||||
rect = image.Rect(0, 128, 128, 256)
|
||||
draw.Draw(img, rect, lowerLeft, image.ZP, draw.Src)
|
||||
|
||||
rect = image.Rect(128, 128, 256, 256)
|
||||
draw.Draw(img, rect, lowerRight, image.ZP, draw.Src)
|
||||
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
@ -9,8 +9,11 @@ import (
|
||||
"mapserver/testutils"
|
||||
"mapserver/mapblockrenderer"
|
||||
"mapserver/coords"
|
||||
"mapserver/layerconfig"
|
||||
"mapserver/tiledb"
|
||||
"os"
|
||||
"testing"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
func TestTileRender(t *testing.T) {
|
||||
@ -20,6 +23,7 @@ func TestTileRender(t *testing.T) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer os.Remove(tmpfile.Name())
|
||||
testutils.CreateTestDatabase(tmpfile.Name())
|
||||
|
||||
@ -42,7 +46,13 @@ func TestTileRender(t *testing.T) {
|
||||
|
||||
r := mapblockrenderer.NewMapBlockRenderer(cache, c)
|
||||
|
||||
tr := NewTileRenderer(r)
|
||||
tiletmpfile, err := ioutil.TempFile("", "TestTileRenderTiles.*.sqlite")
|
||||
defer os.Remove(tiletmpfile.Name())
|
||||
|
||||
tdb, _ := tiledb.NewSqliteAccessor(tiletmpfile.Name())
|
||||
tdb.Migrate()
|
||||
|
||||
tr := NewTileRenderer(r, tdb, layerconfig.DefaultLayers)
|
||||
|
||||
if tr == nil {
|
||||
panic("no renderer")
|
||||
@ -59,4 +69,7 @@ func TestTileRender(t *testing.T) {
|
||||
if data == nil {
|
||||
panic("no data")
|
||||
}
|
||||
|
||||
f, _ := os.Create("../output/0_0_12.png")
|
||||
bytes.NewReader(data).WriteTo(f)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user