Skip to content

Commit

Permalink
feat: zoom filtering added
Browse files Browse the repository at this point in the history
  • Loading branch information
jjcfrancisco committed May 19, 2024
1 parent 1159ce9 commit 1f733f2
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 25 deletions.
23 changes: 20 additions & 3 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package main
import (
"fmt"
"log"
"strconv"

"github.com/urfave/cli/v2"
)

func off(ctx *cli.Context) error {
// MBTiles file path
mbtilesFilepath := ctx.Args().Get(0)
if !fileExists(mbtilesFilepath) {
log.Fatal(fmt.Sprintf("MBTiles file path in %s does not exist.", mbtilesFilepath))
Expand All @@ -17,20 +19,35 @@ func off(ctx *cli.Context) error {
log.Fatal(err)
}
defer conn.db.Close()
// Key Value
rawKeyValue := ctx.Args().Get(1)
keyValue, err := parseKeyValue(rawKeyValue)
if err != nil {
log.Fatal(err)
}
results, err := conn.find(keyValue)
// Zoom Level
strZoomLevel := ctx.Args().Get(2)
var intZoomLevel *int
if strZoomLevel == "" {
intZoomLevel = nil
} else {
num, err := strconv.Atoi(strZoomLevel)
if err != nil {
log.Fatal(err)
}
intZoomLevel = &num
}
// Find feature(s)
results, err := conn.find(keyValue, intZoomLevel)
if err != nil {
log.Fatal(err)
}
if len(results) != 0 {
if err := conn.update(results); err != nil {
// Update feature(s)
if err := conn.update(results, intZoomLevel); err != nil {
log.Fatal(err)
}
fmt.Println(fmt.Sprintf("Successful. The key/value %s was found in %d instance(s). MBTiles updated.", rawKeyValue, len(results)))
fmt.Println(fmt.Sprintf("Successful. The key/value %s was found. MBTiles updated.", rawKeyValue))
} else {
log.Fatal(fmt.Sprintf("The key value %s was not present in the MBTiles file. Nothing was removed.", keyValue))
}
Expand Down
55 changes: 42 additions & 13 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ func createConn(fp string) (*dbConn, error) {
return &dbConn{db: db}, nil
}

func (conn *dbConn) find(keyValue *kv) ([]result, error) {
func (conn *dbConn) find(keyValue *kv, userZoomLevel *int) ([]result, error) {

rows, err := conn.db.Query("SELECT * FROM images;")
rows, err := conn.db.Query("SELECT zoom_level, tile_data, tile_id FROM images;")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -47,18 +47,30 @@ func (conn *dbConn) find(keyValue *kv) ([]result, error) {
for _, f := range layer.Features {
newFeature := geojson.NewFeature(f.Geometry)
newFeature.Properties = f.Properties
// Keep copy of original id
idOg := newFeature.Properties["id"]
newFeature.Properties["id"] = strconv.FormatInt(int64(newFeature.Properties["id"].(float64)), 10)
if newFeature.Properties[keyValue.key] != keyValue.value {
newLayer.Append(newFeature)
if userZoomLevel != nil {
// Zoom level provided
if newFeature.Properties[keyValue.key] != keyValue.value && zoomLevel == *userZoomLevel {
newLayer.Append(newFeature)
}
} else {
// No zoom level provided
if newFeature.Properties[keyValue.key] != keyValue.value {
newLayer.Append(newFeature)
}
}
// Id back to original
newFeature.Properties["id"] = idOg
}
newLayers[i] = newLayer
}
newTileData, err := mvt.MarshalGzipped(mvt.NewLayers(newLayers))
if err != nil {
return nil, err
}
results = append(results, result{zoomLevel: zoomLevel, tileId: tileId, tileData: newTileData})
results = append(results, result{tileId: tileId, tileData: newTileData})
}
err = rows.Err()
if err != nil {
Expand All @@ -69,19 +81,36 @@ func (conn *dbConn) find(keyValue *kv) ([]result, error) {

}

func (conn *dbConn) update(results []result) error {
func (conn *dbConn) update(results []result, userZoomLevel *int) error {

stmt, err := conn.db.Prepare("UPDATE images SET tile_data = ? WHERE tile_id = ? AND zoom_level = ?;")
if err != nil {
return err
}
defer stmt.Close()
if userZoomLevel != nil {
// Zoom level provided
stmt, err := conn.db.Prepare("UPDATE images SET tile_data = ? WHERE tile_id = ? AND zoom_level = ?;")
if err != nil {
return err
}
defer stmt.Close()

for _, result := range results {
_, err = stmt.Exec(result.tileData, result.tileId, result.zoomLevel)
for _, result := range results {
_, err = stmt.Exec(result.tileData, result.tileId, userZoomLevel)
if err != nil {
return err
}
}
} else {
// No zoom level provided
stmt, err := conn.db.Prepare("UPDATE images SET tile_data = ? WHERE tile_id = ?;")
if err != nil {
return err
}
defer stmt.Close()

for _, result := range results {
_, err = stmt.Exec(result.tileData, result.tileId)
if err != nil {
return err
}
}
}

return nil
Expand Down
65 changes: 56 additions & 9 deletions db_test.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,71 @@
package main

import (
"fmt"
"strconv"
"testing"

"github.com/paulmach/orb/encoding/mvt"
"github.com/paulmach/orb/geojson"
"github.com/stretchr/testify/assert"
)

func testCreateConn(t *testing.T) {
_, err := createConn("./tests/example.mbtiles")
func TestCreateConn(t *testing.T) {
_, err := createConn("tests/example.mbtiles")
assert.NoError(t, err)
}

func testFind(t *testing.T) {
conn, err := createConn("./tests/example.mbtiles")
func TestFind(t *testing.T) {
conn, err := createConn("tests/example.mbtiles")
assert.NoError(t, err)
results, err := conn.find(&kv{key: "ROUTE_NO", value: "137"})
assert.NoError(t, err)
assert.Equal(t, len(results), 1)
defer conn.db.Close()
// results, err := conn.find(&kv{key: "ROUTE_NO", value: "137"}, nil)
// assert.NoError(t, err)
// assert.Equal(t, len(results), 1)
}

func testUpdate(t *testing.T) {
// Not implemented yet
func TestUpdate(t *testing.T) {

conn, err := createConn("tests/example.mbtiles")
assert.NoError(t, err)
defer conn.db.Close()

// Check
rows, err := conn.db.Query("SELECT zoom_level, tile_data, tile_id FROM images;")
if err != nil {
panic(err)
}
for rows.Next() {
var zoomLevel int
var tileData []byte
var tileId string
err = rows.Scan(&zoomLevel, &tileData, &tileId)
if err != nil {
panic(err)
}
l, err := mvt.UnmarshalGzipped(tileData)
if err != nil {
panic(err)
}
layers := l.ToFeatureCollections()
for i := range layers {
layer := layers[i]
for _, f := range layer.Features {
newFeature := geojson.NewFeature(f.Geometry)
newFeature.Properties = f.Properties
id := int(newFeature.Properties["id"].(float64))
newFeature.Properties["id"] = strconv.Itoa(id)
if newFeature.Properties["id"] == "506484968" {
fmt.Println("Present!", zoomLevel, tileId)
}
}
}
}
err = rows.Err()
if err != nil {
panic(err)
}

assert.NoError(t, err)

}
Binary file modified tests/example.mbtiles
Binary file not shown.

0 comments on commit 1f733f2

Please sign in to comment.