mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
[wkt] support tabs, newlines and code cleanup
This commit is contained in:
parent
6a7224e369
commit
f92671b933
@ -1,7 +1,7 @@
|
|||||||
[/============================================================================
|
[/============================================================================
|
||||||
Boost.Geometry (aka GGL, Generic Geometry Library)
|
Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
Copyright (c) 2009-2022 Barend Gehrels, Geodan, Amsterdam, the Netherlands.
|
Copyright (c) 2009-2023 Barend Gehrels, Geodan, Amsterdam, the Netherlands.
|
||||||
Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
|
Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
|
||||||
Copyright (c) 2009-2017 Mateusz Loskot <mateusz@loskot.net>, London, UK.
|
Copyright (c) 2009-2017 Mateusz Loskot <mateusz@loskot.net>, London, UK.
|
||||||
Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||||
@ -19,6 +19,22 @@
|
|||||||
|
|
||||||
[section:release_notes Release Notes]
|
[section:release_notes Release Notes]
|
||||||
|
|
||||||
|
[/=================]
|
||||||
|
[heading Boost 1.82]
|
||||||
|
[/=================]
|
||||||
|
|
||||||
|
[*Major improvements]
|
||||||
|
|
||||||
|
* [@https://github.com/boostorg/geometry/pull/1045 1045] Support geographic buffer for (multi)linestrings and (multi)polygons
|
||||||
|
|
||||||
|
[*Solved issues]
|
||||||
|
|
||||||
|
* [@https://github.com/boostorg/geometry/issues/705 705] WKT: allow tabs and new lines
|
||||||
|
|
||||||
|
[*Breaking changes]
|
||||||
|
|
||||||
|
* The WKT output presentation of an empty polygon is now POLYGON() to make it consistent with other geometries
|
||||||
|
|
||||||
[/=================]
|
[/=================]
|
||||||
[heading Boost 1.81]
|
[heading Boost 1.81]
|
||||||
[/=================]
|
[/=================]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||||
|
|
||||||
@ -57,6 +57,20 @@ struct prefix_multipolygon
|
|||||||
static inline const char* apply() { return "MULTIPOLYGON"; }
|
static inline const char* apply() { return "MULTIPOLYGON"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct prefix_segment
|
||||||
|
{
|
||||||
|
static inline const char* apply() { return "SEGMENT"; }
|
||||||
|
};
|
||||||
|
struct prefix_box
|
||||||
|
{
|
||||||
|
static inline const char* apply() { return "BOX"; }
|
||||||
|
};
|
||||||
|
struct prefix_geometrycollection
|
||||||
|
{
|
||||||
|
static inline const char* apply() { return "GEOMETRYCOLLECTION"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}} // namespace wkt::impl
|
}} // namespace wkt::impl
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||||
|
|
||||||
@ -11,46 +11,13 @@
|
|||||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
|
#ifndef BOOST_GEOMETRY_IO_WKT_MULTI_HPP
|
||||||
#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
|
#define BOOST_GEOMETRY_IO_WKT_MULTI_HPP
|
||||||
|
|
||||||
#include <boost/geometry/core/tags.hpp>
|
#include <boost/geometry/core/tags.hpp>
|
||||||
#include <boost/geometry/domains/gis/io/wkt/write.hpp>
|
#include <boost/geometry/domains/gis/io/wkt/write.hpp>
|
||||||
|
|
||||||
|
#include <boost/config/pragma_message.hpp>
|
||||||
|
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||||
|
|
||||||
namespace boost { namespace geometry
|
#endif // BOOST_GEOMETRY_IO_WKT_MULTI_HPP
|
||||||
{
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_NO_DETAIL
|
|
||||||
namespace detail { namespace wkt
|
|
||||||
{
|
|
||||||
|
|
||||||
struct prefix_null
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return ""; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prefix_multipoint
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return "MULTIPOINT"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prefix_multilinestring
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return "MULTILINESTRING"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prefix_multipolygon
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return "MULTIPOLYGON"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace wkt::impl
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace boost::geometry
|
|
||||||
|
|
||||||
#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||||
@ -117,19 +117,26 @@ private :
|
|||||||
namespace detail { namespace wkt
|
namespace detail { namespace wkt
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
inline auto make_tokenizer(std::string const& wkt)
|
||||||
|
{
|
||||||
|
using separator = boost::char_separator<char>;
|
||||||
|
using tokenizer = boost::tokenizer<separator>;
|
||||||
|
const tokenizer tokens(wkt, separator(" \n\t\r", ",()"));
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Point,
|
template <typename Point,
|
||||||
std::size_t Dimension = 0,
|
std::size_t Dimension = 0,
|
||||||
std::size_t DimensionCount = geometry::dimension<Point>::value>
|
std::size_t DimensionCount = geometry::dimension<Point>::value>
|
||||||
struct parsing_assigner
|
struct parsing_assigner
|
||||||
{
|
{
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
Point& point,
|
Point& point,
|
||||||
std::string const& wkt)
|
std::string const& wkt)
|
||||||
{
|
{
|
||||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
using coordinate_type = typename coordinate_type<Point>::type;
|
||||||
|
|
||||||
// Stop at end of tokens, or at "," ot ")"
|
// Stop at end of tokens, or at "," ot ")"
|
||||||
bool finished = (it == end || *it == "," || *it == ")");
|
bool finished = (it == end || *it == "," || *it == ")");
|
||||||
@ -167,8 +174,9 @@ struct parsing_assigner
|
|||||||
template <typename Point, std::size_t DimensionCount>
|
template <typename Point, std::size_t DimensionCount>
|
||||||
struct parsing_assigner<Point, DimensionCount, DimensionCount>
|
struct parsing_assigner<Point, DimensionCount, DimensionCount>
|
||||||
{
|
{
|
||||||
static inline void apply(tokenizer::iterator&,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const&,
|
static inline void apply(TokenizerIterator&,
|
||||||
|
TokenizerIterator const&,
|
||||||
Point&,
|
Point&,
|
||||||
std::string const&)
|
std::string const&)
|
||||||
{
|
{
|
||||||
@ -226,9 +234,9 @@ template <typename Point>
|
|||||||
struct container_inserter
|
struct container_inserter
|
||||||
{
|
{
|
||||||
// Version with output iterator
|
// Version with output iterator
|
||||||
template <typename OutputIterator>
|
template <typename TokenizerIterator, typename OutputIterator>
|
||||||
static inline void apply(tokenizer::iterator& it,
|
static inline void apply(TokenizerIterator& it,
|
||||||
tokenizer::iterator const& end,
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
OutputIterator out)
|
OutputIterator out)
|
||||||
{
|
{
|
||||||
@ -258,10 +266,8 @@ template <typename Geometry,
|
|||||||
closure_selector Closure = closure<Geometry>::value>
|
closure_selector Closure = closure<Geometry>::value>
|
||||||
struct stateful_range_appender
|
struct stateful_range_appender
|
||||||
{
|
{
|
||||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
|
||||||
|
|
||||||
// NOTE: Geometry is a reference
|
// NOTE: Geometry is a reference
|
||||||
inline void append(Geometry geom, point_type const& point, bool)
|
inline void append(Geometry geom, typename geometry::point_type<Geometry>::type const& point, bool)
|
||||||
{
|
{
|
||||||
geometry::append(geom, point);
|
geometry::append(geom, point);
|
||||||
}
|
}
|
||||||
@ -270,13 +276,13 @@ struct stateful_range_appender
|
|||||||
template <typename Geometry>
|
template <typename Geometry>
|
||||||
struct stateful_range_appender<Geometry, open>
|
struct stateful_range_appender<Geometry, open>
|
||||||
{
|
{
|
||||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
using point_type = typename geometry::point_type<Geometry>::type;
|
||||||
typedef typename boost::range_size
|
using size_type = typename boost::range_size
|
||||||
<
|
<
|
||||||
typename util::remove_cptrref<Geometry>::type
|
typename util::remove_cptrref<Geometry>::type
|
||||||
>::type size_type;
|
>::type;
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(( util::is_ring<Geometry>::value ));
|
BOOST_STATIC_ASSERT((util::is_ring<Geometry>::value));
|
||||||
|
|
||||||
inline stateful_range_appender()
|
inline stateful_range_appender()
|
||||||
: pt_index(0)
|
: pt_index(0)
|
||||||
@ -290,11 +296,10 @@ struct stateful_range_appender<Geometry, open>
|
|||||||
if (pt_index == 0)
|
if (pt_index == 0)
|
||||||
{
|
{
|
||||||
first_point = point;
|
first_point = point;
|
||||||
//should_append = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOTE: if there is not enough Points, they're always appended
|
// NOTE: if there are not enough Points, they're always appended
|
||||||
should_append
|
should_append
|
||||||
= is_next_expected
|
= is_next_expected
|
||||||
|| pt_index < core_detail::closure::minimum_ring_size<open>::value
|
|| pt_index < core_detail::closure::minimum_ring_size<open>::value
|
||||||
@ -312,10 +317,10 @@ private:
|
|||||||
static inline bool disjoint(point_type const& p1, point_type const& p2)
|
static inline bool disjoint(point_type const& p1, point_type const& p2)
|
||||||
{
|
{
|
||||||
// TODO: pass strategy
|
// TODO: pass strategy
|
||||||
typedef typename strategies::io::services::default_strategy
|
using strategy_type = typename strategies::io::services::default_strategy
|
||||||
<
|
<
|
||||||
point_type
|
point_type
|
||||||
>::type strategy_type;
|
>::type;
|
||||||
|
|
||||||
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
|
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
|
||||||
}
|
}
|
||||||
@ -328,10 +333,11 @@ private:
|
|||||||
template <typename Geometry>
|
template <typename Geometry>
|
||||||
struct container_appender
|
struct container_appender
|
||||||
{
|
{
|
||||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
using point_type = typename geometry::point_type<Geometry>::type;
|
||||||
|
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Geometry out)
|
Geometry out)
|
||||||
{
|
{
|
||||||
@ -367,8 +373,9 @@ struct container_appender
|
|||||||
template <typename P>
|
template <typename P>
|
||||||
struct point_parser
|
struct point_parser
|
||||||
{
|
{
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
P& point)
|
P& point)
|
||||||
{
|
{
|
||||||
@ -382,8 +389,9 @@ struct point_parser
|
|||||||
template <typename Geometry>
|
template <typename Geometry>
|
||||||
struct linestring_parser
|
struct linestring_parser
|
||||||
{
|
{
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Geometry& geometry)
|
Geometry& geometry)
|
||||||
{
|
{
|
||||||
@ -395,8 +403,9 @@ struct linestring_parser
|
|||||||
template <typename Ring>
|
template <typename Ring>
|
||||||
struct ring_parser
|
struct ring_parser
|
||||||
{
|
{
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Ring& ring)
|
Ring& ring)
|
||||||
{
|
{
|
||||||
@ -417,11 +426,12 @@ struct ring_parser
|
|||||||
template <typename Polygon>
|
template <typename Polygon>
|
||||||
struct polygon_parser
|
struct polygon_parser
|
||||||
{
|
{
|
||||||
typedef typename ring_return_type<Polygon>::type ring_return_type;
|
using ring_return_type = typename ring_return_type<Polygon>::type;
|
||||||
typedef container_appender<ring_return_type> appender;
|
using appender = container_appender<ring_return_type>;
|
||||||
|
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Polygon& poly)
|
Polygon& poly)
|
||||||
{
|
{
|
||||||
@ -457,7 +467,8 @@ struct polygon_parser
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline bool one_of(tokenizer::iterator const& it,
|
template <typename TokenizerIterator>
|
||||||
|
inline bool one_of(TokenizerIterator const& it,
|
||||||
std::string const& value,
|
std::string const& value,
|
||||||
bool& is_present)
|
bool& is_present)
|
||||||
{
|
{
|
||||||
@ -469,7 +480,8 @@ inline bool one_of(tokenizer::iterator const& it,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool one_of(tokenizer::iterator const& it,
|
template <typename TokenizerIterator>
|
||||||
|
inline bool one_of(TokenizerIterator const& it,
|
||||||
std::string const& value,
|
std::string const& value,
|
||||||
bool& present1,
|
bool& present1,
|
||||||
bool& present2)
|
bool& present2)
|
||||||
@ -484,8 +496,9 @@ inline bool one_of(tokenizer::iterator const& it,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void handle_empty_z_m(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
inline void handle_empty_z_m(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
bool& has_empty,
|
bool& has_empty,
|
||||||
bool& has_z,
|
bool& has_z,
|
||||||
bool& has_m)
|
bool& has_m)
|
||||||
@ -535,9 +548,9 @@ struct dimension<Geometry, geometry_collection_tag>
|
|||||||
\brief Internal, starts parsing
|
\brief Internal, starts parsing
|
||||||
\param geometry_name string to compare with first token
|
\param geometry_name string to compare with first token
|
||||||
*/
|
*/
|
||||||
template <typename Geometry>
|
template <typename Geometry, typename TokenizerIterator>
|
||||||
inline bool initialize(tokenizer::iterator& it,
|
inline bool initialize(TokenizerIterator& it,
|
||||||
tokenizer::iterator const& end,
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
std::string const& geometry_name)
|
std::string const& geometry_name)
|
||||||
{
|
{
|
||||||
@ -552,8 +565,8 @@ inline bool initialize(tokenizer::iterator& it,
|
|||||||
|
|
||||||
// Silence warning C4127: conditional expression is constant
|
// Silence warning C4127: conditional expression is constant
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4127)
|
#pragma warning(disable : 4127)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (has_z && dimension<Geometry>::value < 3)
|
if (has_z && dimension<Geometry>::value < 3)
|
||||||
@ -570,7 +583,7 @@ inline bool initialize(tokenizer::iterator& it,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// M is ignored at all.
|
// M is ignored at all.
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,17 +595,18 @@ struct geometry_parser
|
|||||||
{
|
{
|
||||||
geometry::clear(geometry);
|
geometry::clear(geometry);
|
||||||
|
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
auto const tokens{make_tokenizer(wkt)};
|
||||||
tokenizer::iterator it = tokens.begin();
|
auto it = tokens.begin();
|
||||||
tokenizer::iterator const end = tokens.end();
|
auto const end = tokens.end();
|
||||||
|
|
||||||
apply(it, end, wkt, geometry);
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
check_end(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Geometry& geometry)
|
Geometry& geometry)
|
||||||
{
|
{
|
||||||
@ -611,17 +625,18 @@ struct multi_parser
|
|||||||
{
|
{
|
||||||
traits::clear<MultiGeometry>::apply(geometry);
|
traits::clear<MultiGeometry>::apply(geometry);
|
||||||
|
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
auto const tokens{make_tokenizer(wkt)};
|
||||||
tokenizer::iterator it = tokens.begin();
|
auto it = tokens.begin();
|
||||||
tokenizer::iterator const end = tokens.end();
|
auto const end = tokens.end();
|
||||||
|
|
||||||
apply(it, end, wkt, geometry);
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
check_end(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
MultiGeometry& geometry)
|
MultiGeometry& geometry)
|
||||||
{
|
{
|
||||||
@ -652,8 +667,9 @@ struct multi_parser
|
|||||||
template <typename P>
|
template <typename P>
|
||||||
struct noparenthesis_point_parser
|
struct noparenthesis_point_parser
|
||||||
{
|
{
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
P& point)
|
P& point)
|
||||||
{
|
{
|
||||||
@ -668,17 +684,18 @@ struct multi_point_parser
|
|||||||
{
|
{
|
||||||
traits::clear<MultiGeometry>::apply(geometry);
|
traits::clear<MultiGeometry>::apply(geometry);
|
||||||
|
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
auto const tokens{make_tokenizer(wkt)};
|
||||||
tokenizer::iterator it = tokens.begin();
|
auto it = tokens.begin();
|
||||||
tokenizer::iterator const end = tokens.end();
|
auto const end = tokens.end();
|
||||||
|
|
||||||
apply(it, end, wkt, geometry);
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
check_end(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
MultiGeometry& geometry)
|
MultiGeometry& geometry)
|
||||||
{
|
{
|
||||||
@ -735,17 +752,18 @@ struct box_parser
|
|||||||
{
|
{
|
||||||
static inline void apply(std::string const& wkt, Box& box)
|
static inline void apply(std::string const& wkt, Box& box)
|
||||||
{
|
{
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
auto const tokens{make_tokenizer(wkt)};
|
||||||
tokenizer::iterator it = tokens.begin();
|
auto it = tokens.begin();
|
||||||
tokenizer::iterator end = tokens.end();
|
auto end = tokens.end();
|
||||||
|
|
||||||
apply(it, end, wkt, box);
|
apply(it, end, wkt, box);
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
check_end(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Box& box)
|
Box& box)
|
||||||
{
|
{
|
||||||
@ -772,7 +790,7 @@ struct box_parser
|
|||||||
BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt));
|
BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef typename point_type<Box>::type point_type;
|
using point_type = typename point_type<Box>::type;
|
||||||
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));
|
||||||
|
|
||||||
@ -815,21 +833,24 @@ struct segment_parser
|
|||||||
{
|
{
|
||||||
static inline void apply(std::string const& wkt, Segment& segment)
|
static inline void apply(std::string const& wkt, Segment& segment)
|
||||||
{
|
{
|
||||||
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
auto const tokens{make_tokenizer(wkt)};
|
||||||
tokenizer::iterator it = tokens.begin();
|
auto it = tokens.begin();
|
||||||
tokenizer::iterator end = tokens.end();
|
auto end = tokens.end();
|
||||||
|
|
||||||
apply(it, end, wkt, segment);
|
apply(it, end, wkt, segment);
|
||||||
|
|
||||||
check_end(it, end, wkt);
|
check_end(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Segment& segment)
|
Segment& segment)
|
||||||
{
|
{
|
||||||
if (it != end && (boost::iequals(*it, "SEGMENT") || boost::iequals(*it, "LINESTRING")))
|
if (it != end
|
||||||
|
&& (boost::iequals(*it, prefix_segment::apply())
|
||||||
|
|| boost::iequals(*it, prefix_linestring::apply())))
|
||||||
{
|
{
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
@ -838,7 +859,7 @@ struct segment_parser
|
|||||||
BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt));
|
BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef typename point_type<Segment>::type point_type;
|
using point_type = typename point_type<Segment>::type;
|
||||||
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));
|
||||||
|
|
||||||
@ -881,54 +902,67 @@ template
|
|||||||
>
|
>
|
||||||
struct dynamic_readwkt_caller
|
struct dynamic_readwkt_caller
|
||||||
{
|
{
|
||||||
static inline void apply(tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Geometry& geometry)
|
Geometry& geometry)
|
||||||
{
|
{
|
||||||
if (boost::iequals(*it, "POINT"))
|
static const char* tag_point = prefix_point::apply();
|
||||||
|
static const char* tag_linestring = prefix_linestring::apply();
|
||||||
|
static const char* tag_polygon = prefix_polygon::apply();
|
||||||
|
|
||||||
|
static const char* tag_multi_point = prefix_multipoint::apply();
|
||||||
|
static const char* tag_multi_linestring = prefix_multilinestring::apply();
|
||||||
|
static const char* tag_multi_polygon = prefix_multipolygon::apply();
|
||||||
|
|
||||||
|
static const char* tag_segment = prefix_segment::apply();
|
||||||
|
static const char* tag_box = prefix_box::apply();
|
||||||
|
static const char* tag_gc = prefix_geometrycollection::apply();
|
||||||
|
|
||||||
|
if (boost::iequals(*it, tag_point))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_point>("POINT", it, end, wkt, geometry);
|
parse_geometry<util::is_point>(tag_point, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "MULTIPOINT"))
|
else if (boost::iequals(*it, tag_multi_point))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_multi_point>("MULTIPOINT", it, end, wkt, geometry);
|
parse_geometry<util::is_multi_point>(tag_multi_point, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "SEGMENT"))
|
else if (boost::iequals(*it, tag_segment))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_segment>("SEGMENT", it, end, wkt, geometry);
|
parse_geometry<util::is_segment>(tag_segment, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "LINESTRING"))
|
else if (boost::iequals(*it, tag_linestring))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_linestring>("LINESTRING", it, end, wkt, geometry, false)
|
parse_geometry<util::is_linestring>(tag_linestring, it, end, wkt, geometry, false)
|
||||||
|| parse_geometry<util::is_segment>("LINESTRING", it, end, wkt, geometry);
|
|| parse_geometry<util::is_segment>(tag_linestring, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "MULTILINESTRING"))
|
else if (boost::iequals(*it, tag_multi_linestring))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_multi_linestring>("MULTILINESTRING", it, end, wkt, geometry);
|
parse_geometry<util::is_multi_linestring>(tag_multi_linestring, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "BOX"))
|
else if (boost::iequals(*it, tag_box))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_box>("BOX", it, end, wkt, geometry);
|
parse_geometry<util::is_box>(tag_box, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "POLYGON"))
|
else if (boost::iequals(*it, tag_polygon))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_polygon>("POLYGON", it, end, wkt, geometry, false)
|
parse_geometry<util::is_polygon>(tag_polygon, it, end, wkt, geometry, false)
|
||||||
|| parse_geometry<util::is_ring>("POLYGON", it, end, wkt, geometry, false)
|
|| parse_geometry<util::is_ring>(tag_polygon, it, end, wkt, geometry, false)
|
||||||
|| parse_geometry<util::is_box>("POLYGON", it, end, wkt, geometry);
|
|| parse_geometry<util::is_box>(tag_polygon, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "MULTIPOLYGON"))
|
else if (boost::iequals(*it, tag_multi_polygon))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_multi_polygon>("MULTIPOLYGON", it, end, wkt, geometry);
|
parse_geometry<util::is_multi_polygon>(tag_multi_polygon, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else if (boost::iequals(*it, "GEOMETRYCOLLECTION"))
|
else if (boost::iequals(*it, tag_gc))
|
||||||
{
|
{
|
||||||
parse_geometry<util::is_geometry_collection>("GEOMETRYCOLLECTION", it, end, wkt, geometry);
|
parse_geometry<util::is_geometry_collection>(tag_gc, it, end, wkt, geometry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(read_wkt_exception(
|
BOOST_THROW_EXCEPTION(read_wkt_exception(
|
||||||
"Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.",
|
"Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'",
|
||||||
wkt));
|
wkt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -937,6 +971,7 @@ private:
|
|||||||
template
|
template
|
||||||
<
|
<
|
||||||
template <typename> class UnaryPred,
|
template <typename> class UnaryPred,
|
||||||
|
typename TokenizerIterator,
|
||||||
typename Geom = typename util::sequence_find_if
|
typename Geom = typename util::sequence_find_if
|
||||||
<
|
<
|
||||||
typename traits::geometry_types<Geometry>::type, UnaryPred
|
typename traits::geometry_types<Geometry>::type, UnaryPred
|
||||||
@ -944,8 +979,8 @@ private:
|
|||||||
std::enable_if_t<! std::is_void<Geom>::value, int> = 0
|
std::enable_if_t<! std::is_void<Geom>::value, int> = 0
|
||||||
>
|
>
|
||||||
static bool parse_geometry(const char * ,
|
static bool parse_geometry(const char * ,
|
||||||
tokenizer::iterator& it,
|
TokenizerIterator& it,
|
||||||
tokenizer::iterator const& end,
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Geometry& geometry,
|
Geometry& geometry,
|
||||||
bool = true)
|
bool = true)
|
||||||
@ -959,6 +994,7 @@ private:
|
|||||||
template
|
template
|
||||||
<
|
<
|
||||||
template <typename> class UnaryPred,
|
template <typename> class UnaryPred,
|
||||||
|
typename TokenizerIterator,
|
||||||
typename Geom = typename util::sequence_find_if
|
typename Geom = typename util::sequence_find_if
|
||||||
<
|
<
|
||||||
typename traits::geometry_types<Geometry>::type, UnaryPred
|
typename traits::geometry_types<Geometry>::type, UnaryPred
|
||||||
@ -966,8 +1002,8 @@ private:
|
|||||||
std::enable_if_t<std::is_void<Geom>::value, int> = 0
|
std::enable_if_t<std::is_void<Geom>::value, int> = 0
|
||||||
>
|
>
|
||||||
static bool parse_geometry(const char * name,
|
static bool parse_geometry(const char * name,
|
||||||
tokenizer::iterator& ,
|
TokenizerIterator& ,
|
||||||
tokenizer::iterator const& ,
|
TokenizerIterator const& ,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Geometry& ,
|
Geometry& ,
|
||||||
bool throw_on_misfit = true)
|
bool throw_on_misfit = true)
|
||||||
@ -1084,13 +1120,13 @@ struct read_wkt<DynamicGeometry, dynamic_geometry_tag>
|
|||||||
{
|
{
|
||||||
static inline void apply(std::string const& wkt, DynamicGeometry& dynamic_geometry)
|
static inline void apply(std::string const& wkt, DynamicGeometry& dynamic_geometry)
|
||||||
{
|
{
|
||||||
detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
auto tokens{detail::wkt::make_tokenizer(wkt)};
|
||||||
detail::wkt::tokenizer::iterator it = tokens.begin();
|
auto it = tokens.begin();
|
||||||
detail::wkt::tokenizer::iterator end = tokens.end();
|
auto end = tokens.end();
|
||||||
if (it == end)
|
if (it == end)
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(read_wkt_exception(
|
BOOST_THROW_EXCEPTION(read_wkt_exception(
|
||||||
"Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.",
|
"Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'",
|
||||||
wkt));
|
wkt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1111,21 +1147,23 @@ struct read_wkt<Geometry, geometry_collection_tag>
|
|||||||
{
|
{
|
||||||
range::clear(geometry);
|
range::clear(geometry);
|
||||||
|
|
||||||
detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
|
auto tokens{detail::wkt::make_tokenizer(wkt)};
|
||||||
detail::wkt::tokenizer::iterator it = tokens.begin();
|
auto it = tokens.begin();
|
||||||
detail::wkt::tokenizer::iterator const end = tokens.end();
|
auto const end = tokens.end();
|
||||||
|
|
||||||
apply(it, end, wkt, geometry);
|
apply(it, end, wkt, geometry);
|
||||||
|
|
||||||
detail::wkt::check_end(it, end, wkt);
|
detail::wkt::check_end(it, end, wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void apply(detail::wkt::tokenizer::iterator& it,
|
template <typename TokenizerIterator>
|
||||||
detail::wkt::tokenizer::iterator const& end,
|
static inline void apply(TokenizerIterator& it,
|
||||||
|
TokenizerIterator const& end,
|
||||||
std::string const& wkt,
|
std::string const& wkt,
|
||||||
Geometry& geometry)
|
Geometry& geometry)
|
||||||
{
|
{
|
||||||
if (detail::wkt::initialize<Geometry>(it, end, wkt, "GEOMETRYCOLLECTION"))
|
if (detail::wkt::initialize<Geometry>(it, end, wkt,
|
||||||
|
detail::wkt::prefix_geometrycollection::apply()))
|
||||||
{
|
{
|
||||||
detail::wkt::handle_open_parenthesis(it, end, wkt);
|
detail::wkt::handle_open_parenthesis(it, end, wkt);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2017 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2017 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2017 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2017 Mateusz Loskot, London, UK.
|
// Copyright (c) 2009-2017 Mateusz Loskot, London, UK.
|
||||||
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
|
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||||
@ -88,32 +88,6 @@ struct stream_coordinate<P, Count, Count>
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct prefix_linestring_par
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return "LINESTRING("; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prefix_ring_par_par
|
|
||||||
{
|
|
||||||
// Note, double parentheses are intentional, indicating WKT ring begin/end
|
|
||||||
static inline const char* apply() { return "POLYGON(("; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct opening_parenthesis
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return "("; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct closing_parenthesis
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return ")"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct double_closing_parenthesis
|
|
||||||
{
|
|
||||||
static inline const char* apply() { return "))"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Stream points as \ref WKT
|
\brief Stream points as \ref WKT
|
||||||
*/
|
*/
|
||||||
@ -131,14 +105,13 @@ struct wkt_point
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Stream ranges as WKT
|
\brief Stream ranges as WKT
|
||||||
\note policy is used to stream prefix/postfix, enabling derived classes to override this
|
|
||||||
*/
|
*/
|
||||||
template
|
template
|
||||||
<
|
<
|
||||||
typename Range,
|
typename Range,
|
||||||
bool ForceClosurePossible,
|
|
||||||
typename PrefixPolicy,
|
typename PrefixPolicy,
|
||||||
typename SuffixPolicy
|
bool ForceClosurePossible = false,
|
||||||
|
bool WriteDoubleBrackets = false
|
||||||
>
|
>
|
||||||
struct wkt_range
|
struct wkt_range
|
||||||
{
|
{
|
||||||
@ -146,52 +119,60 @@ struct wkt_range
|
|||||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||||
Range const& range, bool force_closure = ForceClosurePossible)
|
Range const& range, bool force_closure = ForceClosurePossible)
|
||||||
{
|
{
|
||||||
typedef typename boost::range_iterator<Range const>::type iterator_type;
|
using stream_type = stream_coordinate
|
||||||
|
|
||||||
typedef stream_coordinate
|
|
||||||
<
|
<
|
||||||
point_type, 0, dimension<point_type>::type::value
|
point_type, 0, dimension<point_type>::type::value
|
||||||
> stream_type;
|
>;
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
os << PrefixPolicy::apply();
|
os << PrefixPolicy::apply();
|
||||||
|
os << "(";
|
||||||
|
|
||||||
// TODO: check EMPTY here
|
if (boost::size(range) > 0)
|
||||||
|
|
||||||
iterator_type begin = boost::begin(range);
|
|
||||||
iterator_type end = boost::end(range);
|
|
||||||
for (iterator_type it = begin; it != end; ++it)
|
|
||||||
{
|
{
|
||||||
os << (first ? "" : ",");
|
if (WriteDoubleBrackets)
|
||||||
stream_type::apply(os, *it);
|
{
|
||||||
first = false;
|
os << "(";
|
||||||
|
}
|
||||||
|
auto begin = boost::begin(range);
|
||||||
|
auto end = boost::end(range);
|
||||||
|
for (auto it = begin; it != end; ++it)
|
||||||
|
{
|
||||||
|
os << (first ? "" : ",");
|
||||||
|
stream_type::apply(os, *it);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// optionally, close range to ring by repeating the first point
|
||||||
|
if (BOOST_GEOMETRY_CONDITION(ForceClosurePossible)
|
||||||
|
&& force_closure
|
||||||
|
&& boost::size(range) > 1
|
||||||
|
&& wkt_range::disjoint(*begin, *(end - 1)))
|
||||||
|
{
|
||||||
|
os << ",";
|
||||||
|
stream_type::apply(os, *begin);
|
||||||
|
}
|
||||||
|
if (WriteDoubleBrackets)
|
||||||
|
{
|
||||||
|
os << ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// optionally, close range to ring by repeating the first point
|
os << ")";
|
||||||
if (BOOST_GEOMETRY_CONDITION(ForceClosurePossible)
|
|
||||||
&& force_closure
|
|
||||||
&& boost::size(range) > 1
|
|
||||||
&& wkt_range::disjoint(*begin, *(end - 1)))
|
|
||||||
{
|
|
||||||
os << ",";
|
|
||||||
stream_type::apply(os, *begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
os << SuffixPolicy::apply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef typename boost::range_value<Range>::type point_type;
|
using point_type = typename boost::range_value<Range>::type;
|
||||||
|
|
||||||
static inline bool disjoint(point_type const& p1, point_type const& p2)
|
static inline bool disjoint(point_type const& p1, point_type const& p2)
|
||||||
{
|
{
|
||||||
// TODO: pass strategy
|
// TODO: pass strategy
|
||||||
typedef typename strategies::io::services::default_strategy
|
using strategy_type = typename strategies::io::services::default_strategy
|
||||||
<
|
<
|
||||||
point_type
|
point_type
|
||||||
>::type strategy_type;
|
>::type;
|
||||||
|
|
||||||
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
|
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
|
||||||
}
|
}
|
||||||
@ -206,9 +187,8 @@ struct wkt_sequence
|
|||||||
: wkt_range
|
: wkt_range
|
||||||
<
|
<
|
||||||
Range,
|
Range,
|
||||||
ForceClosurePossible,
|
prefix_null,
|
||||||
opening_parenthesis,
|
ForceClosurePossible
|
||||||
closing_parenthesis
|
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
@ -219,20 +199,29 @@ struct wkt_poly
|
|||||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||||
Polygon const& poly, bool force_closure)
|
Polygon const& poly, bool force_closure)
|
||||||
{
|
{
|
||||||
typedef typename ring_type<Polygon const>::type ring;
|
using ring = typename ring_type<Polygon const>::type;
|
||||||
|
|
||||||
|
auto const exterior = exterior_ring(poly);
|
||||||
|
auto const rings = interior_rings(poly);
|
||||||
|
|
||||||
|
std::size_t point_count = boost::size(exterior);
|
||||||
|
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||||
|
{
|
||||||
|
point_count += boost::size(*it);
|
||||||
|
}
|
||||||
|
|
||||||
os << PrefixPolicy::apply();
|
os << PrefixPolicy::apply();
|
||||||
// TODO: check EMPTY here
|
|
||||||
os << "(";
|
|
||||||
wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closure);
|
|
||||||
|
|
||||||
typename interior_return_type<Polygon const>::type
|
os << "(";
|
||||||
rings = interior_rings(poly);
|
if (point_count > 0)
|
||||||
for (typename detail::interior_iterator<Polygon const>::type
|
|
||||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
|
||||||
{
|
{
|
||||||
os << ",";
|
wkt_sequence<ring>::apply(os, exterior, force_closure);
|
||||||
wkt_sequence<ring>::apply(os, *it, force_closure);
|
|
||||||
|
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||||
|
{
|
||||||
|
os << ",";
|
||||||
|
wkt_sequence<ring>::apply(os, *it, force_closure);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
os << ")";
|
os << ")";
|
||||||
}
|
}
|
||||||
@ -247,13 +236,9 @@ struct wkt_multi
|
|||||||
Multi const& geometry, bool force_closure)
|
Multi const& geometry, bool force_closure)
|
||||||
{
|
{
|
||||||
os << PrefixPolicy::apply();
|
os << PrefixPolicy::apply();
|
||||||
// TODO: check EMPTY here
|
|
||||||
os << "(";
|
os << "(";
|
||||||
|
|
||||||
for (typename boost::range_iterator<Multi const>::type
|
for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
|
||||||
it = boost::begin(geometry);
|
|
||||||
it != boost::end(geometry);
|
|
||||||
++it)
|
|
||||||
{
|
{
|
||||||
if (it != boost::begin(geometry))
|
if (it != boost::begin(geometry))
|
||||||
{
|
{
|
||||||
@ -269,7 +254,7 @@ struct wkt_multi
|
|||||||
template <typename Box>
|
template <typename Box>
|
||||||
struct wkt_box
|
struct wkt_box
|
||||||
{
|
{
|
||||||
typedef typename point_type<Box>::type point_type;
|
using point_type = typename point_type<Box>::type;
|
||||||
|
|
||||||
template <typename Char, typename Traits>
|
template <typename Char, typename Traits>
|
||||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||||
@ -313,14 +298,14 @@ struct wkt_box
|
|||||||
template <typename Segment>
|
template <typename Segment>
|
||||||
struct wkt_segment
|
struct wkt_segment
|
||||||
{
|
{
|
||||||
typedef typename point_type<Segment>::type point_type;
|
using point_type = typename point_type<Segment>::type;
|
||||||
|
|
||||||
template <typename Char, typename Traits>
|
template <typename Char, typename Traits>
|
||||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||||
Segment const& segment, bool)
|
Segment const& segment, bool)
|
||||||
{
|
{
|
||||||
// Convert to two points, then stream
|
// Convert to two points, then stream
|
||||||
typedef boost::array<point_type, 2> sequence;
|
using sequence = boost::array<point_type, 2>;
|
||||||
|
|
||||||
sequence points;
|
sequence points;
|
||||||
geometry::detail::assign_point_from_index<0>(segment, points[0]);
|
geometry::detail::assign_point_from_index<0>(segment, points[0]);
|
||||||
@ -363,9 +348,7 @@ struct wkt<Linestring, linestring_tag>
|
|||||||
: detail::wkt::wkt_range
|
: detail::wkt::wkt_range
|
||||||
<
|
<
|
||||||
Linestring,
|
Linestring,
|
||||||
false,
|
detail::wkt::prefix_linestring
|
||||||
detail::wkt::prefix_linestring_par,
|
|
||||||
detail::wkt::closing_parenthesis
|
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
@ -395,9 +378,9 @@ struct wkt<Ring, ring_tag>
|
|||||||
: detail::wkt::wkt_range
|
: detail::wkt::wkt_range
|
||||||
<
|
<
|
||||||
Ring,
|
Ring,
|
||||||
|
detail::wkt::prefix_polygon,
|
||||||
true,
|
true,
|
||||||
detail::wkt::prefix_ring_par_par,
|
true
|
||||||
detail::wkt::double_closing_parenthesis
|
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
@ -14,8 +14,7 @@
|
|||||||
#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
|
#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
|
||||||
#define BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
|
#define BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
|
||||||
|
|
||||||
|
#include <boost/config/pragma_message.hpp>
|
||||||
#include <boost/geometry/io/wkt/detail/prefix.hpp>
|
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||||
|
|
||||||
|
|
||||||
#endif // BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
|
#endif // BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
|
||||||
|
@ -87,12 +87,12 @@ void test_all()
|
|||||||
"POLYGON EMPTY"
|
"POLYGON EMPTY"
|
||||||
|
|
||||||
, 0
|
, 0
|
||||||
, "POLYGON(())"
|
, "POLYGON()"
|
||||||
, "POLYGON(())"
|
, "POLYGON()"
|
||||||
|
|
||||||
, ""
|
, ""
|
||||||
, 0
|
, 0
|
||||||
, "POLYGON(())"
|
, "POLYGON()"
|
||||||
);
|
);
|
||||||
test_geometry<bg::model::ring<P, true, false> > // open ring
|
test_geometry<bg::model::ring<P, true, false> > // open ring
|
||||||
(
|
(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
// Unit Test
|
// Unit Test
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||||
|
|
||||||
@ -51,9 +51,8 @@ void check_wkt(G const& geometry, std::string const& expected)
|
|||||||
template <typename G>
|
template <typename G>
|
||||||
void check_to_wkt(G const& geometry, std::string const& expected)
|
void check_to_wkt(G const& geometry, std::string const& expected)
|
||||||
{
|
{
|
||||||
std::string out_string;
|
std::string const out = bg::to_wkt(geometry);
|
||||||
out_string = bg::to_wkt(geometry);
|
BOOST_CHECK_EQUAL(boost::to_upper_copy(out),
|
||||||
BOOST_CHECK_EQUAL(boost::to_upper_copy(out_string),
|
|
||||||
boost::to_upper_copy(expected));
|
boost::to_upper_copy(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +155,6 @@ void test_wkt(std::string const& wkt,
|
|||||||
template <typename G>
|
template <typename G>
|
||||||
void test_relaxed_wkt_read_write(std::string const& wkt, std::string const& expected)
|
void test_relaxed_wkt_read_write(std::string const& wkt, std::string const& expected)
|
||||||
{
|
{
|
||||||
std::string e;
|
|
||||||
G geometry;
|
G geometry;
|
||||||
bg::read_wkt(wkt, geometry);
|
bg::read_wkt(wkt, geometry);
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
@ -168,11 +166,9 @@ void test_relaxed_wkt_read_write(std::string const& wkt, std::string const& expe
|
|||||||
template <typename G>
|
template <typename G>
|
||||||
void test_relaxed_wkt_to_from(std::string const& wkt, std::string const& expected)
|
void test_relaxed_wkt_to_from(std::string const& wkt, std::string const& expected)
|
||||||
{
|
{
|
||||||
std::string e;
|
|
||||||
G geometry;
|
G geometry;
|
||||||
geometry = bg::from_wkt<G>(wkt);
|
geometry = bg::from_wkt<G>(wkt);
|
||||||
std::string out;
|
std::string const out = bg::to_wkt(geometry);
|
||||||
out = bg::to_wkt(geometry);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(boost::to_upper_copy(out), boost::to_upper_copy(expected));
|
BOOST_CHECK_EQUAL(boost::to_upper_copy(out), boost::to_upper_copy(expected));
|
||||||
}
|
}
|
||||||
@ -328,29 +324,32 @@ void test_all()
|
|||||||
//test_wkt<box<P> >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 4, 0, 1, 4);
|
//test_wkt<box<P> >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 4, 0, 1, 4);
|
||||||
test_wkt<bg::model::ring<P> >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 5, 0, 1, 4);
|
test_wkt<bg::model::ring<P> >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 5, 0, 1, 4);
|
||||||
|
|
||||||
// We accept empty sequences as well (much better than EMPTY)...
|
test_relaxed_wkt<bg::model::linestring<P> >("LINESTRING EMPTY", "LINESTRING()");
|
||||||
// ...or even POINT() (see below)
|
test_relaxed_wkt<bg::model::polygon<P> >("POLYGON EMPTY", "POLYGON()");
|
||||||
test_wkt<bg::model::linestring<P> >("LINESTRING()", 0, 0);
|
test_relaxed_wkt<bg::model::ring<P> >("POLYGON EMPTY", "POLYGON()");
|
||||||
test_wkt<bg::model::polygon<P> >("POLYGON(())", 0);
|
|
||||||
// ... or even with empty holes
|
|
||||||
test_wkt<bg::model::polygon<P> >("POLYGON((),(),())", 0);
|
|
||||||
// which all make no valid geometries, but they can exist.
|
|
||||||
|
|
||||||
|
// Accept empty sequences as well
|
||||||
|
test_relaxed_wkt<bg::model::linestring<P> >("LINESTRING()", "LINESTRING()");
|
||||||
|
test_relaxed_wkt<bg::model::polygon<P> >("POLYGON()", "POLYGON()");
|
||||||
|
test_relaxed_wkt<bg::model::polygon<P> >("POLYGON(())", "POLYGON()");
|
||||||
|
test_relaxed_wkt<bg::model::polygon<P> >("POLYGON((),(),())", "POLYGON()");
|
||||||
|
|
||||||
|
// Invalid polygon with an inner ring coordinate is outputted as such
|
||||||
|
test_relaxed_wkt<bg::model::polygon<P> >("POLYGON((),(),(1 2))", "POLYGON((),(),(1 2))");
|
||||||
|
|
||||||
|
// Non OGC: tabs and returns are allowed and handled as normal white space.
|
||||||
|
test_relaxed_wkt<P>("POINT(1\n2)", "POINT(1 2)");
|
||||||
|
test_relaxed_wkt<P>("POINT(1\t2)", "POINT(1 2)");
|
||||||
|
test_relaxed_wkt<P>("POINT(1\r2)", "POINT(1 2)");
|
||||||
|
|
||||||
// These WKT's are incomplete or abnormal but they are considered OK
|
// These WKT's are incomplete or abnormal but they are considered OK
|
||||||
test_relaxed_wkt<P>("POINT(1)", "POINT(1 0)");
|
test_relaxed_wkt<P>("POINT(1)", "POINT(1 0)");
|
||||||
test_relaxed_wkt<P>("POINT()", "POINT(0 0)");
|
test_relaxed_wkt<P>("POINT()", "POINT(0 0)");
|
||||||
test_relaxed_wkt<bg::model::linestring<P> >("LINESTRING(1,2,3)",
|
test_relaxed_wkt<bg::model::linestring<P> >("LINESTRING(1,2,3)", "LINESTRING(1 0,2 0,3 0)");
|
||||||
"LINESTRING(1 0,2 0,3 0)");
|
|
||||||
test_relaxed_wkt<P>("POINT ( 1 2) ", "POINT(1 2)");
|
test_relaxed_wkt<P>("POINT ( 1 2) ", "POINT(1 2)");
|
||||||
test_relaxed_wkt<P>("POINT M ( 1 2)", "POINT(1 2)");
|
test_relaxed_wkt<P>("POINT M ( 1 2)", "POINT(1 2)");
|
||||||
test_relaxed_wkt<bg::model::box<P> >("BOX(1 1,2 2)", "POLYGON((1 1,1 2,2 2,2 1,1 1))");
|
test_relaxed_wkt<bg::model::box<P> >("BOX(1 1,2 2)", "POLYGON((1 1,1 2,2 2,2 1,1 1))");
|
||||||
|
test_relaxed_wkt<bg::model::polygon<P> >("POLYGON( ( ) , ( ) , ( ) )", "POLYGON()");
|
||||||
test_relaxed_wkt<bg::model::linestring<P> >("LINESTRING EMPTY", "LINESTRING()");
|
|
||||||
|
|
||||||
test_relaxed_wkt<bg::model::polygon<P> >("POLYGON( ( ) , ( ) , ( ) )",
|
|
||||||
"POLYGON((),(),())");
|
|
||||||
|
|
||||||
// Wrong WKT's
|
// Wrong WKT's
|
||||||
test_wrong_wkt<P>("POINT(1 2", "expected ')'");
|
test_wrong_wkt<P>("POINT(1 2", "expected ')'");
|
||||||
@ -398,33 +397,3 @@ int test_main(int, char* [])
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Results can be checked in PostGIS by query below,
|
|
||||||
or by MySQL (but replace length by glength and remove the perimeter)
|
|
||||||
|
|
||||||
Note:
|
|
||||||
- PostGIS gives "3" for a numpoints of a multi-linestring of 6 points in total (!)
|
|
||||||
--> "npoints" should be taken for all geometries
|
|
||||||
- SQL Server 2008 gives "6"
|
|
||||||
select geometry::STGeomFromText('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))',0).STNumPoints()
|
|
||||||
- MySQL gives "NULL"
|
|
||||||
|
|
||||||
select 1 as code,'np p' as header,npoints(geomfromtext('POINT(1 2)')) as contents
|
|
||||||
union select 2,'length point', length(geomfromtext('POINT(1 2)'))
|
|
||||||
union select 3,'peri point', perimeter(geomfromtext('POINT(1 2)'))
|
|
||||||
union select 4,'area point',area(geomfromtext('POINT(1 2)'))
|
|
||||||
|
|
||||||
|
|
||||||
union select 5,'# ls',npoints(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
|
|
||||||
union select 6,'length ls',length(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
|
|
||||||
union select 7,'peri ls',perimeter(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
|
|
||||||
union select 8,'aera ls',area(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
|
|
||||||
|
|
||||||
union select 9,'# poly',npoints(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
|
|
||||||
union select 10,'length poly',length(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
|
|
||||||
union select 11,'peri poly',perimeter(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
|
|
||||||
union select 12,'area poly',area(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
// Unit Test
|
// Unit Test
|
||||||
|
|
||||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||||
|
|
||||||
@ -76,6 +76,18 @@ void test_all()
|
|||||||
test_wkt<bg::model::multi_linestring<bg::model::linestring<P> > >("multilinestring((1 1,2 2,3 3),(4 4,5 5,6 6))", 6, 4 * sqrt(2.0));
|
test_wkt<bg::model::multi_linestring<bg::model::linestring<P> > >("multilinestring((1 1,2 2,3 3),(4 4,5 5,6 6))", 6, 4 * sqrt(2.0));
|
||||||
test_wkt<bg::model::multi_polygon<bg::model::polygon<P> > >("multipolygon(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))", 15, 0, 21, 28);
|
test_wkt<bg::model::multi_polygon<bg::model::polygon<P> > >("multipolygon(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))", 15, 0, 21, 28);
|
||||||
|
|
||||||
|
// Support tabs, and new lines.
|
||||||
|
test_relaxed_wkt<bg::model::multi_point<P> >("multipoint((1\t2),\n(3\r4))", "multipoint((1 2),(3 4))");
|
||||||
|
|
||||||
|
// Verify empty multi geometries
|
||||||
|
test_relaxed_wkt<bg::model::multi_point<P> >("multipoint()", "multipoint()");
|
||||||
|
test_relaxed_wkt<bg::model::multi_linestring<bg::model::linestring<P> >>("multilinestring()", "multilinestring()");
|
||||||
|
test_relaxed_wkt<bg::model::multi_polygon<bg::model::polygon<P> > >("multipolygon()", "multipolygon()");
|
||||||
|
|
||||||
|
test_relaxed_wkt<bg::model::multi_point<P> >("multipoint empty", "multipoint()");
|
||||||
|
test_relaxed_wkt<bg::model::multi_linestring<bg::model::linestring<P> >>("multilinestring empty", "multilinestring()");
|
||||||
|
test_relaxed_wkt<bg::model::multi_polygon<bg::model::polygon<P> > >("multipolygon empty", "multipolygon()");
|
||||||
|
|
||||||
// Support for the official alternative syntax for multipoint
|
// Support for the official alternative syntax for multipoint
|
||||||
// (provided by Aleksey Tulinov):
|
// (provided by Aleksey Tulinov):
|
||||||
test_relaxed_wkt<bg::model::multi_point<P> >("multipoint(1 2,3 4)", "multipoint((1 2),(3 4))");
|
test_relaxed_wkt<bg::model::multi_point<P> >("multipoint(1 2,3 4)", "multipoint((1 2),(3 4))");
|
||||||
@ -103,24 +115,3 @@ void test_all()
|
|||||||
|
|
||||||
test_order_closure<T>();
|
test_order_closure<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
... see comments in "wkt.cpp"
|
|
||||||
|
|
||||||
union select 13,'# mpoint',npoints(geomfromtext('MULTIPOINT((1 2),(3 4))'))
|
|
||||||
union select 14,'length mpoint',length(geomfromtext('MULTIPOINT((1 2),(3 4))'))
|
|
||||||
union select 15,'peri mpoint',perimeter(geomfromtext('MULTIPOINT((1 2),(3 4))'))
|
|
||||||
union select 16,'area mpoint',area(geomfromtext('MULTIPOINT((1 2),(3 4))'))
|
|
||||||
|
|
||||||
union select 17,'# mls',npoints(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))'))
|
|
||||||
union select 18,'length mls',length(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))'))
|
|
||||||
union select 19,'peri mls',perimeter(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))'))
|
|
||||||
union select 20,'area mls',area(geomfromtext('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))'))
|
|
||||||
|
|
||||||
union select 21,'# mpoly',npoints(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))'))
|
|
||||||
union select 22,'length mpoly',length(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))'))
|
|
||||||
union select 23,'peri mpoly',perimeter(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))'))
|
|
||||||
union select 24,'area mpoly',area(geomfromtext('MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0),(1 1,1 2,2 2,2 1,1 1)),((0 0,0 4,4 4,4 0,0 0)))'))
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user