/usr/include/boost/geometry/io/wkt
Edit: /usr/include/boost/geometry/io/wkt/write.hpp (15169B)
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2017 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, 2019.
// Modifications copyright (c) 2015-2019, 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.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_IO_WKT_WRITE_HPP
#define BOOST_GEOMETRY_IO_WKT_WRITE_HPP
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost { namespace geometry
{
// Silence warning C4512: 'boost::geometry::wkt_manipulator' : assignment operator could not be generated
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4512)
#endif
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace wkt
{
template
struct stream_coordinate
{
template
static inline void apply(std::basic_ostream& os, P const& p)
{
os << (I > 0 ? " " : "") << get(p);
stream_coordinate::apply(os, p);
}
};
template
struct stream_coordinate
{
template
static inline void apply(std::basic_ostream&, P const&)
{}
};
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
*/
template
struct wkt_point
{
template
static inline void apply(std::basic_ostream& os, Point const& p, bool)
{
os << Policy::apply() << "(";
stream_coordinate::type::value>::apply(os, p);
os << ")";
}
};
/*!
\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
>
struct wkt_range
{
template
static inline void apply(std::basic_ostream& os,
Range const& range, bool force_closure = ForceClosurePossible)
{
typedef typename boost::range_iterator::type iterator_type;
typedef stream_coordinate
<
point_type, 0, dimension::type::value
> stream_type;
bool first = true;
os << PrefixPolicy::apply();
// TODO: check EMPTY here
iterator_type begin = boost::begin(range);
iterator_type end = boost::end(range);
for (iterator_type 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);
}
os << SuffixPolicy::apply();
}
private:
typedef typename boost::range_value::type point_type;
static inline bool disjoint(point_type const& p1, point_type const& p2)
{
// TODO: pass strategy
typedef typename strategy::disjoint::services::default_strategy
<
point_type, point_type
>::type strategy_type;
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
}
};
/*!
\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)
\note Used in polygon, all multi-geometries
*/
template
struct wkt_sequence
: wkt_range
<
Range,
ForceClosurePossible,
opening_parenthesis,
closing_parenthesis
>
{};
template
struct wkt_poly
{
template
static inline void apply(std::basic_ostream& os,
Polygon const& poly, bool force_closure)
{
typedef typename ring_type::type ring;
os << PrefixPolicy::apply();
// TODO: check EMPTY here
os << "(";
wkt_sequence::apply(os, exterior_ring(poly), force_closure);
typename interior_return_type::type
rings = interior_rings(poly);
for (typename detail::interior_iterator::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
os << ",";
wkt_sequence::apply(os, *it, force_closure);
}
os << ")";
}
};
template
struct wkt_multi
{
template
static inline void apply(std::basic_ostream& os,
Multi const& geometry, bool force_closure)
{
os << PrefixPolicy::apply();
// TODO: check EMPTY here
os << "(";
for (typename boost::range_iterator::type
it = boost::begin(geometry);
it != boost::end(geometry);
++it)
{
if (it != boost::begin(geometry))
{
os << ",";
}
StreamPolicy::apply(os, *it, force_closure);
}
os << ")";
}
};
template
struct wkt_box
{
typedef typename point_type::type point_type;
template
static inline void apply(std::basic_ostream& os,
Box const& box, bool force_closure)
{
// Convert to a clockwire ring, then stream.
// Never close it based on last point (box might be empty and
// that should result in POLYGON((0 0,0 0,0 0,0 0, ...)) )
if (force_closure)
{
do_apply >(os, box);
}
else
{
do_apply >(os, box);
}
}
private:
inline wkt_box()
{
// Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
//assert_dimension();
}
template
static inline void do_apply(std::basic_ostream& os,
Box const& box)
{
RingType ring;
geometry::convert(box, ring);
os << "POLYGON(";
wkt_sequence::apply(os, ring);
os << ")";
}
};
template
struct wkt_segment
{
typedef typename point_type::type point_type;
template
static inline void apply(std::basic_ostream& os,
Segment const& segment, bool)
{
// Convert to two points, then stream
typedef boost::array sequence;
sequence points;
geometry::detail::assign_point_from_index<0>(segment, points[0]);
geometry::detail::assign_point_from_index<1>(segment, points[1]);
// In Boost.Geometry a segment is represented
// in WKT-format like (for 2D): LINESTRING(x y,x y)
os << "LINESTRING";
wkt_sequence::apply(os, points);
}
private:
inline wkt_segment()
{}
};
}} // namespace detail::wkt
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template ::type>
struct wkt: not_implemented
{};
template
struct wkt
: detail::wkt::wkt_point
<
Point,
detail::wkt::prefix_point
>
{};
template
struct wkt
: detail::wkt::wkt_range
<
Linestring,
false,
detail::wkt::prefix_linestring_par,
detail::wkt::closing_parenthesis
>
{};
/*!
\brief Specialization to stream a box as WKT
\details A "box" does not exist in WKT.
It is therefore streamed as a polygon
*/
template
struct wkt
: detail::wkt::wkt_box
{};
template
struct wkt
: detail::wkt::wkt_segment
{};
/*!
\brief Specialization to stream a ring as WKT
\details A ring or "linear_ring" does not exist in WKT.
A ring is equivalent to a polygon without inner rings
It is therefore streamed as a polygon
*/
template
struct wkt
: detail::wkt::wkt_range
<
Ring,
true,
detail::wkt::prefix_ring_par_par,
detail::wkt::double_closing_parenthesis
>
{};
/*!
\brief Specialization to stream polygon as WKT
*/
template
struct wkt
: detail::wkt::wkt_poly
<
Polygon,
detail::wkt::prefix_polygon
>
{};
template
struct wkt
: detail::wkt::wkt_multi
<
Multi,
detail::wkt::wkt_point
<
typename boost::range_value::type,
detail::wkt::prefix_null
>,
detail::wkt::prefix_multipoint
>
{};
template
struct wkt
: detail::wkt::wkt_multi
<
Multi,
detail::wkt::wkt_sequence
<
typename boost::range_value::type,
false
>,
detail::wkt::prefix_multilinestring
>
{};
template
struct wkt
: detail::wkt::wkt_multi
<
Multi,
detail::wkt::wkt_poly
<
typename boost::range_value::type,
detail::wkt::prefix_null
>,
detail::wkt::prefix_multipolygon
>
{};
template
struct devarianted_wkt
{
template
static inline void apply(OutputStream& os, Geometry const& geometry,
bool force_closure)
{
wkt::apply(os, geometry, force_closure);
}
};
template
struct devarianted_wkt >
{
template
struct visitor: static_visitor
{
OutputStream& m_os;
bool m_force_closure;
visitor(OutputStream& os, bool force_closure)
: m_os(os)
, m_force_closure(force_closure)
{}
template
inline void operator()(Geometry const& geometry) const
{
devarianted_wkt::apply(m_os, geometry, m_force_closure);
}
};
template
static inline void apply(
OutputStream& os,
variant const& geometry,
bool force_closure)
{
boost::apply_visitor(visitor(os, force_closure), geometry);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
/*!
\brief Generic geometry template manipulator class, takes corresponding output class from traits class
\ingroup wkt
\details Stream manipulator, streams geometry classes as \ref WKT streams
\par Example:
Small example showing how to use the wkt class
\dontinclude doxygen_1.cpp
\skip example_as_wkt_point
\line {
\until }
*/
template
class wkt_manipulator
{
static const bool is_ring = boost::is_same::type, ring_tag>::value;
public:
// Boost.Geometry, by default, closes polygons explictly, but not rings
// NOTE: this might change in the future!
inline wkt_manipulator(Geometry const& g,
bool force_closure = ! is_ring)
: m_geometry(g)
, m_force_closure(force_closure)
{}
template
inline friend std::basic_ostream& operator<<(
std::basic_ostream& os,
wkt_manipulator const& m)
{
dispatch::devarianted_wkt::apply(os, m.m_geometry, m.m_force_closure);
os.flush();
return os;
}
private:
Geometry const& m_geometry;
bool m_force_closure;
};
/*!
\brief Main WKT-streaming function
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\ingroup wkt
\qbk{[include reference/io/wkt.qbk]}
*/
template
inline wkt_manipulator wkt(Geometry const& geometry)
{
concepts::check();
return wkt_manipulator(geometry);
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_IO_WKT_WRITE_HPP