mirror of https://github.com/KLayout/klayout.git
WIP: rectangle error pattern filter implemented.
This commit is contained in:
parent
6c4d1f4ef3
commit
153289b5d8
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue