Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/geometry/io/wkt/read.hpp @ 101:c530137014c0
Update Boost headers (1.58.0)
author | Chris Cannam |
---|---|
date | Mon, 07 Sep 2015 11:12:49 +0100 |
parents | 2665513ce2d3 |
children |
comparison
equal
deleted
inserted
replaced
100:793467b5e61c | 101:c530137014c0 |
---|---|
2 | 2 |
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. | 3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. |
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. | 4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. |
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. | 5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. |
6 | 6 |
7 // This file was modified by Oracle on 2014. | |
8 // Modifications copyright (c) 2014 Oracle and/or its affiliates. | |
9 | |
10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
11 | |
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library | 12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library |
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. | 13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. |
9 | 14 |
10 // Use, modification and distribution is subject to the Boost Software License, | 15 // Use, modification and distribution is subject to the Boost Software License, |
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | 16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
12 // http://www.boost.org/LICENSE_1_0.txt) | 17 // http://www.boost.org/LICENSE_1_0.txt) |
13 | 18 |
14 #ifndef BOOST_GEOMETRY_IO_WKT_READ_HPP | 19 #ifndef BOOST_GEOMETRY_IO_WKT_READ_HPP |
15 #define BOOST_GEOMETRY_IO_WKT_READ_HPP | 20 #define BOOST_GEOMETRY_IO_WKT_READ_HPP |
16 | 21 |
22 #include <cstddef> | |
17 #include <string> | 23 #include <string> |
18 | 24 |
19 #include <boost/lexical_cast.hpp> | 25 #include <boost/lexical_cast.hpp> |
20 #include <boost/tokenizer.hpp> | 26 #include <boost/tokenizer.hpp> |
21 | 27 |
26 #include <boost/type_traits.hpp> | 32 #include <boost/type_traits.hpp> |
27 | 33 |
28 #include <boost/geometry/algorithms/assign.hpp> | 34 #include <boost/geometry/algorithms/assign.hpp> |
29 #include <boost/geometry/algorithms/append.hpp> | 35 #include <boost/geometry/algorithms/append.hpp> |
30 #include <boost/geometry/algorithms/clear.hpp> | 36 #include <boost/geometry/algorithms/clear.hpp> |
37 #include <boost/geometry/algorithms/detail/equals/point_point.hpp> | |
31 | 38 |
32 #include <boost/geometry/core/access.hpp> | 39 #include <boost/geometry/core/access.hpp> |
33 #include <boost/geometry/core/coordinate_dimension.hpp> | 40 #include <boost/geometry/core/coordinate_dimension.hpp> |
34 #include <boost/geometry/core/exception.hpp> | 41 #include <boost/geometry/core/exception.hpp> |
35 #include <boost/geometry/core/exterior_ring.hpp> | 42 #include <boost/geometry/core/exterior_ring.hpp> |
36 #include <boost/geometry/core/geometry_id.hpp> | 43 #include <boost/geometry/core/geometry_id.hpp> |
37 #include <boost/geometry/core/interior_rings.hpp> | 44 #include <boost/geometry/core/interior_rings.hpp> |
38 #include <boost/geometry/core/mutable_range.hpp> | 45 #include <boost/geometry/core/mutable_range.hpp> |
46 #include <boost/geometry/core/point_type.hpp> | |
47 #include <boost/geometry/core/tag_cast.hpp> | |
48 #include <boost/geometry/core/tags.hpp> | |
39 | 49 |
40 #include <boost/geometry/geometries/concepts/check.hpp> | 50 #include <boost/geometry/geometries/concepts/check.hpp> |
41 | 51 |
42 #include <boost/geometry/util/coordinate_cast.hpp> | 52 #include <boost/geometry/util/coordinate_cast.hpp> |
43 | 53 |
93 namespace detail { namespace wkt | 103 namespace detail { namespace wkt |
94 { | 104 { |
95 | 105 |
96 typedef boost::tokenizer<boost::char_separator<char> > tokenizer; | 106 typedef boost::tokenizer<boost::char_separator<char> > tokenizer; |
97 | 107 |
98 template <typename Point, std::size_t Dimension, std::size_t DimensionCount> | 108 template <typename Point, |
109 std::size_t Dimension = 0, | |
110 std::size_t DimensionCount = geometry::dimension<Point>::value> | |
99 struct parsing_assigner | 111 struct parsing_assigner |
100 { | 112 { |
101 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, | 113 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, |
102 Point& point, std::string const& wkt) | 114 Point& point, std::string const& wkt) |
103 { | 115 { |
203 | 215 |
204 // Parse points until closing parenthesis | 216 // Parse points until closing parenthesis |
205 | 217 |
206 while (it != end && *it != ")") | 218 while (it != end && *it != ")") |
207 { | 219 { |
208 parsing_assigner | 220 parsing_assigner<Point>::apply(it, end, point, wkt); |
209 < | |
210 Point, | |
211 0, | |
212 dimension<Point>::value | |
213 >::apply(it, end, point, wkt); | |
214 out = point; | 221 out = point; |
215 ++out; | 222 ++out; |
216 if (it != end && *it == ",") | 223 if (it != end && *it == ",") |
217 { | 224 { |
218 ++it; | 225 ++it; |
222 handle_close_parenthesis(it, end, wkt); | 229 handle_close_parenthesis(it, end, wkt); |
223 } | 230 } |
224 }; | 231 }; |
225 | 232 |
226 | 233 |
234 template <typename Geometry, | |
235 closure_selector Closure = closure<Geometry>::value> | |
236 struct stateful_range_appender | |
237 { | |
238 typedef typename geometry::point_type<Geometry>::type point_type; | |
239 | |
240 // NOTE: Geometry is a reference | |
241 inline void append(Geometry geom, point_type const& point, bool) | |
242 { | |
243 geometry::append(geom, point); | |
244 } | |
245 }; | |
246 | |
247 template <typename Geometry> | |
248 struct stateful_range_appender<Geometry, open> | |
249 { | |
250 typedef typename geometry::point_type<Geometry>::type point_type; | |
251 typedef typename boost::range_size | |
252 < | |
253 typename util::bare_type<Geometry>::type | |
254 >::type size_type; | |
255 | |
256 BOOST_STATIC_ASSERT(( boost::is_same | |
257 < | |
258 typename tag<Geometry>::type, | |
259 ring_tag | |
260 >::value )); | |
261 | |
262 inline stateful_range_appender() | |
263 : pt_index(0) | |
264 {} | |
265 | |
266 // NOTE: Geometry is a reference | |
267 inline void append(Geometry geom, point_type const& point, bool is_next_expected) | |
268 { | |
269 bool should_append = true; | |
270 | |
271 if (pt_index == 0) | |
272 { | |
273 first_point = point; | |
274 //should_append = true; | |
275 } | |
276 else | |
277 { | |
278 // NOTE: if there is not enough Points, they're always appended | |
279 should_append | |
280 = is_next_expected | |
281 || pt_index < core_detail::closure::minimum_ring_size<open>::value | |
282 || !detail::equals::equals_point_point(point, first_point); | |
283 } | |
284 ++pt_index; | |
285 | |
286 if (should_append) | |
287 { | |
288 geometry::append(geom, point); | |
289 } | |
290 } | |
291 | |
292 private: | |
293 size_type pt_index; | |
294 point_type first_point; | |
295 }; | |
296 | |
227 // Geometry is a value-type or reference-type | 297 // Geometry is a value-type or reference-type |
228 template <typename Geometry> | 298 template <typename Geometry> |
229 struct container_appender | 299 struct container_appender |
230 { | 300 { |
231 typedef typename geometry::point_type | 301 typedef typename geometry::point_type<Geometry>::type point_type; |
232 < | |
233 typename boost::remove_reference<Geometry>::type | |
234 >::type point_type; | |
235 | 302 |
236 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, | 303 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, |
237 std::string const& wkt, Geometry out) | 304 std::string const& wkt, Geometry out) |
238 { | 305 { |
239 handle_open_parenthesis(it, end, wkt); | 306 handle_open_parenthesis(it, end, wkt); |
240 | 307 |
241 point_type point; | 308 stateful_range_appender<Geometry> appender; |
242 | 309 |
243 // Parse points until closing parenthesis | 310 // Parse points until closing parenthesis |
244 | |
245 while (it != end && *it != ")") | 311 while (it != end && *it != ")") |
246 { | 312 { |
247 parsing_assigner | 313 point_type point; |
248 < | 314 |
249 point_type, | 315 parsing_assigner<point_type>::apply(it, end, point, wkt); |
250 0, | 316 |
251 dimension<point_type>::value | 317 bool const is_next_expected = it != end && *it == ","; |
252 >::apply(it, end, point, wkt); | 318 |
253 | 319 appender.append(out, point, is_next_expected); |
254 geometry::append(out, point); | 320 |
255 if (it != end && *it == ",") | 321 if (is_next_expected) |
256 { | 322 { |
257 ++it; | 323 ++it; |
258 } | 324 } |
259 } | 325 } |
260 | 326 |
271 { | 337 { |
272 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, | 338 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, |
273 std::string const& wkt, P& point) | 339 std::string const& wkt, P& point) |
274 { | 340 { |
275 handle_open_parenthesis(it, end, wkt); | 341 handle_open_parenthesis(it, end, wkt); |
276 parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt); | 342 parsing_assigner<P>::apply(it, end, point, wkt); |
277 handle_close_parenthesis(it, end, wkt); | 343 handle_close_parenthesis(it, end, wkt); |
278 } | 344 } |
279 }; | 345 }; |
280 | 346 |
281 | 347 |
302 handle_open_parenthesis(it, end, wkt); | 368 handle_open_parenthesis(it, end, wkt); |
303 container_appender<Ring&>::apply(it, end, wkt, ring); | 369 container_appender<Ring&>::apply(it, end, wkt, ring); |
304 handle_close_parenthesis(it, end, wkt); | 370 handle_close_parenthesis(it, end, wkt); |
305 } | 371 } |
306 }; | 372 }; |
307 | |
308 | |
309 | 373 |
310 | 374 |
311 /*! | 375 /*! |
312 \brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))" | 376 \brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))" |
313 \note used for parsing polygons and multi-polygons | 377 \note used for parsing polygons and multi-polygons |
356 | 420 |
357 handle_close_parenthesis(it, end, wkt); | 421 handle_close_parenthesis(it, end, wkt); |
358 } | 422 } |
359 }; | 423 }; |
360 | 424 |
425 | |
361 inline bool one_of(tokenizer::iterator const& it, std::string const& value, | 426 inline bool one_of(tokenizer::iterator const& it, std::string const& value, |
362 bool& is_present) | 427 bool& is_present) |
363 { | 428 { |
364 if (boost::iequals(*it, value)) | 429 if (boost::iequals(*it, value)) |
365 { | 430 { |
467 } | 532 } |
468 } | 533 } |
469 }; | 534 }; |
470 | 535 |
471 | 536 |
472 | 537 template <typename MultiGeometry, template<typename> class Parser, typename PrefixPolicy> |
538 struct multi_parser | |
539 { | |
540 static inline void apply(std::string const& wkt, MultiGeometry& geometry) | |
541 { | |
542 traits::clear<MultiGeometry>::apply(geometry); | |
543 | |
544 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); | |
545 tokenizer::iterator it; | |
546 if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it)) | |
547 { | |
548 handle_open_parenthesis(it, tokens.end(), wkt); | |
549 | |
550 // Parse sub-geometries | |
551 while(it != tokens.end() && *it != ")") | |
552 { | |
553 traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1); | |
554 Parser | |
555 < | |
556 typename boost::range_value<MultiGeometry>::type | |
557 >::apply(it, tokens.end(), wkt, *(boost::end(geometry) - 1)); | |
558 if (it != tokens.end() && *it == ",") | |
559 { | |
560 // Skip "," after multi-element is parsed | |
561 ++it; | |
562 } | |
563 } | |
564 | |
565 handle_close_parenthesis(it, tokens.end(), wkt); | |
566 } | |
567 | |
568 check_end(it, tokens.end(), wkt); | |
569 } | |
570 }; | |
571 | |
572 template <typename P> | |
573 struct noparenthesis_point_parser | |
574 { | |
575 static inline void apply(tokenizer::iterator& it, tokenizer::iterator end, | |
576 std::string const& wkt, P& point) | |
577 { | |
578 parsing_assigner<P>::apply(it, end, point, wkt); | |
579 } | |
580 }; | |
581 | |
582 template <typename MultiGeometry, typename PrefixPolicy> | |
583 struct multi_point_parser | |
584 { | |
585 static inline void apply(std::string const& wkt, MultiGeometry& geometry) | |
586 { | |
587 traits::clear<MultiGeometry>::apply(geometry); | |
588 | |
589 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); | |
590 tokenizer::iterator it; | |
591 | |
592 if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it)) | |
593 { | |
594 handle_open_parenthesis(it, tokens.end(), wkt); | |
595 | |
596 // If first point definition starts with "(" then parse points as (x y) | |
597 // otherwise as "x y" | |
598 bool using_brackets = (it != tokens.end() && *it == "("); | |
599 | |
600 while(it != tokens.end() && *it != ")") | |
601 { | |
602 traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1); | |
603 | |
604 if (using_brackets) | |
605 { | |
606 point_parser | |
607 < | |
608 typename boost::range_value<MultiGeometry>::type | |
609 >::apply(it, tokens.end(), wkt, *(boost::end(geometry) - 1)); | |
610 } | |
611 else | |
612 { | |
613 noparenthesis_point_parser | |
614 < | |
615 typename boost::range_value<MultiGeometry>::type | |
616 >::apply(it, tokens.end(), wkt, *(boost::end(geometry) - 1)); | |
617 } | |
618 | |
619 if (it != tokens.end() && *it == ",") | |
620 { | |
621 // Skip "," after point is parsed | |
622 ++it; | |
623 } | |
624 } | |
625 | |
626 handle_close_parenthesis(it, tokens.end(), wkt); | |
627 } | |
628 | |
629 check_end(it, tokens.end(), wkt); | |
630 } | |
631 }; | |
473 | 632 |
474 | 633 |
475 /*! | 634 /*! |
476 \brief Supports box parsing | 635 \brief Supports box parsing |
477 \note OGC does not define the box geometry, and WKT does not support boxes. | 636 \note OGC does not define the box geometry, and WKT does not support boxes. |
519 { | 678 { |
520 handle_close_parenthesis(it, end, wkt); | 679 handle_close_parenthesis(it, end, wkt); |
521 } | 680 } |
522 check_end(it, end, wkt); | 681 check_end(it, end, wkt); |
523 | 682 |
524 int index = 0; | 683 unsigned int index = 0; |
525 int n = boost::size(points); | 684 std::size_t n = boost::size(points); |
526 if (n == 2) | 685 if (n == 2) |
527 { | 686 { |
528 index = 1; | 687 index = 1; |
529 } | 688 } |
530 else if (n == 4 || n == 5) | 689 else if (n == 4 || n == 5) |
585 throw read_wkt_exception("Segment should have 2 points", wkt); | 744 throw read_wkt_exception("Segment should have 2 points", wkt); |
586 } | 745 } |
587 | 746 |
588 } | 747 } |
589 }; | 748 }; |
590 | |
591 | 749 |
592 | 750 |
593 }} // namespace detail::wkt | 751 }} // namespace detail::wkt |
594 #endif // DOXYGEN_NO_DETAIL | 752 #endif // DOXYGEN_NO_DETAIL |
595 | 753 |
641 detail::wkt::prefix_polygon | 799 detail::wkt::prefix_polygon |
642 > | 800 > |
643 {}; | 801 {}; |
644 | 802 |
645 | 803 |
804 template <typename MultiGeometry> | |
805 struct read_wkt<multi_point_tag, MultiGeometry> | |
806 : detail::wkt::multi_point_parser | |
807 < | |
808 MultiGeometry, | |
809 detail::wkt::prefix_multipoint | |
810 > | |
811 {}; | |
812 | |
813 template <typename MultiGeometry> | |
814 struct read_wkt<multi_linestring_tag, MultiGeometry> | |
815 : detail::wkt::multi_parser | |
816 < | |
817 MultiGeometry, | |
818 detail::wkt::linestring_parser, | |
819 detail::wkt::prefix_multilinestring | |
820 > | |
821 {}; | |
822 | |
823 template <typename MultiGeometry> | |
824 struct read_wkt<multi_polygon_tag, MultiGeometry> | |
825 : detail::wkt::multi_parser | |
826 < | |
827 MultiGeometry, | |
828 detail::wkt::polygon_parser, | |
829 detail::wkt::prefix_multipolygon | |
830 > | |
831 {}; | |
832 | |
833 | |
646 // Box (Non-OGC) | 834 // Box (Non-OGC) |
647 template <typename Box> | 835 template <typename Box> |
648 struct read_wkt<box_tag, Box> | 836 struct read_wkt<box_tag, Box> |
649 : detail::wkt::box_parser<Box> | 837 : detail::wkt::box_parser<Box> |
650 {}; | 838 {}; |
660 #endif // DOXYGEN_NO_DISPATCH | 848 #endif // DOXYGEN_NO_DISPATCH |
661 | 849 |
662 /*! | 850 /*! |
663 \brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry) | 851 \brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry) |
664 \ingroup wkt | 852 \ingroup wkt |
853 \tparam Geometry \tparam_geometry | |
665 \param wkt string containing \ref WKT | 854 \param wkt string containing \ref WKT |
666 \param geometry output geometry | 855 \param geometry \param_geometry output geometry |
667 \par Example: | 856 \ingroup wkt |
668 \note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz" | 857 \qbk{[include reference/io/read_wkt.qbk]} |
669 \note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())" | |
670 Small example showing how to use read_wkt to build a point | |
671 \dontinclude doxygen_1.cpp | |
672 \skip example_from_wkt_point | |
673 \line { | |
674 \until } | |
675 \par Example: | |
676 Small example showing how to use read_wkt to build a linestring | |
677 \dontinclude doxygen_1.cpp | |
678 \skip example_from_wkt_linestring | |
679 \line { | |
680 \until } | |
681 \par Example: | |
682 Small example showing how to use read_wkt to build a polygon | |
683 \dontinclude doxygen_1.cpp | |
684 \skip example_from_wkt_polygon | |
685 \line { | |
686 \until } | |
687 */ | 858 */ |
688 template <typename Geometry> | 859 template <typename Geometry> |
689 inline void read_wkt(std::string const& wkt, Geometry& geometry) | 860 inline void read_wkt(std::string const& wkt, Geometry& geometry) |
690 { | 861 { |
691 geometry::concept::check<Geometry>(); | 862 geometry::concept::check<Geometry>(); |