mirror of https://github.com/KLayout/klayout.git
Fixed issue #228
Reason for the problem: the interaction test has to keep separate "inside" records for both below and above the scanline, not just once. With the single record, the step in the left polygon erased the "inside" condition.
This commit is contained in:
parent
93f4cbf294
commit
fe0d3e28ba
|
|
@ -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 <property_type> *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 <property_type>::const_iterator i = m_inside.begin (); i != m_inside.end (); ++i) {
|
||||
for (std::set <property_type>::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 <property_type>::const_iterator i = m_inside.begin (); i != m_inside.end (); ++i) {
|
||||
for (std::set <property_type>::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 <property_type>::const_iterator i = m_inside.begin (); i != m_inside.end (); ++i) {
|
||||
for (std::set <property_type>::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 <property_type>::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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <int> m_wcv_n, m_wcv_s;
|
||||
std::set <property_type> m_inside;
|
||||
std::set <property_type> m_inside_n, m_inside_s;
|
||||
std::set<std::pair<property_type, property_type> > m_interactions;
|
||||
std::set<property_type> m_non_interactions;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue