Skip to content

Commit 4c11680

Browse files
Merge pull request #530 from hotosm/feature/vector-tiles
Feature : PMtiles , MVT tiles
2 parents 69268bf + 6cee018 commit 4c11680

File tree

9 files changed

+120
-34
lines changed

9 files changed

+120
-34
lines changed

api/serializers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Used by the View classes api/views.py to serialize API responses as JSON or HTML.
66
See DEFAULT_RENDERER_CLASSES setting in core.settings.contrib for the enabled renderers.
77
"""
8+
89
# -*- coding: utf-8 -*-
910
import logging
1011

@@ -113,7 +114,7 @@ class Meta:
113114
"mbtiles_maxzoom",
114115
"pinned",
115116
"unfiltered",
116-
"preserve_geom",
117+
"userinfo",
117118
)
118119
extra_kwargs = {
119120
"the_geom": {"write_only": True},

jobs/migrations/0001_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class Migration(migrations.Migration):
9696
("expire_old_runs", models.BooleanField(default=True)),
9797
("pinned", models.BooleanField(default=False)),
9898
("unfiltered", models.BooleanField(default=False)),
99-
("preserve_geom", models.BooleanField(default=False)),
99+
("userinfo", models.BooleanField(default=False)),
100100
(
101101
"user",
102102
models.ForeignKey(

jobs/models.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ def validate_export_formats(value):
9595
"shp",
9696
"geojson",
9797
"fgb",
98+
"mvt",
99+
"pmtiles",
98100
"csv",
99101
"sql",
100102
"geopackage",
@@ -203,7 +205,7 @@ class Job(models.Model):
203205
expire_old_runs = models.BooleanField(default=True)
204206
pinned = models.BooleanField(default=False)
205207
unfiltered = models.BooleanField(default=False)
206-
preserve_geom = models.BooleanField(default=False)
208+
userinfo = models.BooleanField(default=False)
207209

208210
class Meta: # pragma: no cover
209211
managed = True

tasks/task_runners.py

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ def finish_task(name, created_files=None, response_back=None, planet_file=False)
254254
total_bytes += file.size()
255255
task.filesize_bytes = total_bytes
256256
LOG.debug(total_bytes)
257-
257+
258258
task.save()
259259

260260
is_hdx_export = HDXExportRegion.objects.filter(job_id=run.job_id).exists()
@@ -271,6 +271,8 @@ def finish_task(name, created_files=None, response_back=None, planet_file=False)
271271
"kml",
272272
"shp",
273273
"fgb",
274+
"mvt",
275+
"pmtiles",
274276
"csv",
275277
"sql",
276278
"mbtiles",
@@ -673,17 +675,16 @@ def add_metadata(z, theme):
673675
mapping_filter = mapping
674676
if job.unfiltered:
675677
mapping_filter = None
678+
userinfo = job.userinfo
676679

677680
if "geojson" in export_formats:
678-
preserved_geom = geom
679-
if job.preserve_geom:
680-
preserved_geom = load_geometry(job.the_geom.json)
681681
geojson = Galaxy(
682682
settings.RAW_DATA_API_URL,
683-
preserved_geom,
683+
geom,
684684
mapping=mapping_filter,
685685
file_name=valid_name,
686686
access_token=settings.RAW_DATA_ACCESS_TOKEN,
687+
userinfo=userinfo,
687688
)
688689
start_task("geojson")
689690

@@ -694,6 +695,7 @@ def add_metadata(z, theme):
694695
mapping=mapping_filter,
695696
file_name=valid_name,
696697
access_token=settings.RAW_DATA_ACCESS_TOKEN,
698+
userinfo=userinfo,
697699
)
698700
start_task("fgb")
699701

@@ -714,6 +716,7 @@ def add_metadata(z, theme):
714716
mapping=mapping_filter,
715717
file_name=valid_name,
716718
access_token=settings.RAW_DATA_ACCESS_TOKEN,
719+
userinfo=userinfo,
717720
)
718721
start_task("sql")
719722

@@ -724,6 +727,7 @@ def add_metadata(z, theme):
724727
mapping=mapping_filter,
725728
file_name=valid_name,
726729
access_token=settings.RAW_DATA_ACCESS_TOKEN,
730+
userinfo=userinfo,
727731
)
728732
# geopackage = tabular.Geopackage(join(stage_dir,valid_name),mapping)
729733
# tabular_outputs.append(geopackage)
@@ -736,6 +740,7 @@ def add_metadata(z, theme):
736740
mapping=mapping_filter,
737741
file_name=valid_name,
738742
access_token=settings.RAW_DATA_ACCESS_TOKEN,
743+
userinfo=userinfo,
739744
)
740745
start_task("shp")
741746

@@ -746,6 +751,7 @@ def add_metadata(z, theme):
746751
mapping=mapping_filter,
747752
file_name=valid_name,
748753
access_token=settings.RAW_DATA_ACCESS_TOKEN,
754+
userinfo=userinfo,
749755
)
750756
# kml = tabular.Kml(join(stage_dir,valid_name),mapping)
751757
# tabular_outputs.append(kml)
@@ -910,6 +916,7 @@ def add_metadata(z, theme):
910916
mapping=mapping_filter,
911917
file_name=valid_name,
912918
access_token=settings.RAW_DATA_ACCESS_TOKEN,
919+
userinfo=userinfo,
913920
)
914921
start_task("mbtiles")
915922
LOG.debug(
@@ -934,6 +941,68 @@ def add_metadata(z, theme):
934941
stop_task("mbtiles")
935942
raise ex
936943

944+
if "pmtiles" in export_formats:
945+
try:
946+
pmtiles = Galaxy(
947+
settings.RAW_DATA_API_URL,
948+
geom,
949+
mapping=mapping_filter,
950+
file_name=valid_name,
951+
access_token=settings.RAW_DATA_ACCESS_TOKEN,
952+
userinfo=userinfo,
953+
)
954+
start_task("pmtiles")
955+
LOG.debug(
956+
"Raw Data API fetch started for pmtiles run: {0}".format(run_uid)
957+
)
958+
all_feature_filter_json = join(
959+
os.getcwd(), "tasks/tests/fixtures/all_features_filters.json"
960+
)
961+
response_back = pmtiles.fetch(
962+
"pmtiles",
963+
all_feature_filter_json=all_feature_filter_json,
964+
min_zoom=job.mbtiles_minzoom,
965+
max_zoom=job.mbtiles_maxzoom,
966+
)
967+
write_file_size(response_back)
968+
LOG.debug(
969+
"Raw Data API fetch ended for mbtiles run: {0}".format(run_uid)
970+
)
971+
finish_task("pmtiles", response_back=response_back)
972+
973+
except Exception as ex:
974+
stop_task("pmtiles")
975+
raise ex
976+
977+
if "mvt" in export_formats:
978+
try:
979+
mvt = Galaxy(
980+
settings.RAW_DATA_API_URL,
981+
geom,
982+
mapping=mapping_filter,
983+
file_name=valid_name,
984+
access_token=settings.RAW_DATA_ACCESS_TOKEN,
985+
userinfo=userinfo,
986+
)
987+
start_task("mvt")
988+
LOG.debug("Raw Data API fetch started for mvt run: {0}".format(run_uid))
989+
all_feature_filter_json = join(
990+
os.getcwd(), "tasks/tests/fixtures/all_features_filters.json"
991+
)
992+
response_back = mvt.fetch(
993+
"mvt",
994+
all_feature_filter_json=all_feature_filter_json,
995+
min_zoom=job.mbtiles_minzoom,
996+
max_zoom=job.mbtiles_maxzoom,
997+
)
998+
write_file_size(response_back)
999+
LOG.debug("Raw Data API fetch ended for mvt run: {0}".format(run_uid))
1000+
finish_task("mvt", response_back=response_back)
1001+
1002+
except Exception as ex:
1003+
stop_task("mvt")
1004+
raise ex
1005+
9371006
if use_only_galaxy == False:
9381007
LOG.debug("Source start for run: {0}".format(run_uid))
9391008
source_path = source.path()

ui/app/actions/exports.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export const cloneExport = e => (dispatch, getState) => {
6464
name: e.name,
6565
published: e.published,
6666
unfiltered: e.unfiltered,
67-
preserve_geom: e.preserve_geom,
67+
userinfo: e.userinfo,
6868
the_geom: rsp.data.the_geom,
6969
aoi: {
7070
description: "Cloned Area",

ui/app/components/Summary.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ const messages = defineMessages({
1515
// id: "export.bundle_for_posm.description",
1616
// defaultMessage: "Bundle for POSM"
1717
// },
18-
preserveGeometry: {
19-
id: "export.preserve_geom.description",
20-
defaultMessage: "Preserve Geometry - Avoid simplify ( Only supports for geojson )"
18+
userinfo: {
19+
id: "export.userinfo.description",
20+
defaultMessage: "Include user info on exports"
2121
},
2222
publishedDescription: {
2323
id: "export.published.description",
@@ -84,12 +84,12 @@ export default injectIntl(
8484
component={renderCheckbox}
8585
type="checkbox"
8686
/> */}
87-
{/* <Field
88-
name="preserve_geom"
89-
description={formatMessage(messages.preserveGeometry)}
87+
<Field
88+
name="userinfo"
89+
description={formatMessage(messages.userinfo)}
9090
component={renderCheckbox}
9191
type="checkbox"
92-
/> */}
92+
/>
9393
<Button
9494
bsStyle="danger"
9595
disabled={submitting}

ui/app/components/help/ExportFormats.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export default () =>
101101
</ul>
102102
</div>
103103
<div>
104-
<h2 id="gpkg">GeoJSON .geojson</h2>
104+
<h2 id="geojson">GeoJSON .geojson</h2>
105105
<p>
106106
GeoJSON is an open standard geospatial data interchange format that represents simple geographic features and their nonspatial attributes. Based on JavaScript Object Notation (JSON), GeoJSON is a format for encoding a variety of geographic data structures. It uses a geographic coordinate reference system, World Geodetic System 1984, and units of decimal degrees.
107107
</p>
@@ -142,7 +142,7 @@ export default () =>
142142
</ul>
143143
</div>
144144
<div>
145-
<h2 id="gpkg">FlatGeobuf .fgb</h2>
145+
<h2 id="fgb">FlatGeobuf .fgb</h2>
146146
<p>
147147
FlatGeobuf is a binary file format for storing geospatial vector data in a compact and efficient manner. It uses a hierarchical structure to organize features into layers, and stores attribute data in a separate file.
148148
</p>
@@ -183,7 +183,7 @@ export default () =>
183183
</ul>
184184
</div>
185185
<div>
186-
<h2 id="gpkg">CSV .csv</h2>
186+
<h2 id="csv">CSV .csv</h2>
187187
<p>
188188
CSV is a file format for storing tabular data in plain text format. Each row of data represents a record, and each column represents a field of that record. CSV files are widely used because they are simple and easy to create and manipulate, making them a popular choice for data exchange. </p>
189189
<h4>
@@ -203,7 +203,7 @@ export default () =>
203203
</ul>
204204
</div>
205205
<div>
206-
<h2 id="gpkg">SQL .sql</h2>
206+
<h2 id="sql">SQL .sql</h2>
207207
<p>
208208
SQL files are plain text files that contain SQL commands to create, modify or interact with a relational database. They can be used to define database schemas, constraints, and indexes, as well as to insert, update, and query data.
209209
</p>

ui/app/components/utils.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ export const AVAILABLE_EXPORT_FORMATS = {
6363
MBTiles <code>.mbtiles</code>
6464
</span>
6565
),
66+
pmtiles: (
67+
<span key="pmtiles">
68+
Pmtiles <code>.pmtiles</code>
69+
</span>
70+
),
71+
mvt: (
72+
<span key="mvt">
73+
Mapbox Vector Tiles <code>.mvt</code>
74+
</span>
75+
),
6676
garmin_img: (
6777
<span key="garmin_img">
6878
Garmin <code>.img</code>
@@ -99,6 +109,8 @@ export const REQUIRES_FEATURE_SELECTION = {
99109
shp: true,
100110
geojson:true,
101111
fgb:true,
112+
mvt:true,
113+
pmtiles:true,
102114
sql:true,
103115
csv:true,
104116
geopackage: true,
@@ -110,12 +122,14 @@ export const REQUIRES_FEATURE_SELECTION = {
110122
};
111123

112124
export const REQUIRES_TILE_SOURCE = {
113-
mbtiles: true
125+
mbtiles: true,
126+
pmtiles:true,
127+
mvt:true,
114128
};
115129

116130
export const OMIT_FROM_FORMAT_OPTIONS = {
117131
osm_xml: true,
118-
bundle: true
132+
bundle: true
119133
};
120134

121135
export const getRootUrl = () => {

utils/aoi_utils.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@
1111
# be buffered efficiently, they must be simplified first.
1212
# so first simplify them to 0.01 degrees.
1313

14+
1415
def force2d(geom):
1516
# force geom to be 2d: https://groups.google.com/forum/#!topic/django-users/7c1NZ76UwRU
1617
wkt = wkt_w(dim=2).write(geom).decode()
1718
return GEOSGeometry(wkt)
1819

19-
def simplify_geom(geom,force_buffer=False, preserve_geom=False):
20-
if preserve_geom is False:
21-
if geom.num_coords > 10000:
22-
geom = geom.simplify(0.01)
23-
if geom.num_coords > 500:
24-
geom = geom.buffer(0.02)
25-
param = 0.01
26-
while geom.num_coords > 500:
27-
geom = geom.simplify(param, preserve_topology=True)
28-
param = param * 2
20+
21+
def simplify_geom(geom, force_buffer=False):
22+
if geom.num_coords > 10000:
23+
geom = geom.simplify(0.01)
24+
if geom.num_coords > 500:
25+
geom = geom.buffer(0.02)
26+
param = 0.01
27+
while geom.num_coords > 500:
28+
geom = geom.simplify(param, preserve_topology=True)
29+
param = param * 2
2930
if force_buffer:
30-
geom = geom.buffer(0.02)
31+
geom = geom.buffer(0.02)
3132
return geom
32-

0 commit comments

Comments
 (0)