mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2024-11-17 15:48:17 +01:00
Added naive BigMin interleaved implementation for interleaved spatial query.
This commit is contained in:
parent
0021854000
commit
f7a8c1fdec
@ -21,6 +21,10 @@ type (
|
|||||||
X, Y, Z int16
|
X, Y, Z int16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cuboid struct {
|
||||||
|
P1, P2 Coord
|
||||||
|
}
|
||||||
|
|
||||||
KeyTransformer func(int64) int64
|
KeyTransformer func(int64) int64
|
||||||
KeyEncoder func(int64) ([]byte, error)
|
KeyEncoder func(int64) ([]byte, error)
|
||||||
KeyDecoder func([]byte) (int64, error)
|
KeyDecoder func([]byte) (int64, error)
|
||||||
@ -29,6 +33,12 @@ type (
|
|||||||
KeyJoiner func(Coord) int64
|
KeyJoiner func(Coord) int64
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (cub Cuboid) Contains(c Coord) bool {
|
||||||
|
return c.X >= cub.P1.X && c.X <= cub.P2.X &&
|
||||||
|
c.Y >= cub.P1.Y && c.Y <= cub.P2.Y &&
|
||||||
|
c.Z >= cub.P1.Z && c.Z <= cub.P2.Z
|
||||||
|
}
|
||||||
|
|
||||||
func (c Coord) String() string {
|
func (c Coord) String() string {
|
||||||
return fmt.Sprintf("(%d, %d, %d)", c.X, c.Y, c.Z)
|
return fmt.Sprintf("(%d, %d, %d)", c.X, c.Y, c.Z)
|
||||||
}
|
}
|
||||||
@ -204,3 +214,23 @@ func TranscodeInterleavedToPlain(key []byte) ([]byte, error) {
|
|||||||
return EncodeStringToBytes(TransformInterleavedToPlain(pos))
|
return EncodeStringToBytes(TransformInterleavedToPlain(pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For correctness checks only.
|
||||||
|
func NaiveBigMin(minz, maxz, zcode int64) int64 {
|
||||||
|
c1, c2 := InterleavedToCoord(minz), InterleavedToCoord(maxz)
|
||||||
|
|
||||||
|
cand := minz
|
||||||
|
|
||||||
|
for x := c1.X; x <= c2.X; x++ {
|
||||||
|
for y := c1.Y; y <= c2.Y; y++ {
|
||||||
|
for z := c1.Z; z <= c2.Z; z++ {
|
||||||
|
z := CoordToInterleaved(Coord{X: x, Y: y, Z: z})
|
||||||
|
if z > zcode && z < cand {
|
||||||
|
cand = z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cand
|
||||||
|
}
|
||||||
|
88
sqlite.go
88
sqlite.go
@ -23,7 +23,7 @@ const (
|
|||||||
insertSql = "INSERT INTO blocks (pos, data) VALUES (?, ?)"
|
insertSql = "INSERT INTO blocks (pos, data) VALUES (?, ?)"
|
||||||
countSql = "SELECT count(*) FROM blocks"
|
countSql = "SELECT count(*) FROM blocks"
|
||||||
keysSql = "SELECT pos FROM blocks"
|
keysSql = "SELECT pos FROM blocks"
|
||||||
rangeSql = "SELECT pos, data FROM blocks WHERE pos BETWEEN ? AND ?"
|
rangeSql = "SELECT pos, data FROM blocks WHERE pos BETWEEN ? AND ? ORDER BY pos"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SqliteBackend struct {
|
type SqliteBackend struct {
|
||||||
@ -283,15 +283,13 @@ func (ss *SqliteSession) AllKeys(hash []byte, done chan struct{}) (keys chan []b
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SqliteSession) SpatialQuery(hash, first, second []byte, done chan struct{}) (blocks chan Block, err error) {
|
func (ss *SqliteSession) SpatialQuery(hash, first, second []byte, done chan struct{}) (chan Block, error) {
|
||||||
|
|
||||||
// No implementation for the interleaved case, yet.
|
|
||||||
if ss.backend.interleaved {
|
if ss.backend.interleaved {
|
||||||
err = ErrNotImplemented
|
return ss.interleavedSpatialQuery(first, second, done)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.PlainSpatialQuery(first, second, done)
|
return ss.plainSpatialQuery(first, second, done)
|
||||||
}
|
}
|
||||||
|
|
||||||
func order(a, b int64) (int64, int64) {
|
func order(a, b int64) (int64, int64) {
|
||||||
@ -301,7 +299,79 @@ func order(a, b int64) (int64, int64) {
|
|||||||
return b, a
|
return b, a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SqliteSession) PlainSpatialQuery(first, second []byte, done chan struct{}) (blocks chan Block, err error) {
|
func (ss *SqliteSession) interleavedSpatialQuery(first, second []byte, done chan struct{}) (blocks chan Block, err error) {
|
||||||
|
var (
|
||||||
|
firstKey int64
|
||||||
|
secondKey int64
|
||||||
|
)
|
||||||
|
if firstKey, err = common.DecodeStringFromBytes(first); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if secondKey, err = common.DecodeStringFromBytes(second); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c1 := common.PlainToCoord(firstKey)
|
||||||
|
c2 := common.PlainToCoord(secondKey)
|
||||||
|
c1, c2 = common.MinCoord(c1, c2), common.MaxCoord(c1, c2)
|
||||||
|
|
||||||
|
blocks = make(chan Block)
|
||||||
|
|
||||||
|
globalLock.RLock()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(blocks)
|
||||||
|
defer globalLock.RUnlock()
|
||||||
|
zmin, zmax := common.CoordToInterleaved(c1), common.CoordToInterleaved(c2)
|
||||||
|
// Should not be necessary.
|
||||||
|
zmin, zmax = order(zmin, zmax)
|
||||||
|
cub := common.Cuboid{P1: c1, P2: c2}
|
||||||
|
rangeStmt := ss.txStmt(ss.backend.rangeStmt)
|
||||||
|
OUTER:
|
||||||
|
for {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
rows *sql.Rows
|
||||||
|
)
|
||||||
|
if rows, err = rangeStmt.Query(zmin, zmax); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
var zcode int64
|
||||||
|
var data []byte
|
||||||
|
if err = rows.Scan(&zcode, &data); err != nil {
|
||||||
|
log.Printf("Error in range query: %s", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := common.InterleavedToCoord(zcode)
|
||||||
|
if cub.Contains(c) {
|
||||||
|
var encodedKey []byte
|
||||||
|
if encodedKey, err = common.EncodeStringToBytes(common.CoordToPlain(c)); err != nil {
|
||||||
|
log.Printf("Key encoding failed: %s", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case blocks <- Block{Key: encodedKey, Data: data}:
|
||||||
|
case <-done:
|
||||||
|
rows.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else { // Left the cuboid
|
||||||
|
rows.Close()
|
||||||
|
zmin = common.NaiveBigMin(zmin, zmax, zcode)
|
||||||
|
continue OUTER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = rows.Err(); err != nil {
|
||||||
|
log.Printf("Error in range query: %s", err)
|
||||||
|
}
|
||||||
|
rows.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *SqliteSession) plainSpatialQuery(first, second []byte, done chan struct{}) (blocks chan Block, err error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
firstKey int64
|
firstKey int64
|
||||||
@ -317,10 +387,10 @@ func (ss *SqliteSession) PlainSpatialQuery(first, second []byte, done chan struc
|
|||||||
c2 := common.PlainToCoord(secondKey)
|
c2 := common.PlainToCoord(secondKey)
|
||||||
c1, c2 = common.MinCoord(c1, c2), common.MaxCoord(c1, c2)
|
c1, c2 = common.MinCoord(c1, c2), common.MaxCoord(c1, c2)
|
||||||
|
|
||||||
globalLock.RLock()
|
|
||||||
|
|
||||||
blocks = make(chan Block)
|
blocks = make(chan Block)
|
||||||
|
|
||||||
|
globalLock.RLock()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer globalLock.RUnlock()
|
defer globalLock.RUnlock()
|
||||||
defer close(blocks)
|
defer close(blocks)
|
||||||
|
Loading…
Reference in New Issue
Block a user