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;
|
namespace fusion = boost::fusion;
|
||||||
using space_type = mapnik::json::space_type;
|
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> >
|
template <typename Iterator, typename ErrorHandler = json::error_handler<Iterator> >
|
||||||
struct topojson_grammar : qi::grammar<Iterator, space_type, topology()>
|
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::geometry>()> objects;
|
||||||
qi::rule<Iterator, space_type, std::vector<mapnik::topojson::arc>()> arcs;
|
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::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::transform()> transform;
|
||||||
qi::rule<Iterator, space_type, mapnik::topojson::bounding_box()> bbox;
|
qi::rule<Iterator, space_type, mapnik::topojson::bounding_box()> bbox;
|
||||||
qi::rule<Iterator, space_type, mapnik::topojson::geometry() > geometry;
|
qi::rule<Iterator, qi::locals<int, coordinates_type, arcs_type, properties>, mapnik::topojson::geometry(), space_type> 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, space_type, void(std::vector<mapnik::topojson::geometry>&)> geometry_collection;
|
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<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
|
// properties
|
||||||
qi::rule<Iterator, space_type, mapnik::topojson::properties()> 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)
|
(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(
|
BOOST_FUSION_ADAPT_STRUCT(
|
||||||
mapnik::topojson::topology,
|
mapnik::topojson::topology,
|
||||||
(std::vector<mapnik::topojson::geometry>, geometries)
|
(std::vector<mapnik::topojson::geometry>, geometries)
|
||||||
|
@ -123,13 +87,28 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
||||||
qi::_3_type _3;
|
qi::_3_type _3;
|
||||||
qi::_4_type _4;
|
qi::_4_type _4;
|
||||||
qi::_r1_type _r1;
|
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::fail;
|
||||||
using qi::on_error;
|
using qi::on_error;
|
||||||
using phoenix::push_back;
|
using phoenix::push_back;
|
||||||
using phoenix::construct;
|
using phoenix::construct;
|
||||||
|
|
||||||
|
geometry_type_dispatch.add
|
||||||
|
("\"Point\"",1)
|
||||||
|
("\"LineString\"",2)
|
||||||
|
("\"Polygon\"",3)
|
||||||
|
("\"MultiPoint\"",4)
|
||||||
|
("\"MultiLineString\"",5)
|
||||||
|
("\"MultiPolygon\"",6)
|
||||||
|
("\"GeometryCollection\"",7)
|
||||||
|
;
|
||||||
|
|
||||||
// error handler
|
// error handler
|
||||||
boost::phoenix::function<ErrorHandler> const error_handler;
|
boost::phoenix::function<ErrorHandler> const error_handler;
|
||||||
|
boost::phoenix::function<create_geometry_impl> const create_geometry;
|
||||||
// generic JSON types
|
// generic JSON types
|
||||||
json.value = json.object | json.array | json.string_ | json.number
|
json.value = json.object | json.array | json.string_ | json.number
|
||||||
;
|
;
|
||||||
|
@ -185,89 +164,39 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
||||||
>> lit('}')
|
>> lit('}')
|
||||||
;
|
;
|
||||||
|
|
||||||
geometry =
|
geometry = lit('{')[_a = 0]
|
||||||
point |
|
> ((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1])
|
||||||
linestring |
|
|
|
||||||
polygon |
|
(lit("\"coordinates\"") > lit(':') > coordinates[_b = _1])
|
||||||
multi_point |
|
|
|
||||||
multi_linestring |
|
(lit("\"arcs\"") > lit(':') > rings_array[_c = _1])
|
||||||
multi_polygon |
|
|
|
||||||
omit[json.object]
|
properties[_d = _1]
|
||||||
|
|
|
||||||
|
json.key_value) % lit(',')
|
||||||
|
> lit('}')[_val = create_geometry(_a, _b, _c, _d)]
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
geometry_collection = lit('{')
|
geometry_collection = lit('{')
|
||||||
>> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"")
|
>> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"")
|
||||||
>> -(lit(',') >> omit[bbox])
|
>> lit(',') >> lit("\"geometries\"") >> lit(':')
|
||||||
>> lit(',') >> lit("\"geometries\"") >> lit(':') >> lit('[') >> -(geometry[push_back(_r1, _1)] % lit(','))
|
>> lit('[')
|
||||||
|
>> -(geometry[push_back(_r1, _1)] % lit(','))
|
||||||
>> lit(']')
|
>> 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(']')
|
ring = lit('[') >> -(int_ % lit(',')) >> lit(']')
|
||||||
;
|
;
|
||||||
|
rings = lit('[') >> -(ring % lit(',')) >> lit(']')
|
||||||
|
;
|
||||||
|
rings_array = lit('[') >> -(rings % lit(',')) >> lit(']')
|
||||||
|
|
|
||||||
|
rings
|
||||||
|
|
|
||||||
|
ring
|
||||||
|
;
|
||||||
|
|
||||||
properties = lit("\"properties\"")
|
properties = lit("\"properties\"")
|
||||||
>> lit(':')
|
>> lit(':')
|
||||||
|
@ -277,9 +206,12 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
||||||
arcs = lit("\"arcs\"") >> lit(':')
|
arcs = lit("\"arcs\"") >> lit(':')
|
||||||
>> lit('[') >> -( arc % lit(',')) >> 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");
|
topology.name("topology");
|
||||||
transform.name("transform");
|
transform.name("transform");
|
||||||
|
@ -287,13 +219,8 @@ topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
||||||
arc.name("arc");
|
arc.name("arc");
|
||||||
arcs.name("arcs");
|
arcs.name("arcs");
|
||||||
json.value.name("value");
|
json.value.name("value");
|
||||||
coordinate.name("coordinate");
|
coordinate_.name("coordinate");
|
||||||
|
geometry.name("geometry");
|
||||||
point.name("point");
|
|
||||||
multi_point.name("multi_point");
|
|
||||||
linestring.name("linestring");
|
|
||||||
polygon.name("polygon");
|
|
||||||
multi_polygon.name("multi_polygon");
|
|
||||||
geometry_collection.name("geometry_collection");
|
geometry_collection.name("geometry_collection");
|
||||||
// error handler
|
// error handler
|
||||||
on_error<fail>(topology, error_handler(_1, _2, _3, _4));
|
on_error<fail>(topology, error_handler(_1, _2, _3, _4));
|
||||||
|
|
Loading…
Reference in a new issue