+ modify WKT parser to work with ptr_vector<geometry_type>

+ fix memory leaks in wkt_grammar
+ add support for GEOMETRYCOLLECTION
This commit is contained in:
Artem Pavlenko 2011-09-08 11:52:51 +00:00
parent 7468c95084
commit 53b50c871c
3 changed files with 118 additions and 44 deletions

View file

@ -25,10 +25,11 @@
#include <string> #include <string>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
namespace mapnik { namespace mapnik {
std::pair<bool,geometry_type*> from_wkt(std::string const& wkt); bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths);
} }

View file

@ -70,88 +70,162 @@ struct cleanup
template <typename T0> template <typename T0>
void operator() (T0 & path) const void operator() (T0 & path) const
{ {
if (path) delete path,path=0; if (path) delete path,path=0;
} }
}; };
template <typename Iterator> template <typename Iterator>
struct wkt_grammar : qi::grammar<Iterator, geometry_type*(), ascii::space_type> struct wkt_grammar : qi::grammar<Iterator, boost::ptr_vector<mapnik::geometry_type>() , ascii::space_type>
{ {
wkt_grammar() wkt_grammar()
: wkt_grammar::base_type(start) : wkt_grammar::base_type(geometry_tagged_text)
{ {
using qi::_1;
using qi::_2;
using qi::_val;
using qi::no_case; using qi::no_case;
using boost::phoenix::push_back;
start %= point | linestring | polygon | multipoint | multilinestring | multipolygon | eps[cleanup_(_val)][_pass = false]; geometry_tagged_text = point_tagged_text
| linestring_tagged_text
| polygon_tagged_text
| multipoint_tagged_text
| multilinestring_tagged_text
| multipolygon_tagged_text
;
// <point tagged text> ::= point <point text> // <point tagged text> ::= point <point text>
point = no_case[lit("POINT")] [ _val = new_<geometry_type>(Point) ] point_tagged_text = no_case[lit("POINT")] [ _a = new_<geometry_type>(Point) ]
>> (empty_set | lit('(') >> coord(SEG_MOVETO,_val) >> lit(')')); >> ( point_text(_a) [push_back(_val,_a)]
| eps[cleanup_(_a)][_pass = false])
;
// <point text> ::= <empty set> | <left paren> <point> <right paren>
point_text = (lit("(") >> point(SEG_MOVETO,_r1) >> lit(')'))
| empty_set
;
// <linestring tagged text> ::= linestring <linestring text> // <linestring tagged text> ::= linestring <linestring text>
linestring = no_case[lit("LINESTRING")] [ _val = new_<geometry_type>(LineString) ] >> (empty_set | points(_val)); linestring_tagged_text = no_case[lit("LINESTRING")] [ _a = new_<geometry_type>(LineString) ]
>> (linestring_text(_a)[push_back(_val,_a)]
| eps[cleanup_(_a)][_pass = false])
;
// <linestring text> ::= <empty set> | <left paren> <point> {<comma> <point>}* <right paren>
linestring_text = points(_r1) | empty_set
;
// <polygon tagged text> ::= polygon <polygon text> // <polygon tagged text> ::= polygon <polygon text>
polygon = no_case[lit("POLYGON")] [ _val = new_<geometry_type>(Polygon) ] >> polygon_tagged_text = no_case[lit("POLYGON")] [ _a = new_<geometry_type>(Polygon) ]
(empty_set | lit('(') >> points(_val) % lit(',') >> lit(')')); >> ( polygon_text(_a)[push_back(_val,_a)]
| eps[cleanup_(_a)][_pass = false])
;
// multi point // <polygon text> ::= <empty set> | <left paren> <linestring text> {<comma> <linestring text>}* <right paren>
multipoint = no_case[lit("MULTIPOINT")] [ _val = new_<geometry_type>(MultiPoint) ] polygon_text = (lit('(') >> linestring_text(_r1) % lit(',') >> lit(')')) | empty_set;
>> (empty_set | lit('(') >> coord(SEG_MOVETO,_val) % lit(',') >> ')');
// multi linestring
multilinestring = no_case[lit("MULTILINESTRING")] [ _val = new_<geometry_type>(MultiLineString) ]>>
(empty_set | lit('(') >> points(_val) % lit(',') >> ')');
// multi polygon //<multipoint tagged text> ::= multipoint <multipoint text>
multipolygon = no_case[lit("MULTIPOLYGON")] [ _val = new_<geometry_type>(MultiPolygon)] >> multipoint_tagged_text = no_case[lit("MULTIPOINT")]
(empty_set | lit('(') >> (lit('(') >> >> multipoint_text
points(_val) % ',' >> ')') % ',' >> ')'); ;
// <multipoint text> ::= <empty set> | <left paren> <point text> {<comma> <point text>}* <right paren>
multipoint_text = (lit('(')
>> ((eps[_a = new_<geometry_type>(Point)]
>> (point_text(_a) | empty_set) [push_back(_val,_a)]
| eps[cleanup_(_a)][_pass = false]) % lit(','))
>> lit(')')) | empty_set
;
// <multilinestring tagged text> ::= multilinestring <multilinestring text>
multilinestring_tagged_text = no_case[lit("MULTILINESTRING")]
>> multilinestring_text ;
// <multilinestring text> ::= <empty set> | <left paren> <linestring text> {<comma> <linestring text>}* <right paren>
multilinestring_text = (lit('(')
>> ((eps[_a = new_<geometry_type>(LineString)]
>> ( points(_a)[push_back(_val,_a)]
| eps[cleanup_(_a)][_pass = false]))
% lit(','))
>> lit(')')) | empty_set;
// <multipolygon tagged text> ::= multipolygon <multipolygon text>
multipolygon_tagged_text = no_case[lit("MULTIPOLYGON")]
>> multipolygon_text ;
// <multipolygon text> ::= <empty set> | <left paren> <polygon text> {<comma> <polygon text>}* <right paren>
multipolygon_text = (lit('(')
>> ((eps[_a = new_<geometry_type>(Polygon)]
>> ( polygon_text(_a)[push_back(_val,_a)]
| eps[cleanup_(_a)][_pass = false]))
% lit(','))
>> lit(')')) | empty_set;
// points // points
points = lit('(')[_a = SEG_MOVETO] >> coord (_a,_r1) % lit(',') [_a = SEG_LINETO] >> ')'; points = lit('(')[_a = SEG_MOVETO] >> point (_a,_r1) % lit(',') [_a = SEG_LINETO] >> lit(')');
coord = (double_ >> double_) [push_vertex_(_r1,_r2,_1,_2)]; // point
point = (double_ >> double_) [push_vertex_(_r1,_r2,_1,_2)];
// <empty set> // <empty set>
empty_set = no_case[lit("EMPTY")]; empty_set = no_case[lit("EMPTY")];
} }
// start
qi::rule<Iterator,boost::ptr_vector<geometry_type>(),ascii::space_type> geometry_tagged_text;
qi::rule<Iterator,geometry_type*(),ascii::space_type> start; qi::rule<Iterator,qi::locals<geometry_type*>,boost::ptr_vector<geometry_type>(),ascii::space_type> point_tagged_text;
qi::rule<Iterator,geometry_type*(),ascii::space_type> point; qi::rule<Iterator,qi::locals<geometry_type*>,boost::ptr_vector<geometry_type>(),ascii::space_type> linestring_tagged_text;
qi::rule<Iterator,geometry_type*(),ascii::space_type> multipoint; qi::rule<Iterator,qi::locals<geometry_type*>,boost::ptr_vector<geometry_type>(),ascii::space_type> polygon_tagged_text;
qi::rule<Iterator,geometry_type*(),ascii::space_type> linestring; qi::rule<Iterator,boost::ptr_vector<geometry_type>(),ascii::space_type> multipoint_tagged_text;
qi::rule<Iterator,geometry_type*(),ascii::space_type> multilinestring; qi::rule<Iterator,boost::ptr_vector<geometry_type>(),ascii::space_type> multilinestring_tagged_text;
qi::rule<Iterator,geometry_type*(),ascii::space_type> polygon; qi::rule<Iterator,boost::ptr_vector<geometry_type>(),ascii::space_type> multipolygon_tagged_text;
qi::rule<Iterator,geometry_type*(),ascii::space_type> multipolygon; //
qi::rule<Iterator,void(CommandType,geometry_type*),ascii::space_type> coord; qi::rule<Iterator,void(geometry_type*),ascii::space_type> point_text;
qi::rule<Iterator,void(geometry_type*),ascii::space_type> linestring_text;
qi::rule<Iterator,void(geometry_type*),ascii::space_type> polygon_text;
qi::rule<Iterator, qi::locals<geometry_type*>, boost::ptr_vector<geometry_type>(),ascii::space_type> multipoint_text;
qi::rule<Iterator, qi::locals<geometry_type*>, boost::ptr_vector<geometry_type>(),ascii::space_type> multilinestring_text;
qi::rule<Iterator, qi::locals<geometry_type*>, boost::ptr_vector<geometry_type>(),ascii::space_type> multipolygon_text;
//
qi::rule<Iterator,void(CommandType,geometry_type*),ascii::space_type> point;
qi::rule<Iterator,qi::locals<CommandType>,void(geometry_type*),ascii::space_type> points; qi::rule<Iterator,qi::locals<CommandType>,void(geometry_type*),ascii::space_type> points;
qi::rule<Iterator,ascii::space_type> empty_set; qi::rule<Iterator,ascii::space_type> empty_set;
boost::phoenix::function<push_vertex> push_vertex_; boost::phoenix::function<push_vertex> push_vertex_;
boost::phoenix::function<cleanup> cleanup_; boost::phoenix::function<cleanup> cleanup_;
}; };
template <typename Iterator> template <typename Iterator>
struct wkt_collection_grammar : qi::grammar<Iterator, boost::ptr_vector<geometry_type>(), ascii::space_type> struct wkt_collection_grammar : qi::grammar<Iterator, boost::ptr_vector<mapnik::geometry_type>(), ascii::space_type>
{ {
wkt_collection_grammar() wkt_collection_grammar()
: wkt_collection_grammar::base_type(start) : wkt_collection_grammar::base_type(start)
{ {
using qi::_1; using qi::_1;
using qi::_val; using qi::_val;
using qi::no_case; using qi::no_case;
using boost::phoenix::push_back; using boost::phoenix::push_back;
start = wkt [push_back(_val,_1)] | no_case[lit("GEOMETRYCOLLECTION")] start = wkt | no_case[lit("GEOMETRYCOLLECTION")]
>> (lit("(") >> *wkt[push_back(_val,_1)] % lit(",") >> lit(")")); >> (lit("(") >> wkt % lit(",") >> lit(")"));
} }
qi::rule<Iterator,boost::ptr_vector<geometry_type>(),ascii::space_type> start; qi::rule<Iterator,boost::ptr_vector<mapnik::geometry_type>(),ascii::space_type> start;
wkt_grammar<Iterator> wkt; wkt_grammar<Iterator> wkt;
}; };
template <typename Iterator>
struct wkt_stream_grammar : qi::grammar<Iterator, boost::ptr_vector<mapnik::geometry_type>(), ascii::space_type>
{
wkt_stream_grammar()
: wkt_stream_grammar::base_type(start)
{
start = *wkt_collection;
}
qi::rule<Iterator,boost::ptr_vector<mapnik::geometry_type>(),ascii::space_type> start;
wkt_collection_grammar<Iterator> wkt_collection;
};
}} }}
#endif // MAPNIK_WKT_GRAMMAR_HPP #endif // MAPNIK_WKT_GRAMMAR_HPP

View file

@ -20,24 +20,23 @@
* *
*****************************************************************************/ *****************************************************************************/
// mapnik
#include <mapnik/wkt/wkt_factory.hpp> #include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkt/wkt_grammar.hpp> #include <mapnik/wkt/wkt_grammar.hpp>
// stl
#include <string> #include <string>
namespace mapnik namespace mapnik
{ {
std::pair<bool,geometry_type*> from_wkt(std::string const& wkt) bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths)
{ {
using namespace boost::spirit; using namespace boost::spirit;
typedef std::string::const_iterator iterator_type; typedef std::string::const_iterator iterator_type;
iterator_type first = wkt.begin(); iterator_type first = wkt.begin();
iterator_type last = wkt.end(); iterator_type last = wkt.end();
geometry_type * path = 0; mapnik::wkt::wkt_collection_grammar<iterator_type> grammar;
mapnik::wkt::wkt_grammar<iterator_type> grammar; return qi::phrase_parse(first, last, grammar, ascii::space, paths);
bool result = qi::phrase_parse(first, last, grammar, ascii::space,path);
return std::make_pair(result, path);
} }
} }