WIP: rectangle error pattern filter implemented.

This commit is contained in:
Matthias Koefferlein 2020-12-06 16:33:10 +01:00
parent 6c4d1f4ef3
commit 153289b5d8
5 changed files with 172 additions and 10 deletions

View File

@ -3218,6 +3218,14 @@ public:
return this->obj ().perimeter ();
}
/**
* @brief Returns a value indicating whether the polygon is a box
*/
bool is_box () const
{
return this->obj ().is_box ();
}
/**
* @brief Return the transformed object
*

View File

@ -312,10 +312,72 @@ check_local_operation<TS, TI>::compute_local (db::Layout *layout, const shape_in
}
// implements filtering on rectangles
// implements error filtering on rectangles
if (m_rect_filter != RectFilter::NoSideAllowed && ! result.empty ()) {
// @@@ TODO: implement @@@
std::unordered_set<db::EdgePair> waived;
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const TS &subject = interactions.subject_shape (i->first);
if (! subject.is_box ()) {
continue;
}
unsigned int p = 1;
std::map<db::Edge, unsigned int> edges_with_errors;
for (typename TS::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end (); ++e) {
edges_with_errors [*e] = p;
p <<= 1;
}
unsigned int error_pattern = 0;
for (std::unordered_set<db::EdgePair>::const_iterator ep = result.begin (); ep != result.end (); ++ep) {
std::map<db::Edge, unsigned int>::iterator i = edges_with_errors.find (ep->first ());
if (i != edges_with_errors.end ()) {
if ((error_pattern & i->second) == 0) {
error_pattern |= i->second;
}
}
}
if (error_pattern != 0) {
bool can_be_waived = false;
// decode pattern: consider each group of 4 bits and match them against the error pattern in their four rotation variants
uint32_t p32 = (uint32_t) m_rect_filter;
while (p32 != 0 && ! can_be_waived) {
uint32_t p4 = p32 & 0xf;
p32 >>= 4;
for (unsigned int r = 0; r < 4 && ! can_be_waived; ++r) {
can_be_waived = (error_pattern == p4);
p4 = ((p4 << 1) & 0xf) | ((p4 & 0x8) >> 3);
}
}
if (can_be_waived) {
for (std::unordered_set<db::EdgePair>::const_iterator ep = result.begin (); ep != result.end (); ++ep) {
if (edges_with_errors.find (ep->first ()) != edges_with_errors.end ()) {
waived.insert (*ep);
}
}
}
}
}
if (! waived.empty ()) {
for (std::unordered_set<db::EdgePair>::const_iterator i = waived.begin (); i != waived.end (); ++i) {
result.erase (*i);
}
}
}
}

View File

@ -34,38 +34,49 @@ namespace db
/**
* @brief Specifies an error filter on rectangular shapes
*
* There are actually more combinations possible. The bit pattern of the enum value consists
* of groups of 4 bits each specifying an allowed pattern. Rotation is implicit, so it's just
* required to give on incarnation.
*
* For example: 0x1953 would be one- or two-sided.
*/
enum RectFilter
{
/**
* @brief No filter
*/
NoSideAllowed,
NoSideAllowed = 0,
/**
* @brief Allow errors on one side
*/
OneSideAllowed,
OneSideAllowed = 0x1,
/**
* @brief Allow errors on two sides (not specified which)
*/
TwoSidesAllowed,
TwoSidesAllowed = 0x953,
/**
* @brief Allow errors on two sides ("L" configuration)
*/
TwoConnectedSidesAllowed,
TwoConnectedSidesAllowed = 0x3,
/**
* @brief Allow errors on two opposite sides
*/
TwoOppositeSidesAllowed,
TwoOppositeSidesAllowed = 0x5,
/**
* @brief Allow errors on three sides
*/
ThreeSidesAllowed
ThreeSidesAllowed = 0x7,
/**
* @brief Allow errors when on all sides
*/
FourSidesAllowed = 0xf
};
/**

View File

@ -2527,7 +2527,10 @@ gsi::EnumIn<db::Region, db::RectFilter> decl_Region_RectFilter ("db", "RectFilte
"@brief Allow errors on two opposite sides"
) +
gsi::enum_const ("ThreeSidesAllowed", db::RectFilter::ThreeSidesAllowed,
"@brief Allow errors on three sides"
"@brief Allow errors when on three sides"
) +
gsi::enum_const ("FourSidesAllowed", db::RectFilter::FourSidesAllowed,
"@brief Allow errors when on all sides"
),
"@brief This class represents the error filter mode on rectangles for \\Region#separation and related checks.\n"
"\n"

View File

@ -661,7 +661,6 @@ TEST(15h)
{
// opposite_filter with internal shielding
// shielding within opposite error detection
db::Region r2;
r2.insert (db::Box (db::Point (0, 0), db::Point (90, 100)));
r2.insert (db::Box (db::Point (0, 200), db::Point (90, 300)));
@ -689,6 +688,85 @@ TEST(15h)
"(200,100;200,0)/(210,0;210,100);(100,0;100,100)/(90,100;90,0)");
}
TEST(15i)
{
// rectangle error filter
db::Region r;
r.insert (db::Box (db::Point (-90, -90), db::Point (90, 90)));
db::Region rl;
rl.insert (db::Box (db::Point (-200, -100), db::Point (-100, 100)));
db::Region rr;
rr.insert (db::Box (db::Point (100, -100), db::Point (200, 100)));
db::Region rb;
rb.insert (db::Box (db::Point (-100, -200), db::Point (100, -100)));
db::Region rt;
rt.insert (db::Box (db::Point (-100, 100), db::Point (100, 200)));
db::RegionCheckOptions options;
options.metrics = db::Projection;
options.rect_filter = db::OneSideAllowed;
EXPECT_EQ (r.separation_check (rl + rr, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90);(90,90;90,-90)/(100,-90;100,90)");
EXPECT_EQ (r.separation_check (rl + rt, 40, options).to_string (), "(-90,90;90,90)/(90,100;-90,100);(-90,-90;-90,90)/(-100,90;-100,-90)");
EXPECT_EQ (r.separation_check (rl, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rt + rr + rb, 40, options).to_string (), "(90,-90;-90,-90)/(-90,-100;90,-100);(90,90;90,-90)/(100,-90;100,90);(-90,90;90,90)/(90,100;-90,100)");
options.rect_filter = db::TwoSidesAllowed;
EXPECT_EQ (r.separation_check (rl + rr, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rl + rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rl, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90)");
EXPECT_EQ (r.separation_check (rt, 40, options).to_string (), "(-90,90;90,90)/(90,100;-90,100)");
EXPECT_EQ (r.separation_check (rt + rr + rb, 40, options).to_string (), "(90,-90;-90,-90)/(-90,-100;90,-100);(90,90;90,-90)/(100,-90;100,90);(-90,90;90,90)/(90,100;-90,100)");
options.rect_filter = db::TwoOppositeSidesAllowed;
EXPECT_EQ (r.separation_check (rl + rr, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rl + rt, 40, options).to_string (), "(-90,90;90,90)/(90,100;-90,100);(-90,-90;-90,90)/(-100,90;-100,-90)");
EXPECT_EQ (r.separation_check (rl, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90)");
EXPECT_EQ (r.separation_check (rt, 40, options).to_string (), "(-90,90;90,90)/(90,100;-90,100)");
EXPECT_EQ (r.separation_check (rt + rr + rb, 40, options).to_string (), "(90,-90;-90,-90)/(-90,-100;90,-100);(90,90;90,-90)/(100,-90;100,90);(-90,90;90,90)/(90,100;-90,100)");
options.rect_filter = db::TwoConnectedSidesAllowed;
EXPECT_EQ (r.separation_check (rl + rr, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90);(90,90;90,-90)/(100,-90;100,90)");
EXPECT_EQ (r.separation_check (rl + rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rl, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90)");
EXPECT_EQ (r.separation_check (rt, 40, options).to_string (), "(-90,90;90,90)/(90,100;-90,100)");
EXPECT_EQ (r.separation_check (rt + rr + rb, 40, options).to_string (), "(90,-90;-90,-90)/(-90,-100;90,-100);(90,90;90,-90)/(100,-90;100,90);(-90,90;90,90)/(90,100;-90,100)");
options.rect_filter = db::ThreeSidesAllowed;
EXPECT_EQ (r.separation_check (rl + rr, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90);(90,90;90,-90)/(100,-90;100,90)");
EXPECT_EQ (r.separation_check (rl + rt, 40, options).to_string (), "(-90,90;90,90)/(90,100;-90,100);(-90,-90;-90,90)/(-100,90;-100,-90)");
EXPECT_EQ (r.separation_check (rl, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90)");
EXPECT_EQ (r.separation_check (rt, 40, options).to_string (), "(-90,90;90,90)/(90,100;-90,100)");
EXPECT_EQ (r.separation_check (rt + rr + rb, 40, options).to_string (), "");
options.rect_filter = db::RectFilter (0x9531); // one and two sides allowed
EXPECT_EQ (r.separation_check (rl + rr, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rl + rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rl, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rt + rr + rb, 40, options).to_string (), "(90,-90;-90,-90)/(-90,-100;90,-100);(90,90;90,-90)/(100,-90;100,90);(-90,90;90,90)/(90,100;-90,100)");
options.rect_filter = db::RectFilter (0x31); // one and two connected sides allowed
EXPECT_EQ (r.separation_check (rl + rr, 40, options).to_string (), "(-90,-90;-90,90)/(-100,90;-100,-90);(90,90;90,-90)/(100,-90;100,90)");
EXPECT_EQ (r.separation_check (rl + rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rr + rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rl, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rt, 40, options).to_string (), "");
EXPECT_EQ (r.separation_check (rt + rr + rb, 40, options).to_string (), "(90,-90;-90,-90)/(-90,-100;90,-100);(90,90;90,-90)/(100,-90;100,90);(-90,90;90,90)/(90,100;-90,100)");
}
TEST(16)
{
db::Region a;