mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 05:24:02 +00:00
[io] Add support for GeometryCollection in WKT read and write.
This commit is contained in:
parent
a1ccbcdea7
commit
a5c8258d56
@ -511,21 +511,36 @@ inline void handle_empty_z_m(tokenizer::iterator& it,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
|
||||||
|
struct dimension
|
||||||
|
: geometry::dimension<Geometry>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// TODO: For now assume the dimension of the first type defined for GC
|
||||||
|
// This should probably be unified for all algorithms
|
||||||
|
template <typename Geometry>
|
||||||
|
struct dimension<Geometry, geometry_collection_tag>
|
||||||
|
: geometry::dimension
|
||||||
|
<
|
||||||
|
typename util::sequence_front
|
||||||
|
<
|
||||||
|
typename traits::geometry_types<Geometry>::type
|
||||||
|
>::type
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Internal, starts parsing
|
\brief Internal, starts parsing
|
||||||
\param tokens boost tokens, parsed with separator " " and keeping separator "()"
|
\param geometry_name string to compare with first token
|
||||||
\param geometry string to compare with first token
|
|
||||||
*/
|
*/
|
||||||
template <typename Geometry>
|
template <typename Geometry>
|
||||||
inline bool initialize(tokenizer const& tokens,
|
inline bool initialize(tokenizer::iterator& it,
|
||||||
std::string const& geometry_name,
|
tokenizer::iterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
tokenizer::iterator& it,
|
std::string const& geometry_name)
|
||||||
tokenizer::iterator& end)
|
|
||||||
{
|
{
|
||||||
it = tokens.begin();
|
|
||||||
end = tokens.end();
|
|
||||||
|
|
||||||
if (it == end || ! boost::iequals(*it++, geometry_name))
|
if (it == end || ! boost::iequals(*it++, geometry_name))
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt));
|
BOOST_THROW_EXCEPTION(read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt));
|
||||||
@ -541,7 +556,7 @@ inline bool initialize(tokenizer const& tokens,
|
|||||||
#pragma warning(disable : 4127)
|
#pragma warning(disable : 4127)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (has_z && dimension<Geometry>::type::value < 3)
|
if (has_z && dimension<Geometry>::value < 3)
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(read_wkt_exception("Z only allowed for 3 or more dimensions", wkt));
|
BOOST_THROW_EXCEPTION(read_wkt_exception("Z only allowed for 3 or more dimensions", wkt));
|
||||||
}
|
}
|
||||||
@ -552,7 +567,6 @@ inline bool initialize(tokenizer const& tokens,
|
|||||||
|
|
||||||
if (has_empty)
|
if (has_empty)
|
||||||
{
|
{
|
||||||
check_end(it, end, wkt);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// M is ignored at all.
|
// M is ignored at all.
|
||||||
@ -569,11 +583,22 @@ struct geometry_parser
|
|||||||
geometry::clear(geometry);
|
geometry::clear(geometry);
|
||||||
|
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
||||||
tokenizer::iterator it, end;
|
tokenizer::iterator it = tokens.begin();
|
||||||
if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
|
tokenizer::iterator const end = tokens.end();
|
||||||
|
|
||||||
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
|
check_end(it, end, wkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void apply(tokenizer::iterator& it,
|
||||||
|
tokenizer::iterator const& end,
|
||||||
|
std::string const& wkt,
|
||||||
|
Geometry& geometry)
|
||||||
|
{
|
||||||
|
if (initialize<Geometry>(it, end, wkt, PrefixPolicy::apply()))
|
||||||
{
|
{
|
||||||
Parser<Geometry>::apply(it, end, wkt, geometry);
|
Parser<Geometry>::apply(it, end, wkt, geometry);
|
||||||
check_end(it, end, wkt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -587,8 +612,20 @@ struct multi_parser
|
|||||||
traits::clear<MultiGeometry>::apply(geometry);
|
traits::clear<MultiGeometry>::apply(geometry);
|
||||||
|
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
||||||
tokenizer::iterator it, end;
|
tokenizer::iterator it = tokens.begin();
|
||||||
if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
|
tokenizer::iterator const end = tokens.end();
|
||||||
|
|
||||||
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
|
check_end(it, end, wkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void apply(tokenizer::iterator& it,
|
||||||
|
tokenizer::iterator const& end,
|
||||||
|
std::string const& wkt,
|
||||||
|
MultiGeometry& geometry)
|
||||||
|
{
|
||||||
|
if (initialize<MultiGeometry>(it, end, wkt, PrefixPolicy::apply()))
|
||||||
{
|
{
|
||||||
handle_open_parenthesis(it, end, wkt);
|
handle_open_parenthesis(it, end, wkt);
|
||||||
|
|
||||||
@ -609,8 +646,6 @@ struct multi_parser
|
|||||||
|
|
||||||
handle_close_parenthesis(it, end, wkt);
|
handle_close_parenthesis(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -634,9 +669,20 @@ struct multi_point_parser
|
|||||||
traits::clear<MultiGeometry>::apply(geometry);
|
traits::clear<MultiGeometry>::apply(geometry);
|
||||||
|
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
||||||
tokenizer::iterator it, end;
|
tokenizer::iterator it = tokens.begin();
|
||||||
|
tokenizer::iterator const end = tokens.end();
|
||||||
|
|
||||||
if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
|
check_end(it, end, wkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void apply(tokenizer::iterator& it,
|
||||||
|
tokenizer::iterator const& end,
|
||||||
|
std::string const& wkt,
|
||||||
|
MultiGeometry& geometry)
|
||||||
|
{
|
||||||
|
if (initialize<MultiGeometry>(it, end, wkt, PrefixPolicy::apply()))
|
||||||
{
|
{
|
||||||
handle_open_parenthesis(it, end, wkt);
|
handle_open_parenthesis(it, end, wkt);
|
||||||
|
|
||||||
@ -672,8 +718,6 @@ struct multi_point_parser
|
|||||||
|
|
||||||
handle_close_parenthesis(it, end, wkt);
|
handle_close_parenthesis(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -691,10 +735,21 @@ struct box_parser
|
|||||||
{
|
{
|
||||||
static inline void apply(std::string const& wkt, Box& box)
|
static inline void apply(std::string const& wkt, Box& box)
|
||||||
{
|
{
|
||||||
bool should_close = false;
|
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
||||||
tokenizer::iterator it = tokens.begin();
|
tokenizer::iterator it = tokens.begin();
|
||||||
tokenizer::iterator end = tokens.end();
|
tokenizer::iterator end = tokens.end();
|
||||||
|
|
||||||
|
apply(it, end, wkt, box);
|
||||||
|
|
||||||
|
check_end(it, end, wkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void apply(tokenizer::iterator& it,
|
||||||
|
tokenizer::iterator const& end,
|
||||||
|
std::string const& wkt,
|
||||||
|
Box& box)
|
||||||
|
{
|
||||||
|
bool should_close = false;
|
||||||
if (it != end && boost::iequals(*it, "POLYGON"))
|
if (it != end && boost::iequals(*it, "POLYGON"))
|
||||||
{
|
{
|
||||||
++it;
|
++it;
|
||||||
@ -725,7 +780,6 @@ struct box_parser
|
|||||||
{
|
{
|
||||||
handle_close_parenthesis(it, end, wkt);
|
handle_close_parenthesis(it, end, wkt);
|
||||||
}
|
}
|
||||||
check_end(it, end, wkt);
|
|
||||||
|
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
std::size_t n = boost::size(points);
|
std::size_t n = boost::size(points);
|
||||||
@ -764,9 +818,18 @@ struct segment_parser
|
|||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
||||||
tokenizer::iterator it = tokens.begin();
|
tokenizer::iterator it = tokens.begin();
|
||||||
tokenizer::iterator end = tokens.end();
|
tokenizer::iterator end = tokens.end();
|
||||||
if (it != end &&
|
|
||||||
(boost::iequals(*it, "SEGMENT")
|
apply(it, end, wkt, segment);
|
||||||
|| boost::iequals(*it, "LINESTRING") ))
|
|
||||||
|
check_end(it, end, wkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void apply(tokenizer::iterator& it,
|
||||||
|
tokenizer::iterator const& end,
|
||||||
|
std::string const& wkt,
|
||||||
|
Segment& segment)
|
||||||
|
{
|
||||||
|
if (it != end && (boost::iequals(*it, "SEGMENT") || boost::iequals(*it, "LINESTRING")))
|
||||||
{
|
{
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
@ -779,8 +842,6 @@ struct segment_parser
|
|||||||
std::vector<point_type> points;
|
std::vector<point_type> points;
|
||||||
container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
|
container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
|
||||||
|
|
||||||
if (boost::size(points) == 2)
|
if (boost::size(points) == 2)
|
||||||
{
|
{
|
||||||
geometry::detail::assign_point_to_index<0>(points.front(), segment);
|
geometry::detail::assign_point_to_index<0>(points.front(), segment);
|
||||||
@ -790,10 +851,138 @@ struct segment_parser
|
|||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(read_wkt_exception("Segment should have 2 points", wkt));
|
BOOST_THROW_EXCEPTION(read_wkt_exception("Segment should have 2 points", wkt));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct dynamic_move_assign
|
||||||
|
{
|
||||||
|
template <typename DynamicGeometry, typename Geometry>
|
||||||
|
static void apply(DynamicGeometry& dynamic_geometry, Geometry & geometry)
|
||||||
|
{
|
||||||
|
dynamic_geometry = std::move(geometry);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dynamic_move_emplace_back
|
||||||
|
{
|
||||||
|
template <typename GeometryCollection, typename Geometry>
|
||||||
|
static void apply(GeometryCollection& geometry_collection, Geometry & geometry)
|
||||||
|
{
|
||||||
|
traits::emplace_back<GeometryCollection>::apply(geometry_collection, std::move(geometry));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename Geometry,
|
||||||
|
template <typename, typename> class ReadWkt,
|
||||||
|
typename AppendPolicy
|
||||||
|
>
|
||||||
|
struct dynamic_readwkt_caller
|
||||||
|
{
|
||||||
|
static inline void apply(tokenizer::iterator& it,
|
||||||
|
tokenizer::iterator const& end,
|
||||||
|
std::string const& wkt,
|
||||||
|
Geometry& geometry)
|
||||||
|
{
|
||||||
|
if (boost::iequals(*it, "POINT"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_point>("POINT", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "MULTIPOINT"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_multi_point>("MULTIPOINT", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "SEGMENT"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_segment>("SEGMENT", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "LINESTRING"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_linestring>("LINESTRING", it, end, wkt, geometry, false)
|
||||||
|
|| parse_geometry<util::is_segment>("LINESTRING", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "MULTILINESTRING"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_multi_linestring>("MULTILINESTRING", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "BOX"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_box>("BOX", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "POLYGON"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_polygon>("POLYGON", it, end, wkt, geometry, false)
|
||||||
|
|| parse_geometry<util::is_ring>("POLYGON", it, end, wkt, geometry, false)
|
||||||
|
|| parse_geometry<util::is_box>("POLYGON", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "MULTIPOLYGON"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_multi_polygon>("MULTIPOLYGON", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else if (boost::iequals(*it, "GEOMETRYCOLLECTION"))
|
||||||
|
{
|
||||||
|
parse_geometry<util::is_geometry_collection>("GEOMETRYCOLLECTION", it, end, wkt, geometry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_THROW_EXCEPTION(read_wkt_exception(
|
||||||
|
"Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.",
|
||||||
|
wkt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template
|
||||||
|
<
|
||||||
|
template <typename> class UnaryPred,
|
||||||
|
typename Geom = typename util::sequence_find_if
|
||||||
|
<
|
||||||
|
typename traits::geometry_types<Geometry>::type, UnaryPred
|
||||||
|
>::type,
|
||||||
|
std::enable_if_t<! std::is_void<Geom>::value, int> = 0
|
||||||
|
>
|
||||||
|
static bool parse_geometry(const char * ,
|
||||||
|
tokenizer::iterator& it,
|
||||||
|
tokenizer::iterator const& end,
|
||||||
|
std::string const& wkt,
|
||||||
|
Geometry& geometry,
|
||||||
|
bool = true)
|
||||||
|
{
|
||||||
|
Geom g;
|
||||||
|
ReadWkt<Geom, typename tag<Geom>::type>::apply(it, end, wkt, g);
|
||||||
|
AppendPolicy::apply(geometry, g);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
template <typename> class UnaryPred,
|
||||||
|
typename Geom = typename util::sequence_find_if
|
||||||
|
<
|
||||||
|
typename traits::geometry_types<Geometry>::type, UnaryPred
|
||||||
|
>::type,
|
||||||
|
std::enable_if_t<std::is_void<Geom>::value, int> = 0
|
||||||
|
>
|
||||||
|
static bool parse_geometry(const char * name,
|
||||||
|
tokenizer::iterator& ,
|
||||||
|
tokenizer::iterator const& ,
|
||||||
|
std::string const& wkt,
|
||||||
|
Geometry& ,
|
||||||
|
bool throw_on_misfit = true)
|
||||||
|
{
|
||||||
|
if (throw_on_misfit)
|
||||||
|
{
|
||||||
|
std::string msg = std::string("Unable to store '") + name + "' in this geometry";
|
||||||
|
BOOST_THROW_EXCEPTION(read_wkt_exception(msg, wkt));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}} // namespace detail::wkt
|
}} // namespace detail::wkt
|
||||||
#endif // DOXYGEN_NO_DETAIL
|
#endif // DOXYGEN_NO_DETAIL
|
||||||
|
|
||||||
@ -900,93 +1089,63 @@ struct read_wkt<DynamicGeometry, dynamic_geometry_tag>
|
|||||||
detail::wkt::tokenizer::iterator end = tokens.end();
|
detail::wkt::tokenizer::iterator end = tokens.end();
|
||||||
if (it == end)
|
if (it == end)
|
||||||
{
|
{
|
||||||
throw_unknown_name(wkt);
|
BOOST_THROW_EXCEPTION(read_wkt_exception(
|
||||||
|
"Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.",
|
||||||
|
wkt));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boost::iequals(*it, "POINT"))
|
detail::wkt::dynamic_readwkt_caller
|
||||||
{
|
|
||||||
parse_geometry<util::is_point>("POINT", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else if (boost::iequals(*it, "MULTIPOINT"))
|
|
||||||
{
|
|
||||||
parse_geometry<util::is_multi_point>("MULTIPOINT", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else if (boost::iequals(*it, "SEGMENT"))
|
|
||||||
{
|
|
||||||
parse_geometry<util::is_segment>("SEGMENT", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else if (boost::iequals(*it, "LINESTRING"))
|
|
||||||
{
|
|
||||||
parse_geometry<util::is_linestring>("LINESTRING", wkt, dynamic_geometry, false)
|
|
||||||
|| parse_geometry<util::is_segment>("LINESTRING", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else if (boost::iequals(*it, "MULTILINESTRING"))
|
|
||||||
{
|
|
||||||
parse_geometry<util::is_multi_linestring>("MULTILINESTRING", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else if (boost::iequals(*it, "BOX"))
|
|
||||||
{
|
|
||||||
parse_geometry<util::is_box>("BOX", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else if (boost::iequals(*it, "POLYGON"))
|
|
||||||
{
|
|
||||||
parse_geometry<util::is_polygon>("POLYGON", wkt, dynamic_geometry, false)
|
|
||||||
|| parse_geometry<util::is_ring>("POLYGON", wkt, dynamic_geometry, false)
|
|
||||||
|| parse_geometry<util::is_box>("POLYGON", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else if (boost::iequals(*it, "MULTIPOLYGON"))
|
|
||||||
{
|
|
||||||
parse_geometry<util::is_multi_polygon>("MULTIPOLYGON", wkt, dynamic_geometry);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw_unknown_name(wkt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void throw_unknown_name(std::string const& wkt)
|
|
||||||
{
|
|
||||||
BOOST_THROW_EXCEPTION(read_wkt_exception(
|
|
||||||
"Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.",
|
|
||||||
wkt));
|
|
||||||
}
|
|
||||||
|
|
||||||
template
|
|
||||||
<
|
|
||||||
template <typename> class UnaryPred,
|
|
||||||
typename Geometry = typename util::sequence_find_if
|
|
||||||
<
|
<
|
||||||
typename traits::geometry_types<DynamicGeometry>::type, UnaryPred
|
DynamicGeometry, dispatch::read_wkt, detail::wkt::dynamic_move_assign
|
||||||
>::type,
|
>::apply(it, end, wkt, dynamic_geometry);
|
||||||
std::enable_if_t<! std::is_void<Geometry>::value, int> = 0
|
|
||||||
>
|
|
||||||
static bool parse_geometry(const char * , std::string const& wkt, DynamicGeometry & dynamic_geometry, bool = true)
|
|
||||||
{
|
|
||||||
Geometry g;
|
|
||||||
read_wkt<Geometry>::apply(wkt, g);
|
|
||||||
dynamic_geometry = std::move(g);
|
|
||||||
|
|
||||||
return true;
|
detail::wkt::check_end(it, end, wkt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Geometry>
|
||||||
|
struct read_wkt<Geometry, geometry_collection_tag>
|
||||||
|
{
|
||||||
|
static inline void apply(std::string const& wkt, Geometry& geometry)
|
||||||
|
{
|
||||||
|
range::clear(geometry);
|
||||||
|
|
||||||
|
detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
||||||
|
detail::wkt::tokenizer::iterator it = tokens.begin();
|
||||||
|
detail::wkt::tokenizer::iterator const end = tokens.end();
|
||||||
|
|
||||||
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
|
detail::wkt::check_end(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template
|
static inline void apply(detail::wkt::tokenizer::iterator& it,
|
||||||
<
|
detail::wkt::tokenizer::iterator const& end,
|
||||||
template <typename> class UnaryPred,
|
std::string const& wkt,
|
||||||
typename Geometry = typename util::sequence_find_if
|
Geometry& geometry)
|
||||||
<
|
|
||||||
typename traits::geometry_types<DynamicGeometry>::type, UnaryPred
|
|
||||||
>::type,
|
|
||||||
std::enable_if_t<std::is_void<Geometry>::value, int> = 0
|
|
||||||
>
|
|
||||||
static bool parse_geometry(const char * name, std::string const& wkt, DynamicGeometry & , bool throw_on_misfit = true)
|
|
||||||
{
|
{
|
||||||
if (throw_on_misfit)
|
if (detail::wkt::initialize<Geometry>(it, end, wkt, "GEOMETRYCOLLECTION"))
|
||||||
{
|
{
|
||||||
std::string msg = std::string("Unable to store '") + name + "' in this geometry";
|
detail::wkt::handle_open_parenthesis(it, end, wkt);
|
||||||
BOOST_THROW_EXCEPTION(read_wkt_exception(msg, wkt));
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
// Stop at ")"
|
||||||
|
while (it != end && *it != ")")
|
||||||
|
{
|
||||||
|
detail::wkt::dynamic_readwkt_caller
|
||||||
|
<
|
||||||
|
Geometry, dispatch::read_wkt, detail::wkt::dynamic_move_emplace_back
|
||||||
|
>::apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
|
if (it != end && *it == ",")
|
||||||
|
{
|
||||||
|
// Skip "," after geometry is parsed
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::wkt::handle_close_parenthesis(it, end, wkt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -470,6 +470,55 @@ struct wkt<Geometry, dynamic_geometry_tag>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Implement non-recursive version
|
||||||
|
template <typename Geometry>
|
||||||
|
struct wkt<Geometry, geometry_collection_tag>
|
||||||
|
{
|
||||||
|
template <typename OutputStream>
|
||||||
|
static inline void apply(OutputStream& os, Geometry const& geometry,
|
||||||
|
bool force_closure)
|
||||||
|
{
|
||||||
|
output_or_recursive_call(os, geometry, force_closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename OutputStream, typename Geom,
|
||||||
|
std::enable_if_t<util::is_geometry_collection<Geom>::value, int> = 0
|
||||||
|
>
|
||||||
|
static void output_or_recursive_call(OutputStream& os, Geom const& geom, bool force_closure)
|
||||||
|
{
|
||||||
|
os << "GEOMETRYCOLLECTION(";
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
auto const end = boost::end(geom);
|
||||||
|
for (auto it = boost::begin(geom); it != end; ++it)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
os << ',';
|
||||||
|
|
||||||
|
traits::visit_iterator<Geom>::apply([&](auto const& g)
|
||||||
|
{
|
||||||
|
output_or_recursive_call(os, g, force_closure);
|
||||||
|
}, it);
|
||||||
|
}
|
||||||
|
|
||||||
|
os << ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename OutputStream, typename Geom,
|
||||||
|
std::enable_if_t<! util::is_geometry_collection<Geom>::value, int> = 0
|
||||||
|
>
|
||||||
|
static void output_or_recursive_call(OutputStream& os, Geom const& geom, bool force_closure)
|
||||||
|
{
|
||||||
|
wkt<Geom>::apply(os, geom, force_closure);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace dispatch
|
} // namespace dispatch
|
||||||
#endif // DOXYGEN_NO_DISPATCH
|
#endif // DOXYGEN_NO_DISPATCH
|
||||||
|
@ -98,6 +98,14 @@ void test_wkt_read_write(std::string const& wkt, std::string const& expected,
|
|||||||
boost::variant<G> v;
|
boost::variant<G> v;
|
||||||
bg::read_wkt(wkt, v);
|
bg::read_wkt(wkt, v);
|
||||||
check_wkt(v, expected);
|
check_wkt(v, expected);
|
||||||
|
|
||||||
|
bg::model::geometry_collection<boost::variant<G>> gc1{v};
|
||||||
|
bg::read_wkt(std::string("GEOMETRYCOLLECTION(") + wkt + ')', gc1);
|
||||||
|
check_wkt(gc1, std::string("GEOMETRYCOLLECTION(") + expected + ')');
|
||||||
|
|
||||||
|
bg::model::geometry_collection<boost::variant<G>> gc2{v, v};
|
||||||
|
bg::read_wkt(std::string("GEOMETRYCOLLECTION(") + wkt + ',' + wkt + ')', gc2);
|
||||||
|
check_wkt(gc2, std::string("GEOMETRYCOLLECTION(") + expected + ',' + expected + ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename G>
|
template <typename G>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user