Skip to content

Commit 5e4ea73

Browse files
authoredApr 26, 2019
Merge pull request #9857 from marcel-dancak/tiles_xyz
New Processing Algorithm to generate raster XYZ tiles
2 parents ebab2e1 + e6ff7e0 commit 5e4ea73

File tree

15 files changed

+1210
-1
lines changed

15 files changed

+1210
-1
lines changed
 

‎python/plugins/processing/algs/help/qgis.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,13 @@ qgis:sumlinelengths: >
509509
qgis:texttofloat: >
510510
This algorithm modifies the type of a given attribute in a vector layer, converting a text attribute containing numeric strings into a numeric attribute.
511511

512+
qgis:tilesxyz: >
513+
This algorithm generates raster XYZ tiles of map canvas content.
514+
515+
Tile images can be saved as individual images in directory structure, or as single file in MBTiles format.
516+
517+
Tile size is fixed to 256x256.
518+
512519
qgis:topologicalcoloring: >
513520
This algorithm assigns a color index to polygon features in such a way that no adjacent polygons share the same color index, whilst minimizing the number of colors required.
514521

‎python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
from .StatisticsByCategories import StatisticsByCategories
135135
from .SumLines import SumLines
136136
from .TextToFloat import TextToFloat
137+
from .TilesXYZ import TilesXYZ
137138
from .TinInterpolation import TinInterpolation
138139
from .TopoColors import TopoColor
139140
from .TruncateTable import TruncateTable
@@ -244,6 +245,7 @@ def getAlgs(self):
244245
StatisticsByCategories(),
245246
SumLines(),
246247
TextToFloat(),
248+
TilesXYZ(),
247249
TinInterpolation(),
248250
TopoColor(),
249251
TruncateTable(),

‎python/plugins/processing/algs/qgis/TilesXYZ.py

Lines changed: 393 additions & 0 deletions
Large diffs are not rendered by default.

‎python/plugins/processing/tests/AlgorithmsTestBase.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,12 @@ def check_algorithm(self, name, defs):
8686
:param defs: A python dict containing a test algorithm definition
8787
"""
8888
self.vector_layer_params = {}
89-
QgsProject.instance().removeAllMapLayers()
89+
QgsProject.instance().clear()
90+
91+
if 'project' in defs:
92+
full_project_path = os.path.join(processingTestDataPath(), defs['project'])
93+
project_read_success = QgsProject.instance().read(full_project_path)
94+
self.assertTrue(project_read_success, 'Failed to load project file: ' + defs['project'])
9095

9196
if 'project_crs' in defs:
9297
QgsProject.instance().setCrs(QgsCoordinateReferenceSystem(defs['project_crs']))
@@ -212,6 +217,9 @@ def load_result_param(self, param):
212217
basename = 'raster.tif'
213218
filepath = os.path.join(outdir, basename)
214219
return filepath
220+
elif param['type'] == 'directory':
221+
outdir = tempfile.mkdtemp()
222+
return outdir
215223

216224
raise KeyError("Unknown type '{}' specified for parameter".format(param['type']))
217225

@@ -350,6 +358,11 @@ def check_results(self, results, context, params, expected):
350358
result_filepath = results[id]
351359

352360
self.assertFilesEqual(expected_filepath, result_filepath)
361+
elif 'directory' == expected_result['type']:
362+
expected_dirpath = self.filepath_from_param(expected_result)
363+
result_dirpath = results[id]
364+
365+
self.assertDirectoriesEqual(expected_dirpath, result_dirpath)
353366
elif 'regex' == expected_result['type']:
354367
with open(results[id], 'r') as file:
355368
data = file.read()

‎python/plugins/processing/tests/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,25 @@ OUTPUT:
194194
- 'Feature Count: 6'
195195
```
196196

197+
#### Directories
198+
199+
You can compare the content of an output directory by en expected result reference directory
200+
201+
```yaml
202+
OUTPUT_DIR:
203+
name: expected/tiles_xyz/test_1
204+
type: directory
205+
```
206+
207+
### Algorithm Context
208+
209+
There are few more definitions that can modify context of the algorithm - these can be specified at top level of test:
210+
211+
- `project` - will load a specified QGIS project file before running the algorithm. If not specified, algorithm will run with empty project
212+
- `project_crs` - overrides the default project CRS - e.g. `EPSG:27700`
213+
- `ellipsoid` - overrides the default project ellipsoid used for measurements - e.g. `GRS80`
214+
215+
197216
Running tests locally
198217
------------------
199218
```bash
6.6 KB

Error rendering embedded code

Invalid image source.

11.4 KB
Loading
4.41 KB
Loading
7.32 KB
Loading
17.4 KB
Loading
3.08 KB
Loading
5.47 KB
Loading

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7524,5 +7524,21 @@ tests:
75247524
name: expected/join_to_nearest_no_matches.gml
75257525
type: vector
75267526

7527+
- name: Generate XYZ tiles
7528+
algorithm: qgis:tilesxyz
7529+
project: ../../../../../tests/testdata/xyztiles.qgs
7530+
project_crs: EPSG:3857
7531+
params:
7532+
EXTENT: -12535000,-9883000,3360000,5349000 [EPSG:3857]
7533+
ZOOM_MIN: 1
7534+
ZOOM_MAX: 3
7535+
TILE_FORMAT: 0 # png
7536+
OUTPUT_FORMAT: 0 # directory
7537+
7538+
results:
7539+
OUTPUT_DIRECTORY:
7540+
type: directory
7541+
name: expected/xyztiles
7542+
75277543

75287544
# See ../README.md for a description of the file format

‎python/testing/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import sys
3030
import difflib
3131
import functools
32+
import filecmp
3233

3334
from qgis.PyQt.QtCore import QVariant
3435
from qgis.core import QgsApplication, QgsFeatureRequest, NULL
@@ -196,6 +197,20 @@ def assertFilesEqual(self, filepath_expected, filepath_result):
196197
diff = list(diff)
197198
self.assertEqual(0, len(diff), ''.join(diff))
198199

200+
def assertDirectoriesEqual(self, dirpath_expected, dirpath_result):
201+
""" Checks whether both directories have the same content (recursively) and raises an assertion error if not. """
202+
dc = filecmp.dircmp(dirpath_expected, dirpath_result)
203+
dc.report_full_closure()
204+
205+
def _check_dirs_equal_recursive(dcmp):
206+
self.assertEqual(dcmp.left_only, [])
207+
self.assertEqual(dcmp.right_only, [])
208+
self.assertEqual(dcmp.diff_files, [])
209+
for sub_dcmp in dcmp.subdirs.values():
210+
_check_dirs_equal_recursive(sub_dcmp)
211+
212+
_check_dirs_equal_recursive(dc)
213+
199214
def assertGeometriesEqual(self, geom0, geom1, geom0_id='geometry 1', geom1_id='geometry 2', precision=14, topo_equal_check=False):
200215
self.checkGeometriesEqual(geom0, geom1, geom0_id, geom1_id, use_asserts=True, precision=precision, topo_equal_check=topo_equal_check)
201216

‎tests/testdata/xyztiles.qgs

Lines changed: 744 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.