topojson grammar - re-factor to allow geometry elements to be in any order
This commit is contained in:
parent
fee0ad05ce
commit
01967cfaff
2 changed files with 183 additions and 126 deletions
|
@ -42,6 +42,138 @@ namespace qi = boost::spirit::qi;
|
|||
namespace fusion = boost::fusion;
|
||||
using space_type = mapnik::json::space_type;
|
||||
|
||||
struct create_point
|
||||
{
|
||||
using result_type = mapnik::topojson::point;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & coord, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::point pt;
|
||||
if (coord.template is<mapnik::topojson::coordinate>())
|
||||
{
|
||||
auto const& coord_ = coord.template get<mapnik::topojson::coordinate>();
|
||||
pt.coord = coord_;
|
||||
pt.props = props;
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_point
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_point;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & coords, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_point mpt;
|
||||
if (coords.template is<std::vector<mapnik::topojson::coordinate>>())
|
||||
{
|
||||
auto const& points = coords.template get<std::vector<mapnik::topojson::coordinate>>();
|
||||
mpt. points = points;
|
||||
mpt.props = props;
|
||||
}
|
||||
return mpt;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_line_string
|
||||
{
|
||||
using result_type = mapnik::topojson::linestring;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::linestring line;
|
||||
if (arcs.template is<std::vector<index_type>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<index_type>>();
|
||||
line.rings = arcs_;
|
||||
line.props = props;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_line_string
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_linestring;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_linestring mline;
|
||||
if (arcs.template is<std::vector<std::vector<index_type>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<index_type>>>();
|
||||
mline.lines = arcs_;
|
||||
mline.props = props;
|
||||
}
|
||||
return mline;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_polygon
|
||||
{
|
||||
using result_type = mapnik::topojson::polygon;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::polygon poly;
|
||||
if (arcs.template is<std::vector<std::vector<index_type>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<index_type>>>();
|
||||
poly.rings = arcs_;
|
||||
poly.props = props;
|
||||
}
|
||||
return poly;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_polygon
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_polygon;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_polygon mpoly;
|
||||
if (arcs.template is<std::vector<std::vector<std::vector<index_type>>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<std::vector<index_type>>>>();
|
||||
mpoly.polygons = arcs_;
|
||||
mpoly.props = props;
|
||||
}
|
||||
return mpoly;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct create_geometry_impl
|
||||
{
|
||||
using result_type = mapnik::topojson::geometry;
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
result_type operator()(T0 geom_type, T1 & coord, T2 & arcs, T3 & props) const
|
||||
{
|
||||
switch (geom_type)
|
||||
{
|
||||
case 1: //Point
|
||||
return create_point()(coord, props);
|
||||
case 2: //LineString
|
||||
return create_line_string()(arcs, props);
|
||||
case 3: //Polygon
|
||||
return create_polygon()(arcs, props);
|
||||
case 4: //MultiPoint
|
||||
return create_multi_point()(coord, props);
|
||||
case 5: //MultiLineString
|
||||
return create_multi_line_string()(arcs, props);
|
||||
case 6: //MultiPolygon
|
||||
return create_multi_polygon()(arcs, props);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return mapnik::topojson::geometry(); //empty
|
||||
}
|
||||
};
|
||||
|
||||
using coordinates_type = util::variant<coordinate,std::vector<coordinate>>;
|
||||
using arcs_type = util::variant<std::vector<index_type>, std::vector<std::vector<index_type>>, std::vector<std::vector<std::vector<index_type>>>>;
|
||||
template <typename Iterator, typename ErrorHandler = json::error_handler<Iterator> >
|
||||
struct topojson_grammar : qi::grammar<Iterator, space_type, topology()>
|
||||
|
||||
|
@ -55,20 +187,18 @@ private:
|
|||
qi::rule<Iterator, space_type, std::vector<mapnik::topojson::geometry>()> objects;
|
||||
qi::rule<Iterator, space_type, std::vector<mapnik::topojson::arc>()> arcs;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::arc()> arc;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::coordinate()> coordinate;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::coordinate()> coordinate_;
|
||||
qi::rule<Iterator, space_type, coordinates_type()> coordinates;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::transform()> transform;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::bounding_box()> bbox;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::geometry() > geometry;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::point()> point;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::multi_point()> multi_point;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::linestring()> linestring;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::multi_linestring()> multi_linestring;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::polygon()> polygon;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::multi_polygon()> multi_polygon;
|
||||
qi::rule<Iterator, qi::locals<int, coordinates_type, arcs_type, properties>, mapnik::topojson::geometry(), space_type> geometry;
|
||||
qi::rule<Iterator, space_type, void(std::vector<mapnik::topojson::geometry>&)> geometry_collection;
|
||||
qi::rule<Iterator, space_type, std::vector<index_type>()> ring;
|
||||
qi::rule<Iterator, space_type, std::vector<std::vector<index_type>>()> rings;
|
||||
qi::rule<Iterator, space_type, arcs_type()> rings_array;
|
||||
// properties
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::properties()> properties;
|
||||
qi::symbols<char, int> geometry_type_dispatch;
|
||||
};
|
||||
|
||||
}}
|
||||
|
|
|
@ -57,42 +57,6 @@ BOOST_FUSION_ADAPT_STRUCT(
|
|||
(double, maxy)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::point,
|
||||
(mapnik::topojson::coordinate, coord)
|
||||
(boost::optional<mapnik::topojson::properties>, props)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::multi_point,
|
||||
(std::vector<mapnik::topojson::coordinate>, points)
|
||||
(boost::optional<mapnik::topojson::properties>, props)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::linestring,
|
||||
(std::vector<mapnik::topojson::index_type>, rings)
|
||||
(boost::optional<mapnik::topojson::properties>, props)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::multi_linestring,
|
||||
(std::vector<std::vector<mapnik::topojson::index_type> >, lines)
|
||||
(boost::optional<mapnik::topojson::properties>, props)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::polygon,
|
||||
(std::vector<std::vector<mapnik::topojson::index_type> >, rings)
|
||||
(boost::optional<mapnik::topojson::properties>, props)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::multi_polygon,
|
||||
(std::vector<std::vector<std::vector<mapnik::topojson::index_type> > >, polygons)
|
||||
(boost::optional<mapnik::topojson::properties>, props)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::topology,
|
||||
(std::vector<mapnik::topojson::geometry>, geometries)
|
||||
|
@ -123,13 +87,28 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
|||
qi::_3_type _3;
|
||||
qi::_4_type _4;
|
||||
qi::_r1_type _r1;
|
||||
qi::_a_type _a;
|
||||
qi::_b_type _b;
|
||||
qi::_c_type _c;
|
||||
qi::_d_type _d;
|
||||
using qi::fail;
|
||||
using qi::on_error;
|
||||
using phoenix::push_back;
|
||||
using phoenix::construct;
|
||||
|
||||
geometry_type_dispatch.add
|
||||
("\"Point\"",1)
|
||||
("\"LineString\"",2)
|
||||
("\"Polygon\"",3)
|
||||
("\"MultiPoint\"",4)
|
||||
("\"MultiLineString\"",5)
|
||||
("\"MultiPolygon\"",6)
|
||||
("\"GeometryCollection\"",7)
|
||||
;
|
||||
|
||||
// error handler
|
||||
boost::phoenix::function<ErrorHandler> const error_handler;
|
||||
boost::phoenix::function<create_geometry_impl> const create_geometry;
|
||||
// generic JSON types
|
||||
json.value = json.object | json.array | json.string_ | json.number
|
||||
;
|
||||
|
@ -185,89 +164,39 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
|||
>> lit('}')
|
||||
;
|
||||
|
||||
geometry =
|
||||
point |
|
||||
linestring |
|
||||
polygon |
|
||||
multi_point |
|
||||
multi_linestring |
|
||||
multi_polygon |
|
||||
omit[json.object]
|
||||
geometry = lit('{')[_a = 0]
|
||||
> ((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1])
|
||||
|
|
||||
(lit("\"coordinates\"") > lit(':') > coordinates[_b = _1])
|
||||
|
|
||||
(lit("\"arcs\"") > lit(':') > rings_array[_c = _1])
|
||||
|
|
||||
properties[_d = _1]
|
||||
|
|
||||
json.key_value) % lit(',')
|
||||
> lit('}')[_val = create_geometry(_a, _b, _c, _d)]
|
||||
;
|
||||
|
||||
|
||||
geometry_collection = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"")
|
||||
>> -(lit(',') >> omit[bbox])
|
||||
>> lit(',') >> lit("\"geometries\"") >> lit(':') >> lit('[') >> -(geometry[push_back(_r1, _1)] % lit(','))
|
||||
>> lit(',') >> lit("\"geometries\"") >> lit(':')
|
||||
>> lit('[')
|
||||
>> -(geometry[push_back(_r1, _1)] % lit(','))
|
||||
>> lit(']')
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
point = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"Point\"")
|
||||
>> -(lit(',') >> omit[bbox])
|
||||
>> ((lit(',') >> lit("\"coordinates\"") >> lit(':') >> coordinate)
|
||||
^
|
||||
(lit(',') >> properties)
|
||||
^
|
||||
(lit(',') >> omit[json.key_value]))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
multi_point = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"MultiPoint\"")
|
||||
>> -(lit(',') >> omit[bbox])
|
||||
>> ((lit(',') >> lit("\"coordinates\"") >> lit(':')
|
||||
>> lit('[') >> -(coordinate % lit(',')) >> lit(']'))
|
||||
^
|
||||
(lit(',') >> properties) ^ (lit(',') >> omit[json.key_value]))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
linestring = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"LineString\"")
|
||||
>> (lit(',') >> (lit("\"arcs\"") >> lit(':') >> ring)
|
||||
^
|
||||
(lit(',') >> properties))
|
||||
//^
|
||||
// (lit(',') >> omit[json.key_value]))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
multi_linestring = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"MultiLineString\"")
|
||||
>> -(lit(',') >> omit[bbox])
|
||||
>> ((lit(',') >> lit("\"arcs\"") >> lit(':')
|
||||
>> lit('[') >> -(ring % lit(',')) >> lit(']'))
|
||||
^
|
||||
(lit(',') >> properties)
|
||||
^
|
||||
(lit(',') >> omit[json.key_value]))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
polygon = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"Polygon\"")
|
||||
>> -(lit(',') >> omit[bbox])
|
||||
>> ((lit(',') >> lit("\"arcs\"") >> lit(':')
|
||||
>> lit('[') >> -(ring % lit(',')) >> lit(']'))
|
||||
^ (lit(',') >> properties))
|
||||
//^ (lit(',') >> omit[json.key_value]))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
multi_polygon = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"MultiPolygon\"")
|
||||
>> -(lit(',') >> omit[bbox])
|
||||
>> ((lit(',') >> lit("\"arcs\"") >> lit(':')
|
||||
>> lit('[')
|
||||
>> -((lit('[') >> -(ring % lit(',')) >> lit(']')) % lit(','))
|
||||
>> lit(']')) ^ (lit(',') >> properties) ^ (lit(',') >> omit[json.key_value]))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
ring = lit('[') >> -(int_ % lit(',')) >> lit(']')
|
||||
;
|
||||
rings = lit('[') >> -(ring % lit(',')) >> lit(']')
|
||||
;
|
||||
rings_array = lit('[') >> -(rings % lit(',')) >> lit(']')
|
||||
|
|
||||
rings
|
||||
|
|
||||
ring
|
||||
;
|
||||
|
||||
properties = lit("\"properties\"")
|
||||
>> lit(':')
|
||||
|
@ -277,9 +206,12 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
|||
arcs = lit("\"arcs\"") >> lit(':')
|
||||
>> lit('[') >> -( arc % lit(',')) >> lit(']') ;
|
||||
|
||||
arc = lit('[') >> -(coordinate % lit(',')) >> lit(']') ;
|
||||
arc = lit('[') >> -(coordinate_ % lit(',')) >> lit(']') ;
|
||||
|
||||
coordinate = lit('[') >> double_ >> lit(',') >> double_ >> lit(']');
|
||||
coordinate_ = lit('[') > double_ > lit(',') > double_ > lit(']');
|
||||
|
||||
coordinates = (lit('[') >> coordinate_ % lit(',') > lit(']'))
|
||||
| coordinate_;
|
||||
|
||||
topology.name("topology");
|
||||
transform.name("transform");
|
||||
|
@ -287,13 +219,8 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
|||
arc.name("arc");
|
||||
arcs.name("arcs");
|
||||
json.value.name("value");
|
||||
coordinate.name("coordinate");
|
||||
|
||||
point.name("point");
|
||||
multi_point.name("multi_point");
|
||||
linestring.name("linestring");
|
||||
polygon.name("polygon");
|
||||
multi_polygon.name("multi_polygon");
|
||||
coordinate_.name("coordinate");
|
||||
geometry.name("geometry");
|
||||
geometry_collection.name("geometry_collection");
|
||||
// error handler
|
||||
on_error<fail>(topology, error_handler(_1, _2, _3, _4));
|
||||
|
|
Loading…
Reference in a new issue