Created
October 8, 2014 06:52
-
-
Save springmeyer/739672d7414dc8741df0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/bindings/python/mapnik_generator_grammars.cpp b/bindings/python/mapnik_generator_grammars.cpp | |
index e621628..f6fa4d1 100644 | |
--- a/bindings/python/mapnik_generator_grammars.cpp | |
+++ b/bindings/python/mapnik_generator_grammars.cpp | |
@@ -29,8 +29,8 @@ | |
using sink_type = std::back_insert_iterator<std::string>; | |
template struct mapnik::json::feature_generator_grammar<sink_type>; | |
-template struct mapnik::json::geometry_generator_grammar<sink_type>; | |
-template struct mapnik::json::multi_geometry_generator_grammar<sink_type>; | |
+template struct mapnik::json::geometry_generator_grammar<sink_type, mapnik::geometry_type>; | |
+template struct mapnik::json::multi_geometry_generator_grammar<sink_type, mapnik::geometry_type>; | |
template struct mapnik::svg::svg_path_generator<sink_type, mapnik::geometry_type>; | |
template struct mapnik::wkt::wkt_generator<sink_type, mapnik::geometry_type>; | |
template struct mapnik::wkt::wkt_multi_generator<sink_type, mapnik::geometry_container>; | |
diff --git a/include/mapnik/json/feature_generator_grammar.hpp b/include/mapnik/json/feature_generator_grammar.hpp | |
index 973c682..46ddaee 100644 | |
--- a/include/mapnik/json/feature_generator_grammar.hpp | |
+++ b/include/mapnik/json/feature_generator_grammar.hpp | |
@@ -156,7 +156,7 @@ struct feature_generator_grammar: | |
feature_generator_grammar(); | |
karma::rule<OutputIterator, mapnik::feature_impl const&()> feature; | |
- multi_geometry_generator_grammar<OutputIterator> geometry; | |
+ multi_geometry_generator_grammar<OutputIterator,mapnik::geometry_container> geometry; | |
escaped_string<OutputIterator> escaped_string_; | |
karma::rule<OutputIterator, mapnik::feature_impl const&()> properties; | |
karma::rule<OutputIterator, pair_type()> pair; | |
diff --git a/include/mapnik/json/geometry_generator_grammar.hpp b/include/mapnik/json/geometry_generator_grammar.hpp | |
index 2d61e9f..76d8810 100644 | |
--- a/include/mapnik/json/geometry_generator_grammar.hpp | |
+++ b/include/mapnik/json/geometry_generator_grammar.hpp | |
@@ -26,14 +26,18 @@ | |
// mapnik | |
#include <mapnik/global.hpp> | |
#include <mapnik/geometry.hpp> | |
-#include <mapnik/util/path_iterator.hpp> | |
-#include <mapnik/util/container_adapter.hpp> | |
#include <mapnik/vertex.hpp> // for CommandType::SEG_MOVETO | |
+#include <mapnik/util/container_adapter.hpp> | |
// boost | |
#include <boost/spirit/include/karma.hpp> | |
+#include <boost/spirit/include/phoenix_core.hpp> | |
+#include <boost/spirit/include/phoenix_operator.hpp> | |
+#include <boost/spirit/include/phoenix_fusion.hpp> | |
#include <boost/spirit/include/phoenix_function.hpp> | |
+#include <boost/spirit/include/phoenix_statement.hpp> | |
#include <boost/fusion/adapted/std_tuple.hpp> | |
+#include <boost/type_traits/remove_pointer.hpp> | |
#include <boost/math/special_functions/trunc.hpp> // for vc++ and android whose c++11 libs lack std::trunc | |
//stl | |
@@ -42,54 +46,99 @@ | |
namespace mapnik { namespace json { | |
namespace karma = boost::spirit::karma; | |
+namespace phoenix = boost::phoenix; | |
namespace detail { | |
+template <typename Geometry> | |
struct get_type | |
{ | |
- using result_type = int; | |
- result_type operator() (geometry_type const& geom) const | |
+ template <typename T> | |
+ struct result { using type = int; }; | |
+ | |
+ int operator() (Geometry const& geom) const | |
{ | |
return static_cast<int>(geom.type()); | |
} | |
}; | |
+template <typename T> | |
struct get_first | |
{ | |
- using result_type = geometry_type::value_type const; | |
- result_type operator() (geometry_type const& geom) const | |
+ using geometry_type = T; | |
+ | |
+ template <typename U> | |
+ struct result { using type = const typename geometry_type::value_type; }; | |
+ | |
+ typename geometry_type::value_type const operator() (geometry_type const& geom) const | |
{ | |
- geometry_type::value_type coord; | |
- std::get<0>(coord) = geom.vertex(0,&std::get<1>(coord),&std::get<2>(coord)); | |
+ typename geometry_type::value_type coord; | |
+ geom.rewind(0); | |
+ std::get<0>(coord) = geom.vertex(&std::get<1>(coord),&std::get<2>(coord)); | |
return coord; | |
} | |
}; | |
-struct multi_geometry_type | |
+template <typename T> | |
+struct multi_geometry_ | |
{ | |
- using result_type = std::tuple<unsigned,bool> ; | |
- result_type operator() (geometry_container const& cont) const | |
+ using geometry_container = T; | |
+ | |
+ template <typename U> | |
+ struct result { using type = bool; }; | |
+ bool operator() (geometry_container const& geom) const | |
{ | |
- unsigned type = 0u; | |
- bool collection = false; | |
- for (auto const& geom : cont) | |
- { | |
- if (type != 0u && geom.type() != type) | |
- { | |
- collection = true; | |
- break; | |
- } | |
- type = geom.type(); | |
- } | |
- if (cont.size() > 1) type +=3; | |
- return std::tuple<unsigned,bool>(type, collection); | |
+ return geom.size() > 1 ? true : false; | |
+ } | |
+}; | |
+ | |
+template <typename T> | |
+struct get_x | |
+{ | |
+ using value_type = T; | |
+ | |
+ template <typename U> | |
+ struct result { using type = double; }; | |
+ | |
+ double operator() (value_type const& val) const | |
+ { | |
+ return std::get<1>(val); | |
} | |
}; | |
+template <typename T> | |
+struct get_y | |
+{ | |
+ using value_type = T; | |
+ | |
+ template <typename U> | |
+ struct result { using type = double; }; | |
+ | |
+ double operator() (value_type const& val) const | |
+ { | |
+ return std::get<2>(val); | |
+ } | |
+}; | |
+ | |
+template <typename T> | |
+struct multi_geometry_type | |
+{ | |
+ using geometry_container = T; | |
+ | |
+ template <typename U> | |
+ struct result { using type = std::tuple<unsigned,bool>; }; | |
+ | |
+ std::tuple<unsigned,bool> operator() (geometry_container const& geom) const; | |
+}; | |
+ | |
+template <typename Container> | |
struct not_empty | |
{ | |
- using result_type = bool; | |
- result_type operator() (geometry_container const& cont) const | |
+ | |
+ template <typename T> | |
+ struct result { using type = bool; }; | |
+ | |
+ bool operator() (Container const& cont) const | |
{ | |
for (auto const& geom : cont) | |
{ | |
@@ -104,7 +153,6 @@ struct json_coordinate_policy : karma::real_policies<T> | |
{ | |
using base_type = boost::spirit::karma::real_policies<T>; | |
static int floatfield(T n) { return base_type::fmtflags::fixed; } | |
- | |
static unsigned precision(T n) | |
{ | |
if (n == 0.0) return 0; | |
@@ -121,7 +169,7 @@ struct json_coordinate_policy : karma::real_policies<T> | |
template <typename OutputIterator> | |
static bool fraction_part(OutputIterator& sink, T n | |
- , unsigned adjprec, unsigned precision) | |
+ , unsigned adjprec, unsigned precision) | |
{ | |
if (n == 0) return true; | |
return base_type::fraction_part(sink, n, adjprec, precision); | |
@@ -130,44 +178,47 @@ struct json_coordinate_policy : karma::real_policies<T> | |
} | |
-template <typename OutputIterator> | |
+template <typename OutputIterator, typename Geometry> | |
struct geometry_generator_grammar : | |
- karma::grammar<OutputIterator, geometry_type const& ()> | |
+ karma::grammar<OutputIterator, Geometry const& ()> | |
{ | |
+ using geometry_type = Geometry; | |
+ using coord_type = typename boost::remove_pointer<typename geometry_type::value_type>::type; | |
+ | |
geometry_generator_grammar(); | |
- karma::rule<OutputIterator, geometry_type const& ()> coordinates; | |
+ karma::rule<OutputIterator, geometry_type const& ()> json; | |
karma::rule<OutputIterator, geometry_type const& ()> point; | |
karma::rule<OutputIterator, geometry_type const& ()> linestring; | |
karma::rule<OutputIterator, geometry_type const& ()> polygon; | |
karma::rule<OutputIterator, geometry_type const& ()> coords; | |
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2; | |
- karma::rule<OutputIterator, geometry_type::value_type ()> point_coord; | |
- karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord; | |
- boost::phoenix::function<detail::get_type > _type; | |
- boost::phoenix::function<detail::get_first> _first; | |
- karma::real_generator<double, detail::json_coordinate_policy<double> > coord_type; | |
+ karma::rule<OutputIterator, coord_type ()> point_coord; | |
+ karma::rule<OutputIterator, coord_type (unsigned& )> polygon_coord; | |
+ phoenix::function<detail::get_type<geometry_type>> _type; | |
+ phoenix::function<detail::get_first<geometry_type>> _first; | |
+ phoenix::function<detail::get_x<typename geometry_type::value_type> > _x; | |
+ phoenix::function<detail::get_y<typename geometry_type::value_type> > _y; | |
+ karma::real_generator<double, detail::json_coordinate_policy<double> > coordinate; | |
}; | |
-template <typename OutputIterator> | |
+template <typename OutputIterator, typename GeometryContainer> | |
struct multi_geometry_generator_grammar : | |
- karma::grammar<OutputIterator, karma::locals<std::tuple<unsigned,bool> >, | |
- geometry_container const& ()> | |
+ karma::grammar<OutputIterator, karma::locals<std::tuple<unsigned,bool>>, GeometryContainer const& ()> | |
{ | |
+ using geometry_type = typename boost::remove_pointer<typename GeometryContainer::value_type>::type; | |
+ | |
multi_geometry_generator_grammar(); | |
- karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >, | |
- geometry_container const&()> start; | |
- karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >, | |
- geometry_container const&()> geometry_collection; | |
- karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >, | |
- geometry_container const&()> geometry; | |
- karma::rule<OutputIterator, karma::locals<unsigned>, | |
- geometry_type const&()> geometry2; | |
- karma::rule<OutputIterator, geometry_container const&()> coordinates; | |
- geometry_generator_grammar<OutputIterator> path; | |
- boost::phoenix::function<detail::multi_geometry_type> multi_type_; | |
- boost::phoenix::function<detail::get_type > type_; | |
- boost::phoenix::function<detail::not_empty> not_empty_; | |
+ karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >, GeometryContainer const&()> json; | |
+ karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >, GeometryContainer const&()> geometry; | |
+ karma::rule<OutputIterator, karma::locals<std::tuple<unsigned,bool> >, GeometryContainer const&()> geometry_collection; | |
+ karma::rule<OutputIterator, karma::locals<unsigned>,geometry_type const&()> geometry2; | |
+ karma::rule<OutputIterator, GeometryContainer const&()> coordinates; | |
+ geometry_generator_grammar<OutputIterator,geometry_type > path; | |
+ phoenix::function<detail::multi_geometry_<GeometryContainer> > is_multi; | |
+ phoenix::function<detail::multi_geometry_type<geometry_type>> multi_type_; | |
+ phoenix::function<detail::get_type<geometry_type>> type_; | |
+ phoenix::function<detail::not_empty<geometry_type>> not_empty_; | |
karma::symbols<unsigned, char const*> geometry_types; | |
}; | |
diff --git a/include/mapnik/json/geometry_generator_grammar_impl.hpp b/include/mapnik/json/geometry_generator_grammar_impl.hpp | |
index 61be1b9..ceb8860 100644 | |
--- a/include/mapnik/json/geometry_generator_grammar_impl.hpp | |
+++ b/include/mapnik/json/geometry_generator_grammar_impl.hpp | |
@@ -32,11 +32,34 @@ | |
namespace mapnik { namespace json { | |
+template <typename T> | |
+std::tuple<unsigned,bool> detail::multi_geometry_type<T>::operator() (T const& geom) const | |
+{ | |
+ using geometry_container = T; | |
+ unsigned type = 0u; | |
+ bool collection = false; | |
+ | |
+ typename geometry_container::const_iterator itr = geom.begin(); | |
+ typename geometry_container::const_iterator end = geom.end(); | |
+ | |
+ for ( ; itr != end; ++itr) | |
+ { | |
+ if (type != 0 && itr->type() != type) | |
+ { | |
+ collection = true; | |
+ break; | |
+ } | |
+ type = itr->type(); | |
+ } | |
+ return std::tuple<unsigned,bool>(type, collection); | |
+} | |
+ | |
+ | |
namespace karma = boost::spirit::karma; | |
-template <typename OutputIterator> | |
-geometry_generator_grammar<OutputIterator>::geometry_generator_grammar() | |
- : geometry_generator_grammar::base_type(coordinates) | |
+template <typename OutputIterator, typename Geometry> | |
+geometry_generator_grammar<OutputIterator,Geometry>::geometry_generator_grammar() | |
+ : geometry_generator_grammar::base_type(json) | |
{ | |
boost::spirit::karma::uint_type uint_; | |
boost::spirit::bool_type bool_; | |
@@ -44,11 +67,13 @@ geometry_generator_grammar<OutputIterator>::geometry_generator_grammar() | |
boost::spirit::karma::_1_type _1; | |
boost::spirit::karma::lit_type lit; | |
boost::spirit::karma::_a_type _a; | |
+ boost::spirit::karma::_b_type _b; | |
+ boost::spirit::karma::_c_type _c; | |
boost::spirit::karma::_r1_type _r1; | |
boost::spirit::karma::eps_type eps; | |
boost::spirit::karma::string_type kstring; | |
- coordinates = point | linestring | polygon | |
+ json = point | linestring | polygon | |
; | |
point = &uint_(mapnik::geometry_type::types::Point)[_1 = _type(_val)] | |
@@ -69,28 +94,33 @@ geometry_generator_grammar<OutputIterator>::geometry_generator_grammar() | |
point_coord = &uint_ | |
<< lit('[') | |
- << coord_type << lit(',') << coord_type | |
+ << coordinate << lit(',') << coordinate | |
<< lit(']') | |
; | |
- polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] | |
+ polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) | |
+ << eps[_r1 += 1][_a = _x(_val)][ _b = _y(_val)] | |
<< kstring[ if_ (_r1 > 1u) [_1 = "],["] | |
- .else_[_1 = '[' ]] | |
+ .else_[_1 = '[' ]] | |
| | |
&uint_(mapnik::SEG_LINETO) | |
- << lit(',')) << lit('[') << coord_type << lit(',') << coord_type << lit(']') | |
+ << lit(',') << eps[_a = _x(_val)][_b = _y(_val)] | |
+ ) | |
+ << coordinate[_1 = _a] | |
+ << lit(' ') | |
+ << coordinate[_1 = _b] | |
; | |
- coords2 %= *polygon_coord(_a) | |
+ coords2 %= *polygon_coord(_a,_b,_c) | |
; | |
coords = point_coord % lit(',') | |
; | |
} | |
-template <typename OutputIterator> | |
-multi_geometry_generator_grammar<OutputIterator>::multi_geometry_generator_grammar() | |
- : multi_geometry_generator_grammar::base_type(start) | |
+template <typename OutputIterator, typename GeometryContainer> | |
+multi_geometry_generator_grammar<OutputIterator,GeometryContainer>::multi_geometry_generator_grammar() | |
+ : multi_geometry_generator_grammar::base_type(json) | |
{ | |
boost::spirit::karma::uint_type uint_; | |
boost::spirit::bool_type bool_; | |
@@ -110,7 +140,7 @@ multi_geometry_generator_grammar<OutputIterator>::multi_geometry_generator_gramm | |
(mapnik::geometry_type::types::Polygon + 3,"\"MultiPolygon\"") | |
; | |
- start %= ( eps(boost::phoenix::at_c<1>(_a))[_a = multi_type_(_val)] | |
+ json %= ( eps(boost::phoenix::at_c<1>(_a))[_a = multi_type_(_val)] | |
<< lit("{\"type\":\"GeometryCollection\",\"geometries\":[") | |
<< geometry_collection << lit("]}") | |
| | |
diff --git a/include/mapnik/util/geometry_to_geojson.hpp b/include/mapnik/util/geometry_to_geojson.hpp | |
index cbdce3d..b661d5c 100644 | |
--- a/include/mapnik/util/geometry_to_geojson.hpp | |
+++ b/include/mapnik/util/geometry_to_geojson.hpp | |
@@ -32,7 +32,7 @@ namespace mapnik { namespace util { | |
inline bool to_geojson(std::string & json, mapnik::geometry_type const& geom) | |
{ | |
using sink_type = std::back_insert_iterator<std::string>; | |
- static const mapnik::json::geometry_generator_grammar<sink_type> grammar; | |
+ static const mapnik::json::geometry_generator_grammar<sink_type,mapnik::geometry_type> grammar; | |
sink_type sink(json); | |
return boost::spirit::karma::generate(sink, grammar, geom); | |
} | |
@@ -40,7 +40,7 @@ inline bool to_geojson(std::string & json, mapnik::geometry_type const& geom) | |
inline bool to_geojson(std::string & json, mapnik::geometry_container const& geom) | |
{ | |
using sink_type = std::back_insert_iterator<std::string>; | |
- static const mapnik::json::multi_geometry_generator_grammar<sink_type> grammar; | |
+ static const mapnik::json::multi_geometry_generator_grammar<sink_type,mapnik::geometry_container> grammar; | |
sink_type sink(json); | |
return boost::spirit::karma::generate(sink, grammar, geom); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment