[mapnik-vector-tile] 02/07: Imported Upstream version 1.2.0+dfsg

Bas Couwenberg sebastic at debian.org
Fri Aug 5 20:57:47 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository mapnik-vector-tile.

commit 899f67f8eaed1207d55854c852775202bc9866cd
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Aug 5 22:18:38 2016 +0200

    Imported Upstream version 1.2.0+dfsg
---
 CHANGELOG.md                                 |   6 +
 bin/vtile-fuzz.cpp                           | 126 ++++--
 package.json                                 |   2 +-
 src/vector_tile_featureset_pbf.ipp           |   8 +-
 src/vector_tile_geometry_decoder.cpp         |  20 +-
 src/vector_tile_geometry_decoder.hpp         |  43 +-
 src/vector_tile_geometry_decoder.ipp         | 648 ++++++++++++---------------
 test/data/0.0.0.vector-b.mvt                 | Bin 2840 -> 2824 bytes
 test/data/simplified_geometry.geojson        |   2 +-
 test/data/simplified_geometry_pbf.geojson    |   2 +-
 test/fixtures/rasterize-expected-1.png       | Bin 12645 -> 12577 bytes
 test/geometry_visual_test.cpp                |   6 +-
 test/system/encode_and_datasource_decode.cpp |   4 +-
 test/system/processor_and_datasource.cpp     |   4 +-
 test/unit/datasource-pbf/from_layer.cpp      |   4 +-
 test/unit/decoding/linestring.cpp            | 102 ++---
 test/unit/decoding/point.cpp                 |  72 +--
 test/unit/decoding/polygon.cpp               | 234 +++++-----
 test/unit/decoding/polygon_scaling.cpp       |  60 +--
 test/utils/decoding_util.cpp                 |   8 +-
 test/utils/decoding_util.hpp                 |   3 +-
 test/utils/encoding_util.cpp                 |   4 +-
 test/utils/round_trip.cpp                    |   4 +-
 test/vector_tile.cpp                         |   4 +-
 test/vector_tile_pbf.cpp                     |  26 +-
 test/vector_tile_rasterize.cpp               |  10 +-
 26 files changed, 672 insertions(+), 730 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fd0bd71..c8ed24a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## 1.2.0
+
+- Big overhaul to the interface around the vector tile decoder
+- Slight performance increase in decoder
+- Fixed a bug around throwing on incorrect winding order incorrectly when the exterior ring in a polygon was dropped by its extent but an interior ring was included.
+
 ## 1.1.2
 
 - Fix performance regression when passing raster through vector tile
diff --git a/bin/vtile-fuzz.cpp b/bin/vtile-fuzz.cpp
index 243ecf2..dc33ab7 100644
--- a/bin/vtile-fuzz.cpp
+++ b/bin/vtile-fuzz.cpp
@@ -1,11 +1,9 @@
 #include "vector_tile_geometry_clipper.hpp"
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
 #include <vector>
 #include <iostream>
 #include <limits>
