diff --git a/include/mapnik/wkt/wkt_factory.hpp b/include/mapnik/wkt/wkt_factory.hpp index 14f509dda..722fc18d6 100644 --- a/include/mapnik/wkt/wkt_factory.hpp +++ b/include/mapnik/wkt/wkt_factory.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * 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 @@ -25,24 +25,12 @@ // mapnik #include - -#include -#include - // stl #include namespace mapnik { -inline bool from_wkt(std::string const& wkt, mapnik::geometry::geometry & geom) -{ - using namespace boost::spirit; - static const mapnik::wkt::wkt_grammar g; - ascii::space_type space; - std::string::const_iterator first = wkt.begin(); - std::string::const_iterator last = wkt.end(); - return qi::phrase_parse(first, last, (g)(boost::phoenix::ref(geom)), space); -} +bool from_wkt(std::string const& wkt, mapnik::geometry::geometry & geom); } diff --git a/include/mapnik/wkt/wkt_grammar.hpp b/include/mapnik/wkt/wkt_grammar.hpp deleted file mode 100644 index 2040b86fa..000000000 --- a/include/mapnik/wkt/wkt_grammar.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 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 - * - *****************************************************************************/ - -#ifndef MAPNIK_WKT_GRAMMAR_HPP -#define MAPNIK_WKT_GRAMMAR_HPP - -// mapnik -#include -#include -#pragma GCC diagnostic push -#include -#include -#include -#pragma GCC diagnostic pop - - -namespace mapnik { namespace wkt { - -using namespace boost::spirit; - -namespace detail { - -struct assign -{ - using result_type = void; - template - void operator() (T0 & geom, T1 && obj) const - { - geom = std::move(obj); - } -}; - -struct move_part -{ - using result_type = void; - template - void operator() (Geometry & geom, Part && part) const - { - geom.push_back(std::move(part)); - } -}; - -struct set_exterior -{ - using result_type = void; - template - void operator() (Polygon & poly, Ring && ring) const - { - poly.set_exterior_ring(std::move(ring)); - } -}; - -struct add_hole -{ - using result_type = void; - template - void operator() (Polygon & poly, Ring && ring) const - { - poly.add_hole(std::move(ring)); - } -}; - -} - -template -struct wkt_grammar : qi::grammar &) , ascii::space_type> -{ - wkt_grammar(); - qi::rule &), ascii::space_type> geometry_tagged_text; - qi::rule &), ascii::space_type> point_tagged_text; - qi::rule &), ascii::space_type> linestring_tagged_text; - qi::rule &), ascii::space_type> polygon_tagged_text; - qi::rule &), ascii::space_type> multipoint_tagged_text; - qi::rule &), ascii::space_type> multilinestring_tagged_text; - qi::rule &), ascii::space_type> multipolygon_tagged_text; - qi::rule &), ascii::space_type> geometrycollection_tagged_text; - qi::rule(), ascii::space_type> point_text; - qi::rule(), ascii::space_type> linestring_text; - qi::rule(), ascii::space_type> linearring_text; - qi::rule(), ascii::space_type> polygon_text; - qi::rule(), ascii::space_type> multipoint_text; - qi::rule(), ascii::space_type> multilinestring_text; - qi::rule(), ascii::space_type> multipolygon_text; - qi::rule >, - mapnik::geometry::geometry_collection(), ascii::space_type> geometrycollection_text; - qi::rule(), ascii::space_type> point; - qi::rule(), ascii::space_type> points; - qi::rule(), ascii::space_type> ring_points; - qi::rule empty_set; - boost::phoenix::function assign; - boost::phoenix::function move_part; - boost::phoenix::function set_exterior; - boost::phoenix::function add_hole; -}; - -}} - -#endif // MAPNIK_WKT_GRAMMAR_HPP diff --git a/include/mapnik/wkt/wkt_grammar_impl.hpp b/include/mapnik/wkt/wkt_grammar_impl.hpp deleted file mode 100644 index 05c60b578..000000000 --- a/include/mapnik/wkt/wkt_grammar_impl.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2015 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 - * - *****************************************************************************/ - -#include -#include - -#pragma GCC diagnostic push -#include -#include -#include -#pragma GCC diagnostic pop - -namespace mapnik { namespace wkt { - -using namespace boost::spirit; - -template -wkt_grammar::wkt_grammar() - : wkt_grammar::base_type(geometry_tagged_text) -{ - qi::eps_type eps; - qi::_r1_type _r1; - qi::_val_type _val; - qi::lit_type lit; - qi::no_case_type no_case; - qi::double_type double_; - qi::_1_type _1; - qi::_a_type _a; - using boost::phoenix::construct; - geometry_tagged_text = point_tagged_text(_r1) - | linestring_tagged_text(_r1) - | polygon_tagged_text(_r1) - | multipoint_tagged_text(_r1) - | multilinestring_tagged_text(_r1) - | multipolygon_tagged_text(_r1) - | geometrycollection_tagged_text(_r1) - ; - - // ::= point - point_tagged_text = no_case[lit("POINT")] - >> (point_text[assign(_r1,_1)] | empty_set[assign(_r1,construct())]) - ; - // ::= | - point_text = (lit("(") >> point >> lit(')')) - //| empty_set - we're catching 'POINT EMPTY' case in point_tagged_text rule ^^ by creating geometry_empty - // because our geometry::point can't be empty - ; - - // ::= linestring - linestring_tagged_text = no_case[lit("LINESTRING")] - >> linestring_text[assign(_r1,_1)] - ; - - // ::= | { }* - linestring_text = points | empty_set - ; - - // ::= polygon - polygon_tagged_text = no_case[lit("POLYGON")] - >> polygon_text[assign(_r1,_1)] - ; - - // ::= | { }* - polygon_text = - (lit('(') >> linearring_text[set_exterior(_val,_1)] >> *(lit(',') >> linearring_text[add_hole(_val,_1)]) >> lit(')')) - | - empty_set - ; - - linearring_text = ring_points | empty_set - ; - // ::= multipoint - multipoint_tagged_text = no_case[lit("MULTIPOINT")] - >> multipoint_text[assign(_r1,_1)] - ; - - // ::= | { }* - multipoint_text = (lit('(') - >> point_text % lit(',') - >> lit(')')) - | - (lit('(') - >> point % lit(',') - >> lit(')')) - | - empty_set - ; - - // ::= multilinestring - multilinestring_tagged_text = no_case[lit("MULTILINESTRING")] - >> multilinestring_text[assign(_r1,_1)] ; - - // ::= | { }* - multilinestring_text = (lit('(') - >> points[move_part(_val,_1)] % lit(',') - >> lit(')')) | empty_set; - - // ::= multipolygon - multipolygon_tagged_text = no_case[lit("MULTIPOLYGON")] - >> multipolygon_text[assign(_r1,_1)] ; - - // ::= | { }* - multipolygon_text = (lit('(') - >> polygon_text[move_part(_val,_1)] % lit(',') - >> lit(')')) - | - empty_set; - - // geometry collection tagged text - geometrycollection_tagged_text = no_case[lit("GEOMETRYCOLLECTION")] - >> geometrycollection_text[assign(_r1,_1)] - ; - - // geometry collection text - geometrycollection_text = (lit('(') - >> ( eps[_a = construct >()] - >> geometry_tagged_text(_a)[move_part(_val,_a)] % lit(',')) - >> lit(')')) - | - empty_set; - // points - points = lit('(') >> point % lit(',') >> lit(')') - ; - // ring points - ring_points = lit('(') >> point % lit(',') >> lit(')') - ; - // point - point = double_ >> double_ - ; - - // - empty_set = no_case[lit("EMPTY")]; -} - -}} diff --git a/include/mapnik/wkt/wkt_grammar_x3.hpp b/include/mapnik/wkt/wkt_grammar_x3.hpp new file mode 100644 index 000000000..3fd969848 --- /dev/null +++ b/include/mapnik/wkt/wkt_grammar_x3.hpp @@ -0,0 +1,49 @@ +/***************************************************************************** + * + * 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 + * + *****************************************************************************/ + +#ifndef MAPNIK_WKT_GRAMMAR_X3_HPP +#define MAPNIK_WKT_GRAMMAR_X3_HPP + +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + +#include + +namespace mapnik { namespace grammar { + +namespace x3 = boost::spirit::x3; +struct wkt_class; // top-most ID +using wkt_grammar_type = x3::rule>; + +BOOST_SPIRIT_DECLARE(wkt_grammar_type); + +}} + +namespace mapnik +{ +grammar::wkt_grammar_type wkt_grammar(); +} + + +#endif // MAPNIK_WKT_GRAMMAR_X3_HPP diff --git a/include/mapnik/wkt/wkt_grammar_x3_def.hpp b/include/mapnik/wkt/wkt_grammar_x3_def.hpp new file mode 100644 index 000000000..62fdb1ac0 --- /dev/null +++ b/include/mapnik/wkt/wkt_grammar_x3_def.hpp @@ -0,0 +1,130 @@ +/***************************************************************************** + * + * 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 + * + *****************************************************************************/ + +#ifndef MAPNIK_WKT_GRAMMAR_X3_DEF_HPP +#define MAPNIK_WKT_GRAMMAR_X3_DEF_HPP + +#include +#include + +namespace mapnik { namespace grammar { + +namespace x3 = boost::spirit::x3; +namespace ascii = boost::spirit::x3::ascii; +using x3::lit; +using x3::double_; +using x3::no_case; + +// functors +auto make_empty = [](auto const& ctx) +{ + _val(ctx) = geometry::geometry_empty(); +}; + +auto set_exterior = [](auto const& ctx) +{ + _val(ctx).set_exterior_ring(std::move(_attr(ctx))); +}; + +auto add_hole = [](auto const& ctx) +{ + _val(ctx).add_hole(std::move(_attr(ctx))); +}; + +// start rule +wkt_grammar_type const wkt("wkt"); +// rules +x3::rule const empty("EMPTY"); +x3::rule > const point("POINT"); +x3::rule > const line_string("LINESTRING"); +x3::rule > const polygon("POLYGON"); +x3::rule > const multi_point("MULTIPOINT"); +x3::rule > const multi_line_string("MULTILINESTRING"); +x3::rule > const multi_polygon("MULTIPOLYGON"); +x3::rule > const geometry_collection("GEOMETRYCOLLECTION"); + +x3::rule > const point_text("point-text"); +x3::rule > const positions("positions"); +x3::rule > const polygon_rings("polygon-rings"); +x3::rule > const points("points"); +x3::rule > const lines("lines"); +x3::rule > const polygons("polygons"); +x3::rule > const geometries("geometries"); + + +auto const point_text_def = '(' > double_ > double_ > ')'; +auto const positions_def = lit('(') > (double_ > double_) % lit(',') > lit(')'); +auto const polygon_rings_def = '(' > positions[set_exterior] > *(lit(',') > positions[add_hole]) > ')'; +auto const points_def = (lit('(') >> ((point_text_def % ',') > lit(')'))) | positions_def ; +auto const lines_def = lit('(') > (positions_def % lit(',')) > lit(')'); +auto const polygons_def = lit('(') > (polygon_rings % lit(',')) > lit(')'); +auto const geometries_def = lit('(') > -(wkt % ',') > lit(')'); + +// +auto const wkt_def = point | line_string | polygon | multi_point | multi_line_string | multi_polygon | geometry_collection; + +// EMPTY +auto const empty_def = no_case["EMPTY"][make_empty]; +// POINT +auto const point_def = no_case["POINT"] > (point_text | empty); +// LINESTRING +auto const line_string_def = no_case["LINESTRING"] > (positions | no_case["EMPTY"]); +// POLYGON +auto const polygon_def = no_case["POLYGON"] > (polygon_rings | no_case["EMPTY"]); +// MULTIPOINT +auto const multi_point_def = no_case["MULTIPOINT"] > (points | no_case["EMPTY"]); +// MULTILINESTRING +auto const multi_line_string_def = no_case["MULTILINESTRING"] > (lines | no_case["EMPTY"]); +// MULTIPOLYGON +auto const multi_polygon_def = no_case["MULTIPOLYGON"] > (polygons | no_case["EMPTY"]); +// GEOMETRYCOLLECTION +auto const geometry_collection_def = no_case["GEOMETRYCOLLECTION"] > (geometries | no_case["EMPTY"]); + +BOOST_SPIRIT_DEFINE( + wkt, + point_text, + positions, + points, + lines, + polygons, + geometries, + empty, + point, + line_string, + polygon_rings, + polygon, + multi_point, + multi_line_string, + multi_polygon, + geometry_collection + ); +}} + +namespace mapnik +{ +grammar::wkt_grammar_type wkt_grammar() +{ + return grammar::wkt; +} +} + +#endif // MAPNIK_WKT_GRAMMAR_X3_DEF_HPP diff --git a/src/wkt/mapnik_wkt_grammar.cpp b/src/wkt/wkt_grammar_x3.cpp similarity index 77% rename from src/wkt/mapnik_wkt_grammar.cpp rename to src/wkt/wkt_grammar_x3.cpp index aea52a917..eeb602e7d 100644 --- a/src/wkt/mapnik_wkt_grammar.cpp +++ b/src/wkt/wkt_grammar_x3.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2015 Artem Pavlenko + * 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 @@ -20,12 +20,13 @@ * *****************************************************************************/ -#include -#include +#include -namespace mapnik { namespace wkt { +namespace mapnik { namespace grammar { +namespace x3 = boost::spirit::x3; using iterator_type = std::string::const_iterator; -template struct wkt_grammar; +using context_type = x3::phrase_parse_context::type; +BOOST_SPIRIT_INSTANTIATE(wkt_grammar_type, iterator_type, context_type); }}