1996 строки
63 KiB
Python
Исполняемый файл
1996 строки
63 KiB
Python
Исполняемый файл
#!/usr/bin/env pytest
|
|
###############################################################################
|
|
# $Id$
|
|
#
|
|
# Project: GDAL/OGR Test Suite
|
|
# Purpose: Test OGR MVT driver functionality.
|
|
# Author: Even Rouault <even dot rouault at spatialys dot com>
|
|
#
|
|
###############################################################################
|
|
# Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
# copy of this software and associated documentation files (the "Software"),
|
|
# to deal in the Software without restriction, including without limitation
|
|
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
# and/or sell copies of the Software, and to permit persons to whom the
|
|
# Software is furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included
|
|
# in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
# DEALINGS IN THE SOFTWARE.
|
|
###############################################################################
|
|
|
|
import json
|
|
|
|
import gdaltest
|
|
import ogrtest
|
|
import pytest
|
|
import webserver
|
|
|
|
from osgeo import gdal, ogr, osr
|
|
|
|
pytestmark = pytest.mark.require_driver("MVT")
|
|
|
|
|
|
@pytest.fixture(scope="module", autouse=True)
|
|
def init():
|
|
with gdaltest.config_option("OGR_MVT_ENFORE_EXTERNAL_RING_IS_CLOCKWISE", "YES"):
|
|
yield
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.fixture
|
|
def has_make_valid():
|
|
# Check if MakeValid() is available
|
|
g = ogr.CreateGeometryFromWkt("POLYGON ((0 0,10 10,0 10,10 0,0 0))")
|
|
with gdaltest.error_handler(), gdaltest.disable_exceptions():
|
|
return g.MakeValid() is not None
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_datatypes():
|
|
|
|
# With metadata.json
|
|
ds = ogr.Open("data/mvt/datatypes/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
f["bool_false"] != 0
|
|
or f["bool_true"] != 1
|
|
or f["pos_int_value"] != 1
|
|
or f["pos_int64_value"] != 123456789012345
|
|
or f["neg_int_value"] != -1
|
|
or f["neg_int64_value"] != -123456789012345
|
|
or f["pos_sint_value"] != 1
|
|
or f["pos_sint64_value"] != 123456789012345
|
|
or f["neg_sint_value"] != -1
|
|
or f["neg_sint64_value"] != -123456789012345
|
|
or f["uint_value"] != 2000000000
|
|
or f["uint64_value"] != 4000000000
|
|
or f["float_value"] != 1.25
|
|
or f["real_value"] != 1.23456789
|
|
or f["string_value"] != "str"
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Without metadata.json
|
|
ds = gdal.OpenEx("data/mvt/datatypes/0/0/0.pbf", open_options=["METADATA_FILE="])
|
|
lyr = ds.GetLayer(0)
|
|
|
|
count = lyr.GetLayerDefn().GetFieldCount()
|
|
assert count == 16
|
|
|
|
tab = []
|
|
for i in range(lyr.GetLayerDefn().GetFieldCount()):
|
|
fld_defn = lyr.GetLayerDefn().GetFieldDefn(i)
|
|
tab += [(fld_defn.GetName(), fld_defn.GetType(), fld_defn.GetSubType())]
|
|
expected_tab = [
|
|
("mvt_id", ogr.OFTInteger64, ogr.OFSTNone),
|
|
("bool_true", ogr.OFTInteger, ogr.OFSTBoolean),
|
|
("bool_false", ogr.OFTInteger, ogr.OFSTBoolean),
|
|
("pos_int_value", ogr.OFTInteger, ogr.OFSTNone),
|
|
("pos_int64_value", ogr.OFTInteger64, ogr.OFSTNone),
|
|
("neg_int_value", ogr.OFTInteger, ogr.OFSTNone),
|
|
("neg_int64_value", ogr.OFTInteger64, ogr.OFSTNone),
|
|
("pos_sint_value", ogr.OFTInteger, ogr.OFSTNone),
|
|
("pos_sint64_value", ogr.OFTInteger64, ogr.OFSTNone),
|
|
("neg_sint_value", ogr.OFTInteger, ogr.OFSTNone),
|
|
("neg_sint64_value", ogr.OFTInteger64, ogr.OFSTNone),
|
|
("uint_value", ogr.OFTInteger, ogr.OFSTNone),
|
|
("uint64_value", ogr.OFTInteger64, ogr.OFSTNone),
|
|
("float_value", ogr.OFTReal, ogr.OFSTFloat32),
|
|
("real_value", ogr.OFTReal, ogr.OFSTNone),
|
|
("string_value", ogr.OFTString, ogr.OFSTNone),
|
|
]
|
|
assert tab == expected_tab
|
|
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
f["bool_false"] != 0
|
|
or f["bool_true"] != 1
|
|
or f["pos_int_value"] != 1
|
|
or f["pos_int64_value"] != 123456789012345
|
|
or f["neg_int_value"] != -1
|
|
or f["neg_int64_value"] != -123456789012345
|
|
or f["pos_sint_value"] != 1
|
|
or f["pos_sint64_value"] != 123456789012345
|
|
or f["neg_sint_value"] != -1
|
|
or f["neg_sint64_value"] != -123456789012345
|
|
or f["uint_value"] != 2000000000
|
|
or f["uint64_value"] != 4000000000
|
|
or f["float_value"] != 1.25
|
|
or f["real_value"] != 1.23456789
|
|
or f["string_value"] != "str"
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_datatype_promotion():
|
|
|
|
ds = ogr.Open("data/mvt/datatype_promotion.pbf")
|
|
tab = [
|
|
("int_to_int64", ogr.OFTInteger64),
|
|
("int_to_real", ogr.OFTReal),
|
|
("int64_to_real", ogr.OFTReal),
|
|
("bool_to_int", ogr.OFTInteger),
|
|
("bool_to_str", ogr.OFTString),
|
|
("float_to_double", ogr.OFTReal),
|
|
]
|
|
for layer_name, dt in tab:
|
|
lyr = ds.GetLayerByName(layer_name)
|
|
fld_defn = lyr.GetLayerDefn().GetFieldDefn(1)
|
|
assert fld_defn.GetType() == dt, layer_name
|
|
assert fld_defn.GetSubType() == ogr.OFSTNone, layer_name
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_limit_cases():
|
|
|
|
with gdaltest.error_handler():
|
|
ds = ogr.Open("data/mvt/limit_cases.pbf")
|
|
|
|
lyr = ds.GetLayerByName("empty")
|
|
assert lyr.GetFeatureCount() == 0
|
|
|
|
lyr = ds.GetLayerByName("layer1")
|
|
assert lyr.GetFeatureCount() == 7
|
|
|
|
f = lyr.GetFeature(1)
|
|
assert f["mvt_id"] == 1
|
|
|
|
with pytest.raises(Exception):
|
|
f = lyr.GetFeature(6)
|
|
assert f["b"] == 1
|
|
|
|
lyr = ds.GetLayerByName("layer2")
|
|
assert lyr.GetFeatureCount() == 0
|
|
|
|
lyr = ds.GetLayerByName("layer3")
|
|
assert lyr.GetFeatureCount() == 0
|
|
|
|
lyr = ds.GetLayerByName("layer4")
|
|
assert lyr.GetFeatureCount() == 0
|
|
|
|
lyr = ds.GetLayerByName("layer5")
|
|
assert lyr.GetFeatureCount() == 1
|
|
f = lyr.GetNextFeature()
|
|
assert f.GetGeometryRef().ExportToWkt() == "POINT (2070 2690)"
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_with_extension_fields():
|
|
|
|
ds = ogr.Open("data/mvt/with_extension_fields.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if ogrtest.check_feature_geometry(f, "LINESTRING (2070 2690,2082 2707)") != 0:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_mixed():
|
|
|
|
ds = ogr.Open("data/mvt/mixed/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"MULTIPOINT ((215246.671651058 6281289.23636264),(332653.947097085 6447616.20991119))",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"LINESTRING (215246.671651058 6281289.23636264,332653.947097085 6447616.20991119)",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_linestring():
|
|
|
|
ds = ogr.Open("data/mvt/linestring/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"MULTILINESTRING ((215246.671651058 6281289.23636264,332653.947097085 6447616.20991119))",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
ds = gdal.OpenEx("data/mvt/linestring/0/0/0.pbf", open_options=["METADATA_FILE="])
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"LINESTRING (215246.671651058 6281289.23636264,332653.947097085 6447616.20991119)",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_multilinestring():
|
|
|
|
ds = ogr.Open("data/mvt/multilinestring/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"MULTILINESTRING ((215246.671651058 6281289.23636264,332653.947097085 6447616.20991119),(440277.282922614 6623727.12308023,547900.618748143 6809621.97586978),(665307.894194175 6985732.88903883,772931.230019704 7171627.74182838))",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
ds = gdal.OpenEx(
|
|
"data/mvt/multilinestring/0/0/0.pbf", open_options=["METADATA_FILE="]
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"MULTILINESTRING ((215246.671651058 6281289.23636264,332653.947097085 6447616.20991119),(440277.282922614 6623727.12308023,547900.618748143 6809621.97586978),(665307.894194175 6985732.88903883,772931.230019704 7171627.74182838))",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_polygon():
|
|
|
|
ds = ogr.Open("data/mvt/polygon/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"MULTIPOLYGON (((332653.947097085 6447616.20991119,332653.947097085 6281289.23636264,215246.671651058 6281289.23636264,215246.671651058 6447616.20991119,332653.947097085 6447616.20991119)))",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
ds = gdal.OpenEx("data/mvt/polygon/0/0/0.pbf", open_options=["METADATA_FILE="])
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"POLYGON ((332653.947097085 6447616.20991119,332653.947097085 6281289.23636264,215246.671651058 6281289.23636264,215246.671651058 6447616.20991119,332653.947097085 6447616.20991119))",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_point_polygon():
|
|
|
|
ds = ogr.Open("data/mvt/point_polygon/0")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f, "MULTIPOINT ((215246.671651058 6281289.23636264))"
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
lyr = ds.GetLayer(1)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"MULTIPOLYGON (((440277.282922614 450061.222543117,440277.282922614 -440277.282922614,0.0 -440277.282922614,0.0 -215246.671651058,215246.671651058 -215246.671651058,215246.671651058 225030.61127156,0.0 225030.61127156,0.0 450061.222543117,440277.282922614 450061.222543117)),((0.0 117407.275446031,0.0 -107623.335825529,-117407.275446031 -107623.335825529,-117407.275446031 117407.275446031,0.0 117407.275446031)),((107623.335825529 58703.6377230138,107623.335825529 -48919.6981025115,48919.6981025115 -48919.6981025115,48919.6981025115 58703.6377230138,107623.335825529 58703.6377230138)))",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_point_polygon_clip():
|
|
|
|
if not (ogrtest.have_geos() or gdal.GetConfigOption("OGR_MVT_CLIP") is not None):
|
|
pytest.skip()
|
|
|
|
ds = ogr.Open("data/mvt/point_polygon/1")
|
|
lyr = ds.GetLayer(1)
|
|
f = lyr.GetNextFeature()
|
|
expected_wkt = "MULTIPOLYGON (((0.0 112515.30563578,0 0,-112515.30563578 0.0,-112515.30563578 112515.30563578,0.0 112515.30563578)))"
|
|
expected_wkt2 = "MULTIPOLYGON (((-112515.30563578 112515.30563578,0.0 112515.30563578,0 0,-112515.30563578 0.0,-112515.30563578 112515.30563578)))"
|
|
expected_wkt3 = "MULTIPOLYGON (((0 0,-112515.30563578 0.0,-112515.30563578 112515.30563578,0.0 112515.30563578,0 0)))"
|
|
assert (
|
|
ogrtest.check_feature_geometry(f, expected_wkt) == 0
|
|
or ogrtest.check_feature_geometry(f, expected_wkt2) == 0
|
|
or ogrtest.check_feature_geometry(f, expected_wkt3) == 0
|
|
), f.GetGeometryRef().ExportToWkt()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_tileset_without_readdir():
|
|
|
|
with gdaltest.config_option("MVT_USE_READDIR", "NO"):
|
|
ds = gdal.OpenEx("data/mvt/linestring/0")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_tileset_tilegl():
|
|
|
|
ds = ogr.Open("data/mvt/linestring_tilejson_gl/0")
|
|
lyr = ds.GetLayer(0)
|
|
assert lyr.GetLayerDefn().GetFieldCount() == 2
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_tileset_without_metadata_file():
|
|
|
|
ds = gdal.OpenEx(
|
|
"data/mvt/point_polygon/1", open_options=["METADATA_FILE=", "CLIP=NO"]
|
|
)
|
|
lyr = ds.GetLayerByName("point")
|
|
assert lyr.GetGeomType() == ogr.wkbMultiPoint
|
|
|
|
lyr = ds.GetLayerByName("polygon2")
|
|
assert lyr.GetGeomType() == ogr.wkbMultiPolygon
|
|
assert lyr.GetLayerDefn().GetFieldCount() == 2
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_tileset_json_field():
|
|
|
|
ds = gdal.OpenEx(
|
|
"data/mvt/datatypes/0",
|
|
open_options=["METADATA_FILE=", "JSON_FIELD=YES", "CLIP=NO"],
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
assert lyr.GetLayerDefn().GetFieldCount() == 2
|
|
f = lyr.GetNextFeature()
|
|
d = json.loads(f.GetFieldAsString("json"))
|
|
assert d == {
|
|
"bool_true": True,
|
|
"bool_false": False,
|
|
"pos_int_value": 1,
|
|
"pos_int64_value": 123456789012345,
|
|
"neg_int_value": -1,
|
|
"neg_int64_value": -123456789012345,
|
|
"pos_sint_value": 1,
|
|
"pos_sint64_value": 123456789012345,
|
|
"neg_sint_value": -1,
|
|
"neg_sint64_value": -123456789012345,
|
|
"uint_value": 2000000000,
|
|
"uint64_value": 4000000000,
|
|
"float_value": 1.25,
|
|
"real_value": 1.23456789,
|
|
"string_value": "str",
|
|
}, f.GetFieldAsString("json")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_open_variants():
|
|
|
|
expected_geom = "MULTILINESTRING ((215246.671651058 6281289.23636264,332653.947097085 6447616.20991119))"
|
|
|
|
ds = ogr.Open("MVT:data/mvt/linestring/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if ogrtest.check_feature_geometry(f, expected_geom) != 0:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
ds = ogr.Open("MVT:data/mvt/linestring/0")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if ogrtest.check_feature_geometry(f, expected_geom) != 0:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
ds = ogr.Open("/vsigzip/data/mvt/linestring/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if ogrtest.check_feature_geometry(f, expected_geom) != 0:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
ds = ogr.Open("MVT:/vsigzip/data/mvt/linestring/0/0/0.pbf")
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if ogrtest.check_feature_geometry(f, expected_geom) != 0:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_xyz_options():
|
|
|
|
ds = gdal.OpenEx("data/mvt/datatypes/0/0/0.pbf", open_options=["X=1", "Y=2", "Z=3"])
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(f, "POINT (-12496536.8802869 8299226.7830913)")
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_test_ogrsf_pbf():
|
|
|
|
import test_cli_utilities
|
|
|
|
if test_cli_utilities.get_test_ogrsf_path() is None:
|
|
pytest.skip()
|
|
|
|
ret = gdaltest.runexternal(
|
|
test_cli_utilities.get_test_ogrsf_path() + " -ro data/mvt/datatypes/0/0/0.pbf"
|
|
)
|
|
|
|
assert ret.find("INFO") != -1 and ret.find("ERROR") == -1
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_test_ogrsf_directory():
|
|
|
|
import test_cli_utilities
|
|
|
|
if test_cli_utilities.get_test_ogrsf_path() is None:
|
|
pytest.skip()
|
|
|
|
ret = gdaltest.runexternal(
|
|
test_cli_utilities.get_test_ogrsf_path() + " -ro data/mvt/datatypes/0"
|
|
)
|
|
|
|
assert ret.find("INFO") != -1 and ret.find("ERROR") == -1
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("MBTILES")
|
|
def test_ogr_mvt_mbtiles():
|
|
|
|
ds = ogr.Open("data/mvt/point_polygon.mbtiles")
|
|
lyr = ds.GetLayerByName("point")
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f, "MULTIPOINT ((220138.641461308 6276397.26655239))"
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
lyr.SetSpatialFilterRect(0, 0, 10000000, 10000000)
|
|
lyr.ResetReading()
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f, "MULTIPOINT ((220138.641461308 6276397.26655239))"
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("MBTILES")
|
|
def test_ogr_mvt_mbtiles_json_field():
|
|
|
|
ds = gdal.OpenEx(
|
|
"data/mvt/datatypes.mbtiles", open_options=["JSON_FIELD=YES", "CLIP=NO"]
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
assert lyr.GetLayerDefn().GetFieldCount() == 2
|
|
f = lyr.GetNextFeature()
|
|
d = json.loads(f.GetFieldAsString("json"))
|
|
assert d == {
|
|
"int64_value": 123456789012345,
|
|
"string_value": "str",
|
|
"real_value": 1.23456789,
|
|
"bool_false": False,
|
|
"pos_int_value": 1,
|
|
"neg_int_value": -1,
|
|
"bool_true": True,
|
|
"float_value": 1.25,
|
|
}, f.GetFieldAsString("json")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("MBTILES")
|
|
def test_ogr_mvt_mbtiles_json_field_auto():
|
|
|
|
ds = gdal.OpenEx(
|
|
"data/mvt/datatypes_json_field_auto.mbtiles", open_options=["CLIP=NO"]
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
assert lyr.GetLayerDefn().GetFieldCount() == 2
|
|
f = lyr.GetNextFeature()
|
|
d = json.loads(f.GetFieldAsString("json"))
|
|
assert d == {
|
|
"int64_value": 123456789012345,
|
|
"string_value": "str",
|
|
"real_value": 1.23456789,
|
|
"bool_false": False,
|
|
"pos_int_value": 1,
|
|
"neg_int_value": -1,
|
|
"bool_true": True,
|
|
"float_value": 1.25,
|
|
}, f.GetFieldAsString("json")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("MBTILES")
|
|
def test_ogr_mvt_mbtiles_test_ogrsf():
|
|
|
|
import test_cli_utilities
|
|
|
|
if test_cli_utilities.get_test_ogrsf_path() is None:
|
|
pytest.skip()
|
|
|
|
ret = gdaltest.runexternal(
|
|
test_cli_utilities.get_test_ogrsf_path()
|
|
+ " -ro data/mvt/point_polygon.mbtiles polygon2"
|
|
)
|
|
|
|
assert ret.find("INFO") != -1 and ret.find("ERROR") == -1
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("MBTILES")
|
|
def test_ogr_mvt_mbtiles_open_vector_in_raster_mode():
|
|
|
|
with pytest.raises(Exception):
|
|
gdal.OpenEx("data/mvt/datatypes.mbtiles", gdal.OF_RASTER)
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_x_y_z_filename_scheme():
|
|
|
|
tmpfilename = "/vsimem/0-0-0.pbf"
|
|
gdal.FileFromMemBuffer(
|
|
tmpfilename, open("data/mvt/linestring/0/0/0.pbf", "rb").read()
|
|
)
|
|
ds = ogr.Open(tmpfilename)
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
f,
|
|
"LINESTRING (215246.671651058 6281289.23636264,332653.947097085 6447616.20991119)",
|
|
)
|
|
!= 0
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
ds = None
|
|
gdal.Unlink(tmpfilename)
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_polygon_larger_than_header():
|
|
|
|
with gdaltest.config_option("OGR_MVT_ENFORE_EXTERNAL_RING_IS_CLOCKWISE", "NO"):
|
|
ds = gdal.OpenEx(
|
|
"data/mvt/polygon_larger_than_header.pbf", open_options=["CLIP=NO"]
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_ogr_mvt_errors():
|
|
|
|
with pytest.raises(Exception):
|
|
assert ogr.Open("MVT:/i_do_not/exist") is None
|
|
|
|
# Cannot detect Z in directory name
|
|
with pytest.raises(Exception):
|
|
assert ogr.Open("MVT:data") is None
|
|
|
|
# Invalid Z
|
|
gdal.Mkdir("/vsimem/33", 0)
|
|
|
|
with pytest.raises(Exception):
|
|
assert ogr.Open("MVT:/vsimem/33") is None
|
|
|
|
gdal.Rmdir("/vsimem/33")
|
|
|
|
# Inexisting metadata
|
|
with gdaltest.error_handler():
|
|
assert (
|
|
gdal.OpenEx(
|
|
"data/mvt/linestring/0/0/0.pbf",
|
|
open_options=["METADATA_FILE=/i_do_not/exist"],
|
|
)
|
|
is not None
|
|
)
|
|
|
|
# Invalid metadata
|
|
with gdaltest.error_handler():
|
|
assert (
|
|
gdal.OpenEx(
|
|
"data/mvt/linestring/0/0/0.pbf",
|
|
open_options=["METADATA_FILE=ogr_mvt.py"],
|
|
)
|
|
is not None
|
|
)
|
|
|
|
# Invalid metadata
|
|
gdal.FileFromMemBuffer("/vsimem/my.json", "{}")
|
|
with gdaltest.error_handler():
|
|
assert (
|
|
gdal.OpenEx(
|
|
"data/mvt/linestring/0/0/0.pbf",
|
|
open_options=["METADATA_FILE=/vsimem/my.json"],
|
|
)
|
|
is not None
|
|
)
|
|
gdal.Unlink("/vsimem/my.json")
|
|
|
|
# Invalid metadata
|
|
gdal.FileFromMemBuffer("/vsimem/my.json", '{ "json": "x y" }')
|
|
with gdaltest.error_handler():
|
|
assert (
|
|
gdal.OpenEx(
|
|
"data/mvt/linestring/0/0/0.pbf",
|
|
open_options=["METADATA_FILE=/vsimem/my.json"],
|
|
)
|
|
is not None
|
|
)
|
|
gdal.Unlink("/vsimem/my.json")
|
|
|
|
# Too big file
|
|
tmpfilename = "/vsimem/foo.pbf"
|
|
gdal.FileFromMemBuffer(
|
|
tmpfilename, open("data/mvt/polygon_larger_than_header.pbf", "rb").read()
|
|
)
|
|
f = gdal.VSIFOpenL(tmpfilename, "rb+")
|
|
gdal.VSIFSeekL(f, 20 * 1024 * 1024, 0)
|
|
gdal.VSIFWriteL(" ", 1, 1, f)
|
|
gdal.VSIFCloseL(f)
|
|
with pytest.raises(Exception):
|
|
ogr.Open(tmpfilename)
|
|
gdal.Unlink(tmpfilename)
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_curl()
|
|
def test_ogr_mvt_http_start():
|
|
|
|
gdaltest.webserver_process = None
|
|
gdaltest.webserver_port = 0
|
|
|
|
(gdaltest.webserver_process, gdaltest.webserver_port) = webserver.launch(
|
|
handler=webserver.DispatcherHttpHandler
|
|
)
|
|
if gdaltest.webserver_port == 0:
|
|
pytest.skip()
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_curl()
|
|
def test_ogr_mvt_http():
|
|
|
|
if gdaltest.webserver_port == 0:
|
|
pytest.skip()
|
|
|
|
handler = webserver.SequentialHandler()
|
|
handler.add(
|
|
"GET",
|
|
"/linestring/metadata.json",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/metadata.json", "rb").read(),
|
|
)
|
|
handler.add(
|
|
"GET",
|
|
"/linestring/0/0/0.pbf",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/0/0/0.pbf", "rb").read(),
|
|
)
|
|
handler.add(
|
|
"GET",
|
|
"/linestring/0/0/0.pbf",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/0/0/0.pbf", "rb").read(),
|
|
)
|
|
with webserver.install_http_handler(handler):
|
|
ds = ogr.Open("MVT:http://127.0.0.1:%d/linestring/0" % gdaltest.webserver_port)
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
|
|
# No metadata file nor tile
|
|
handler = webserver.SequentialHandler()
|
|
handler.add("GET", "/linestring/metadata.json", 404, {})
|
|
handler.add("GET", "/linestring.json", 404, {})
|
|
handler.add("GET", "/linestring/0/0/0.pbf", 404, {})
|
|
with webserver.install_http_handler(handler):
|
|
with pytest.raises(Exception):
|
|
ogr.Open("MVT:http://127.0.0.1:%d/linestring/0" % gdaltest.webserver_port)
|
|
|
|
# No metadata file, but tiles
|
|
handler = webserver.SequentialHandler()
|
|
handler.add("GET", "/linestring/metadata.json", 404, {})
|
|
handler.add("GET", "/linestring.json", 404, {})
|
|
handler.add(
|
|
"GET",
|
|
"/linestring/0/0/0.pbf",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/0/0/0.pbf", "rb").read(),
|
|
)
|
|
handler.add(
|
|
"GET",
|
|
"/linestring/0/0/0.pbf",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/0/0/0.pbf", "rb").read(),
|
|
)
|
|
with webserver.install_http_handler(handler):
|
|
ds = ogr.Open("MVT:http://127.0.0.1:%d/linestring/0" % gdaltest.webserver_port)
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
|
|
# metadata.json file, but no tiles
|
|
handler = webserver.SequentialHandler()
|
|
handler.add(
|
|
"GET",
|
|
"/linestring/metadata.json",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/metadata.json", "rb").read(),
|
|
)
|
|
handler.add("GET", "/linestring/0/0/0.pbf", 404, {})
|
|
handler.add("GET", "/linestring/0/0/0.pbf", 404, {})
|
|
with webserver.install_http_handler(handler):
|
|
ds = ogr.Open("MVT:http://127.0.0.1:%d/linestring/0" % gdaltest.webserver_port)
|
|
lyr = ds.GetLayer(0)
|
|
with pytest.raises(Exception):
|
|
lyr.GetNextFeature()
|
|
|
|
# No metadata.json file, but a linestring.json and no tiles
|
|
handler = webserver.SequentialHandler()
|
|
handler.add("GET", "/linestring/metadata.json", 404, {})
|
|
handler.add(
|
|
"GET",
|
|
"/linestring.json",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/metadata.json", "rb").read(),
|
|
)
|
|
handler.add("GET", "/linestring/0/0/0.pbf", 404, {})
|
|
handler.add("GET", "/linestring/0/0/0.pbf", 404, {})
|
|
with webserver.install_http_handler(handler):
|
|
ds = ogr.Open("MVT:http://127.0.0.1:%d/linestring/0" % gdaltest.webserver_port)
|
|
lyr = ds.GetLayer(0)
|
|
with pytest.raises(Exception):
|
|
lyr.GetNextFeature()
|
|
|
|
# Open pbf file
|
|
handler = webserver.SequentialHandler()
|
|
handler.add(
|
|
"GET",
|
|
"/linestring/0/0/0.pbf",
|
|
200,
|
|
{},
|
|
open("data/mvt/linestring/0/0/0.pbf", "rb").read(),
|
|
)
|
|
with webserver.install_http_handler(handler):
|
|
ds = ogr.Open(
|
|
"MVT:http://127.0.0.1:%d/linestring/0/0/0.pbf" % gdaltest.webserver_port
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_curl()
|
|
def test_ogr_mvt_http_stop():
|
|
|
|
if gdaltest.webserver_port == 0:
|
|
pytest.skip()
|
|
|
|
webserver.server_stop(gdaltest.webserver_process, gdaltest.webserver_port)
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_one_layer(has_make_valid):
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
lyr.CreateField(ogr.FieldDefn("strfield", ogr.OFTString))
|
|
lyr.CreateField(ogr.FieldDefn("intfield", ogr.OFTInteger))
|
|
lyr.CreateField(ogr.FieldDefn("int64field", ogr.OFTInteger64))
|
|
lyr.CreateField(ogr.FieldDefn("realfield", ogr.OFTReal))
|
|
lyr.CreateField(ogr.FieldDefn("datefield", ogr.OFTDate))
|
|
lyr.CreateField(ogr.FieldDefn("datetimefield", ogr.OFTDateTime))
|
|
boolfield = ogr.FieldDefn("boolfield", ogr.OFTInteger)
|
|
boolfield.SetSubType(ogr.OFSTBoolean)
|
|
lyr.CreateField(boolfield)
|
|
|
|
# Test empty layer: OK
|
|
with gdaltest.error_handler():
|
|
out_ds = gdal.VectorTranslate("/vsimem/outmvt", src_ds, format="MVT")
|
|
assert out_ds is not None
|
|
|
|
# Cannot create directory
|
|
with pytest.raises(Exception):
|
|
gdal.VectorTranslate("/i_dont/exist/outmvt", src_ds, format="MVT")
|
|
|
|
# Directory already exists
|
|
with pytest.raises(Exception):
|
|
gdal.VectorTranslate("/vsimem/outmvt", src_ds, format="MVT")
|
|
|
|
gdal.RmdirRecursive("/vsimem/outmvt")
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetFID(123)
|
|
f["strfield"] = "foo"
|
|
f["intfield"] = -1
|
|
f["int64field"] = 123456789012345
|
|
f["realfield"] = 1.25
|
|
f["datefield"] = "2018/02/01"
|
|
f["datetimefield"] = "2018/02/01 12:34:56"
|
|
f["boolfield"] = True
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(500000 1000000)"))
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetFID(124)
|
|
f["strfield"] = "foo"
|
|
f["intfield"] = -1
|
|
f["int64field"] = 123456789012345
|
|
f["realfield"] = 1.25
|
|
f["datefield"] = "2018/02/01"
|
|
f["datetimefield"] = "2018/02/01 12:34:56"
|
|
f["boolfield"] = True
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"LINESTRING(500000 1000000,510000 1010000,520000 1020000)"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetFID(125)
|
|
f["strfield"] = "foobarbazbaw"
|
|
f["intfield"] = 1
|
|
f["int64field"] = -123456789012345
|
|
f["realfield"] = -1.25678
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"POLYGON((500000 1000000,510000 1000000,510000 1010000,500000 1000000))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetFID(126)
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt("MULTIPOINT(500000 1000000,510000 1010000)")
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetFID(127)
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"MULTILINESTRING((500000 1000000,510000 1010000),(510000 1010000,510000 1000000))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetFID(128)
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"MULTIPOLYGON(((500000 1000000,510000 1000000,510000 1010000,500000 1000000)),((-500000 1000000,-510000 1000000,-510000 1010000,-500000 1000000),(-502000 1001000,-509000 1001000,-509000 1008500,-502000 1001000)))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetFID(129)
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"GEOMETRYCOLLECTION(POINT(500000 1000000),LINESTRING(500000 1000000,510000 1010000,520000 1020000))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
with gdaltest.error_handler():
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/outmvt", src_ds, options="-f MVT -preserve_fid"
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/outmvt/0")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
out_f["mvt_id"] != 123
|
|
or out_f["strfield"] != "foo"
|
|
or out_f["intfield"] != -1
|
|
or out_f["int64field"] != 123456789012345
|
|
or out_f["realfield"] != 1.25
|
|
or out_f["datefield"] != "2018-02-01"
|
|
or out_f["datetimefield"] != "2018-02-01T12:34:56"
|
|
or out_f["boolfield"] is False
|
|
or ogrtest.check_feature_geometry(
|
|
out_f, "POINT (498980.920645632 997961.84129126)"
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
out_f["strfield"] != "foo"
|
|
or out_f["intfield"] != -1
|
|
or out_f["int64field"] != 123456789012345
|
|
or out_f["realfield"] != 1.25
|
|
or out_f["datefield"] != "2018-02-01"
|
|
or out_f["datetimefield"] != "2018-02-01T12:34:56"
|
|
or out_f["boolfield"] is False
|
|
or ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTILINESTRING ((498980.920645632 997961.84129126,508764.860266134 1007745.78091176,518548.799886636 1017529.72053226))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
out_f["strfield"] != "foobarbazbaw"
|
|
or out_f["intfield"] != 1
|
|
or out_f["int64field"] != -123456789012345
|
|
or out_f["realfield"] != -1.25678
|
|
or out_f.IsFieldSet("datefield")
|
|
or out_f.IsFieldSet("datetimefield")
|
|
or out_f.IsFieldSet("boolfield")
|
|
or ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"POLYGON ((498980.920645632 997961.84129126,508764.860266134 1007745.78091176,508764.860266134 997961.84129126,498980.920645632 997961.84129126))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOINT ((498980.920645632 997961.84129126),(508764.860266134 1007745.78091176))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTILINESTRING ((498980.920645632 997961.84129126,508764.860266134 1007745.78091176),(508764.860266134 1007745.78091176,508764.860266134 997961.84129126))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
(
|
|
(not has_make_valid)
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((498980.920645632 997961.84129126,508764.860266134 1007745.78091176,508764.860266134 997961.84129126,498980.920645632 997961.84129126)),((-498980.920645632 997961.84129126,-508764.860266134 997961.84129126,-508764.860266134 1007745.78091176,-498980.920645632 997961.84129126)))",
|
|
)
|
|
!= 0
|
|
)
|
|
# Below is what we get with MakeValid() available
|
|
or (
|
|
# GEOS > 3.8 (not sure which minimum version)
|
|
has_make_valid
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((-508764.860266134 1007745.78091176,-498980.920645632 997961.84129126,-508764.860266134 997961.84129126,-508764.860266134 1007745.78091176)),((508764.860266134 1007745.78091176,508764.860266134 997961.84129126,498980.920645632 997961.84129126,508764.860266134 1007745.78091176)))",
|
|
)
|
|
!= 0
|
|
# Below result with GEOS 3.8
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((498980.920645632 997961.84129126,508764.860266134 1007745.78091176,508764.860266134 997961.84129126,498980.920645632 997961.84129126)),((-508764.860266134 997961.84129126,-508764.860266134 1007745.78091176,-498980.920645632 997961.84129126,-508764.860266134 997961.84129126)))",
|
|
)
|
|
!= 0
|
|
)
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
(
|
|
out_f.GetGeometryRef().GetGeometryType() == ogr.wkbPoint
|
|
and ogrtest.check_feature_geometry(
|
|
out_f, "POINT (498980.920645632 997961.84129126)"
|
|
)
|
|
!= 0
|
|
)
|
|
or (
|
|
out_f.GetGeometryRef().GetGeometryType() == ogr.wkbMultiLineString
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTILINESTRING ((498980.920645632 997961.84129126,508764.860266134 1007745.78091176,518548.799886636 1017529.72053226))",
|
|
)
|
|
!= 0
|
|
)
|
|
or out_f.GetGeometryRef().GetGeometryType()
|
|
not in (ogr.wkbPoint, ogr.wkbMultiLineString)
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
(
|
|
out_f.GetGeometryRef().GetGeometryType() == ogr.wkbPoint
|
|
and ogrtest.check_feature_geometry(
|
|
out_f, "POINT (498980.920645632 997961.84129126)"
|
|
)
|
|
!= 0
|
|
)
|
|
or (
|
|
out_f.GetGeometryRef().GetGeometryType() == ogr.wkbMultiLineString
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTILINESTRING ((498980.920645632 997961.84129126,508764.860266134 1007745.78091176,518548.799886636 1017529.72053226))",
|
|
)
|
|
!= 0
|
|
)
|
|
or out_f.GetGeometryRef().GetGeometryType()
|
|
not in (ogr.wkbPoint, ogr.wkbMultiLineString)
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_ds = ogr.Open("/vsimem/outmvt/5")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
assert out_lyr.GetFeatureCount() == 9
|
|
|
|
f = gdal.VSIFOpenL("/vsimem/outmvt/metadata.json", "rb")
|
|
assert f is not None
|
|
data = gdal.VSIFReadL(1, 100000, f).decode("ASCII")
|
|
gdal.VSIFCloseL(f)
|
|
data_json = json.loads(data)
|
|
expected_json = {
|
|
"name": "outmvt",
|
|
"description": "",
|
|
"version": 2,
|
|
"minzoom": 0,
|
|
"maxzoom": 5,
|
|
"center": "0.0449158,9.0352907,0",
|
|
"bounds": "-4.5814079,8.9465739,4.6712395,9.1240075",
|
|
"type": "overlay",
|
|
"format": "pbf",
|
|
}
|
|
for k in expected_json:
|
|
assert k in data_json and data_json[k] == expected_json[k], data
|
|
json_json = json.loads(data_json["json"])
|
|
expected_json_json = {
|
|
"vector_layers": [
|
|
{
|
|
"id": "mylayer",
|
|
"description": "",
|
|
"minzoom": 0,
|
|
"maxzoom": 5,
|
|
"fields": {
|
|
"strfield": "String",
|
|
"intfield": "Number",
|
|
"int64field": "Number",
|
|
"realfield": "Number",
|
|
"datefield": "String",
|
|
"datetimefield": "String",
|
|
"boolfield": "Boolean",
|
|
},
|
|
}
|
|
],
|
|
"tilestats": {
|
|
"layerCount": 1,
|
|
"layers": [
|
|
{
|
|
"layer": "mylayer",
|
|
"count": 7,
|
|
"geometry": "LineString",
|
|
"attributeCount": 7,
|
|
"attributes": [
|
|
{
|
|
"attribute": "strfield",
|
|
"count": 2,
|
|
"type": "string",
|
|
"values": ["foo", "foobarbazbaw"],
|
|
},
|
|
{
|
|
"attribute": "intfield",
|
|
"count": 2,
|
|
"type": "number",
|
|
"values": [-1, 1],
|
|
"min": -1,
|
|
"max": 1,
|
|
},
|
|
{
|
|
"attribute": "int64field",
|
|
"count": 2,
|
|
"type": "number",
|
|
"values": [-123456789012345, 123456789012345],
|
|
"min": -123456789012345,
|
|
"max": 123456789012345,
|
|
},
|
|
{
|
|
"attribute": "realfield",
|
|
"count": 2,
|
|
"type": "number",
|
|
"values": [-1.256780, 1.250000],
|
|
"min": -1.25678,
|
|
"max": 1.25,
|
|
},
|
|
{
|
|
"attribute": "datefield",
|
|
"count": 1,
|
|
"type": "string",
|
|
"values": ["2018-02-01"],
|
|
},
|
|
{
|
|
"attribute": "datetimefield",
|
|
"count": 1,
|
|
"type": "string",
|
|
"values": ["2018-02-01T12:34:56"],
|
|
},
|
|
{
|
|
"attribute": "boolfield",
|
|
"count": 1,
|
|
"type": "boolean",
|
|
"values": [True],
|
|
},
|
|
],
|
|
}
|
|
],
|
|
},
|
|
}
|
|
|
|
assert json_json == expected_json_json, data_json["json"]
|
|
|
|
gdal.RmdirRecursive("/vsimem/outmvt")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_conf():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(500000 1000000)"))
|
|
lyr.CreateFeature(f)
|
|
|
|
conf = {
|
|
"mylayer": {
|
|
"target_name": "TheLayer",
|
|
"description": "the layer",
|
|
"minzoom": 1,
|
|
"maxzoom": 2,
|
|
}
|
|
}
|
|
with gdaltest.tempfile("/vsimem/conf.json", json.dumps(conf)):
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/outmvt",
|
|
src_ds,
|
|
format="MVT",
|
|
datasetCreationOptions=["CONF=/vsimem/conf.json"],
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/outmvt/1")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("TheLayer")
|
|
assert out_lyr
|
|
out_ds = None
|
|
|
|
gdal.RmdirRecursive("/vsimem/outmvt")
|
|
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/outmvt",
|
|
src_ds,
|
|
format="MVT",
|
|
datasetCreationOptions=["CONF=%s" % json.dumps(conf)],
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/outmvt/1")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("TheLayer")
|
|
assert out_lyr
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f, "MULTIPOINT (498980.920645632 997961.84129126)"
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
f = gdal.VSIFOpenL("/vsimem/outmvt/metadata.json", "rb")
|
|
assert f is not None
|
|
data = gdal.VSIFReadL(1, 100000, f).decode("ASCII")
|
|
gdal.VSIFCloseL(f)
|
|
data_json = json.loads(data)
|
|
json_json = json.loads(data_json["json"])
|
|
expected_json_json = {
|
|
"vector_layers": [
|
|
{
|
|
"id": "TheLayer",
|
|
"description": "the layer",
|
|
"minzoom": 1,
|
|
"maxzoom": 2,
|
|
"fields": {},
|
|
}
|
|
],
|
|
"tilestats": {
|
|
"layerCount": 1,
|
|
"layers": [
|
|
{
|
|
"layer": "TheLayer",
|
|
"count": 1,
|
|
"geometry": "Point",
|
|
"attributeCount": 0,
|
|
"attributes": [],
|
|
}
|
|
],
|
|
},
|
|
}
|
|
|
|
assert json_json == expected_json_json, data_json["json"]
|
|
|
|
gdal.RmdirRecursive("/vsimem/outmvt")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_mbtiles():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(500000 1000000)"))
|
|
lyr.CreateFeature(f)
|
|
|
|
out_ds = gdal.VectorTranslate("/vsimem/out.mbtiles", src_ds)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/out.mbtiles")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f, "MULTIPOINT ((499898.164985053 1000102.07808325))"
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_ds = None
|
|
|
|
gdal.Unlink("/vsimem/out.mbtiles")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_limitations_max_size():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
lyr.CreateField(ogr.FieldDefn("field"))
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetField(
|
|
"field", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
)
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(500000 1000000)"))
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt("LINESTRING(500000 1000000,510000 1000000)")
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
# Also test single threaded execution
|
|
with gdaltest.config_option("GDAL_NUM_THREADS", "1"):
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/out.mbtiles",
|
|
src_ds,
|
|
datasetCreationOptions=["MAX_SIZE=100", "SIMPLIFICATION=1"],
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/out.mbtiles")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTILINESTRING ((498980.920645631 1007745.78091176,508764.860266133 1007745.78091176))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f, "POINT (498980.920645631 1007745.78091176)"
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_ds = None
|
|
|
|
gdal.Unlink("/vsimem/out.mbtiles")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_polygon_repaired():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
lyr.CreateField(ogr.FieldDefn("field"))
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"POLYGON((0 0,0 500000,100000 500000,100000 200000,100500 200000,100500 500000,500000 500000,500000 0,0 0))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"MULTIPOLYGON(((0 0,0 500000,100000 500000,100000 200000,100500 200000,100500 500000,500000 500000,500000 0,0 0)),((1000000 0,1000000 1000000,2000000 1000000,1000000 0)))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
# Cannot be repaired
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POLYGON((0 0,0 1,1 1,0 0))"))
|
|
lyr.CreateFeature(f)
|
|
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/out.mbtiles", src_ds, datasetCreationOptions=["MAXZOOM=0"]
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/out.mbtiles")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
# Second expected result is using the HAVE_MAKE_VALID code path with GEOS 3.8
|
|
# Third expected result is using the HAVE_MAKE_VALID code path with GEOS 3.10
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((0 0,0.0 498980.920645632,498980.920645632 498980.920645632,498980.920645632 0.0,0 0)))",
|
|
)
|
|
!= 0
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((97839.3962050267 498980.920645632,498980.920645632 498980.920645632,498980.920645632 0.0,0 0,0.0 498980.920645632,97839.3962050267 498980.920645632)))",
|
|
)
|
|
!= 0
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((0.0 498980.920645632,97839.3962050267 498980.920645632,498980.920645632 498980.920645632,498980.920645632 0.0,0 0,0.0 498980.920645632)))",
|
|
)
|
|
!= 0
|
|
):
|
|
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
out_f = out_lyr.GetNextFeature()
|
|
# Second expected result is using the HAVE_MAKE_VALID code path
|
|
# Third expected result is using the HAVE_MAKE_VALID code path with GEOS 3.10
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((0 0,0.0 498980.920645632,498980.920645632 498980.920645632,498980.920645632 0.0,0 0)),((997961.84129126 0.0,997961.84129126 997961.84129126,1995923.68258252 997961.84129126,997961.84129126 0.0)))",
|
|
)
|
|
!= 0
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((997961.84129126 0.0,997961.84129126 997961.84129126,1995923.68258252 997961.84129126,997961.84129126 0.0)),((97839.3962050267 498980.920645632,498980.920645632 498980.920645632,498980.920645632 0.0,0 0,0.0 498980.920645632,97839.3962050267 498980.920645632)))",
|
|
)
|
|
!= 0
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((997961.84129126 997961.84129126,1995923.68258252 997961.84129126,997961.84129126 0.0,997961.84129126 997961.84129126)),((0 0,0.0 498980.920645632,97839.3962050267 498980.920645632,498980.920645632 498980.920645632,498980.920645632 0.0,0 0)))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_f = out_lyr.GetNextFeature()
|
|
if out_f is not None:
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_ds = None
|
|
|
|
gdal.Unlink("/vsimem/out.mbtiles")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_conflicting_innner_ring(has_make_valid):
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
lyr.CreateField(ogr.FieldDefn("field"))
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
# the second inner ring conflicts with the first one once transformed to integer coordinates
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"POLYGON((-500000 1000000,-510000 1000000,-510000 1010000,-500000 1000000),(-502000 1001000,-509000 1001000,-509000 1008500,-502000 1001000),(-502000 1000900,-509000 1000900,-509000 1000800,-502000 1000900))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
out_ds = gdal.VectorTranslate("/vsimem/out.mbtiles", src_ds)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/out.mbtiles")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
(
|
|
(not has_make_valid)
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((-499898.164985052 1000102.07808325,-509987.852718695 1000102.07808325,-509987.852718695 1009886.01770375,-499898.164985052 1000102.07808325),(-502038.401777037 1001019.32242267,-509070.608379273 1008357.27713804,-509070.608379273 1001019.32242267,-502038.401777037 1001019.32242267)))",
|
|
)
|
|
!= 0
|
|
)
|
|
# Below is what we get with MakeValid() available
|
|
or (
|
|
has_make_valid
|
|
and ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((-499898.164985052 1000102.07808325,-509987.852718695 1000102.07808325,-509987.852718695 1009886.01770375,-499898.164985052 1000102.07808325),(-502038.401777037 1001019.32242267,-509070.608379273 1008357.27713804,-509070.608379273 1001019.32242267,-509070.608379273 1000713.57430953,-502038.401777037 1001019.32242267)))",
|
|
)
|
|
!= 0
|
|
)
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_ds = None
|
|
|
|
gdal.Unlink("/vsimem/out.mbtiles")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_limitations_max_size_polygon():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
lyr.CreateField(ogr.FieldDefn("field"))
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetField(
|
|
"field", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
)
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"POLYGON((500000 1000000,510000 1000000,510000 1010000,500000 1000000),(503000 1003000,507000 1003000,507000 1005000,503000 1003000))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/out.mbtiles", src_ds, datasetCreationOptions=["MAX_SIZE=100"]
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/out.mbtiles")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"MULTIPOLYGON (((498980.920645631 1007745.78091176,508764.860266133 1017529.72053227,508764.860266133 1007745.78091176,498980.920645631 1007745.78091176)))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_ds = None
|
|
|
|
gdal.Unlink("/vsimem/out.mbtiles")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_limitations_max_features():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(500000 1000000)"))
|
|
lyr.CreateFeature(f)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(
|
|
ogr.CreateGeometryFromWkt(
|
|
"POLYGON((500000 1000000,510000 1000000,510000 1100000,500000 1000000))"
|
|
)
|
|
)
|
|
lyr.CreateFeature(f)
|
|
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/out.mbtiles",
|
|
src_ds,
|
|
format="MVT",
|
|
datasetCreationOptions=["MAX_FEATURES=1"],
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/out.mbtiles")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f,
|
|
"POLYGON ((499898.164985053 1000102.07808325,509987.852718696 1100081.71108026,509987.852718696 1000102.07808325,499898.164985053 1000102.07808325))",
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_f = out_lyr.GetNextFeature()
|
|
if out_f is not None:
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_ds = None
|
|
|
|
gdal.Unlink("/vsimem/out.mbtiles")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_custom_tiling_scheme():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
srs = osr.SpatialReference()
|
|
srs.SetFromUserInput("WGS84")
|
|
lyr = src_ds.CreateLayer("mylayer", srs=srs)
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("LINESTRING(12 71,13 72)"))
|
|
lyr.CreateFeature(f)
|
|
|
|
out_ds = gdal.VectorTranslate(
|
|
"/vsimem/out",
|
|
src_ds,
|
|
format="MVT",
|
|
datasetCreationOptions=["TILING_SCHEME=EPSG:3067,-548576,8388608,2097152"],
|
|
)
|
|
assert out_ds is not None
|
|
out_ds = None
|
|
|
|
out_ds = ogr.Open("/vsimem/out/1")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
assert out_lyr.GetSpatialRef().ExportToWkt().find("3067") >= 0
|
|
out_f = out_lyr.GetNextFeature()
|
|
if (
|
|
ogrtest.check_feature_geometry(
|
|
out_f, "MULTILINESTRING ((-40160 7944704,21024 8044800))"
|
|
)
|
|
!= 0
|
|
):
|
|
out_f.DumpReadable()
|
|
pytest.fail()
|
|
out_ds = None
|
|
|
|
gdal.RmdirRecursive("/vsimem/out")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
@gdaltest.disable_exceptions()
|
|
def test_ogr_mvt_write_errors():
|
|
|
|
# Raster creation attempt
|
|
if gdal.VSIStatL("/vsimem/foo") is not None:
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
ds = gdal.GetDriverByName("MVT").Create("/vsimem/foo", 1, 1)
|
|
assert ds is None
|
|
|
|
# should have mbtiles extension
|
|
gdal.RmdirRecursive("/vsimem/foo.bar")
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo.bar", options=["FORMAT=MBTILES"]
|
|
)
|
|
assert ds is None
|
|
|
|
# Cannot create temporary database
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["TEMPORARY_DB=/i/do_not/exist.db"]
|
|
)
|
|
assert ds is None
|
|
|
|
# cannot create mbtiles file
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/i/do_not/exist.mbtiles", options=["TEMPORARY_DB=/vsimem/temp.db"]
|
|
)
|
|
assert ds is None
|
|
gdal.Unlink("/vsimem/temp.db")
|
|
|
|
# invalid MINZOOM
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["MINZOOM=-1"]
|
|
)
|
|
assert ds is None
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["MINZOOM=30"]
|
|
)
|
|
assert ds is None
|
|
|
|
# invalid MAXZOOM
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["MAXZOOM=-1"]
|
|
)
|
|
assert ds is None
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["MAXZOOM=30"]
|
|
)
|
|
assert ds is None
|
|
|
|
# invalid MINZOOM vs MAXZOOM
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["MINZOOM=1", "MAXZOOM=0"]
|
|
)
|
|
assert ds is None
|
|
|
|
# invalid MINZOOM for layer
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
lyr = ds.CreateLayer("foo", options=["MINZOOM=-1"])
|
|
assert lyr is None
|
|
|
|
# invalid CONF
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
gdal.FileFromMemBuffer("/vsimem/invalid.json", "foo bar")
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["CONF=/vsimem/invalid.json"]
|
|
)
|
|
gdal.Unlink("/vsimem/invalid.json")
|
|
assert ds is None
|
|
|
|
# TILING_SCHEME not allowed with MBTILES
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo.mbtiles", options=["TILING_SCHEME=EPSG:4326,-180,180,360"]
|
|
)
|
|
assert ds is None
|
|
|
|
# Invalid TILING_SCHEME
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource(
|
|
"/vsimem/foo", options=["TILING_SCHEME=EPSG:4326"]
|
|
)
|
|
assert ds is None
|
|
|
|
# Test failure in creating tile
|
|
gdal.RmdirRecursive("tmp/tmpmvt")
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource("tmp/tmpmvt")
|
|
gdal.RmdirRecursive("tmp/tmpmvt")
|
|
lyr = ds.CreateLayer("test")
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(0 0)"))
|
|
lyr.CreateFeature(f)
|
|
with gdaltest.error_handler():
|
|
ds = None
|
|
assert gdal.GetLastErrorMsg() != ""
|
|
gdal.RmdirRecursive("tmp/tmpmvt")
|
|
|
|
# Test failure in writing in temp db (multi-threaded)
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.config_option("OGR_MVT_REMOVE_TEMP_FILE", "NO"):
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource("/vsimem/foo")
|
|
temp_ds = ogr.Open("/vsimem/foo.temp.db", update=1)
|
|
temp_ds.ExecuteSQL("DROP TABLE temp")
|
|
temp_ds = None
|
|
gdal.Unlink("/vsimem/foo.temp.db")
|
|
lyr = ds.CreateLayer("test")
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("GEOMETRYCOLLECTION(POINT(0 0))"))
|
|
with gdaltest.error_handler():
|
|
lyr.CreateFeature(f)
|
|
ds = None
|
|
assert gdal.GetLastErrorMsg() != ""
|
|
gdal.RmdirRecursive("tmp/tmpmvt")
|
|
|
|
# Test failure in writing in temp db (single-threaded)
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
with gdaltest.config_option("OGR_MVT_REMOVE_TEMP_FILE", "NO"):
|
|
with gdaltest.config_option("GDAL_NUM_THREADS", "1"):
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource("/vsimem/foo")
|
|
temp_ds = ogr.Open("/vsimem/foo.temp.db", update=1)
|
|
temp_ds.ExecuteSQL("DROP TABLE temp")
|
|
temp_ds = None
|
|
gdal.Unlink("/vsimem/foo.temp.db")
|
|
lyr = ds.CreateLayer("test")
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("GEOMETRYCOLLECTION(POINT(0 0))"))
|
|
with gdaltest.error_handler():
|
|
lyr.CreateFeature(f)
|
|
ds = None
|
|
assert gdal.GetLastErrorMsg() != ""
|
|
gdal.RmdirRecursive("tmp/tmpmvt")
|
|
|
|
# Test reprojection failure
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
ds = ogr.GetDriverByName("MVT").CreateDataSource("/vsimem/foo")
|
|
with gdaltest.error_handler():
|
|
lyr = ds.CreateLayer("test", srs=osr.SpatialReference())
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(0 0)"))
|
|
lyr.CreateFeature(f)
|
|
ds = None
|
|
|
|
gdal.RmdirRecursive("/vsimem/foo")
|
|
|
|
|
|
###############################################################################
|
|
#
|
|
|
|
|
|
@pytest.mark.require_driver("SQLite")
|
|
@pytest.mark.require_geos
|
|
def test_ogr_mvt_write_reuse_temp_db():
|
|
|
|
src_ds = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown)
|
|
lyr = src_ds.CreateLayer("mylayer")
|
|
|
|
f = ogr.Feature(lyr.GetLayerDefn())
|
|
f.SetGeometry(ogr.CreateGeometryFromWkt("LINESTRING(0 0,100000 100000,200000 0)"))
|
|
lyr.CreateFeature(f)
|
|
|
|
with gdaltest.config_option("OGR_MVT_REMOVE_TEMP_FILE", "NO"):
|
|
gdal.VectorTranslate("/vsimem/out", src_ds, format="MVT")
|
|
|
|
assert gdal.VSIStatL("/vsimem/out.temp.db") is not None
|
|
|
|
gdal.RmdirRecursive("/vsimem/out")
|
|
|
|
with gdaltest.config_option("OGR_MVT_REUSE_TEMP_FILE", "YES"):
|
|
gdal.VectorTranslate("/vsimem/out", src_ds, format="MVT")
|
|
|
|
out_ds = ogr.Open("/vsimem/out/5")
|
|
assert out_ds is not None
|
|
out_lyr = out_ds.GetLayerByName("mylayer")
|
|
out_f = out_lyr.GetNextFeature()
|
|
assert out_f is not None
|
|
out_ds = None
|
|
|
|
gdal.RmdirRecursive("/vsimem/out")
|
|
gdal.Unlink("/vsimem/out.temp.db")
|
|
|
|
|
|
###############################################################################
|
|
#
|