annotate DEPENDENCIES/generic/include/boost/geometry/io/wkt/read.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
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@16 6
Chris@16 7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 9
Chris@16 10 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 12 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 13
Chris@16 14 #ifndef BOOST_GEOMETRY_IO_WKT_READ_HPP
Chris@16 15 #define BOOST_GEOMETRY_IO_WKT_READ_HPP
Chris@16 16
Chris@16 17 #include <string>
Chris@16 18
Chris@16 19 #include <boost/lexical_cast.hpp>
Chris@16 20 #include <boost/tokenizer.hpp>
Chris@16 21
Chris@16 22 #include <boost/algorithm/string.hpp>
Chris@16 23 #include <boost/mpl/if.hpp>
Chris@16 24 #include <boost/range.hpp>
Chris@16 25
Chris@16 26 #include <boost/type_traits.hpp>
Chris@16 27
Chris@16 28 #include <boost/geometry/algorithms/assign.hpp>
Chris@16 29 #include <boost/geometry/algorithms/append.hpp>
Chris@16 30 #include <boost/geometry/algorithms/clear.hpp>
Chris@16 31
Chris@16 32 #include <boost/geometry/core/access.hpp>
Chris@16 33 #include <boost/geometry/core/coordinate_dimension.hpp>
Chris@16 34 #include <boost/geometry/core/exception.hpp>
Chris@16 35 #include <boost/geometry/core/exterior_ring.hpp>
Chris@16 36 #include <boost/geometry/core/geometry_id.hpp>
Chris@16 37 #include <boost/geometry/core/interior_rings.hpp>
Chris@16 38 #include <boost/geometry/core/mutable_range.hpp>
Chris@16 39
Chris@16 40 #include <boost/geometry/geometries/concepts/check.hpp>
Chris@16 41
Chris@16 42 #include <boost/geometry/util/coordinate_cast.hpp>
Chris@16 43
Chris@16 44 #include <boost/geometry/io/wkt/detail/prefix.hpp>
Chris@16 45
Chris@16 46 namespace boost { namespace geometry
Chris@16 47 {
Chris@16 48
Chris@16 49 /*!
Chris@16 50 \brief Exception showing things wrong with WKT parsing
Chris@16 51 \ingroup wkt
Chris@16 52 */
Chris@16 53 struct read_wkt_exception : public geometry::exception
Chris@16 54 {
Chris@16 55 template <typename Iterator>
Chris@16 56 read_wkt_exception(std::string const& msg,
Chris@16 57 Iterator const& it, Iterator const& end, std::string const& wkt)
Chris@16 58 : message(msg)
Chris@16 59 , wkt(wkt)
Chris@16 60 {
Chris@16 61 if (it != end)
Chris@16 62 {
Chris@16 63 source = " at '";
Chris@16 64 source += it->c_str();
Chris@16 65 source += "'";
Chris@16 66 }
Chris@16 67 complete = message + source + " in '" + wkt.substr(0, 100) + "'";
Chris@16 68 }
Chris@16 69
Chris@16 70 read_wkt_exception(std::string const& msg, std::string const& wkt)
Chris@16 71 : message(msg)
Chris@16 72 , wkt(wkt)
Chris@16 73 {
Chris@16 74 complete = message + "' in (" + wkt.substr(0, 100) + ")";
Chris@16 75 }
Chris@16 76
Chris@16 77 virtual ~read_wkt_exception() throw() {}
Chris@16 78
Chris@16 79 virtual const char* what() const throw()
Chris@16 80 {
Chris@16 81 return complete.c_str();
Chris@16 82 }
Chris@16 83 private :
Chris@16 84 std::string source;
Chris@16 85 std::string message;
Chris@16 86 std::string wkt;
Chris@16 87 std::string complete;
Chris@16 88 };
Chris@16 89
Chris@16 90
Chris@16 91 #ifndef DOXYGEN_NO_DETAIL
Chris@16 92 // (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostGIS))
Chris@16 93 namespace detail { namespace wkt
Chris@16 94 {
Chris@16 95
Chris@16 96 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
Chris@16 97
Chris@16 98 template <typename Point, std::size_t Dimension, std::size_t DimensionCount>
Chris@16 99 struct parsing_assigner
Chris@16 100 {
Chris@16 101 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 102 Point& point, std::string const& wkt)
Chris@16 103 {
Chris@16 104 typedef typename coordinate_type<Point>::type coordinate_type;
Chris@16 105
Chris@16 106 // Stop at end of tokens, or at "," ot ")"
Chris@16 107 bool finished = (it == end || *it == "," || *it == ")");
Chris@16 108
Chris@16 109 try
Chris@16 110 {
Chris@16 111 // Initialize missing coordinates to default constructor (zero)
Chris@16 112 // OR
Chris@16 113 // Use lexical_cast for conversion to double/int
Chris@16 114 // Note that it is much slower than atof. However, it is more standard
Chris@16 115 // and in parsing the change in performance falls probably away against
Chris@16 116 // the tokenizing
Chris@16 117 set<Dimension>(point, finished
Chris@16 118 ? coordinate_type()
Chris@16 119 : coordinate_cast<coordinate_type>::apply(*it));
Chris@16 120 }
Chris@16 121 catch(boost::bad_lexical_cast const& blc)
Chris@16 122 {
Chris@16 123 throw read_wkt_exception(blc.what(), it, end, wkt);
Chris@16 124 }
Chris@16 125 catch(std::exception const& e)
Chris@16 126 {
Chris@16 127 throw read_wkt_exception(e.what(), it, end, wkt);
Chris@16 128 }
Chris@16 129 catch(...)
Chris@16 130 {
Chris@16 131 throw read_wkt_exception("", it, end, wkt);
Chris@16 132 }
Chris@16 133
Chris@16 134 parsing_assigner<Point, Dimension + 1, DimensionCount>::apply(
Chris@16 135 (finished ? it : ++it), end, point, wkt);
Chris@16 136 }
Chris@16 137 };
Chris@16 138
Chris@16 139 template <typename Point, std::size_t DimensionCount>
Chris@16 140 struct parsing_assigner<Point, DimensionCount, DimensionCount>
Chris@16 141 {
Chris@16 142 static inline void apply(tokenizer::iterator&, tokenizer::iterator, Point&,
Chris@16 143 std::string const&)
Chris@16 144 {
Chris@16 145 }
Chris@16 146 };
Chris@16 147
Chris@16 148
Chris@16 149
Chris@16 150 template <typename Iterator>
Chris@16 151 inline void handle_open_parenthesis(Iterator& it,
Chris@16 152 Iterator const& end, std::string const& wkt)
Chris@16 153 {
Chris@16 154 if (it == end || *it != "(")
Chris@16 155 {
Chris@16 156 throw read_wkt_exception("Expected '('", it, end, wkt);
Chris@16 157 }
Chris@16 158 ++it;
Chris@16 159 }
Chris@16 160
Chris@16 161
Chris@16 162 template <typename Iterator>
Chris@16 163 inline void handle_close_parenthesis(Iterator& it,
Chris@16 164 Iterator const& end, std::string const& wkt)
Chris@16 165 {
Chris@16 166 if (it != end && *it == ")")
Chris@16 167 {
Chris@16 168 ++it;
Chris@16 169 }
Chris@16 170 else
Chris@16 171 {
Chris@16 172 throw read_wkt_exception("Expected ')'", it, end, wkt);
Chris@16 173 }
Chris@16 174 }
Chris@16 175
Chris@16 176 template <typename Iterator>
Chris@16 177 inline void check_end(Iterator& it,
Chris@16 178 Iterator const& end, std::string const& wkt)
Chris@16 179 {
Chris@16 180 if (it != end)
Chris@16 181 {
Chris@16 182 throw read_wkt_exception("Too much tokens", it, end, wkt);
Chris@16 183 }
Chris@16 184 }
Chris@16 185
Chris@16 186 /*!
Chris@16 187 \brief Internal, parses coordinate sequences, strings are formated like "(1 2,3 4,...)"
Chris@16 188 \param it token-iterator, should be pre-positioned at "(", is post-positions after last ")"
Chris@16 189 \param end end-token-iterator
Chris@16 190 \param out Output itererator receiving coordinates
Chris@16 191 */
Chris@16 192 template <typename Point>
Chris@16 193 struct container_inserter
Chris@16 194 {
Chris@16 195 // Version with output iterator
Chris@16 196 template <typename OutputIterator>
Chris@16 197 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 198 std::string const& wkt, OutputIterator out)
Chris@16 199 {
Chris@16 200 handle_open_parenthesis(it, end, wkt);
Chris@16 201
Chris@16 202 Point point;
Chris@16 203
Chris@16 204 // Parse points until closing parenthesis
Chris@16 205
Chris@16 206 while (it != end && *it != ")")
Chris@16 207 {
Chris@16 208 parsing_assigner
Chris@16 209 <
Chris@16 210 Point,
Chris@16 211 0,
Chris@16 212 dimension<Point>::value
Chris@16 213 >::apply(it, end, point, wkt);
Chris@16 214 out = point;
Chris@16 215 ++out;
Chris@16 216 if (it != end && *it == ",")
Chris@16 217 {
Chris@16 218 ++it;
Chris@16 219 }
Chris@16 220 }
Chris@16 221
Chris@16 222 handle_close_parenthesis(it, end, wkt);
Chris@16 223 }
Chris@16 224 };
Chris@16 225
Chris@16 226
Chris@16 227 // Geometry is a value-type or reference-type
Chris@16 228 template <typename Geometry>
Chris@16 229 struct container_appender
Chris@16 230 {
Chris@16 231 typedef typename geometry::point_type
Chris@16 232 <
Chris@16 233 typename boost::remove_reference<Geometry>::type
Chris@16 234 >::type point_type;
Chris@16 235
Chris@16 236 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 237 std::string const& wkt, Geometry out)
Chris@16 238 {
Chris@16 239 handle_open_parenthesis(it, end, wkt);
Chris@16 240
Chris@16 241 point_type point;
Chris@16 242
Chris@16 243 // Parse points until closing parenthesis
Chris@16 244
Chris@16 245 while (it != end && *it != ")")
Chris@16 246 {
Chris@16 247 parsing_assigner
Chris@16 248 <
Chris@16 249 point_type,
Chris@16 250 0,
Chris@16 251 dimension<point_type>::value
Chris@16 252 >::apply(it, end, point, wkt);
Chris@16 253
Chris@16 254 geometry::append(out, point);
Chris@16 255 if (it != end && *it == ",")
Chris@16 256 {
Chris@16 257 ++it;
Chris@16 258 }
Chris@16 259 }
Chris@16 260
Chris@16 261 handle_close_parenthesis(it, end, wkt);
Chris@16 262 }
Chris@16 263 };
Chris@16 264
Chris@16 265 /*!
Chris@16 266 \brief Internal, parses a point from a string like this "(x y)"
Chris@16 267 \note used for parsing points and multi-points
Chris@16 268 */
Chris@16 269 template <typename P>
Chris@16 270 struct point_parser
Chris@16 271 {
Chris@16 272 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 273 std::string const& wkt, P& point)
Chris@16 274 {
Chris@16 275 handle_open_parenthesis(it, end, wkt);
Chris@16 276 parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt);
Chris@16 277 handle_close_parenthesis(it, end, wkt);
Chris@16 278 }
Chris@16 279 };
Chris@16 280
Chris@16 281
Chris@16 282 template <typename Geometry>
Chris@16 283 struct linestring_parser
Chris@16 284 {
Chris@16 285 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 286 std::string const& wkt, Geometry& geometry)
Chris@16 287 {
Chris@16 288 container_appender<Geometry&>::apply(it, end, wkt, geometry);
Chris@16 289 }
Chris@16 290 };
Chris@16 291
Chris@16 292
Chris@16 293 template <typename Ring>
Chris@16 294 struct ring_parser
Chris@16 295 {
Chris@16 296 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 297 std::string const& wkt, Ring& ring)
Chris@16 298 {
Chris@16 299 // A ring should look like polygon((x y,x y,x y...))
Chris@16 300 // So handle the extra opening/closing parentheses
Chris@16 301 // and in between parse using the container-inserter
Chris@16 302 handle_open_parenthesis(it, end, wkt);
Chris@16 303 container_appender<Ring&>::apply(it, end, wkt, ring);
Chris@16 304 handle_close_parenthesis(it, end, wkt);
Chris@16 305 }
Chris@16 306 };
Chris@16 307
Chris@16 308
Chris@16 309
Chris@16 310
Chris@16 311 /*!
Chris@16 312 \brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))"
Chris@16 313 \note used for parsing polygons and multi-polygons
Chris@16 314 */
Chris@16 315 template <typename Polygon>
Chris@16 316 struct polygon_parser
Chris@16 317 {
Chris@16 318 typedef typename ring_return_type<Polygon>::type ring_return_type;
Chris@16 319 typedef container_appender<ring_return_type> appender;
Chris@16 320
Chris@16 321 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 322 std::string const& wkt, Polygon& poly)
Chris@16 323 {
Chris@16 324
Chris@16 325 handle_open_parenthesis(it, end, wkt);
Chris@16 326
Chris@16 327 int n = -1;
Chris@16 328
Chris@16 329 // Stop at ")"
Chris@16 330 while (it != end && *it != ")")
Chris@16 331 {
Chris@16 332 // Parse ring
Chris@16 333 if (++n == 0)
Chris@16 334 {
Chris@16 335 appender::apply(it, end, wkt, exterior_ring(poly));
Chris@16 336 }
Chris@16 337 else
Chris@16 338 {
Chris@16 339 typename ring_type<Polygon>::type ring;
Chris@16 340 appender::apply(it, end, wkt, ring);
Chris@16 341 traits::push_back
Chris@16 342 <
Chris@16 343 typename boost::remove_reference
Chris@16 344 <
Chris@16 345 typename traits::interior_mutable_type<Polygon>::type
Chris@16 346 >::type
Chris@16 347 >::apply(interior_rings(poly), ring);
Chris@16 348 }
Chris@16 349
Chris@16 350 if (it != end && *it == ",")
Chris@16 351 {
Chris@16 352 // Skip "," after ring is parsed
Chris@16 353 ++it;
Chris@16 354 }
Chris@16 355 }
Chris@16 356
Chris@16 357 handle_close_parenthesis(it, end, wkt);
Chris@16 358 }
Chris@16 359 };
Chris@16 360
Chris@16 361 inline bool one_of(tokenizer::iterator const& it, std::string const& value,
Chris@16 362 bool& is_present)
Chris@16 363 {
Chris@16 364 if (boost::iequals(*it, value))
Chris@16 365 {
Chris@16 366 is_present = true;
Chris@16 367 return true;
Chris@16 368 }
Chris@16 369 return false;
Chris@16 370 }
Chris@16 371
Chris@16 372 inline bool one_of(tokenizer::iterator const& it, std::string const& value,
Chris@16 373 bool& present1, bool& present2)
Chris@16 374 {
Chris@16 375 if (boost::iequals(*it, value))
Chris@16 376 {
Chris@16 377 present1 = true;
Chris@16 378 present2 = true;
Chris@16 379 return true;
Chris@16 380 }
Chris@16 381 return false;
Chris@16 382 }
Chris@16 383
Chris@16 384
Chris@16 385 inline void handle_empty_z_m(tokenizer::iterator& it, tokenizer::iterator end,
Chris@16 386 bool& has_empty, bool& has_z, bool& has_m)
Chris@16 387 {
Chris@16 388 has_empty = false;
Chris@16 389 has_z = false;
Chris@16 390 has_m = false;
Chris@16 391
Chris@16 392 // WKT can optionally have Z and M (measured) values as in
Chris@16 393 // POINT ZM (1 1 5 60), POINT M (1 1 80), POINT Z (1 1 5)
Chris@16 394 // GGL supports any of them as coordinate values, but is not aware
Chris@16 395 // of any Measured value.
Chris@16 396 while (it != end
Chris@16 397 && (one_of(it, "M", has_m)
Chris@16 398 || one_of(it, "Z", has_z)
Chris@16 399 || one_of(it, "EMPTY", has_empty)
Chris@16 400 || one_of(it, "MZ", has_m, has_z)
Chris@16 401 || one_of(it, "ZM", has_z, has_m)
Chris@16 402 )
Chris@16 403 )
Chris@16 404 {
Chris@16 405 ++it;
Chris@16 406 }
Chris@16 407 }
Chris@16 408
Chris@16 409 /*!
Chris@16 410 \brief Internal, starts parsing
Chris@16 411 \param tokens boost tokens, parsed with separator " " and keeping separator "()"
Chris@16 412 \param geometry string to compare with first token
Chris@16 413 */
Chris@16 414 template <typename Geometry>
Chris@16 415 inline bool initialize(tokenizer const& tokens,
Chris@16 416 std::string const& geometry_name, std::string const& wkt,
Chris@16 417 tokenizer::iterator& it)
Chris@16 418 {
Chris@16 419 it = tokens.begin();
Chris@16 420 if (it != tokens.end() && boost::iequals(*it++, geometry_name))
Chris@16 421 {
Chris@16 422 bool has_empty, has_z, has_m;
Chris@16 423
Chris@16 424 handle_empty_z_m(it, tokens.end(), has_empty, has_z, has_m);
Chris@16 425
Chris@16 426 // Silence warning C4127: conditional expression is constant
Chris@16 427 #if defined(_MSC_VER)
Chris@16 428 #pragma warning(push)
Chris@16 429 #pragma warning(disable : 4127)
Chris@16 430 #endif
Chris@16 431
Chris@16 432 if (has_z && dimension<Geometry>::type::value < 3)
Chris@16 433 {
Chris@16 434 throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt);
Chris@16 435 }
Chris@16 436
Chris@16 437 #if defined(_MSC_VER)
Chris@16 438 #pragma warning(pop)
Chris@16 439 #endif
Chris@16 440
Chris@16 441 if (has_empty)
Chris@16 442 {
Chris@16 443 check_end(it, tokens.end(), wkt);
Chris@16 444 return false;
Chris@16 445 }
Chris@16 446 // M is ignored at all.
Chris@16 447
Chris@16 448 return true;
Chris@16 449 }
Chris@16 450 throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt);
Chris@16 451 }
Chris@16 452
Chris@16 453
Chris@16 454 template <typename Geometry, template<typename> class Parser, typename PrefixPolicy>
Chris@16 455 struct geometry_parser
Chris@16 456 {
Chris@16 457 static inline void apply(std::string const& wkt, Geometry& geometry)
Chris@16 458 {
Chris@16 459 geometry::clear(geometry);
Chris@16 460
Chris@16 461 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
Chris@16 462 tokenizer::iterator it;
Chris@16 463 if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it))
Chris@16 464 {
Chris@16 465 Parser<Geometry>::apply(it, tokens.end(), wkt, geometry);
Chris@16 466 check_end(it, tokens.end(), wkt);
Chris@16 467 }
Chris@16 468 }
Chris@16 469 };
Chris@16 470
Chris@16 471
Chris@16 472
Chris@16 473
Chris@16 474
Chris@16 475 /*!
Chris@16 476 \brief Supports box parsing
Chris@16 477 \note OGC does not define the box geometry, and WKT does not support boxes.
Chris@16 478 However, to be generic GGL supports reading and writing from and to boxes.
Chris@16 479 Boxes are outputted as a standard POLYGON. GGL can read boxes from
Chris@16 480 a standard POLYGON, from a POLYGON with 2 points of from a BOX
Chris@16 481 \tparam Box the box
Chris@16 482 */
Chris@16 483 template <typename Box>
Chris@16 484 struct box_parser
Chris@16 485 {
Chris@16 486 static inline void apply(std::string const& wkt, Box& box)
Chris@16 487 {
Chris@16 488 bool should_close = false;
Chris@16 489 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
Chris@16 490 tokenizer::iterator it = tokens.begin();
Chris@16 491 tokenizer::iterator end = tokens.end();
Chris@16 492 if (it != end && boost::iequals(*it, "POLYGON"))
Chris@16 493 {
Chris@16 494 ++it;
Chris@16 495 bool has_empty, has_z, has_m;
Chris@16 496 handle_empty_z_m(it, end, has_empty, has_z, has_m);
Chris@16 497 if (has_empty)
Chris@16 498 {
Chris@16 499 assign_zero(box);
Chris@16 500 return;
Chris@16 501 }
Chris@16 502 handle_open_parenthesis(it, end, wkt);
Chris@16 503 should_close = true;
Chris@16 504 }
Chris@16 505 else if (it != end && boost::iequals(*it, "BOX"))
Chris@16 506 {
Chris@16 507 ++it;
Chris@16 508 }
Chris@16 509 else
Chris@16 510 {
Chris@16 511 throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt);
Chris@16 512 }
Chris@16 513
Chris@16 514 typedef typename point_type<Box>::type point_type;
Chris@16 515 std::vector<point_type> points;
Chris@16 516 container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
Chris@16 517
Chris@16 518 if (should_close)
Chris@16 519 {
Chris@16 520 handle_close_parenthesis(it, end, wkt);
Chris@16 521 }
Chris@16 522 check_end(it, end, wkt);
Chris@16 523
Chris@16 524 int index = 0;
Chris@16 525 int n = boost::size(points);
Chris@16 526 if (n == 2)
Chris@16 527 {
Chris@16 528 index = 1;
Chris@16 529 }
Chris@16 530 else if (n == 4 || n == 5)
Chris@16 531 {
Chris@16 532 // In case of 4 or 5 points, we do not check the other ones, just
Chris@16 533 // take the opposite corner which is always 2
Chris@16 534 index = 2;
Chris@16 535 }
Chris@16 536 else
Chris@16 537 {
Chris@16 538 throw read_wkt_exception("Box should have 2,4 or 5 points", wkt);
Chris@16 539 }
Chris@16 540
Chris@16 541 geometry::detail::assign_point_to_index<min_corner>(points.front(), box);
Chris@16 542 geometry::detail::assign_point_to_index<max_corner>(points[index], box);
Chris@16 543 }
Chris@16 544 };
Chris@16 545
Chris@16 546
Chris@16 547 /*!
Chris@16 548 \brief Supports segment parsing
Chris@16 549 \note OGC does not define the segment, and WKT does not support segmentes.
Chris@16 550 However, it is useful to implement it, also for testing purposes
Chris@16 551 \tparam Segment the segment
Chris@16 552 */
Chris@16 553 template <typename Segment>
Chris@16 554 struct segment_parser
Chris@16 555 {
Chris@16 556 static inline void apply(std::string const& wkt, Segment& segment)
Chris@16 557 {
Chris@16 558 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
Chris@16 559 tokenizer::iterator it = tokens.begin();
Chris@16 560 tokenizer::iterator end = tokens.end();
Chris@16 561 if (it != end &&
Chris@16 562 (boost::iequals(*it, "SEGMENT")
Chris@16 563 || boost::iequals(*it, "LINESTRING") ))
Chris@16 564 {
Chris@16 565 ++it;
Chris@16 566 }
Chris@16 567 else
Chris@16 568 {
Chris@16 569 throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt);
Chris@16 570 }
Chris@16 571
Chris@16 572 typedef typename point_type<Segment>::type point_type;
Chris@16 573 std::vector<point_type> points;
Chris@16 574 container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
Chris@16 575
Chris@16 576 check_end(it, end, wkt);
Chris@16 577
Chris@16 578 if (boost::size(points) == 2)
Chris@16 579 {
Chris@16 580 geometry::detail::assign_point_to_index<0>(points.front(), segment);
Chris@16 581 geometry::detail::assign_point_to_index<1>(points.back(), segment);
Chris@16 582 }
Chris@16 583 else
Chris@16 584 {
Chris@16 585 throw read_wkt_exception("Segment should have 2 points", wkt);
Chris@16 586 }
Chris@16 587
Chris@16 588 }
Chris@16 589 };
Chris@16 590
Chris@16 591
Chris@16 592
Chris@16 593 }} // namespace detail::wkt
Chris@16 594 #endif // DOXYGEN_NO_DETAIL
Chris@16 595
Chris@16 596 #ifndef DOXYGEN_NO_DISPATCH
Chris@16 597 namespace dispatch
Chris@16 598 {
Chris@16 599
Chris@16 600 template <typename Tag, typename Geometry>
Chris@16 601 struct read_wkt {};
Chris@16 602
Chris@16 603
Chris@16 604 template <typename Point>
Chris@16 605 struct read_wkt<point_tag, Point>
Chris@16 606 : detail::wkt::geometry_parser
Chris@16 607 <
Chris@16 608 Point,
Chris@16 609 detail::wkt::point_parser,
Chris@16 610 detail::wkt::prefix_point
Chris@16 611 >
Chris@16 612 {};
Chris@16 613
Chris@16 614
Chris@16 615 template <typename L>
Chris@16 616 struct read_wkt<linestring_tag, L>
Chris@16 617 : detail::wkt::geometry_parser
Chris@16 618 <
Chris@16 619 L,
Chris@16 620 detail::wkt::linestring_parser,
Chris@16 621 detail::wkt::prefix_linestring
Chris@16 622 >
Chris@16 623 {};
Chris@16 624
Chris@16 625 template <typename Ring>
Chris@16 626 struct read_wkt<ring_tag, Ring>
Chris@16 627 : detail::wkt::geometry_parser
Chris@16 628 <
Chris@16 629 Ring,
Chris@16 630 detail::wkt::ring_parser,
Chris@16 631 detail::wkt::prefix_polygon
Chris@16 632 >
Chris@16 633 {};
Chris@16 634
Chris@16 635 template <typename Geometry>
Chris@16 636 struct read_wkt<polygon_tag, Geometry>
Chris@16 637 : detail::wkt::geometry_parser
Chris@16 638 <
Chris@16 639 Geometry,
Chris@16 640 detail::wkt::polygon_parser,
Chris@16 641 detail::wkt::prefix_polygon
Chris@16 642 >
Chris@16 643 {};
Chris@16 644
Chris@16 645
Chris@16 646 // Box (Non-OGC)
Chris@16 647 template <typename Box>
Chris@16 648 struct read_wkt<box_tag, Box>
Chris@16 649 : detail::wkt::box_parser<Box>
Chris@16 650 {};
Chris@16 651
Chris@16 652 // Segment (Non-OGC)
Chris@16 653 template <typename Segment>
Chris@16 654 struct read_wkt<segment_tag, Segment>
Chris@16 655 : detail::wkt::segment_parser<Segment>
Chris@16 656 {};
Chris@16 657
Chris@16 658
Chris@16 659 } // namespace dispatch
Chris@16 660 #endif // DOXYGEN_NO_DISPATCH
Chris@16 661
Chris@16 662 /*!
Chris@16 663 \brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry)
Chris@16 664 \ingroup wkt
Chris@16 665 \param wkt string containing \ref WKT
Chris@16 666 \param geometry output geometry
Chris@16 667 \par Example:
Chris@16 668 \note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz"
Chris@16 669 \note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())"
Chris@16 670 Small example showing how to use read_wkt to build a point
Chris@16 671 \dontinclude doxygen_1.cpp
Chris@16 672 \skip example_from_wkt_point
Chris@16 673 \line {
Chris@16 674 \until }
Chris@16 675 \par Example:
Chris@16 676 Small example showing how to use read_wkt to build a linestring
Chris@16 677 \dontinclude doxygen_1.cpp
Chris@16 678 \skip example_from_wkt_linestring
Chris@16 679 \line {
Chris@16 680 \until }
Chris@16 681 \par Example:
Chris@16 682 Small example showing how to use read_wkt to build a polygon
Chris@16 683 \dontinclude doxygen_1.cpp
Chris@16 684 \skip example_from_wkt_polygon
Chris@16 685 \line {
Chris@16 686 \until }
Chris@16 687 */
Chris@16 688 template <typename Geometry>
Chris@16 689 inline void read_wkt(std::string const& wkt, Geometry& geometry)
Chris@16 690 {
Chris@16 691 geometry::concept::check<Geometry>();
Chris@16 692 dispatch::read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);
Chris@16 693 }
Chris@16 694
Chris@16 695 }} // namespace boost::geometry
Chris@16 696
Chris@16 697 #endif // BOOST_GEOMETRY_IO_WKT_READ_HPP