+#include <cstdlib>
 
 
 /*
@@ -28,56 +26,88 @@ int main() {
 
     noop_process no_op;
     using clipping_process = mapnik::vector_tile_impl::geometry_clipper<noop_process>;
-    double area_threshold = 0;
-    bool strictly_simple = true;
-    bool multi_polygon_union = true;
-    mapnik::vector_tile_impl::polygon_fill_type fill_type = mapnik::vector_tile_impl::even_odd_fill;
-    bool process_all_rings = true;
-    mapnik::box2d<int> tile_clipping_extent(std::numeric_limits<int>::min(),
+    mapnik::box2d<int> no_op_max_extent(std::numeric_limits<int>::min(),
                                             std::numeric_limits<int>::min(),
                                             std::numeric_limits<int>::max(),
                                             std::numeric_limits<int>::max());
-    clipping_process clipper(tile_clipping_extent,
-                     area_threshold,
-                     strictly_simple,
-                     multi_polygon_union,
-                     fill_type,
-                     process_all_rings,
-                     no_op);
-
-    srand(time(NULL));
-
-    while (1) {
-
-        std::size_t len = rand() % 700 + 3;
-
-        mapnik::geometry::polygon<std::int64_t> poly;
-        mapnik::geometry::linear_ring<std::int64_t> ring;
-
-        bool added_exterior = false;
-
-        for (std::size_t i = 0; i < len; ++i) {
-            std::int64_t x = rand() % 4096;
-            std::int64_t y = rand() % 4096;
-            //std::clog << x << "," << y;
-
-            ring.add_coord(x,y);
-
-            if (!added_exterior && i > 100) {
-                poly.set_exterior_ring(std::move(ring));
-                ring = mapnik::geometry::linear_ring<std::int64_t>(); 
-                //std::clog << "added exterior\n";
-                added_exterior = true;
-            }
+    while (1)
+    {
 
-            if (added_exterior && rand() % 50 == 0 && ring.size() >= 3) {
-                poly.add_hole(std::move(ring));
-                ring = mapnik::geometry::linear_ring<std::int64_t>();
-                //std::clog << "added hole\n";               
+        std::size_t len = std::rand() % 700 + 3;
+
+        for (auto strictly_simple : { true, false })
+        {
+            for (auto multi_polygon_union : { true, false })
+            {
+                for (auto process_all_rings : { true, false })
+                {
+                    for (auto area_threshold : { 0.0, 0.5 })
+                    {
+                        for (auto fill_type : { mapnik::vector_tile_impl::even_odd_fill,
+                                                mapnik::vector_tile_impl::non_zero_fill,
+                                                mapnik::vector_tile_impl::positive_fill,
+                                                mapnik::vector_tile_impl::negative_fill })
+                        {
+                            mapnik::geometry::polygon<std::int64_t> poly;
+                            mapnik::geometry::linear_ring<std::int64_t> ring;
+                            mapnik::box2d<int> geom_extent;
+
+                            bool added_exterior = false;
+                            bool first = true;
+
+                            for (std::size_t i = 0; i < len; ++i) {
+                                std::int64_t x = std::rand() % 4096;
+                                std::int64_t y = std::rand() % 4096;
+
+                                ring.add_coord(x,y);
+                                if (first) {
+                                    first = false;
+                                    geom_extent.init(x,y,x,y);
+                                } else {
+                                    geom_extent.expand_to_include(x,y);
+                                }
+
+                                if (!added_exterior && i > 100) {
+                                    poly.set_exterior_ring(std::move(ring));
+                                    ring = mapnik::geometry::linear_ring<std::int64_t>();
+                                    added_exterior = true;
+                                }
+
+                                if (added_exterior && std::rand() % 50 == 0 && ring.size() >= 3) {
+                                    poly.add_hole(std::move(ring));
+                                    ring = mapnik::geometry::linear_ring<std::int64_t>();
+                                }
+                            }
+                            std::clog << "size: " << poly.num_rings() << "\n";
+                            // clip with max extent: should result in nothing being clipped
+                            {
+                                clipping_process clipper(no_op_max_extent,
+                                                         area_threshold,
+                                                         strictly_simple,
+                                                         multi_polygon_union,
+                                                         fill_type,
+                                                         process_all_rings,
+                                                         no_op);
+                                clipper(poly);
+                            }
+                            // clip with the extent of geometries minus a bit
+                            {
+                                // TODO - mapnik core needs support for ints
+                                //mapnik::box2d<int> geom_extent = mapnik::geometry::envelope(poly);
+                                geom_extent.pad(-100);
+                                clipping_process clipper(geom_extent,
+                                                         area_threshold,
+                                                         strictly_simple,
+                                                         multi_polygon_union,
+                                                         fill_type,
+                                                         process_all_rings,
+                                                         no_op);
+                                clipper(poly);
+                            }
+                        }
+                    }
+                }
             }
         }
-
-        std::clog << "size: " << poly.num_rings() << "\n";
-        clipper(poly);
     }
 }
\ No newline at end of file
diff --git a/package.json b/package.json
index 1412ab0..ad62879 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "mapnik-vector-tile",
-    "version": "1.1.2",
+    "version": "1.2.0",
     "description": "Mapnik Vector Tile API",
     "main": "./package.json",
     "repository"   :  {
diff --git a/src/vector_tile_featureset_pbf.ipp b/src/vector_tile_featureset_pbf.ipp
index 978b198..1e7e86a 100644
--- a/src/vector_tile_featureset_pbf.ipp
+++ b/src/vector_tile_featureset_pbf.ipp
@@ -269,8 +269,8 @@ feature_ptr tile_featureset_pbf<Filter>::next()
             }
             if (version_ != 1)
             {
-                mapnik::vector_tile_impl::GeometryPBF<double> geoms(geom_itr, tile_x_,tile_y_,scale_,-1*scale_);
-                mapnik::geometry::geometry<double> geom = decode_geometry(geoms, geometry_type, version_, filter_.box_);
+                mapnik::vector_tile_impl::GeometryPBF geoms(geom_itr);
+                mapnik::geometry::geometry<double> geom = decode_geometry<double>(geoms, geometry_type, version_, tile_x_, tile_y_, scale_, -1.0 * scale_, filter_.box_);
                 if (geom.is<mapnik::geometry::geometry_empty>())
                 {
                     continue;
@@ -290,8 +290,8 @@ feature_ptr tile_featureset_pbf<Filter>::next()
             {
                 try
                 {
-                    mapnik::vector_tile_impl::GeometryPBF<double> geoms(geom_itr, tile_x_,tile_y_,scale_,-1*scale_);
-                    mapnik::geometry::geometry<double> geom = decode_geometry(geoms, geometry_type, version_, filter_.box_);
+                    mapnik::vector_tile_impl::GeometryPBF geoms(geom_itr);
+                    mapnik::geometry::geometry<double> geom = decode_geometry<double>(geoms, geometry_type, version_, tile_x_, tile_y_, scale_, -1.0 * scale_, filter_.box_);
                     if (geom.is<mapnik::geometry::geometry_empty>())
                     {
                         continue;
diff --git a/src/vector_tile_geometry_decoder.cpp b/src/vector_tile_geometry_decoder.cpp
index 5bbd2b9..07cfc39 100644
--- a/src/vector_tile_geometry_decoder.cpp
+++ b/src/vector_tile_geometry_decoder.cpp
@@ -7,13 +7,21 @@ namespace mapnik
 namespace vector_tile_impl
 {
 
-// Geometry classes
-template class GeometryPBF<double>;
-template class GeometryPBF<std::int64_t>;
-
 // decode geometry
-template mapnik::geometry::geometry<double> decode_geometry(GeometryPBF<double> & paths, int32_t geom_type, unsigned version);
-template mapnik::geometry::geometry<std::int64_t> decode_geometry(GeometryPBF<std::int64_t> & paths, int32_t geom_type, unsigned version);
+template mapnik::geometry::geometry<double> decode_geometry<double>(GeometryPBF & paths, 
+                                                                    int32_t geom_type, 
+                                                                    unsigned version,
+                                                                    double tile_x,
+                                                                    double tile_y,
+                                                                    double scale_x, 
+                                                                    double scale_y);
+template mapnik::geometry::geometry<std::int64_t> decode_geometry<std::int64_t>(GeometryPBF & paths, 
+                                                                                int32_t geom_type, 
+                                                                                unsigned version,
+                                                                                std::int64_t tile_x,
+                                                                                std::int64_t tile_y,
+                                                                                double scale_x, 
+                                                                                double scale_y);
 
 } // end ns vector_tile_impl
 
diff --git a/src/vector_tile_geometry_decoder.hpp b/src/vector_tile_geometry_decoder.hpp
index 998cba7..3a1b5de 100644
--- a/src/vector_tile_geometry_decoder.hpp
+++ b/src/vector_tile_geometry_decoder.hpp
@@ -27,18 +27,13 @@ namespace vector_tile_impl
 
 // NOTE: this object is for one-time use.  Once you've progressed to the end
 //       by calling next(), to re-iterate, you must construct a new object
-template <typename T>
 class GeometryPBF 
 {
 public:
-    using value_type = T;
+    using value_type = std::int64_t;
     using pbf_itr = std::pair<protozero::pbf_reader::const_uint32_iterator, protozero::pbf_reader::const_uint32_iterator >;
     
-    explicit GeometryPBF(pbf_itr const& geo_iterator,
-                         value_type tile_x, 
-                         value_type tile_y,
-                         double scale_x, 
-                         double scale_y);
+    explicit GeometryPBF(pbf_itr const& geo_iterator);
 
     enum command : uint8_t
     {
@@ -48,12 +43,6 @@ public:
         close = 7
     };
 
-
-    bool scaling_reversed_orientation() const
-    {
-        return (scale_x_ * scale_y_) < 0;
-    }
-
     uint32_t get_length() const
     {
         return length;
@@ -65,8 +54,6 @@ public:
 
 private:
     std::pair< protozero::pbf_reader::const_uint32_iterator, protozero::pbf_reader::const_uint32_iterator > geo_iterator_;
-    double scale_x_;
-    double scale_y_;
     value_type x, y;
     value_type ox, oy;
     uint32_t length;
@@ -77,14 +64,24 @@ public:
     #endif
 };
 
-template <typename T>
-MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<typename T::value_type> decode_geometry(T & paths, 
-                                                                   int32_t geom_type, 
-                                                                   unsigned version,
-                                                                   mapnik::box2d<double> const& bbox);
-
-template <typename T>
-MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<typename T::value_type> decode_geometry(T & paths, int32_t geom_type, unsigned version);
+template <typename value_type>
+MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<value_type> decode_geometry(GeometryPBF & paths, 
+                                                                            std::int32_t geom_type, 
+                                                                            unsigned version,
+                                                                            value_type tile_x,
+                                                                            value_type tile_y,
+                                                                            double scale_x,
+                                                                            double scale_y,
+                                                                            mapnik::box2d<double> const& bbox);
+
+template <typename value_type>
+MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<value_type> decode_geometry(GeometryPBF & paths, 
+                                                                            std::int32_t geom_type, 
+                                                                            unsigned version,
+                                                                            value_type tile_x,
+                                                                            value_type tile_y,
+                                                                            double scale_x,
+                                                                            double scale_y);
 
 } // end ns vector_tile_impl
 
diff --git a/src/vector_tile_geometry_decoder.ipp b/src/vector_tile_geometry_decoder.ipp
index 56120fa..3947f13 100644
--- a/src/vector_tile_geometry_decoder.ipp
+++ b/src/vector_tile_geometry_decoder.ipp
@@ -22,53 +22,60 @@ namespace vector_tile_impl
 namespace detail
 {
 
-template <typename T>
-bool ring_is_clockwise(T const& ring)
+template <typename value_type>
+inline double calculate_segment_area(value_type const x0, value_type const y0, value_type const x1, value_type const y1)
 {
-    std::size_t num_points = ring.size();
-    if (num_points < 3)
-    {
-        return false;
-    }
-    double area = 0.0;
-    double orig_x = ring[0].x;
-    double orig_y = ring[0].y;
-    for (std::size_t i = 0; i < num_points; ++i)
-    {
-        auto const& p0 = ring[i];
-        auto const& p1 = ring[(i + 1) % num_points];
-        double x0 = p0.x - orig_x;
-        double y0 = p0.y - orig_y;
-        double x1 = p1.x - orig_x;
-        double y1 = p1.y - orig_y;
-        area += x0 * y1 - x1 * y0;
-    }
-    return (area < 0.0) ? true : false;
+    return (static_cast<double>(x0) * static_cast<double>(y1)) - (static_cast<double>(y0) * static_cast<double>(x1));
+}
+
+inline bool area_is_clockwise(double area)
+{
+    return (area < 0.0);
+}
+
+template <typename value_type>
+inline bool scaling_reversed_orientation(value_type const scale_x_, value_type const scale_y_)
+{
+    return (scale_x_ * scale_y_) < 0;
 }
 
 template <typename value_type>
-inline void move_cursor(value_type & x, value_type & y, std::int32_t dx, std::int32_t dy, double scale_x_, double scale_y_)
+inline void move_cursor(value_type & x, value_type & y, std::int32_t dx, std::int32_t dy)
 {
-    x += static_cast<value_type>(std::round(static_cast<double>(dx) / scale_x_));
-    y += static_cast<value_type>(std::round(static_cast<double>(dy) / scale_y_));
+    x += static_cast<value_type>(dx);
+    y += static_cast<value_type>(dy);
+}
+
+
+template <typename value_type>
+inline value_type get_point_value(value_type const val, 
+                                  double const scale_val,
+                                  double const tile_loc)
+{
+    return (tile_loc + static_cast<value_type>(std::round(static_cast<double>(val) / scale_val)));
 }
 
 template <>
-inline void move_cursor<double>(double & x, double & y, std::int32_t dx, std::int32_t dy, double scale_x_, double scale_y_)
+inline double get_point_value<double>(double const val, 
+                                      double const scale_val,
+                                      double const tile_loc)
 {
-    x += static_cast<double>(dx) / scale_x_;
-    y += static_cast<double>(dy) / scale_y_;
+    return tile_loc + (val / scale_val);
 }
 
-template <typename T>
-void decode_point(mapnik::geometry::geometry<typename T::value_type> & geom, 
-                  T & paths, 
+template <typename geom_value_type>
+void decode_point(mapnik::geometry::geometry<geom_value_type> & geom, 
+                  GeometryPBF & paths, 
+                  geom_value_type const tile_x,
+                  geom_value_type const tile_y,
+                  double const scale_x,
+                  double const scale_y,
                   mapnik::box2d<double> const& bbox)
 {
-    using value_type = typename T::value_type;
-    typename T::command cmd;
-    value_type x1, y1;
-    mapnik::geometry::multi_point<value_type> mp;
+    typename GeometryPBF::command cmd;
+    using pbf_value_type = GeometryPBF::value_type;
+    pbf_value_type x1, y1;
+    mapnik::geometry::multi_point<geom_value_type> mp;
     #if defined(DEBUG)
     std::uint32_t previous_len = 0;
     #endif
@@ -76,12 +83,14 @@ void decode_point(mapnik::geometry::geometry<typename T::value_type> & geom,
     while (true)
     {
         cmd = paths.point_next(x1, y1);
-        if (cmd == T::end)
+        geom_value_type x1_ = get_point_value<geom_value_type>(x1, scale_x, tile_x);
+        geom_value_type y1_ = get_point_value<geom_value_type>(y1, scale_y, tile_y);
+        if (cmd == GeometryPBF::end)
         {
-            geom = std::move(mapnik::geometry::geometry_empty());
+            geom = mapnik::geometry::geometry_empty();
             return;
         } 
-        else if (bbox.intersects(x1,y1))
+        else if (bbox.intersects(x1_, y1_))
         {
             #if defined(DEBUG)
             if (previous_len <= paths.get_length() && !paths.already_had_error)
@@ -92,11 +101,11 @@ void decode_point(mapnik::geometry::geometry<typename T::value_type> & geom,
             previous_len = paths.get_length();
             #endif
             mp.reserve(paths.get_length() + 1);
-            mp.emplace_back(x1,y1);
+            mp.emplace_back(x1_, y1_);
             break;
         }
     }
-    while ((cmd = paths.point_next(x1, y1)) != T::end)
+    while ((cmd = paths.point_next(x1, y1)) != GeometryPBF::end)
     {
         #if defined(DEBUG)
         if (previous_len <= paths.get_length() && !paths.already_had_error)
@@ -111,16 +120,18 @@ void decode_point(mapnik::geometry::geometry<typename T::value_type> & geom,
         // perfect, but when some points are thrown out we will allocate more than needed
         // the "all points intersect" case I think is going to be more common/important
         // however worth a future look to see if the "some or few points intersect" can be optimized
-        if (!bbox.intersects(x1,y1))
+        geom_value_type x1_ = get_point_value<geom_value_type>(x1, scale_x, tile_x);
+        geom_value_type y1_ = get_point_value<geom_value_type>(y1, scale_y, tile_y);
+        if (!bbox.intersects(x1_, y1_))
         {
             continue;
         }
-        mp.emplace_back(x1,y1);
+        mp.emplace_back(x1_, y1_);
     }
     std::size_t num_points = mp.size();
     if (num_points == 0)
     {
-        geom = std::move(mapnik::geometry::geometry_empty());
+        geom = mapnik::geometry::geometry_empty();
     }
     else if (num_points == 1)
     {
@@ -133,28 +144,34 @@ void decode_point(mapnik::geometry::geometry<typename T::value_type> & geom,
     }
 }
 
-template <typename T>
-void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom, 
-                       T & paths, 
+template <typename geom_value_type>
+void decode_linestring(mapnik::geometry::geometry<geom_value_type> & geom, 
+                       GeometryPBF & paths,
+                       geom_value_type const tile_x,
+                       geom_value_type const tile_y,
+                       double scale_x,
+                       double scale_y,
                        mapnik::box2d<double> const& bbox,
                        unsigned version)
 {
-    using value_type = typename T::value_type;
-    typename T::command cmd;
-    value_type x0, y0;
-    value_type x1, y1;
-    mapnik::geometry::multi_line_string<value_type> multi_line;
+    using pbf_value_type = GeometryPBF::value_type;
+    typename GeometryPBF::command cmd;
+    pbf_value_type x0, y0;
+    pbf_value_type x1, y1;
+    geom_value_type x0_, y0_;
+    geom_value_type x1_, y1_;
+    mapnik::geometry::multi_line_string<geom_value_type> multi_line;
     #if defined(DEBUG)
     std::uint32_t previous_len = 0;
     #endif
     mapnik::box2d<double> part_env;
     cmd = paths.line_next(x0, y0, false);
-    if (cmd == T::end)
+    if (cmd == GeometryPBF::end)
     {
-        geom = std::move(mapnik::geometry::geometry_empty());
+        geom = mapnik::geometry::geometry_empty();
         return;
     }
-    else if (cmd != T::move_to)
+    else if (cmd != GeometryPBF::move_to)
     {
         throw std::runtime_error("Vector Tile has LINESTRING type geometry where the first command is not MOVETO.");
     }
@@ -162,9 +179,9 @@ void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom
     while (true)
     {
         cmd = paths.line_next(x1, y1, true);
-        if (cmd != T::line_to)
+        if (cmd != GeometryPBF::line_to)
         {
-            if (cmd == T::move_to)
+            if (cmd == GeometryPBF::move_to)
             {
                 if (version == 1)
                 {
@@ -180,7 +197,7 @@ void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom
                     throw std::runtime_error("Vector Tile has LINESTRING type geometry with repeated MOVETO commands.");
                 }
             }
-            else //cmd == T::end
+            else //cmd == GeometryPBF::end
             {   
                 if (version == 1)
                 {
@@ -201,18 +218,24 @@ void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom
         // reserve prior
         line.reserve(paths.get_length() + 2);
         // add moveto command position
-        line.add_coord(x0, y0);
-        part_env.init(x0, y0, x0, y0);
+        x0_ = get_point_value<geom_value_type>(x0, scale_x, tile_x);
+        y0_ = get_point_value<geom_value_type>(y0, scale_y, tile_y);
+        line.add_coord(x0_, y0_);
+        part_env.init(x0_, y0_, x0_, y0_);
         // add first lineto
-        line.add_coord(x1, y1);
-        part_env.expand_to_include(x1, y1);
+        x1_ = get_point_value<geom_value_type>(x1, scale_x, tile_x);
+        y1_ = get_point_value<geom_value_type>(y1, scale_y, tile_y);
+        line.add_coord(x1_, y1_);
+        part_env.expand_to_include(x1_, y1_);
         #if defined(DEBUG)
         previous_len = paths.get_length();
         #endif
-        while ((cmd = paths.line_next(x1, y1, true)) == T::line_to)
+        while ((cmd = paths.line_next(x1, y1, true)) == GeometryPBF::line_to)
         {
-            line.add_coord(x1, y1);
-            part_env.expand_to_include(x1, y1);
+            x1_ = get_point_value<geom_value_type>(x1, scale_x, tile_x);
+            y1_ = get_point_value<geom_value_type>(y1, scale_y, tile_y);
+            line.add_coord(x1_, y1_);
+            part_env.expand_to_include(x1_, y1_);
             #if defined(DEBUG)
             if (previous_len <= paths.get_length() && !paths.already_had_error)
             {
@@ -227,7 +250,7 @@ void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom
             // remove last linestring
             multi_line.pop_back();
         }
-        if (cmd == T::end)
+        if (cmd == GeometryPBF::end)
         {
             break;
         } 
@@ -239,7 +262,7 @@ void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom
     std::size_t num_lines = multi_line.size();
     if (num_lines == 0)
     {
-        geom = std::move(mapnik::geometry::geometry_empty());
+        geom = mapnik::geometry::geometry_empty();
     }
     else if (num_lines == 1)
     {
@@ -248,6 +271,10 @@ void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom
         {
             geom = std::move(*itr);
         }
+        else
+        {
+            geom = mapnik::geometry::geometry_empty();
+        }
     }
     else if (num_lines > 1)
     {
@@ -255,27 +282,41 @@ void decode_linestring(mapnik::geometry::geometry<typename T::value_type> & geom
     }
 }
 
-template <typename T>
-void read_rings(std::vector<mapnik::geometry::linear_ring<typename T::value_type> > & rings,
-                T & paths, 
-                mapnik::box2d<double> const& bbox,
-                unsigned version)
+template <typename geom_value_type>
+void decode_polygon(mapnik::geometry::geometry<geom_value_type> & geom,
+                    GeometryPBF & paths, 
+                    geom_value_type const tile_x,
+                    geom_value_type const tile_y,
+                    double scale_x,
+                    double scale_y,
+                    mapnik::box2d<double> const& bbox,
+                    unsigned version)
 {
-    using value_type = typename T::value_type;
-    typename T::command cmd;
-    value_type x0, y0;
-    value_type x1, y1;
-    value_type x2, y2;
+    typename GeometryPBF::command cmd;
+    using pbf_value_type = GeometryPBF::value_type;
+    pbf_value_type x0, y0;
+    pbf_value_type x1, y1;
+    pbf_value_type x2, y2;
+    geom_value_type x0_, y0_;
+    geom_value_type x1_, y1_;
+    geom_value_type x2_, y2_;
     #if defined(DEBUG)
     std::uint32_t previous_len;
     #endif
+    double ring_area = 0.0;
+    bool first_ring = true;
+    bool first_ring_is_clockwise = false;
+    bool last_exterior_not_included = false;
+    std::vector<mapnik::geometry::linear_ring<geom_value_type> > rings;
+    std::vector<bool> rings_exterior;
     mapnik::box2d<double> part_env;
     cmd = paths.ring_next(x0, y0, false);
-    if (cmd == T::end)
+    if (cmd == GeometryPBF::end)
     {
+        geom = mapnik::geometry::geometry_empty();
         return;
     }
-    else if (cmd != T::move_to)
+    else if (cmd != GeometryPBF::move_to)
     {
         throw std::runtime_error("Vector Tile has POLYGON type geometry where the first command is not MOVETO.");
     }
@@ -283,26 +324,26 @@ void read_rings(std::vector<mapnik::geometry::linear_ring<typename T::value_type
     while (true)
     {
         cmd = paths.ring_next(x1, y1, true);
-        if (cmd != T::line_to)
+        if (cmd != GeometryPBF::line_to)
         {
-            if (cmd == T::close && version == 1)
+            if (cmd == GeometryPBF::close && version == 1)
             {
                 // Version 1 of the specification was not clear on the command requirements for polygons
                 // lets just to recover from this situation.
                 cmd = paths.ring_next(x0, y0, false);
-                if (cmd == T::end)
+                if (cmd == GeometryPBF::end)
                 {
                     break;
                 }
-                else if (cmd == T::move_to)
+                else if (cmd == GeometryPBF::move_to)
                 {
                     continue;
                 }
-                else if (cmd == T::close)
+                else if (cmd == GeometryPBF::close)
                 {
                     throw std::runtime_error("Vector Tile has POLYGON type geometry where a CLOSE is followed by a CLOSE.");
                 }
-                else // cmd == T::line_to
+                else // cmd == GeometryPBF::line_to
                 {
                     throw std::runtime_error("Vector Tile has POLYGON type geometry where a CLOSE is followed by a LINETO.");
                 }
@@ -316,26 +357,26 @@ void read_rings(std::vector<mapnik::geometry::linear_ring<typename T::value_type
         previous_len = paths.get_length();
         #endif
         cmd = paths.ring_next(x2, y2, true);
-        if (cmd != T::line_to)
+        if (cmd != GeometryPBF::line_to)
         {
-            if (cmd == T::close && version == 1)
+            if (cmd == GeometryPBF::close && version == 1)
             {
                 // Version 1 of the specification was not clear on the command requirements for polygons
                 // lets just to recover from this situation.
                 cmd = paths.ring_next(x0, y0, false);
-                if (cmd == T::end)
+                if (cmd == GeometryPBF::end)
                 {
                     break;
                 }
-                else if (cmd == T::move_to)
+                else if (cmd == GeometryPBF::move_to)
                 {
                     continue;
                 }
-                else if (cmd == T::close)
+                else if (cmd == GeometryPBF::close)
                 {
                     throw std::runtime_error("Vector Tile has POLYGON type geometry where a CLOSE is followed by a CLOSE.");
                 }
-                else // cmd == T::line_to
+                else // cmd == GeometryPBF::line_to
                 {
                     throw std::runtime_error("Vector Tile has POLYGON type geometry where a CLOSE is followed by a LINETO.");
                 }
@@ -351,14 +392,24 @@ void read_rings(std::vector<mapnik::geometry::linear_ring<typename T::value_type
         // reserve prior
         ring.reserve(paths.get_length() + 4);
         // add moveto command position
-        ring.add_coord(x0, y0);
-        part_env.init(x0, y0, x0, y0);
+        x0_ = get_point_value<geom_value_type>(x0, scale_x, tile_x);
+        y0_ = get_point_value<geom_value_type>(y0, scale_y, tile_y);
+        ring.add_coord(x0_, y0_);
+        part_env.init(x0_, y0_, x0_, y0_);
         // add first lineto
-        ring.add_coord(x1, y1);
-        part_env.expand_to_include(x1, y1);
+        x1_ = get_point_value<geom_value_type>(x1, scale_x, tile_x);
+        y1_ = get_point_value<geom_value_type>(y1, scale_y, tile_y);
+        ring.add_coord(x1_, y1_);
+        part_env.expand_to_include(x1_, y1_);
+        ring_area += calculate_segment_area(x0, y0, x1, y1);
         // add second lineto
-        ring.add_coord(x2, y2);
-        part_env.expand_to_include(x2, y2);
+        x2_ = get_point_value<geom_value_type>(x2, scale_x, tile_x);
+        y2_ = get_point_value<geom_value_type>(y2, scale_y, tile_y);
+        ring.add_coord(x2_, y2_);
+        part_env.expand_to_include(x2_, y2_);
+        ring_area += calculate_segment_area(x1, y1, x2, y2);
+        x1 = x2;
+        y1 = y2;
         #if defined(DEBUG)
         if (previous_len <= paths.get_length() && !paths.already_had_error)
         {
@@ -367,10 +418,15 @@ void read_rings(std::vector<mapnik::geometry::linear_ring<typename T::value_type
         }
         previous_len = paths.get_length();
         #endif
-        while ((cmd = paths.ring_next(x1, y1, true)) == T::line_to)
-        {
-            ring.add_coord(x1,y1);
-            part_env.expand_to_include(x1,y1);
+        while ((cmd = paths.ring_next(x2, y2, true)) == GeometryPBF::line_to)
+        {
+            x2_ = get_point_value<geom_value_type>(x2, scale_x, tile_x);
+            y2_ = get_point_value<geom_value_type>(y2, scale_y, tile_y);
+            ring.add_coord(x2_, y2_);
+            part_env.expand_to_include(x2_, y2_);
+            ring_area += calculate_segment_area(x1, y1, x2, y2);
+            x1 = x2;
+            y1 = y2;
             #if defined(DEBUG)
             if (previous_len <= paths.get_length() && !paths.already_had_error)
             {
@@ -381,271 +437,126 @@ void read_rings(std::vector<mapnik::geometry::linear_ring<typename T::value_type
             #endif
         }
         // Make sure we are now on a close command
-        if (cmd != T::close)
+        if (cmd != GeometryPBF::close)
         {
             throw std::runtime_error("Vector Tile has POLYGON type geometry with a ring not closed by a CLOSE command.");
         }
-        if (ring.back().x != x0 || ring.back().y != y0)
+        if (ring.back().x != x0_ || ring.back().y != y0_)
         {
             // If the previous lineto didn't already close the polygon (WHICH IT SHOULD NOT)
             // close out the polygon ring.
-            ring.add_coord(x0,y0);
+            ring.add_coord(x0_, y0_);
+            ring_area += calculate_segment_area(x1, y1, x0, y0);
         }
-
-        if (!bbox.intersects(part_env))
+        if (ring.size() > 3)
+        {
+            if (first_ring)
+            {
+                first_ring_is_clockwise = area_is_clockwise(ring_area);
+                if (version != 1 && first_ring_is_clockwise)
+                {
+                    throw std::runtime_error("Vector Tile has POLYGON with first ring clockwise. It is not valid according to v2 of VT spec.");
+                }
+                first_ring = false;
+            }
+            bool is_exterior = (first_ring_is_clockwise == area_is_clockwise(ring_area));
+            if ((!is_exterior && last_exterior_not_included) || !bbox.intersects(part_env))
+            {
+                // remove last linestring
+                if (is_exterior)
+                {
+                    last_exterior_not_included = true;
+                }
+                rings.pop_back();
+            }
+            else
+            {
+                if (is_exterior)
+                {
+                    last_exterior_not_included = false;
+                }
+                rings_exterior.push_back(is_exterior);
+            }
+        }
+        else
         {
-            // remove last linestring
             rings.pop_back();
         }
+        ring_area = 0.0;  
 
         cmd = paths.ring_next(x0, y0, false);
-        if (cmd == T::end)
+        if (cmd == GeometryPBF::end)
         {
             break;
         }
-        else if (cmd != T::move_to)
+        else if (cmd != GeometryPBF::move_to)
         {
-            if (cmd == T::close)
+            if (cmd == GeometryPBF::close)
             {
                 throw std::runtime_error("Vector Tile has POLYGON type geometry where a CLOSE is followed by a CLOSE.");
             }
-            else // cmd == T::line_to
+            else // cmd == GeometryPBF::line_to
             {
                 throw std::runtime_error("Vector Tile has POLYGON type geometry where a CLOSE is followed by a LINETO.");
             }
         }
     }
-}
 
-template <typename T1, typename T2>
-void decode_polygons(mapnik::geometry::geometry<T1> & geom, 
-                     T2 && rings, 
-                     unsigned version, 
-                     bool scaling_reversed_orientation)
-{
-    using value_type = T1;
+    if (rings.size() == 0)
+    {   
+        geom = mapnik::geometry::geometry_empty();
+        return;
+    }
+    std::size_t i = 0;
+    bool reverse_rings = (scaling_reversed_orientation(scale_x, scale_y) != first_ring_is_clockwise);
     auto rings_itr = std::make_move_iterator(rings.begin());
     auto rings_end = std::make_move_iterator(rings.end());
-    std::size_t num_rings = rings.size();
-    if (num_rings == 0)
+    mapnik::geometry::multi_polygon<geom_value_type> multi_poly;
+    while (rings_itr != rings_end)
     {
-        geom = std::move(mapnik::geometry::geometry_empty());
-    }
-    else if (num_rings == 1)
-    {
-        if (rings_itr->size() < 4)
+        multi_poly.emplace_back();
+        auto & poly = multi_poly.back();
+        if (reverse_rings)
         {
-            if (version == 1)
-            {
-                geom = std::move(mapnik::geometry::geometry_empty());
-                return;
-            }
-            else
-            {
-                throw std::runtime_error("Vector Tile has POLYGON has ring with too few points. It is not valid according to v2 of VT spec.");
-            }
+            std::reverse(rings_itr->begin(), rings_itr->end());
         }
-        
-        // We are going to check if the current ring is clockwise, keeping in mind that
-        // the orientation could have flipped due to scaling.
-        if (ring_is_clockwise(*rings_itr))
+        poly.set_exterior_ring(std::move(*rings_itr));
+        ++rings_itr;
+        ++i;
+        while (rings_itr != rings_end)
         {
-            if (scaling_reversed_orientation)
-            {
-                // Because the way we scaled changed the orientation of the ring (most likely due to a flipping of axis)
-                // we now have an exterior ring that clockwise. Internally in mapnik we want this to be counter clockwise
-                // so we must flip this.
-                std::reverse(rings_itr->begin(), rings_itr->end());
-            }
-            else
+            if (rings_exterior[i])
             {
-                if (version == 1)
-                {
-                    std::reverse(rings_itr->begin(), rings_itr->end());
-                }
-                else
-                {
-                    throw std::runtime_error("Vector Tile has POLYGON with first ring clockwise. It is not valid according to v2 of VT spec.");
-                }
+                break;
             }
-        }
-        else if (scaling_reversed_orientation) // ring is counter clockwise
-        {
-            // ring is counter clockwise but scaling reversed it.
-            // this means in the vector tile it is incorrectly orientated.
-            if (version == 1)
+            if (reverse_rings)
             {
                 std::reverse(rings_itr->begin(), rings_itr->end());
             }
-            else
-            {
-                throw std::runtime_error("Vector Tile has POLYGON with first ring clockwise. It is not valid according to v2 of VT spec.");
-            }
+            poly.add_hole(std::move(*rings_itr));
+            ++rings_itr;
+            ++i;
         }
-        // else ring is counter clockwise and scaling didn't reverse orientation.
-
-        // return the single polygon without interior rings
-        mapnik::geometry::polygon<value_type> poly;
-        poly.set_exterior_ring(std::move(*rings_itr));
-        geom = std::move(poly);
     }
-    else if (version == 1)
+
+    auto num_poly = multi_poly.size();
+    if (num_poly == 1)
     {
-        // Version 1 didn't specify the winding order, so we are forced
-        // to do a best guess. This means assuming the first ring is an exterior
-        // ring and then basing all winding order off that. For this we can
-        // ignore if the scaling reversed the orientation.
-        mapnik::geometry::multi_polygon<value_type> multi_poly;
-        bool first = true;
-        bool first_is_clockwise = false;
-        for (; rings_itr != rings_end; ++rings_itr)
-        {
-            if (rings_itr->size() < 4)
-            {
-                continue;
-            }
-            if (first)
-            {
-                first_is_clockwise = ring_is_clockwise(*rings_itr);
-                // first ring always exterior and sets all future winding order
-                multi_poly.emplace_back();
-                if (first_is_clockwise)
-                {
-                    // Going into mapnik we want the outer ring to be CCW
-                    std::reverse(rings_itr->begin(), rings_itr->end());
-                }
-                multi_poly.back().set_exterior_ring(std::move(*rings_itr));
-                first = false;
-            }
-            else if (first_is_clockwise == ring_is_clockwise(*rings_itr))
-            {
-                // hit a new exterior ring, so start a new polygon
-                multi_poly.emplace_back(); // start new polygon
-                if (first_is_clockwise)
-                {
-                    // Going into mapnik we want the outer ring to be CCW,
-                    // since first winding order was CW, we need to reverse
-                    // these rings.
-                    std::reverse(rings_itr->begin(), rings_itr->end());
-                }
-                multi_poly.back().set_exterior_ring(std::move(*rings_itr));
-            }
-            else
-            {
-                if (first_is_clockwise)
-                {
-                    // Going into mapnik we want the inner ring to be CW,
-                    // since first winding order of the outer ring CW, we
-                    // need to reverse these rings as they are CCW.
-                    std::reverse(rings_itr->begin(), rings_itr->end());
-                }
-                multi_poly.back().add_hole(std::move(*rings_itr));
-            }
-        }
-        
-        auto num_poly = multi_poly.size();
-        if (num_poly == 1)
-        {
-            auto itr = std::make_move_iterator(multi_poly.begin());
-            geom = std::move(*itr);
-        }
-        else
-        {
-            geom = std::move(multi_poly);
-        }
+        auto itr = std::make_move_iterator(multi_poly.begin());
+        geom = std::move(*itr);
     }
-    else // if (version == 2)
+    else
     {
-        mapnik::geometry::multi_polygon<value_type> multi_poly;
-        bool first = true;
-        for (; rings_itr != rings_end; ++rings_itr)
-        {
-            if (rings_itr->size() < 4)
-            {
-                throw std::runtime_error("Vector Tile has POLYGON has ring with too few points. It is not valid according to v2 of VT spec.");
-            }
-
-            if (first)
-            {
-                if (ring_is_clockwise(*rings_itr))
-                {
-                    if (scaling_reversed_orientation)
-                    {
-                        // Need to reverse ring so that it is proper going into mapnik.
-                        // as mapnik needs CCW exterior rings
-                        std::reverse(rings_itr->begin(), rings_itr->end());
-                    }
-                    else
-                    {
-                        throw std::runtime_error("Vector Tile has POLYGON with first ring clockwise. It is not valid according to v2 of VT spec.");
-                    }
-                } 
-                else if (scaling_reversed_orientation)
-                {
-                    throw std::runtime_error("Vector Tile has POLYGON with first ring clockwise. It is not valid according to v2 of VT spec.");
-                }
-                multi_poly.emplace_back();
-                multi_poly.back().set_exterior_ring(std::move(*rings_itr));
-                first = false;
-            }
-            else if (ring_is_clockwise(*rings_itr)) // interior ring
-            {
-                if (scaling_reversed_orientation)
-                {
-                    // This is an exterior ring but needs to be reversed.
-                    std::reverse(rings_itr->begin(), rings_itr->end());
-                    multi_poly.emplace_back(); // start new polygon
-                    multi_poly.back().set_exterior_ring(std::move(*rings_itr));
-                }
-                else
-                {
-                    // this is an interior ring
-                    multi_poly.back().add_hole(std::move(*rings_itr));
-                }
-            }
-            else 
-            {
-                if (scaling_reversed_orientation)
-                {
-                    // This is interior ring and it must be reversed.
-                    std::reverse(rings_itr->begin(), rings_itr->end());
-                    multi_poly.back().add_hole(std::move(*rings_itr));
-                }
-                else
-                {
-                    // hit a new exterior ring, so start a new polygon
-                    multi_poly.emplace_back(); // start new polygon
-                    multi_poly.back().set_exterior_ring(std::move(*rings_itr));
-                }
-            }
-        }
-        
-        auto num_poly = multi_poly.size();
-        if (num_poly == 1)
-        {
-            auto itr = std::make_move_iterator(multi_poly.begin());
-            geom = std::move(*itr);
-        }
-        else
-        {
-            geom = std::move(multi_poly);
-        }
+        geom = std::move(multi_poly);
     }
 }
 
 } // end ns detail
 
-template <typename T>
-GeometryPBF<T>::GeometryPBF(pbf_itr const& geo_iterator,
-                            value_type tile_x, 
-                            value_type tile_y,
-                            double scale_x, 
-                            double scale_y)
+GeometryPBF::GeometryPBF(pbf_itr const& geo_iterator)
     : geo_iterator_(geo_iterator),
-      scale_x_(scale_x),
-      scale_y_(scale_y),
-      x(tile_x),
-      y(tile_y),
+      x(0),
+      y(0),
       ox(0), 
       oy(0),
       length(0),
@@ -656,8 +567,7 @@ GeometryPBF<T>::GeometryPBF(pbf_itr const& geo_iterator,
     #endif
 }
 
-template <typename T>
-typename GeometryPBF<T>::command GeometryPBF<T>::point_next(value_type & rx, value_type & ry)
+typename GeometryPBF::command GeometryPBF::point_next(value_type & rx, value_type & ry)
 {
     if (length == 0) 
     {
@@ -703,16 +613,15 @@ typename GeometryPBF<T>::command GeometryPBF<T>::point_next(value_type & rx, val
     // While this error message is not verbose a try catch here would slow down processing.
     int32_t dx = protozero::decode_zigzag32(static_cast<uint32_t>(*geo_iterator_.first++));
     int32_t dy = protozero::decode_zigzag32(static_cast<uint32_t>(*geo_iterator_.first++));
-    detail::move_cursor(x, y, dx, dy, scale_x_, scale_y_);
+    detail::move_cursor(x, y, dx, dy);
     rx = x;
     ry = y;
     return move_to;
 }
 
-template <typename T>
-typename GeometryPBF<T>::command GeometryPBF<T>::line_next(value_type & rx, 
-                                                           value_type & ry, 
-                                                           bool skip_lineto_zero)
+typename GeometryPBF::command GeometryPBF::line_next(value_type & rx, 
+                                                     value_type & ry, 
+                                                     bool skip_lineto_zero)
 {
     if (length == 0)
     {
@@ -735,7 +644,7 @@ typename GeometryPBF<T>::command GeometryPBF<T>::line_next(value_type & rx,
                 // While this error message is not verbose a try catch here would slow down processing.
                 int32_t dx = protozero::decode_zigzag32(static_cast<uint32_t>(*geo_iterator_.first++));
                 int32_t dy = protozero::decode_zigzag32(static_cast<uint32_t>(*geo_iterator_.first++));
-                detail::move_cursor(x, y, dx, dy, scale_x_, scale_y_);
+                detail::move_cursor(x, y, dx, dy);
                 rx = x;
                 ry = y;
                 return move_to;
@@ -778,16 +687,15 @@ typename GeometryPBF<T>::command GeometryPBF<T>::line_next(value_type & rx,
         // We are going to skip this vertex as the point doesn't move call line_next again
         return line_next(rx, ry, true);
     }
-    detail::move_cursor(x, y, dx, dy, scale_x_, scale_y_);
+    detail::move_cursor(x, y, dx, dy);
     rx = x;
     ry = y;
     return line_to;
 }
 
-template <typename T>
-typename GeometryPBF<T>::command GeometryPBF<T>::ring_next(value_type & rx, 
-                                                           value_type & ry, 
-                                                           bool skip_lineto_zero)
+typename GeometryPBF::command GeometryPBF::ring_next(value_type & rx, 
+                                                     value_type & ry, 
+                                                     bool skip_lineto_zero)
 {
     if (length == 0)
     {
@@ -810,7 +718,7 @@ typename GeometryPBF<T>::command GeometryPBF<T>::ring_next(value_type & rx,
                 // While this error message is not verbose a try catch here would slow down processing.
                 int32_t dx = protozero::decode_zigzag32(static_cast<uint32_t>(*geo_iterator_.first++));
                 int32_t dy = protozero::decode_zigzag32(static_cast<uint32_t>(*geo_iterator_.first++));
-                detail::move_cursor(x, y, dx, dy, scale_x_, scale_y_);
+                detail::move_cursor(x, y, dx, dy);
                 rx = x;
                 ry = y;
                 ox = x;
@@ -858,66 +766,66 @@ typename GeometryPBF<T>::command GeometryPBF<T>::ring_next(value_type & rx,
         // We are going to skip this vertex as the point doesn't move call ring_next again
         return ring_next(rx, ry, true);
     }
-    detail::move_cursor(x, y, dx, dy, scale_x_, scale_y_);
+    detail::move_cursor(x, y, dx, dy);
     rx = x;
     ry = y;
     return line_to;
 }
 
-template <typename T>
-MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<typename T::value_type> decode_geometry(T & paths, 
-                                                                   int32_t geom_type, 
-                                                                   unsigned version,
-                                                                   mapnik::box2d<double> const& bbox)
+template <typename value_type>
+MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<value_type> decode_geometry(GeometryPBF & paths, 
+                                                                            int32_t geom_type, 
+                                                                            unsigned version,
+                                                                            value_type tile_x,
+                                                                            value_type tile_y,
+                                                                            double scale_x,
+                                                                            double scale_y,
+                                                                            mapnik::box2d<double> const& bbox)
 {
-    using value_type = typename T::value_type;
     mapnik::geometry::geometry<value_type> geom; // output geometry
     switch (geom_type)
     {
-    case Geometry_Type::POINT:
-    {
-        detail::decode_point<T>(geom, paths, bbox);
-        break;
-    }
-    case Geometry_Type::LINESTRING:
-    {
-        detail::decode_linestring<T>(geom, paths, bbox, version);
-        break;
-    }
-    case Geometry_Type::POLYGON:
-    {
-        std::vector<mapnik::geometry::linear_ring<value_type> > rings;
-        detail::read_rings<T>(rings, paths, bbox, version);
-        if (rings.empty())
+        case Geometry_Type::POINT:
         {
-            geom = std::move(mapnik::geometry::geometry_empty());
+            detail::decode_point<value_type>(geom, paths, tile_x, tile_y, scale_x, scale_y, bbox);
+            break;
         }
-        else
+        case Geometry_Type::LINESTRING:
         {
-            detail::decode_polygons(geom, rings, version, paths.scaling_reversed_orientation());
+            detail::decode_linestring<value_type>(geom, paths, tile_x, tile_y, scale_x, scale_y, bbox, version);
+            break;
+        }
+        case Geometry_Type::POLYGON:
+        {
+            detail::decode_polygon<value_type>(geom, paths, tile_x, tile_y, scale_x, scale_y, bbox, version);
+            break;
+        }
+        case Geometry_Type::UNKNOWN:
+        default:
+        {
+            // This was changed to not throw as unknown according to v2 of spec can simply be ignored and doesn't require
+            // it failing the processing
+            geom = mapnik::geometry::geometry_empty();
+            break;
         }
-        break;
-    }
-    case Geometry_Type::UNKNOWN:
-    default:
-    {
-        // This was changed to not throw as unknown according to v2 of spec can simply be ignored and doesn't require
-        // it failing the processing
-        geom = std::move(mapnik::geometry::geometry_empty());
-        break;
-    }
     }
-    return std::move(geom);
+    return geom;
 }
 
-template <typename T>
-MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<typename T::value_type> decode_geometry(T & paths, int32_t geom_type, unsigned version)
+template <typename value_type>
+MAPNIK_VECTOR_INLINE mapnik::geometry::geometry<value_type> decode_geometry(GeometryPBF & paths, 
+                                                                            int32_t geom_type, 
+                                                                            unsigned version,
+                                                                            value_type tile_x,
+                                                                            value_type tile_y,
+                                                                            double scale_x,
+                                                                            double scale_y)
 {
     mapnik::box2d<double> bbox(std::numeric_limits<double>::lowest(),
                                std::numeric_limits<double>::lowest(),
                                std::numeric_limits<double>::max(),
                                std::numeric_limits<double>::max());
-    return decode_geometry(paths, geom_type, version, bbox);
+    return decode_geometry<value_type>(paths, geom_type, version, tile_x, tile_y, scale_x, scale_y, bbox);
 }
 
 } // end ns vector_tile_impl
diff --git a/test/data/0.0.0.vector-b.mvt b/test/data/0.0.0.vector-b.mvt
index 25b6972..7c04db5 100644
Binary files a/test/data/0.0.0.vector-b.mvt and b/test/data/0.0.0.vector-b.mvt differ
diff --git a/test/data/simplified_geometry.geojson b/test/data/simplified_geometry.geojson
index 3e590aa..72b81c0 100644
--- a/test/data/simplified_geometry.geojson
+++ b/test/data/simplified_geometry.geojson
@@ -1 +1 @@
-{"type":"Polygon","coordinates":[[[160.36171875,11.2997786224589],[160.3828125,11.3011576095711],[160.408125,11.3039155638972],[160.408125,11.2997786224589],[160.425,11.3094313929343],[160.41234375,11.3411453475587],[160.3996875,11.3301148056307],[160.40953125,11.3700984927314],[160.39265625,11.3618264654176],[160.396875,11.3797488877286],[160.4053125,11.3893989555911],[160.40953125,11.3866418267411],[160.419375,11.4004272036667],[160.41515625,11.4059411672242],[160.419375,11.41145502372 [...]
\ No newline at end of file
+{"type":"Polygon","coordinates":[[[160.36171875,11.2997786224589],[160.3828125,11.3011576095711],[160.408125,11.3039155638971],[160.408125,11.2997786224589],[160.425,11.3094313929343],[160.41234375,11.3411453475587],[160.3996875,11.3301148056307],[160.40953125,11.3700984927314],[160.39265625,11.3618264654176],[160.396875,11.3797488877286],[160.4053125,11.3893989555911],[160.40953125,11.3866418267411],[160.419375,11.4004272036667],[160.41515625,11.4059411672241],[160.419375,11.41145502372 [...]
\ No newline at end of file
diff --git a/test/data/simplified_geometry_pbf.geojson b/test/data/simplified_geometry_pbf.geojson
index 3e590aa..72b81c0 100644
--- a/test/data/simplified_geometry_pbf.geojson
+++ b/test/data/simplified_geometry_pbf.geojson
@@ -1 +1 @@
-{"type":"Polygon","coordinates":[[[160.36171875,11.2997786224589],[160.3828125,11.3011576095711],[160.408125,11.3039155638972],[160.408125,11.2997786224589],[160.425,11.3094313929343],[160.41234375,11.3411453475587],[160.3996875,11.3301148056307],[160.40953125,11.3700984927314],[160.39265625,11.3618264654176],[160.396875,11.3797488877286],[160.4053125,11.3893989555911],[160.40953125,11.3866418267411],[160.419375,11.4004272036667],[160.41515625,11.4059411672242],[160.419375,11.41145502372 [...]
\ No newline at end of file
+{"type":"Polygon","coordinates":[[[160.36171875,11.2997786224589],[160.3828125,11.3011576095711],[160.408125,11.3039155638971],[160.408125,11.2997786224589],[160.425,11.3094313929343],[160.41234375,11.3411453475587],[160.3996875,11.3301148056307],[160.40953125,11.3700984927314],[160.39265625,11.3618264654176],[160.396875,11.3797488877286],[160.4053125,11.3893989555911],[160.40953125,11.3866418267411],[160.419375,11.4004272036667],[160.41515625,11.4059411672241],[160.419375,11.41145502372 [...]
\ No newline at end of file
diff --git a/test/fixtures/rasterize-expected-1.png b/test/fixtures/rasterize-expected-1.png
index 2308d2f..9216d28 100644
Binary files a/test/fixtures/rasterize-expected-1.png and b/test/fixtures/rasterize-expected-1.png differ
diff --git a/test/geometry_visual_test.cpp b/test/geometry_visual_test.cpp
index e77e1ff..3c94cf5 100644
--- a/test/geometry_visual_test.cpp
+++ b/test/geometry_visual_test.cpp
@@ -89,10 +89,8 @@ void clip_geometry(mapnik::Map const& map,
             double i_x = bbox.minx();
             double i_y = bbox.maxy();
             
-            mapnik::vector_tile_impl::GeometryPBF<double> geoms2_pbf(geom_itr, i_x, i_y, 1.0 * sx, -1.0 * sy);
-            geom4326_pbf = mapnik::vector_tile_impl::decode_geometry(geoms2_pbf, geometry_type, 2);
-            //mapnik::vector_tile_impl::GeometryPBF<double> geoms2_pbf(geom_itr, 0.0, 0.0, 1.0, 1.0);
-            //geom4326_pbf = std::move(mapnik::vector_tile_impl::decode_geometry(geoms2_pbf, geometry_type, 2));
+            mapnik::vector_tile_impl::GeometryPBF geoms2_pbf(geom_itr);
+            geom4326_pbf = mapnik::vector_tile_impl::decode_geometry<double>(geoms2_pbf, geometry_type, 2, i_x, i_y, 1.0 * sx, -1.0 * sy);
             
             std::string reason;
             std::string is_valid = "false";
diff --git a/test/system/encode_and_datasource_decode.cpp b/test/system/encode_and_datasource_decode.cpp
index a9ef5e6..830301c 100644
--- a/test/system/encode_and_datasource_decode.cpp
+++ b/test/system/encode_and_datasource_decode.cpp
@@ -47,7 +47,7 @@ TEST_CASE("encoding multi line string and check output datasource")
 
     REQUIRE(1 == tile.layers_size());
     vector_tile::Tile_Layer const& layer = tile.layers(0);
-    CHECK(1 == layer.features_size());
+    REQUIRE(1 == layer.features_size());
     vector_tile::Tile_Feature const& f = layer.features(0);
     CHECK(12 == f.geometry_size());
     CHECK(9 == f.geometry(0)); // 1 move_to
@@ -75,7 +75,7 @@ TEST_CASE("encoding multi line string and check output datasource")
     mapnik::box2d<double> bbox(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);
     fs = ds.features(mapnik::query(bbox));
     f_ptr = fs->next();
-    CHECK(f_ptr != mapnik::feature_ptr());
+    REQUIRE(f_ptr != mapnik::feature_ptr());
     // no attributes
     CHECK(f_ptr->context()->size() == 0);
 
diff --git a/test/system/processor_and_datasource.cpp b/test/system/processor_and_datasource.cpp
index 5748075..6af58ce 100644
--- a/test/system/processor_and_datasource.cpp
+++ b/test/system/processor_and_datasource.cpp
@@ -253,7 +253,7 @@ TEST_CASE("vector tile datasource -- should filter features outside extent")
     REQUIRE(1 == tile.layers_size());
     vector_tile::Tile_Layer const& layer = tile.layers(0);
     CHECK(std::string("layer") == layer.name());
-    CHECK(1 == layer.features_size());
+    REQUIRE(1 == layer.features_size());
     vector_tile::Tile_Feature const& f = layer.features(0);
     CHECK(static_cast<mapnik::value_integer>(1) == static_cast<mapnik::value_integer>(f.id()));
     CHECK(3 == f.geometry_size());
@@ -273,7 +273,7 @@ TEST_CASE("vector tile datasource -- should filter features outside extent")
     fs = ds.features(mapnik::query(bbox));
     mapnik::feature_ptr feat = fs->next();
     // Check that feature is not empty.
-    CHECK(feat != mapnik::feature_ptr());
+    REQUIRE(feat != mapnik::feature_ptr());
     CHECK(feat->size() == 0);
     // Check that this was the only feature so next should be empty
     CHECK(fs->next() == mapnik::feature_ptr());
diff --git a/test/unit/datasource-pbf/from_layer.cpp b/test/unit/datasource-pbf/from_layer.cpp
index 557b134..a2c7b34 100644
--- a/test/unit/datasource-pbf/from_layer.cpp
+++ b/test/unit/datasource-pbf/from_layer.cpp
@@ -149,7 +149,7 @@ TEST_CASE( "extent of a tile effects the scale of features" )
         mapnik::featureset_ptr featureset = ds.features(q);
         REQUIRE(featureset);
         mapnik::feature_ptr feature = featureset->next();
-
+        REQUIRE(feature);
         std::string wkt0;
         mapnik::util::to_wkt(wkt0, feature->get_geometry());
         CHECK(wkt0 == "POINT(-19988588.6446867 19988588.6446867)");
@@ -167,7 +167,7 @@ TEST_CASE( "extent of a tile effects the scale of features" )
         mapnik::featureset_ptr featureset = ds.features(q);
         REQUIRE(featureset);
         mapnik::feature_ptr feature = featureset->next();
-
+        REQUIRE(feature);
         std::string wkt0;
         mapnik::util::to_wkt(wkt0, feature->get_geometry());
         CHECK(wkt0 == "POINT(-19939668.9465842 19939668.9465842)");
diff --git a/test/unit/decoding/linestring.cpp b/test/unit/decoding/linestring.cpp
index 275c092..fe2b5a5 100644
--- a/test/unit/decoding/linestring.cpp
+++ b/test/unit/decoding/linestring.cpp
@@ -41,11 +41,11 @@ TEST_CASE("decode simple linestring")
     feature.add_geometry(protozero::encode_zigzag32(0));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2,10 10,0 10)");
@@ -54,7 +54,7 @@ TEST_CASE("decode simple linestring")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2,10 10,0 10)");
@@ -72,17 +72,17 @@ TEST_CASE("decode degenerate line_string only moveto")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -100,17 +100,17 @@ TEST_CASE("decode degenerate line_string lineto(0,0)")
     feature.add_geometry(protozero::encode_zigzag32(0));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -130,11 +130,11 @@ TEST_CASE("decode line_string with first lineto command having delta zero")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2)");
@@ -143,7 +143,7 @@ TEST_CASE("decode line_string with first lineto command having delta zero")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2)");
@@ -167,11 +167,11 @@ TEST_CASE("decode line_string with second lineto command having delta zero")
     feature.add_geometry(protozero::encode_zigzag32(0));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2)");
@@ -180,7 +180,7 @@ TEST_CASE("decode line_string with second lineto command having delta zero")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2)");
@@ -206,11 +206,11 @@ TEST_CASE("decode line_string with third lineto command having delta zero")
     feature.add_geometry(protozero::encode_zigzag32(0));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2,3 3)");
@@ -219,7 +219,7 @@ TEST_CASE("decode line_string with third lineto command having delta zero")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(1 1,2 2,3 3)");
@@ -243,16 +243,16 @@ TEST_CASE("decode degenerate linestring with close command at end")
     feature.add_geometry(15); // close_path
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -272,16 +272,16 @@ TEST_CASE("decode degenerate linestring with close command first")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -302,16 +302,16 @@ TEST_CASE("decode degenerate linestring with moveto command count greater then 1
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -329,16 +329,16 @@ TEST_CASE("decode degenerate linestring with moveto command count of zero")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -358,16 +358,16 @@ TEST_CASE("decode degenerate linestring with lineto command count of zero")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -386,16 +386,16 @@ TEST_CASE("decode degenerate linestring that starts with unknown command")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -414,16 +414,16 @@ TEST_CASE("decode degenerate linestring that ends with unknown command")
     feature.add_geometry((1 << 3u) | 5u); // invalid command
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -445,16 +445,16 @@ TEST_CASE("decode degenerate linestring that begins with lineto")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -476,16 +476,16 @@ TEST_CASE("decode degenerate linestring that begins with lineto delta zero")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -504,16 +504,16 @@ TEST_CASE("decode degenerate linestring that begins with close")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -536,11 +536,11 @@ TEST_CASE("decode linestring that begins with two moveto commands")
     feature.add_geometry(protozero::encode_zigzag32(1));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "LINESTRING(2 2,3 3)");
@@ -549,6 +549,6 @@ TEST_CASE("decode linestring that begins with two moveto commands")
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_LINESTRING, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_LINESTRING, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
diff --git a/test/unit/decoding/point.cpp b/test/unit/decoding/point.cpp
index 0345dc3..db210e7 100644
--- a/test/unit/decoding/point.cpp
+++ b/test/unit/decoding/point.cpp
@@ -34,11 +34,11 @@ TEST_CASE("decode simple point")
     feature.add_geometry(protozero::encode_zigzag32(5));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(5 5)");
@@ -47,7 +47,7 @@ TEST_CASE("decode simple point")
 
     SECTION("VT Spec v2") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(5 5)");
@@ -65,11 +65,11 @@ TEST_CASE("decode simple negative point")
     feature.add_geometry(protozero::encode_zigzag32(-5));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(-5 -5)");
@@ -78,7 +78,7 @@ TEST_CASE("decode simple negative point")
 
     SECTION("VT Spec v2") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(-5 -5)");
@@ -96,11 +96,11 @@ TEST_CASE("point with delta of max int32")
     feature.add_geometry(protozero::encode_zigzag32(max_32t));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(2147483647 2147483647)");
@@ -109,7 +109,7 @@ TEST_CASE("point with delta of max int32")
 
     SECTION("VT Spec v2") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(2147483647 2147483647)");
@@ -127,11 +127,11 @@ TEST_CASE("point with delta of min int32")
     feature.add_geometry(protozero::encode_zigzag32(min_32t));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(-2147483648 -2147483648)");
@@ -140,7 +140,7 @@ TEST_CASE("point with delta of min int32")
 
     SECTION("VT Spec v2") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(-2147483648 -2147483648)");
@@ -158,11 +158,11 @@ TEST_CASE("point with delta of min int32 + 1")
     feature.add_geometry(protozero::encode_zigzag32(min_32t));
     
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(-2147483647 -2147483647)");
@@ -171,7 +171,7 @@ TEST_CASE("point with delta of min int32 + 1")
 
     SECTION("VT Spec v2") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POINT(-2147483647 -2147483647)");
@@ -192,16 +192,16 @@ TEST_CASE("degenerate point with close command")
     feature.add_geometry(15); // close_path
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -219,16 +219,16 @@ TEST_CASE("degenerate point with lineto command")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -241,16 +241,16 @@ TEST_CASE("degenerate point with moveto with out enough parameters")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -264,16 +264,16 @@ TEST_CASE("degenerate point with moveto with out enough parameters - case 2")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -287,16 +287,16 @@ TEST_CASE("degenerate point with moveto with command count of zero")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -310,16 +310,16 @@ TEST_CASE("degenerate point with invalid command")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
     
     SECTION("VT Spec v1") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2") 
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -343,11 +343,11 @@ TEST_CASE("multipoint with three movetos with command count 1")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v2") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "MULTIPOINT(1 1,2 2,3 3)");
@@ -356,7 +356,7 @@ TEST_CASE("multipoint with three movetos with command count 1")
 
     SECTION("VT Spec v1") 
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POINT, 1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POINT, 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "MULTIPOINT(1 1,2 2,3 3)");
diff --git a/test/unit/decoding/polygon.cpp b/test/unit/decoding/polygon.cpp
index d04e67b..643daf3 100644
--- a/test/unit/decoding/polygon.cpp
+++ b/test/unit/decoding/polygon.cpp
@@ -43,11 +43,11 @@ TEST_CASE("decode simple polygon")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0))");
@@ -56,7 +56,7 @@ TEST_CASE("decode simple polygon")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0))");
@@ -86,11 +86,11 @@ TEST_CASE("decode simple polygon - int64 decode")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<std::int64_t> geoms = feature_to_pbf_geometry<std::int64_t>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0))");
@@ -99,7 +99,7 @@ TEST_CASE("decode simple polygon - int64 decode")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0))");
@@ -148,11 +148,11 @@ TEST_CASE("decode simple polygon with hole")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0),(-7 7,-3 7,-3 3,-7 3,-7 7))");
@@ -161,7 +161,7 @@ TEST_CASE("decode simple polygon with hole")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0),(-7 7,-3 7,-3 3,-7 3,-7 7))");
@@ -210,11 +210,11 @@ TEST_CASE("decode simple multipolygon")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "MULTIPOLYGON(((0 0,0 10,-10 10,-10 0,0 0)),((-7 7,-7 3,-3 3,-3 7,-7 7)))");
@@ -223,7 +223,7 @@ TEST_CASE("decode simple multipolygon")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "MULTIPOLYGON(((0 0,0 10,-10 10,-10 0,0 0)),((-7 7,-7 3,-3 3,-3 7,-7 7)))");
@@ -274,11 +274,11 @@ TEST_CASE("decode polygon with hole where winding orders are reversed.")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0),(-7 7,-3 7,-3 3,-7 3,-7 7))");
@@ -287,7 +287,7 @@ TEST_CASE("decode polygon with hole where winding orders are reversed.")
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -368,11 +368,11 @@ TEST_CASE("decode simple multi polygon with hole")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "MULTIPOLYGON(((0 0,0 10,-10 10,-10 0,0 0),(-7 7,-3 7,-3 3,-7 3,-7 7)),((0 0,0 10,-10 10,-10 0,0 0),(-7 7,-3 7,-3 3,-7 3,-7 7)))");
@@ -381,7 +381,7 @@ TEST_CASE("decode simple multi polygon with hole")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "MULTIPOLYGON(((0 0,0 10,-10 10,-10 0,0 0),(-7 7,-3 7,-3 3,-7 3,-7 7)),((0 0,0 10,-10 10,-10 0,0 0),(-7 7,-3 7,-3 3,-7 3,-7 7)))");
@@ -465,11 +465,11 @@ TEST_CASE("decode multi polygon with holes - first ring invalid")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "MULTIPOLYGON(((-7 7,-7 3,-3 3,-3 7,-7 7),(0 0,-10 0,-10 10,0 10,0 0)),((-7 7,-7 3,-3 3,-3 7,-7 7)))");
@@ -478,7 +478,7 @@ TEST_CASE("decode multi polygon with holes - first ring invalid")
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -507,11 +507,11 @@ TEST_CASE("decode simple polygon -- incorrect exterior winding order")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,10 0,10 10,0 10,0 0))");
@@ -520,7 +520,7 @@ TEST_CASE("decode simple polygon -- incorrect exterior winding order")
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -534,16 +534,16 @@ TEST_CASE("decode polygon - only moveto")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -559,17 +559,17 @@ TEST_CASE("decode polygon - only moveto and close")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -587,16 +587,16 @@ TEST_CASE("decode polygon - only moveto and close followed by close")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -616,16 +616,16 @@ TEST_CASE("decode polygon - only moveto and close followed by lineto")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -645,16 +645,16 @@ TEST_CASE("decode polygon - only moveto and close followed by lineto -- delta ze
     feature.add_geometry(protozero::encode_zigzag32(0));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -686,11 +686,11 @@ TEST_CASE("decode polygon - moveto and close followed by real polygon")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0))");
@@ -699,7 +699,7 @@ TEST_CASE("decode polygon - moveto and close followed by real polygon")
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -717,16 +717,16 @@ TEST_CASE("decode polygon - only moveto and lineto")
     feature.add_geometry(protozero::encode_zigzag32(0));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -760,16 +760,16 @@ TEST_CASE("decode polygon - moveto and lineto followed by real polygon")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -790,17 +790,17 @@ TEST_CASE("decode polygon - only moveto lineto and close")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -822,16 +822,16 @@ TEST_CASE("decode polygon - only moveto, lineto, and close followed by close")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -855,16 +855,16 @@ TEST_CASE("decode polygon - only moveto, lineto, and close followed by lineto")
     feature.add_geometry(protozero::encode_zigzag32(1));
         
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -888,16 +888,16 @@ TEST_CASE("decode polygon - only moveto, lineto, and close followed by lineto --
     feature.add_geometry(protozero::encode_zigzag32(0));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -933,11 +933,11 @@ TEST_CASE("decode polygon - moveto lineto and close followed by real polygon")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 10,-10 10,-10 0,0 0))");
@@ -946,7 +946,7 @@ TEST_CASE("decode polygon - moveto lineto and close followed by real polygon")
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -969,17 +969,17 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - both delta z
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1003,17 +1003,17 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - both delta z
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1037,17 +1037,17 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - first delta
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1071,17 +1071,17 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - second delta
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         CHECK( geom.is<mapnik::geometry::geometry_empty>() );
     }
     
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1105,11 +1105,11 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - lineto two c
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,10 0,10 10,0 0))");
@@ -1118,7 +1118,7 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - lineto two c
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,10 0,10 10,0 0))");
@@ -1144,11 +1144,11 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - lineto one c
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,10 0,10 10,0 0))");
@@ -1157,7 +1157,7 @@ TEST_CASE("decode polygon - only moveto, lineto, lineto and close - lineto one c
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,10 0,10 10,0 0))");
@@ -1187,16 +1187,16 @@ TEST_CASE("decode polygon -- moveto command count zero")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1222,16 +1222,16 @@ TEST_CASE("decode polygon -- moveto command count two")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1259,16 +1259,16 @@ TEST_CASE("decode polygon -- lineto command count 0")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1294,16 +1294,16 @@ TEST_CASE("decode polygon -- lineto command count 2 when it should be 3")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1329,16 +1329,16 @@ TEST_CASE("decode polygon -- lineto command count 4 when it should be 3")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1369,16 +1369,16 @@ TEST_CASE("decode polygon -- close is first command")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1409,16 +1409,16 @@ TEST_CASE("decode polygon -- extra close command")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1451,16 +1451,16 @@ TEST_CASE("decode polygon -- lineto is first command -- delta zero")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1490,16 +1490,16 @@ TEST_CASE("decode polygon -- lineto is first command")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1532,16 +1532,16 @@ TEST_CASE("decode polygon -- lineto is last command -- delta zero")
     feature.add_geometry(protozero::encode_zigzag32(0));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1571,16 +1571,16 @@ TEST_CASE("decode polygon -- lineto is last command")
     feature.add_geometry(protozero::encode_zigzag32(1));
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
 
@@ -1607,15 +1607,15 @@ TEST_CASE("decode polygon -- has invalid command first")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 1));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 1, 0.0, 0.0, 1.0, 1.0));
     }
 
     SECTION("VT Spec v2")
     {
-        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry(geoms, vector_tile::Tile_GeomType_POLYGON, 2));
+        CHECK_THROWS(mapnik::vector_tile_impl::decode_geometry<double>(geoms, vector_tile::Tile_GeomType_POLYGON, 2, 0.0, 0.0, 1.0, 1.0));
     }
 }
diff --git a/test/unit/decoding/polygon_scaling.cpp b/test/unit/decoding/polygon_scaling.cpp
index 33f10d2..904b19a 100644
--- a/test/unit/decoding/polygon_scaling.cpp
+++ b/test/unit/decoding/polygon_scaling.cpp
@@ -43,11 +43,11 @@ TEST_CASE("decode simple polygon - scale 2")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string, 2.0, 2.0);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 2.0, 2.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 5,-5 5,-5 0,0 0))");
@@ -56,7 +56,7 @@ TEST_CASE("decode simple polygon - scale 2")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 2.0, 2.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 5,-5 5,-5 0,0 0))");
@@ -86,11 +86,11 @@ TEST_CASE("decode simple polygon - scale 2 - int64 decode")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<std::int64_t> geoms = feature_to_pbf_geometry<std::int64_t>(feature_string, 2.0, 2.0);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 1, 0.0, 0.0, 2.0, 2.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 5,-5 5,-5 0,0 0))");
@@ -99,7 +99,7 @@ TEST_CASE("decode simple polygon - scale 2 - int64 decode")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 2, 0.0, 0.0, 2.0, 2.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 5,-5 5,-5 0,0 0))");
@@ -129,11 +129,11 @@ TEST_CASE("decode simple polygon - scale 3.214")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string, 3.214, 3.214);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 3.214, 3.214);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 3.11138767890479,-3.11138767890479 3.11138767890479,-3.11138767890479 0,0 0))");
@@ -142,7 +142,7 @@ TEST_CASE("decode simple polygon - scale 3.214")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 3.214, 3.214);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 3.11138767890479,-3.11138767890479 3.11138767890479,-3.11138767890479 0,0 0))");
@@ -172,11 +172,11 @@ TEST_CASE("decode simple polygon - scale 3.214 - int64 decode")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<std::int64_t> geoms = feature_to_pbf_geometry<std::int64_t>(feature_string, 3.214, 3.214);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 1, 0.0, 0.0, 3.214, 3.214);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 3,-3 3,-3 0,0 0))");
@@ -185,7 +185,7 @@ TEST_CASE("decode simple polygon - scale 3.214 - int64 decode")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 2, 0.0, 0.0, 3.214, 3.214);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 3,-3 3,-3 0,0 0))");
@@ -215,11 +215,11 @@ TEST_CASE("decode simple polygon - scale 0.46")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string, 0.46, 0.46);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 0.46, 0.46);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 21.7391304347826,-21.7391304347826 21.7391304347826,-21.7391304347826 0,0 0))");
@@ -228,7 +228,7 @@ TEST_CASE("decode simple polygon - scale 0.46")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 0.46, 0.46);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 21.7391304347826,-21.7391304347826 21.7391304347826,-21.7391304347826 0,0 0))");
@@ -258,11 +258,11 @@ TEST_CASE("decode simple polygon - scale 0.46 - int64 decode")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<std::int64_t> geoms = feature_to_pbf_geometry<std::int64_t>(feature_string, 0.46, 0.46);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 1, 0.0, 0.0, 0.46, 0.46);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 22,-22 22,-22 0,0 0))");
@@ -271,7 +271,7 @@ TEST_CASE("decode simple polygon - scale 0.46 - int64 decode")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<std::int64_t>(geoms, feature.type(), 2, 0.0, 0.0, 0.46, 0.46);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 22,-22 22,-22 0,0 0))");
@@ -301,11 +301,11 @@ TEST_CASE("decode simple polygon - inverted y axis")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string, 1.0, -1.0);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, -1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,-10 0,-10 -10,0 -10,0 0))");
@@ -314,7 +314,7 @@ TEST_CASE("decode simple polygon - inverted y axis")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, -1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,-10 0,-10 -10,0 -10,0 0))");
@@ -344,11 +344,11 @@ TEST_CASE("decode simple polygon - inverted x axis")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string, -1.0, 1.0);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, -1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,10 0,10 10,0 10,0 0))");
@@ -357,7 +357,7 @@ TEST_CASE("decode simple polygon - inverted x axis")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, -1.0, 1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,10 0,10 10,0 10,0 0))");
@@ -387,11 +387,11 @@ TEST_CASE("decode simple polygon - inverted x axis and y axis")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string, -1.0, -1.0);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, -1.0, -1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 -10,10 -10,10 0,0 0))");
@@ -400,7 +400,7 @@ TEST_CASE("decode simple polygon - inverted x axis and y axis")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, -1.0, -1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,0 -10,10 -10,10 0,0 0))");
@@ -449,11 +449,11 @@ TEST_CASE("decode simple polygon with hole - invert y axis")
     feature.add_geometry(15);
 
     std::string feature_string = feature.SerializeAsString();
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms = feature_to_pbf_geometry<double>(feature_string, 1.0, -1.0);
+    mapnik::vector_tile_impl::GeometryPBF geoms = feature_to_pbf_geometry(feature_string);
 
     SECTION("VT Spec v1")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),1);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 1, 0.0, 0.0, 1.0, -1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,-10 0,-10 -10,0 -10,0 0),(-7 -7,-7 -3,-3 -3,-3 -7,-7 -7))");
@@ -462,7 +462,7 @@ TEST_CASE("decode simple polygon with hole - invert y axis")
 
     SECTION("VT Spec v2")
     {
-        auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, feature.type(),2);
+        auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, feature.type(), 2, 0.0, 0.0, 1.0, -1.0);
         std::string wkt0;
         CHECK( test_utils::to_wkt(wkt0,geom) );
         CHECK( wkt0 == "POLYGON((0 0,-10 0,-10 -10,0 -10,0 0),(-7 -7,-7 -3,-3 -3,-3 -7,-7 -7))");
diff --git a/test/utils/decoding_util.cpp b/test/utils/decoding_util.cpp
index 27cd3b3..c42c7fc 100644
--- a/test/utils/decoding_util.cpp
+++ b/test/utils/decoding_util.cpp
@@ -4,13 +4,9 @@
 // mapnik-vector-tile
 #include "vector_tile_geometry_decoder.hpp"
 
-template <typename T>
-mapnik::vector_tile_impl::GeometryPBF<T> feature_to_pbf_geometry(std::string const& feature_string, double scale_x, double scale_y)
+mapnik::vector_tile_impl::GeometryPBF feature_to_pbf_geometry(std::string const& feature_string)
 {
     protozero::pbf_reader feature_pbf(feature_string);
     feature_pbf.next(4);
-    return mapnik::vector_tile_impl::GeometryPBF<T>(feature_pbf.get_packed_uint32(),0.0,0.0,scale_x,scale_y);
+    return mapnik::vector_tile_impl::GeometryPBF(feature_pbf.get_packed_uint32());
 }
-
-template mapnik::vector_tile_impl::GeometryPBF<double> feature_to_pbf_geometry<double>(std::string const& feature_string, double scale_x, double scale_y);
-template mapnik::vector_tile_impl::GeometryPBF<std::int64_t> feature_to_pbf_geometry<std::int64_t>(std::string const& feature_string, double scale_x, double scale_y);
diff --git a/test/utils/decoding_util.hpp b/test/utils/decoding_util.hpp
index d8becfa..7916073 100644
--- a/test/utils/decoding_util.hpp
+++ b/test/utils/decoding_util.hpp
@@ -4,7 +4,6 @@
 // mapnik vector tile
 #include "vector_tile_geometry_decoder.hpp"
 
-template <typename T>
-mapnik::vector_tile_impl::GeometryPBF<T> feature_to_pbf_geometry(std::string const& feature_string, double scale_x = 1.0, double scale_y = 1.0);
+mapnik::vector_tile_impl::GeometryPBF feature_to_pbf_geometry(std::string const& feature_string);
 
 #endif // __MAPNIK_VECTOR_TILE_TEST_DECODING_UTIL_H__
diff --git a/test/utils/encoding_util.cpp b/test/utils/encoding_util.cpp
index 563092a..6611aee 100644
--- a/test/utils/encoding_util.cpp
+++ b/test/utils/encoding_util.cpp
@@ -81,7 +81,7 @@ std::string compare_pbf(mapnik::geometry::geometry<std::int64_t> const& g, unsig
             feature_reader.skip();
         }
     }
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms(geom_itr, 0.0, 0.0, 1.0, 1.0);
-    auto g2 = mapnik::vector_tile_impl::decode_geometry(geoms, geometry_type, version);
+    mapnik::vector_tile_impl::GeometryPBF geoms(geom_itr);
+    auto g2 = mapnik::vector_tile_impl::decode_geometry<double>(geoms, geometry_type, version, 0.0, 0.0, 1.0, 1.0);
     return decode_to_path_string(g2);
 }
diff --git a/test/utils/round_trip.cpp b/test/utils/round_trip.cpp
index 9166014..dbf2b1e 100644
--- a/test/utils/round_trip.cpp
+++ b/test/utils/round_trip.cpp
@@ -86,8 +86,8 @@ mapnik::geometry::geometry<double> round_trip(mapnik::geometry::geometry<double>
             feature_reader.skip();
         }
     }
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms(geom_itr, 0, 0, 1000, -1000);
-    return mapnik::vector_tile_impl::decode_geometry(geoms, geometry_type, 2);
+    mapnik::vector_tile_impl::GeometryPBF geoms(geom_itr);
+    return mapnik::vector_tile_impl::decode_geometry<double>(geoms, geometry_type, 2, 0.0, 0.0, 1000.0, -1000.0);
 }
 
 } // end ns
diff --git a/test/vector_tile.cpp b/test/vector_tile.cpp
index a250271..cfe566b 100644
--- a/test/vector_tile.cpp
+++ b/test/vector_tile.cpp
@@ -87,8 +87,8 @@ TEST_CASE("vector tile from simplified geojson")
             feature_reader.skip();
         }
     }
-    mapnik::vector_tile_impl::GeometryPBF<double> geoms(geom_itr, tile_x, tile_y, scale, -1*scale);
-    auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, geometry_type, 2);
+    mapnik::vector_tile_impl::GeometryPBF geoms(geom_itr);
+    auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, geometry_type, 2, tile_x, tile_y, scale, -1.0 * scale);
 
     unsigned int n_err = 0;
     mapnik::projection wgs84("+init=epsg:4326",true);
diff --git a/test/vector_tile_pbf.cpp b/test/vector_tile_pbf.cpp
index d9034ab..ce00c7f 100644
--- a/test/vector_tile_pbf.cpp
+++ b/test/vector_tile_pbf.cpp
@@ -170,14 +170,14 @@ TEST_CASE("pbf vector tile datasource")
     mapnik::box2d<double> bbox(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);
     fs = ds.features(mapnik::query(bbox));
     mapnik::feature_ptr feat = fs->next();
-    CHECK(feat != mapnik::feature_ptr());
+    REQUIRE(feat != mapnik::feature_ptr());
     CHECK(feat->size() == 0);
     CHECK(fs->next() == mapnik::feature_ptr());
     mapnik::query qq = mapnik::query(mapnik::box2d<double>(-1,-1,1,1));
     qq.add_property_name("name");
     fs = ds.features(qq);
     feat = fs->next();
-    CHECK(feat != mapnik::feature_ptr());
+    REQUIRE(feat != mapnik::feature_ptr());
     CHECK(feat->size() == 1);
     CHECK(feat->get("name") == mapnik::value_unicode_string("null island"));
 
@@ -187,10 +187,10 @@ TEST_CASE("pbf vector tile datasource")
 
     // ensure same behavior for feature_at_point
     fs = ds.features_at_point(mapnik::coord2d(0.0,0.0),0.0001);
-    CHECK(fs->next() != mapnik::feature_ptr());
+    REQUIRE(fs->next() != mapnik::feature_ptr());
 
     fs = ds.features_at_point(mapnik::coord2d(1.0,1.0),1.0001);
-    CHECK(fs->next() != mapnik::feature_ptr());
+    REQUIRE(fs->next() != mapnik::feature_ptr());
 
     fs = ds.features_at_point(mapnik::coord2d(-10,-10),0);
     CHECK(fs->next() == mapnik::feature_ptr());
@@ -199,7 +199,7 @@ TEST_CASE("pbf vector tile datasource")
     mapnik::feature_ptr f_ptr;
     fs = ds.features(mapnik::query(bbox));
     f_ptr = fs->next();
-    CHECK(f_ptr != mapnik::feature_ptr());
+    REQUIRE(f_ptr != mapnik::feature_ptr());
     // no attributes
     CHECK(f_ptr->context()->size() == 0);
 
@@ -207,7 +207,7 @@ TEST_CASE("pbf vector tile datasource")
     q.add_property_name("name");
     fs = ds.features(q);
     f_ptr = fs->next();
-    CHECK(f_ptr != mapnik::feature_ptr());
+    REQUIRE(f_ptr != mapnik::feature_ptr());
     // one attribute
     CHECK(f_ptr->context()->size() == 1);
 }
@@ -273,7 +273,7 @@ TEST_CASE("pbf encoding multi line")
     mapnik::box2d<double> bbox(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);
     fs = ds.features(mapnik::query(bbox));
     f_ptr = fs->next();
-    CHECK(f_ptr != mapnik::feature_ptr());
+    REQUIRE(f_ptr != mapnik::feature_ptr());
     // no attributes
     CHECK(f_ptr->context()->size() == 0);
 
@@ -415,9 +415,9 @@ TEST_CASE("pbf vector tile from simplified geojson")
       {
           found = true;
           std::pair< protozero::pbf_reader::const_uint32_iterator, protozero::pbf_reader::const_uint32_iterator > geom_itr = pbf_feature.get_packed_uint32();
-          mapnik::vector_tile_impl::GeometryPBF<double> geoms(geom_itr, tile_x,tile_y,scale,-1*scale);
-          auto geom = mapnik::vector_tile_impl::decode_geometry(geoms, f.type(),2);
-              unsigned int n_err = 0;
+          mapnik::vector_tile_impl::GeometryPBF geoms(geom_itr);
+          auto geom = mapnik::vector_tile_impl::decode_geometry<double>(geoms, f.type(), 2, tile_x, tile_y, scale, -1.0 * scale);
+          unsigned int n_err = 0;
           mapnik::projection wgs84("+init=epsg:4326",true);
           mapnik::projection merc("+init=epsg:3857",true);
           mapnik::proj_transform prj_trans(merc,wgs84);
@@ -602,19 +602,19 @@ TEST_CASE("pbf vector tile from linestring geojson")
     std::size_t expected_num_attr_returned = q.property_names().size();
     auto fs = ds2->features(q);
     auto f_ptr = fs->next();
-    CHECK(f_ptr != mapnik::feature_ptr());
+    REQUIRE(f_ptr != mapnik::feature_ptr());
     // no attributes
     CHECK(f_ptr->context()->size() == expected_num_attr_returned);
     CHECK(f_ptr->get_geometry().is<mapnik::geometry::line_string<double> >());
     // second feature
     f_ptr = fs->next();
-    CHECK(f_ptr != mapnik::feature_ptr());
+    REQUIRE(f_ptr != mapnik::feature_ptr());
     CHECK(f_ptr->context()->size() == expected_num_attr_returned);
     CHECK(f_ptr->get_geometry().is<mapnik::geometry::line_string<double> >());
 
     // third feature
     f_ptr = fs->next();
-    CHECK(f_ptr != mapnik::feature_ptr());
+    REQUIRE(f_ptr != mapnik::feature_ptr());
     CHECK(f_ptr->context()->size() == expected_num_attr_returned);
     CHECK(f_ptr->get_geometry().is<mapnik::geometry::point<double> >());
 
diff --git a/test/vector_tile_rasterize.cpp b/test/vector_tile_rasterize.cpp
index 4f43a34..334250f 100644
--- a/test/vector_tile_rasterize.cpp
+++ b/test/vector_tile_rasterize.cpp
@@ -122,7 +122,7 @@ TEST_CASE("vector tile rasterize -- should try to decode windfail tile")
     // now `tile` should contain all the data
     std::string buffer2;
     out_tile.serialize_to_string(buffer2);
-    CHECK(2840 == buffer2.size());
+    CHECK(2824 == buffer2.size());
 
     std::ofstream stream_out("./test/data/0.0.0.vector-b.mvt",std::ios_base::out|std::ios_base::binary);
     stream_out << buffer2;
@@ -133,7 +133,7 @@ TEST_CASE("vector tile rasterize -- should try to decode windfail tile")
         mapnik::Map map(256,256,"+init=epsg:3857");
         vector_tile::Tile tile2;
         CHECK(tile2.ParseFromString(buffer2));
-        CHECK(1 == tile2.layers_size());
+        REQUIRE(1 == tile2.layers_size());
         vector_tile::Tile_Layer const& layer2 = tile2.layers(0);
         CHECK(std::string("water") == layer2.name());
         CHECK(5 == layer2.features_size());
@@ -168,9 +168,9 @@ TEST_CASE("vector tile rasterize -- should try to decode windfail tile")
         mapnik::agg_renderer<mapnik::image_rgba8> ren(map,im);
         ren.apply();
         unsigned diff = testing::compare_images(im,"test/fixtures/rasterize-expected-1.png");
-        // should be almost equal (50 is good enough since re-rendering filters a few small degenerates)
-        CHECK(50 == diff);
-        if (diff > 50)
+        // should be almost equal (111 is good enough since re-rendering filters a few small degenerates)
+        CHECK(111 == diff);
+        if (diff > 111)
         {
             mapnik::save_to_file(im,"test/fixtures/rasterize-actual-1.png","png32");
         }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mapnik-vector-tile.git



More information about the Pkg-grass-devel mailing list