Skip to content

Commit 3186e15

Browse files
committed
init
1 parent 2b43e4f commit 3186e15

File tree

12 files changed

+412
-0
lines changed

12 files changed

+412
-0
lines changed

.circleci/config.yml

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
version: 2
2+
common: &common
3+
working_directory: ~/rio-tiler-mvt
4+
steps:
5+
- checkout
6+
- run:
7+
name: install dependencies
8+
command: pip install tox codecov pre-commit --user
9+
- run:
10+
name: run tox
11+
command: ~/.local/bin/tox
12+
- run:
13+
name: run pre-commit
14+
command: |
15+
if [[ "$CIRCLE_JOB" == "python-3.6" ]]; then
16+
~/.local/bin/pre-commit run --all-files
17+
fi
18+
- run:
19+
name: upload coverage report
20+
command: |
21+
if [[ "$UPLOAD_COVERAGE" == 1 ]]; then
22+
~/.local/bin/coverage xml
23+
~/.local/bin/codecov
24+
fi
25+
when: always
26+
27+
jobs:
28+
"python-3.6":
29+
<<: *common
30+
docker:
31+
- image: circleci/python:3.6.5
32+
environment:
33+
- TOXENV=py36
34+
- UPLOAD_COVERAGE=1
35+
36+
"python-3.7":
37+
<<: *common
38+
docker:
39+
- image: circleci/python:3.7.2
40+
environment:
41+
- TOXENV=py37
42+
43+
deploy:
44+
docker:
45+
- image: circleci/python:3.7.2
46+
environment:
47+
- TOXENV=release
48+
working_directory: ~/rio-tiler-mvt
49+
steps:
50+
- checkout
51+
- run:
52+
name: verify git tag vs. version
53+
command: |
54+
VERSION=$(python -c 'import rio_tiler_mvt; print(rio_tiler_mvt.version)')
55+
if [ "$VERSION" = "$CIRCLE_TAG" ]; then exit 0; else exit 3; fi
56+
- run:
57+
name: install dependencies
58+
command: pip install tox --user
59+
- run:
60+
name: init .pypirc
61+
command: |
62+
echo -e "[pypi]" >> ~/.pypirc
63+
echo -e "username = $PYPI_USER" >> ~/.pypirc
64+
echo -e "password = $PYPI_PASSWORD" >> ~/.pypirc
65+
- run:
66+
name: run tox
67+
command: ~/.local/bin/tox
68+
69+
workflows:
70+
version: 2
71+
build_and_deploy:
72+
jobs:
73+
- "python-3.6"
74+
- "python-3.7":
75+
filters: # required since `deploy` has tag filters AND requires `build`
76+
tags:
77+
only: /.*/
78+
- deploy:
79+
requires:
80+
- "python-3.7"
81+
filters:
82+
tags:
83+
only: /^[0-9]+.*/
84+
branches:
85+
ignore: /.*/

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,5 @@ venv.bak/
102102

103103
# mypy
104104
.mypy_cache/
105+
106+
rio_tiler_mvt/mvt.c

.pre-commit-config.yaml

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
repos:
3+
-
4+
repo: 'https://github.com/ambv/black'
5+
# 18.6b1
6+
rev: ed50737290662f6ef4016a7ea44da78ee1eff1e2
7+
hooks:
8+
- id: black
9+
args: ['--safe']
10+
language_version: python3.6
11+
-
12+
repo: 'https://github.com/pre-commit/pre-commit-hooks'
13+
# v1.3.0
14+
rev: a6209d8d4f97a09b61855ea3f1fb250f55147b8b
15+
hooks:
16+
- id: flake8
17+
language_version: python3.6
18+
args: [
19+
# E501 let black handle all line length decisions
20+
# W503 black conflicts with "line break before operator" rule
21+
# E203 black conflicts with "whitespace before ':'" rule
22+
'--ignore=E501,W503,E203']
23+
-
24+
repo: 'https://github.com/chewse/pre-commit-mirrors-pydocstyle'
25+
# 2.1.1
26+
rev: 22d3ccf6cf91ffce3b16caa946c155778f0cb20f
27+
hooks:
28+
- id: pydocstyle
29+
language_version: python3.6
30+
args: [
31+
# Check for docstring presence only
32+
'--select=D1',
33+
# Don't require docstrings for tests
34+
'--match=(?!test).*\.py']

README.md

