diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 6bc88688e..4db4a302b 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -46,32 +46,6 @@ static inline const db::PolygonRef *push_polygon_to_heap (db::Layout *layout, co return &heap.back (); } -static inline bool needs_merge (const std::unordered_set &polygons) -{ - if (polygons.empty ()) { - return false; - } else if (polygons.size () > 1) { - return true; - } else if (polygons.begin ()->obj ().is_box ()) { - return false; - } else { - return true; - } -} - -static inline bool needs_merge (const std::unordered_set &polygons) -{ - if (polygons.empty ()) { - return false; - } else if (polygons.size () > 1) { - return true; - } else if (polygons.begin ()->is_box ()) { - return false; - } else { - return true; - } -} - struct ResultInserter { typedef db::Polygon value_type; @@ -167,7 +141,6 @@ static bool shields_interaction (const db::EdgePair &ep, const P &poly) return false; } - template check_local_operation::check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool other_is_merged, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter) : m_check (check), m_different_polygons (different_polygons), m_has_other (has_other), m_other_is_merged (other_is_merged), m_shielded (shielded), m_opposite_filter (opposite_filter), m_rect_filter (rect_filter) @@ -175,6 +148,23 @@ check_local_operation::check_local_operation (const EdgeRelationFilter & // .. nothing yet .. } +namespace +{ + +template +void insert_into_hash (std::unordered_set &, const S &) +{ + tl_assert (false); +} + +template +void insert_into_hash (std::unordered_set &hash, const T &shape) +{ + hash.insert (shape); +} + +} + template void check_local_operation::compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const @@ -190,13 +180,14 @@ check_local_operation::compute_local (db::Layout *layout, const shape_in db::box_scanner scanner; std::unordered_set polygons; - if (m_has_other) { - - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - polygons.insert (interactions.intruder_shape (*j).second); - } + std::set ids; + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + ids.insert (*j); } + } + + if (m_has_other) { size_t n = 0; for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { @@ -207,14 +198,20 @@ check_local_operation::compute_local (db::Layout *layout, const shape_in // merge the intruders to remove inner edges - if (! m_other_is_merged && needs_merge (polygons)) { + if (ids.empty ()) { + + // empty intruders + + } else if (! m_other_is_merged && (ids.size () > 1 || ! interactions.intruder_shape (*ids.begin ()).second.is_box ())) { db::EdgeProcessor ep; ep.clear (); size_t i = 0; - for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { - for (typename TI::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) { + + for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + const TI &is = interactions.intruder_shape (*id).second; + for (typename TI::polygon_edge_iterator e = is.begin_edge (); ! e.at_end (); ++e) { ep.insert (*e, i); } ++i; @@ -227,29 +224,44 @@ check_local_operation::compute_local (db::Layout *layout, const shape_in db::SimpleMerge op (1 /*wc>0*/); ep.process (pg, op); - } + n = 1; + for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { + scanner.insert (push_polygon_to_heap (layout, *o, heap), n); + n += 2; + } + + } else { + + n = 1; + for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + scanner.insert (push_polygon_to_heap (layout, interactions.intruder_shape (*id).second, heap), n); + n += 2; + } - n = 1; - for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { - scanner.insert (push_polygon_to_heap (layout, *o, heap), n); - n += 2; } } else { - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - polygons.insert (interactions.subject_shape (i->first)); - for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - polygons.insert (interactions.intruder_shape (*j).second); - } - } + // NOTE: we need to eliminate identical shapes from intruders and subjects because those will shield size_t n = 0; - for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { - scanner.insert (push_polygon_to_heap (layout, *o, heap), n); + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + // we can't directly insert because TS may be != TI + const TS &ts = interactions.subject_shape (i->first); + insert_into_hash (polygons, ts); + scanner.insert (push_polygon_to_heap (layout, ts, heap), n); n += 2; } + for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + if (polygons.find (ti) == polygons.end ()) { + scanner.insert (push_polygon_to_heap (layout, ti, heap), n); + n += 2; + } + } + } do { diff --git a/src/db/unit_tests/dbRegionTests.cc b/src/db/unit_tests/dbRegionTests.cc index 62e8190d4..9162acfdc 100644 --- a/src/db/unit_tests/dbRegionTests.cc +++ b/src/db/unit_tests/dbRegionTests.cc @@ -508,11 +508,11 @@ TEST(15a) EXPECT_EQ (r.width_check (15).to_string (), "(0,0;0,10)/(10,10;10,0);(0,10;10,10)/(10,0;0,0)"); EXPECT_EQ (r.width_check (5).to_string (), ""); EXPECT_EQ (r.width_check (5, db::RegionCheckOptions (false, db::Euclidian, 91)).to_string (), "(0,5;0,10)/(0,10;5,10);(0,0;0,5)/(5,0;0,0);(5,10;10,10)/(10,10;10,5);(10,5;10,0)/(10,0;5,0);(20,45;20,50)/(20,50;25,50);(20,20;20,25)/(25,20;20,20);(35,50;40,50)/(40,50;40,45);(40,25;40,20)/(40,20;35,20)"); - EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Euclidian, 91)).to_string (), "(10,10;10,9)/(21,20;20,20);(10,10;10,9)/(20,20;20,21);(9,10;10,10)/(21,20;20,20);(9,10;10,10)/(20,20;20,21)"); - EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square, 91)).to_string (), "(10,10;10,5)/(25,20;20,20);(10,10;10,5)/(20,20;20,25);(5,10;10,10)/(25,20;20,20);(5,10;10,10)/(20,20;20,25)"); - EXPECT_EQ (r.space_check (15).to_string (), "(10,10;10,9)/(20,20;20,21);(9,10;10,10)/(21,20;20,20)"); - EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (true)).to_string (), "(10,10;10,0)/(20,20;20,50);(0,10;10,10)/(40,20;20,20)"); - EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square)).to_string (), "(10,10;10,5)/(20,20;20,25);(5,10;10,10)/(25,20;20,20)"); + EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Euclidian, 91)).to_string (), "(21,20;20,20)/(10,10;10,9);(21,20;20,20)/(9,10;10,10);(20,20;20,21)/(10,10;10,9);(20,20;20,21)/(9,10;10,10)"); + EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square, 91)).to_string (), "(25,20;20,20)/(10,10;10,5);(25,20;20,20)/(5,10;10,10);(20,20;20,25)/(10,10;10,5);(20,20;20,25)/(5,10;10,10)"); + EXPECT_EQ (r.space_check (15).to_string (), "(21,20;20,20)/(9,10;10,10);(20,20;20,21)/(10,10;10,9)"); + EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (true)).to_string (), "(40,20;20,20)/(0,10;10,10);(20,20;20,50)/(10,10;10,0)"); + EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square)).to_string (), "(25,20;20,20)/(5,10;10,10);(20,20;20,25)/(10,10;10,5)"); r.clear (); db::Point pts[] = { @@ -545,9 +545,9 @@ TEST(15b) r.insert (db::Box (db::Point (400, 200), db::Point (500, 300))); EXPECT_EQ (r.width_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(400,200;400,300)/(500,300;500,200)"); - EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(200,500;200,300)/(300,300;300,500);(300,200;400,200)/(400,300;300,300);(200,200;200,0)/(300,0;300,200)"); + EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)/(400,300;300,300);(300,300;300,500)/(200,500;200,300);(300,0;300,200)/(200,200;200,0)"); EXPECT_EQ (r.notch_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)/(400,300;300,300)"); - EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,300;300,500)/(200,500;200,300);(300,0;300,200)/(200,200;200,0)"); + EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(200,500;200,300)/(300,300;300,500);(200,200;200,0)/(300,0;300,200)"); } TEST(15c) @@ -563,9 +563,9 @@ TEST(15c) r.insert (db::Box (db::Point (400, 250), db::Point (500, 300))); EXPECT_EQ (r.width_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(400,200;400,300)/(500,300;500,200)"); - EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(200,500;200,300)/(300,300;300,500);(300,200;400,200)/(400,300;300,300);(200,200;200,0)/(300,0;300,200)"); + EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)/(400,300;300,300);(300,300;300,500)/(200,500;200,300);(300,0;300,200)/(200,200;200,0)"); EXPECT_EQ (r.notch_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)/(400,300;300,300)"); - EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,300;300,500)/(200,500;200,300);(300,0;300,200)/(200,200;200,0)"); + EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(200,500;200,300)/(300,300;300,500);(200,200;200,0)/(300,0;300,200)"); } TEST(15d) @@ -581,12 +581,12 @@ TEST(15d) r.insert (db::Box (db::Point (0, 140), db::Point (350, 160))); EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), - "(600,100;700,100)/(700,200;600,200);" - "(300,160;350,160)/(350,200;300,200);" - "(0,100;100,100)/(100,140;0,140);" - "(300,100;350,100)/(350,140;300,140);" - "(300,100;400,100)/(400,200;300,200);" - "(100,200;0,200)/(0,160;100,160)" + "(100,140;0,140)/(0,100;100,100);" + "(350,140;300,140)/(300,100;350,100);" + "(100,200;0,200)/(0,160;100,160);" + "(400,200;300,200)/(300,100;400,100);" + "(350,200;300,200)/(300,160;350,160);" + "(700,200;600,200)/(600,100;700,100)" ); } @@ -1242,7 +1242,7 @@ TEST(20) { db::Region r1 (db::RecursiveShapeIterator (ly, ly.cell (top), l2)); EXPECT_EQ (r1.has_valid_polygons (), false); - EXPECT_EQ (r1.space_check (30).to_string (), "(70,20;70,12)/(80,40;80,48);(60,20;70,20)/(92,40;80,40);(40,40;40,10)/(60,10;60,20)"); + EXPECT_EQ (r1.space_check (30).to_string (), "(40,40;40,10)/(60,10;60,20);(92,40;80,40)/(60,20;70,20);(80,40;80,48)/(70,20;70,12)"); EXPECT_EQ (r1.space_check (2).to_string (), ""); }