diff --git a/doc/reference.qbk b/doc/reference.qbk index e84115ece..699712399 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -89,7 +89,10 @@ [include generated/clear.qbk] [include generated/convert.qbk] [include generated/convex_hull.qbk] + +[section:correct correct] [include generated/correct.qbk] +[endsect] [section:covered_by covered_by] [include generated/covered_by.qbk] diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 9758b4c92..aca0f84d1 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -18,6 +18,32 @@ [section:release_notes Release Notes] +[/=================] +[heading Boost 1.65] +[/=================] + +[*Improvements] + +* Add correct() overload taking area strategy +* Add missing relational operations (covered_by, crosses, equals, etc.) for MultiPoint/AnyGeometry + +[*Solved issues] + +* [@https://svn.boost.org/trac/boost/ticket/12410 12410] Lack of support of geographic coordinate system in correct() +* [@https://svn.boost.org/trac/boost/ticket/13035 13035] Wrong result of non-cartesian intersection strategies for segments near poles. +* [@https://svn.boost.org/trac/boost/ticket/13057 13057] Wrong result of intersects() for linestrings caused by numerical issue in disjoint() for boxes. + +[*Bugfixes] + +* Fix is_valid which could return false for multipolygons where an interior ring touches another interior ring +* Fix is_valid which could return false for multipolygons where a polygon was located in an interior ring, all touching each other +* Fix union which could produce invalid results (for some cases, this needs to define BOOST_GEOMETRY_INCLUDE_SELF_TURNS) +* Fix intersection (idem), but some cases are still not yet valid +* Fix difference (idem), but some cases are still not yet valid +* Fix propagation of area strategy into the internals of various algorithms from intersection strategy +* Fix uninitialized variable in relate and reference to temporary in overlay +* Fix error in disjoint for geographic Segment/Box + [/=================] [heading Boost 1.64] [/=================] diff --git a/include/boost/geometry/algorithms/correct.hpp b/include/boost/geometry/algorithms/correct.hpp index 5d3b6939a..a572d921d 100644 --- a/include/boost/geometry/algorithms/correct.hpp +++ b/include/boost/geometry/algorithms/correct.hpp @@ -5,6 +5,10 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -61,7 +65,8 @@ namespace detail { namespace correct template struct correct_nop { - static inline void apply(Geometry& ) + template + static inline void apply(Geometry& , Strategy const& ) {} }; @@ -104,8 +109,8 @@ struct correct_box_loop template struct correct_box { - - static inline void apply(Box& box) + template + static inline void apply(Box& box, Strategy const& ) { // Currently only for Cartesian coordinates // (or spherical without crossing dateline) @@ -119,18 +124,12 @@ struct correct_box // Close a ring, if not closed -template +template class Predicate> struct correct_ring { typedef typename point_type::type point_type; typedef typename coordinate_type::type coordinate_type; - typedef typename strategy::area::services::default_strategy - < - typename cs_tag::type, - point_type - >::type strategy_type; - typedef detail::area::ring_area < order_as_direction::value>::value, @@ -138,7 +137,8 @@ struct correct_ring > ring_area_type; - static inline void apply(Ring& r) + template + static inline void apply(Ring& r, Strategy const& strategy) { // Check close-ness if (boost::size(r) > 2) @@ -158,10 +158,10 @@ struct correct_ring } } // Check area - Predicate predicate; - typedef typename default_area_result::type area_result_type; - area_result_type const zero = area_result_type(); - if (predicate(ring_area_type::apply(r, strategy_type()), zero)) + typedef typename Strategy::return_type area_result_type; + Predicate predicate; + area_result_type const zero = 0; + if (predicate(ring_area_type::apply(r, strategy), zero)) { std::reverse(boost::begin(r), boost::end(r)); } @@ -174,15 +174,15 @@ template struct correct_polygon { typedef typename ring_type::type ring_type; - typedef typename default_area_result::type area_result_type; - - static inline void apply(Polygon& poly) + + template + static inline void apply(Polygon& poly, Strategy const& strategy) { correct_ring < ring_type, - std::less - >::apply(exterior_ring(poly)); + std::less + >::apply(exterior_ring(poly), strategy); typename interior_return_type::type rings = interior_rings(poly); @@ -192,8 +192,8 @@ struct correct_polygon correct_ring < ring_type, - std::greater - >::apply(*it); + std::greater + >::apply(*it, strategy); } } }; @@ -237,7 +237,7 @@ struct correct : detail::correct::correct_ring < Ring, - std::less::type> + std::less > {}; @@ -281,29 +281,36 @@ namespace resolve_variant { template struct correct { - static inline void apply(Geometry& geometry) + template + static inline void apply(Geometry& geometry, Strategy const& strategy) { concepts::check(); - dispatch::correct::apply(geometry); + dispatch::correct::apply(geometry, strategy); } }; template struct correct > { + template struct visitor: boost::static_visitor { + Strategy const& m_strategy; + + visitor(Strategy const& strategy): m_strategy(strategy) {} + template void operator()(Geometry& geometry) const { - correct::apply(geometry); + correct::apply(geometry, m_strategy); } }; + template static inline void - apply(boost::variant& geometry) + apply(boost::variant& geometry, Strategy const& strategy) { - boost::apply_visitor(visitor(), geometry); + boost::apply_visitor(visitor(strategy), geometry); } }; @@ -325,7 +332,37 @@ struct correct > template inline void correct(Geometry& geometry) { - resolve_variant::correct::apply(geometry); + typedef typename point_type::type point_type; + + typedef typename strategy::area::services::default_strategy + < + typename cs_tag::type, + point_type + >::type strategy_type; + + resolve_variant::correct::apply(geometry, strategy_type()); +} + +/*! +\brief Corrects a geometry +\details Corrects a geometry: all rings which are wrongly oriented with respect + to their expected orientation are reversed. To all rings which do not have a + closing point and are typed as they should have one, the first point is + appended. Also boxes can be corrected. +\ingroup correct +\tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{Area} +\param geometry \param_geometry which will be corrected if necessary +\param strategy \param_strategy{area} + +\qbk{distinguish,with strategy} + +\qbk{[include reference/algorithms/correct.qbk]} +*/ +template +inline void correct(Geometry& geometry, Strategy const& strategy) +{ + resolve_variant::correct::apply(geometry, strategy); } #if defined(_MSC_VER) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index aa6302f39..4bb7a281f 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -142,10 +142,20 @@ struct buffered_piece_collection robust_point_type >::type robust_comparable_radius_type; - typedef typename strategy::side::services::default_strategy + typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; + + typedef typename IntersectionStrategy::template area_strategy < - typename cs_tag::type - >::type side_strategy; + point_type + >::type area_strategy_type; + + typedef typename IntersectionStrategy::template area_strategy + < + robust_point_type + >::type robust_area_strategy_type; + + typedef typename area_strategy_type::return_type area_result_type; + typedef typename robust_area_strategy_type::return_type robust_area_result_type; typedef typename geometry::rescale_policy_type < @@ -306,7 +316,10 @@ struct buffered_piece_collection cluster_type m_clusters; - IntersectionStrategy const& m_intersection_strategy; + IntersectionStrategy m_intersection_strategy; + side_strategy_type m_side_strategy; + area_strategy_type m_area_strategy; + robust_area_strategy_type m_robust_area_strategy; RobustPolicy const& m_robust_policy; struct redundant_turn @@ -321,6 +334,9 @@ struct buffered_piece_collection RobustPolicy const& robust_policy) : m_first_piece_index(-1) , m_intersection_strategy(intersection_strategy) + , m_side_strategy(intersection_strategy.get_side_strategy()) + , m_area_strategy(intersection_strategy.template get_area_strategy()) + , m_robust_area_strategy(intersection_strategy.template get_area_strategy()) , m_robust_policy(robust_policy) {} @@ -699,7 +715,7 @@ struct buffered_piece_collection ++it) { piece& pc = *it; - if (geometry::area(pc.robust_ring) < 0) + if (geometry::area(pc.robust_ring, m_robust_area_strategy) < 0) { // Rings can be ccw: // - in a concave piece @@ -1220,14 +1236,9 @@ struct buffered_piece_collection inline void enrich() { - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type side_strategy_type; - enrich_intersection_points(m_turns, m_clusters, offsetted_rings, offsetted_rings, - m_robust_policy, side_strategy_type()); + m_robust_policy, m_side_strategy); } // Discards all rings which do have not-OK intersection points only. @@ -1314,7 +1325,7 @@ struct buffered_piece_collection buffered_ring& ring = *it; if (! ring.has_intersections() && boost::size(ring) > 0u - && geometry::area(ring) < 0) + && geometry::area(ring, m_area_strategy) < 0) { if (! point_coveredby_original(geometry::range::front(ring))) { @@ -1391,7 +1402,7 @@ struct buffered_piece_collection template inline OutputIterator assign(OutputIterator out) const { - typedef detail::overlay::ring_properties properties; + typedef detail::overlay::ring_properties properties; std::map selected; @@ -1407,7 +1418,7 @@ struct buffered_piece_collection if (! it->has_intersections() && ! it->is_untouched_outside_original) { - properties p = properties(*it); + properties p = properties(*it, m_area_strategy); if (p.valid) { ring_identifier id(0, index, -1); @@ -1423,7 +1434,7 @@ struct buffered_piece_collection it != boost::end(traversed_rings); ++it, ++index) { - properties p = properties(*it); + properties p = properties(*it, m_area_strategy); if (p.valid) { ring_identifier id(2, index, -1); diff --git a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp index f830f8161..87618939b 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp @@ -121,9 +121,18 @@ struct box_box // calculate positive longitude translation with b1_min as origin calc_t const diff_min = math::longitude_distance_unsigned(b1_min, b2_min); calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min + calc_t b2_max_transl = b2_min_transl - constants::period() + diff2; - if (b2_min_transl > b1_max // b2_min right of b1_max - && b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min + // if the translation is too close then use the original point + // note that math::abs(b2_max_transl - b2_max) takes values very + // close to k*2*constants::period() for k=0,1,2,... + if (math::abs(b2_max_transl - b2_max) < constants::period() / 2) + { + b2_max_transl = b2_max; + } + + if (b2_min_transl > b1_max // b2_min right of b1_max + && b2_max_transl < b1_min) // b2_max left of b1_min { return true; } diff --git a/include/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp b/include/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp index bac541219..fccc0ffdb 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp @@ -125,34 +125,6 @@ private: typedef typename boost::range_value::type polygon; typedef is_acceptable_turn base; - template - static inline - bool check_int_ext(Operation const& op1, - detail::overlay::operation_type optype1, - Operation const& op2, - detail::overlay::operation_type optype2) - { - // u/i is acceptable for touch of interior ring with another exterior ring - // (but only if there is a colocated uu-turn of its exterior, TODO) - return op1.seg_id.ring_index == -1 - && op2.seg_id.ring_index >= 0 - && op1.operation == optype1 - && op2.operation == optype2; - } - - template - static inline - bool check_int_int(Operation const& op1, - Operation const& op2, - detail::overlay::operation_type optype) - { - // i/i is acceptable for touching interior/interior rings - return op1.seg_id.ring_index >= 0 - && op2.seg_id.ring_index >= 0 - && op1.operation == optype - && op2.operation == optype; - } - public: template static inline bool apply(Turn const& turn) @@ -172,26 +144,11 @@ public: return true; } - if (turn.method != method_touch) - { - return false; - } - - operation_type const reverse_op - = op == operation_union - ? operation_intersection - : operation_union; - - if ( check_int_int(turn.operations[0], turn.operations[1], reverse_op) - || check_int_ext(turn.operations[0], reverse_op, - turn.operations[1], op) - || check_int_ext(turn.operations[1], reverse_op, - turn.operations[0], op)) - { - return true; - } - - return false; + // Turn is acceptable only in case of a touch(interior) and both lines + // (polygons) do not cross + return (turn.method == method_touch + || turn.method == method_touch_interior) + && turn.touch_only; } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index caacda8a3..ed24b1381 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -89,12 +89,15 @@ private: { boost::ignore_unused(visitor); - // collect all polygons that have turns + // collect all polygons that have crossing turns std::set multi_indices; for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit) { - multi_indices.insert(tit->operations[0].seg_id.multi_index); - multi_indices.insert(tit->operations[1].seg_id.multi_index); + if (! tit->touch_only) + { + multi_indices.insert(tit->operations[0].seg_id.multi_index); + multi_indices.insert(tit->operations[1].seg_id.multi_index); + } } typedef geometry::model::box::type> box_type; diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index 7c8a5d58c..5c6229b79 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -216,14 +217,26 @@ protected: , m_strategy(strategy) {} + template + inline bool is_within(Item const& first, Item const& second) + { + typename point_type::type point; + typedef detail::point_on_border::point_on_range pob; + + // TODO: this should check for a point on the interior, instead + // of on border. Or it should check using the overlap function. + + return pob::apply(point, points_begin(first), points_end(first)) + && geometry::within(point, second, m_strategy); + } + template inline bool apply(partition_item const& item1, partition_item const& item2) { if (! items_overlap - && (geometry::within(*points_begin(*item1.get()), *item2.get(), m_strategy) - || geometry::within(*points_begin(*item2.get()), *item1.get(), m_strategy)) - ) + && (is_within(*item1.get(), *item2.get()) + || is_within(*item2.get(), *item1.get()))) { items_overlap = true; return false; // interrupt diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp index 9ab68fdc4..996da7d96 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -115,7 +115,10 @@ struct is_properly_oriented geometry::closure::value > ring_area_type; - typedef typename default_area_result::type area_result_type; + typedef typename Strategy::template area_strategy + < + point_type + >::type::return_type area_result_type; typename ring_area_predicate < diff --git a/include/boost/geometry/algorithms/detail/multi_modify.hpp b/include/boost/geometry/algorithms/detail/multi_modify.hpp index f0b9ddd3e..23187f932 100644 --- a/include/boost/geometry/algorithms/detail/multi_modify.hpp +++ b/include/boost/geometry/algorithms/detail/multi_modify.hpp @@ -4,6 +4,10 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -40,6 +44,18 @@ struct multi_modify Policy::apply(*it); } } + + template + static inline void apply(MultiGeometry& multi, Strategy const& strategy) + { + typedef typename boost::range_iterator::type iterator_type; + for (iterator_type it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + Policy::apply(*it, strategy); + } + } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index e8bb2c1ac..78160f520 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -107,21 +107,19 @@ static inline bool within_selected_input(Item const& item2, } -template +template struct ring_info_helper { - typedef typename geometry::default_area_result::type area_type; - ring_identifier id; - area_type real_area; - area_type abs_area; + AreaType real_area; + AreaType abs_area; model::box envelope; inline ring_info_helper() : real_area(0), abs_area(0) {} - inline ring_info_helper(ring_identifier i, area_type a) + inline ring_info_helper(ring_identifier i, AreaType const& a) : id(i), real_area(a), abs_area(geometry::math::abs(a)) {} }; @@ -234,11 +232,15 @@ inline void assign_parents(Geometry1 const& geometry1, typedef typename RingMap::mapped_type ring_info_type; typedef typename ring_info_type::point_type point_type; typedef model::box box_type; + typedef typename Strategy::template area_strategy + < + point_type + >::type::return_type area_result_type; typedef typename RingMap::iterator map_iterator_type; { - typedef ring_info_helper helper; + typedef ring_info_helper helper; typedef std::vector vector_type; typedef typename boost::range_iterator::type vector_iterator_type; 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 08bc34218..895952c8f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -190,6 +190,7 @@ struct touch_interior : public base_turn_handler // Q turns left on the right side of P (test "MR3") // Both directions for "intersection" both(ti, operation_intersection); + ti.touch_only = true; } else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1) { @@ -197,6 +198,7 @@ struct touch_interior : public base_turn_handler // Union: take both operation // Intersection: skip both(ti, operation_union); + ti.touch_only = true; } else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q) { @@ -207,6 +209,7 @@ struct touch_interior : public base_turn_handler unsigned int index = side_qk_q == 1 ? index_q : index_p; ti.operations[index].operation = operation_union; ti.operations[1 - index].operation = operation_intersection; + ti.touch_only = true; } else if (side_qk_p == 0) { @@ -346,6 +349,7 @@ struct touch : public base_turn_handler if (side_pk_q2 == -side_qk_q) { ui_else_iu(! q_turns_left, ti); + ti.touch_only = true; return; } @@ -358,6 +362,10 @@ struct touch : public base_turn_handler { ti.operations[1].operation = operation_blocked; } + else + { + ti.touch_only = true; + } //block_second(block_q, ti); return; } @@ -373,6 +381,10 @@ struct touch : public base_turn_handler : side_qi_p1 == 1 || side_qk_p1 == 1 ? operation_union : operation_intersection; + if (! block_q) + { + ti.touch_only = true; + } return; } @@ -400,6 +412,7 @@ struct touch : public base_turn_handler if (side_pk_q1 == side_qk_p1) { uu_else_ii(right_to_left, ti); + ti.touch_only = true; return; } } @@ -418,6 +431,7 @@ struct touch : public base_turn_handler if (side_pk_q2 == side_qk_p1) { ui_else_iu(right_to_left, ti); + ti.touch_only = true; return; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index 5f2cb07fa..f8247cd24 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -66,7 +66,7 @@ struct side_calculator Qj const& m_qj; Qk const& m_qk; - SideStrategy const& m_side_strategy; + SideStrategy m_side_strategy; }; template diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index 90258cc84..10829abd4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -197,7 +197,16 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, typename geometry::ring_type::type > ring_container_type; - typedef ring_properties::type> properties; + typedef typename geometry::point_type::type point_type1; + + typedef ring_properties + < + point_type1, + typename Strategy::template area_strategy + < + point_type1 + >::type::return_type + > properties; // Silence warning C4127: conditional expression is constant #if defined(_MSC_VER) @@ -309,7 +318,7 @@ std::cout << "get turns" << std::endl; #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "enrich" << std::endl; #endif - typename Strategy::side_strategy_type side_strategy; + typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy(); cluster_type clusters; geometry::enrich_intersection_points(turns, @@ -341,10 +350,13 @@ std::cout << "traverse" << std::endl; std::map turn_info_per_ring; get_ring_turn_info(turn_info_per_ring, turns, clusters); + typedef typename Strategy::template area_strategy::type area_strategy_type; + typedef ring_properties - < - typename geometry::point_type::type - > properties; + < + point_type, + typename area_strategy_type::return_type + > properties; // Select all rings which are NOT touched by any intersection point std::map selected_ring_properties; @@ -353,13 +365,15 @@ std::cout << "traverse" << std::endl; // Add rings created during traversal { + area_strategy_type const area_strategy = strategy.template get_area_strategy(); + ring_identifier id(2, 0, -1); for (typename boost::range_iterator::type it = boost::begin(rings); it != boost::end(rings); ++it) { - selected_ring_properties[id] = properties(*it); + selected_ring_properties[id] = properties(*it, area_strategy); selected_ring_properties[id].reversed = ReverseOut; id.multi_index++; } diff --git a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp index abade1fe1..7dbc5d5fa 100644 --- a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp @@ -27,11 +27,11 @@ namespace boost { namespace geometry namespace detail { namespace overlay { -template +template struct ring_properties { typedef Point point_type; - typedef typename default_area_result::type area_type; + typedef AreaType area_type; bool valid; @@ -56,13 +56,13 @@ struct ring_properties , parent_area(-1) {} - template - inline ring_properties(RingOrBox const& ring_or_box) + template + inline ring_properties(RingOrBox const& ring_or_box, AreaStrategy const& strategy) : reversed(false) , discarded(false) , parent_area(-1) { - this->area = geometry::area(ring_or_box); + this->area = geometry::area(ring_or_box, strategy); valid = geometry::point_on_border(this->point, ring_or_box); } diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp index 638bcf474..67a4f4bb7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -59,41 +59,45 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Box const& box, Geometry const& , - ring_identifier const& id, RingPropertyMap& ring_properties) + ring_identifier const& id, RingPropertyMap& ring_properties, + AreaStrategy const& strategy) { - ring_properties[id] = typename RingPropertyMap::mapped_type(box); + ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); } - template + template static inline void apply(Box const& box, - ring_identifier const& id, RingPropertyMap& ring_properties) + ring_identifier const& id, RingPropertyMap& ring_properties, + AreaStrategy const& strategy) { - ring_properties[id] = typename RingPropertyMap::mapped_type(box); + ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); } }; template struct select_rings { - template + template static inline void apply(Ring const& ring, Geometry const& , - ring_identifier const& id, RingPropertyMap& ring_properties) + ring_identifier const& id, RingPropertyMap& ring_properties, + AreaStrategy const& strategy) { if (boost::size(ring) > 0) { - ring_properties[id] = typename RingPropertyMap::mapped_type(ring); + ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy); } } - template + template static inline void apply(Ring const& ring, - ring_identifier const& id, RingPropertyMap& ring_properties) + ring_identifier const& id, RingPropertyMap& ring_properties, + AreaStrategy const& strategy) { if (boost::size(ring) > 0) { - ring_properties[id] = typename RingPropertyMap::mapped_type(ring); + ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy); } } }; @@ -102,14 +106,15 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Polygon const& polygon, Geometry const& geometry, - ring_identifier id, RingPropertyMap& ring_properties) + ring_identifier id, RingPropertyMap& ring_properties, + AreaStrategy const& strategy) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; - per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties); + per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties, strategy); typename interior_return_type::type rings = interior_rings(polygon); @@ -117,18 +122,19 @@ namespace dispatch it = boost::begin(rings); it != boost::end(rings); ++it) { id.ring_index++; - per_ring::apply(*it, geometry, id, ring_properties); + per_ring::apply(*it, geometry, id, ring_properties, strategy); } } - template + template static inline void apply(Polygon const& polygon, - ring_identifier id, RingPropertyMap& ring_properties) + ring_identifier id, RingPropertyMap& ring_properties, + AreaStrategy const& strategy) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; - per_ring::apply(exterior_ring(polygon), id, ring_properties); + per_ring::apply(exterior_ring(polygon), id, ring_properties, strategy); typename interior_return_type::type rings = interior_rings(polygon); @@ -136,7 +142,7 @@ namespace dispatch it = boost::begin(rings); it != boost::end(rings); ++it) { id.ring_index++; - per_ring::apply(*it, id, ring_properties); + per_ring::apply(*it, id, ring_properties, strategy); } } }; @@ -144,9 +150,10 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Multi const& multi, Geometry const& geometry, - ring_identifier id, RingPropertyMap& ring_properties) + ring_identifier id, RingPropertyMap& ring_properties, + AreaStrategy const& strategy) { typedef typename boost::range_iterator < @@ -159,7 +166,7 @@ namespace dispatch for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it) { id.ring_index = -1; - per_polygon::apply(*it, geometry, id, ring_properties); + per_polygon::apply(*it, geometry, id, ring_properties, strategy); id.multi_index++; } } @@ -311,12 +318,16 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2, { typedef typename geometry::tag::type tag1; typedef typename geometry::tag::type tag2; + typedef typename geometry::point_type::type point1_type; + typedef typename geometry::point_type::type point2_type; RingPropertyMap all_ring_properties; dispatch::select_rings::apply(geometry1, geometry2, - ring_identifier(0, -1, -1), all_ring_properties); + ring_identifier(0, -1, -1), all_ring_properties, + strategy.template get_area_strategy()); dispatch::select_rings::apply(geometry2, geometry1, - ring_identifier(1, -1, -1), all_ring_properties); + ring_identifier(1, -1, -1), all_ring_properties, + strategy.template get_area_strategy()); update_ring_selection(geometry1, geometry2, turn_info_per_ring, all_ring_properties, selected_ring_properties, @@ -337,10 +348,12 @@ inline void select_rings(Geometry const& geometry, Strategy const& strategy) { typedef typename geometry::tag::type tag; + typedef typename geometry::point_type::type point_type; RingPropertyMap all_ring_properties; dispatch::select_rings::apply(geometry, - ring_identifier(0, -1, -1), all_ring_properties); + ring_identifier(0, -1, -1), all_ring_properties, + strategy.template get_area_strategy()); update_ring_selection(geometry, geometry, turn_info_per_ring, all_ring_properties, selected_ring_properties, diff --git a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp index 06bf1a293..3a4c2e94a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp @@ -89,6 +89,7 @@ struct turn_info Point point; method_type method; + bool touch_only; // True in case of method touch(interior) and lines do not cross signed_size_type cluster_id; // For multiple turns on same location, >= 0. Else -1 bool discarded; @@ -101,6 +102,7 @@ struct turn_info inline turn_info() : method(method_none) + , touch_only(false) , cluster_id(-1) , discarded(false) , colocated_ii(false) diff --git a/include/boost/geometry/algorithms/detail/point_on_border.hpp b/include/boost/geometry/algorithms/detail/point_on_border.hpp index a5b03d842..831081aa6 100644 --- a/include/boost/geometry/algorithms/detail/point_on_border.hpp +++ b/include/boost/geometry/algorithms/detail/point_on_border.hpp @@ -84,43 +84,49 @@ struct midpoint_helper template struct point_on_range { + // Version with iterator + template + static inline bool apply(Point& point, Iterator begin, Iterator end) + { + Iterator it = begin; + if (it == end) + { + return false; + } + + if (! Midpoint) + { + geometry::detail::conversion::convert_point_to_point(*it, point); + return true; + } + + Iterator prev = it++; + + // Go to next non-duplicate point + while (it != end + && detail::equals::equals_point_point(*it, *prev)) + { + prev = it++; + } + if (it != end) + { + return midpoint_helper + < + Point, + 0, dimension::value + >::apply(point, *prev, *it); + } + return false; + } + + // Version with range template static inline bool apply(Point& point, Range const& range) { typedef typename geometry::cs_tag::type cs_tag; BOOST_STATIC_ASSERT((! Midpoint || boost::is_same::value)); - const std::size_t n = boost::size(range); - if (Midpoint && n > 1) - { - typedef typename boost::range_iterator - < - Range const - >::type iterator; - - iterator it = boost::begin(range); - iterator prev = it++; - while (it != boost::end(range) - && detail::equals::equals_point_point(*it, *prev)) - { - prev = it++; - } - if (it != boost::end(range)) - { - return midpoint_helper - < - Point, - 0, dimension::value - >::apply(point, *prev, *it); - } - } - - if (n > 0) - { - geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point); - return true; - } - return false; + return apply(point, boost::begin(range), boost::end(range)); } }; diff --git a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp index 67cc554cf..654999d8f 100644 --- a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp @@ -165,6 +165,8 @@ private: m_endpoints.reserve(boost::size(m_mls) * 2); + m_has_interior = false; + typedef typename boost::range_iterator::type ls_iterator; for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it ) { diff --git a/include/boost/geometry/formulas/vertex_longitude.hpp b/include/boost/geometry/formulas/vertex_longitude.hpp index e30ae12e1..00f2fd4e7 100644 --- a/include/boost/geometry/formulas/vertex_longitude.hpp +++ b/include/boost/geometry/formulas/vertex_longitude.hpp @@ -1,8 +1,9 @@ // Boost.Geometry -// Copyright (c) 2016 Oracle and/or its affiliates. +// Copyright (c) 2016-2017 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, 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 @@ -306,7 +307,7 @@ public : //Segment lay on meridian if (math::equals(lon1, lon2)) { - return std::max(lat1, lat2); + return (std::max)(lat1, lat2); } BOOST_ASSERT(lon1 < lon2); diff --git a/include/boost/geometry/strategies/geographic/intersection.hpp b/include/boost/geometry/strategies/geographic/intersection.hpp index 84acd149c..59a40f281 100644 --- a/include/boost/geometry/strategies/geographic/intersection.hpp +++ b/include/boost/geometry/strategies/geographic/intersection.hpp @@ -289,6 +289,8 @@ private: typedef typename select_calculation_type ::type calc_t; + static const calc_t c0 = 0; + // normalized spheroid srs::spheroid spheroid = normalized_spheroid(m_spheroid); @@ -325,31 +327,80 @@ private: // TODO: no need to call inverse formula if we know that the points are equal // distance can be set to 0 in this case and azimuth may be not calculated - bool const is_equal_a1_b1 = equals_point_point(a1, b1); - bool const is_equal_a2_b1 = equals_point_point(a2, b1); + bool is_equal_a1_b1 = equals_point_point(a1, b1); + bool is_equal_a2_b1 = equals_point_point(a2, b1); + bool degen_neq_coords = false; - inverse_result res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid); - inverse_result res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid); - inverse_result res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid); - sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth), - is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth)); - if (sides.same<0>()) + inverse_result res_b1_b2, res_b1_a1, res_b1_a2; + if (! b_is_point) { - // Both points are at the same side of other segment, we can leave - return Policy::disjoint(); + res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid); + if (math::equals(res_b1_b2.distance, c0)) + { + b_is_point = true; + degen_neq_coords = true; + } + else + { + res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid); + if (math::equals(res_b1_a1.distance, c0)) + { + is_equal_a1_b1 = true; + } + res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid); + if (math::equals(res_b1_a2.distance, c0)) + { + is_equal_a2_b1 = true; + } + sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth), + is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth)); + if (sides.same<0>()) + { + // Both points are at the same side of other segment, we can leave + return Policy::disjoint(); + } + } } - bool const is_equal_a1_b2 = equals_point_point(a1, b2); + bool is_equal_a1_b2 = equals_point_point(a1, b2); - inverse_result res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid); - inverse_result res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid); - inverse_result res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid); - sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth), - is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth)); - if (sides.same<1>()) + inverse_result res_a1_a2, res_a1_b1, res_a1_b2; + if (! a_is_point) { - // Both points are at the same side of other segment, we can leave - return Policy::disjoint(); + res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid); + if (math::equals(res_a1_a2.distance, c0)) + { + a_is_point = true; + degen_neq_coords = true; + } + else + { + res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid); + if (math::equals(res_a1_b1.distance, c0)) + { + is_equal_a1_b1 = true; + } + res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid); + if (math::equals(res_a1_b2.distance, c0)) + { + is_equal_a1_b2 = true; + } + sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth), + is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth)); + if (sides.same<1>()) + { + // Both points are at the same side of other segment, we can leave + return Policy::disjoint(); + } + } + } + + if(a_is_point && b_is_point) + { + return is_equal_a1_b2 + ? Policy::degenerate(a, true) + : Policy::disjoint() + ; } // NOTE: at this point the segments may still be disjoint @@ -379,11 +430,11 @@ private: { if (a_is_point) { - return collinear_one_degenerated(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, is_b_reversed); + return collinear_one_degenerated(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, is_b_reversed, degen_neq_coords); } else if (b_is_point) { - return collinear_one_degenerated(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, is_a_reversed); + return collinear_one_degenerated(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, is_a_reversed, degen_neq_coords); } else { @@ -392,16 +443,16 @@ private: // use shorter segment if (res_a1_a2.distance <= res_b1_b2.distance) { - calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, dist_a1_a2, dist_a1_b1); - calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, dist_a1_a2, dist_a1_b2); + calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_a1_a2, dist_a1_b1); + calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, res_a1_b1, dist_a1_a2, dist_a1_b2); dist_b1_b2 = dist_a1_b2 - dist_a1_b1; dist_b1_a1 = -dist_a1_b1; dist_b1_a2 = dist_a1_a2 - dist_a1_b1; } else { - calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, dist_b1_b2, dist_b1_a1); - calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, dist_b1_b2, dist_b1_a2); + calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, dist_b1_b2, dist_b1_a1); + calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, res_b1_a1, dist_b1_b2, dist_b1_a2); dist_a1_a2 = dist_b1_a2 - dist_b1_a1; dist_a1_b1 = -dist_b1_a1; dist_a1_b2 = dist_b1_b2 - dist_b1_a1; @@ -549,11 +600,13 @@ private: Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2, ResultInverse const& res_a1_a2, - ResultInverse const& res_a1_bi, - bool is_other_reversed) + ResultInverse const& res_a1_b1, + ResultInverse const& res_a1_b2, + bool is_other_reversed, + bool degen_neq_coords) { CalcT dist_1_2, dist_1_o; - if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_bi, dist_1_2, dist_1_o)) + if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_1_2, dist_1_o, degen_neq_coords)) { return Policy::disjoint(); } @@ -574,13 +627,16 @@ private: static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in Point2 const& b1, Point2 const& b2, // in ResultInverse const& res_a1_a2, // in - ResultInverse const& res_a1_bi, // in - CalcT& dist_a1_a2, CalcT& dist_a1_bi) // out + ResultInverse const& res_a1_b1, // in + ResultInverse const& res_a1_b2, // in + CalcT& dist_a1_a2, // out + CalcT& dist_a1_bi, // out + bool degen_neq_coords = false) // in { dist_a1_a2 = res_a1_a2.distance; - dist_a1_bi = res_a1_bi.distance; - if (! same_direction(res_a1_bi.azimuth, res_a1_a2.azimuth)) + dist_a1_bi = res_a1_b1.distance; + if (! same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth)) { dist_a1_bi = -dist_a1_bi; } @@ -598,6 +654,22 @@ private: return true; } + // check the other endpoint of a very short segment near the pole + if (degen_neq_coords) + { + static CalcT const c0 = 0; + if (math::equals(res_a1_b2.distance, c0)) + { + dist_a1_bi = 0; + return true; + } + else if (math::equals(dist_a1_a2 - res_a1_b2.distance, c0)) + { + dist_a1_bi = dist_a1_a2; + return true; + } + } + // or i1 is on b return segment_ratio(dist_a1_bi, dist_a1_a2).on_segment(); } @@ -825,8 +897,9 @@ private: static inline bool is_endpoint_equal(CalcT const& dist, P1 const& ai, P2 const& b1, P2 const& b2) { + static CalcT const c0 = 0; using geometry::detail::equals::equals_point_point; - return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2)); + return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0)); } template diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index 035961c0a..44b1cc62b 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -302,36 +302,64 @@ struct ecef_segments vec3d_t const b1v = calc_policy.template to_cart3d(b1); vec3d_t const b2v = calc_policy.template to_cart3d(b2); + bool degen_neq_coords = false; side_info sides; typename CalcPolicy::template plane plane2 = calc_policy.get_plane(b1v, b2v); - // not normalized normals, the same as in side strategy - sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v)); - if (sides.same<0>()) + calc_t dist_b1_b2 = 0; + if (! b_is_point) { - // Both points are at same side of other segment, we can leave - return Policy::disjoint(); + calculate_dist(b1v, b2v, plane2, dist_b1_b2); + if (math::equals(dist_b1_b2, c0)) + { + degen_neq_coords = true; + b_is_point = true; + dist_b1_b2 = 0; + } + else + { + // not normalized normals, the same as in side strategy + sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v)); + if (sides.same<0>()) + { + // Both points are at same side of other segment, we can leave + return Policy::disjoint(); + } + } } typename CalcPolicy::template plane plane1 = calc_policy.get_plane(a1v, a2v); - // not normalized normals, the same as in side strategy - sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v)); - if (sides.same<1>()) + calc_t dist_a1_a2 = 0; + if (! a_is_point) { - // Both points are at same side of other segment, we can leave - return Policy::disjoint(); + calculate_dist(a1v, a2v, plane1, dist_a1_a2); + if (math::equals(dist_a1_a2, c0)) + { + degen_neq_coords = true; + a_is_point = true; + dist_a1_a2 = 0; + } + else + { + // not normalized normals, the same as in side strategy + sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v)); + if (sides.same<1>()) + { + // Both points are at same side of other segment, we can leave + return Policy::disjoint(); + } + } } // NOTE: at this point the segments may still be disjoint - calc_t len1, len2; - + calc_t len1 = 0; // point or opposite sides of a sphere/spheroid, assume point - if (! detail::vec_normalize(plane1.normal, len1)) + if (! a_is_point && ! detail::vec_normalize(plane1.normal, len1)) { a_is_point = true; if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0) @@ -340,7 +368,8 @@ struct ecef_segments } } - if (! detail::vec_normalize(plane2.normal, len2)) + calc_t len2 = 0; + if (! b_is_point && ! detail::vec_normalize(plane2.normal, len2)) { b_is_point = true; if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0) @@ -404,30 +433,32 @@ struct ecef_segments { if (a_is_point) { - return collinear_one_degenerated(a, true, b1, b2, a1, a2, b1v, b2v, plane2, a1v); + return collinear_one_degenerated(a, true, b1, b2, a1, a2, b1v, b2v, + plane2, a1v, a2v, dist_b1_b2, degen_neq_coords); } else if (b_is_point) { // b2 used to be consistent with (degenerated) checks above (is it needed?) - return collinear_one_degenerated(b, false, a1, a2, b1, b2, a1v, a2v, plane1, b1v); + return collinear_one_degenerated(b, false, a1, a2, b1, b2, a1v, a2v, + plane1, b1v, b2v, dist_a1_a2, degen_neq_coords); } else { - calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2; - calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2; + calc_t dist_a1_b1, dist_a1_b2; + calc_t dist_b1_a1, dist_b1_a2; // use shorter segment if (len1 <= len2) { - calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, dist_a1_a2, dist_a1_b1); - calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, dist_a1_a2, dist_a1_b2); + calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, b2v, dist_a1_a2, dist_a1_b1); + calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, b1v, dist_a1_a2, dist_a1_b2); dist_b1_b2 = dist_a1_b2 - dist_a1_b1; dist_b1_a1 = -dist_a1_b1; dist_b1_a2 = dist_a1_a2 - dist_a1_b1; } else { - calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, dist_b1_b2, dist_b1_a1); - calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, dist_b1_b2, dist_b1_a2); + calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, a2v, dist_b1_b2, dist_b1_a1); + calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, a1v, dist_b1_b2, dist_b1_a2); dist_a1_a2 = dist_b1_a2 - dist_b1_a1; dist_a1_b1 = -dist_b1_a1; dist_a1_b2 = dist_b1_b2 - dist_b1_a1; @@ -487,10 +518,11 @@ struct ecef_segments vec3d_t i1; intersection_point_flag ip_flag; - calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1; + calc_t dist_a1_i1, dist_b1_i1; if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v, - plane1, plane2, calc_policy, sides, - i1, dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1, ip_flag)) + plane1, plane2, calc_policy, + sides, dist_a1_a2, dist_b1_b2, + i1, dist_a1_i1, dist_b1_i1, ip_flag)) { // intersects segment_intersection_info @@ -520,12 +552,14 @@ private: collinear_one_degenerated(Segment const& segment, bool degenerated_a, Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2, - Vec3d const& v1, Vec3d const& v2, + Vec3d const& a1v, Vec3d const& a2v, Plane const& plane, - Vec3d const& vother) + Vec3d const& b1v, Vec3d const& b2v, + CalcT const& dist_1_2, + bool degen_neq_coords) { - CalcT dist_1_2, dist_1_o; - return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, plane, vother, dist_1_2, dist_1_o) + CalcT dist_1_o; + return ! calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane, b1v, b2v, dist_1_2, dist_1_o, degen_neq_coords) ? Policy::disjoint() : Policy::one_degenerate(segment, segment_ratio(dist_1_o, dist_1_2), degenerated_a); } @@ -536,11 +570,14 @@ private: Vec3d const& a1v, // in Vec3d const& a2v, // in Plane const& plane1, // in - Vec3d const& b1v_or_b2v, // in - CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out + Vec3d const& b1v, // in + Vec3d const& b2v, // in + CalcT const& dist_a1_a2, // in + CalcT& dist_a1_i1, // out + bool degen_neq_coords = false) // in { // calculate dist_a1_a2 and dist_a1_i1 - calculate_dists(a1v, a2v, plane1, b1v_or_b2v, dist_a1_a2, dist_a1_i1); + calculate_dist(a1v, a2v, plane1, b1v, dist_a1_i1); // if i1 is close to a1 and b1 or b2 is equal to a1 if (is_endpoint_equal(dist_a1_i1, a1, b1, b2)) @@ -555,6 +592,26 @@ private: return true; } + // check the other endpoint of a very short segment near the pole + if (degen_neq_coords) + { + static CalcT const c0 = 0; + + CalcT dist_a1_i2 = 0; + calculate_dist(a1v, a2v, plane1, b2v, dist_a1_i2); + + if (math::equals(dist_a1_i2, c0)) + { + dist_a1_i1 = 0; + return true; + } + else if (math::equals(dist_a1_a2 - dist_a1_i2, c0)) + { + dist_a1_i1 = dist_a1_a2; + return true; + } + } + // or i1 is on b return segment_ratio(dist_a1_i1, dist_a1_a2).on_segment(); } @@ -568,15 +625,17 @@ private: Plane const& plane2, // in CalcPolicy const& calc_policy, // in side_info const& sides, // in - Vec3d & ip, // out - CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out - CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out - intersection_point_flag& ip_flag) // out + CalcT const& dist_a1_a2, // in + CalcT const& dist_b1_b2, // in + Vec3d & ip, // out + CalcT& dist_a1_ip, // out + CalcT& dist_b1_ip, // out + intersection_point_flag& ip_flag) // out { Vec3d ip1, ip2; calc_policy.intersection_points(plane1, plane2, ip1, ip2); - calculate_dists(a1v, a2v, plane1, ip1, dist_a1_a2, dist_a1_ip); + calculate_dist(a1v, a2v, plane1, ip1, dist_a1_ip); ip = ip1; // choose the opposite side of the globe if the distance is shorter @@ -602,7 +661,7 @@ private: return false; } - calculate_dists(b1v, b2v, plane2, ip, dist_b1_b2, dist_b1_ip); + calculate_dist(b1v, b2v, plane2, ip, dist_b1_ip); bool is_on_b = false, is_near_b1 = false, is_near_b2 = false; if (! is_potentially_crossing(dist_b1_b2, dist_b1_ip, is_on_b, is_near_b1, is_near_b2)) @@ -701,20 +760,26 @@ private: } template - static inline void calculate_dists(Vec3d const& a1v, // in - Vec3d const& a2v, // in - Plane const& plane1, // in - Vec3d const& i1, // in - CalcT& dist_a1_a2, // out - CalcT& dist_a1_i1) // out + static inline void calculate_dist(Vec3d const& a1v, // in + Vec3d const& a2v, // in + Plane const& plane1, // in + CalcT& dist_a1_a2) // out { - //CalcT const c0 = 0; - CalcT const c1 = 1; - CalcT const c2 = 2; - CalcT const c4 = 4; - - CalcT cos_a1_a2 = plane1.cos_angle_between(a1v, a2v); + static CalcT const c1 = 1; + CalcT const cos_a1_a2 = plane1.cos_angle_between(a1v, a2v); dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi] + } + + template + static inline void calculate_dist(Vec3d const& a1v, // in + Vec3d const& /*a2v*/, // in + Plane const& plane1, // in + Vec3d const& i1, // in + CalcT& dist_a1_i1) // out + { + static CalcT const c1 = 1; + static CalcT const c2 = 2; + static CalcT const c4 = 4; bool is_forward = true; CalcT cos_a1_i1 = plane1.cos_angle_between(a1v, i1, is_forward); @@ -728,7 +793,19 @@ private: dist_a1_i1 += c4; // += 2pi } } - + /* + template + static inline void calculate_dists(Vec3d const& a1v, // in + Vec3d const& a2v, // in + Plane const& plane1, // in + Vec3d const& i1, // in + CalcT& dist_a1_a2, // out + CalcT& dist_a1_i1) // out + { + calculate_dist(a1v, a2v, plane1, dist_a1_a2); + calculate_dist(a1v, a2v, plane1, i1, dist_a1_i1); + } + */ // the dist of the ip on the other side of the sphere template static inline CalcT dist_of_i2(CalcT const& dist_a1_i1) @@ -769,8 +846,9 @@ private: static inline bool is_endpoint_equal(CalcT const& dist, P1 const& ai, P2 const& b1, P2 const& b2) { + static CalcT const c0 = 0; using geometry::detail::equals::equals_point_point; - return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2)); + return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0)); } template diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index 1fc356f64..b683b4c21 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -963,6 +963,12 @@ inline void test_open_multipolygons() "MULTIPOLYGON(((10 5,5 10,0 5,5 0),(10 5,5 4,4 6)),((10 5,10 0,20 0,20 10,10 10),(10 5,18 8,15 3)))", true); + // Two polygons, one inside interior of other one, touching all at same point (0,0) + test::apply + ("mpg23", + "MULTIPOLYGON(((0 0,10 0,10 10,0 10),(0 0,1 9,9 9,9 1)),((0 0,8 2,8 8,2 8)))", + true); + // MySQL report 12.06.2015 { std::string wkt = "MULTIPOLYGON(" @@ -1186,11 +1192,8 @@ inline void test_open_multipolygons() BOOST_AUTO_TEST_CASE( test_is_valid_multipolygon ) { - bool const allow_duplicates = true; - bool const do_not_allow_duplicates = !allow_duplicates; - - test_open_multipolygons(); - test_open_multipolygons(); + test_open_multipolygons(); + test_open_multipolygons(); } diff --git a/test/algorithms/overlay/get_turn_info.cpp b/test/algorithms/overlay/get_turn_info.cpp index 24fc5ac74..6310e248e 100644 --- a/test/algorithms/overlay/get_turn_info.cpp +++ b/test/algorithms/overlay/get_turn_info.cpp @@ -36,6 +36,7 @@ void test_with_point(std::string const& caseid, T pi_x, T pi_y, T pj_x, T pj_y, T pk_x, T pk_y, T qi_x, T qi_y, T qj_x, T qj_y, T qk_x, T qk_y, bg::detail::overlay::method_type expected_method, + bool expected_touch_only, T ip_x, T ip_y, std::string const& expected, T ip_x2, T ip_y2) @@ -100,6 +101,10 @@ void test_with_point(std::string const& caseid, if (! info.empty()) { BOOST_CHECK_EQUAL(info[0].method, expected_method); + BOOST_CHECK_MESSAGE(info[0].touch_only == expected_touch_only, + caseid + << " detected: " << info[0].touch_only + << " expected: " << expected_touch_only); BOOST_CHECK_CLOSE(bg::get<0>(info[0].point), ip_x, 0.001); BOOST_CHECK_CLOSE(bg::get<1>(info[0].point), ip_y, 0.001); @@ -164,6 +169,8 @@ void test_with_point(std::string const& caseid, op.clear(); op += bg::method_char(it->method); + op += ' '; + op += (it->touch_only ? 'o' : '*'); if (info.size() != 1) { op += ch; @@ -183,6 +190,7 @@ void test_both(std::string const& caseid, T qi_x, T qi_y, T qj_x, T qj_y, T qk_x, T qk_y, bg::detail::overlay::method_type method = bg::detail::overlay::method_none, + bool expected_touch_only = false, T ip_x = -1, T ip_y = -1, std::string const& expected = "", T ip_x2 = -1, T ip_y2 = -1) @@ -190,9 +198,7 @@ void test_both(std::string const& caseid, test_with_point(caseid, pi_x, pi_y, pj_x, pj_y, pk_x, pk_y, qi_x, qi_y, qj_x, qj_y, qk_x, qk_y, - method, ip_x, ip_y, expected, ip_x2, ip_y2); - - //return; + method, expected_touch_only, ip_x, ip_y, expected, ip_x2, ip_y2); std::string reversed(expected.rbegin(), expected.rend()); @@ -205,7 +211,7 @@ void test_both(std::string const& caseid, test_with_point(caseid + "_r", qi_x, qi_y, qj_x, qj_y, qk_x, qk_y, // q pi_x, pi_y, pj_x, pj_y, pk_x, pk_y, // p - method, ip_x, ip_y, reversed, ip_x2, ip_y2); + method, expected_touch_only, ip_x, ip_y, reversed, ip_x2, ip_y2); } @@ -223,27 +229,27 @@ void test_all() test_both("il1", 5, 1, 5, 6, 7, 8, // p 3, 3, 7, 5, 8, 3, // q - method_crosses, 5, 4, "ui"); + method_crosses, false, 5, 4, "ui"); test_both("il2", 5, 1, 5, 6, 7, 8, // p 3, 5, 7, 5, 3, 3, // q - method_crosses, 5, 5, "ui"); + method_crosses, false, 5, 5, "ui"); test_both("il3", 5, 1, 5, 6, 7, 8, // p 3, 3, 7, 5, 3, 5, // q - method_crosses, 5, 4, "ui"); + method_crosses, false, 5, 4, "ui"); test_both("il4", 5, 1, 5, 6, 7, 8, // p 3, 3, 7, 5, 4, 8, // q - method_crosses, 5, 4, "ui"); + method_crosses, false, 5, 4, "ui"); test_both("ir1", 5, 1, 5, 6, 7, 8, // p 7, 5, 3, 3, 2, 5, // q - method_crosses, 5, 4, "iu"); + method_crosses, false, 5, 4, "iu"); // ------------------------------------------------------------------------ @@ -252,52 +258,52 @@ void test_all() test_both("ml1", 5, 1, 5, 6, 7, 8, // p 3, 3, 5, 4, 7, 3, // q - method_touch_interior, 5, 4, "ui"); + method_touch_interior, false, 5, 4, "ui"); test_both("ml2", 5, 1, 5, 6, 7, 8, // p 3, 3, 5, 4, 3, 6, // q - method_touch_interior, 5, 4, "iu"); + method_touch_interior, true, 5, 4, "iu"); test_both("ml3", 5, 1, 5, 6, 7, 8, // p 3, 6, 5, 4, 3, 3, // q - method_touch_interior, 5, 4, "uu"); + method_touch_interior, true, 5, 4, "uu"); test_both("mr1", 5, 1, 5, 6, 7, 8, // p 7, 3, 5, 4, 3, 3, // q - method_touch_interior, 5, 4, "iu"); + method_touch_interior, false, 5, 4, "iu"); test_both("mr2", 5, 1, 5, 6, 7, 8, // p 7, 3, 5, 4, 7, 6, // q - method_touch_interior, 5, 4, "ui"); + method_touch_interior, true, 5, 4, "ui"); test_both("mr3", 5, 1, 5, 6, 7, 8, // p 7, 6, 5, 4, 7, 3, // q - method_touch_interior, 5, 4, "ii"); + method_touch_interior, true, 5, 4, "ii"); test_both("mcl", 5, 1, 5, 6, 7, 8, // p 3, 2, 5, 3, 5, 5, // q - method_touch_interior, 5, 3, "cc"); + method_touch_interior, false, 5, 3, "cc"); test_both("mcr", 5, 1, 5, 6, 7, 8, // p 7, 2, 5, 3, 5, 5, // q - method_touch_interior, 5, 3, "cc"); + method_touch_interior, false, 5, 3, "cc"); test_both("mclo", 5, 1, 5, 6, 7, 8, // p 3, 4, 5, 5, 5, 3, // q - method_touch_interior, 5, 5, "ux"); + method_touch_interior, false, 5, 5, "ux"); test_both("mcro", 5, 1, 5, 6, 7, 8, // p 7, 4, 5, 5, 5, 3, // q - method_touch_interior, 5, 5, "ix"); + method_touch_interior, false, 5, 5, "ix"); // ------------------------------------------------------------------------ // COLLINEAR @@ -305,53 +311,53 @@ void test_all() test_both("cll1", 5, 1, 5, 6, 3, 8, // p 5, 5, 5, 7, 3, 8, // q - method_collinear, 5, 6, "ui"); + method_collinear, false, 5, 6, "ui"); test_both("cll2", 5, 1, 5, 6, 3, 8, // p 5, 3, 5, 5, 3, 6, // q - method_collinear, 5, 5, "iu"); + method_collinear, false, 5, 5, "iu"); test_both("clr1", 5, 1, 5, 6, 3, 8, // p 5, 5, 5, 7, 6, 8, // q - method_collinear, 5, 6, "ui"); + method_collinear, false, 5, 6, "ui"); test_both("clr2", 5, 1, 5, 6, 3, 8, // p 5, 3, 5, 5, 6, 6, // q - method_collinear, 5, 5, "ui"); + method_collinear, false, 5, 5, "ui"); test_both("crl1", 5, 1, 5, 6, 7, 8, // p 5, 5, 5, 7, 3, 8, // q - method_collinear, 5, 6, "iu"); + method_collinear, false, 5, 6, "iu"); test_both("crl2", 5, 1, 5, 6, 7, 8, // p 5, 3, 5, 5, 3, 6, // q - method_collinear, 5, 5, "iu"); + method_collinear, false, 5, 5, "iu"); test_both("crr1", 5, 1, 5, 6, 7, 8, // p 5, 5, 5, 7, 6, 8, // q - method_collinear, 5, 6, "iu"); + method_collinear, false, 5, 6, "iu"); test_both("crr2", 5, 1, 5, 6, 7, 8, // p 5, 3, 5, 5, 6, 6, // q - method_collinear, 5, 5, "ui"); + method_collinear, false, 5, 5, "ui"); // The next two cases are changed (BSG 2013-09-24), they contain turn info (#buffer_rt_g) // In new approach they are changed back (BSG 2013-10-20) test_both("ccx1", 5, 1, 5, 6, 5, 8, // p 5, 5, 5, 7, 3, 8, // q - method_collinear, 5, 6, "cc"); // "iu"); + method_collinear, false, 5, 6, "cc"); // "iu"); test_both("cxc1", 5, 1, 5, 6, 7, 8, // p 5, 3, 5, 5, 5, 7, // q - method_collinear, 5, 5, "cc"); // "iu"); + method_collinear, false, 5, 5, "cc"); // "iu"); // Bug in case #54 of "overlay_cases.hpp" test_both("c_bug1", 5, 0, 2, 0, 2, 2, // p 4, 0, 1, 0, 1, 2, // q - method_collinear, 2, 0, "iu"); + method_collinear, false, 2, 0, "iu"); // ------------------------------------------------------------------------ @@ -361,66 +367,66 @@ void test_all() test_both("clo1", 5, 2, 5, 6, 3, 8, // p 5, 7, 5, 5, 3, 3, // q - method_collinear, 5, 6, "ixxu", 5, 5); + method_collinear, false, 5, 6, "ixxu", 5, 5); test_both("clo2", 5, 2, 5, 6, 3, 8, // p 5, 7, 5, 5, 5, 2, // q - method_collinear, 5, 6, "ix"); + method_collinear, false, 5, 6, "ix"); // actually "xxix", xx is skipped everywhere test_both("clo3", 5, 2, 5, 6, 3, 8, // p 5, 7, 5, 5, 7, 3, // q - method_collinear, 5, 6, "ixxi", 5, 5); + method_collinear, false, 5, 6, "ixxi", 5, 5); test_both("cco1", 5, 2, 5, 6, 5, 8, // p 5, 7, 5, 5, 3, 3, // q - method_collinear, 5, 5, "xu"); // "xuxx" + method_collinear, false, 5, 5, "xu"); // "xuxx" test_both("cco2", 5, 2, 5, 6, 5, 8, // p 5, 7, 5, 5, 5, 2); // q "xxxx" test_both("cco3", 5, 2, 5, 6, 5, 8, // p 5, 7, 5, 5, 7, 3, // q - method_collinear, 5, 5, "xi"); // "xixx" + method_collinear, false, 5, 5, "xi"); // "xixx" test_both("cro1", 5, 2, 5, 6, 7, 8, // p 5, 7, 5, 5, 3, 3, // q - method_collinear, 5, 6, "uxxu", 5, 5); + method_collinear, false, 5, 6, "uxxu", 5, 5); test_both("cro2", 5, 2, 5, 6, 7, 8, // p 5, 7, 5, 5, 5, 2, // q - method_collinear, 5, 6, "ux"); // "xxux" + method_collinear, false, 5, 6, "ux"); // "xxux" test_both("cro3", 5, 2, 5, 6, 7, 8, // p 5, 7, 5, 5, 7, 3, // q - method_collinear, 5, 6, "uxxi", 5, 5); + method_collinear, false, 5, 6, "uxxi", 5, 5); test_both("cxo1", 5, 2, 5, 6, 3, 8, // p 5, 5, 5, 3, 3, 1, // q - method_collinear, 5, 3, "xu"); + method_collinear, false, 5, 3, "xu"); test_both("cxo2", 5, 2, 5, 6, 3, 8, // p 5, 5, 5, 3, 5, 0); // q "xx" test_both("cxo3", 5, 2, 5, 6, 3, 8, // p 5, 5, 5, 3, 7, 1, // q - method_collinear, 5, 3, "xi"); + method_collinear, false, 5, 3, "xi"); test_both("cxo4", 5, 2, 5, 6, 3, 8, // p 5, 7, 5, 1, 3, 0, // q - method_collinear, 5, 6, "ix"); + method_collinear, false, 5, 6, "ix"); test_both("cxo5", 5, 2, 5, 6, 5, 8, // p 5, 7, 5, 1, 3, 0); // q "xx" test_both("cxo6", 5, 2, 5, 6, 7, 8, // p 5, 7, 5, 1, 3, 0, // q - method_collinear, 5, 6, "ux"); + method_collinear, false, 5, 6, "ux"); // Verify @@ -441,61 +447,61 @@ void test_all() test_both("blr1", 5, 1, 5, 6, 4, 4, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "ui"); + method_touch, true, 5, 6, "ui"); test_both("blr2", 5, 1, 5, 6, 1, 4, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("blr3", 5, 1, 5, 6, 3, 6, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "iu"); + method_touch, false, 5, 6, "iu"); test_both("blr4", 5, 1, 5, 6, 1, 8, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "xu"); + method_touch, false, 5, 6, "xu"); test_both("blr5", 5, 1, 5, 6, 4, 8, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); test_both("blr6", 5, 1, 5, 6, 6, 4, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); test_both("blr7", 5, 1, 5, 6, 3, 6, // p 3, 7, 5, 6, 5, 3, // q - method_touch, 5, 6, "ix"); + method_touch, false, 5, 6, "ix"); test_both("blr8", 5, 1, 5, 6, 3, 6, // p 3, 6, 5, 6, 5, 3, // q - method_touch, 5, 6, "xx"); + method_touch, false, 5, 6, "xx"); test_both("blr9", 5, 1, 5, 6, 3, 6, // p 3, 5, 5, 6, 5, 3, // q - method_touch, 5, 6, "ux"); + method_touch, false, 5, 6, "ux"); // Variants test_both("blr7-a", 5, 1, 5, 6, 3, 6, // p 5, 8, 5, 6, 5, 3, // q - method_touch, 5, 6, "ix"); + method_touch, false, 5, 6, "ix"); test_both("blr7-b", // in fact NOT "both-left" 5, 1, 5, 6, 3, 6, // p 6, 8, 5, 6, 5, 3, // q - method_touch, 5, 6, "ix"); + method_touch, false, 5, 6, "ix"); // To check if "collinear-check" on other side // does not apply to this side test_both("blr6-c1", 5, 1, 5, 6, 7, 5, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); test_both("blr6-c2", 5, 1, 5, 6, 7, 7, // p 3, 7, 5, 6, 3, 5, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); @@ -503,75 +509,75 @@ void test_all() test_both("brr1", 5, 1, 5, 6, 6, 4, // p 7, 5, 5, 6, 7, 7, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); test_both("brr2", 5, 1, 5, 6, 9, 4, // p 7, 5, 5, 6, 7, 7, // q - method_touch, 5, 6, "xu"); + method_touch, false, 5, 6, "xu"); test_both("brr3", 5, 1, 5, 6, 7, 6, // p 7, 5, 5, 6, 7, 7, // q - method_touch, 5, 6, "iu"); + method_touch, false, 5, 6, "iu"); test_both("brr4", 5, 1, 5, 6, 9, 8, // p 7, 5, 5, 6, 7, 7, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("brr5", 5, 1, 5, 6, 6, 8, // p 7, 5, 5, 6, 7, 7, // q - method_touch, 5, 6, "ui"); + method_touch, true, 5, 6, "ui"); test_both("brr6", 5, 1, 5, 6, 4, 4, // p 7, 5, 5, 6, 7, 7, // q - method_touch, 5, 6, "ui"); + method_touch, true, 5, 6, "ui"); // Both right, Q turns left test_both("brl1", 5, 1, 5, 6, 6, 4, // p 7, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "iu"); + method_touch, true, 5, 6, "iu"); test_both("brl2", 5, 1, 5, 6, 9, 4, // p 7, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("brl3", 5, 1, 5, 6, 7, 6, // p 7, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("brl4", 5, 1, 5, 6, 9, 8, // p 7, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "xi"); + method_touch, false, 5, 6, "xi"); test_both("brl5", 5, 1, 5, 6, 6, 8, // p 7, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "ii"); + method_touch, true, 5, 6, "ii"); test_both("brl6", 5, 1, 5, 6, 4, 4, // p 7, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "ii"); + method_touch, true, 5, 6, "ii"); test_both("brl7", 5, 1, 5, 6, 7, 6, // p 7, 7, 5, 6, 5, 3, // q - method_touch, 5, 6, "ux"); + method_touch, false, 5, 6, "ux"); test_both("brl8", 5, 1, 5, 6, 7, 6, // p 7, 6, 5, 6, 5, 3, // q - method_touch, 5, 6, "xx"); + method_touch, false, 5, 6, "xx"); test_both("brl9", 5, 1, 5, 6, 7, 6, // p 7, 5, 5, 6, 5, 3, // q - method_touch, 5, 6, "ix"); + method_touch, false, 5, 6, "ix"); // Variants test_both("brl7-a", 5, 1, 5, 6, 7, 6, // p 5, 8, 5, 6, 5, 3, // q - method_touch, 5, 6, "ux"); + method_touch, false, 5, 6, "ux"); test_both("brl7-b", // in fact NOT "both right" 5, 1, 5, 6, 7, 6, // p 4, 8, 5, 6, 5, 3, // q - method_touch, 5, 6, "ux"); + method_touch, false, 5, 6, "ux"); @@ -579,251 +585,251 @@ void test_all() test_both("bll1", 5, 1, 5, 6, 4, 4, // p 3, 5, 5, 6, 3, 7, // q - method_touch, 5, 6, "ii"); + method_touch, true, 5, 6, "ii"); test_both("bll2", 5, 1, 5, 6, 1, 4, // p 3, 5, 5, 6, 3, 7, // q - method_touch, 5, 6, "xi"); + method_touch, false, 5, 6, "xi"); test_both("bll3", 5, 1, 5, 6, 3, 6, // p 3, 5, 5, 6, 3, 7, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("bll4", 5, 1, 5, 6, 1, 8, // p 3, 5, 5, 6, 3, 7, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("bll5", 5, 1, 5, 6, 4, 8, // p 3, 5, 5, 6, 3, 7, // q - method_touch, 5, 6, "iu"); + method_touch, true, 5, 6, "iu"); test_both("bll6", 5, 1, 5, 6, 6, 4, // p 3, 5, 5, 6, 3, 7, // q - method_touch, 5, 6, "iu"); + method_touch, true, 5, 6, "iu"); // TOUCH - COLLINEAR + one side // Collinear/left, Q turns right test_both("t-clr1", 5, 1, 5, 6, 4, 4, // p 5, 8, 5, 6, 3, 5, // q - method_touch, 5, 6, "ui"); + method_touch, true, 5, 6, "ui"); test_both("t-clr2", 5, 1, 5, 6, 1, 4, // p 5, 8, 5, 6, 3, 5, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("t-clr3", 5, 1, 5, 6, 3, 6, // p 5, 8, 5, 6, 3, 5, // q - method_touch, 5, 6, "iu"); + method_touch, false, 5, 6, "iu"); test_both("t-clr4", 5, 1, 5, 6, 5, 8, // p 5, 8, 5, 6, 3, 5, // q - method_touch, 5, 6, "xu"); + method_touch, false, 5, 6, "xu"); // 5 n.a. test_both("t-clr6", 5, 1, 5, 6, 6, 4, // p 5, 8, 5, 6, 3, 5, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); // Collinear/right, Q turns right test_both("t-crr1", 5, 1, 5, 6, 6, 4, // p 7, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); test_both("t-crr2", 5, 1, 5, 6, 9, 4, // p 7, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "xu"); + method_touch, false, 5, 6, "xu"); test_both("t-crr3", 5, 1, 5, 6, 7, 6, // p 7, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "iu"); + method_touch, false, 5, 6, "iu"); test_both("t-crr4", 5, 1, 5, 6, 5, 9, // p 7, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); // 5 n.a. test_both("t-crr6", 5, 1, 5, 6, 4, 4, // p 7, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "ui"); + method_touch, true, 5, 6, "ui"); // Collinear/right, Q turns left test_both("t-crl1", 5, 1, 5, 6, 6, 4, // p 5, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "iu"); + method_touch, true, 5, 6, "iu"); test_both("t-crl2", 5, 1, 5, 6, 9, 4, // p 5, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("t-crl3", 5, 1, 5, 6, 7, 6, // p 5, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("t-crl4", 5, 1, 5, 6, 5, 8, // p 5, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "xi"); + method_touch, false, 5, 6, "xi"); // 5 n.a. test_both("t-crl6", 5, 1, 5, 6, 4, 4, // p 5, 7, 5, 6, 7, 5, // q - method_touch, 5, 6, "ii"); + method_touch, true, 5, 6, "ii"); // Collinear/left, Q turns left test_both("t-cll1", 5, 1, 5, 6, 4, 4, // p 3, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "ii"); + method_touch, true, 5, 6, "ii"); test_both("t-cll2", 5, 1, 5, 6, 1, 4, // p 3, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "xi"); + method_touch, false, 5, 6, "xi"); test_both("t-cll3", 5, 1, 5, 6, 3, 6, // p 3, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("t-cll4", 5, 1, 5, 6, 5, 9, // p 3, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); // 5 n.a. test_both("t-cll6", 5, 1, 5, 6, 6, 4, // p 3, 5, 5, 6, 5, 8, // q - method_touch, 5, 6, "iu"); + method_touch, true, 5, 6, "iu"); // Left to right test_both("lr1", 5, 1, 5, 6, 3, 3, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "ii"); + method_touch, true, 5, 6, "ii"); test_both("lr2", 5, 1, 5, 6, 1, 5, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "xi"); + method_touch, false, 5, 6, "xi"); test_both("lr3", 5, 1, 5, 6, 4, 8, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("lr4", 5, 1, 5, 6, 9, 5, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("lr5", 5, 1, 5, 6, 7, 3, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "iu"); + method_touch, true, 5, 6, "iu"); // otherwise case more thoroughly test_both("lr3a", 5, 1, 5, 6, 1, 6, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("lr3b", 5, 1, 5, 6, 5, 10, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("lr3c", 5, 1, 5, 6, 8, 9, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("lr3d", 5, 1, 5, 6, 9, 7, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); test_both("lr3e", 5, 1, 5, 6, 9, 6, // p 1, 5, 5, 6, 9, 5, // q - method_touch, 5, 6, "ui"); + method_touch, false, 5, 6, "ui"); // Right to left test_both("rl1", 5, 1, 5, 6, 3, 3, // p 9, 5, 5, 6, 1, 5, // q - method_touch, 5, 6, "ui"); + method_touch, true, 5, 6, "ui"); test_both("rl2", 5, 1, 5, 6, 1, 5, // p 9, 5, 5, 6, 1, 5, // q - method_touch, 5, 6, "cc"); + method_touch, false, 5, 6, "cc"); test_both("rl3", 5, 1, 5, 6, 4, 8, // p 9, 5, 5, 6, 1, 5, // q - method_touch, 5, 6, "iu"); + method_touch, false, 5, 6, "iu"); test_both("rl4", 5, 1, 5, 6, 9, 5, // p 9, 5, 5, 6, 1, 5, // q - method_touch, 5, 6, "xu"); + method_touch, false, 5, 6, "xu"); test_both("rl5", 5, 1, 5, 6, 7, 3, // p 9, 5, 5, 6, 1, 5, // q - method_touch, 5, 6, "uu"); + method_touch, true, 5, 6, "uu"); // Equal (p1/q1 are equal) test_both("ebl1", 5, 1, 5, 6, 3, 4, // p 5, 1, 5, 6, 3, 8, // q - method_equal, 5, 6, "ui"); + method_equal, false, 5, 6, "ui"); test_both("ebl2", 5, 1, 5, 6, 3, 8, // p 5, 1, 5, 6, 3, 4, // q - method_equal, 5, 6, "iu"); + method_equal, false, 5, 6, "iu"); test_both("ebl3", 5, 1, 5, 6, 3, 8, // p 5, 1, 5, 6, 3, 8, // q - method_equal, 5, 6, "cc"); + method_equal, false, 5, 6, "cc"); test_both("ebl3-c1", 5, 1, 5, 6, 10, 1, // p 5, 1, 5, 6, 3, 8, // q - method_equal, 5, 6, "iu"); + method_equal, false, 5, 6, "iu"); test_both("ebr1", 5, 1, 5, 6, 7, 4, // p 5, 1, 5, 6, 7, 8, // q - method_equal, 5, 6, "iu"); + method_equal, false, 5, 6, "iu"); test_both("ebr2", 5, 1, 5, 6, 7, 8, // p 5, 1, 5, 6, 7, 4, // q - method_equal, 5, 6, "ui"); + method_equal, false, 5, 6, "ui"); test_both("ebr3", 5, 1, 5, 6, 7, 8, // p 5, 1, 5, 6, 7, 8, // q - method_equal, 5, 6, "cc"); + method_equal, false, 5, 6, "cc"); test_both("ebr3-c1", 5, 1, 5, 6, 0, 1, // p 5, 1, 5, 6, 7, 8, // q - method_equal, 5, 6, "ui"); + method_equal, false, 5, 6, "ui"); test_both("elr1", 5, 1, 5, 6, 7, 8, // p 5, 1, 5, 6, 3, 8, // q - method_equal, 5, 6, "iu"); + method_equal, false, 5, 6, "iu"); test_both("elr2", 5, 1, 5, 6, 3, 8, // p 5, 1, 5, 6, 7, 8, // q - method_equal, 5, 6, "ui"); + method_equal, false, 5, 6, "ui"); test_both("ec1", 5, 1, 5, 6, 5, 8, // p 5, 1, 5, 6, 5, 8, // q - method_equal, 5, 6, "cc"); + method_equal, false, 5, 6, "cc"); test_both("ec2", 5, 1, 5, 6, 5, 8, // p 5, 1, 5, 6, 5, 7, // q - method_equal, 5, 6, "cc"); + method_equal, false, 5, 6, "cc"); test_both("snl-1", 0, 3, 2, 3, 4, 3, // p 4, 3, 2, 3, 0, 3, // q - method_touch, 2, 3, "xx"); + method_touch, false, 2, 3, "xx"); // BSG 2012-05-26 to be decided what's the problem here and what it tests... // Anyway, test results are not filled out. //test_both("issue_buffer_mill", // 5.1983614873206241 , 6.7259025813913107 , 5.0499999999999998 , 6.4291796067500622 , 5.1983614873206241 , 6.7259025813913107, // p // 5.0499999999999998 , 6.4291796067500622 , 5.0499999999999998 , 6.4291796067500622 , 5.1983614873206241 , 6.7259025813913107, // q - // method_collinear, 2, 0, "tt"); + // method_collinear, false, 2, 0, "tt"); } diff --git a/test/algorithms/overlay/select_rings.cpp b/test/algorithms/overlay/select_rings.cpp index b1ad67850..af43328f5 100644 --- a/test/algorithms/overlay/select_rings.cpp +++ b/test/algorithms/overlay/select_rings.cpp @@ -1,6 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// +// This file was modified by Oracle on 2017. +// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, 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 // http://www.boost.org/LICENSE_1_0.txt) @@ -36,7 +41,11 @@ template void test_geometry(std::string const& wkt1, std::string const& wkt2, RingIdVector const& expected_ids) { - typedef bg::detail::overlay::ring_properties::type> properties; + typedef bg::detail::overlay::ring_properties + < + typename bg::point_type::type, + double + > properties; Geometry1 geometry1; Geometry2 geometry2; diff --git a/test/algorithms/overlay/sort_by_side.cpp b/test/algorithms/overlay/sort_by_side.cpp index 19c90bd24..5635d46f6 100644 --- a/test/algorithms/overlay/sort_by_side.cpp +++ b/test/algorithms/overlay/sort_by_side.cpp @@ -232,32 +232,24 @@ void test_all() // Selection of test cases having only one cluster - TEST_INT(case_62_multi, list_of(1)); - TEST_INT(case_63_multi, list_of(1)); TEST_INT(case_64_multi, list_of(1)); TEST_INT(case_72_multi, list_of(3)); TEST_INT(case_107_multi, list_of(2)); TEST_INT(case_123_multi, list_of(3)); TEST_INT(case_124_multi, list_of(3)); - TEST_INT(case_recursive_boxes_1, list_of(2)); TEST_INT(case_recursive_boxes_10, list_of(2)); - TEST_INT(case_recursive_boxes_18, list_of(0)); - TEST_INT(case_recursive_boxes_19, list_of(0)); TEST_INT(case_recursive_boxes_20, list_of(2)); TEST_INT(case_recursive_boxes_21, list_of(1)); TEST_INT(case_recursive_boxes_22, list_of(0)); - TEST_INT(case_recursive_boxes_23, list_of(1)); TEST_UNION(case_recursive_boxes_46, list_of(2)(1)(2)(1)(1)(2)(1)); TEST_UNION(case_62_multi, list_of(2)); TEST_UNION(case_63_multi, list_of(2)); TEST_UNION(case_64_multi, list_of(1)); - TEST_UNION(case_72_multi, list_of(0)); TEST_UNION(case_107_multi, list_of(1)); TEST_UNION(case_123_multi, list_of(1)); TEST_UNION(case_124_multi, list_of(1)); - TEST_UNION(case_recursive_boxes_1, list_of(1)); TEST_UNION(case_recursive_boxes_10, list_of(1)); TEST_UNION(case_recursive_boxes_18, list_of(3)); TEST_UNION(case_recursive_boxes_19, list_of(3)); diff --git a/test/algorithms/relational_operations/disjoint/disjoint_sph.cpp b/test/algorithms/relational_operations/disjoint/disjoint_sph.cpp index cee4c8d16..d9a21fdad 100644 --- a/test/algorithms/relational_operations/disjoint/disjoint_sph.cpp +++ b/test/algorithms/relational_operations/disjoint/disjoint_sph.cpp @@ -188,6 +188,21 @@ void test_linestring_linestring() test_geometry("LINESTRING(1 0,2 2,2 3)", "LINESTRING(0 0, 2 2, 3 2)", false); } +//https://svn.boost.org/trac10/ticket/13057 +template +void test_linestring_linestring_radians() +{ + typedef bg::model::linestring

ls; + + test_geometry("LINESTRING(0 -0.31415926535897897853,\ + 0.26179938779914918578 0,\ + -0.034906585039886556254 0.13962634015954622502,\ + -0.12217304763960294689 0.12217304763960294689)",\ + "LINESTRING(-0.034906585039886556254 0.13962634015954622502,\ + -0.26179938779914918578 0)", false); + +} + template void test_linestring_multi_linestring() { @@ -255,6 +270,9 @@ void test_all() test_linestring_multi_linestring

(); test_multi_linestring_multi_linestring

(); + test_linestring_linestring_radians > >(); + test_point_polygon

(); } diff --git a/test/algorithms/set_operations/check_validity.hpp b/test/algorithms/set_operations/check_validity.hpp new file mode 100644 index 000000000..3e81538dc --- /dev/null +++ b/test/algorithms/set_operations/check_validity.hpp @@ -0,0 +1,50 @@ +// Boost.Geometry + +// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP +#define BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP + +#include + +#include + +template +< + typename Geometry, + typename Tag = typename bg::tag::type +> +struct check_validity +{ + static inline + bool apply(Geometry const& geometry, std::string& message) + { + return bg::is_valid(geometry, message); + } +}; + +// Specialization for vector of (e.g. rings) +template +struct check_validity +{ + static inline + bool apply(Geometry const& geometry, std::string& message) + { + typedef typename boost::range_value::type single_type; + BOOST_FOREACH(single_type const& element, geometry) + { + if (! bg::is_valid(element, message)) + { + return false; + } + } + return true; + } +}; + + +#endif // BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index 00983708f..e1a811676 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -41,10 +41,13 @@ ( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \ clips3, -1, area1 + area2) +#if !defined(BOOST_GEOMETRY_INCLUDE_SELF_TURNS) #define TEST_DIFFERENCE_IGNORE(caseid, clips1, area1, clips2, area2, clips3) \ + { ut_settings ignore_validity; ignore_validity.test_validity = false; \ (test_one) \ ( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \ - clips3, -1, area1 + area2, ignore_validity) + clips3, -1, area1 + area2, ignore_validity); } +#endif template void test_all() @@ -55,9 +58,6 @@ void test_all() typedef typename bg::coordinate_type

