Skip to content
Commits on Source (6)
......@@ -30,6 +30,15 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: [ 'libstdc++-5-dev', 'xutils-dev']
# test a build with sse disabled
- os: linux
sudo: false
compiler: ": clang"
env: JOBS=10 SSE_MATH=false CXX="ccache clang++-4.0 -Qunused-arguments"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: [ 'libstdc++-5-dev', 'xutils-dev']
- os: linux
sudo: false
compiler: ": clang-coverage"
......
# Changelog
## 1.6.0
- Bug fix for possible massive allocations in invalid vector tiles
- Fixed mercator bounding box code so that it does not require tile size, removed spherical mercator class
- Added the ability to use SSE code to improve the performance of simplification prior to vector tile creation.
## 1.5.0
- Added back ability to build against external mapnik (see docs for instructions)
......
GYP_REVISION=3464008
SSE_MATH ?= true
default: release
mason_packages/.link/bin:
......@@ -16,7 +18,7 @@ pre_build_check:
git clone https://chromium.googlesource.com/external/gyp.git ./deps/gyp && cd ./deps/gyp && git checkout $(GYP_REVISION)
build/Makefile: pre_build_check ./deps/gyp gyp/build.gyp test/*
deps/gyp/gyp gyp/build.gyp --depth=. -DMAPNIK_PLUGINDIR=\"$(shell mapnik-config --input-plugins)\" -Goutput_dir=. --generator-output=./build -f make
deps/gyp/gyp gyp/build.gyp -Denable_sse=$(SSE_MATH) --depth=. -DMAPNIK_PLUGINDIR=\"$(shell mapnik-config --input-plugins)\" -Goutput_dir=. --generator-output=./build -f make
$(MAKE) -C build/ V=$(V)
release: mason_packages/.link/bin/mapnik-config Makefile
......
......@@ -33,6 +33,12 @@ If you have Mapnik, libprotobuf, and all the Mapnik deps already installed on yo
make release_base
Note: SSE optimizations are enabled by default. If you want to turn them off do:
```
SSE_MATH=false make
```
If building against an external Mapnik please know that Mapnik Vector Tile does not currently support Mapnik 3.1.x.
- mapnik-vector-tile >=1.4.x depends on Mapnik >=v3.0.14
......
......@@ -133,7 +133,7 @@ int main(int argc, char** argv)
unsigned tile_size = layer_extent;
int buffer_size = 0;
mapnik::box2d<double> bbox = mapnik::vector_tile_impl::merc_extent(tile_size, x, y, z);
mapnik::box2d<double> bbox = mapnik::vector_tile_impl::tile_mercator_bbox(x, y, z);
// Create a fresh map to render into a tile
mapnik::Map map(tile_size,tile_size,"+init=epsg:3857");
......
......@@ -37,10 +37,7 @@ int main()
mapnik::proj_transform prj_trans(merc,merc); // no-op
mapnik::proj_transform prj_trans2(merc2,merc); // op
unsigned tile_size = 256;
mapnik::vector_tile_impl::spherical_mercator merc_tiler(tile_size);
double minx,miny,maxx,maxy;
merc_tiler.xyz(9664,20435,15,minx,miny,maxx,maxy);
mapnik::box2d<double> z15_extent(minx,miny,maxx,maxy);
mapnik::box2d<double> z15_extent = mapnik::vector_tile_impl::tile_mercator_bbox(9664,20435,15);
unsigned path_multiplier = 16;
mapnik::view_transform tr(tile_size * path_multiplier,
tile_size * path_multiplier,
......
mapnik-vector-tile (1.6.0+dfsg-1) unstable; urgency=medium
* Team upload.
* New upstream release.
* Refresh patches.
* Check DEB_BUILD_PROFILES to nocheck in dh_auto_test override.
-- Bas Couwenberg <sebastic@debian.org> Thu, 08 Feb 2018 16:24:01 +0100
mapnik-vector-tile (1.5.0+dfsg-3) unstable; urgency=medium
* Team upload.
......
......@@ -4,7 +4,7 @@ Forwarded: not-needed
--- a/Makefile
+++ b/Makefile
@@ -28,10 +28,7 @@ debug: mason_packages/.link/bin/mapnik-c
@@ -30,10 +30,7 @@ debug: mason_packages/.link/bin/mapnik-c
# note: we set PATH to the mason bins to pick up protoc
# and CXXFLAGS/LDFLAGS to find protobuf headers/libs
# This will only find mason installed mapnik-config if run via the `release` or `debug` targets
......
......@@ -4,7 +4,7 @@ Forwarded: not-needed
--- a/gyp/build.gyp
+++ b/gyp/build.gyp
@@ -37,7 +37,8 @@
@@ -38,7 +38,8 @@
"<(SHARED_INTERMEDIATE_DIR)/vector_tile.pb.cc"
],
'include_dirs': [
......@@ -12,9 +12,9 @@ Forwarded: not-needed
+ '<(SHARED_INTERMEDIATE_DIR)/',
+ '/usr/include'
],
'cflags_cc' : [
'-D_THREAD_SAFE',
@@ -55,7 +56,8 @@
'conditions': [
['enable_sse == "true"', {
@@ -61,7 +62,8 @@
},
'direct_dependent_settings': {
'include_dirs': [
......@@ -24,7 +24,7 @@ Forwarded: not-needed
],
'libraries':[
'-lprotobuf-lite'
@@ -91,7 +93,8 @@
@@ -102,7 +104,8 @@
},
'direct_dependent_settings': {
'include_dirs': [
......
......@@ -23,8 +23,10 @@ override_dh_auto_build:
dh_auto_build -- release_base
override_dh_auto_test:
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
python debian/create-raster.py
dh_auto_test || echo "Ignoring test failures"
endif
override_dh_installexamples:
dh_installexamples
......
......@@ -4,8 +4,9 @@
],
'variables': {
'MAPNIK_PLUGINDIR%': '',
'enable_sse%':'true',
'common_defines' : [
'MAPNIK_VECTOR_TILE_LIBRARY=1',
'MAPNIK_VECTOR_TILE_LIBRARY=1'
]
},
"targets": [
......@@ -39,6 +40,11 @@
'include_dirs': [
'<(SHARED_INTERMEDIATE_DIR)/'
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
'cflags_cc' : [
'-D_THREAD_SAFE',
'<!@(mapnik-config --cflags)',
......@@ -81,6 +87,11 @@
'defines' : [
"<@(common_defines)"
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
'cflags_cc' : [
'<!@(mapnik-config --cflags)'
],
......@@ -123,6 +134,11 @@
"<@(common_defines)",
"MAPNIK_PLUGINDIR=<(MAPNIK_PLUGINDIR)"
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
"sources": [
"<!@(find ../test/ -name '*.cpp')"
],
......@@ -140,6 +156,11 @@
"<@(common_defines)",
"MAPNIK_PLUGINDIR=<(MAPNIK_PLUGINDIR)"
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
"sources": [
"../bench/vtile-transform.cpp"
],
......@@ -155,6 +176,11 @@
"<@(common_defines)",
"MAPNIK_PLUGINDIR=<(MAPNIK_PLUGINDIR)"
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
"sources": [
"../bench/vtile-decode.cpp"
],
......@@ -170,6 +196,11 @@
"<@(common_defines)",
"MAPNIK_PLUGINDIR=<(MAPNIK_PLUGINDIR)"
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
"sources": [
"../bench/vtile-encode.cpp"
],
......@@ -185,6 +216,11 @@
"<@(common_defines)",
"MAPNIK_PLUGINDIR=<(MAPNIK_PLUGINDIR)"
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
"sources": [
"../bin/vtile-edit.cpp"
],
......@@ -199,6 +235,11 @@
"sources": [
"../examples/c++/tileinfo.cpp"
],
'conditions': [
['enable_sse == "true"', {
'defines' : [ 'SSE_MATH' ]
}]
],
"include_dirs": [
"../src"
],
......
......@@ -9,7 +9,7 @@ function install() {
}
ICU_VERSION="57.1"
MASON_VERSION="v0.14.2"
MASON_VERSION="9a3f4d195614bb30d9ca54dd6070739de605cb14"
if [ ! -f ./mason/mason.sh ]; then
mkdir -p ./mason
......@@ -35,14 +35,14 @@ if [[ ${SKIP_MAPNIK_INSTALL:-} != 'YES' ]] && [[ ! -f ./mason_packages/.link/bin
install cairo 1.14.8
install webp 0.6.0
install libgdal 2.1.3
install boost 1.63.0
install boost_libsystem 1.63.0
install boost_libfilesystem 1.63.0
install boost_libregex_icu57 1.63.0
install boost 1.65.1
install boost_libsystem 1.65.1
install boost_libfilesystem 1.65.1
install boost_libregex_icu57 1.65.1
install freetype 2.7.1
install harfbuzz 1.4.2-ft
# mapnik
install mapnik 3.0.14
install mapnik 3.0.18
fi
{
"name": "mapnik-vector-tile",
"version": "1.5.0",
"version": "1.6.0",
"description": "Mapnik Vector Tile API",
"main": "include_dirs.js",
"repository" : {
......
......@@ -19,7 +19,7 @@ namespace mapnik
namespace vector_tile_impl
{
void composite(merc_tile & target_vt,
inline void composite(merc_tile & target_vt,
std::vector<merc_tile_ptr> const& vtiles,
mapnik::Map & map,
processor & ren, // processor should be on map object provided
......
......@@ -219,10 +219,7 @@ void tile_datasource_pbf::set_envelope(box2d<double> const& bbox)
box2d<double> tile_datasource_pbf::get_tile_extent() const
{
spherical_mercator merc(tile_size_);
double minx,miny,maxx,maxy;
merc.xyz(x_,y_,z_,minx,miny,maxx,maxy);
return box2d<double>(minx,miny,maxx,maxy);
return tile_mercator_bbox(x_, y_, z_);
}
box2d<double> tile_datasource_pbf::envelope() const
......
......@@ -40,6 +40,13 @@
// std
#include <vector>
#include <limits>
#ifdef SSE_MATH
// simd
#include <xmmintrin.h>
#include <emmintrin.h>
#endif
namespace mapnik
{
......@@ -67,14 +74,14 @@ struct douglas_peucker_point
}
};
template <typename value_type, typename calc_type>
inline void consider(typename std::vector<douglas_peucker_point<value_type> >::iterator begin,
typename std::vector<douglas_peucker_point<value_type> >::iterator end,
calc_type const& max_dist)
template <typename Range>
inline void consider(Range const& vec,
std::vector<bool> & included,
std::size_t begin_idx,
std::size_t last_idx,
double max_dist)
{
typedef typename std::vector<douglas_peucker_point<value_type> >::iterator iterator_type;
std::size_t size = end - begin;
std::size_t size = last_idx - begin_idx + 1;
// size must be at least 3
// because we want to consider a candidate point in between
......@@ -83,12 +90,9 @@ inline void consider(typename std::vector<douglas_peucker_point<value_type> >::i
return;
}
iterator_type last = end - 1;
// Find most far point, compare to the current segment
calc_type md(-1.0); // any value < 0
iterator_type candidate;
{
double md = -1.0; // any value < 0
std::size_t candidate = begin_idx + 1;
/*
Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
VECTOR v(x2 - x1, y2 - y1)
......@@ -98,42 +102,178 @@ inline void consider(typename std::vector<douglas_peucker_point<value_type> >::i
b = c1 / c2
RETURN POINT(x1 + b * vx, y1 + b * vy)
*/
calc_type const v_x = last->p.x - begin->p.x;
calc_type const v_y = last->p.y - begin->p.y;
calc_type const c2 = v_x * v_x + v_y * v_y;
for(iterator_type it = begin + 1; it != last; ++it)
{
calc_type const w_x = it->p.x - begin->p.x;
calc_type const w_y = it->p.y - begin->p.y;
calc_type const c1 = w_x * v_x + w_y * v_y;
calc_type dist;
auto const& last = vec[last_idx];
auto const& begin = vec[begin_idx];
double const v_x = last.x - begin.x;
double const v_y = last.y - begin.y;
double const c2 = v_x * v_x + v_y * v_y;
std::size_t i = begin_idx + 1;
#ifdef SSE_MATH
if (size > 4 && size < std::numeric_limits<std::uint32_t>::max())
{
__m128 begin_x_4 = _mm_set1_ps(begin.x);
__m128 begin_y_4 = _mm_set1_ps(begin.y);
__m128 last_x_4 = _mm_set1_ps(last.x);
__m128 last_y_4 = _mm_set1_ps(last.y);
__m128 v_x_4 = _mm_set1_ps(v_x);
__m128 v_y_4 = _mm_set1_ps(v_y);
__m128 c2_4 = _mm_set1_ps(c2);
__m128 zero_4 = _mm_set1_ps(0.0);
__m128 true_4 = _mm_castsi128_ps(_mm_set1_epi32(std::numeric_limits<std::uint32_t>::max()));
__m128 md_4 = _mm_set1_ps(md);
__m128 md_idx = _mm_castsi128_ps(_mm_set1_epi32(i));
for (; i + 3 < last_idx; i += 4)
{
// Setup loop values
__m128 it_x_4 = _mm_set_ps(vec[i+3].x, vec[i+2].x, vec[i+1].x, vec[i].x);
__m128 it_y_4 = _mm_set_ps(vec[i+3].y, vec[i+2].y, vec[i+1].y, vec[i].y);
__m128 it_idx = _mm_castsi128_ps(_mm_set_epi32(i+3, i+2, i+1, i));
// Calculate c1
__m128 w_x_4 = _mm_sub_ps(it_x_4, begin_x_4);
__m128 w_y_4 = _mm_sub_ps(it_y_4, begin_y_4);
__m128 u_x_4 = _mm_sub_ps(it_x_4, last_x_4);
__m128 u_y_4 = _mm_sub_ps(it_y_4, last_y_4);
__m128 c1_4 = _mm_add_ps(_mm_mul_ps(w_x_4, v_x_4), _mm_mul_ps(w_y_4, v_y_4));
// Calculate two optional distance results
__m128 dist_1 = _mm_add_ps(_mm_mul_ps(w_x_4, w_x_4), _mm_mul_ps(w_y_4, w_y_4));
__m128 dist_2 = _mm_add_ps(_mm_mul_ps(u_x_4, u_x_4), _mm_mul_ps(u_y_4, u_y_4));
__m128 bool_dist_1 = _mm_cmple_ps(c1_4, zero_4);
__m128 bool_dist_2 = _mm_cmple_ps(c2_4, c1_4);
// Calculate the default distance solution now
__m128 b_4 = _mm_div_ps(c1_4, c2_4);
__m128 dx_4 = _mm_sub_ps(w_x_4, _mm_mul_ps(b_4, v_x_4));
__m128 dy_4 = _mm_sub_ps(w_y_4, _mm_mul_ps(b_4, v_y_4));
__m128 dist_3 = _mm_add_ps(_mm_mul_ps(dx_4, dx_4), _mm_mul_ps(dy_4, dy_4));
__m128 dist = _mm_and_ps(dist_1, bool_dist_1);
dist = _mm_or_ps(dist, _mm_and_ps(_mm_and_ps(_mm_andnot_ps(bool_dist_1, true_4), bool_dist_2), dist_2));
dist = _mm_or_ps(dist, _mm_and_ps(_mm_andnot_ps(_mm_or_ps(bool_dist_1, bool_dist_2), true_4), dist_3));
__m128 bool_md = _mm_cmplt_ps(md_4, dist);
md_4 = _mm_or_ps(_mm_andnot_ps(bool_md, md_4), _mm_and_ps(bool_md, dist));
md_idx = _mm_or_ps(_mm_andnot_ps(bool_md, md_idx), _mm_and_ps(bool_md, it_idx));
}
float md_out [4];
std::uint32_t md_idx_out [4];
_mm_store_ps(md_out, md_4);
_mm_store_ps(reinterpret_cast<float*>(md_idx_out), md_idx);
md = md_out[0];
candidate = md_idx_out[0];
for (std::size_t j = 1; j < 4; ++j)
{
if (md < md_out[j])
{
md = md_out[j];
candidate = md_idx_out[j];
}
else if (md == md_out[j] && md_idx_out[j] < candidate)
{
candidate = md_idx_out[j];
}
}
}
else if (size > 2)
{
__m128d begin_x_2 = _mm_set1_pd(begin.x);
__m128d begin_y_2 = _mm_set1_pd(begin.y);
__m128d last_x_2 = _mm_set1_pd(last.x);
__m128d last_y_2 = _mm_set1_pd(last.y);
__m128d v_x_2 = _mm_set1_pd(v_x);
__m128d v_y_2 = _mm_set1_pd(v_y);
__m128d c2_2 = _mm_set1_pd(c2);
__m128d zero_2 = _mm_set1_pd(0.0);
__m128d true_2 = _mm_castsi128_pd(_mm_set1_epi64(reinterpret_cast<__m64>(std::numeric_limits<std::uint64_t>::max())));
__m128d md_2 = _mm_set1_pd(md);
__m128d md_idx = _mm_castsi128_pd(_mm_set1_epi64(reinterpret_cast<__m64>(i)));
for (; i + 1 < last_idx; i += 2)
{
// Setup loop values
__m128d it_x_2 = _mm_set_pd(vec[i+1].x, vec[i].x);
__m128d it_y_2 = _mm_set_pd(vec[i+1].y, vec[i].y);
__m128d it_idx = _mm_castsi128_pd(_mm_set_epi64(reinterpret_cast<__m64>(i+1), reinterpret_cast<__m64>(i)));
// Calculate c1
__m128d w_x_2 = _mm_sub_pd(it_x_2, begin_x_2);
__m128d w_y_2 = _mm_sub_pd(it_y_2, begin_y_2);
__m128d u_x_2 = _mm_sub_pd(it_x_2, last_x_2);
__m128d u_y_2 = _mm_sub_pd(it_y_2, last_y_2);
__m128d c1_2 = _mm_add_pd(_mm_mul_pd(w_x_2, v_x_2), _mm_mul_pd(w_y_2, v_y_2));
// Calculate two optional distance results
__m128d dist_1 = _mm_add_pd(_mm_mul_pd(w_x_2, w_x_2), _mm_mul_pd(w_y_2, w_y_2));
__m128d dist_2 = _mm_add_pd(_mm_mul_pd(u_x_2, u_x_2), _mm_mul_pd(u_y_2, u_y_2));
__m128d bool_dist_1 = _mm_cmple_pd(c1_2, zero_2);
__m128d bool_dist_2 = _mm_cmple_pd(c2_2, c1_2);
// Calculate the default distance solution now
__m128d b_2 = _mm_div_pd(c1_2, c2_2);
__m128d dx_2 = _mm_sub_pd(w_x_2, _mm_mul_pd(b_2, v_x_2));
__m128d dy_2 = _mm_sub_pd(w_y_2, _mm_mul_pd(b_2, v_y_2));
__m128d dist_3 = _mm_add_pd(_mm_mul_pd(dx_2, dx_2), _mm_mul_pd(dy_2, dy_2));
__m128d dist = _mm_and_pd(dist_1, bool_dist_1);
dist = _mm_or_pd(dist, _mm_and_pd(_mm_and_pd(_mm_andnot_pd(bool_dist_1, true_2), bool_dist_2), dist_2));
dist = _mm_or_pd(dist, _mm_and_pd(_mm_andnot_pd(_mm_or_pd(bool_dist_1, bool_dist_2), true_2), dist_3));
__m128d bool_md = _mm_cmplt_pd(md_2, dist);
md_2 = _mm_or_pd(_mm_andnot_pd(bool_md, md_2), _mm_and_pd(bool_md, dist));
md_idx = _mm_or_pd(_mm_andnot_pd(bool_md, md_idx), _mm_and_pd(bool_md, it_idx));
}
double md_out [2];
std::size_t md_idx_out [2];
_mm_store_pd(md_out, md_2);
_mm_store_pd(reinterpret_cast<double*>(md_idx_out), md_idx);
md = md_out[0];
candidate = md_idx_out[0];
if (md < md_out[1])
{
md = md_out[1];
candidate = md_idx_out[1];
}
else if (md == md_out[1] && md_idx_out[1] < candidate)
{
candidate = md_idx_out[1];
}
}
#endif
for (; i < last_idx; ++i)
{
auto const& it = vec[i];
double const w_x = it.x - begin.x;
double const w_y = it.y - begin.y;
double const c1 = w_x * v_x + w_y * v_y;
double dist;
if (c1 <= 0) // calc_type() should be 0 of the proper calc type format
{
calc_type const dx = it->p.x - begin->p.x;
calc_type const dy = it->p.y - begin->p.y;
dist = dx * dx + dy * dy;
dist = w_x * w_x + w_y * w_y;
}
else if (c2 <= c1)
{
calc_type const dx = it->p.x - last->p.x;
calc_type const dy = it->p.y - last->p.y;
double const dx = it.x - last.x;
double const dy = it.y - last.y;
dist = dx * dx + dy * dy;
}
else
{
// See above, c1 > 0 AND c2 > c1 so: c2 != 0
calc_type const b = c1 / c2;
calc_type const p_x = begin->p.x + b * v_x;
calc_type const p_y = begin->p.y + b * v_y;
calc_type const dx = it->p.x - p_x;
calc_type const dy = it->p.y - p_y;
double const b = c1 / c2;
double const dx = w_x - b * v_x;
double const dy = w_y - b * v_y;
dist = dx * dx + dy * dy;
}
if (md < dist)
{
md = dist;
candidate = it;
}
candidate = i;
}
}
......@@ -141,49 +281,45 @@ inline void consider(typename std::vector<douglas_peucker_point<value_type> >::i
// and handle segments in between recursively
if (max_dist < md)
{
candidate->included = true;
consider<value_type>(begin, candidate + 1, max_dist);
consider<value_type>(candidate, end, max_dist);
included[candidate] = true;
consider<Range>(vec, included, begin_idx, candidate, max_dist);
consider<Range>(vec, included, candidate, last_idx, max_dist);
}
}
} // end ns detail
template <typename value_type, typename calc_type, typename Range, typename OutputIterator>
template <typename Range, typename OutputIterator>
inline void douglas_peucker(Range const& range,
OutputIterator out,
calc_type max_distance)
double max_distance)
{
// Copy coordinates, a vector of references to all points
std::vector<detail::douglas_peucker_point<value_type> > ref_candidates(std::begin(range),
std::end(range));
std::vector<bool> included(range.size());
// Include first and last point of line,
// they are always part of the line
ref_candidates.front().included = true;
ref_candidates.back().included = true;
included.front() = true;
included.back() = true;
// We will compare to squared of distance so we don't have to do a sqrt
calc_type const max_sqrd = max_distance * max_distance;
double const max_sqrd = max_distance * max_distance;
// Get points, recursively, including them if they are further away
// than the specified distance
detail::consider<value_type, calc_type>(std::begin(ref_candidates), std::end(ref_candidates), max_sqrd);
detail::consider<Range>(range, included, 0, range.size() - 1, max_sqrd);
// Copy included elements to the output
for(typename std::vector<detail::douglas_peucker_point<value_type> >::const_iterator it
= std::begin(ref_candidates);
it != std::end(ref_candidates);
++it)
auto data = std::begin(range);
auto end_data = std::end(range);
auto inc = included.begin();
for (; data != end_data; ++data)
{
if (it->included)
if (*inc)
{
// copy-coordinates does not work because OutputIterator
// does not model Point (??)
//geometry::convert(it->p, *out);
*out = it->p;
out++;
*out++ = *data;
}
++inc;
}
}
......
......@@ -63,6 +63,13 @@ inline double get_point_value<double>(double const val,
return tile_loc + (val / scale_val);
}
constexpr std::size_t max_reserve()
{
// Based on int64_t geometry being 16 bytes in size and
// maximum allocation size of 1 MB.
return (1024 * 1024) / 16;
}
template <typename geom_value_type>
void decode_point(mapnik::geometry::geometry<geom_value_type> & geom,
GeometryPBF & paths,
......@@ -100,7 +107,15 @@ void decode_point(mapnik::geometry::geometry<geom_value_type> & geom,
}
previous_len = paths.get_length();
#endif
constexpr std::size_t max_size = max_reserve();
if (paths.get_length() + 1 < max_size)
{
mp.reserve(paths.get_length() + 1);
}
else
{
mp.reserve(max_size);
}
mp.emplace_back(x1_, y1_);
break;
}
......@@ -216,7 +231,15 @@ void decode_linestring(mapnik::geometry::geometry<geom_value_type> & geom,
multi_line.emplace_back();
auto & line = multi_line.back();
// reserve prior
constexpr std::size_t max_size = max_reserve();
if (paths.get_length() + 2 < max_size)
{
line.reserve(paths.get_length() + 2);
}
else
{
line.reserve(max_size);
}
// add moveto command position
x0_ = get_point_value<geom_value_type>(x0, scale_x, tile_x);
y0_ = get_point_value<geom_value_type>(y0, scale_y, tile_y);
......@@ -390,7 +413,15 @@ void decode_polygon(mapnik::geometry::geometry<geom_value_type> & geom,
rings.emplace_back();
auto & ring = rings.back();
// reserve prior
constexpr std::size_t max_size = max_reserve();
if (paths.get_length() + 4 < max_size)
{
ring.reserve(paths.get_length() + 4);
}
else
{
ring.reserve(max_size);
}
// add moveto command position
x0_ = get_point_value<geom_value_type>(x0, scale_x, tile_x);
y0_ = get_point_value<geom_value_type>(y0, scale_y, tile_y);
......
......@@ -41,7 +41,7 @@ struct geometry_simplifier
else
{
mapbox::geometry::line_string<std::int64_t> simplified;
douglas_peucker<std::int64_t>(geom, std::back_inserter(simplified), simplify_distance_);
douglas_peucker(geom, std::back_inserter(simplified), simplify_distance_);
next_(simplified);
}
}
......@@ -58,7 +58,7 @@ struct geometry_simplifier
else
{
mapbox::geometry::line_string<std::int64_t> simplified_line;
douglas_peucker<std::int64_t>(g, std::back_inserter(simplified_line), simplify_distance_);
douglas_peucker(g, std::back_inserter(simplified_line), simplify_distance_);
simplified.push_back(simplified_line);
}
}
......@@ -77,7 +77,7 @@ struct geometry_simplifier
else
{
mapbox::geometry::linear_ring<std::int64_t> simplified_ring;
douglas_peucker<std::int64_t>(g, std::back_inserter(simplified_ring), simplify_distance_);
douglas_peucker(g, std::back_inserter(simplified_ring), simplify_distance_);
simplified.push_back(simplified_ring);
}
}
......@@ -99,7 +99,7 @@ struct geometry_simplifier
else
{
mapbox::geometry::linear_ring<std::int64_t> simplified_ring;
douglas_peucker<std::int64_t>(g, std::back_inserter(simplified_ring), simplify_distance_);
douglas_peucker(g, std::back_inserter(simplified_ring), simplify_distance_);
simplified.push_back(simplified_ring);
}
}
......
......@@ -243,7 +243,7 @@ public:
{
if (!prj_trans_.forward(unbuffered_query_extent, PROJ_ENVELOPE_POINTS))
{
throw std::runtime_error("vector_tile_processor: unbuffered query extent did not repoject back to map projection");
throw std::runtime_error("vector_tile_processor: unbuffered query extent did not reproject back to map projection");
}
}
......@@ -265,7 +265,7 @@ public:
// forward project layer extent back into native projection
if (!prj_trans_.forward(query_extent, PROJ_ENVELOPE_POINTS))
{
throw std::runtime_error("vector_tile_processor: query extent did not repoject back to map projection");
throw std::runtime_error("vector_tile_processor: query extent did not reproject back to map projection");
}
}
else
......
......@@ -29,7 +29,7 @@ namespace mapnik
namespace vector_tile_impl
{
std::pair<std::string,std::uint32_t> get_layer_name_and_version(protozero::pbf_reader & layer_msg)
inline std::pair<std::string,std::uint32_t> get_layer_name_and_version(protozero::pbf_reader & layer_msg)
{
std::string name;
std::uint32_t version = 1;
......@@ -51,7 +51,7 @@ std::pair<std::string,std::uint32_t> get_layer_name_and_version(protozero::pbf_r
return std::make_pair(name,version);
}
void merge_from_buffer(merc_tile & t, const char * data, std::size_t size, bool validate = false, bool upgrade = false)
inline void merge_from_buffer(merc_tile & t, const char * data, std::size_t size, bool validate = false, bool upgrade = false)
{
using ds_ptr = std::shared_ptr<mapnik::vector_tile_impl::tile_datasource_pbf>;
protozero::pbf_reader tile_msg(data, size);
......@@ -137,7 +137,7 @@ void merge_from_buffer(merc_tile & t, const char * data, std::size_t size, bool
t.buffer_size(prev_buffer_size);
}
void merge_from_compressed_buffer(merc_tile & t, const char * data, std::size_t size, bool validate = false, bool upgrade = false)
inline void merge_from_compressed_buffer(merc_tile & t, const char * data, std::size_t size, bool validate = false, bool upgrade = false)
{
if (mapnik::vector_tile_impl::is_gzip_compressed(data,size) ||
mapnik::vector_tile_impl::is_zlib_compressed(data,size))
......@@ -152,7 +152,7 @@ void merge_from_compressed_buffer(merc_tile & t, const char * data, std::size_t
}
}
void add_image_buffer_as_tile_layer(merc_tile & t, std::string const& layer_name, const char * data, std::size_t size)
inline void add_image_buffer_as_tile_layer(merc_tile & t, std::string const& layer_name, const char * data, std::size_t size)
{
std::string layer_buffer;
protozero::pbf_writer layer_writer(layer_buffer);
......