WIP: Some optimization of check functions

This commit is contained in:
Matthias Koefferlein 2020-12-27 01:05:55 +01:00
parent 3f8113e404
commit 1026d197cb
2 changed files with 77 additions and 65 deletions

View File

@ -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<db::PolygonRef> &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<db::Polygon> &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 <class TS, class TI>
check_local_operation<TS, TI>::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<TS, TI>::check_local_operation (const EdgeRelationFilter &
// .. nothing yet ..
}
namespace
{
template <class T, class S>
void insert_into_hash (std::unordered_set<T> &, const S &)
{
tl_assert (false);
}
template <class T>
void insert_into_hash (std::unordered_set<T> &hash, const T &shape)
{
hash.insert (shape);
}
}
template <class TS, class TI>
void
check_local_operation<TS, TI>::compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
@ -190,13 +180,14 @@ check_local_operation<TS, TI>::compute_local (db::Layout *layout, const shape_in
db::box_scanner<TS, size_t> scanner;
std::unordered_set<TI> polygons;
if (m_has_other) {
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (typename shape_interactions<TS, TI>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
polygons.insert (interactions.intruder_shape (*j).second);
}
std::set<unsigned int> ids;
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (typename shape_interactions<TS, TI>::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<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
@ -207,14 +198,20 @@ check_local_operation<TS, TI>::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<TI>::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<unsigned int>::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<TS, TI>::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<TI>::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<unsigned int>::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<TI>::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<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
polygons.insert (interactions.subject_shape (i->first));
for (typename shape_interactions<TS, TI>::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<TI>::const_iterator o = polygons.begin (); o != polygons.end (); ++o) {
scanner.insert (push_polygon_to_heap (layout, *o, heap), n);
for (typename shape_interactions<TS, TI>::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<unsigned int>::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 {

View File

@ -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 (), "");
}