extract bounding boxes from GeoJSON - re-implement grammar to store offset and size of "Feature" elements

This commit is contained in:
artemp 2015-01-19 18:09:23 +01:00
parent f50a34d1b8
commit 15a83ff54d
2 changed files with 23 additions and 32 deletions

View file

@ -43,7 +43,7 @@
namespace mapnik { namespace json {
using position = std::tuple<double,double>;
using boxes = std::vector<std::tuple<box2d<double>, std::size_t>>;
using boxes = std::vector<std::pair<box2d<double>, std::pair<std::size_t, std::size_t>>>;
namespace qi = boost::spirit::qi;
namespace standard_wide = boost::spirit::standard_wide;
@ -51,7 +51,7 @@ using standard_wide::space_type;
struct calculate_bounding_box_impl
{
using result_type = void;// box2d<double>;
using result_type = void;
template <typename T0, typename T1>
result_type operator() (T0 & bbox, T1 const& pos) const
{
@ -74,20 +74,10 @@ struct calculate_bounding_box_impl
struct push_box_impl
{
using result_type = void;
template <typename T>
result_type operator() (T & boxes, std::size_t offset, box2d<double> const& box) const
template <typename T0, typename T1, typename T2, typename T3>
void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const
{
boxes.emplace_back(box, offset);
}
};
struct offset_impl
{
using result_type = std::size_t;
template <typename T0, typename T1>
std::size_t operator() (T0 const& begin, T1 const& itr) const
{
return std::distance(begin, itr);
boxes.emplace_back(box, std::make_pair(std::distance(begin, range.begin()), std::distance(range.begin(), range.end())));
}
};
@ -96,17 +86,17 @@ struct extract_bounding_box_grammar :
qi::grammar<Iterator, void(boxes&) ,space_type>
{
extract_bounding_box_grammar();
// rules
qi::rule<Iterator, void(boxes&), space_type> start;
qi::rule<Iterator, qi::locals<Iterator,Iterator>, void(boxes&), space_type> features;
qi::rule<Iterator, void(boxes&, Iterator const&, Iterator const&), space_type> feature;
qi::rule<Iterator, void(boxes&,std::size_t), space_type> bounding_box;
qi::rule<Iterator, qi::locals<Iterator>, void(boxes&), space_type> features;
qi::rule<Iterator, qi::locals<int, box2d<double>>, void(boxes&, Iterator const&), space_type> feature;
qi::rule<Iterator, qi::locals<box2d<double>>, box2d<double>(), space_type> coords;
qi::rule<Iterator, boost::optional<position>(), space_type> pos;
qi::rule<Iterator, void(box2d<double>&), space_type> ring;
qi::rule<Iterator, void(box2d<double>&), space_type> rings;
qi::rule<Iterator, void(box2d<double>&), space_type> rings_array;
boost::phoenix::function<offset_impl> offset;
// phoenix functions
boost::phoenix::function<push_box_impl> push_box;
boost::phoenix::function<calculate_bounding_box_impl> calculate_bounding_box;
// error handler

View file

@ -28,7 +28,6 @@
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
// stl
#include <iostream>
@ -52,16 +51,15 @@ extract_bounding_box_grammar<Iterator, ErrorHandler>::extract_bounding_box_gramm
qi::omit_type omit;
qi::_r1_type _r1;
qi::_r2_type _r2;
qi::_r3_type _r3;
qi::_a_type _a;
qi::_b_type _b;
qi::skip_type skip;
qi::lexeme_type lexeme;
boost::spirit::repository::qi::seek_type seek;
qi::eps_type eps;
qi::raw_type raw;
standard_wide::char_type char_;
boost::spirit::repository::qi::iter_pos_type iter_pos;
using qi::fail;
using qi::on_error;
using boost::phoenix::push_back;
start = features(_r1)
;
@ -69,15 +67,18 @@ extract_bounding_box_grammar<Iterator, ErrorHandler>::extract_bounding_box_gramm
>> lit(':') >> lit("\"FeatureCollection\"")
>> lit(',') >> lit("\"features\"")
>> lit(':'))
>> lit('[') >> *(seek[lexeme[skip[iter_pos[_b = _1] >> lit('{') >> lit("\"type\"") >> lit(':') >> lit("\"Feature\"")]]]
>> feature(_r1, _a, _b))
>> lit('[') >> (feature(_r1,_a) % lit(',')) >> lit(']')
;
feature = bounding_box(_r1, offset(_r2, _r3))
feature = raw[lit('{')[_a = 1] >> lit("\"type\"") >> lit(':') >> lit("\"Feature\"")
>> *(eps(_a > 0) >> (lit('{')[_a += 1]
|
lit('}')[_a -=1]
|
coords[_b = _1]
|
char_))][push_box(_r1, _r2, _b, _1)]
;
bounding_box = seek["\"coordinates\""] >> lit(':') >> coords[push_box(_r1, _r2, _1)]
;
coords = (rings_array(_a) | rings (_a) | ring(_a) | pos[calculate_bounding_box(_a,_1)])[_val = _a]
coords = lit("\"coordinates\"") >> lit(':') >> (rings_array(_a) | rings (_a) | ring(_a) | pos[calculate_bounding_box(_a,_1)])[_val = _a]
;
pos = lit('[') > -(double_ > lit(',') > double_) > omit[*(lit(',') > double_)] > lit(']')
;