Skip to content

Commit

Permalink
converter: don't rely on minzoom/maxzoom from metadata, use entries [#25
Browse files Browse the repository at this point in the history
]
  • Loading branch information
bdon committed Oct 24, 2022
1 parent 2c7f833 commit 00357bd
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 109 deletions.
62 changes: 15 additions & 47 deletions pmtiles/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@ func add_directoryv2_entries(dir DirectoryV2, entries *[]EntryV3, f *os.File) {
}
}

func set_zoom_center_defaults(header *HeaderV3, entries []EntryV3) {
min_z, _, _ := IdToZxy(entries[0].TileId)
header.MinZoom = min_z
max_z, _, _ := IdToZxy(entries[len(entries)-1].TileId)
header.MaxZoom = max_z

if header.CenterZoom == 0 && header.CenterLonE7 == 0 && header.CenterLatE7 == 0 {
header.CenterZoom = header.MinZoom
header.CenterLonE7 = (header.MinLonE7 + header.MaxLonE7) / 2
header.CenterLatE7 = (header.MinLatE7 + header.MaxLatE7) / 2
}
}

func ConvertPmtilesV2(logger *log.Logger, input string, output string) error {
start := time.Now()
f, err := os.Open(input)
Expand Down Expand Up @@ -362,6 +375,8 @@ func finalize(logger *log.Logger, resolver *Resolver, header HeaderV3, tmpfile *
metadata_bytes = b.Bytes()
}

set_zoom_center_defaults(&header, resolver.Entries)

header.Clustered = true
header.InternalCompression = Gzip
header.TileCompression = Gzip
Expand Down Expand Up @@ -392,37 +407,7 @@ func finalize(logger *log.Logger, resolver *Resolver, header HeaderV3, tmpfile *

func v2_to_header_json(v2_json_metadata map[string]interface{}, first4 []byte) (HeaderV3, map[string]interface{}, error) {
header := HeaderV3{}
if val, ok := v2_json_metadata["minzoom"]; ok {
switch v := val.(type) {
case int:
header.MinZoom = uint8(v)
case string:
i, err := strconv.ParseInt(v, 10, 8)
if err != nil {
return header, v2_json_metadata, err
}
header.MinZoom = uint8(i)
default:
return header, v2_json_metadata, errors.New("Can't parse minzoom")
}
delete(v2_json_metadata, "minzoom")
}
if val, ok := v2_json_metadata["maxzoom"]; ok {
switch v := val.(type) {
case int:
header.MaxZoom = uint8(v)
case string:
i, err := strconv.ParseInt(v, 10, 8)
if err != nil {
return header, v2_json_metadata, err
}
header.MaxZoom = uint8(i)
default:
return header, v2_json_metadata, errors.New("Can't parse minzoom")
}

delete(v2_json_metadata, "maxzoom")
}
if val, ok := v2_json_metadata["bounds"]; ok {
min_lon, min_lat, max_lon, max_lat, err := parse_bounds(val.(string))
if err != nil {
Expand All @@ -446,10 +431,6 @@ func v2_to_header_json(v2_json_metadata map[string]interface{}, first4 []byte) (
header.CenterLatE7 = center_lat
header.CenterZoom = center_zoom
delete(v2_json_metadata, "center")
} else {
header.CenterLatE7 = (header.MinLatE7 + header.MaxLatE7) / 2
header.CenterLonE7 = (header.MinLonE7 + header.MaxLonE7) / 2
header.CenterZoom = header.MinZoom
}

if val, ok := v2_json_metadata["compression"]; ok {
Expand Down Expand Up @@ -532,7 +513,6 @@ func parse_center(center string) (int32, int32, uint8, error) {
return 0, 0, 0, err
}
return int32(center_lon * E7), int32(center_lat * E7), uint8(center_zoom), nil

}

func mbtiles_to_header_json(mbtiles_metadata []string) (HeaderV3, map[string]interface{}, error) {
Expand Down Expand Up @@ -570,18 +550,6 @@ func mbtiles_to_header_json(mbtiles_metadata []string) (HeaderV3, map[string]int
header.CenterLonE7 = center_lon
header.CenterLatE7 = center_lat
header.CenterZoom = center_zoom
case "minzoom":
i, err := strconv.ParseInt(value, 10, 8)
if err != nil {
return header, json_result, err
}
header.MinZoom = uint8(i)
case "maxzoom":
i, err := strconv.ParseInt(value, 10, 8)
if err != nil {
return header, json_result, err
}
header.MaxZoom = uint8(i)
case "json":
var mbtiles_json map[string]interface{}
json.Unmarshal([]byte(value), &mbtiles_json)
Expand Down
99 changes: 37 additions & 62 deletions pmtiles/convert_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pmtiles

import (
"github.com/stretchr/testify/assert"
"testing"
)

Expand Down Expand Up @@ -33,29 +34,15 @@ func TestResolver(t *testing.T) {

func TestV2UpgradeBarebones(t *testing.T) {
header, json_metadata, err := v2_to_header_json(map[string]interface{}{
"minzoom": 4,
"maxzoom": 5,
"bounds": "-180.0,-85,178,83",
"attribution": "abcd",
}, []byte{0x1f, 0x8b, 0x0, 0x0})
if err != nil {
t.Fatalf("parsing error %s", err)
}
if header.MinZoom != 4 {
t.Fatalf("expected minzoom=4, was %d", header.MinZoom)
}
if header.MaxZoom != 5 {
t.Fatalf("expected maxzoom=5, was %d", header.MaxZoom)
}
if _, ok := json_metadata["attribution"]; !ok {
t.Fatalf("expected key in result")
}
if _, ok := json_metadata["minzoom"]; ok {
t.Fatalf("expected minzoom not in result")
}
if _, ok := json_metadata["maxzoom"]; ok {
t.Fatalf("expected maxzoom not in result")
}
if header.MinLonE7 != -180*10000000 {
t.Fatalf(`expected min lon`)
}
Expand All @@ -71,15 +58,6 @@ func TestV2UpgradeBarebones(t *testing.T) {
if _, ok := json_metadata["bounds"]; ok {
t.Fatalf("expected bounds not in result")
}
if header.CenterLatE7 != -1*10000000 {
t.Fatalf(`expected default center lat -1`)
}
if header.CenterLonE7 != -1*10000000 {
t.Fatalf(`expected default center lat -1`)
}
if header.CenterZoom != 4 {
t.Fatalf(`expected default center zoom = minzoom`)
}
if header.TileCompression != Gzip {
t.Fatalf(`expected infer gzip`)
}
Expand All @@ -88,28 +66,9 @@ func TestV2UpgradeBarebones(t *testing.T) {
}
}

func TestV2UpgradeStrings(t *testing.T) {
header, _, err := v2_to_header_json(map[string]interface{}{
"minzoom": "0",
"maxzoom": "14",
"bounds": "-180.0,-85,178,83",
}, []byte{0x1f, 0x8b, 0x0, 0x0})
if err != nil {
t.Fatalf("parsing error %s", err)
}
if header.MinZoom != 0 {
t.Fatalf("expected minzoom=0, was %d", header.MinZoom)
}
if header.MaxZoom != 14 {
t.Fatalf("expected maxzoom=14, was %d", header.MaxZoom)
}
}

func TestV2UpgradeExtra(t *testing.T) {
// with the fields tippecanoe usually has
header, json_metadata, err := v2_to_header_json(map[string]interface{}{
"minzoom": 1,
"maxzoom": 2,
"bounds": "-180.0,-85,180,85",
"center": "-122.1906,37.7599,11",
"format": "pbf",
Expand All @@ -132,36 +91,60 @@ func TestV2UpgradeExtra(t *testing.T) {
}
}

func TestZoomCenterDefaults(t *testing.T) {
// with no center set
header := HeaderV3{}
header.MinLonE7 = -45 * 10000000
header.MaxLonE7 = -43 * 10000000
header.MinLatE7 = 21 * 10000000
header.MaxLatE7 = 23 * 10000000
entries := make([]EntryV3, 0)
entries = append(entries, EntryV3{ZxyToId(3, 0, 0), 0, 0, 0})
entries = append(entries, EntryV3{ZxyToId(4, 0, 0), 1, 1, 1})
set_zoom_center_defaults(&header, entries)
assert.Equal(t, uint8(3), header.MinZoom)
assert.Equal(t, uint8(4), header.MaxZoom)
assert.Equal(t, uint8(3), header.CenterZoom)
assert.Equal(t, int32(-44*10000000), header.CenterLonE7)
assert.Equal(t, int32(22*10000000), header.CenterLatE7)

// with a center set
header = HeaderV3{}
header.MinLonE7 = -45 * 10000000
header.MaxLonE7 = -43 * 10000000
header.MinLatE7 = 21 * 10000000
header.MaxLatE7 = 23 * 10000000
header.CenterLonE7 = header.MinLonE7
header.CenterLatE7 = header.MinLatE7
header.CenterZoom = 4
set_zoom_center_defaults(&header, entries)
assert.Equal(t, uint8(4), header.CenterZoom)
assert.Equal(t, int32(-45*10000000), header.CenterLonE7)
assert.Equal(t, int32(21*10000000), header.CenterLatE7)
}

func TestV2UpgradeInfer(t *testing.T) {
header, _, err := v2_to_header_json(map[string]interface{}{
"minzoom": 1,
"maxzoom": 2,
"bounds": "-180.0,-85,180,85",
"bounds": "-180.0,-85,180,85",
}, []byte{0xff, 0xd8, 0xff, 0xe0})
if err != nil || header.TileType != Jpeg || header.TileCompression != NoCompression {
t.Fatalf("expected inferred tile type")
}

header, _, err = v2_to_header_json(map[string]interface{}{
"minzoom": 1,
"maxzoom": 2,
"bounds": "-180.0,-85,180,85",
"bounds": "-180.0,-85,180,85",
}, []byte{0x89, 0x50, 0x4e, 0x47})
if err != nil || header.TileType != Png || header.TileCompression != NoCompression {
t.Fatalf("expected inferred tile type")
}
header, _, err = v2_to_header_json(map[string]interface{}{
"minzoom": 1,
"maxzoom": 2,
"bounds": "-180.0,-85,180,85",
"bounds": "-180.0,-85,180,85",
}, []byte{0x00, 00, 00, 00})
if header.TileType != Mvt || header.TileCompression != NoCompression {
t.Fatalf("expected inferred tile type")
}
header, _, err = v2_to_header_json(map[string]interface{}{
"minzoom": 1,
"maxzoom": 2,
"bounds": "-180.0,-85,180,85",
"bounds": "-180.0,-85,180,85",
}, []byte{0x1f, 0x8b, 00, 00})
if err != nil || header.TileType != Mvt || header.TileCompression != Gzip {
t.Fatalf("expected inferred tile type")
Expand All @@ -174,8 +157,6 @@ func TestMbtiles(t *testing.T) {
"format", "pbf",
"bounds", "-180.0,-85,180,85",
"center", "-122.1906,37.7599,11",
"minzoom", "1",
"maxzoom", "2",
"attribution", "<div>abc</div>",
"description", "a description",
"type", "overlay",
Expand Down Expand Up @@ -211,12 +192,6 @@ func TestMbtiles(t *testing.T) {
if header.CenterZoom != 11 {
t.Fatalf(`expected center zoom`)
}
if header.MinZoom != 1 {
t.Fatalf(`expected min zoom`)
}
if header.MaxZoom != 2 {
t.Fatalf(`expected max zoom`)
}
if header.TileCompression != Gzip {
t.Fatalf(`expected tile compression`)
}
Expand Down

0 comments on commit 00357bd

Please sign in to comment.