+69
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,71 @@
11
# rio-tiler-mvt
2+
3+
[![Packaging status](https://badge.fury.io/py/rio-tiler-mvt.svg)](https://badge.fury.io/py/rio-tiler-mvt)
4+
[![CircleCI](https://circleci.com/gh/cogeotiff/rio-tiler-mvt.svg?style=svg)](https://codecov.io/gh/cogeotiff/rio-tiler-mvt)
5+
[![codecov](https://codecov.io/gh/cogeotiff/rio-tiler-mvt/branch/master/graph/badge.svg)](https://circleci.com/gh/cogeotiff/rio-tiler-mvt)
6+
7+
28
A rio-tiler plugin to translate tile array to MVT (using python-vtzero)
9+
10+
![](https://user-images.githubusercontent.com/10407788/57476379-72cf6000-7264-11e9-979d-bf9f486518c2.png)
11+
12+
https://medium.com/devseed/cog-talk-part-1-whats-new-941facbcd3d1
13+
14+
## Install
15+
16+
### Requirements
17+
18+
rio-tiler-mvt use [python-vtzero](https://github.com/tilery/python-vtzero) wrapper to encode point and polygons to MVT. Because VTZERO is a C++ library, python-vtzero is written in Cython, thus cython~=0.28 is required to compile this library.
19+
20+
```bash
21+
$ pip install cython~=0.28 # see https://github.com/tilery/python-vtzero#requirements
22+
23+
$ pip install rio-tiler-mvt
24+
```
25+
Or
26+
```bash
27+
$ git clone https://github.com/cogeotiff/rio-tiler-mvt
28+
$ cd rio-tiler-mvt
29+
$ pip install -e .
30+
```
31+
32+
## Rio-tiler + Mapbox Vector tiles
33+
34+
### API
35+
36+
`mvt.encoder(data, mask, band_names=[], layer_name="my_layer", feature_type="point")`
37+
38+
Inputs:
39+
- data : raster tile data to encode
40+
- mask : mask data
41+
- band_names : Raster band's names
42+
- layer_name : Layer name
43+
- feature_type : Feature type (point or polygon)
44+
45+
Returns:
46+
- mvt : Mapbox Vector Tile encoded data.
47+
48+
49+
## Contribution & Development
50+
51+
Issues and pull requests are more than welcome.
52+
53+
**dev install**
54+
55+
```bash
56+
$ git clone https://github.com/cogeotiff/rio-tiler-mvt.git
57+
$ cd rio-tiler-mvt
58+
$ pip install -e .[dev]
59+
```
60+
61+
**Python3.6 only**
62+
63+
This repo is set to use `pre-commit` to run *flake8*, *pydocstring* and *black* ("uncompromising Python code formatter") when commiting new code.
64+
65+
```bash
66+
$ pre-commit install
67+
```
68+
69+
70+
## Implementation
71+
[cogeo-mosaic](https://github.com/developmentseed/cogeo-mosaic.git)

codecov.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
comment: off
2+
3+
coverage:
4+
status:
5+
project:
6+
default:
7+
target: auto
8+
threshold: 5

requirements.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
numpy
2+
vtzero

rio_tiler_mvt/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""rio-tiler-mvt: MVT encoder."""
2+
3+
import pkg_resources
4+
5+
version = pkg_resources.get_distribution(__package__).version

rio_tiler_mvt/mvt.pyx

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
import numpy
3+
4+
from vtzero.tile import Tile, Layer, Point, Polygon
5+
6+
cimport numpy
7+
8+
cpdef bytes encoder(
9+
data,
10+
mask,
11+
list band_names = [],
12+
str layer_name = "my_layer",
13+
str feature_type = "point",
14+
):
15+
cdef int sc = 4096 // data.shape[1]
16+
cdef tuple indexes = numpy.where(mask)
17+
18+
cdef tuple idx
19+
cdef int x, y
20+
21+
if not band_names:
22+
band_names = [
23+
f"band{ix}" for ix in range(1, data.shape[0] + 1)
24+
]
25+
26+
mvt = Tile()
27+
mvt_layer = Layer(mvt, layer_name.encode())
28+
for idx in zip(indexes[1], indexes[0]):
29+
x, y = idx
30+
x *= sc
31+
y *= sc
32+
33+
if feature_type == 'point':
34+
feature = Point(mvt_layer)
35+
feature.add_point(x + sc / 2, y - sc / 2)
36+
37+
elif feature_type == 'polygon':
38+
feature = Polygon(mvt_layer)
39+
feature.add_ring(5)
40+
feature.set_point(x, y)
41+
feature.set_point(x + sc, y)
42+
feature.set_point(x + sc, y - sc)
43+
feature.set_point(x, y - sc)
44+
feature.set_point(x, y)
45+
46+
# TODO: fix https://github.com/tilery/python-vtzero/issues/3
47+
for bidx in range(data.shape[0]):
48+
feature.add_property(
49+
band_names[bidx].encode(),
50+
str(data[bidx, idx[1], idx[0]]).encode()
51+
)
52+
feature.commit()
53+
54+
return mvt.serialize()

setup.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""Setup for rio-tiler-mvt."""
2+
3+
from setuptools.extension import Extension
4+
from setuptools import setup, find_packages
5+
from Cython.Build import cythonize
6+
7+
import numpy
8+
9+
# Runtime requirements.
10+
inst_reqs = ["numpy", "vtzero"]
11+
12+
vt = "vector-tile-base @ git+https://github.com/mapbox/vector-tile-base"
13+
extra_reqs = {
14+
"test": [vt, "rio-tiler", "pytest", "pytest-cov"],
15+
"dev": [vt, "rio-tiler", "pytest", "pytest-cov", "pre-commit"],
16+
}
17+
18+
ext_options = {"include_dirs": [numpy.get_include()]}
19+
ext_modules = cythonize(
20+
[
21+
Extension(
22+
"rio_tiler_mvt.mvt",
23+
["rio_tiler_mvt/mvt.pyx"],
24+
**ext_options
25+
)
26+
]
27+
)
28+
29+
setup(
30+
name="rio-tiler-mvt",
31+
version="0.0.1b",
32+
description=u"""A rio-tiler plugin to encode tile array to MVT""",
33+
python_requires=">=3",
34+
classifiers=[
35+
"Intended Audience :: Information Technology",
36+
"Intended Audience :: Science/Research",
37+
"License :: OSI Approved :: BSD License",
38+
"Programming Language :: Python :: 3.6",
39+
"Topic :: Scientific/Engineering :: GIS",
40+
],
41+
keywords="COG MVT mapbox vectortile GIS",
42+
author=u"Vincent Sarago",
43+
author_email="[email protected]",
44+
url="https://github.com/cogeotiff/rio-tiler-mvt",
45+
license="BSD",
46+
packages=find_packages(exclude=["ez_setup", "examples", "tests"]),
47+
include_package_data=True,
48+
zip_safe=False,
49+
install_requires=inst_reqs,
50+
extras_require=extra_reqs,
51+
ext_modules=ext_modules,
52+
)

tests/fixtures/test.tif

290 KB
Binary file not shown.

tests/test_mvt.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""tests ard_tiler.mosaic."""
2+
3+
import os
4+
5+
from rio_tiler.main import tile as cogTiler
6+
from rio_tiler_mvt.mvt import encoder
7+
8+
import vector_tile_base
9+
10+
asset = os.path.join(os.path.dirname(__file__), "fixtures", "test.tif")
11+
x = 72
12+
y = 63
13+
z = 7
14+
15+
tile, mask = cogTiler(asset, x, y, z)
16+
17+
18+
def test_mvt_encoder():
19+
"""Test MVT encoder."""
20+
# test with default
21+
vt = encoder(tile, mask)
22+
mvt = vector_tile_base.VectorTile(vt)
23+
assert len(mvt.layers) == 1
24+
layer = mvt.layers[0]
25+
assert layer.name == "my_layer"
26+
assert layer.extent == 4096
27+
assert layer.version == 2
28+
assert len(layer.features) == 16
29+
feat = layer.features[0]
30+
assert feat.type == "point"
31+
props = feat.properties
32+
assert len(props) == 1
33+
assert props["band1"] == "14.9334077835083"
34+
35+
# Test polygon
36+
vt = encoder(tile, mask, feature_type="polygon")
37+
mvt = vector_tile_base.VectorTile(vt)
38+
layer = mvt.layers[0]
39+
feat = layer.features[0]
40+
assert feat.type == "polygon"
41+
props = feat.properties
42+
assert props["band1"] == "14.9334077835083"
43+
44+
# Test band name
45+
vt = encoder(tile, mask, band_names=["pop"])
46+
mvt = vector_tile_base.VectorTile(vt)
47+
props = mvt.layers[0].features[0].properties
48+
assert props["pop"] == "14.9334077835083"
49+
50+
# Test layer name
51+
vt = encoder(tile, mask, layer_name="facebook")
52+
mvt = vector_tile_base.VectorTile(vt)
53+
assert len(mvt.layers) == 1
54+
layer = mvt.layers[0]
55+
assert layer.name == "facebook"

0 commit comments

Comments
 (0)