update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -5,9 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -25,9 +24,9 @@
#include <string>
#include <boost/concept_check.hpp>
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@@ -169,15 +168,11 @@ struct dsv_range
Range const& range,
dsv_settings const& settings)
{
typedef typename boost::range_iterator<Range const>::type iterator_type;
bool first = true;
os << settings.list_open;
for (iterator_type it = boost::begin(range);
it != boost::end(range);
++it)
for (auto it = boost::begin(range); it != boost::end(range); ++it)
{
os << (first ? "" : settings.point_separator)
<< settings.point_open;
@@ -217,10 +212,8 @@ struct dsv_poly
dsv_range<ring>::apply(os, exterior_ring(poly), settings);
typename interior_return_type<Polygon const>::type
rings = interior_rings(poly);
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
auto const& rings = interior_rings(poly);
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
os << settings.list_separator;
dsv_range<ring>::apply(os, *it, settings);
@@ -361,12 +354,6 @@ struct dsv_multi
typename boost::range_value<MultiGeometry>::type
> dispatch_one;
typedef typename boost::range_iterator
<
MultiGeometry const
>::type iterator;
template <typename Char, typename Traits>
static inline void apply(std::basic_ostream<Char, Traits>& os,
MultiGeometry const& multi,
@@ -375,9 +362,7 @@ struct dsv_multi
os << settings.list_open;
bool first = true;
for(iterator it = boost::begin(multi);
it != boost::end(multi);
++it, first = false)
for(auto it = boost::begin(multi); it != boost::end(multi); ++it, first = false)
{
os << (first ? "" : settings.list_separator);
dispatch_one::apply(os, *it, settings);

View File

@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015, 2016.
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -19,23 +19,18 @@
#define BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
#include <cstdio>
#include <memory>
#include <type_traits>
#include <vector>
#include <boost/config.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
@@ -61,11 +56,9 @@ namespace dispatch
template <typename GeometryTag, typename Geometry, typename SvgPoint>
struct svg_map
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (Geometry)
);
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not or not yet implemented for this Geometry type.",
GeometryTag, Geometry);
};
@@ -168,10 +161,7 @@ struct svg_map<multi_tag, Multi, SvgPoint>
std::string const& style, double size,
Multi const& multi, TransformStrategy const& strategy)
{
for (typename boost::range_iterator<Multi const>::type it
= boost::begin(multi);
it != boost::end(multi);
++it)
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
svg_map
<
@@ -201,7 +191,7 @@ struct devarianted_svg_map
typename tag<Geometry>::type,
multi_tag
>::type,
typename boost::remove_const<Geometry>::type,
typename std::remove_const<Geometry>::type,
SvgPoint
>::apply(stream, style, size, geometry, strategy);
}
@@ -298,39 +288,89 @@ class svg_mapper : boost::noncopyable
> transformer_type;
model::box<Point> m_bounding_box;
boost::scoped_ptr<transformer_type> m_matrix;
std::unique_ptr<transformer_type> m_matrix;
std::ostream& m_stream;
SvgCoordinateType m_width, m_height;
std::string m_width_height; // for <svg> tag only, defaults to 2x 100%
SvgCoordinateType const m_width;
SvgCoordinateType const m_height;
calculation_type const m_scale{1.0};
void scale_bounding_box()
{
if (m_scale != 1.0 && m_scale > 0)
{
// Zoom out (scale < 1) or zoom in (scale > 1).
// The default is 0.95, giving a small margin around geometries.
auto& b = m_bounding_box;
auto const w = geometry::get<1, 0>(b) - geometry::get<0, 0>(b);
auto const h = geometry::get<1, 1>(b) - geometry::get<0, 1>(b);
auto const& m = (std::max)(w, h) * (1.0 - m_scale);
geometry::set<0, 0>(b, geometry::get<0, 0>(b) - m);
geometry::set<0, 1>(b, geometry::get<0, 1>(b) - m);
geometry::set<1, 0>(b, geometry::get<1, 0>(b) + m);
geometry::set<1, 1>(b, geometry::get<1, 1>(b) + m);
}
}
void init_matrix()
{
if (! m_matrix)
{
scale_bounding_box();
m_matrix.reset(new transformer_type(m_bounding_box,
m_width, m_height));
m_stream << "<?xml version=\"1.0\" standalone=\"no\"?>"
<< std::endl
<< "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""
<< std::endl
<< "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
<< std::endl
<< "<svg " << m_width_height << " version=\"1.1\""
<< std::endl
<< "xmlns=\"http://www.w3.org/2000/svg\""
<< std::endl
<< "xmlns:xlink=\"http://www.w3.org/1999/xlink\""
<< ">"
<< std::endl;
}
}
void write_header(std::string const& width_height)
{
m_stream << "<?xml version=\"1.0\" standalone=\"no\"?>"
<< std::endl
<< "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""
<< std::endl
<< "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
<< std::endl
<< "<svg " << width_height << " version=\"1.1\""
<< std::endl
<< "xmlns=\"http://www.w3.org/2000/svg\""
<< std::endl
<< "xmlns:xlink=\"http://www.w3.org/1999/xlink\""
<< ">"
<< std::endl;
}
public :
/*!
\brief Constructor, initializing the SVG map. Opens and initializes the SVG.
\brief Constructor, initializing the SVG map. Opens and initializes the SVG.
Should be called explicitly.
\param stream Output stream, should be a stream already open
\param width Width of the SVG map (in SVG pixels)
\param height Height of the SVG map (in SVG pixels)
\param scale Scale factor of the automatically determined bounding box.
If the factor is less than 1.0, there will be a margin around the
geometries. A factor of 0.95 is often a convenient margin. If the
factor is more than 1.0, the SVG map is zoomed and not all
geometries will be visible.
\param width_height Optional information to increase width and/or height
*/
svg_mapper(std::ostream& stream
, SvgCoordinateType width
, SvgCoordinateType height
, calculation_type scale
, std::string const& width_height = "width=\"100%\" height=\"100%\"")
: m_stream(stream)
, m_width(width)
, m_height(height)
, m_scale(scale)
{
assign_inverse(m_bounding_box);
write_header(width_height);
}
/*!
\brief Constructor, initializing the SVG map. Opens and initializes the SVG.
Should be called explicitly.
\param stream Output stream, should be a stream already open
\param width Width of the SVG map (in SVG pixels)
@@ -344,9 +384,9 @@ public :
: m_stream(stream)
, m_width(width)
, m_height(height)
, m_width_height(width_height)
{
assign_inverse(m_bounding_box);
write_header(width_height);
}
/*!
@@ -424,19 +464,17 @@ public :
{
// Multi-line modus
std::vector<std::string> splitted;
boost::split(splitted, s, boost::is_any_of("\n"));
for (std::vector<std::string>::const_iterator it
= splitted.begin();
it != splitted.end();
++it, offset_y += lineheight)
std::vector<std::string> split;
boost::split(split, s, boost::is_any_of("\n"));
for (auto const& item : split)
{
m_stream
<< "<tspan x=\"" << get<0>(map_point) + offset_x
<< "\""
<< " y=\"" << get<1>(map_point) + offset_y
<< "\""
<< ">" << *it << "</tspan>";
<< ">" << item << "</tspan>";
offset_y += lineheight;
}
}
m_stream << "</text>" << std::endl;

View File

@@ -3,8 +3,8 @@
// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016.
// Modifications copyright (c) 2016, Oracle and/or its affiliates.
// This file was modified by Oracle on 2016-2020.
// Modifications copyright (c) 2016-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,18 +22,17 @@
#include <string>
#include <boost/config.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -98,7 +97,7 @@ struct svg_segment
ct y1 = geometry::get<0, 1>(segment);
ct x2 = geometry::get<1, 0>(segment);
ct y2 = geometry::get<1, 1>(segment);
os << "<line x1=\"" << x1 << "\" y1=\"" << y1
<< "\" x2=\"" << x2 << "\" y2=\"" << y2
<< "\" style=\"" << style << "\"/>";
@@ -116,15 +115,11 @@ struct svg_range
static inline void apply(std::basic_ostream<Char, Traits>& os,
Range const& range, std::string const& style, double)
{
typedef typename boost::range_iterator<Range const>::type iterator;
bool first = true;
os << "<" << Policy::prefix() << " points=\"";
for (iterator it = boost::begin(range);
it != boost::end(range);
++it, first = false)
for (auto it = boost::begin(range); it != boost::end(range); ++it, first = false)
{
os << (first ? "" : " " )
<< geometry::get<0>(*it)
@@ -145,15 +140,12 @@ struct svg_poly
Polygon const& polygon, std::string const& style, double)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef typename boost::range_iterator<ring_type const>::type iterator_type;
bool first = true;
os << "<g fill-rule=\"evenodd\"><path d=\"";
ring_type const& ring = geometry::exterior_ring(polygon);
for (iterator_type it = boost::begin(ring);
it != boost::end(ring);
++it, first = false)
for (auto it = boost::begin(ring); it != boost::end(ring); ++it, first = false)
{
os << (first ? "M" : " L") << " "
<< geometry::get<0>(*it)
@@ -163,15 +155,11 @@ struct svg_poly
// Inner rings:
{
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
for (typename detail::interior_iterator<Polygon const>::type
rit = boost::begin(rings); rit != boost::end(rings); ++rit)
auto const& rings = interior_rings(polygon);
for (auto rit = boost::begin(rings); rit != boost::end(rings); ++rit)
{
first = true;
for (typename detail::interior_ring_iterator<Polygon const>::type
it = boost::begin(*rit); it != boost::end(*rit);
++it, first = false)
for (auto it = boost::begin(*rit); it != boost::end(*rit); ++it, first = false)
{
os << (first ? "M" : " L") << " "
<< geometry::get<0>(*it)
@@ -208,14 +196,10 @@ struct svg_multi
static inline void apply(std::basic_ostream<Char, Traits>& os,
MultiGeometry const& multi, std::string const& style, double size)
{
for (typename boost::range_iterator<MultiGeometry const>::type
it = boost::begin(multi);
it != boost::end(multi);
++it)
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(os, *it, style, size);
}
}
};
@@ -240,11 +224,9 @@ static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct svg
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (Geometry)
);
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not or not yet implemented for this Geometry type.",
Geometry, Tag);
};
template <typename Point>

View File

@@ -1,6 +1,6 @@
// 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) 2009-2012 Mateusz Loskot, London, UK.
@@ -57,6 +57,20 @@ struct prefix_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
#endif

View File

@@ -1,6 +1,6 @@
// 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) 2009-2012 Mateusz Loskot, London, UK.
@@ -11,46 +11,13 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
#ifndef BOOST_GEOMETRY_IO_WKT_MULTI_HPP
#define BOOST_GEOMETRY_IO_WKT_MULTI_HPP
#include <boost/geometry/core/tags.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
{
#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
#endif // BOOST_GEOMETRY_IO_WKT_MULTI_HPP

View File

@@ -1,13 +1,13 @@
// 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) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2018.
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2020 Baidyanath Kundu, Haldia, India
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -23,18 +23,14 @@
#include <cstddef>
#include <string>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/mpl/if.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/tokenizer.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/append.hpp>
@@ -46,18 +42,27 @@
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/geometry_id.hpp>
#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For consistency with other functions
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/coordinate_cast.hpp>
#include <boost/geometry/io/wkt/detail/prefix.hpp>
#include <boost/geometry/strategies/io/cartesian.hpp>
#include <boost/geometry/strategies/io/geographic.hpp>
#include <boost/geometry/strategies/io/spherical.hpp>
#include <boost/geometry/util/coordinate_cast.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
@@ -110,19 +115,26 @@ private :
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,
std::size_t Dimension = 0,
std::size_t DimensionCount = geometry::dimension<Point>::value>
struct parsing_assigner
{
static inline void apply(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
Point& point,
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 ")"
bool finished = (it == end || *it == "," || *it == ")");
@@ -160,8 +172,9 @@ struct parsing_assigner
template <typename Point, std::size_t DimensionCount>
struct parsing_assigner<Point, DimensionCount, DimensionCount>
{
static inline void apply(tokenizer::iterator&,
tokenizer::iterator const&,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator&,
TokenizerIterator const&,
Point&,
std::string const&)
{
@@ -219,9 +232,9 @@ template <typename Point>
struct container_inserter
{
// Version with output iterator
template <typename OutputIterator>
static inline void apply(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator, typename OutputIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
OutputIterator out)
{
@@ -251,10 +264,8 @@ template <typename Geometry,
closure_selector Closure = closure<Geometry>::value>
struct stateful_range_appender
{
typedef typename geometry::point_type<Geometry>::type point_type;
// 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);
}
@@ -263,17 +274,13 @@ struct stateful_range_appender
template <typename Geometry>
struct stateful_range_appender<Geometry, open>
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename boost::range_size
using point_type = typename geometry::point_type<Geometry>::type;
using size_type = typename boost::range_size
<
typename util::bare_type<Geometry>::type
>::type size_type;
typename util::remove_cptrref<Geometry>::type
>::type;
BOOST_STATIC_ASSERT(( boost::is_same
<
typename tag<Geometry>::type,
ring_tag
>::value ));
BOOST_STATIC_ASSERT((util::is_ring<Geometry>::value));
inline stateful_range_appender()
: pt_index(0)
@@ -287,11 +294,10 @@ struct stateful_range_appender<Geometry, open>
if (pt_index == 0)
{
first_point = point;
//should_append = true;
}
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
= is_next_expected
|| pt_index < core_detail::closure::minimum_ring_size<open>::value
@@ -309,10 +315,10 @@ private:
static inline bool disjoint(point_type const& p1, point_type const& p2)
{
// TODO: pass strategy
typedef typename strategy::disjoint::services::default_strategy
using strategy_type = typename strategies::io::services::default_strategy
<
point_type, point_type
>::type strategy_type;
point_type
>::type;
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
}
@@ -325,10 +331,11 @@ private:
template <typename Geometry>
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,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Geometry out)
{
@@ -364,8 +371,9 @@ struct container_appender
template <typename P>
struct point_parser
{
static inline void apply(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
P& point)
{
@@ -379,8 +387,9 @@ struct point_parser
template <typename Geometry>
struct linestring_parser
{
static inline void apply(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
@@ -392,8 +401,9 @@ struct linestring_parser
template <typename Ring>
struct ring_parser
{
static inline void apply(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Ring& ring)
{
@@ -414,11 +424,12 @@ struct ring_parser
template <typename Polygon>
struct polygon_parser
{
typedef typename ring_return_type<Polygon>::type ring_return_type;
typedef container_appender<ring_return_type> appender;
using ring_return_type = typename ring_return_type<Polygon>::type;
using appender = container_appender<ring_return_type>;
static inline void apply(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Polygon& poly)
{
@@ -439,13 +450,7 @@ struct polygon_parser
{
typename ring_type<Polygon>::type ring;
appender::apply(it, end, wkt, ring);
traits::push_back
<
typename boost::remove_reference
<
typename traits::interior_mutable_type<Polygon>::type
>::type
>::apply(interior_rings(poly), ring);
range::push_back(geometry::interior_rings(poly), std::move(ring));
}
if (it != end && *it == ",")
@@ -460,7 +465,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,
bool& is_present)
{
@@ -472,7 +478,8 @@ inline bool one_of(tokenizer::iterator const& it,
return false;
}
inline bool one_of(tokenizer::iterator const& it,
template <typename TokenizerIterator>
inline bool one_of(TokenizerIterator const& it,
std::string const& value,
bool& present1,
bool& present2)
@@ -487,8 +494,9 @@ inline bool one_of(tokenizer::iterator const& it,
}
inline void handle_empty_z_m(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
inline void handle_empty_z_m(TokenizerIterator& it,
TokenizerIterator const& end,
bool& has_empty,
bool& has_z,
bool& has_m)
@@ -514,21 +522,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
\param tokens boost tokens, parsed with separator " " and keeping separator "()"
\param geometry string to compare with first token
\param geometry_name string to compare with first token
*/
template <typename Geometry>
inline bool initialize(tokenizer const& tokens,
std::string const& geometry_name,
template <typename Geometry, typename TokenizerIterator>
inline bool initialize(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
tokenizer::iterator& it,
tokenizer::iterator& end)
std::string const& geometry_name)
{
it = tokens.begin();
end = tokens.end();
if (it == end || ! boost::iequals(*it++, geometry_name))
{
BOOST_THROW_EXCEPTION(read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt));
@@ -540,11 +563,11 @@ inline bool initialize(tokenizer const& tokens,
// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4127)
#pragma warning(push)
#pragma warning(disable : 4127)
#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));
}
@@ -555,11 +578,10 @@ inline bool initialize(tokenizer const& tokens,
if (has_empty)
{
check_end(it, end, wkt);
return false;
}
// M is ignored at all.
return true;
}
@@ -571,12 +593,24 @@ struct geometry_parser
{
geometry::clear(geometry);
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
tokenizer::iterator it, end;
if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
auto const tokens{make_tokenizer(wkt)};
auto it = tokens.begin();
auto const end = tokens.end();
apply(it, end, wkt, geometry);
check_end(it, end, wkt);
}
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
if (initialize<Geometry>(it, end, wkt, PrefixPolicy::apply()))
{
Parser<Geometry>::apply(it, end, wkt, geometry);
check_end(it, end, wkt);
}
}
};
@@ -589,9 +623,22 @@ struct multi_parser
{
traits::clear<MultiGeometry>::apply(geometry);
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
tokenizer::iterator it, end;
if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
auto const tokens{make_tokenizer(wkt)};
auto it = tokens.begin();
auto const end = tokens.end();
apply(it, end, wkt, geometry);
check_end(it, end, wkt);
}
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
MultiGeometry& geometry)
{
if (initialize<MultiGeometry>(it, end, wkt, PrefixPolicy::apply()))
{
handle_open_parenthesis(it, end, wkt);
@@ -612,16 +659,15 @@ struct multi_parser
handle_close_parenthesis(it, end, wkt);
}
check_end(it, end, wkt);
}
};
template <typename P>
struct noparenthesis_point_parser
{
static inline void apply(tokenizer::iterator& it,
tokenizer::iterator const& end,
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
P& point)
{
@@ -636,10 +682,22 @@ struct multi_point_parser
{
traits::clear<MultiGeometry>::apply(geometry);
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
tokenizer::iterator it, end;
auto const tokens{make_tokenizer(wkt)};
auto it = tokens.begin();
auto const end = tokens.end();
if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
apply(it, end, wkt, geometry);
check_end(it, end, wkt);
}
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
MultiGeometry& geometry)
{
if (initialize<MultiGeometry>(it, end, wkt, PrefixPolicy::apply()))
{
handle_open_parenthesis(it, end, wkt);
@@ -675,8 +733,6 @@ struct multi_point_parser
handle_close_parenthesis(it, end, wkt);
}
check_end(it, end, wkt);
}
};
@@ -693,11 +749,23 @@ template <typename Box>
struct box_parser
{
static inline void apply(std::string const& wkt, Box& box)
{
auto const tokens{make_tokenizer(wkt)};
auto it = tokens.begin();
auto const end = tokens.end();
apply(it, end, wkt, box);
check_end(it, end, wkt);
}
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Box& box)
{
bool should_close = false;
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
tokenizer::iterator it = tokens.begin();
tokenizer::iterator end = tokens.end();
if (it != end && boost::iequals(*it, "POLYGON"))
{
++it;
@@ -720,7 +788,7 @@ struct box_parser
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;
container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
@@ -728,7 +796,6 @@ struct box_parser
{
handle_close_parenthesis(it, end, wkt);
}
check_end(it, end, wkt);
unsigned int index = 0;
std::size_t n = boost::size(points);
@@ -764,12 +831,24 @@ struct segment_parser
{
static inline void apply(std::string const& wkt, Segment& segment)
{
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
tokenizer::iterator it = tokens.begin();
tokenizer::iterator end = tokens.end();
if (it != end &&
(boost::iequals(*it, "SEGMENT")
|| boost::iequals(*it, "LINESTRING") ))
auto const tokens{make_tokenizer(wkt)};
auto it = tokens.begin();
auto const end = tokens.end();
apply(it, end, wkt, segment);
check_end(it, end, wkt);
}
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Segment& segment)
{
if (it != end
&& (boost::iequals(*it, prefix_segment::apply())
|| boost::iequals(*it, prefix_linestring::apply())))
{
++it;
}
@@ -778,12 +857,10 @@ struct segment_parser
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;
container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
check_end(it, end, wkt);
if (boost::size(points) == 2)
{
geometry::detail::assign_point_to_index<0>(points.front(), segment);
@@ -793,7 +870,149 @@ struct segment_parser
{
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
{
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
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>(tag_point, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_multi_point))
{
parse_geometry<util::is_multi_point>(tag_multi_point, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_segment))
{
parse_geometry<util::is_segment>(tag_segment, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_linestring))
{
parse_geometry<util::is_linestring>(tag_linestring, it, end, wkt, geometry, false)
|| parse_geometry<util::is_segment>(tag_linestring, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_multi_linestring))
{
parse_geometry<util::is_multi_linestring>(tag_multi_linestring, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_box))
{
parse_geometry<util::is_box>(tag_box, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_polygon))
{
parse_geometry<util::is_polygon>(tag_polygon, it, end, wkt, geometry, false)
|| parse_geometry<util::is_ring>(tag_polygon, it, end, wkt, geometry, false)
|| parse_geometry<util::is_box>(tag_polygon, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_multi_polygon))
{
parse_geometry<util::is_multi_polygon>(tag_multi_polygon, it, end, wkt, geometry);
}
else if (boost::iequals(*it, tag_gc))
{
parse_geometry<util::is_geometry_collection>(tag_gc, it, end, wkt, geometry);
}
else
{
BOOST_THROW_EXCEPTION(read_wkt_exception(
"Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'",
wkt));
}
}
private:
template
<
template <typename> class UnaryPred,
typename TokenizerIterator,
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 * ,
TokenizerIterator& it,
TokenizerIterator 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 TokenizerIterator,
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,
TokenizerIterator& ,
TokenizerIterator 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;
}
};
@@ -805,12 +1024,12 @@ struct segment_parser
namespace dispatch
{
template <typename Tag, typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct read_wkt {};
template <typename Point>
struct read_wkt<point_tag, Point>
struct read_wkt<Point, point_tag>
: detail::wkt::geometry_parser
<
Point,
@@ -821,7 +1040,7 @@ struct read_wkt<point_tag, Point>
template <typename L>
struct read_wkt<linestring_tag, L>
struct read_wkt<L, linestring_tag>
: detail::wkt::geometry_parser
<
L,
@@ -831,7 +1050,7 @@ struct read_wkt<linestring_tag, L>
{};
template <typename Ring>
struct read_wkt<ring_tag, Ring>
struct read_wkt<Ring, ring_tag>
: detail::wkt::geometry_parser
<
Ring,
@@ -841,7 +1060,7 @@ struct read_wkt<ring_tag, Ring>
{};
template <typename Geometry>
struct read_wkt<polygon_tag, Geometry>
struct read_wkt<Geometry, polygon_tag>
: detail::wkt::geometry_parser
<
Geometry,
@@ -852,7 +1071,7 @@ struct read_wkt<polygon_tag, Geometry>
template <typename MultiGeometry>
struct read_wkt<multi_point_tag, MultiGeometry>
struct read_wkt<MultiGeometry, multi_point_tag>
: detail::wkt::multi_point_parser
<
MultiGeometry,
@@ -861,7 +1080,7 @@ struct read_wkt<multi_point_tag, MultiGeometry>
{};
template <typename MultiGeometry>
struct read_wkt<multi_linestring_tag, MultiGeometry>
struct read_wkt<MultiGeometry, multi_linestring_tag>
: detail::wkt::multi_parser
<
MultiGeometry,
@@ -871,7 +1090,7 @@ struct read_wkt<multi_linestring_tag, MultiGeometry>
{};
template <typename MultiGeometry>
struct read_wkt<multi_polygon_tag, MultiGeometry>
struct read_wkt<MultiGeometry, multi_polygon_tag>
: detail::wkt::multi_parser
<
MultiGeometry,
@@ -883,17 +1102,90 @@ struct read_wkt<multi_polygon_tag, MultiGeometry>
// Box (Non-OGC)
template <typename Box>
struct read_wkt<box_tag, Box>
struct read_wkt<Box, box_tag>
: detail::wkt::box_parser<Box>
{};
// Segment (Non-OGC)
template <typename Segment>
struct read_wkt<segment_tag, Segment>
struct read_wkt<Segment, segment_tag>
: detail::wkt::segment_parser<Segment>
{};
template <typename DynamicGeometry>
struct read_wkt<DynamicGeometry, dynamic_geometry_tag>
{
static inline void apply(std::string const& wkt, DynamicGeometry& dynamic_geometry)
{
auto tokens{detail::wkt::make_tokenizer(wkt)};
auto it = tokens.begin();
auto const end = tokens.end();
if (it == end)
{
BOOST_THROW_EXCEPTION(read_wkt_exception(
"Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'",
wkt));
}
detail::wkt::dynamic_readwkt_caller
<
DynamicGeometry, dispatch::read_wkt, detail::wkt::dynamic_move_assign
>::apply(it, end, wkt, dynamic_geometry);
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);
auto tokens{detail::wkt::make_tokenizer(wkt)};
auto it = tokens.begin();
auto const end = tokens.end();
apply(it, end, wkt, geometry);
detail::wkt::check_end(it, end, wkt);
}
template <typename TokenizerIterator>
static inline void apply(TokenizerIterator& it,
TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
if (detail::wkt::initialize<Geometry>(it, end, wkt,
detail::wkt::prefix_geometrycollection::apply()))
{
detail::wkt::handle_open_parenthesis(it, end, wkt);
// 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);
}
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
@@ -910,7 +1202,24 @@ template <typename Geometry>
inline void read_wkt(std::string const& wkt, Geometry& geometry)
{
geometry::concepts::check<Geometry>();
dispatch::read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);
dispatch::read_wkt<Geometry>::apply(wkt, geometry);
}
/*!
\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry) and returns it
\ingroup wkt
\tparam Geometry \tparam_geometry
\param wkt string containing \ref WKT
\ingroup wkt
\qbk{[include reference/io/from_wkt.qbk]}
*/
template <typename Geometry>
inline Geometry from_wkt(std::string const& wkt)
{
Geometry geometry;
geometry::concepts::check<Geometry>();
dispatch::read_wkt<Geometry>::apply(wkt, geometry);
return geometry;
}
}} // namespace boost::geometry

View File

@@ -19,7 +19,7 @@
// BSG 2011-02-03
// We don't include stream.hpp by default. That tries to stream anything not known
// by default (such as ttmath) and reports errors.
// by default and reports errors.
// Users can include stream.hpp themselves (if they want to)
#endif // BOOST_GEOMETRY_IO_WKT_WKT_HPP

View File

@@ -1,14 +1,15 @@
// 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) 2009-2017 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// Copyright (c) 2014-2023 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2020 Baidyanath Kundu, Haldia, India.
// This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -20,17 +21,15 @@
#ifndef BOOST_GEOMETRY_IO_WKT_WRITE_HPP
#define BOOST_GEOMETRY_IO_WKT_WRITE_HPP
#include <array>
#include <ostream>
#include <string>
#include <boost/array.hpp>
#include <boost/range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
@@ -39,20 +38,29 @@
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/io/wkt/detail/prefix.hpp>
#include <boost/geometry/strategies/io/cartesian.hpp>
#include <boost/geometry/strategies/io/geographic.hpp>
#include <boost/geometry/strategies/io/spherical.hpp>
#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
// Silence warning C4512: 'boost::geometry::wkt_manipulator<Geometry>' : assignment operator could not be generated
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4512)
#pragma warning(push)
#pragma warning(disable : 4512)
#endif
#ifndef DOXYGEN_NO_DETAIL
@@ -78,32 +86,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
*/
@@ -121,14 +103,13 @@ struct wkt_point
/*!
\brief Stream ranges as WKT
\note policy is used to stream prefix/postfix, enabling derived classes to override this
*/
template
<
typename Range,
bool ForceClosurePossible,
typename PrefixPolicy,
typename SuffixPolicy
bool ForceClosurePossible = false,
bool WriteDoubleBrackets = false
>
struct wkt_range
{
@@ -136,52 +117,62 @@ struct wkt_range
static inline void apply(std::basic_ostream<Char, Traits>& os,
Range const& range, bool force_closure = ForceClosurePossible)
{
typedef typename boost::range_iterator<Range const>::type iterator_type;
typedef stream_coordinate
using stream_type = stream_coordinate
<
point_type, 0, dimension<point_type>::type::value
> stream_type;
>;
bool first = true;
os << PrefixPolicy::apply();
os << "(";
// TODO: check EMPTY here
iterator_type begin = boost::begin(range);
iterator_type end = boost::end(range);
for (iterator_type it = begin; it != end; ++it)
if (boost::size(range) > 0)
{
os << (first ? "" : ",");
stream_type::apply(os, *it);
first = false;
if BOOST_GEOMETRY_CONSTEXPR (WriteDoubleBrackets)
{
os << "(";
}
auto begin = boost::begin(range);
auto const 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_CONSTEXPR (ForceClosurePossible)
{
if (force_closure
&& boost::size(range) > 1
&& wkt_range::disjoint(*begin, *(end - 1)))
{
os << ",";
stream_type::apply(os, *begin);
}
}
if BOOST_GEOMETRY_CONSTEXPR (WriteDoubleBrackets)
{
os << ")";
}
}
// optionally, close range to ring by repeating the first point
if (ForceClosurePossible
&& force_closure
&& boost::size(range) > 1
&& wkt_range::disjoint(*begin, *(end - 1)))
{
os << ",";
stream_type::apply(os, *begin);
}
os << SuffixPolicy::apply();
os << ")";
}
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)
{
// TODO: pass strategy
typedef typename strategy::disjoint::services::default_strategy
using strategy_type = typename strategies::io::services::default_strategy
<
point_type, point_type
>::type strategy_type;
point_type
>::type;
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
}
@@ -196,9 +187,8 @@ struct wkt_sequence
: wkt_range
<
Range,
ForceClosurePossible,
opening_parenthesis,
closing_parenthesis
prefix_null,
ForceClosurePossible
>
{};
@@ -209,20 +199,29 @@ struct wkt_poly
static inline void apply(std::basic_ostream<Char, Traits>& os,
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();
// TODO: check EMPTY here
os << "(";
wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closure);
typename interior_return_type<Polygon const>::type
rings = interior_rings(poly);
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
os << "(";
if (point_count > 0)
{
os << ",";
wkt_sequence<ring>::apply(os, *it, force_closure);
wkt_sequence<ring>::apply(os, exterior, force_closure);
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
os << ",";
wkt_sequence<ring>::apply(os, *it, force_closure);
}
}
os << ")";
}
@@ -237,13 +236,9 @@ struct wkt_multi
Multi const& geometry, bool force_closure)
{
os << PrefixPolicy::apply();
// TODO: check EMPTY here
os << "(";
for (typename boost::range_iterator<Multi const>::type
it = boost::begin(geometry);
it != boost::end(geometry);
++it)
for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
if (it != boost::begin(geometry))
{
@@ -259,7 +254,7 @@ struct wkt_multi
template <typename 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>
static inline void apply(std::basic_ostream<Char, Traits>& os,
@@ -303,14 +298,14 @@ struct wkt_box
template <typename 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>
static inline void apply(std::basic_ostream<Char, Traits>& os,
Segment const& segment, bool)
{
// Convert to two points, then stream
typedef boost::array<point_type, 2> sequence;
using sequence = std::array<point_type, 2>;
sequence points;
geometry::detail::assign_point_from_index<0>(segment, points[0]);
@@ -353,9 +348,7 @@ struct wkt<Linestring, linestring_tag>
: detail::wkt::wkt_range
<
Linestring,
false,
detail::wkt::prefix_linestring_par,
detail::wkt::closing_parenthesis
detail::wkt::prefix_linestring
>
{};
@@ -385,9 +378,9 @@ struct wkt<Ring, ring_tag>
: detail::wkt::wkt_range
<
Ring,
detail::wkt::prefix_polygon,
true,
detail::wkt::prefix_ring_par_par,
detail::wkt::double_closing_parenthesis
true
>
{};
@@ -447,44 +440,66 @@ struct wkt<Multi, multi_polygon_tag>
template <typename Geometry>
struct devarianted_wkt
struct wkt<Geometry, dynamic_geometry_tag>
{
template <typename OutputStream>
static inline void apply(OutputStream& os, Geometry const& geometry,
bool force_closure)
{
wkt<Geometry>::apply(os, geometry, force_closure);
traits::visit<Geometry>::apply([&](auto const& g)
{
wkt<util::remove_cref_t<decltype(g)>>::apply(os, g, force_closure);
}, geometry);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
// TODO: Implement non-recursive version
template <typename Geometry>
struct wkt<Geometry, geometry_collection_tag>
{
template <typename OutputStream>
struct visitor: static_visitor<void>
static inline void apply(OutputStream& os, Geometry const& geometry,
bool force_closure)
{
OutputStream& m_os;
bool m_force_closure;
wkt::output_or_recursive_call(os, geometry, force_closure);
}
visitor(OutputStream& os, bool force_closure)
: m_os(os)
, m_force_closure(force_closure)
{}
private:
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(";
template <typename Geometry>
inline void operator()(Geometry const& geometry) const
bool first = true;
auto const end = boost::end(geom);
for (auto it = boost::begin(geom); it != end; ++it)
{
devarianted_wkt<Geometry>::apply(m_os, geometry, m_force_closure);
}
};
if (first)
first = false;
else
os << ',';
template <typename OutputStream>
static inline void apply(
OutputStream& os,
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
bool force_closure)
traits::iter_visit<Geom>::apply([&](auto const& g)
{
wkt::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)
{
boost::apply_visitor(visitor<OutputStream>(os, force_closure), geometry);
wkt<Geom>::apply(os, geom, force_closure);
}
};
@@ -506,7 +521,7 @@ Small example showing how to use the wkt class
template <typename Geometry>
class wkt_manipulator
{
static const bool is_ring = boost::is_same<typename tag<Geometry>::type, ring_tag>::value;
static const bool is_ring = util::is_ring<Geometry>::value;
public:
@@ -523,7 +538,7 @@ public:
std::basic_ostream<Char, Traits>& os,
wkt_manipulator const& m)
{
dispatch::devarianted_wkt<Geometry>::apply(os, m.m_geometry, m.m_force_closure);
dispatch::wkt<Geometry>::apply(os, m.m_geometry, m.m_force_closure);
os.flush();
return os;
}
@@ -548,8 +563,33 @@ inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)
return wkt_manipulator<Geometry>(geometry);
}
/*!
\brief WKT-string formulating function
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\param significant_digits Specifies the no of significant digits to use in the output wkt
\ingroup wkt
\qbk{[include reference/io/to_wkt.qbk]}
*/
template <typename Geometry>
inline std::string to_wkt(Geometry const& geometry)
{
std::stringstream ss;
ss << boost::geometry::wkt(geometry);
return ss.str();
}
template <typename Geometry>
inline std::string to_wkt(Geometry const& geometry, int significant_digits)
{
std::stringstream ss;
ss.precision(significant_digits);
ss << boost::geometry::wkt(geometry);
return ss.str();
}
#if defined(_MSC_VER)
#pragma warning(pop)
#pragma warning(pop)
#endif
}} // namespace boost::geometry