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>();