diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 572d4a321..30171f6b7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -859,13 +859,15 @@ public: IntersectionInfo const& intersection_info, DirInfo const& dir_info, SidePolicy const& side, - MethodAndOperationsReplacer method_and_operations_replacer) + MethodAndOperationsReplacer method_and_operations_replacer, + bool const is_pk_valid = true, bool const is_qk_valid = true) { TurnInfo tp = tp_model; // If P arrives within Q, there is a turn dependent on P - if (dir_info.arrival[0] == 1 - && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, intersection_info)) + if ( dir_info.arrival[0] == 1 + && is_pk_valid + && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, intersection_info) ) { method_and_operations_replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); @@ -874,8 +876,9 @@ public: } // If Q arrives within P, there is a turn dependent on Q - if (dir_info.arrival[1] == 1 - && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, intersection_info)) + if ( dir_info.arrival[1] == 1 + && is_qk_valid + && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, intersection_info) ) { method_and_operations_replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index fe50fa911..f89d474e6 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -184,10 +184,10 @@ struct get_turn_info_for_endpoint p_operation0, q_operation0, tp_model, result, 0, out); - bool result_ignore_ip0 = !opposite ? // <=> ip_count == 1 || ip_count == 2 && !opposite - append0_last : - (append0_last && (p0j || (is_q_last && q0j && q1i))); - // NOTE: based on how collinear is calculated for opposite segments + // NOTE: opposite && ip_count == 1 may be true! + + // don't ignore only for collinear opposite + bool result_ignore_ip0 = append0_last && ( ip_count == 1 || !opposite ); if ( p_operation1 == operation_none ) return result_ignore_ip0; @@ -199,11 +199,8 @@ struct get_turn_info_for_endpoint p_operation1, q_operation1, tp_model, result, 1, out); - bool result_ignore_ip1 = !opposite ? // <=> ip_count == 2 && !opposite - append1_last : - (append1_last && (q1j || (is_p_last && p1j && p0i))); - // NOTE: based on how collinear is calculated for opposite segments - // this condition is symmetric to the one above + // don't ignore only for collinear opposite + bool result_ignore_ip1 = append1_last && !opposite /*&& ip_count == 2*/; return result_ignore_ip0 || result_ignore_ip1; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 0e56fbf02..8a0d26084 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -235,12 +235,13 @@ struct get_turn_info_linear_areal equal::apply(pi, pj, pk, qi, qj, qk, tp, result.template get<0>(), result.template get<1>(), side_calc); - spike_detector spike_detect(side_calc); + // TODO: This isn't correct handling, hence commented out + /*spike_detector spike_detect(side_calc); if ( tp.operations[0].operation == operation_union && spike_detect.is_spike_p()) { tp.operations[0].operation = operation_continue; - } + }*/ replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); @@ -508,9 +509,7 @@ struct get_turn_info_linear_areal // IP on the last point of Linear Geometry if ( EnableLast && is_p_last - && ( ip_count > 1 ? p1j : p0j ) - && (!q0i || (q0i && q1j)) // prevents duplication - && !q1i ) // prevents duplication + && ( ip_count > 1 ? (p1j && !q1i) : (p0j && !q0i) ) ) // prevents duplication { TurnInfo tp = tp_model; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index d337dfbbf..079ca0586 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -352,7 +352,7 @@ struct get_turn_info_linear_linear AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, tp, out, result.template get<0>(), result.template get<1>(), side_calc, - replacer); + replacer, !is_p_last, !is_q_last); } } } diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index d6b641e92..c64dc9590 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -294,7 +294,7 @@ struct sectionalize_part section_type section; bool mark_first_non_duplicated = true; - std::size_t last_non_duplicate_index = 0; + std::size_t last_non_duplicate_index = sections.size(); iterator_type it = boost::begin(range); diff --git a/include/boost/geometry/iterators/concatenate_iterator.hpp b/include/boost/geometry/iterators/concatenate_iterator.hpp new file mode 100644 index 000000000..32a8b2332 --- /dev/null +++ b/include/boost/geometry/iterators/concatenate_iterator.hpp @@ -0,0 +1,109 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP + +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + + +template +struct concatenate_iterator + : public boost::iterator_facade + < + concatenate_iterator, + Value, + boost::forward_traversal_tag + > +{ +private: + Iterator1 m_it1, m_end1; + Iterator2 m_it2; + + struct enabler {}; + +public: + typedef Iterator1 first_iterator_type; + typedef Iterator2 second_iterator_type; + + // default constructor + concatenate_iterator() {} + + // for begin + concatenate_iterator(Iterator1 it1, Iterator1 end1, + Iterator2 it2) + : m_it1(it1), m_end1(end1), m_it2(it2) + {} + + // for end + concatenate_iterator(Iterator1 end1, Iterator2 end2) + : m_it1(end1), m_end1(end1), m_it2(end2) + {} + + template + concatenate_iterator + (concatenate_iterator const& other, + typename boost::enable_if_c + < + boost::is_convertible::value + && boost::is_convertible::value, + enabler + >::type = enabler()) + : m_it1(other.m_it1), m_end1(other.m_end1), m_it2(other.m_it2) + {} + + + +private: + friend class boost::iterator_core_access; + + template + friend class concatenate_iterator; + + Value& dereference() const + { + if ( m_it1 == m_end1 ) + { + return *m_it2; + } + return *m_it1; + } + + bool equal(concatenate_iterator const& other) const + { + return m_it1 == other.m_it1 && m_it2 == other.m_it2; + } + + void increment() + { + if ( m_it1 == m_end1 ) + { + ++m_it2; + } + else + { + ++m_it1; + } + } +}; + + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/dispatch/point_iterator.hpp b/include/boost/geometry/iterators/dispatch/point_iterator.hpp new file mode 100644 index 000000000..c07f3a865 --- /dev/null +++ b/include/boost/geometry/iterators/dispatch/point_iterator.hpp @@ -0,0 +1,47 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP + +#include +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// dispatch for points_begin +template ::type> +struct points_begin + : not_implemented +{}; + + + +// dispatch for points_end +template ::type> +struct points_end + : not_implemented +{}; + + + +} // namespace core_dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp b/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp new file mode 100644 index 000000000..02c40acae --- /dev/null +++ b/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp @@ -0,0 +1,37 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP +#define BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP + +#include +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template ::type> +struct point_iterator_type + : not_implemented +{}; + + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP diff --git a/include/boost/geometry/iterators/flatten_iterator.hpp b/include/boost/geometry/iterators/flatten_iterator.hpp new file mode 100644 index 000000000..9e3983cc4 --- /dev/null +++ b/include/boost/geometry/iterators/flatten_iterator.hpp @@ -0,0 +1,208 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP + +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + + +template +< + typename OuterIterator, + typename InnerIterator, + typename Value, + typename AccessInnerBegin, + typename AccessInnerEnd +> +struct flatten_iterator + : public boost::iterator_facade + < + flatten_iterator + < + OuterIterator, + InnerIterator, + Value, + AccessInnerBegin, + AccessInnerEnd>, + Value, + boost::forward_traversal_tag + > +{ +private: + OuterIterator m_outer_it, m_outer_end; + InnerIterator m_inner_it; + + struct enabler {}; + +public: + typedef OuterIterator outer_iterator_type; + typedef InnerIterator inner_iterator_type; + + // default constructor + flatten_iterator() {} + + // for begin + flatten_iterator(OuterIterator outer_it, OuterIterator outer_end) + : m_outer_it(outer_it), m_outer_end(outer_end) + { + advance_through_empty(); + } + + // for end + flatten_iterator(OuterIterator outer_end) + : m_outer_it(outer_end), m_outer_end(outer_end) + {} + + template + < + typename OtherOuterIterator, typename OtherInnerIterator, + typename OtherValue, + typename OtherAccessInnerBegin, typename OtherAccessInnerEnd + > + flatten_iterator(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + OtherAccessInnerBegin, + OtherAccessInnerEnd + > const& other, + typename boost::enable_if + < + boost::is_convertible, + enabler + >::type = enabler()) + : m_outer_it(other.m_outer_it), + m_outer_end(other.m_outer_end), + m_inner_it(other.m_inner_it) + {} + + template + < + typename OtherOuterIterator, + typename OtherInnerIterator, + typename OtherValue, + typename OtherAccessInnerBegin, + typename OtherAccessInnerEnd + > + flatten_iterator operator=(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + OtherAccessInnerBegin, + OtherAccessInnerEnd + > const& other) + { + m_outer_it = other.m_outer_it; + m_outer_end = other.m_outer_end; + m_inner_it = other.m_inner_it; + return *this; + } + +private: + friend class boost::iterator_core_access; + + template + < + typename Outer, + typename Inner, + typename V, + typename InnerBegin, + typename InnerEnd + > + friend class flatten_iterator; + + static inline bool empty(OuterIterator outer_it) + { + return + AccessInnerBegin::apply(*outer_it) == AccessInnerEnd::apply(*outer_it); + } + + inline void advance_through_empty() + { + while ( m_outer_it != m_outer_end && empty(m_outer_it) ) + { + ++m_outer_it; + } + + if ( m_outer_it != m_outer_end ) + { + m_inner_it = AccessInnerBegin::apply(*m_outer_it); + } + } + + Value& dereference() const + { + BOOST_ASSERT( m_outer_it != m_outer_end ); + BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); + return *m_inner_it; + } + + + template + < + typename OtherOuterIterator, + typename OtherInnerIterator, + typename OtherValue, + typename OtherAccessInnerBegin, + typename OtherAccessInnerEnd + > + inline bool equal(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + OtherAccessInnerBegin, + OtherAccessInnerEnd + > const& other) const + { + if ( this->m_outer_it != other.m_outer_it ) + { + return false; + } + + if ( this->m_outer_it == m_outer_end ) + { + return true; + } + + return this->m_inner_it == other.m_inner_it; + } + + inline void increment() + { + BOOST_ASSERT( m_outer_it != m_outer_end ); + BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); + + ++m_inner_it; + if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) ) + { + ++m_outer_it; + advance_through_empty(); + } + } +}; + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/point_iterator.hpp b/include/boost/geometry/iterators/point_iterator.hpp new file mode 100644 index 000000000..07a70c4e0 --- /dev/null +++ b/include/boost/geometry/iterators/point_iterator.hpp @@ -0,0 +1,278 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// specializations for points_begin + + +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(Linestring& linestring) + { + return boost::begin(linestring); + } +}; + + +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(Ring& ring) + { + return boost::begin(ring); + } +}; + + +template +struct points_begin +{ + typedef typename point_iterator_type::type return_type; + + static inline return_type apply(Polygon& polygon) + { + typedef typename return_type::second_iterator_type flatten_iterator; + + return return_type + (boost::begin(geometry::exterior_ring(polygon)), + boost::end(geometry::exterior_ring(polygon)), + flatten_iterator(boost::begin(geometry::interior_rings(polygon)), + boost::end(geometry::interior_rings(polygon)) + ) + ); + } +}; + + +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(MultiPoint& multipoint) + { + return boost::begin(multipoint); + } +}; + + +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(MultiLinestring& multilinestring) + { + return typename point_iterator_type + < + MultiLinestring + >::type(boost::begin(multilinestring), boost::end(multilinestring)); + } +}; + + +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(MultiPolygon& multipolygon) + { + return typename point_iterator_type + < + MultiPolygon + >::type(boost::begin(multipolygon), boost::end(multipolygon)); + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// specializations for points_end + + +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(Linestring& linestring) + { + return boost::end(linestring); + } +}; + + +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(Ring& ring) + { + return boost::end(ring); + } +}; + + +template +struct points_end +{ + typedef typename point_iterator_type::type return_type; + + static inline return_type apply(Polygon& polygon) + { + typedef typename return_type::second_iterator_type flatten_iterator; + + return return_type + (boost::end(geometry::exterior_ring(polygon)), + flatten_iterator( boost::end(geometry::interior_rings(polygon)) ) + ); + } +}; + + +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(MultiPoint& multipoint) + { + return boost::end(multipoint); + } +}; + + +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(MultiLinestring& multilinestring) + { + return typename point_iterator_type + < + MultiLinestring + >::type(boost::end(multilinestring)); + } +}; + + +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(MultiPolygon& multipolygon) + { + return typename point_iterator_type + < + MultiPolygon + >::type(boost::end(multipolygon)); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +// MK:: need to add doc here +template +class point_iterator + : public dispatch::point_iterator_type::type +{ +private: + typedef typename dispatch::point_iterator_type::type base; + + base* base_ptr() + { + return this; + } + + base const* base_ptr() const + { + return this; + } + + template + struct is_convertible + : boost::is_convertible + < + typename dispatch::point_iterator_type::type, + typename dispatch::point_iterator_type::type + > + {}; + + struct enabler {}; + + template friend class point_iterator; + template friend inline point_iterator points_begin(G&); + template friend inline point_iterator points_end(G&); + + point_iterator(base const& base_it) : base(base_it) {} + +public: + point_iterator() {} + + template + point_iterator(point_iterator const& other, + typename boost::enable_if + < + is_convertible, + enabler + >::type = enabler()) + + : base(*other.base_ptr()) + {} +}; + + +// MK:: need to add doc here +template +inline point_iterator +points_begin(Geometry& geometry) +{ + return dispatch::points_begin::apply(geometry); +} + + +// MK:: need to add doc here +template +inline point_iterator +points_end(Geometry& geometry) +{ + return dispatch::points_end::apply(geometry); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/point_iterator_type.hpp b/include/boost/geometry/iterators/point_iterator_type.hpp new file mode 100644 index 000000000..4d50e42c4 --- /dev/null +++ b/include/boost/geometry/iterators/point_iterator_type.hpp @@ -0,0 +1,203 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP +#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail_dispatch +{ + + +template +struct point_iterator_value_type +{ + typedef typename boost::mpl::if_c + < + !boost::is_const::type::value, + typename geometry::point_type::type, + typename geometry::point_type::type const + >::type type; +}; + + + + +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct point_iterator_inner_range_type +{ + typedef typename boost::mpl::if_c + < + !boost::is_const::type::value, + typename boost::range_value::type, + typename boost::range_value::type const + >::type type; +}; + + +template +struct point_iterator_inner_range_type +{ + typedef typename boost::mpl::if_c + < + !boost::is_const::type::value, + typename geometry::ring_type::type, + typename geometry::ring_type::type const + >::type type; +}; + + + +} // namespace detail_dispatch +#endif // DOXYGEN_NO_DETAIL + + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct point_iterator_type +{ + typedef typename boost::range_iterator::type type; +}; + + +template +struct point_iterator_type +{ + typedef typename boost::range_iterator::type type; +}; + + +template +class point_iterator_type +{ +private: + typedef typename detail_dispatch::point_iterator_inner_range_type + < + Polygon + >::type InnerRange; + +public: + typedef concatenate_iterator + < + typename boost::range_iterator::type, + flatten_iterator + < + typename boost::range_iterator + < + typename geometry::interior_type::type + >::type, + typename dispatch::point_iterator_type + < + InnerRange + >::type, + typename detail_dispatch::point_iterator_value_type + < + Polygon + >::type, + dispatch::points_begin, + dispatch::points_end + >, + typename detail_dispatch::point_iterator_value_type::type + > type; +}; + + +template +struct point_iterator_type +{ + typedef typename boost::range_iterator::type type; +}; + + +template +class point_iterator_type +{ +private: + typedef typename detail_dispatch::point_iterator_inner_range_type + < + MultiLinestring + >::type InnerRange; + +public: + typedef flatten_iterator + < + typename boost::range_iterator::type, + typename dispatch::point_iterator_type::type, + typename detail_dispatch::point_iterator_value_type + < + MultiLinestring + >::type, + dispatch::points_begin, + dispatch::points_end + > type; +}; + + +template +class point_iterator_type +{ +private: + typedef typename detail_dispatch::point_iterator_inner_range_type + < + MultiPolygon + >::type InnerRange; + +public: + typedef flatten_iterator + < + typename boost::range_iterator::type, + typename dispatch::point_iterator_type::type, + typename detail_dispatch::point_iterator_value_type + < + MultiPolygon + >::type, + dispatch::points_begin, + dispatch::points_end + > type; +}; + + + + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP diff --git a/test/algorithms/overlay/get_turns_linear_linear.cpp b/test/algorithms/overlay/get_turns_linear_linear.cpp index ebaff5128..fdafbdae2 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -22,14 +22,15 @@ //TEST //#include -//#include -//#include +#include +#include template void test_all() { typedef bg::model::point pt; typedef bg::model::linestring ls; + typedef bg::model::multi_linestring mls; test_geometry("LINESTRING(0 0,2 0)", "LINESTRING(0 0,2 0)", "tii", "txx"); test_geometry("LINESTRING(0 0,2 0)", "LINESTRING(2 0,0 0)", "tix", "txi"); @@ -120,6 +121,14 @@ void test_all() // to_svg("LINESTRING(31 0,15 0,10 5,5 5,4 0,1 0,0 0,-1 1)", "LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)", "test33.svg"); // to_svg("LINESTRING(31 0,15 0,10 5,5 5,4 0,1 0,0 0,-1 1)", "LINESTRING(30 0,3 0,2.5 1,2 0,1 0,0 0,-1 -1)", "test34.svg"); //} + + test_geometry("MULTILINESTRING((0 0,10 0,30 0))", + "MULTILINESTRING((0 10,5 0,20 0,20 0,30 0),(2 0,2 0),(3 0,3 0,3 0))", + expected("mii")("ccc")("ccc")("txx")); + + test_geometry("LINESTRING(2 2,5 -1,15 2,18 0,20 0)", + "LINESTRING(30 0,19 0,18 0,0 0)", + expected("iuu")("iuu")("tiu")("mxi")); } int test_main(int, char* []) diff --git a/test/iterators/Jamfile.v2 b/test/iterators/Jamfile.v2 index 72091f21f..40273145d 100644 --- a/test/iterators/Jamfile.v2 +++ b/test/iterators/Jamfile.v2 @@ -1,8 +1,13 @@ # Boost.Geometry (aka GGL, Generic Geometry Library) # -# Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +# Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +# +# This file was modified by Oracle on 2014. +# Modifications copyright (c) 2014, Oracle and/or its affiliates. +# +# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle # # Use, modification and distribution is subject to the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -12,4 +17,7 @@ test-suite boost-geometry-iterators : [ run closing_iterator.cpp ] [ run ever_circling_iterator.cpp ] + [ run point_iterator.cpp ] + [ run concatenate_iterator.cpp ] + [ run flatten_iterator.cpp ] ; diff --git a/test/iterators/concatenate_iterator.cpp b/test/iterators/concatenate_iterator.cpp new file mode 100644 index 000000000..6a488bcde --- /dev/null +++ b/test/iterators/concatenate_iterator.cpp @@ -0,0 +1,260 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_concatenate_iterator +#endif + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace boost::assign; + +template +std::ostream& print_container(std::ostream& os, + Iterator begin, Iterator end, + std::string const& header) +{ + std::cout << header; + for (Iterator it = begin; it != end; ++it) + { + os << " " << *it; + } + return os; +} + + +template +struct is_odd +{ + inline bool operator()(T const& t) const + { + return t % 2 != 0; + } +}; + +struct test_concatenate_iterator +{ + template + static inline void apply(Container1& c1, Container2& c2, + std::string const& case_id) + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "case id: " << case_id << std::endl; +#endif + typedef typename Container1::const_iterator const_iterator1; + typedef typename Container2::const_iterator const_iterator2; + typedef typename Container1::iterator iterator1; + typedef typename Container2::iterator iterator2; + + typedef boost::geometry::concatenate_iterator + < + const_iterator1, const_iterator2, + typename Container1::value_type const + > const_concat_iterator; + + typedef boost::geometry::concatenate_iterator + < + iterator1, iterator2, typename Container1::value_type + > concat_iterator; + + + concat_iterator begin(c1.begin(), c1.end(), c2.begin()); + concat_iterator end(c1.end(), c2.end()); + const_concat_iterator const_begin(begin); + const_concat_iterator const_end(end); + const_begin = begin; + const_end = end; + + std::size_t size(0); + for (const_concat_iterator it = const_begin; it != const_end; ++it) + { + ++size; + } + BOOST_CHECK( c1.size() + c2.size() == size ); + + size = 0; + for (concat_iterator it = begin; it != end; ++it) + { + ++size; + } + BOOST_CHECK( c1.size() + c2.size() == size ); + +#ifdef GEOMETRY_TEST_DEBUG + print_container(std::cout, c1.begin(), c1.end(), "first :") + << std::endl; + print_container(std::cout, c2.begin(), c2.end(), "second :") + << std::endl; + print_container(std::cout, begin, end, "combined:") + << std::endl; + + if ( begin != end ) + { + std::cout << "min element: " + << *std::min_element(begin, end) + << std::endl; + std::cout << "max element: " + << *std::max_element(const_begin, const_end) + << std::endl; + } +#endif + + { + const_iterator1 it1 = c1.begin(); + const_iterator2 it2 = c2.begin(); + for (const_concat_iterator it = const_begin; it != const_end; ++it) + { + if ( it1 != c1.end() ) + { + BOOST_CHECK( *it == *it1 ); + ++it1; + } + else + { + BOOST_CHECK( *it == *it2 ); + ++it2; + } + } + } + + typedef typename std::iterator_traits + < + concat_iterator + >::value_type value_type; + + if ( c1.size() != 0 ) + { + concat_iterator it_max = std::max_element(begin, end); + const_concat_iterator const_it_max = + std::max_element(const_begin, const_end); + + BOOST_CHECK( it_max == const_it_max ); + + value_type old_value = *const_begin; + value_type new_value = *it_max + 1; + + *begin = *it_max + 1; + BOOST_CHECK( *c1.begin() == new_value ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "modified element of 1st container:" << std::endl; + print_container(std::cout, c1.begin(), c1.end(), "first :") + << std::endl; + print_container(std::cout, begin, end, "combined:") + << std::endl; +#endif + + *begin = old_value; + BOOST_CHECK( *c1.begin() == old_value ); + } + + if ( c2.size() != 0 ) + { + concat_iterator begin2 = begin; + std::size_t counter(0); + while ( counter != c1.size() ) + { + ++counter; + begin2++; + } + + concat_iterator it_max = std::max_element(begin, end); + const_concat_iterator const_it_max = + std::max_element(const_begin, const_end); + + BOOST_CHECK( it_max == const_it_max ); + + value_type old_value = *begin2; + value_type new_value = *it_max + 1; + + *begin2 = *it_max + 1; + BOOST_CHECK( *c2.begin() == new_value ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "modified element of 2nd container:" << std::endl; + print_container(std::cout, c2.begin(), c2.end(), "second :") + << std::endl; + print_container(std::cout, begin, end, "combined:") + << std::endl; +#endif + + *begin2 = old_value; + BOOST_CHECK( *c2.begin() == old_value ); + } + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "odd elements removed:" << std::endl; + print_container(std::cout, begin, end, "before:") + << std::endl; +#endif + concat_iterator new_end = + std::remove_if(begin, end, is_odd()); + + for (const_concat_iterator it = const_begin; it != new_end; ++it) + { + BOOST_CHECK( !is_odd()(*it) ); + } + +#ifdef GEOMETRY_TEST_DEBUG + print_container(std::cout, begin, new_end, "after :") + << std::endl; +#endif + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "====================" << std::endl << std::endl; +#endif + } +}; + + +BOOST_AUTO_TEST_CASE( test_concatenate_iterator_all ) +{ + { + std::vector v; + std::list l; + + test_concatenate_iterator::apply(v, l, "empty_both"); + } + { + std::vector v; + std::list l; + l += 10,11,12,13,14,15,16,17,18,19,20; + + test_concatenate_iterator::apply(v, l, "empty_first"); + } + { + std::vector v; + v += 0,1,2,3,4,5,6; + std::list l; + + test_concatenate_iterator::apply(v, l, "empty_second"); + } + { + std::vector v; + v += 0,1,2,3,4,5,6; + std::list l; + l += 10,11,12,13,14,15,16,17,18,19,20; + + test_concatenate_iterator::apply(l, v, "non_empty"); + } +} diff --git a/test/iterators/flatten_iterator.cpp b/test/iterators/flatten_iterator.cpp new file mode 100644 index 000000000..98e8643e2 --- /dev/null +++ b/test/iterators/flatten_iterator.cpp @@ -0,0 +1,430 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_flatten_iterator +#endif + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace boost::assign; + +template +std::ostream& print_container(std::ostream& os, + Iterator begin, Iterator end, + std::string const& header) +{ + std::cout << header; + for (Iterator it = begin; it != end; ++it) + { + os << " " << *it; + } + return os; +} + + +template +std::ostream& print_nested_container(std::ostream& os, + Iterator begin, Iterator end, + std::string const& header) +{ + std::cout << header; + for (Iterator outer = begin; outer != end; ++outer) + { + os << " ("; + for (BOOST_AUTO_TPL(inner, outer->begin()); + inner != outer->end(); ++inner) + { + if ( inner != outer->begin() ) + { + os << " "; + } + os << *inner; + } + os << ") "; + } + return os; +} + + +template +struct is_odd +{ + inline bool operator()(T const& t) const + { + return t % 2 != 0; + } +}; + + +template +struct is_even +{ + inline bool operator()(T const& t) const + { + return !is_odd()(t); + } +}; + + + +template +struct access_begin +{ + typedef typename boost::mpl::if_ + < + typename boost::is_const::type, + typename InnerContainer::const_iterator, + typename InnerContainer::iterator + >::type return_type; + + static inline return_type apply(InnerContainer& inner) + { + return inner.begin(); + } +}; + + +template +struct access_end +{ + typedef typename boost::mpl::if_ + < + typename boost::is_const::type, + typename InnerContainer::const_iterator, + typename InnerContainer::iterator + >::type return_type; + + static inline return_type apply(InnerContainer& inner) + { + return inner.end(); + } +}; + + +template +std::size_t number_of_elements(NestedContainer const& c) +{ + std::size_t num_elements(0); + for (typename NestedContainer::const_iterator outer = c.begin(); + outer != c.end(); ++outer) + { + num_elements += outer->size(); + } + return num_elements; +} + + +struct test_flatten_iterator +{ + template + static inline void apply(NestedContainer& c, + std::string const& case_id, + std::string const& container_id) + { +#ifdef GEOMETRY_TEST_DEBUG + std::stringstream sstream; + sstream << case_id << " " << "[" << container_id << "]"; + + std::cout << "case id: " << sstream.str() << std::endl; +#endif + typedef typename NestedContainer::const_iterator const_outer_iterator; + typedef typename NestedContainer::iterator outer_iterator; + typedef typename NestedContainer::value_type inner_container; + + typedef typename inner_container::const_iterator const_inner_iterator; + typedef typename inner_container::iterator inner_iterator; + + typedef boost::geometry::flatten_iterator + < + const_outer_iterator, + const_inner_iterator, + typename inner_container::value_type const, + access_begin, + access_end + > const_flatten_iterator; + + typedef boost::geometry::flatten_iterator + < + outer_iterator, + inner_iterator, + typename inner_container::value_type, + access_begin, + access_end + > flatten_iterator; + + + flatten_iterator begin(c.begin(), c.end()); + flatten_iterator end(c.end()); + const_flatten_iterator const_begin(begin); + const_flatten_iterator const_end(end); + const_begin = begin; + const_end = end; + + std::size_t size(0); + for (const_flatten_iterator it = const_begin; it != const_end; ++it) + { + ++size; + } + BOOST_CHECK( number_of_elements(c) == size ); + + size = 0; + for (flatten_iterator it = begin; it != end; ++it) + { + ++size; + } + BOOST_CHECK( number_of_elements(c) == size ); + +#ifdef GEOMETRY_TEST_DEBUG + print_nested_container(std::cout, c.begin(), c.end(), "nested :") + << std::endl; + print_container(std::cout, begin, end, "flattened :") + << std::endl; + + if ( begin != end ) + { + std::cout << "min element: " + << *std::min_element(begin, end) + << std::endl; + std::cout << "max element: " + << *std::max_element(const_begin, const_end) + << std::endl; + } +#endif + + { + const_flatten_iterator it = begin; + const_outer_iterator outer_begin = c.begin(); + const_outer_iterator outer_end = c.end(); + for (const_outer_iterator outer = outer_begin; + outer != outer_end; ++outer) + { + const_inner_iterator inner_begin = outer->begin(); + const_inner_iterator inner_end = outer->end(); + for (const_inner_iterator inner = inner_begin; + inner != inner_end; ++inner, it++) + // it++, instead of ++it, on purpose here + { + BOOST_CHECK( *it == *inner ); + } + } + } + + typedef typename std::iterator_traits + < + flatten_iterator + >::value_type value_type; + + if ( begin != end ) + { + flatten_iterator it_max = std::max_element(begin, end); + const_flatten_iterator const_it_max = + std::max_element(const_begin, const_end); + + BOOST_CHECK( it_max == const_it_max ); + BOOST_CHECK( *it_max == *const_it_max ); + + value_type old_value = *const_begin; + value_type new_value = *it_max + 1; + + *begin = *it_max + 1; + const_outer_iterator outer = c.begin(); + while ( outer->begin() == outer->end() ) + { + ++outer; + } + const_inner_iterator inner = outer->begin(); + + BOOST_CHECK( *inner == new_value ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "modified 1st element of 1st non-empty " + << "inner container:" << std::endl; + print_nested_container(std::cout, c.begin(), c.end(), "nested :") + << std::endl; + print_container(std::cout, begin, end, "flattened:") + << std::endl; +#endif + + *begin = old_value; + BOOST_CHECK( *inner == old_value ); + } + + + if ( begin != end ) + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "odd elements removed:" << std::endl; + print_nested_container(std::cout, c.begin(), c.end(), + "nested before:") + << std::endl; + print_container(std::cout, begin, end, + "flattended before:") + << std::endl; +#endif + typename std::iterator_traits::difference_type + num_even = std::count_if(begin, end, is_even()); + + flatten_iterator new_end = + std::remove_if(begin, end, is_odd()); + + std::size_t new_size(0); + for (const_flatten_iterator it = const_begin; it != new_end; ++it) + { + ++new_size; + BOOST_CHECK( !is_odd()(*it) ); + } + BOOST_CHECK( new_size == static_cast(num_even) ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + print_nested_container(std::cout, c.begin(), c.end(), + "nested after (all elements) :") + << std::endl; + print_container(std::cout, begin, new_end, "flattened after :") + << std::endl; +#endif + } + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "====================" << std::endl << std::endl; +#endif + } +}; + + + +// the actual test cases -- START +template +struct test_case_per_container; + +template<> +struct test_case_per_container<0> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + test_flatten_iterator::apply(c, case_id, container_id); + } +}; + +template<> +struct test_case_per_container<1> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + for (int i = 0; i < 5; ++i) + { + c += typename NestedContainer::value_type(); + } + test_flatten_iterator::apply(c, case_id, container_id); + } +}; + +template<> +struct test_case_per_container<2> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + typename NestedContainer::value_type ic[4]; + + ic[0] += 5,4,3,2,1; + ic[1] += 6,7,8; + ic[2] += 9; + ic[3] += 9,8,7,6,5; + c += ic[0],ic[1],ic[2],ic[3]; + + test_flatten_iterator::apply(c, case_id, container_id); + } +}; + +template<> +struct test_case_per_container<3> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + typename NestedContainer::value_type ic[20]; + + ic[2] += 5,4,3,2,1; + ic[3] += 6,7,8; + ic[8] += 9; + ic[9] += 9,8,7,6,5; + ic[14] += 4,3,2,1; + for (std::size_t i = 0; i < 20; ++i) + { + c += ic[i]; + } + + test_flatten_iterator::apply(c, case_id, container_id); + } +}; +// the actual test cases -- END + + + +template +inline void test_case_all_containers(std::string const& case_id) +{ + typedef typename std::vector > VV; + typedef typename std::vector > VL; + typedef typename std::list > LV; + typedef typename std::list > LL; + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif + test_case_per_container::template apply(case_id, "VV"); + test_case_per_container::template apply(case_id, "VL"); + test_case_per_container::template apply(case_id, "LV"); + test_case_per_container::template apply(case_id, "LL"); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "********************************************************" + << std::endl << std::endl; +#endif +} + + + +BOOST_AUTO_TEST_CASE( test_flatten_iterator_all ) +{ + test_case_all_containers<0>("empty"); + test_case_all_containers<1>("case1"); + test_case_all_containers<2>("case2"); + test_case_all_containers<3>("case3"); +} diff --git a/test/iterators/point_iterator.cpp b/test/iterators/point_iterator.cpp new file mode 100644 index 000000000..13d77fdf8 --- /dev/null +++ b/test/iterators/point_iterator.cpp @@ -0,0 +1,468 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + + +#include + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_point_iterator +#endif + +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace bg = ::boost::geometry; +namespace ba = ::boost::assign; + +typedef bg::model::point point_type; +typedef bg::model::point point_type_3d; +typedef bg::model::linestring linestring_type; +typedef bg::model::polygon polygon_type; //ccw, open + +// multi geometries +typedef bg::model::multi_point multi_point_type; +typedef bg::model::multi_point multi_point_type_3d; +typedef bg::model::multi_linestring multi_linestring_type; +typedef bg::model::multi_polygon multi_polygon_type; + +typedef boost::tuple tuple_point_type; +typedef boost::tuple tuple_point_type_3d; +typedef std::vector tuple_multi_point_type; +typedef std::vector tuple_multi_point_type_3d; + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type) +BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type_3d) + + +template +Geometry from_wkt(std::string const& wkt) +{ + Geometry geometry; + boost::geometry::read_wkt(wkt, geometry); + return geometry; +} + + +struct equals +{ + template + static inline std::size_t number_of_elements(Iterator begin, + Iterator end) + { + std::size_t num_elems(0); + for (Iterator it = begin; it != end; ++it) + { + ++num_elems; + } + return num_elems; + } + + template + static inline bool apply(Iterator1 begin1, Iterator1 end1, + Iterator2 begin2, Iterator2 end2) + { + std::size_t num_points1 = number_of_elements(begin1, end1); + std::size_t num_points2 = number_of_elements(begin2, end2); + + if ( num_points1 != num_points2 ) + { + return false; + } + + Iterator1 it1 = begin1; + Iterator2 it2 = begin2; + for (; it1 != end1; ++it1, ++it2) + { + if ( !bg::equals(*it1, *it2) ) + { + return false; + } + } + return true; + } +}; + + +struct test_assignment +{ + template + static inline void apply(Iterator it, ConstIterator cit, + Value const& value1, Value const& value2) + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "== before assignment ==" << std::endl; + std::cout << "value1: " << bg::wkt(value1) << std::endl; + std::cout << "value2: " << bg::wkt(value2) << std::endl; + std::cout << "*it : " << bg::wkt(*it) << std::endl; + std::cout << "*cit : " << bg::wkt(*cit) << std::endl; +#endif + + BOOST_CHECK( bg::equals(*it, value1) ); + BOOST_CHECK( !bg::equals(*it, value2) ); + BOOST_CHECK( bg::equals(*cit, value1) ); + BOOST_CHECK( !bg::equals(*cit, value2) ); + + *it = value2; + BOOST_CHECK( bg::equals(*it, value2) ); + BOOST_CHECK( !bg::equals(*it, value1) ); + BOOST_CHECK( bg::equals(*cit, value2) ); + BOOST_CHECK( !bg::equals(*cit, value1) ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "== after 1st assignment ==" << std::endl; + std::cout << "value1: " << bg::wkt(value1) << std::endl; + std::cout << "value2: " << bg::wkt(value2) << std::endl; + std::cout << "*it : " << bg::wkt(*it) << std::endl; + std::cout << "*cit : " << bg::wkt(*cit) << std::endl; +#endif + + *it = value1; + BOOST_CHECK( bg::equals(*it, value1) ); + BOOST_CHECK( !bg::equals(*it, value2) ); + BOOST_CHECK( bg::equals(*cit, value1) ); + BOOST_CHECK( !bg::equals(*cit, value2) ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "== after 2nd assignment ==" << std::endl; + std::cout << "value1: " << bg::wkt(value1) << std::endl; + std::cout << "value2: " << bg::wkt(value2) << std::endl; + std::cout << "*it : " << bg::wkt(*it) << std::endl; + std::cout << "*cit : " << bg::wkt(*cit) << std::endl; + std::cout << std::endl; +#endif + } +}; + + +template +struct test_point_iterator_of_geometry +{ + template + static inline void base_test(G& geometry, + PointRange const& point_range, + std::string const& header) + { + typedef bg::point_iterator point_iterator; + typedef bg::point_iterator const_point_iterator; + + point_iterator begin = bg::points_begin(geometry); + point_iterator end = bg::points_end(geometry); + + BOOST_CHECK( equals::apply(begin, end, + bg::points_begin(point_range), + bg::points_end(point_range)) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << header << " geometry: " << bg::wkt(geometry) << std::endl; + std::cout << "point range: ("; + for (point_iterator pit = begin; pit != end; ++pit) + { + std::cout << " " << bg::dsv(*pit); + } + std::cout << " )" << std::endl; + + typedef bg::point_iterator point_range_iterator; + + point_range_iterator rng_begin = bg::points_begin(point_range); + point_range_iterator rng_end = bg::points_end(point_range); + std::cout << "expected point range: ("; + for (point_range_iterator pit = rng_begin; pit != rng_end; ++pit) + { + std::cout << " " << bg::dsv(*pit); + } + std::cout << " )" << std::endl; +#endif + } + + static inline void apply(Geometry geometry, PointRange const& point_range) + { + base_test(geometry, point_range, "non-const"); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; +#endif + + base_test(geometry, point_range, "const"); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif + + // testing construction of const and non-const iterator + typedef bg::point_iterator point_iterator; + typedef bg::point_iterator const_point_iterator; + + point_iterator begin = bg::points_begin(geometry); + point_iterator end = bg::points_end(geometry); + + const_point_iterator const_begin = bg::points_begin(geometry); + const_point_iterator const_end = bg::points_end(geometry); + + // testing assignment of non-const to const iterator + const_begin = begin; + const_end = end; + + // testing dereferencing/assignment + if ( begin != end ) + { + typedef typename bg::point_type::type point; + + point p = *begin; + point q = bg::make_zero(); + + test_assignment::apply(begin, const_begin, p, q); + + *begin = q; + test_assignment::apply(begin, const_begin, q, p); + + *begin = p; + } + } +}; + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_linestring_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** LINESTRING ***" << std::endl; +#endif + + typedef tuple_multi_point_type TMP; + typedef linestring_type L; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("LINESTRING()"), + TMP() + ); + + tester::apply(from_wkt("LINESTRING(3 3,4 4,5 5)"), + ba::tuple_list_of(3,3)(4,4)(5,5) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_polygon_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** POLYGON ***" << std::endl; +#endif + + typedef tuple_multi_point_type TMP; + typedef polygon_type P; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt

("POLYGON()"), + TMP() + ); + + tester::apply(from_wkt

("POLYGON(())"), + TMP() + ); + + tester::apply(from_wkt

("POLYGON((1 1,9 1,9 9,1 9),(5 5,6 5,6 6,5 6))"), + ba::tuple_list_of(1,1)(9,1)(9,9)(1,9)(5,5)(6,5)(6,6)(5,6) + ); + + tester::apply(from_wkt

("POLYGON((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),())"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9) + ); + + tester::apply(from_wkt

("POLYGON((),(3 3,4 4,5 5),(),(),(6 6,7 7,8 8),(),(),(9 9),())"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multipoint_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTIPOINT ***" << std::endl; +#endif + + typedef tuple_multi_point_type TMP; + typedef multi_point_type MP; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTIPOINT()"), + TMP() + ); + + tester::apply(from_wkt("MULTIPOINT(3 3,4 4,5 5)"), + ba::tuple_list_of(3,3)(4,4)(5,5) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multipoint_3d_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTIPOINT 3D ***" << std::endl; +#endif + + typedef tuple_multi_point_type_3d TMP; + typedef multi_point_type_3d MP; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTIPOINT()"), + TMP() + ); + + tester::apply(from_wkt("MULTIPOINT(3 3 3,4 4 4,5 5 5)"), + ba::tuple_list_of(3,3,3)(4,4,4)(5,5,5) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multilinestring_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTILINESTRING ***" << std::endl; +#endif + + typedef tuple_multi_point_type TMP; + typedef multi_linestring_type ML; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTILINESTRING()"), + TMP() + ); + + tester::apply(from_wkt("MULTILINESTRING(())"), + TMP() + ); + + tester::apply(from_wkt("MULTILINESTRING((),(),())"), + TMP() + ); + + tester::apply(from_wkt("MULTILINESTRING((1 1,2 2,3 3),(3 3,4 4,5 5),(6 6))"), + ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6) + ); + + tester::apply(from_wkt("MULTILINESTRING((),(),(1 1,2 2,3 3),(),(),(3 3,4 4,5 5),(),(6 6),(),(),())"), + ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multipolygon_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTIPOLYGON ***" << std::endl; +#endif + + typedef tuple_multi_point_type TMP; + typedef multi_polygon_type MPL; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTIPOLYGON()"), + TMP() + ); + + tester::apply(from_wkt("MULTIPOLYGON( () )"), + TMP() + ); + + tester::apply(from_wkt("MULTIPOLYGON( (()) )"), + TMP() + ); + + tester::apply(from_wkt("MULTIPOLYGON( ((),()) )"), + TMP() + ); + + tester::apply(from_wkt("MULTIPOLYGON(((3 3,4 4,5 5),(6 6,7 7,8 8),(9 9)),((1 1,2 2,10 10),(11 11,12 12)))"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\ + (1,1)(2,2)(10,10)(11,11)(12,12) + ); + + tester::apply(from_wkt("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()))"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\ + (1,1)(2,2)(10,10)(11,11)(12,12)(13,13) + ); + + tester::apply(from_wkt("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()),((),(),()))"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\ + (1,1)(2,2)(10,10)(11,11)(12,12)(13,13) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif +}