annotate DEPENDENCIES/generic/include/boost/geometry/io/wkt/write.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@16 4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
Chris@16 5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
Chris@101 6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
Chris@16 7
Chris@16 8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 10
Chris@16 11 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 13 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 14
Chris@16 15 #ifndef BOOST_GEOMETRY_IO_WKT_WRITE_HPP
Chris@16 16 #define BOOST_GEOMETRY_IO_WKT_WRITE_HPP
Chris@16 17
Chris@16 18 #include <ostream>
Chris@16 19 #include <string>
Chris@16 20
Chris@16 21 #include <boost/array.hpp>
Chris@16 22 #include <boost/range.hpp>
Chris@16 23
Chris@101 24 #include <boost/variant/apply_visitor.hpp>
Chris@101 25 #include <boost/variant/static_visitor.hpp>
Chris@101 26 #include <boost/variant/variant_fwd.hpp>
Chris@101 27
Chris@101 28 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
Chris@16 29 #include <boost/geometry/algorithms/assign.hpp>
Chris@16 30 #include <boost/geometry/algorithms/convert.hpp>
Chris@101 31 #include <boost/geometry/algorithms/disjoint.hpp>
Chris@16 32 #include <boost/geometry/algorithms/not_implemented.hpp>
Chris@16 33 #include <boost/geometry/core/exterior_ring.hpp>
Chris@16 34 #include <boost/geometry/core/interior_rings.hpp>
Chris@16 35 #include <boost/geometry/core/ring_type.hpp>
Chris@101 36 #include <boost/geometry/core/tags.hpp>
Chris@16 37
Chris@16 38 #include <boost/geometry/geometries/concepts/check.hpp>
Chris@16 39 #include <boost/geometry/geometries/ring.hpp>
Chris@16 40
Chris@16 41 #include <boost/geometry/io/wkt/detail/prefix.hpp>
Chris@16 42
Chris@16 43
Chris@16 44 namespace boost { namespace geometry
Chris@16 45 {
Chris@16 46
Chris@16 47 // Silence warning C4512: 'boost::geometry::wkt_manipulator<Geometry>' : assignment operator could not be generated
Chris@16 48 #if defined(_MSC_VER)
Chris@16 49 #pragma warning(push)
Chris@16 50 #pragma warning(disable : 4512)
Chris@16 51 #endif
Chris@16 52
Chris@16 53 #ifndef DOXYGEN_NO_DETAIL
Chris@16 54 namespace detail { namespace wkt
Chris@16 55 {
Chris@16 56
Chris@16 57 template <typename P, int I, int Count>
Chris@16 58 struct stream_coordinate
Chris@16 59 {
Chris@16 60 template <typename Char, typename Traits>
Chris@16 61 static inline void apply(std::basic_ostream<Char, Traits>& os, P const& p)
Chris@16 62 {
Chris@16 63 os << (I > 0 ? " " : "") << get<I>(p);
Chris@16 64 stream_coordinate<P, I + 1, Count>::apply(os, p);
Chris@16 65 }
Chris@16 66 };
Chris@16 67
Chris@16 68 template <typename P, int Count>
Chris@16 69 struct stream_coordinate<P, Count, Count>
Chris@16 70 {
Chris@16 71 template <typename Char, typename Traits>
Chris@16 72 static inline void apply(std::basic_ostream<Char, Traits>&, P const&)
Chris@16 73 {}
Chris@16 74 };
Chris@16 75
Chris@16 76 struct prefix_linestring_par
Chris@16 77 {
Chris@16 78 static inline const char* apply() { return "LINESTRING("; }
Chris@16 79 };
Chris@16 80
Chris@16 81 struct prefix_ring_par_par
Chris@16 82 {
Chris@16 83 // Note, double parentheses are intentional, indicating WKT ring begin/end
Chris@16 84 static inline const char* apply() { return "POLYGON(("; }
Chris@16 85 };
Chris@16 86
Chris@16 87 struct opening_parenthesis
Chris@16 88 {
Chris@16 89 static inline const char* apply() { return "("; }
Chris@16 90 };
Chris@16 91
Chris@16 92 struct closing_parenthesis
Chris@16 93 {
Chris@16 94 static inline const char* apply() { return ")"; }
Chris@16 95 };
Chris@16 96
Chris@16 97 struct double_closing_parenthesis
Chris@16 98 {
Chris@16 99 static inline const char* apply() { return "))"; }
Chris@16 100 };
Chris@16 101
Chris@16 102 /*!
Chris@16 103 \brief Stream points as \ref WKT
Chris@16 104 */
Chris@16 105 template <typename Point, typename Policy>
Chris@16 106 struct wkt_point
Chris@16 107 {
Chris@16 108 template <typename Char, typename Traits>
Chris@16 109 static inline void apply(std::basic_ostream<Char, Traits>& os, Point const& p)
Chris@16 110 {
Chris@16 111 os << Policy::apply() << "(";
Chris@16 112 stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p);
Chris@16 113 os << ")";
Chris@16 114 }
Chris@16 115 };
Chris@16 116
Chris@16 117 /*!
Chris@16 118 \brief Stream ranges as WKT
Chris@16 119 \note policy is used to stream prefix/postfix, enabling derived classes to override this
Chris@16 120 */
Chris@16 121 template <typename Range, typename PrefixPolicy, typename SuffixPolicy>
Chris@16 122 struct wkt_range
Chris@16 123 {
Chris@16 124 template <typename Char, typename Traits>
Chris@16 125 static inline void apply(std::basic_ostream<Char, Traits>& os,
Chris@101 126 Range const& range, bool force_closed)
Chris@16 127 {
Chris@16 128 typedef typename boost::range_iterator<Range const>::type iterator_type;
Chris@16 129
Chris@101 130 typedef stream_coordinate
Chris@101 131 <
Chris@101 132 point_type, 0, dimension<point_type>::type::value
Chris@101 133 > stream_type;
Chris@101 134
Chris@16 135 bool first = true;
Chris@16 136
Chris@16 137 os << PrefixPolicy::apply();
Chris@16 138
Chris@16 139 // TODO: check EMPTY here
Chris@16 140
Chris@101 141 iterator_type begin = boost::begin(range);
Chris@101 142 iterator_type end = boost::end(range);
Chris@101 143 for (iterator_type it = begin; it != end; ++it)
Chris@16 144 {
Chris@16 145 os << (first ? "" : ",");
Chris@101 146 stream_type::apply(os, *it);
Chris@16 147 first = false;
Chris@16 148 }
Chris@16 149
Chris@101 150 // optionally, close range to ring by repeating the first point
Chris@101 151 if (force_closed
Chris@101 152 && boost::size(range) > 1
Chris@101 153 && geometry::disjoint(*begin, *(end - 1)))
Chris@101 154 {
Chris@101 155 os << ",";
Chris@101 156 stream_type::apply(os, *begin);
Chris@101 157 }
Chris@101 158
Chris@16 159 os << SuffixPolicy::apply();
Chris@16 160 }
Chris@16 161
Chris@101 162 template <typename Char, typename Traits>
Chris@101 163 static inline void apply(std::basic_ostream<Char, Traits>& os,
Chris@101 164 Range const& range)
Chris@101 165 {
Chris@101 166 apply(os, range, false);
Chris@101 167 }
Chris@101 168
Chris@16 169 private:
Chris@16 170 typedef typename boost::range_value<Range>::type point_type;
Chris@16 171 };
Chris@16 172
Chris@16 173 /*!
Chris@16 174 \brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)
Chris@16 175 \note Used in polygon, all multi-geometries
Chris@16 176 */
Chris@16 177 template <typename Range>
Chris@16 178 struct wkt_sequence
Chris@16 179 : wkt_range
Chris@16 180 <
Chris@16 181 Range,
Chris@16 182 opening_parenthesis,
Chris@16 183 closing_parenthesis
Chris@16 184 >
Chris@16 185 {};
Chris@16 186
Chris@16 187 template <typename Polygon, typename PrefixPolicy>
Chris@16 188 struct wkt_poly
Chris@16 189 {
Chris@16 190 template <typename Char, typename Traits>
Chris@16 191 static inline void apply(std::basic_ostream<Char, Traits>& os,
Chris@16 192 Polygon const& poly)
Chris@16 193 {
Chris@16 194 typedef typename ring_type<Polygon const>::type ring;
Chris@101 195 bool const force_closed = true;
Chris@16 196
Chris@16 197 os << PrefixPolicy::apply();
Chris@16 198 // TODO: check EMPTY here
Chris@16 199 os << "(";
Chris@101 200 wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closed);
Chris@16 201
Chris@101 202 typename interior_return_type<Polygon const>::type
Chris@101 203 rings = interior_rings(poly);
Chris@101 204 for (typename detail::interior_iterator<Polygon const>::type
Chris@101 205 it = boost::begin(rings); it != boost::end(rings); ++it)
Chris@16 206 {
Chris@16 207 os << ",";
Chris@101 208 wkt_sequence<ring>::apply(os, *it, force_closed);
Chris@16 209 }
Chris@16 210 os << ")";
Chris@16 211 }
Chris@16 212 };
Chris@16 213
Chris@101 214 template <typename Multi, typename StreamPolicy, typename PrefixPolicy>
Chris@101 215 struct wkt_multi
Chris@101 216 {
Chris@101 217 template <typename Char, typename Traits>
Chris@101 218 static inline void apply(std::basic_ostream<Char, Traits>& os,
Chris@101 219 Multi const& geometry)
Chris@101 220 {
Chris@101 221 os << PrefixPolicy::apply();
Chris@101 222 // TODO: check EMPTY here
Chris@101 223 os << "(";
Chris@101 224
Chris@101 225 for (typename boost::range_iterator<Multi const>::type
Chris@101 226 it = boost::begin(geometry);
Chris@101 227 it != boost::end(geometry);
Chris@101 228 ++it)
Chris@101 229 {
Chris@101 230 if (it != boost::begin(geometry))
Chris@101 231 {
Chris@101 232 os << ",";
Chris@101 233 }
Chris@101 234 StreamPolicy::apply(os, *it);
Chris@101 235 }
Chris@101 236
Chris@101 237 os << ")";
Chris@101 238 }
Chris@101 239 };
Chris@101 240
Chris@16 241 template <typename Box>
Chris@16 242 struct wkt_box
Chris@16 243 {
Chris@16 244 typedef typename point_type<Box>::type point_type;
Chris@16 245
Chris@16 246 template <typename Char, typename Traits>
Chris@16 247 static inline void apply(std::basic_ostream<Char, Traits>& os,
Chris@16 248 Box const& box)
Chris@16 249 {
Chris@16 250 // Convert to ring, then stream
Chris@16 251 typedef model::ring<point_type> ring_type;
Chris@16 252 ring_type ring;
Chris@16 253 geometry::convert(box, ring);
Chris@16 254 os << "POLYGON(";
Chris@16 255 wkt_sequence<ring_type>::apply(os, ring);
Chris@16 256 os << ")";
Chris@16 257 }
Chris@16 258
Chris@16 259 private:
Chris@16 260
Chris@16 261 inline wkt_box()
Chris@16 262 {
Chris@16 263 // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
Chris@16 264 //assert_dimension<B, 2>();
Chris@16 265 }
Chris@16 266 };
Chris@16 267
Chris@16 268
Chris@16 269 template <typename Segment>
Chris@16 270 struct wkt_segment
Chris@16 271 {
Chris@16 272 typedef typename point_type<Segment>::type point_type;
Chris@16 273
Chris@16 274 template <typename Char, typename Traits>
Chris@16 275 static inline void apply(std::basic_ostream<Char, Traits>& os,
Chris@16 276 Segment const& segment)
Chris@16 277 {
Chris@16 278 // Convert to two points, then stream
Chris@16 279 typedef boost::array<point_type, 2> sequence;
Chris@16 280
Chris@16 281 sequence points;
Chris@16 282 geometry::detail::assign_point_from_index<0>(segment, points[0]);
Chris@16 283 geometry::detail::assign_point_from_index<1>(segment, points[1]);
Chris@16 284
Chris@16 285 // In Boost.Geometry a segment is represented
Chris@16 286 // in WKT-format like (for 2D): LINESTRING(x y,x y)
Chris@16 287 os << "LINESTRING";
Chris@16 288 wkt_sequence<sequence>::apply(os, points);
Chris@16 289 }
Chris@16 290
Chris@16 291 private:
Chris@16 292
Chris@16 293 inline wkt_segment()
Chris@16 294 {}
Chris@16 295 };
Chris@16 296
Chris@16 297 }} // namespace detail::wkt
Chris@16 298 #endif // DOXYGEN_NO_DETAIL
Chris@16 299
Chris@16 300 #ifndef DOXYGEN_NO_DISPATCH
Chris@16 301 namespace dispatch
Chris@16 302 {
Chris@16 303
Chris@16 304 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
Chris@16 305 struct wkt: not_implemented<Tag>
Chris@16 306 {};
Chris@16 307
Chris@16 308 template <typename Point>
Chris@16 309 struct wkt<Point, point_tag>
Chris@16 310 : detail::wkt::wkt_point
Chris@16 311 <
Chris@16 312 Point,
Chris@16 313 detail::wkt::prefix_point
Chris@16 314 >
Chris@16 315 {};
Chris@16 316
Chris@16 317 template <typename Linestring>
Chris@16 318 struct wkt<Linestring, linestring_tag>
Chris@16 319 : detail::wkt::wkt_range
Chris@16 320 <
Chris@16 321 Linestring,
Chris@16 322 detail::wkt::prefix_linestring_par,
Chris@16 323 detail::wkt::closing_parenthesis
Chris@16 324 >
Chris@16 325 {};
Chris@16 326
Chris@16 327 /*!
Chris@16 328 \brief Specialization to stream a box as WKT
Chris@16 329 \details A "box" does not exist in WKT.
Chris@16 330 It is therefore streamed as a polygon
Chris@16 331 */
Chris@16 332 template <typename Box>
Chris@16 333 struct wkt<Box, box_tag>
Chris@16 334 : detail::wkt::wkt_box<Box>
Chris@16 335 {};
Chris@16 336
Chris@16 337 template <typename Segment>
Chris@16 338 struct wkt<Segment, segment_tag>
Chris@16 339 : detail::wkt::wkt_segment<Segment>
Chris@16 340 {};
Chris@16 341
Chris@16 342 /*!
Chris@16 343 \brief Specialization to stream a ring as WKT
Chris@16 344 \details A ring or "linear_ring" does not exist in WKT.
Chris@16 345 A ring is equivalent to a polygon without inner rings
Chris@16 346 It is therefore streamed as a polygon
Chris@16 347 */
Chris@16 348 template <typename Ring>
Chris@16 349 struct wkt<Ring, ring_tag>
Chris@16 350 : detail::wkt::wkt_range
Chris@16 351 <
Chris@16 352 Ring,
Chris@16 353 detail::wkt::prefix_ring_par_par,
Chris@16 354 detail::wkt::double_closing_parenthesis
Chris@16 355 >
Chris@16 356 {};
Chris@16 357
Chris@16 358 /*!
Chris@16 359 \brief Specialization to stream polygon as WKT
Chris@16 360 */
Chris@16 361 template <typename Polygon>
Chris@16 362 struct wkt<Polygon, polygon_tag>
Chris@16 363 : detail::wkt::wkt_poly
Chris@16 364 <
Chris@16 365 Polygon,
Chris@16 366 detail::wkt::prefix_polygon
Chris@16 367 >
Chris@16 368 {};
Chris@16 369
Chris@101 370 template <typename Multi>
Chris@101 371 struct wkt<Multi, multi_point_tag>
Chris@101 372 : detail::wkt::wkt_multi
Chris@101 373 <
Chris@101 374 Multi,
Chris@101 375 detail::wkt::wkt_point
Chris@101 376 <
Chris@101 377 typename boost::range_value<Multi>::type,
Chris@101 378 detail::wkt::prefix_null
Chris@101 379 >,
Chris@101 380 detail::wkt::prefix_multipoint
Chris@101 381 >
Chris@101 382 {};
Chris@101 383
Chris@101 384 template <typename Multi>
Chris@101 385 struct wkt<Multi, multi_linestring_tag>
Chris@101 386 : detail::wkt::wkt_multi
Chris@101 387 <
Chris@101 388 Multi,
Chris@101 389 detail::wkt::wkt_sequence
Chris@101 390 <
Chris@101 391 typename boost::range_value<Multi>::type
Chris@101 392 >,
Chris@101 393 detail::wkt::prefix_multilinestring
Chris@101 394 >
Chris@101 395 {};
Chris@101 396
Chris@101 397 template <typename Multi>
Chris@101 398 struct wkt<Multi, multi_polygon_tag>
Chris@101 399 : detail::wkt::wkt_multi
Chris@101 400 <
Chris@101 401 Multi,
Chris@101 402 detail::wkt::wkt_poly
Chris@101 403 <
Chris@101 404 typename boost::range_value<Multi>::type,
Chris@101 405 detail::wkt::prefix_null
Chris@101 406 >,
Chris@101 407 detail::wkt::prefix_multipolygon
Chris@101 408 >
Chris@101 409 {};
Chris@101 410
Chris@16 411
Chris@16 412 template <typename Geometry>
Chris@16 413 struct devarianted_wkt
Chris@16 414 {
Chris@16 415 template <typename OutputStream>
Chris@16 416 static inline void apply(OutputStream& os, Geometry const& geometry)
Chris@16 417 {
Chris@16 418 wkt<Geometry>::apply(os, geometry);
Chris@16 419 }
Chris@16 420 };
Chris@16 421
Chris@16 422 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
Chris@16 423 struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
Chris@16 424 {
Chris@16 425 template <typename OutputStream>
Chris@16 426 struct visitor: static_visitor<void>
Chris@16 427 {
Chris@16 428 OutputStream& m_os;
Chris@16 429
Chris@16 430 visitor(OutputStream& os)
Chris@16 431 : m_os(os)
Chris@16 432 {}
Chris@16 433
Chris@16 434 template <typename Geometry>
Chris@16 435 inline void operator()(Geometry const& geometry) const
Chris@16 436 {
Chris@16 437 devarianted_wkt<Geometry>::apply(m_os, geometry);
Chris@16 438 }
Chris@16 439 };
Chris@16 440
Chris@16 441 template <typename OutputStream>
Chris@16 442 static inline void apply(
Chris@16 443 OutputStream& os,
Chris@16 444 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry
Chris@16 445 )
Chris@16 446 {
Chris@16 447 apply_visitor(visitor<OutputStream>(os), geometry);
Chris@16 448 }
Chris@16 449 };
Chris@16 450
Chris@16 451
Chris@16 452 } // namespace dispatch
Chris@16 453 #endif // DOXYGEN_NO_DISPATCH
Chris@16 454
Chris@16 455 /*!
Chris@16 456 \brief Generic geometry template manipulator class, takes corresponding output class from traits class
Chris@16 457 \ingroup wkt
Chris@16 458 \details Stream manipulator, streams geometry classes as \ref WKT streams
Chris@16 459 \par Example:
Chris@16 460 Small example showing how to use the wkt class
Chris@16 461 \dontinclude doxygen_1.cpp
Chris@16 462 \skip example_as_wkt_point
Chris@16 463 \line {
Chris@16 464 \until }
Chris@16 465 */
Chris@16 466 template <typename Geometry>
Chris@16 467 class wkt_manipulator
Chris@16 468 {
Chris@16 469 public:
Chris@16 470
Chris@16 471 inline wkt_manipulator(Geometry const& g)
Chris@16 472 : m_geometry(g)
Chris@16 473 {}
Chris@16 474
Chris@16 475 template <typename Char, typename Traits>
Chris@16 476 inline friend std::basic_ostream<Char, Traits>& operator<<(
Chris@16 477 std::basic_ostream<Char, Traits>& os,
Chris@16 478 wkt_manipulator const& m)
Chris@16 479 {
Chris@16 480 dispatch::devarianted_wkt<Geometry>::apply(os, m.m_geometry);
Chris@16 481 os.flush();
Chris@16 482 return os;
Chris@16 483 }
Chris@16 484
Chris@16 485 private:
Chris@16 486 Geometry const& m_geometry;
Chris@16 487 };
Chris@16 488
Chris@16 489 /*!
Chris@16 490 \brief Main WKT-streaming function
Chris@101 491 \tparam Geometry \tparam_geometry
Chris@101 492 \param geometry \param_geometry
Chris@16 493 \ingroup wkt
Chris@101 494 \qbk{[include reference/io/wkt.qbk]}
Chris@16 495 */
Chris@16 496 template <typename Geometry>
Chris@16 497 inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)
Chris@16 498 {
Chris@16 499 concept::check<Geometry const>();
Chris@16 500
Chris@16 501 return wkt_manipulator<Geometry>(geometry);
Chris@16 502 }
Chris@16 503
Chris@16 504 #if defined(_MSC_VER)
Chris@16 505 #pragma warning(pop)
Chris@16 506 #endif
Chris@16 507
Chris@16 508 }} // namespace boost::geometry
Chris@16 509
Chris@16 510 #endif // BOOST_GEOMETRY_IO_WKT_WRITE_HPP