1
0
forked from MTSR/mapserver

working initial rendering

This commit is contained in:
NatureFreshMilk 2019-01-21 13:27:36 +01:00
parent 3b2741f390
commit 3bb9d97e06
9 changed files with 137 additions and 72 deletions

View File

@ -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))

View File

@ -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")

View File

@ -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,

View File

@ -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")
} }

View File

@ -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()

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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},