diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 19f9187c4..40f4939be 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -23,6 +23,8 @@ [*Solved tickets] +* [@https://svn.boost.org/trac/boost/ticket/10398 10398] Wrong neighbour check in buffer, calculating turns + [*Bugfixes] [/=================] diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index c37f32fd7..43d54fecf 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -126,6 +126,9 @@ struct buffer_turn_info int count_within; int count_on_offsetted; int count_on_helper; + int count_within_near_offsetted; + + // Obsolete: int count_on_occupied; int count_on_multi; @@ -135,6 +138,7 @@ struct buffer_turn_info , count_within(0) , count_on_offsetted(0) , count_on_helper(0) + , count_within_near_offsetted(0) , count_on_occupied(0) , count_on_multi(0) {} 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 5cca314df..97a20ebe2 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -147,7 +147,6 @@ struct buffered_piece_collection int m_first_piece_index; buffered_ring_collection > offsetted_rings; // indexed by multi_index - std::vector< std::vector < robust_point_type > > robust_offsetted_rings; buffered_ring_collection traversed_rings; segment_identifier current_segment_id; @@ -340,12 +339,17 @@ struct buffered_piece_collection boost::begin(m_turns); it != boost::end(m_turns); ++it) { if (it->count_within > 0) + { + it->location = inside_buffer; + } + if (it->count_within_near_offsetted > 0) { // Within can have in rare cases a rounding issue. We don't discard this // point, so it can be used to continue started rings in traversal. But // will never start a new ring from this type of points. it->selectable_start = false; } + } } @@ -525,7 +529,7 @@ struct buffered_piece_collection buffered_ring_collection >, turn_vector_type, RobustPolicy - > visitor(offsetted_rings, m_turns, m_robust_policy, m_pieces.size()); + > visitor(offsetted_rings, m_turns, m_robust_policy); geometry::partition < @@ -827,7 +831,7 @@ struct buffered_piece_collection selected[id] = properties(*it, true); } - detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, false); + detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true); return detail::overlay::add_rings(selected, offsetted_rings, traversed_rings, out); } diff --git a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index e3c41a2a4..23b09e1c8 100644 --- a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -56,7 +56,6 @@ class piece_turn_visitor Rings const& m_rings; Turns& m_turns; RobustPolicy const& m_robust_policy; - int m_last_piece_index; template inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const @@ -66,14 +65,8 @@ class piece_turn_visitor return false; } - if (std::abs(piece1.index - piece2.index) == 1) - { - return true; - } - - return (piece1.index == 0 && piece2.index == m_last_piece_index) - || (piece1.index == m_last_piece_index && piece2.index == 0) - ; + return piece1.index == piece2.left_index + || piece1.index == piece2.right_index; } template @@ -171,12 +164,10 @@ public: piece_turn_visitor(Rings const& ring_collection, Turns& turns, - RobustPolicy const& robust_policy, - int last_piece_index) + RobustPolicy const& robust_policy) : m_rings(ring_collection) , m_turns(turns) , m_robust_policy(robust_policy) - , m_last_piece_index(last_piece_index) {} template diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index 182f5af6a..97463cacd 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -19,6 +19,9 @@ #include #include +#include +#include + namespace boost { namespace geometry { @@ -56,6 +59,8 @@ class turn_in_piece_visitor Turns& m_turns; // because partition is currently operating on const input only Pieces const& m_pieces; // to check for piece-type + typedef boost::long_long_type calculation_type; + template static inline bool projection_on_segment(Point const& subject, Point const& p, Point const& q) { @@ -83,7 +88,6 @@ class turn_in_piece_visitor return true; } - template inline bool on_offsetted(Point const& point, Piece const& piece) const { @@ -105,11 +109,25 @@ class turn_in_piece_visitor return true; } } - } return false; } + template + static inline + calculation_type comparable_distance_from_offsetted(Point const& point, + Piece const& piece) + { + // TODO: pass subrange to dispatch to avoid making copy + geometry::model::linestring ls; + std::copy(piece.robust_ring.begin(), + piece.robust_ring.begin() + piece.offsetted_count, + std::back_inserter(ls)); + typename default_comparable_distance_result::type + const comp = geometry::comparable_distance(point, ls); + + return static_cast(comp); + } public: @@ -167,11 +185,15 @@ public: { return; } + if (geometry_code == 0 && neighbour) + { + return; + } Turn& mutable_turn = m_turns[turn.turn_index]; - if (geometry_code == 0 && ! neighbour) + if (geometry_code == 0) { - // If it is on the border and they are neighbours, it should be + // If it is on the border and they are not neighbours, it should be // on the offsetted ring if (! on_offsetted(turn.robust_point, piece)) @@ -180,14 +202,29 @@ public: // Then it is somewhere on the helper-segments // Classify it as inside geometry_code = 1; - mutable_turn.count_on_helper++; + mutable_turn.count_on_helper++; // can still become "near_offsetted" + } + else + { + mutable_turn.count_on_offsetted++; // value is not used anymore } } - switch (geometry_code) + if (geometry_code == 1) { - case 1 : mutable_turn.count_within++; break; - case 0 : mutable_turn.count_on_offsetted++; break; + calculation_type const distance + = comparable_distance_from_offsetted(turn.robust_point, piece); + if (distance >= 4) + { + // This is too far from the border, it counts as "really within" + mutable_turn.count_within++; + } + else + { + // Other points count as still "on border" because they might be + // travelled through, but not used as starting point + mutable_turn.count_within_near_offsetted++; + } } } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index a7cbd038d..67b48cc47 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -127,30 +127,30 @@ struct assign_visitor template inline void apply(Item const& outer, Item const& inner, bool first = true) { - if (first && outer.real_area < 0) + if (first && outer.abs_area < inner.abs_area) { - // Reverse arguments + // Apply with reversed arguments apply(inner, outer, false); return; } - if (math::larger(outer.real_area, 0)) + if (m_check_for_orientation + || (math::larger(outer.real_area, 0) + && math::smaller(inner.real_area, 0))) { - if (inner.real_area < 0 || m_check_for_orientation) - { - ring_info_type& inner_in_map = m_ring_map[inner.id]; + ring_info_type& inner_in_map = m_ring_map[inner.id]; - if (geometry::within(inner_in_map.point, outer.envelope) - && within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection) - ) + if (geometry::within(inner_in_map.point, outer.envelope) + && within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection) + ) + { + // Assign a parent if there was no earlier parent, or the newly + // found parent is smaller than the previous one + if (inner_in_map.parent.source_index == -1 + || outer.abs_area < inner_in_map.parent_area) { - // Only assign parent if that parent is smaller (or if it is the first) - if (inner_in_map.parent.source_index == -1 - || outer.abs_area < inner_in_map.parent_area) - { - inner_in_map.parent = outer.id; - inner_in_map.parent_area = outer.abs_area; - } + inner_in_map.parent = outer.id; + inner_in_map.parent_area = outer.abs_area; } } } @@ -288,13 +288,21 @@ inline void assign_parents(Geometry1 const& geometry1, { it->second.discarded = true; } - else if (it->second.parent.source_index >= 0 && it->second.get_area() > 0) + else if (it->second.parent.source_index >= 0 + && math::larger(it->second.get_area(), 0)) { - // Discard positive inner ring with parent - it->second.discarded = true; + const ring_info_type& parent = ring_map[it->second.parent]; + + if (math::larger(parent.area, 0)) + { + // Discard positive inner ring with positive parent + it->second.discarded = true; + } + // Remove parent ID from any positive inner ring it->second.parent.source_index = -1; } - else if (it->second.parent.source_index < 0 && it->second.get_area() < 0) + else if (it->second.parent.source_index < 0 + && math::smaller(it->second.get_area(), 0)) { // Reverse negative ring without parent it->second.reversed = true; @@ -313,6 +321,8 @@ inline void assign_parents(Geometry1 const& geometry1, } } + +// Version for one geometry (called by buffer) template < typename Geometry, @@ -324,7 +334,7 @@ inline void assign_parents(Geometry const& geometry, RingMap& ring_map, bool check_for_orientation) { - // Call it with an empty geometry + // Call it with an empty geometry as second geometry (source_id == 1) // (ring_map should be empty for source_id==1) Geometry empty; diff --git a/test/algorithms/buffer/linestring_buffer.cpp b/test/algorithms/buffer/linestring_buffer.cpp index eaff55e67..bdca6e3d0 100644 --- a/test/algorithms/buffer/linestring_buffer.cpp +++ b/test/algorithms/buffer/linestring_buffer.cpp @@ -64,9 +64,9 @@ void test_all() // test_one("simplex_asym_neg", simplex, join_miter, end_round, 3.202, +1.5, -1.0); // test_one("simplex_asym_pos", simplex, join_miter, end_round, 3.202, -1.0, +1.5); - // Generates a reverse polygon, with a negative area, which will be made empty TODO decide about this - test_one("simplex_asym_neg_rev", simplex, join_miter, end_flat, 0, +1.0, -1.5); - test_one("simplex_asym_pos_rev", simplex, join_miter, end_flat, 0, -1.5, +1.0); + // Generates (initially) a reversed polygon, with a negative area, which is reversed afterwards in assign_parents + test_one("simplex_asym_neg_rev", simplex, join_miter, end_flat, 3.202, +1.0, -1.5); + test_one("simplex_asym_pos_rev", simplex, join_miter, end_flat, 3.202, -1.5, +1.0); test_one("straight", straight, join_round, end_flat, 38.4187, 1.5, 1.5); test_one("straight", straight, join_miter, end_flat, 38.4187, 1.5, 1.5); diff --git a/test/algorithms/buffer/multi_polygon_buffer.cpp b/test/algorithms/buffer/multi_polygon_buffer.cpp index aa0f42890..c86c75a6a 100644 --- a/test/algorithms/buffer/multi_polygon_buffer.cpp +++ b/test/algorithms/buffer/multi_polygon_buffer.cpp @@ -24,7 +24,7 @@ static std::string const wrapped static std::string const triangles = "MULTIPOLYGON(((0 4,3 0,-2.5 -1,0 4)),((3 8,5.5 13,8 8,3 8)),((11 4,13.5 -1,8 0,11 4)))"; -// From robustness tests +// From robustness tests (rt) // Case with duplicate points (due to chained boxes) (round) static std::string const rt_a @@ -89,7 +89,6 @@ static std::string const rt_m1 static std::string const rt_m2 = "MULTIPOLYGON(((0 3,1 4,1 3,0 3)),((3 6,4 7,4 6,4 5,3 5,3 6)))"; - // Segment-intersection problem (disjoint nearly collinear segments were reported as intersecting), fixed. static std::string const rt_n = "MULTIPOLYGON(((0 0,1 1,1 0,0 0)),((3 3,4 4,4 3,3 3)))"; @@ -188,11 +187,9 @@ static std::string const rt_p20 static std::string const rt_p21 = "MULTIPOLYGON(((4 2,4 3,5 3,4 2)),((4 1,5 2,5 1,4 1)),((5 2,6 3,6 2,5 2)))"; - static std::string const rt_p22 = "MULTIPOLYGON(((4 8,5 9,5 8,4 8)),((5 9,6 10,6 9,5 9)),((1 7,1 8,2 8,2 7,1 7)),((2 6,3 7,3 6,2 6)))"; - // Occupation map with a uu-turn static std::string const rt_q1 = "MULTIPOLYGON(((4 6,4 7,5 7,5 6,4 6)),((1 6,1 7,2 7,2 6,1 6)),((1 9,1 10,2 10,2 9,1 9)))"; @@ -217,8 +214,29 @@ static std::string const rt_s2 static std::string const rt_t = "MULTIPOLYGON(((1 3,1 4,2 3,1 3)),((1 4,0 3,0 4,0 5,1 4)))"; +// Creates traversed ring +static std::string const rt_u1 + = "MULTIPOLYGON(((7 6,8 7,8 6,7 6)),((8 9,9 10,9 9,8 9)),((2 8,3 9,3 8,2 8)),((6 5,6 6,7 6,6 5)),((6 7,7 7,6 6,5 6,6 7)),((7 7,7 8,8 7,7 7)),((6 7,6 8,7 8,6 7)),((8 7,8 8,9 8,9 7,8 7)))"; +static std::string const rt_u2 + = "MULTIPOLYGON(((4 2,5 3,5 2,4 2)),((6 4,6 5,7 5,6 4)),((7 4,7 5,8 5,7 4)),((7 3,7 4,8 3,7 3)),((7 10,8 10,7 9,6 9,7 10)),((0 7,0 8,1 7,0 7)),((6 1,6 2,7 2,7 1,6 1)),((5 7,5 8,6 9,6 8,7 9,7 8,7 7,6 6,6 7,5 7)),((5 4,6 4,6 3,5 3,4 3,4 4,5 4)),((5 2,6 2,5 1,4 0,3 0,4 1,3 1,3 2,3 3,4 3,4 2,4.5 1.5,5 2)),((5 6,5 5,4 5,4 6,4 7,5 7,5 6)),((5 0,5 1,5.5 0.5,6 1,6 0,5 0)),((5 9,5 8,4 8,3 8,2 8,1 8,0 8,1 9,1 10,2 9,2 10,3 10,4 10,5 10,5 9)),((4 5,4 4,3 4,3 3,2 3,1 3,0 3,0 4,0 5,0 6,1 6,2 5,1 5,1 4,2 4,3 5,2 5,2 6,2.5 5.5,3 6,4 5)),((3 2,2 2,2 3,3 2)),((2 0,1 0,2 1,3 0,2 0)),((1 1,0 1,0 2,0 3,1 2,1.5 1.5,2 2,3 1,2 1,1 1)),((2 6,1 6,1 7,2 7,3 7,2 6)),((4 8,4 7,3 7,4 8)),((9 6,8 6,7 6,7 7,8 7,8.5 6.5,9 7,8 7,8 8,8.5 7.5,9 8,8 8,8 9,9 9,9 10,10 10,10 9,10 8,10 7,10 6,10 5,9 4,9 5,8 5,9 6)),((7 0,6 0,7 1,8 1,7 0)),((8 3,9 2,8 2,7 2,8 3)),((10 2,10 1,10 0,9 0,9 1,8 1,8 2,8.5 1.5,9 2,9 3,10 4,10 3,10 2)),((9 4,9 3,8 3,8 4,9 4)))"; +static std::string const rt_u3 + = "MULTIPOLYGON(((3 0,4 1,4 0,3 0)),((2 0,2 1,3 1,2 0)),((6 7,7 8,7 7,6 7)),((1 2,2 3,2 2,1 2)),((9 1,10 2,10 1,9 1)),((0 2,0 3,1 3,1 2,0 2)),((5 0,5 1,6 1,6 0,5 0)),((1 1,2 2,2 1,1 1)),((0 7,0 8,1 7,0 7)),((9 0,10 1,10 0,9 0)),((0 5,0 6,1 6,1 5,0 5)),((1 6,2 7,2 6,1 6)),((7 0,8 1,8 0,7 0)),((8 6,9 7,9 6,8 6)),((9 6,10 7,10 6,9 6)),((1 4,1 5,2 5,1 4)),((5 6,4 5,4 6,5 7,5 6)),((5 4,4.5 3.5,5 3,4 3,4 2,3 1,3 2,3 3,2 3,2 4,3 4,4 4,5 5,5 4)),((4 7,3 7,3 8,4 9,5 10,6 10,6 9,5 9,4 8,5 8,4 7)),((6 3,5 3,5 4,5.5 3.5,6 4,7 4,7 3,8 3,8 2,8 1,7 1,6 1,6 2,6 3)),((3 5,2 4,2 5,2 6,3 5)),((1 1,1 0,0 0,0 1,1 2,1 1)),((2 9,2 8,1 8,0 8,1 9,1 10,1.5 9.5,2 10,2.5 9.5,3 10,3 9,2 9)),((6 5,6 6,7 7,8 7,8 6,7 6,7 5,6 4,6 5)),((7 8,6 8,6 9,7 9,8 8,7 8)),((9 10,10 10,10 9,10 8,9 7,9 8,8 8,9 9,8 9,8 10,9 10)))"; + +static std::string const rt_u4 + = "MULTIPOLYGON(((5 0,6 1,6 0,5 0)),((6 1,6 2,7 2,7 1,6 1)),((6 6,7 7,7 6,6 6)),((4 7,4 8,5 8,4 7)),((1 6,1 7,2 7,1 6)),((3 4,3 5,4 5,3 4)),((2 0,2 1,3 0,2 0)),((7 2,7 3,8 3,7 2)),((3 3,4 4,4 3,3 3)),((5 9,5 10,6 10,7 10,6 9,5 8,5 9)),((5 4,5 5,6 4,5 4)),((3 1,4 2,4 1,3 1)),((3 0,3 1,4 0,3 0)),((2 7,2 8,3 8,3 7,2 7)),((9 2,9 3,10 2,9 2)),((6 2,6 3,7 3,6 2)),((8 8,9 9,9 8,8 8)),((2 1,2 2,3 2,3 1,2 1)),((4 3,5 4,5 3,4 3)),((4 6,5 7,5 6,4 6)),((1 8,1 9,2 8,1 7,1 8)),((8 8,9 7,8 7,7 7,7 8,8 8)),((8 1,8 2,9 2,9 1,10 1,9 0,8 0,8 1)),((5 2,4 2,4 3,5 2)),((2 5,1 5,1 6,2 6,3 5,2 5)),((1 3,2 4,2 3,2 2,1 1,0 1,1 2,1 3)),((1 0,0 0,1 1,2 1,1.5 0.5,2 0,1 0)),((2 10,3 10,4 10,4 9,3 9,2 8,2 9,1 9,0 9,1 10,2 10)),((9 5,9 6,10 6,10 5,10 4,9 4,8.5 3.5,9 3,8 3,8 4,7 4,7 5,8 5,9 5)),((7 0,6 0,7 1,8 1,7 0)),((7 9,7 8,6 8,6 9,7 9)))"; + +static std::string const rt_u5 + = "MULTIPOLYGON(((4 3,4 4,5 4,5 3,4 3)),((6 5,6 6,7 6,6 5)),((5 4,6 5,6 4,5 4)),((4 0,4 1,5 1,5 0,4 0)),((7 8,8 9,8 8,7 8)),((8 2,8 3,9 3,8 2)),((2 1,2 2,3 1,2 1)),((5 7,5 8,6 8,5 7)),((4 5,4 6,5 5,4 5)),((7 0,8 1,8 0,7 0)),((7 2,8 1,7 1,6 1,7 2)),((3 3,4 3,4 2,3 2,3 3)),((3 9,3 10,4 9,3 9)),((1 2,2 3,2 2,1 2)),((2 4,2 5,3 4,2 3,2 4)),((3 7,4 7,3 6,2 6,3 7)))"; + +static std::string const rt_u6 + = "MULTIPOLYGON(((2 2,3 3,3 2,2 2)),((9 8,9 9,10 9,10 8,9 8)),((5 3,6 4,6 3,5 3)),((5 5,5 6,6 6,5 5)),((5 1,6 2,6 1,5 1)),((6 5,7 6,7 5,6 5)),((3 0,4 1,4 0,3 0)),((6 6,6 7,7 6,6 6)),((9 2,10 2,10 1,9 1,9 2)),((6 8,6 9,7 9,7 8,6 8)),((7 0,7 1,8 0,7 0)),((4 4,4 5,5 5,4 4)),((0 7,0 8,1 8,0 7)),((5 9,6 10,6 9,5 9)),((4 9,4 10,5 10,5 9,4 9)),((3 7,4 7,3 6,2 6,3 7)),((9 7,10 6,9 6,8 6,9 7)),((5 3,5 2,4 2,4 3,4 4,5 4,5 3)),((1 1,2 0,1 0,0 0,1 1)),((2 10,3 10,3 9,2 9,1 9,1 10,2 10)),((8.5 4.5,9 4,8 4,7 4,8 5,9 5,8.5 4.5)),((8 3,9 3,9 2,8 2,8 3)))"; + +// For this case (and more), get_left_turns or using a more specific sort order is essential +static std::string const rt_u7 + = "MULTIPOLYGON(((4 5,4 6,5 5,4 5)),((9 2,9 3,10 3,10 2,9 2)),((7 3,7 4,8 4,8 3,7 3)),((5 5,6 6,6 5,5 5)),((3 6,4 7,4 6,3 6)),((0 5,0 6,1 5,0 5)))"; + // = "MULTIPOLYGON(((4 5,4 6,5 5,4 5)),((9 2,9 3,10 3,10 2,9 2)),((7 3,7 4,8 4,8 3,7 3)),((5 5,6 6,6 5,5 5)),((3 6,4 7,4 6,3 6)))"; //removing the leftmost uninvolved polygon solves somehow the problem... template void test_all() @@ -244,9 +262,6 @@ void test_all() test_one("multi_simplex_50", simplex, join_round, end_flat, 174.46, 5.0); test_one("multi_simplex_50", simplex, join_miter, end_flat, 298.797, 5.0); - // This one does not work: - // test_one("multi_simplex_50", simplex, 'd', 174.46, 5.0); - test_one("zonethru_05", zonethru, join_round, end_flat, 67.4627, 0.5); test_one("zonethru_05", zonethru, join_miter, end_flat, 68.0000, 0.5); test_one("zonethru_10", zonethru, join_round, end_flat, 93.8508, 1.0); @@ -260,9 +275,7 @@ void test_all() test_one("wrapped_15", wrapped, join_round, end_flat, 167.066, 1.5); test_one("wrapped_15", wrapped, join_miter, end_flat, 169.000, 1.5); - // TODO: there is still an undetected hole inside rt_a test_one("rt_a", rt_a, join_round, end_flat, 34.5381, 1.0); - test_one("rt_a", rt_a, join_miter, end_flat, 36, 1.0); test_one("rt_b", rt_b, join_round, end_flat, 31.4186, 1.0); test_one("rt_b", rt_b, join_miter, end_flat, 34, 1.0); @@ -272,7 +285,6 @@ void test_all() test_one("rt_d", rt_d, join_miter, end_flat, 19.8823, 0.3); test_one("rt_e", rt_e, join_round, end_flat, 14.1866, 0.3); test_one("rt_e", rt_e, join_miter, end_flat, 15.1198, 0.3); - // This does not add anything: test_one("rt_f", rt_f, join_round, end_flat, 4.28937, 0.3); test_one("rt_f", rt_f, join_miter, end_flat, 4.60853, 0.3); @@ -289,13 +301,11 @@ void test_all() test_one("rt_j", rt_j, join_miter, end_flat, 35.1421, 1.0); test_one("rt_k", rt_k, join_round, end_flat, 42.0092, 1.0); test_one("rt_k", rt_k, join_miter, end_flat, 48.0563, 1.0); - // This does not add anything: test_one("rt_l", rt_l, join_round, end_flat, 14.1074, 1.0); test_one("rt_l", rt_l, join_miter, end_flat, 19.3995, 1.0); test_one("rt_m1", rt_m1, join_round, end_flat, 14.1074, 1.0); test_one("rt_m1", rt_m1, join_miter, end_flat, 19.4853, 1.0); test_one("rt_m2", rt_m2, join_miter, end_flat, 21.4853, 1.0); - // This does not add anything: test_one("rt_n", rt_n, join_round, end_flat, 14.1074, 1.0); test_one("rt_n", rt_n, join_miter, end_flat, 18.4853, 1.0); test_one("rt_o1", rt_o1, join_round, end_flat, 17.536, 1.0); @@ -336,9 +346,20 @@ void test_all() test_one("rt_s1", rt_s1, join_miter, end_flat, 20.4853, 1.0); test_one("rt_s2", rt_s2, join_miter, end_flat, 24.6495, 1.0); test_one("rt_t", rt_t, join_miter, end_flat, 15.6569, 1.0); -} -int point_buffer_count; + test_one("rt_u1", rt_u1, join_round, end_flat, 33.2032, 1.0); + test_one("rt_u2", rt_u2, join_round, end_flat, 138.8001, 1.0); + test_one("rt_u3", rt_u3, join_round, end_flat, 133.4526, 1.0); + test_one("rt_u4", rt_u4, join_round, end_flat, 126.9268, 1.0); + test_one("rt_u5", rt_u5, join_round, end_flat, 78.4906, 1.0); + test_one("rt_u6", rt_u6, join_round, end_flat, 115.4461, 1.0); +#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS) + { + bg::strategy::buffer::join_round join_round_rough(12); // temporary + test_one("rt_u7", rt_u7, join_round_rough, end_flat, 999, 1.0); + } +#endif +} int test_main(int, char* []) { @@ -348,3 +369,5 @@ int test_main(int, char* []) return 0; } +// intersecting: +//= "MULTIPOLYGON(((8 6,9 7,9 6,8 6)),((0 6,0 7,1 6,0 6)),((1 6,1 7,2 7,2 6,1 6)),((2 0,2 1,3 0,2 0)),((9 2,10 3,10 2,9 2)),((7 0,7 1,8 1,7 0)),((4 6,5 7,5 6,4 6)),((7 1,7 2,8 2,7 1)),((0 8,0 9,1 8,0 8)),((0 1,0 2,1 2,0 1)),((7 2,7 3,8 3,7 2)),((9 8,9 9,10 8,9 8)),((5 2,5 3,6 3,6 2,5 2)),((1 1,1 2,2 2,2 1,1 1)),((5 3,4 2,4 3,5 4,6 5,6 6,6 7,7 7,7 6,8 6,7 5,8 4,7 4,6 4,5 3)),((3 4,2 4,2 5,2 6,3 6,3 5,4 5,3 4)),((3 7,2 7,2 8,3 8,4 8,5 8,4 7,3 7)))"; diff --git a/test/algorithms/buffer/polygon_buffer.cpp b/test/algorithms/buffer/polygon_buffer.cpp index 0cba186fa..e19b4f500 100644 --- a/test/algorithms/buffer/polygon_buffer.cpp +++ b/test/algorithms/buffer/polygon_buffer.cpp @@ -327,24 +327,21 @@ void test_all() test_one("donut_simplex6", donut_simplex, join_miter, end_flat, 12.8920, -0.6); test_one("donut_simplex6", donut_simplex, join_round, end_flat, 12.9157, -0.6); -#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS) - // Areas yet to be changed - test_one("ticket_10398_1_5", ticket_10398_1, join_miter, end_flat, 99, 0.5); - test_one("ticket_10398_1_25", ticket_10398_1, join_miter, end_flat, 99, 2.5); - test_one("ticket_10398_1_84", ticket_10398_1, join_miter, end_flat, 99, 8.4); + test_one("ticket_10398_1_5", ticket_10398_1, join_miter, end_flat, 494.7192, 0.5, -999, false); + test_one("ticket_10398_1_25", ticket_10398_1, join_miter, end_flat, 697.7798, 2.5, -999, false); + test_one("ticket_10398_1_84", ticket_10398_1, join_miter, end_flat, 1470.8096, 8.4, -999, false); - test_one("ticket_10398_2_45", ticket_10398_2, join_miter, end_flat, 99, 4.5); - test_one("ticket_10398_2_62", ticket_10398_2, join_miter, end_flat, 99, 6.2); - test_one("ticket_10398_2_73", ticket_10398_2, join_miter, end_flat, 99, 7.3); + test_one("ticket_10398_2_45", ticket_10398_2, join_miter, end_flat, 535.4780, 4.5, -999, false); + test_one("ticket_10398_2_62", ticket_10398_2, join_miter, end_flat, 705.2046, 6.2, -999, false); + test_one("ticket_10398_2_73", ticket_10398_2, join_miter, end_flat, 827.3394, 7.3, -999, false); - test_one("ticket_10398_3_12", ticket_10398_3, join_miter, end_flat, 99, 1.2); - test_one("ticket_10398_3_35", ticket_10398_3, join_miter, end_flat, 99, 3.5); - test_one("ticket_10398_3_54", ticket_10398_3, join_miter, end_flat, 99, 5.4); + test_one("ticket_10398_3_12", ticket_10398_3, join_miter, end_flat, 122.9443, 1.2, -999, false); + test_one("ticket_10398_3_35", ticket_10398_3, join_miter, end_flat, 258.2729, 3.5, -999, false); + test_one("ticket_10398_3_54", ticket_10398_3, join_miter, end_flat, 402.0571, 5.4, -999, false); - test_one("ticket_10398_4_30", ticket_10398_4, join_miter, end_flat, 99, 3.0); - test_one("ticket_10398_4_66", ticket_10398_4, join_miter, end_flat, 99, 6.6); - test_one("ticket_10398_4_91", ticket_10398_4, join_miter, end_flat, 99, 9.1); -#endif + test_one("ticket_10398_4_30", ticket_10398_4, join_miter, end_flat, 257.9482, 3.0, -999, false); + test_one("ticket_10398_4_66", ticket_10398_4, join_miter, end_flat, 553.0112, 6.6, -999, false); + test_one("ticket_10398_4_91", ticket_10398_4, join_miter, end_flat, 819.1406, 9.1, -999, false); test_one("ticket_10412", ticket_10412, join_miter, end_flat, 3109.6616, 1.5, -999, false); } diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index cd6685d95..6a8b9932d 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -111,8 +111,9 @@ struct svg_visitor std::map > offsets; + int index = 0; for (typename boost::range_iterator::type it = - boost::begin(turns); it != boost::end(turns); ++it) + boost::begin(turns); it != boost::end(turns); ++it, index++) { char color = 'g'; std::string fill = "fill:rgb(0,255,0);"; @@ -132,17 +133,32 @@ struct svg_visitor fill += "fill-opacity:0.7;"; std::ostringstream out; - out << it->operations[0].piece_index << "/" << it->operations[1].piece_index + out << index + << " " << it->operations[0].piece_index << "/" << it->operations[1].piece_index << " " << si(it->operations[0].seg_id) << "/" << si(it->operations[1].seg_id) + +// If you want to see travel information + << std::endl + << " nxt " << it->operations[0].enriched.travels_to_ip_index + << "/" << it->operations[1].enriched.travels_to_ip_index + << " or " << it->operations[0].enriched.next_ip_index + << "/" << it->operations[1].enriched.next_ip_index + //<< " frac " << it->operations[0].fraction + +// If you want to see robust-point coordinates (e.g. to find duplicates) +// << std::endl +// << " " << bg::get<0>(it->robust_point) << " , " << bg::get<1>(it->robust_point) + << std::endl; out << " " << bg::method_char(it->method) << ":" << bg::operation_char(it->operations[0].operation) << "/" << bg::operation_char(it->operations[1].operation); - out << " " << (!it->selectable_start ? "w" : "") - << (it->count_on_multi > 0 ? "m" : "") - << (it->count_on_occupied > 0 ? "o" : "") + out << " " << (it->count_on_offsetted > 0 ? "b" : "") // b: offsetted border + << (it->count_within_near_offsetted > 0 ? "n" : "") + << (it->count_within > 0 ? "w" : "") << (it->count_on_helper > 0 ? "h" : "") + << (it->count_on_multi > 0 ? "m" : "") ; offsets[it->get_robust_point()] += 10; @@ -208,10 +224,11 @@ struct svg_visitor std::ostringstream out; out << piece.index << "/" << int(piece.type) << "/" << piece.first_seg_id.segment_index << ".." << piece.last_segment_index - 1; point_type label_point = corner.front(); - if (corner.size() >= 2) + int const mid_offset = piece.offsetted_count / 2 - 1; + if (mid_offset >= 0 && mid_offset + 1 < corner.size()) { - bg::set<0>(label_point, (bg::get<0>(corner[0]) + bg::get<0>(corner[1])) / 2.0); - bg::set<1>(label_point, (bg::get<1>(corner[0]) + bg::get<1>(corner[1])) / 2.0); + bg::set<0>(label_point, (bg::get<0>(corner[mid_offset]) + bg::get<0>(corner[mid_offset + 1])) / 2.0); + bg::set<1>(label_point, (bg::get<1>(corner[mid_offset]) + bg::get<1>(corner[mid_offset + 1])) / 2.0); } m_mapper.text(label_point, out.str(), "fill:rgb(255,0,0);font-family='Arial';font-size:10px;", 5, 5); } diff --git a/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp b/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp index d62e83a2b..737f22c2e 100644 --- a/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp +++ b/test/robustness/overlay/buffer/recursive_polygons_buffer.cpp @@ -200,6 +200,8 @@ bool test_buffer(MultiPolygon& result, int& index, bg::strategy::buffer::end_round end_strategy; bg::strategy::buffer::point_circle point_strategy; bg::strategy::buffer::side_straight side_strategy; + bg::strategy::buffer::join_round join_round_strategy(100); // Compatible with unit tests + bg::strategy::buffer::join_miter join_miter_strategy; try { @@ -208,13 +210,13 @@ bool test_buffer(MultiPolygon& result, int& index, case 1 : bg::buffer(mp, buffered, distance_strategy, side_strategy, - bg::strategy::buffer::join_round(), + join_round_strategy, end_strategy, point_strategy); break; case 2 : bg::buffer(mp, buffered, distance_strategy, side_strategy, - bg::strategy::buffer::join_miter(), + join_miter_strategy, end_strategy, point_strategy); break; default :