::type ct; - ut_settings ignore_validity; - ignore_validity.test_validity = false; - ut_settings sym_settings; #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) sym_settings.sym_difference = false; @@ -211,8 +211,7 @@ void test_all() test_one("case_80", case_80[0], case_80[1], 1, 9, 44.5, - 1, 10, 84.5, - ignore_validity); + 1, 10, 84.5); #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS // Fails, holes are not subtracted @@ -371,10 +370,18 @@ void test_all() } #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) - test_one("ggl_list_20110820_christophe", - ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1], - 1, -1, 2.8570121719168924, - 1, -1, 64.498061986388564); + { + // symmetric difference is not valid due to robustness issue, it has + // two turns (touch_only) and a midpoint is located in other polygon + ut_settings ignore_validity; + ignore_validity.test_validity = false; + + test_one("ggl_list_20110820_christophe", + ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1], + 1, -1, 2.8570121719168924, + 1, -1, 64.498061986388564, + ignore_validity); + } #endif test_one("ggl_list_20120717_volker", @@ -540,20 +547,16 @@ void test_all() TEST_DIFFERENCE(mysql_21965285, 1, 92.0, 1, 14.0, 1); - TEST_DIFFERENCE_IGNORE(mysql_23023665_1, 1, 92.0, 1, 142.5, 2); - TEST_DIFFERENCE_IGNORE(mysql_23023665_2, 1, 96.0, 1, 16.0, 2); - TEST_DIFFERENCE_IGNORE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2); + TEST_DIFFERENCE(mysql_23023665_1, 1, 92.0, 1, 142.5, 2); + TEST_DIFFERENCE(mysql_23023665_2, 1, 96.0, 1, 16.0, 2); + TEST_DIFFERENCE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2); #ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS TEST_DIFFERENCE(mysql_23023665_5, 2, 165.23735, 2, 105.73735, 4); #else TEST_DIFFERENCE_IGNORE(mysql_23023665_5, 1, 165.23735, 2, 105.73735, 3); #endif -#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) TEST_DIFFERENCE(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5); -#else - TEST_DIFFERENCE_IGNORE(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5); -#endif #ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS TEST_DIFFERENCE(mysql_23023665_13, 3, 99.74526, 3, 37.74526, 6); @@ -585,15 +588,10 @@ void test_specific() 2, 8, 489763.5, 1, 4, 6731652.0); - // Generates spikes, both a-b and b-a #ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS TEST_DIFFERENCE(ticket_11676, 2, 2537992.5, 2, 294963.5, 3); #else - - ut_settings ignore_validity; - ignore_validity.test_validity = false; - TEST_DIFFERENCE_IGNORE(ticket_11676, 1, 2537992.5, 2, 294963.5, 2); #endif } diff --git a/test/algorithms/set_operations/difference/difference_multi.cpp b/test/algorithms/set_operations/difference/difference_multi.cpp index ca4effb7b..36ca296e9 100644 --- a/test/algorithms/set_operations/difference/difference_multi.cpp +++ b/test/algorithms/set_operations/difference/difference_multi.cpp @@ -30,9 +30,10 @@ clips3, -1, area1 + area2) #define TEST_DIFFERENCE_IGNORE(caseid, clips1, area1, clips2, area2, clips3) \ + { ut_settings ignore_validity; ignore_validity.test_validity = false; \ (test_one) \ ( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \ - clips3, -1, area1 + area2, ignore_validity) + clips3, -1, area1 + area2, ignore_validity); } #define TEST_DIFFERENCE_WITH(index1, index2, caseid, clips1, area1, \ clips2, area2, clips3) \ @@ -46,9 +47,6 @@ template void test_areal() { - ut_settings ignore_validity; - ignore_validity.test_validity = false; - ut_settings sym_settings; #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) sym_settings.sym_difference = false; @@ -94,7 +92,7 @@ void test_areal() test_one("case_72_multi", case_72_multi[0], case_72_multi[1], - 3, 13, 1.65, 3, 17, 6.15, ignore_validity); + 3, 13, 1.65, 3, 17, 6.15); test_one("case_77_multi", case_77_multi[0], case_77_multi[1], @@ -108,7 +106,7 @@ void test_areal() TEST_DIFFERENCE(case_123_multi, 1, 0.25, 2, 0.625, 3); TEST_DIFFERENCE(case_124_multi, 1, 0.25, 2, 0.4375, 3); - TEST_DIFFERENCE_IGNORE(case_125_multi, 1, 0.25, 2, 0.400, 3); + TEST_DIFFERENCE(case_125_multi, 1, 0.25, 2, 0.400, 3); // A should have 3 clips, B should have 5 clips #ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS @@ -178,11 +176,7 @@ void test_areal() tolerance(0.001)); // POSTGIS areas: 3.75893745345145, 2.5810000723917e-15 - test_one("bug_21155501", - bug_21155501[0], bug_21155501[1], - 1, 9, 3.758937, - 0, 0, 0.0, - ignore_validity); + TEST_DIFFERENCE_IGNORE(bug_21155501, 1, 3.758937, 0, 0.0, 1); #endif // Areas and #clips correspond with POSTGIS (except sym case) diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index 781fb03f1..10d23addd 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -48,8 +48,7 @@ BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector) #if ! defined(BOOST_GEOMETRY_INCLUDE_SELF_TURNS) #define TEST_INTERSECTION_IGNORE(caseid, clips, points, area) \ - { ut_settings ignore_validity; \ - ignore_validity.test_validity = false; \ + { ut_settings ignore_validity; ignore_validity.test_validity = false; \ (test_one) \ ( #caseid, caseid[0], caseid[1], clips, points, area, ignore_validity); } #endif diff --git a/test/algorithms/set_operations/intersection/intersection_multi.cpp b/test/algorithms/set_operations/intersection/intersection_multi.cpp index 10a6ff5d1..ef7e5226a 100644 --- a/test/algorithms/set_operations/intersection/intersection_multi.cpp +++ b/test/algorithms/set_operations/intersection/intersection_multi.cpp @@ -33,15 +33,13 @@ ( #caseid, caseid[0], caseid[1], clips, points, area) #define TEST_INTERSECTION_IGNORE(caseid, clips, points, area) \ + { ut_settings ignore_validity; ignore_validity.test_validity = false; \ (test_one) \ - ( #caseid, caseid[0], caseid[1], clips, points, area, ignore_validity) + ( #caseid, caseid[0], caseid[1], clips, points, area, ignore_validity); } template void test_areal() { - ut_settings ignore_validity; - ignore_validity.test_validity = false; - test_one("simplex_multi", case_multi_simplex[0], case_multi_simplex[1], 2, 12, 6.42); diff --git a/test/algorithms/set_operations/intersection/test_intersection.hpp b/test/algorithms/set_operations/intersection/test_intersection.hpp index 8c8f68aa2..4afe42f5b 100644 --- a/test/algorithms/set_operations/intersection/test_intersection.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection.hpp @@ -41,6 +41,7 @@ #include #include "../setop_output_type.hpp" +#include "../check_validity.hpp" struct ut_settings { @@ -56,7 +57,13 @@ struct ut_settings }; -template +template +< + typename G1, + typename G2, + typename ResultType, + typename IntersectionOutput +> typename bg::default_area_result::type check_result( IntersectionOutput const& intersection_output, @@ -96,15 +103,15 @@ check_result( { std::cout << std::setprecision(20) << bg::wkt(*it) << std::endl; } + } - if (settings.test_validity) - { - std::string message; - bool const valid = bg::is_valid(*it, message); - BOOST_CHECK_MESSAGE(valid, - "intersection: " << caseid << " not valid: " << message - << " type: " << (type_for_assert_message())); - } + if (settings.test_validity) + { + std::string message; + bool const valid = check_validity::apply(intersection_output, message); + BOOST_CHECK_MESSAGE(valid, + "intersection: " << caseid << " not valid: " << message + << " type: " << (type_for_assert_message())); } #if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST) @@ -194,7 +201,7 @@ typename bg::default_area_result::type test_intersection(std::string const& result_type intersection_output; bg::intersection(g1, g2, intersection_output); - check_result(intersection_output, caseid, expected_count, + check_result(intersection_output, caseid, expected_count, expected_holes_count, expected_point_count, expected_length_or_area, settings); @@ -203,21 +210,21 @@ typename bg::default_area_result::type test_intersection(std::string const& intersection_output.clear(); bg::intersection(boost::variant(g1), g2, intersection_output); - check_result(intersection_output, caseid, expected_count, + check_result(intersection_output, caseid, expected_count, expected_holes_count, expected_point_count, expected_length_or_area, settings); intersection_output.clear(); bg::intersection(g1, boost::variant(g2), intersection_output); - check_result(intersection_output, caseid, expected_count, + check_result(intersection_output, caseid, expected_count, expected_holes_count, expected_point_count, expected_length_or_area, settings); intersection_output.clear(); bg::intersection(boost::variant(g1), boost::variant(g2), intersection_output); - check_result(intersection_output, caseid, expected_count, + check_result(intersection_output, caseid, expected_count, expected_holes_count, expected_point_count, expected_length_or_area, settings); #endif diff --git a/test/algorithms/set_operations/union/test_union.hpp b/test/algorithms/set_operations/union/test_union.hpp index 9b32292c5..352521eb2 100644 --- a/test/algorithms/set_operations/union/test_union.hpp +++ b/test/algorithms/set_operations/union/test_union.hpp @@ -19,6 +19,7 @@ #include #include "../setop_output_type.hpp" +#include "../check_validity.hpp" #include #include @@ -71,42 +72,6 @@ inline void check_input_validity(std::string const& caseid, int case_index, } #endif -template -< - typename Geometry, - typename Tag = typename bg::tag::type -> -struct check_validity -{ - static inline - bool apply(Geometry const& geometry, std::string& message) - { - if (! bg::is_valid(geometry, message)) - { - std::cout << bg::wkt(geometry) << std::endl; - } - return bg::is_valid(geometry, message); - } -}; - -// Specialization for vector of (e.g. rings) -template -struct check_validity -{ - static inline - bool apply(Geometry const& geometry, std::string& message) - { - typedef typename boost::range_value::type single_type; - BOOST_FOREACH(single_type const& element, geometry) - { - if (! bg::is_valid(element, message)) - { - return false; - } - } - return true; - } -}; template diff --git a/test/formulas/Jamfile.v2 b/test/formulas/Jamfile.v2 index 80c18de5b..a8f835be8 100644 --- a/test/formulas/Jamfile.v2 +++ b/test/formulas/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.Geometry # -# Copyright (c) 2016, Oracle and/or its affiliates. +# Copyright (c) 2016-2017, Oracle and/or its affiliates. # # Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle # @@ -13,5 +13,5 @@ test-suite boost-geometry-formulas [ run inverse.cpp : : : : formulas_inverse ] [ run direct.cpp : : : : formulas_direct ] [ run intersection.cpp : : : : formulas_intersection ] - [ run vertex_longitude.cpp : : : : vertex_longitude ] + [ run vertex_longitude.cpp : : : : formulas_vertex_longitude ] ;