forked from MTSR/mapserver
working initial rendering
This commit is contained in:
parent
3b2741f390
commit
3bb9d97e06
@ -2,17 +2,33 @@ package coords
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
"mapserver/layer"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MAX_ZOOM = 13
|
MAX_ZOOM = 13
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetTileCoordsFromMapBlock(mbc MapBlockCoords) TileCoords {
|
func GetTileCoordsFromMapBlock(mbc MapBlockCoords, layers []layer.Layer) *TileCoords {
|
||||||
return TileCoords{X: mbc.X, Y: (mbc.Z + 1) * -1, Zoom: MAX_ZOOM}
|
tc := TileCoords{X: mbc.X, Y: (mbc.Z + 1) * -1, Zoom: MAX_ZOOM}
|
||||||
|
|
||||||
|
var layerid *int
|
||||||
|
for _, l := range layers {
|
||||||
|
if mbc.Y > l.From && mbc.Y < l.To {
|
||||||
|
layerid = &l.Id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if layerid == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tc.LayerId = *layerid
|
||||||
|
|
||||||
|
return &tc
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMapBlockRangeFromTile(tc TileCoords, y int) MapBlockRange {
|
func GetMapBlockRangeFromTile(tc *TileCoords, y int) MapBlockRange {
|
||||||
scaleDiff := float64(MAX_ZOOM - tc.Zoom)
|
scaleDiff := float64(MAX_ZOOM - tc.Zoom)
|
||||||
scale := int(math.Pow(2, scaleDiff))
|
scale := int(math.Pow(2, scaleDiff))
|
||||||
|
|
||||||
|
@ -2,13 +2,22 @@ package coords
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"mapserver/layer"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConvertMapblockToTile1(t *testing.T) {
|
func TestConvertMapblockToTile1(t *testing.T) {
|
||||||
mbc := NewMapBlockCoords(0, 0, 0)
|
mbc := NewMapBlockCoords(0, 0, 0)
|
||||||
tc := GetTileCoordsFromMapBlock(mbc)
|
layers := []layer.Layer{
|
||||||
|
layer.Layer{
|
||||||
|
Id: 0,
|
||||||
|
Name: "Base",
|
||||||
|
From: -16,
|
||||||
|
To: 160,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tc := GetTileCoordsFromMapBlock(mbc, layers)
|
||||||
|
|
||||||
if tc.X != 0 {
|
if tc.X != 0 {
|
||||||
t.Fatal("x does not match")
|
t.Fatal("x does not match")
|
||||||
@ -39,7 +48,16 @@ func TestGetMapBlockRangeFromTile(t *testing.T) {
|
|||||||
|
|
||||||
func TestConvertMapblockToTile2(t *testing.T) {
|
func TestConvertMapblockToTile2(t *testing.T) {
|
||||||
mbc := NewMapBlockCoords(1, 0, 1)
|
mbc := NewMapBlockCoords(1, 0, 1)
|
||||||
tc := GetTileCoordsFromMapBlock(mbc)
|
layers := []layer.Layer{
|
||||||
|
layer.Layer{
|
||||||
|
Id: 0,
|
||||||
|
Name: "Base",
|
||||||
|
From: -16,
|
||||||
|
To: 160,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tc := GetTileCoordsFromMapBlock(mbc, layers)
|
||||||
|
|
||||||
if tc.X != 1 {
|
if tc.X != 1 {
|
||||||
t.Fatal("x does not match")
|
t.Fatal("x does not match")
|
||||||
@ -56,7 +74,16 @@ func TestConvertMapblockToTile2(t *testing.T) {
|
|||||||
|
|
||||||
func TestConvertMapblockToTile3(t *testing.T) {
|
func TestConvertMapblockToTile3(t *testing.T) {
|
||||||
mbc := NewMapBlockCoords(-1, 0, -1)
|
mbc := NewMapBlockCoords(-1, 0, -1)
|
||||||
tc := GetTileCoordsFromMapBlock(mbc)
|
layers := []layer.Layer{
|
||||||
|
layer.Layer{
|
||||||
|
Id: 0,
|
||||||
|
Name: "Base",
|
||||||
|
From: -16,
|
||||||
|
To: 160,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tc := GetTileCoordsFromMapBlock(mbc, layers)
|
||||||
|
|
||||||
if tc.X != -1 {
|
if tc.X != -1 {
|
||||||
t.Fatal("x does not match")
|
t.Fatal("x does not match")
|
||||||
|
@ -11,31 +11,31 @@ type TileCoords struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TileQuadrants struct {
|
type TileQuadrants struct {
|
||||||
UpperLeft, UpperRight, LowerLeft, LowerRight TileCoords
|
UpperLeft, UpperRight, LowerLeft, LowerRight *TileCoords
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTileCoords(x, y, zoom int, layerId int) TileCoords {
|
func NewTileCoords(x, y, zoom int, layerId int) *TileCoords {
|
||||||
return TileCoords{X: x, Y: y, Zoom: zoom, LayerId: layerId}
|
return &TileCoords{X: x, Y: y, Zoom: zoom, LayerId: layerId}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc TileCoords) GetZoomedOutTile() TileCoords {
|
func (tc *TileCoords) GetZoomedOutTile() *TileCoords {
|
||||||
return TileCoords{
|
return &TileCoords{
|
||||||
X: int(math.Floor(float64(tc.X) / 2.0)),
|
X: int(math.Floor(float64(tc.X) / 2.0)),
|
||||||
Y: int(math.Floor(float64(tc.Y) / 2.0)),
|
Y: int(math.Floor(float64(tc.Y) / 2.0)),
|
||||||
Zoom: tc.Zoom - 1,
|
Zoom: tc.Zoom - 1,
|
||||||
LayerId: tc.LayerId}
|
LayerId: tc.LayerId}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc TileCoords) GetZoomedQuadrantsFromTile() TileQuadrants {
|
func (tc *TileCoords) GetZoomedQuadrantsFromTile() TileQuadrants {
|
||||||
nextZoom := tc.Zoom + 1
|
nextZoom := tc.Zoom + 1
|
||||||
|
|
||||||
nextZoomX := tc.X * 2
|
nextZoomX := tc.X * 2
|
||||||
nextZoomY := tc.Y * 2
|
nextZoomY := tc.Y * 2
|
||||||
|
|
||||||
upperLeft := TileCoords{X: nextZoomX, Y: nextZoomY, Zoom: nextZoom, LayerId: tc.LayerId}
|
upperLeft := &TileCoords{X: nextZoomX, Y: nextZoomY, Zoom: nextZoom, LayerId: tc.LayerId}
|
||||||
upperRight := TileCoords{X: nextZoomX + 1, Y: nextZoomY, Zoom: nextZoom, LayerId: tc.LayerId}
|
upperRight := &TileCoords{X: nextZoomX + 1, Y: nextZoomY, Zoom: nextZoom, LayerId: tc.LayerId}
|
||||||
lowerLeft := TileCoords{X: nextZoomX, Y: nextZoomY + 1, Zoom: nextZoom, LayerId: tc.LayerId}
|
lowerLeft := &TileCoords{X: nextZoomX, Y: nextZoomY + 1, Zoom: nextZoom, LayerId: tc.LayerId}
|
||||||
lowerRight := TileCoords{X: nextZoomX + 1, Y: nextZoomY + 1, Zoom: nextZoom, LayerId: tc.LayerId}
|
lowerRight := &TileCoords{X: nextZoomX + 1, Y: nextZoomY + 1, Zoom: nextZoom, LayerId: tc.LayerId}
|
||||||
|
|
||||||
return TileQuadrants{
|
return TileQuadrants{
|
||||||
UpperLeft: upperLeft,
|
UpperLeft: upperLeft,
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"mapserver/app"
|
"mapserver/app"
|
||||||
"mapserver/coords"
|
"mapserver/coords"
|
||||||
|
"mapserver/mapblockparser"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Job(ctx *app.App) {
|
func Job(ctx *app.App) {
|
||||||
@ -32,12 +33,43 @@ func Job(ctx *app.App) {
|
|||||||
|
|
||||||
lastcoords = *newlastcoords
|
lastcoords = *newlastcoords
|
||||||
|
|
||||||
for _, mb := range mblist {
|
//only mapblocks with valid layer
|
||||||
tc := coords.GetTileCoordsFromMapBlock(mb.Pos)
|
validmblist := make([]*mapblockparser.MapBlock, 0)
|
||||||
|
|
||||||
_, err = ctx.Tilerenderer.Render(tc)
|
//Invalidate zoom 12-1
|
||||||
if err != nil {
|
for _, mb := range mblist {
|
||||||
panic(err)
|
tc := coords.GetTileCoordsFromMapBlock(mb.Pos, ctx.Config.Layers)
|
||||||
|
|
||||||
|
if tc == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
validmblist = append(validmblist, mb)
|
||||||
|
|
||||||
|
for tc.Zoom > 1 {
|
||||||
|
tc = tc.GetZoomedOutTile()
|
||||||
|
ctx.Tiledb.RemoveTile(tc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Render zoom 12-1
|
||||||
|
for _, mb := range validmblist {
|
||||||
|
tc := coords.GetTileCoordsFromMapBlock(mb.Pos, ctx.Config.Layers)
|
||||||
|
for tc.Zoom > 1 {
|
||||||
|
tc = tc.GetZoomedOutTile()
|
||||||
|
|
||||||
|
fields = logrus.Fields{
|
||||||
|
"X": tc.X,
|
||||||
|
"Y": tc.Y,
|
||||||
|
"Zoom": tc.Zoom,
|
||||||
|
"LayerId": tc.LayerId,
|
||||||
|
}
|
||||||
|
logrus.WithFields(fields).Debug("Dispatching tile rendering")
|
||||||
|
|
||||||
|
_, err = ctx.Tilerenderer.Render(tc)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +84,7 @@ func Job(ctx *app.App) {
|
|||||||
"X": lastcoords.X,
|
"X": lastcoords.X,
|
||||||
"Y": lastcoords.Y,
|
"Y": lastcoords.Y,
|
||||||
"Z": lastcoords.Z,
|
"Z": lastcoords.Z,
|
||||||
|
"validcount": len(validmblist),
|
||||||
}
|
}
|
||||||
logrus.WithFields(fields).Info("Initial rendering")
|
logrus.WithFields(fields).Info("Initial rendering")
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"mapserver/db"
|
"mapserver/db"
|
||||||
"mapserver/mapblockaccessor"
|
"mapserver/mapblockaccessor"
|
||||||
"mapserver/testutils"
|
"mapserver/testutils"
|
||||||
|
"mapserver/layer"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -16,6 +17,15 @@ import (
|
|||||||
func TestSimpleRender(t *testing.T) {
|
func TestSimpleRender(t *testing.T) {
|
||||||
logrus.SetLevel(logrus.InfoLevel)
|
logrus.SetLevel(logrus.InfoLevel)
|
||||||
|
|
||||||
|
layers := []layer.Layer{
|
||||||
|
layer.Layer{
|
||||||
|
Id: 0,
|
||||||
|
Name: "Base",
|
||||||
|
From: -16,
|
||||||
|
To: 160,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
tmpfile, err := ioutil.TempFile("", "TestMigrate.*.sqlite")
|
tmpfile, err := ioutil.TempFile("", "TestMigrate.*.sqlite")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -56,7 +66,7 @@ func TestSimpleRender(t *testing.T) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
tc := coords.GetTileCoordsFromMapBlock(result.Job.Pos1)
|
tc := coords.GetTileCoordsFromMapBlock(result.Job.Pos1, layers)
|
||||||
f, _ := os.Create(fmt.Sprintf("../output/image_%d_%d.png", tc.X, tc.Y))
|
f, _ := os.Create(fmt.Sprintf("../output/image_%d_%d.png", tc.X, tc.Y))
|
||||||
result.Data.WriteTo(f)
|
result.Data.WriteTo(f)
|
||||||
f.Close()
|
f.Close()
|
||||||
|
@ -5,14 +5,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Tile struct {
|
type Tile struct {
|
||||||
Pos coords.TileCoords
|
Pos *coords.TileCoords
|
||||||
Data []byte
|
Data []byte
|
||||||
Mtime int64
|
Mtime int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type DBAccessor interface {
|
type DBAccessor interface {
|
||||||
Migrate() error
|
Migrate() error
|
||||||
GetTile(pos coords.TileCoords) (*Tile, error)
|
GetTile(pos *coords.TileCoords) (*Tile, error)
|
||||||
SetTile(tile *Tile) error
|
SetTile(tile *Tile) error
|
||||||
RemoveTile(pos coords.TileCoords) error
|
RemoveTile(pos *coords.TileCoords) error
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ and t.y = ?
|
|||||||
and t.zoom = ?
|
and t.zoom = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
func (db *Sqlite3Accessor) GetTile(pos coords.TileCoords) (*Tile, error) {
|
func (db *Sqlite3Accessor) GetTile(pos *coords.TileCoords) (*Tile, error) {
|
||||||
rows, err := db.db.Query(getTileQuery, pos.LayerId, pos.X, pos.Y, pos.Zoom)
|
rows, err := db.db.Query(getTileQuery, pos.LayerId, pos.X, pos.Y, pos.Zoom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -95,7 +95,7 @@ delete from tiles
|
|||||||
where x = ? and y = ? and zoom = ? and layerid = ?
|
where x = ? and y = ? and zoom = ? and layerid = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
func (db *Sqlite3Accessor) RemoveTile(pos coords.TileCoords) error {
|
func (db *Sqlite3Accessor) RemoveTile(pos *coords.TileCoords) error {
|
||||||
_, err := db.db.Exec(removeTileQuery, pos.X, pos.Y, pos.Zoom, pos.LayerId)
|
_, err := db.db.Exec(removeTileQuery, pos.X, pos.Y, pos.Zoom, pos.LayerId)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ const (
|
|||||||
IMG_SIZE = 256
|
IMG_SIZE = 256
|
||||||
)
|
)
|
||||||
|
|
||||||
func (tr *TileRenderer) Render(tc coords.TileCoords) ([]byte, error) {
|
func (tr *TileRenderer) Render(tc *coords.TileCoords) ([]byte, error) {
|
||||||
|
|
||||||
//Check cache
|
//Check cache
|
||||||
tile, err := tr.tdb.GetTile(tc)
|
tile, err := tr.tdb.GetTile(tc)
|
||||||
@ -51,7 +51,7 @@ func (tr *TileRenderer) Render(tc coords.TileCoords) ([]byte, error) {
|
|||||||
|
|
||||||
if tile == nil {
|
if tile == nil {
|
||||||
//No tile in db
|
//No tile in db
|
||||||
img, err := tr.RenderImage(tc)
|
img, err := tr.RenderImage(tc, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -71,7 +71,7 @@ func (tr *TileRenderer) Render(tc coords.TileCoords) ([]byte, error) {
|
|||||||
return tile.Data, nil
|
return tile.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *TileRenderer) RenderImage(tc coords.TileCoords) (*image.NRGBA, error) {
|
func (tr *TileRenderer) RenderImage(tc *coords.TileCoords, cachedOnly bool) (*image.NRGBA, error) {
|
||||||
|
|
||||||
cachedtile, err := tr.tdb.GetTile(tc)
|
cachedtile, err := tr.tdb.GetTile(tc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -85,7 +85,19 @@ func (tr *TileRenderer) RenderImage(tc coords.TileCoords) (*image.NRGBA, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cachedimg.(*image.NRGBA), nil
|
rect := image.Rectangle{
|
||||||
|
image.Point{0, 0},
|
||||||
|
image.Point{IMG_SIZE, IMG_SIZE},
|
||||||
|
}
|
||||||
|
|
||||||
|
img := image.NewNRGBA(rect)
|
||||||
|
draw.Draw(img, rect, cachedimg, image.ZP, draw.Src)
|
||||||
|
|
||||||
|
return img, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if cachedOnly {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(logrus.Fields{"x": tc.X, "y": tc.Y, "zoom": tc.Zoom}).Debug("RenderImage")
|
log.WithFields(logrus.Fields{"x": tc.X, "y": tc.Y, "zoom": tc.Zoom}).Debug("RenderImage")
|
||||||
@ -112,67 +124,34 @@ func (tr *TileRenderer) RenderImage(tc coords.TileCoords) (*image.NRGBA, error)
|
|||||||
mbr.Pos1.Y = layer.From
|
mbr.Pos1.Y = layer.From
|
||||||
mbr.Pos2.Y = layer.To
|
mbr.Pos2.Y = layer.To
|
||||||
|
|
||||||
//count blocks
|
|
||||||
count, err := tr.dba.CountBlocks(mbr.Pos1, mbr.Pos2)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if count == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return tr.mapblockrenderer.Render(mbr.Pos1, mbr.Pos2)
|
return tr.mapblockrenderer.Render(mbr.Pos1, mbr.Pos2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tc.Zoom == 12 {
|
|
||||||
//count blocks and ignore empty tiles
|
|
||||||
mbr := coords.GetMapBlockRangeFromTile(tc, 0)
|
|
||||||
mbr.Pos1.Y = layer.From
|
|
||||||
mbr.Pos2.Y = layer.To
|
|
||||||
|
|
||||||
count, err := tr.dba.CountBlocks(mbr.Pos1, mbr.Pos2)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if count == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//zoom 1-12
|
//zoom 1-12
|
||||||
quads := tc.GetZoomedQuadrantsFromTile()
|
quads := tc.GetZoomedQuadrantsFromTile()
|
||||||
|
|
||||||
upperLeft, err := tr.RenderImage(quads.UpperLeft)
|
recursiveCachedOnly := tc.Zoom < 12
|
||||||
|
|
||||||
|
upperLeft, err := tr.RenderImage(quads.UpperLeft, recursiveCachedOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
upperRight, err := tr.RenderImage(quads.UpperRight)
|
upperRight, err := tr.RenderImage(quads.UpperRight, recursiveCachedOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lowerLeft, err := tr.RenderImage(quads.LowerLeft)
|
lowerLeft, err := tr.RenderImage(quads.LowerLeft, recursiveCachedOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lowerRight, err := tr.RenderImage(quads.LowerRight)
|
lowerRight, err := tr.RenderImage(quads.LowerRight, recursiveCachedOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
isEmpty := upperLeft == nil && upperRight == nil && lowerLeft == nil && lowerRight == nil
|
|
||||||
|
|
||||||
if isEmpty && (tc.Zoom == 11 || tc.Zoom == 10) {
|
|
||||||
//don't cache empty zoomed tiles
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
img := image.NewNRGBA(
|
img := image.NewNRGBA(
|
||||||
image.Rectangle{
|
image.Rectangle{
|
||||||
image.Point{0, 0},
|
image.Point{0, 0},
|
||||||
|
@ -41,7 +41,7 @@ func (t *Tiles) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
resp.Write(tile.Data)
|
resp.Write(tile.Data)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user