]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/io/wkt/read.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / geometry / io / wkt / read.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
b32b8144 6// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
7c673cae
FG
7
8// This file was modified by Oracle on 2014, 2015.
9// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
10
11// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12
13// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
15
16// Use, modification and distribution is subject to the Boost Software License,
17// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18// http://www.boost.org/LICENSE_1_0.txt)
19
20#ifndef BOOST_GEOMETRY_IO_WKT_READ_HPP
21#define BOOST_GEOMETRY_IO_WKT_READ_HPP
22
23#include <cstddef>
24#include <string>
25
26#include <boost/lexical_cast.hpp>
27#include <boost/tokenizer.hpp>
28
29#include <boost/algorithm/string.hpp>
30#include <boost/mpl/if.hpp>
31#include <boost/range/begin.hpp>
32#include <boost/range/end.hpp>
33#include <boost/range/size.hpp>
34#include <boost/range/value_type.hpp>
b32b8144 35#include <boost/throw_exception.hpp>
7c673cae
FG
36#include <boost/type_traits/is_same.hpp>
37#include <boost/type_traits/remove_reference.hpp>
38
39#include <boost/geometry/algorithms/assign.hpp>
40#include <boost/geometry/algorithms/append.hpp>
41#include <boost/geometry/algorithms/clear.hpp>
42#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
43
44#include <boost/geometry/core/access.hpp>
45#include <boost/geometry/core/coordinate_dimension.hpp>
46#include <boost/geometry/core/exception.hpp>
47#include <boost/geometry/core/exterior_ring.hpp>
48#include <boost/geometry/core/geometry_id.hpp>
49#include <boost/geometry/core/interior_rings.hpp>
50#include <boost/geometry/core/mutable_range.hpp>
51#include <boost/geometry/core/point_type.hpp>
52#include <boost/geometry/core/tag_cast.hpp>
53#include <boost/geometry/core/tags.hpp>
54
55#include <boost/geometry/geometries/concepts/check.hpp>
56
57#include <boost/geometry/util/coordinate_cast.hpp>
58
59#include <boost/geometry/io/wkt/detail/prefix.hpp>
60
61namespace boost { namespace geometry
62{
63
64/*!
65\brief Exception showing things wrong with WKT parsing
66\ingroup wkt
67*/
68struct read_wkt_exception : public geometry::exception
69{
70 template <typename Iterator>
71 read_wkt_exception(std::string const& msg,
72 Iterator const& it,
73 Iterator const& end,
74 std::string const& wkt)
75 : message(msg)
76 , wkt(wkt)
77 {
78 if (it != end)
79 {
80 source = " at '";
81 source += it->c_str();
82 source += "'";
83 }
84 complete = message + source + " in '" + wkt.substr(0, 100) + "'";
85 }
86
87 read_wkt_exception(std::string const& msg, std::string const& wkt)
88 : message(msg)
89 , wkt(wkt)
90 {
91 complete = message + "' in (" + wkt.substr(0, 100) + ")";
92 }
93
94 virtual ~read_wkt_exception() throw() {}
95
96 virtual const char* what() const throw()
97 {
98 return complete.c_str();
99 }
100private :
101 std::string source;
102 std::string message;
103 std::string wkt;
104 std::string complete;
105};
106
107
108#ifndef DOXYGEN_NO_DETAIL
109// (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostGIS))
110namespace detail { namespace wkt
111{
112
113typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
114
115template <typename Point,
116 std::size_t Dimension = 0,
117 std::size_t DimensionCount = geometry::dimension<Point>::value>
118struct parsing_assigner
119{
120 static inline void apply(tokenizer::iterator& it,
121 tokenizer::iterator const& end,
122 Point& point,
123 std::string const& wkt)
124 {
125 typedef typename coordinate_type<Point>::type coordinate_type;
126
127 // Stop at end of tokens, or at "," ot ")"
128 bool finished = (it == end || *it == "," || *it == ")");
129
130 try
131 {
132 // Initialize missing coordinates to default constructor (zero)
133 // OR
134 // Use lexical_cast for conversion to double/int
135 // Note that it is much slower than atof. However, it is more standard
136 // and in parsing the change in performance falls probably away against
137 // the tokenizing
138 set<Dimension>(point, finished
139 ? coordinate_type()
140 : coordinate_cast<coordinate_type>::apply(*it));
141 }
142 catch(boost::bad_lexical_cast const& blc)
143 {
b32b8144 144 BOOST_THROW_EXCEPTION(read_wkt_exception(blc.what(), it, end, wkt));
7c673cae
FG
145 }
146 catch(std::exception const& e)
147 {
b32b8144 148 BOOST_THROW_EXCEPTION(read_wkt_exception(e.what(), it, end, wkt));
7c673cae
FG
149 }
150 catch(...)
151 {
b32b8144 152 BOOST_THROW_EXCEPTION(read_wkt_exception("", it, end, wkt));
7c673cae
FG
153 }
154
155 parsing_assigner<Point, Dimension + 1, DimensionCount>::apply(
156 (finished ? it : ++it), end, point, wkt);
157 }
158};
159
160template <typename Point, std::size_t DimensionCount>
161struct parsing_assigner<Point, DimensionCount, DimensionCount>
162{
163 static inline void apply(tokenizer::iterator&,
164 tokenizer::iterator const&,
165 Point&,
166 std::string const&)
167 {
168 }
169};
170
171
172
173template <typename Iterator>
174inline void handle_open_parenthesis(Iterator& it,
175 Iterator const& end,
176 std::string const& wkt)
177{
178 if (it == end || *it != "(")
179 {
b32b8144 180 BOOST_THROW_EXCEPTION(read_wkt_exception("Expected '('", it, end, wkt));
7c673cae
FG
181 }
182 ++it;
183}
184
185
186template <typename Iterator>
187inline void handle_close_parenthesis(Iterator& it,
188 Iterator const& end,
189 std::string const& wkt)
190{
191 if (it != end && *it == ")")
192 {
193 ++it;
194 }
195 else
196 {
b32b8144 197 BOOST_THROW_EXCEPTION(read_wkt_exception("Expected ')'", it, end, wkt));
7c673cae
FG
198 }
199}
200
201template <typename Iterator>
202inline void check_end(Iterator& it,
203 Iterator const& end,
204 std::string const& wkt)
205{
206 if (it != end)
207 {
b32b8144 208 BOOST_THROW_EXCEPTION(read_wkt_exception("Too many tokens", it, end, wkt));
7c673cae
FG
209 }
210}
211
212/*!
213\brief Internal, parses coordinate sequences, strings are formated like "(1 2,3 4,...)"
214\param it token-iterator, should be pre-positioned at "(", is post-positions after last ")"
215\param end end-token-iterator
216\param out Output itererator receiving coordinates
217*/
218template <typename Point>
219struct container_inserter
220{
221 // Version with output iterator
222 template <typename OutputIterator>
223 static inline void apply(tokenizer::iterator& it,
224 tokenizer::iterator const& end,
225 std::string const& wkt,
226 OutputIterator out)
227 {
228 handle_open_parenthesis(it, end, wkt);
229
230 Point point;
231
232 // Parse points until closing parenthesis
233
234 while (it != end && *it != ")")
235 {
236 parsing_assigner<Point>::apply(it, end, point, wkt);
237 out = point;
238 ++out;
239 if (it != end && *it == ",")
240 {
241 ++it;
242 }
243 }
244
245 handle_close_parenthesis(it, end, wkt);
246 }
247};
248
249
250template <typename Geometry,
251 closure_selector Closure = closure<Geometry>::value>
252struct stateful_range_appender
253{
254 typedef typename geometry::point_type<Geometry>::type point_type;
255
256 // NOTE: Geometry is a reference
257 inline void append(Geometry geom, point_type const& point, bool)
258 {
259 geometry::append(geom, point);
260 }
261};
262
263template <typename Geometry>
264struct stateful_range_appender<Geometry, open>
265{
266 typedef typename geometry::point_type<Geometry>::type point_type;
267 typedef typename boost::range_size
268 <
269 typename util::bare_type<Geometry>::type
270 >::type size_type;
271
272 BOOST_STATIC_ASSERT(( boost::is_same
273 <
274 typename tag<Geometry>::type,
275 ring_tag
276 >::value ));
277
278 inline stateful_range_appender()
279 : pt_index(0)
280 {}
281
282 // NOTE: Geometry is a reference
283 inline void append(Geometry geom, point_type const& point, bool is_next_expected)
284 {
285 bool should_append = true;
286
287 if (pt_index == 0)
288 {
289 first_point = point;
290 //should_append = true;
291 }
292 else
293 {
294 // NOTE: if there is not enough Points, they're always appended
295 should_append
296 = is_next_expected
297 || pt_index < core_detail::closure::minimum_ring_size<open>::value
298 || !detail::equals::equals_point_point(point, first_point);
299 }
300 ++pt_index;
301
302 if (should_append)
303 {
304 geometry::append(geom, point);
305 }
306 }
307
308private:
309 size_type pt_index;
310 point_type first_point;
311};
312
313// Geometry is a value-type or reference-type
314template <typename Geometry>
315struct container_appender
316{
317 typedef typename geometry::point_type<Geometry>::type point_type;
318
319 static inline void apply(tokenizer::iterator& it,
320 tokenizer::iterator const& end,
321 std::string const& wkt,
322 Geometry out)
323 {
324 handle_open_parenthesis(it, end, wkt);
325
326 stateful_range_appender<Geometry> appender;
327
328 // Parse points until closing parenthesis
329 while (it != end && *it != ")")
330 {
331 point_type point;
332
333 parsing_assigner<point_type>::apply(it, end, point, wkt);
334
335 bool const is_next_expected = it != end && *it == ",";
336
337 appender.append(out, point, is_next_expected);
338
339 if (is_next_expected)
340 {
341 ++it;
342 }
343 }
344
345 handle_close_parenthesis(it, end, wkt);
346 }
347};
348
349/*!
350\brief Internal, parses a point from a string like this "(x y)"
351\note used for parsing points and multi-points
352*/
353template <typename P>
354struct point_parser
355{
356 static inline void apply(tokenizer::iterator& it,
357 tokenizer::iterator const& end,
358 std::string const& wkt,
359 P& point)
360 {
361 handle_open_parenthesis(it, end, wkt);
362 parsing_assigner<P>::apply(it, end, point, wkt);
363 handle_close_parenthesis(it, end, wkt);
364 }
365};
366
367
368template <typename Geometry>
369struct linestring_parser
370{
371 static inline void apply(tokenizer::iterator& it,
372 tokenizer::iterator const& end,
373 std::string const& wkt,
374 Geometry& geometry)
375 {
376 container_appender<Geometry&>::apply(it, end, wkt, geometry);
377 }
378};
379
380
381template <typename Ring>
382struct ring_parser
383{
384 static inline void apply(tokenizer::iterator& it,
385 tokenizer::iterator const& end,
386 std::string const& wkt,
387 Ring& ring)
388 {
389 // A ring should look like polygon((x y,x y,x y...))
390 // So handle the extra opening/closing parentheses
391 // and in between parse using the container-inserter
392 handle_open_parenthesis(it, end, wkt);
393 container_appender<Ring&>::apply(it, end, wkt, ring);
394 handle_close_parenthesis(it, end, wkt);
395 }
396};
397
398
399/*!
400\brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))"
401\note used for parsing polygons and multi-polygons
402*/
403template <typename Polygon>
404struct polygon_parser
405{
406 typedef typename ring_return_type<Polygon>::type ring_return_type;
407 typedef container_appender<ring_return_type> appender;
408
409 static inline void apply(tokenizer::iterator& it,
410 tokenizer::iterator const& end,
411 std::string const& wkt,
412 Polygon& poly)
413 {
414
415 handle_open_parenthesis(it, end, wkt);
416
417 int n = -1;
418
419 // Stop at ")"
420 while (it != end && *it != ")")
421 {
422 // Parse ring
423 if (++n == 0)
424 {
425 appender::apply(it, end, wkt, exterior_ring(poly));
426 }
427 else
428 {
429 typename ring_type<Polygon>::type ring;
430 appender::apply(it, end, wkt, ring);
431 traits::push_back
432 <
433 typename boost::remove_reference
434 <
435 typename traits::interior_mutable_type<Polygon>::type
436 >::type
437 >::apply(interior_rings(poly), ring);
438 }
439
440 if (it != end && *it == ",")
441 {
442 // Skip "," after ring is parsed
443 ++it;
444 }
445 }
446
447 handle_close_parenthesis(it, end, wkt);
448 }
449};
450
451
452inline bool one_of(tokenizer::iterator const& it,
453 std::string const& value,
454 bool& is_present)
455{
456 if (boost::iequals(*it, value))
457 {
458 is_present = true;
459 return true;
460 }
461 return false;
462}
463
464inline bool one_of(tokenizer::iterator const& it,
465 std::string const& value,
466 bool& present1,
467 bool& present2)
468{
469 if (boost::iequals(*it, value))
470 {
471 present1 = true;
472 present2 = true;
473 return true;
474 }
475 return false;
476}
477
478
479inline void handle_empty_z_m(tokenizer::iterator& it,
480 tokenizer::iterator const& end,
481 bool& has_empty,
482 bool& has_z,
483 bool& has_m)
484{
485 has_empty = false;
486 has_z = false;
487 has_m = false;
488
489 // WKT can optionally have Z and M (measured) values as in
490 // POINT ZM (1 1 5 60), POINT M (1 1 80), POINT Z (1 1 5)
491 // GGL supports any of them as coordinate values, but is not aware
492 // of any Measured value.
493 while (it != end
494 && (one_of(it, "M", has_m)
495 || one_of(it, "Z", has_z)
496 || one_of(it, "EMPTY", has_empty)
497 || one_of(it, "MZ", has_m, has_z)
498 || one_of(it, "ZM", has_z, has_m)
499 )
500 )
501 {
502 ++it;
503 }
504}
505
506/*!
507\brief Internal, starts parsing
508\param tokens boost tokens, parsed with separator " " and keeping separator "()"
509\param geometry string to compare with first token
510*/
511template <typename Geometry>
512inline bool initialize(tokenizer const& tokens,
513 std::string const& geometry_name,
514 std::string const& wkt,
515 tokenizer::iterator& it,
516 tokenizer::iterator& end)
517{
518 it = tokens.begin();
519 end = tokens.end();
11fdf7f2
TL
520
521 if (it == end || ! boost::iequals(*it++, geometry_name))
7c673cae 522 {
11fdf7f2
TL
523 BOOST_THROW_EXCEPTION(read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt));
524 }
7c673cae 525
11fdf7f2
TL
526 bool has_empty, has_z, has_m;
527
528 handle_empty_z_m(it, end, has_empty, has_z, has_m);
7c673cae
FG
529
530// Silence warning C4127: conditional expression is constant
531#if defined(_MSC_VER)
532#pragma warning(push)
533#pragma warning(disable : 4127)
534#endif
535
11fdf7f2
TL
536 if (has_z && dimension<Geometry>::type::value < 3)
537 {
538 BOOST_THROW_EXCEPTION(read_wkt_exception("Z only allowed for 3 or more dimensions", wkt));
539 }
7c673cae
FG
540
541#if defined(_MSC_VER)
542#pragma warning(pop)
543#endif
544
11fdf7f2
TL
545 if (has_empty)
546 {
547 check_end(it, end, wkt);
548 return false;
7c673cae 549 }
11fdf7f2
TL
550 // M is ignored at all.
551
552 return true;
7c673cae
FG
553}
554
555
556template <typename Geometry, template<typename> class Parser, typename PrefixPolicy>
557struct geometry_parser
558{
559 static inline void apply(std::string const& wkt, Geometry& geometry)
560 {
561 geometry::clear(geometry);
562
563 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
564 tokenizer::iterator it, end;
565 if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
566 {
567 Parser<Geometry>::apply(it, end, wkt, geometry);
568 check_end(it, end, wkt);
569 }
570 }
571};
572
573
574template <typename MultiGeometry, template<typename> class Parser, typename PrefixPolicy>
575struct multi_parser
576{
577 static inline void apply(std::string const& wkt, MultiGeometry& geometry)
578 {
579 traits::clear<MultiGeometry>::apply(geometry);
580
581 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
582 tokenizer::iterator it, end;
583 if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
584 {
585 handle_open_parenthesis(it, end, wkt);
586
587 // Parse sub-geometries
588 while(it != end && *it != ")")
589 {
590 traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1);
591 Parser
592 <
593 typename boost::range_value<MultiGeometry>::type
594 >::apply(it, end, wkt, *(boost::end(geometry) - 1));
595 if (it != end && *it == ",")
596 {
597 // Skip "," after multi-element is parsed
598 ++it;
599 }
600 }
601
602 handle_close_parenthesis(it, end, wkt);
603 }
604
605 check_end(it, end, wkt);
606 }
607};
608
609template <typename P>
610struct noparenthesis_point_parser
611{
612 static inline void apply(tokenizer::iterator& it,
613 tokenizer::iterator const& end,
614 std::string const& wkt,
615 P& point)
616 {
617 parsing_assigner<P>::apply(it, end, point, wkt);
618 }
619};
620
621template <typename MultiGeometry, typename PrefixPolicy>
622struct multi_point_parser
623{
624 static inline void apply(std::string const& wkt, MultiGeometry& geometry)
625 {
626 traits::clear<MultiGeometry>::apply(geometry);
627
628 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
629 tokenizer::iterator it, end;
630
631 if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
632 {
633 handle_open_parenthesis(it, end, wkt);
634
635 // If first point definition starts with "(" then parse points as (x y)
636 // otherwise as "x y"
637 bool using_brackets = (it != end && *it == "(");
638
639 while(it != end && *it != ")")
640 {
641 traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1);
642
643 if (using_brackets)
644 {
645 point_parser
646 <
647 typename boost::range_value<MultiGeometry>::type
648 >::apply(it, end, wkt, *(boost::end(geometry) - 1));
649 }
650 else
651 {
652 noparenthesis_point_parser
653 <
654 typename boost::range_value<MultiGeometry>::type
655 >::apply(it, end, wkt, *(boost::end(geometry) - 1));
656 }
657
658 if (it != end && *it == ",")
659 {
660 // Skip "," after point is parsed
661 ++it;
662 }
663 }
664
665 handle_close_parenthesis(it, end, wkt);
666 }
667
668 check_end(it, end, wkt);
669 }
670};
671
672
673/*!
674\brief Supports box parsing
675\note OGC does not define the box geometry, and WKT does not support boxes.
676 However, to be generic GGL supports reading and writing from and to boxes.
677 Boxes are outputted as a standard POLYGON. GGL can read boxes from
678 a standard POLYGON, from a POLYGON with 2 points of from a BOX
679\tparam Box the box
680*/
681template <typename Box>
682struct box_parser
683{
684 static inline void apply(std::string const& wkt, Box& box)
685 {
686 bool should_close = false;
687 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
688 tokenizer::iterator it = tokens.begin();
689 tokenizer::iterator end = tokens.end();
690 if (it != end && boost::iequals(*it, "POLYGON"))
691 {
692 ++it;
693 bool has_empty, has_z, has_m;
694 handle_empty_z_m(it, end, has_empty, has_z, has_m);
695 if (has_empty)
696 {
697 assign_zero(box);
698 return;
699 }
700 handle_open_parenthesis(it, end, wkt);
701 should_close = true;
702 }
703 else if (it != end && boost::iequals(*it, "BOX"))
704 {
705 ++it;
706 }
707 else
708 {
b32b8144 709 BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt));
7c673cae
FG
710 }
711
712 typedef typename point_type<Box>::type point_type;
713 std::vector<point_type> points;
714 container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
715
716 if (should_close)
717 {
718 handle_close_parenthesis(it, end, wkt);
719 }
720 check_end(it, end, wkt);
721
722 unsigned int index = 0;
723 std::size_t n = boost::size(points);
724 if (n == 2)
725 {
726 index = 1;
727 }
728 else if (n == 4 || n == 5)
729 {
730 // In case of 4 or 5 points, we do not check the other ones, just
731 // take the opposite corner which is always 2
732 index = 2;
733 }
734 else
735 {
b32b8144 736 BOOST_THROW_EXCEPTION(read_wkt_exception("Box should have 2,4 or 5 points", wkt));
7c673cae
FG
737 }
738
739 geometry::detail::assign_point_to_index<min_corner>(points.front(), box);
740 geometry::detail::assign_point_to_index<max_corner>(points[index], box);
741 }
742};
743
744
745/*!
746\brief Supports segment parsing
747\note OGC does not define the segment, and WKT does not support segmentes.
748 However, it is useful to implement it, also for testing purposes
749\tparam Segment the segment
750*/
751template <typename Segment>
752struct segment_parser
753{
754 static inline void apply(std::string const& wkt, Segment& segment)
755 {
756 tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
757 tokenizer::iterator it = tokens.begin();
758 tokenizer::iterator end = tokens.end();
759 if (it != end &&
760 (boost::iequals(*it, "SEGMENT")
761 || boost::iequals(*it, "LINESTRING") ))
762 {
763 ++it;
764 }
765 else
766 {
b32b8144 767 BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt));
7c673cae
FG
768 }
769
770 typedef typename point_type<Segment>::type point_type;
771 std::vector<point_type> points;
772 container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
773
774 check_end(it, end, wkt);
775
776 if (boost::size(points) == 2)
777 {
778 geometry::detail::assign_point_to_index<0>(points.front(), segment);
779 geometry::detail::assign_point_to_index<1>(points.back(), segment);
780 }
781 else
782 {
b32b8144 783 BOOST_THROW_EXCEPTION(read_wkt_exception("Segment should have 2 points", wkt));
7c673cae
FG
784 }
785
786 }
787};
788
789
790}} // namespace detail::wkt
791#endif // DOXYGEN_NO_DETAIL
792
793#ifndef DOXYGEN_NO_DISPATCH
794namespace dispatch
795{
796
797template <typename Tag, typename Geometry>
798struct read_wkt {};
799
800
801template <typename Point>
802struct read_wkt<point_tag, Point>
803 : detail::wkt::geometry_parser
804 <
805 Point,
806 detail::wkt::point_parser,
807 detail::wkt::prefix_point
808 >
809{};
810
811
812template <typename L>
813struct read_wkt<linestring_tag, L>
814 : detail::wkt::geometry_parser
815 <
816 L,
817 detail::wkt::linestring_parser,
818 detail::wkt::prefix_linestring
819 >
820{};
821
822template <typename Ring>
823struct read_wkt<ring_tag, Ring>
824 : detail::wkt::geometry_parser
825 <
826 Ring,
827 detail::wkt::ring_parser,
828 detail::wkt::prefix_polygon
829 >
830{};
831
832template <typename Geometry>
833struct read_wkt<polygon_tag, Geometry>
834 : detail::wkt::geometry_parser
835 <
836 Geometry,
837 detail::wkt::polygon_parser,
838 detail::wkt::prefix_polygon
839 >
840{};
841
842
843template <typename MultiGeometry>
844struct read_wkt<multi_point_tag, MultiGeometry>
845 : detail::wkt::multi_point_parser
846 <
847 MultiGeometry,
848 detail::wkt::prefix_multipoint
849 >
850{};
851
852template <typename MultiGeometry>
853struct read_wkt<multi_linestring_tag, MultiGeometry>
854 : detail::wkt::multi_parser
855 <
856 MultiGeometry,
857 detail::wkt::linestring_parser,
858 detail::wkt::prefix_multilinestring
859 >
860{};
861
862template <typename MultiGeometry>
863struct read_wkt<multi_polygon_tag, MultiGeometry>
864 : detail::wkt::multi_parser
865 <
866 MultiGeometry,
867 detail::wkt::polygon_parser,
868 detail::wkt::prefix_multipolygon
869 >
870{};
871
872
873// Box (Non-OGC)
874template <typename Box>
875struct read_wkt<box_tag, Box>
876 : detail::wkt::box_parser<Box>
877{};
878
879// Segment (Non-OGC)
880template <typename Segment>
881struct read_wkt<segment_tag, Segment>
882 : detail::wkt::segment_parser<Segment>
883{};
884
885
886} // namespace dispatch
887#endif // DOXYGEN_NO_DISPATCH
888
889/*!
890\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry)
891\ingroup wkt
892\tparam Geometry \tparam_geometry
893\param wkt string containing \ref WKT
894\param geometry \param_geometry output geometry
895\ingroup wkt
896\qbk{[include reference/io/read_wkt.qbk]}
897*/
898template <typename Geometry>
899inline void read_wkt(std::string const& wkt, Geometry& geometry)
900{
901 geometry::concepts::check<Geometry>();
902 dispatch::read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);
903}
904
905}} // namespace boost::geometry
906
907#endif // BOOST_GEOMETRY_IO_WKT_READ_HPP