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
// mapnik
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkt/wkt_generator_grammar.hpp>
// boost
#include <boost/spirit/include/karma.hpp>
#include <mapnik/geometry.hpp>
// stl
#include <string>
namespace mapnik { namespace util {
inline 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);
}
bool to_wkt(std::string & wkt, mapnik::geometry::geometry<double> const& geom);
}}

View file

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

View file

@ -22,9 +22,7 @@
// mapnik
#include <mapnik/wkt/wkt_generator_grammar.hpp>
#include <mapnik/util/spirit_transform_attribute.hpp>
#include <mapnik/geometry/fusion_adapted.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.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::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::uint_type uint_;
boost::spirit::karma::eps_type eps;
empty.add
(geometry::geometry_types::Point, "POINT EMPTY")
(geometry::geometry_types::LineString, "LINESTRING EMPTY")
(geometry::geometry_types::Polygon, "POLYGON EMPTY")
(geometry::geometry_types::MultiPoint, "MULTIPOINT EMPTY")
(geometry::geometry_types::MultiLineString, "MULTILINESTRING EMPTY")
(geometry::geometry_types::MultiPolygon, "MULTIPOLYGON EMPTY")
(geometry::geometry_types::GeometryCollection, "GEOMETRYCOLLECTION EMPTY")
geometry =
point
|
linestring
|
polygon
|
multi_point
|
multi_linestring
|
multi_polygon
|
geometry_collection
|
lit("POINT EMPTY") // special case for geometry_empty
;
geometry = geometry_dispatch.alias()
;
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(")")
point = lit("POINT(") << coordinate << lit(' ') << coordinate << lit(")")
;
linestring = lit("LINESTRING(") << linestring_coord << 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/wkt/wkt_generator_grammar_impl.hpp>
#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 {
using sink_type = std::back_insert_iterator<std::string>;