mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2025-06-28 06:12:08 +02:00
mtwebmapper: First version of pyramid tile updater. Needs testing.
This commit is contained in:
@ -6,11 +6,17 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/draw"
|
||||
"log"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/nfnt/resize"
|
||||
|
||||
"bitbucket.org/s_l_teichmann/mtredisalize/common"
|
||||
)
|
||||
|
||||
@ -47,7 +53,16 @@ func (c xz) parent() xzm {
|
||||
zp, zr := c.Z>>1, uint16(c.Z&1)
|
||||
return xzm{
|
||||
P: xz{X: xp, Z: zp},
|
||||
Mask: ((1 << xr) << 2) | (1 << zr)}
|
||||
Mask: 1 << (xr<<1 | zr)}
|
||||
}
|
||||
|
||||
func (c xzm) numChanges() (n int) {
|
||||
for i := uint16(0); i < 4; i++ {
|
||||
if c.Mask&(1<<i) != 0 {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func newTileUpdater(mapDir, redisAddress string, colors *common.Colors, workers int) *tileUpdater {
|
||||
@ -151,11 +166,75 @@ func min(a, b int) int {
|
||||
|
||||
func updatePyramidTiles(level int, baseDir string, jobs chan xzm, done *sync.WaitGroup) {
|
||||
defer done.Done()
|
||||
scratch := image.NewRGBA(image.Rect(0, 0, 256, 256))
|
||||
|
||||
for job := range jobs {
|
||||
_ = job
|
||||
if err := updatePyramidTile(scratch, level, baseDir, job); err != nil {
|
||||
log.Printf("Updating pyramid tile failed: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dps = [4]image.Point{
|
||||
image.Pt(0, 128),
|
||||
image.Pt(0, 0),
|
||||
image.Pt(128, 128),
|
||||
image.Pt(128, 0)}
|
||||
|
||||
var ofs = [4][2]int{
|
||||
{0, 0},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}}
|
||||
|
||||
func clip8(x int) int {
|
||||
switch {
|
||||
case x < 0:
|
||||
return 0
|
||||
case x > 256:
|
||||
return 256
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func clipRect(r image.Rectangle) image.Rectangle {
|
||||
return image.Rectangle{
|
||||
Min: image.Point{X: clip8(r.Min.X), Y: clip8(r.Min.Y)},
|
||||
Max: image.Point{X: clip8(r.Max.X), Y: clip8(r.Max.Y)}}
|
||||
}
|
||||
|
||||
func updatePyramidTile(scratch *image.RGBA, level int, baseDir string, j xzm) error {
|
||||
|
||||
var orig image.Image
|
||||
|
||||
origPath := filepath.Join(
|
||||
baseDir, strconv.Itoa(level), strconv.Itoa(int(j.P.X)), fmt.Sprintf("%d.png", j.P.Z))
|
||||
|
||||
if j.numChanges() < 4 {
|
||||
orig = common.LoadPNG(origPath)
|
||||
}
|
||||
|
||||
for i := uint16(0); i < 4; i++ {
|
||||
if j.Mask&(1<<i) != 0 {
|
||||
o := ofs[i]
|
||||
bx, bz := int(2*j.P.X), int(2*j.P.Z)
|
||||
path := filepath.Join(
|
||||
baseDir, strconv.Itoa(level+1), strconv.Itoa(bx+o[0]), fmt.Sprintf("%d.png", bz+o[1]))
|
||||
img := common.LoadPNG(path)
|
||||
img = resize.Resize(128, 128, img, resize.Lanczos3)
|
||||
sr := img.Bounds()
|
||||
r := sr.Sub(sr.Min).Add(dps[i])
|
||||
draw.Draw(scratch, r, img, sr.Min, draw.Src)
|
||||
} else {
|
||||
sr := clipRect(orig.Bounds())
|
||||
r := sr.Sub(sr.Min).Add(dps[i])
|
||||
draw.Draw(scratch, r, orig, sr.Min, draw.Src)
|
||||
}
|
||||
}
|
||||
|
||||
return common.SaveAsPNGAtomic(origPath, scratch)
|
||||
}
|
||||
|
||||
func updateBaseTiles(jobs chan xz, btc *common.BaseTileCreator, done *sync.WaitGroup) {
|
||||
defer btc.Close()
|
||||
defer done.Done()
|
||||
|
Reference in New Issue
Block a user