adapt mapnik::geometry::geometry<double> to work with boost::spirit::karma + simplify and optimise WKT generator

This commit is contained in:
artemp 2016-09-19 15:51:21 +02:00 committed by Mickey Rose
parent bdaef2cc91
commit 9853353353
5 changed files with 155 additions and 102 deletions

View file

@ -24,29 +24,13 @@
#define MAPNIK_GEOMETRY_TO_WKT_HPP #define MAPNIK_GEOMETRY_TO_WKT_HPP
// mapnik // mapnik
#include <mapnik/wkt/wkt_factory.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_generator_grammar.hpp> // stl
#include <string>
// boost
#include <boost/spirit/include/karma.hpp>
namespace mapnik { namespace util { namespace mapnik { namespace util {
inline bool to_wkt(std::string & wkt, mapnik::geometry::geometry<double> const& geom) bool to_wkt(std::string & wkt, mapnik::geometry::geometry<double> const& geom);
{
using sink_type = std::back_insert_iterator<std::string>;
static const mapnik::wkt::wkt_generator_grammar<sink_type, mapnik::geometry::geometry<double>> generator;
sink_type sink(wkt);
return boost::spirit::karma::generate(sink, generator, geom);
}
inline bool to_wkt(std::string & wkt, mapnik::geometry::geometry<std::int64_t> const& geom)
{
using sink_type = std::back_insert_iterator<std::string>;
static const mapnik::wkt::wkt_generator_grammar<sink_type, mapnik::geometry::geometry<std::int64_t>> generator;
sink_type sink(wkt);
return boost::spirit::karma::generate(sink, generator, geom);
}
}} }}

View file

