diff --git a/src/db/db/dbEdgeProcessor.cc b/src/db/db/dbEdgeProcessor.cc index 0a1481cd1..756f6af72 100644 --- a/src/db/db/dbEdgeProcessor.cc +++ b/src/db/db/dbEdgeProcessor.cc @@ -639,7 +639,8 @@ InteractionDetector::reset () { m_wcv_n.clear (); m_wcv_s.clear (); - m_inside.clear (); + m_inside_n.clear (); + m_inside_s.clear (); } void @@ -649,7 +650,8 @@ InteractionDetector::reserve (size_t n) m_wcv_s.clear (); m_wcv_n.resize (n, 0); m_wcv_s.resize (n, 0); - m_inside.clear (); + m_inside_n.clear (); + m_inside_s.clear (); } int @@ -667,9 +669,11 @@ InteractionDetector::edge (bool north, bool enter, property_type p) // we have to catch interactions between objects north and south to the scanline if (north || (m_mode == 0 && m_include_touching)) { + std::set *inside = north ? &m_inside_n : &m_inside_s; + if (inside_after < inside_before) { - m_inside.erase (p); + inside->erase (p); if (m_mode != 0) { @@ -677,7 +681,7 @@ InteractionDetector::edge (bool north, bool enter, property_type p) // (due to prefer_touch == true and the sorting of coincident edges by property id) // hence every remaining parts count as non-interacting (outside) if (p == m_container_id) { - for (std::set ::const_iterator i = m_inside.begin (); i != m_inside.end (); ++i) { + for (std::set ::const_iterator i = inside->begin (); i != inside->end (); ++i) { if (*i != m_container_id) { m_non_interactions.insert (*i); } @@ -695,13 +699,13 @@ InteractionDetector::edge (bool north, bool enter, property_type p) // note that the container parts will be delivered first of all coincident // edges hence we can check whether the container is present even for coincident // edges - if (m_inside.find (m_container_id) != m_inside.end ()) { + if (inside->find (m_container_id) != inside->end ()) { m_interactions.insert (std::make_pair (m_container_id, p)); } else { m_non_interactions.insert (p); } } else { - for (std::set ::const_iterator i = m_inside.begin (); i != m_inside.end (); ++i) { + for (std::set ::const_iterator i = inside->begin (); i != inside->end (); ++i) { if (*i != m_container_id) { m_interactions.insert (std::make_pair (m_container_id, *i)); } @@ -710,7 +714,15 @@ InteractionDetector::edge (bool north, bool enter, property_type p) } else { - for (std::set ::const_iterator i = m_inside.begin (); i != m_inside.end (); ++i) { + for (std::set ::const_iterator i = m_inside_n.begin (); i != m_inside_n.end (); ++i) { + if (*i < p) { + m_interactions.insert (std::make_pair (*i, p)); + } else if (*i > p) { + m_interactions.insert (std::make_pair (p, *i)); + } + } + + for (std::set ::const_iterator i = m_inside_s.begin (); i != m_inside_s.end (); ++i) { if (*i < p) { m_interactions.insert (std::make_pair (*i, p)); } else if (*i > p) { @@ -720,7 +732,7 @@ InteractionDetector::edge (bool north, bool enter, property_type p) } - m_inside.insert (p); + inside->insert (p); } diff --git a/src/db/db/dbEdgeProcessor.h b/src/db/db/dbEdgeProcessor.h index bca103bc2..9cca1308a 100644 --- a/src/db/db/dbEdgeProcessor.h +++ b/src/db/db/dbEdgeProcessor.h @@ -299,7 +299,7 @@ public: virtual void reserve (size_t n); virtual int edge (bool north, bool enter, property_type p); virtual int compare_ns () const; - virtual bool is_reset () const { return m_inside.empty (); } + virtual bool is_reset () const { return m_inside_s.empty () && m_inside_n.empty (); } virtual bool prefer_touch () const { return m_include_touching; } private: @@ -307,7 +307,7 @@ private: bool m_include_touching; property_type m_container_id; std::vector m_wcv_n, m_wcv_s; - std::set m_inside; + std::set m_inside_n, m_inside_s; std::set > m_interactions; std::set m_non_interactions; }; diff --git a/src/db/unit_tests/dbRegion.cc b/src/db/unit_tests/dbRegion.cc index 686ec4062..55f61df92 100644 --- a/src/db/unit_tests/dbRegion.cc +++ b/src/db/unit_tests/dbRegion.cc @@ -1329,3 +1329,27 @@ TEST(30c) EXPECT_EQ (r.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); } +TEST(issue_228) +{ + db::Region r; + db::Point pts[] = { + db::Point (0, 10), + db::Point (0, 290), + db::Point (280, 290), + db::Point (280, 230), + db::Point (360, 230), + db::Point (360, 70), + db::Point (280,70), + db::Point (280,10) + }; + + db::Polygon poly; + poly.assign_hull (pts, pts + sizeof (pts) / sizeof (pts [0])); + r.insert (poly); + + db::Region rr; + rr.insert (db::Box (360, 70, 480, 230)); + + EXPECT_EQ (r.selected_interacting (rr).to_string (), r.to_string ()); + EXPECT_EQ (rr.selected_interacting (r).to_string (), rr.to_string ()); +}