@ -25,8 +25,8 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/geometry/geometry_type.hpp>
#pragma GCC diagnostic push #pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp> #include <mapnik/warning_ignore.hpp>
@ -43,18 +43,6 @@ namespace phoenix = boost::phoenix;
namespace detail { namespace detail {
template <typename Geometry>
struct get_type
{
using result_type = mapnik::geometry::geometry_types;
template <typename T>
result_type operator() (T const& geom) const
{
auto type = mapnik::geometry::geometry_type(geom);
return type;
}
};
template <typename T> template <typename T>
struct wkt_coordinate_policy : karma::real_policies<T> struct wkt_coordinate_policy : karma::real_policies<T>
{ {
@ -102,31 +90,29 @@ struct coordinate_generator<std::int64_t>
template <typename OutputIterator, typename Geometry> template <typename OutputIterator, typename Geometry>
struct wkt_generator_grammar : struct wkt_generator_grammar :
karma::grammar<OutputIterator, Geometry const& ()> karma::grammar<OutputIterator, Geometry()>
{ {
using coord_type = typename Geometry::coord_type; using coord_type = typename Geometry::coord_type;
wkt_generator_grammar(); wkt_generator_grammar();
// rules // rules
karma::rule<OutputIterator, Geometry const&()> geometry; karma::rule<OutputIterator, Geometry()> geometry;
karma::rule<OutputIterator, karma::locals<mapnik::geometry::geometry_types>, Geometry const&() > geometry_dispatch; karma::rule<OutputIterator, geometry::geometry_empty()> empty;
karma::rule<OutputIterator, geometry::geometry<coord_type> const&()> point; karma::rule<OutputIterator, geometry::point<coord_type>()> point;
karma::rule<OutputIterator, geometry::point<coord_type> const&()> point_coord; karma::rule<OutputIterator, geometry::point<coord_type>()> point_coord;
karma::rule<OutputIterator, geometry::geometry<coord_type> const&()> linestring; karma::rule<OutputIterator, geometry::line_string<coord_type>()> linestring;
karma::rule<OutputIterator, geometry::line_string<coord_type> const&()> linestring_coord; karma::rule<OutputIterator, geometry::line_string<coord_type>()> linestring_coord;
karma::rule<OutputIterator, geometry::geometry<coord_type> const&()> polygon; karma::rule<OutputIterator, geometry::polygon<coord_type>()> polygon;
karma::rule<OutputIterator, geometry::polygon<coord_type> const&()> polygon_coord; karma::rule<OutputIterator, geometry::polygon<coord_type>()> polygon_coord;
karma::rule<OutputIterator, geometry::linear_ring<coord_type> const&()> exterior_ring_coord; karma::rule<OutputIterator, geometry::linear_ring<coord_type>()> exterior_ring_coord;
karma::rule<OutputIterator, std::vector<geometry::linear_ring<coord_type> > const&()> interior_ring_coord; karma::rule<OutputIterator, std::vector<geometry::linear_ring<coord_type> >()> interior_ring_coord;
karma::rule<OutputIterator, geometry::geometry<coord_type> const& ()> multi_point; karma::rule<OutputIterator, geometry::multi_point<coord_type>()> multi_point;
karma::rule<OutputIterator, geometry::multi_point<coord_type> const& ()> multi_point_coord; karma::rule<OutputIterator, geometry::multi_point<coord_type>()> multi_point_coord;
karma::rule<OutputIterator, geometry::geometry<coord_type> const& ()> multi_linestring; karma::rule<OutputIterator, geometry::multi_line_string<coord_type>()> multi_linestring;
karma::rule<OutputIterator, geometry::multi_line_string<coord_type> const& ()> multi_linestring_coord; karma::rule<OutputIterator, geometry::multi_line_string<coord_type>()> multi_linestring_coord;
karma::rule<OutputIterator, geometry::geometry<coord_type> const& ()> multi_polygon; karma::rule<OutputIterator, geometry::multi_polygon<coord_type>()> multi_polygon;
karma::rule<OutputIterator, geometry::multi_polygon<coord_type> const& ()> multi_polygon_coord; karma::rule<OutputIterator, geometry::multi_polygon<coord_type>()> multi_polygon_coord;
karma::rule<OutputIterator, geometry::geometry<coord_type> const& ()> geometry_collection; karma::rule<OutputIterator, geometry::geometry_collection<coord_type>()> geometry_collection;
karma::rule<OutputIterator, geometry::geometry_collection<coord_type> const& ()> geometries; karma::rule<OutputIterator, geometry::geometry_collection<coord_type>()> geometries;
boost::phoenix::function<detail::get_type<Geometry> > geometry_type;
karma::symbols<mapnik::geometry::geometry_types, char const*> empty;
// //
typename detail::coordinate_generator<coord_type>::generator coordinate; typename detail::coordinate_generator<coord_type>::generator coordinate;
}; };

View file

@ -22,9 +22,7 @@
// mapnik // mapnik
#include <mapnik/wkt/wkt_generator_grammar.hpp> #include <mapnik/wkt/wkt_generator_grammar.hpp>
#include <mapnik/util/spirit_transform_attribute.hpp>
#include <mapnik/geometry/fusion_adapted.hpp> #include <mapnik/geometry/fusion_adapted.hpp>
#pragma GCC diagnostic push #pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp> #include <mapnik/warning_ignore.hpp>
#include <boost/spirit/include/phoenix.hpp> #include <boost/spirit/include/phoenix.hpp>
@ -36,53 +34,26 @@ template <typename OutputIterator, typename Geometry>
wkt_generator_grammar<OutputIterator, Geometry>::wkt_generator_grammar() wkt_generator_grammar<OutputIterator, Geometry>::wkt_generator_grammar()
: wkt_generator_grammar::base_type(geometry) : wkt_generator_grammar::base_type(geometry)
{ {
boost::spirit::karma::_val_type _val;
boost::spirit::karma::_1_type _1;
boost::spirit::karma::_a_type _a;
boost::spirit::karma::lit_type lit; boost::spirit::karma::lit_type lit;
boost::spirit::karma::uint_type uint_; geometry =
boost::spirit::karma::eps_type eps; point
|
empty.add linestring
(geometry::geometry_types::Point, "POINT EMPTY") |
(geometry::geometry_types::LineString, "LINESTRING EMPTY") polygon
(geometry::geometry_types::Polygon, "POLYGON EMPTY") |
(geometry::geometry_types::MultiPoint, "MULTIPOINT EMPTY") multi_point
(geometry::geometry_types::MultiLineString, "MULTILINESTRING EMPTY") |
(geometry::geometry_types::MultiPolygon, "MULTIPOLYGON EMPTY") multi_linestring
(geometry::geometry_types::GeometryCollection, "GEOMETRYCOLLECTION EMPTY") |
multi_polygon
|
geometry_collection
|
lit("POINT EMPTY") // special case for geometry_empty
; ;
geometry = geometry_dispatch.alias() point = lit("POINT(") << coordinate << lit(' ') << coordinate << lit(")")
;
geometry_dispatch = eps[_a = geometry_type(_val)] <<
(&uint_(geometry::geometry_types::Point)[_1 = _a]
<< point)
|
(&uint_(geometry::geometry_types::LineString)[_1 = _a]
<< (linestring | empty[_1 = _a]))
|
(&uint_(geometry::geometry_types::Polygon)[_1 = _a]
<< (polygon | empty[_1 = _a]))
|
(&uint_(geometry::geometry_types::MultiPoint)[_1 = _a]
<< ( multi_point | empty[_1 = _a]))
|
(&uint_(geometry::geometry_types::MultiLineString)[_1 = _a]
<< (multi_linestring | empty[_1 = _a]))
|
(&uint_(geometry::geometry_types::MultiPolygon)[_1 = _a]
<< (multi_polygon | empty[_1 = _a]))
|
(&uint_(geometry::geometry_types::GeometryCollection)[_1 = _a]
<< (geometry_collection | empty[_1 = _a]))
|
(&uint_(geometry::geometry_types::Unknown)[_1 = _a]
<< lit("POINT EMPTY")) // special case for geometry_empty as mapnik::geometry::point<double> can't be empty
;
point = lit("POINT(") << point_coord << lit(")")
; ;
linestring = lit("LINESTRING(") << linestring_coord << lit(")") linestring = lit("LINESTRING(") << linestring_coord << lit(")")
; ;
@ -112,7 +83,7 @@ wkt_generator_grammar<OutputIterator, Geometry>::wkt_generator_grammar()
; ;
multi_polygon_coord = (lit('(') << polygon_coord << lit(')')) % lit(',') multi_polygon_coord = (lit('(') << polygon_coord << lit(')')) % lit(',')
; ;
geometries = geometry % lit(',') geometries = geometry % lit(',')
; ;
} }

View file

@ -0,0 +1,48 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2016 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// mapnik
#include <mapnik/util/geometry_to_wkt.hpp>
#include <mapnik/wkt/wkt_generator_grammar.hpp>
// boost
#include <boost/spirit/include/karma.hpp>
namespace mapnik { namespace util {
bool to_wkt(std::string & wkt, mapnik::geometry::geometry<double> const& geom)
{
using sink_type = std::back_insert_iterator<std::string>;
static const mapnik::wkt::wkt_generator_grammar<sink_type, mapnik::geometry::geometry<double>> generator;
sink_type sink(wkt);
return boost::spirit::karma::generate(sink, generator, geom);
}
/*
inline bool to_wkt(std::string & wkt, mapnik::geometry::geometry<std::int64_t> const& geom)
{
using sink_type = std::back_insert_iterator<std::string>;
static const mapnik::wkt::wkt_generator_grammar<sink_type, mapnik::geometry::geometry<std::int64_t>> generator;
sink_type sink(wkt);
return boost::spirit::karma::generate(sink, generator, geom);
}
*/
}}

View file

@ -21,9 +21,73 @@
*****************************************************************************/ *****************************************************************************/
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_generator_grammar_impl.hpp>
#include <string> #include <string>
namespace boost { using mapbox::util::get; }
#include <mapnik/wkt/wkt_generator_grammar_impl.hpp>
namespace boost { namespace spirit { namespace traits
{
template <>
struct not_is_variant<mapnik::geometry::geometry<double>, karma::domain>
: mpl::false_
{};
template <>
struct variant_which< mapnik::geometry::geometry<double> >
{
static int call(mapnik::geometry::geometry<double> const& v)
{
return v.which();
}
};
namespace detail {
template <typename T, typename Tuple>
struct has_type;
template <typename T>
struct has_type<T, std::tuple<>> : std::false_type {};
template <typename T, typename U, typename... Types>
struct has_type<T, std::tuple<U, Types...>> : has_type<T, std::tuple<Types...>> {};
template <typename T, typename... Types>
struct has_type<T, std::tuple<T, Types...>> : std::true_type {};
template <typename T, typename Tuple>
struct index;
template <typename T, typename... Types>
struct index<T, std::tuple<T, Types...>>
{
static const std::size_t value = 0;
};
template <typename T, typename U, typename... Types>
struct index<T, std::tuple<U, Types...>>
{
static const std::size_t value = 1 + index<T, std::tuple<Types...>>::value;
};
}
template <typename Expected>
struct compute_compatible_component_variant<mapnik::geometry::geometry<double>, Expected>
: detail::has_type<Expected, mapnik::geometry::geometry<double>::types>
{
using compatible_type = Expected;
static bool is_compatible(int index)
{
return (index == detail::index<compatible_type, mapnik::geometry::geometry<double>::types>::value);
}
};
}}}
namespace mapnik { namespace wkt { namespace mapnik { namespace wkt {
using sink_type = std::back_insert_iterator<std::string>; using sink_type = std::back_insert_iterator<std::string>;