WIP: fixed tests, dropped property constraint on XOR and OR (not implemented properly), added 'ignore' property constraint - in the 'no properties' case, properties are passed from the first input.

This commit is contained in:
Matthias Koefferlein 2023-01-16 16:27:31 +01:00
parent 3b4a460581
commit 58ab6ce9fd
6 changed files with 68 additions and 83 deletions

View File

@ -780,7 +780,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyC
{
DeepLayer dl_out (deep_layer ().derived ());
if (property_constraint == db::NoPropertyConstraint) {
if (property_constraint == db::IgnoreProperties) {
db::BoolAndOrNotLocalOperation op (and_op);
@ -819,7 +819,7 @@ DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint proper
DeepLayer dl_out1 (deep_layer ().derived ());
DeepLayer dl_out2 (deep_layer ().derived ());
if (property_constraint == db::NoPropertyConstraint) {
if (property_constraint == db::IgnoreProperties) {
db::TwoBoolAndNotLocalOperation op;

View File

@ -236,14 +236,14 @@ BoolAndOrNotLocalOperationWithProperties::do_compute_local (db::Layout *layout,
} else {
db::properties_id_type prop_id_s = (m_property_constraint != db::NoPropertyConstraint ? pms (subject.properties_id ()) : 0);
db::properties_id_type prop_id_s = pms (subject.properties_id ());
std::pair<tl::slist<db::PolygonRef>, std::set<db::PolygonRef> > &shapes_by_prop = by_prop_id [prop_id_s];
shapes_by_prop.first.push_front (subject);
for (shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
const db::PolygonRefWithProperties &intruder = interactions.intruder_shape (*j).second;
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? pmi (intruder.properties_id ()) : 0);
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? pmi (intruder.properties_id ()) : prop_id_s);
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
shapes_by_prop.second.insert (intruder);
}
@ -423,14 +423,14 @@ TwoBoolAndNotLocalOperationWithProperties::do_compute_local (db::Layout *layout,
} else {
db::properties_id_type prop_id_s = (m_property_constraint != db::NoPropertyConstraint ? pms (subject.properties_id ()) : 0);
db::properties_id_type prop_id_s = pms (subject.properties_id ());
std::pair<tl::slist<db::PolygonRef>, std::set<db::PolygonRef> > &shapes_by_prop = by_prop_id [prop_id_s];
shapes_by_prop.first.push_front (subject);
for (shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
const db::PolygonRefWithProperties &intruder = interactions.intruder_shape (*j).second;
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? pmi (intruder.properties_id ()) : 0);
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? pmi (intruder.properties_id ()) : prop_id_s);
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
shapes_by_prop.second.insert (intruder);
}

View File

@ -36,19 +36,32 @@ namespace db
enum PropertyConstraint
{
/**
* @brief No constraint, shapes are processed regardless of their properties
* @brief Ignore properties
*
* In this mode, properties are not considered and erased.
*/
NoPropertyConstraint = 0,
IgnoreProperties = 0,
/**
* @brief No constraint, shapes are processed regardless of their properties
*
* Properties are attached to the outputs where applicable.
*/
NoPropertyConstraint = 1,
/**
* @brief Shapes are processed if their properties are the same
*
* Properties are attached to the outputs where applicable.
*/
SamePropertiesConstraint = 1,
SamePropertiesConstraint = 2,
/**
* @brief Shapes are processed if their properties are different
*
* Properties are attached to the outputs where applicable.
*/
DifferentPropertiesConstraint = 2
DifferentPropertiesConstraint = 3
};
}

View File

@ -1036,13 +1036,13 @@ public:
*/
Region operator& (const Region &other) const
{
return Region (mp_delegate->and_with (other, db::NoPropertyConstraint));
return Region (mp_delegate->and_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean AND operator with options
*/
Region bool_and (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
Region bool_and (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->and_with (other, prop_constraint));
}
@ -1055,7 +1055,7 @@ public:
*/
Region &operator&= (const Region &other)
{
set_delegate (mp_delegate->and_with (other, db::NoPropertyConstraint));
set_delegate (mp_delegate->and_with (other, db::IgnoreProperties));
return *this;
}
@ -1065,7 +1065,7 @@ public:
* This method does not necessarily merge the region. To ensure the region
* is merged, call merge afterwards.
*/
Region &bool_and_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
Region &bool_and_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->and_with (other, prop_constraint));
return *this;
@ -1076,13 +1076,13 @@ public:
*/
Region operator- (const Region &other) const
{
return Region (mp_delegate->not_with (other, db::NoPropertyConstraint));
return Region (mp_delegate->not_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean NOT operator with options
*/
Region bool_not (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
Region bool_not (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->not_with (other, prop_constraint));
}
@ -1095,7 +1095,7 @@ public:
*/
Region &operator-= (const Region &other)
{
set_delegate (mp_delegate->not_with (other, db::NoPropertyConstraint));
set_delegate (mp_delegate->not_with (other, db::IgnoreProperties));
return *this;
}
@ -1105,7 +1105,7 @@ public:
* This method does not necessarily merge the region. To ensure the region
* is merged, call merge afterwards.
*/
Region bool_not_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
Region bool_not_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->not_with (other, prop_constraint));
return *this;
@ -1116,13 +1116,15 @@ public:
*/
Region operator^ (const Region &other) const
{
return Region (mp_delegate->xor_with (other, db::NoPropertyConstraint));
return Region (mp_delegate->xor_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean XOR operator with options
*
* TODO: property constraints are not implemented propertly yet.
*/
Region bool_xor (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
Region bool_xor (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->xor_with (other, prop_constraint));
}
@ -1135,7 +1137,7 @@ public:
*/
Region &operator^= (const Region &other)
{
set_delegate (mp_delegate->xor_with (other, db::NoPropertyConstraint));
set_delegate (mp_delegate->xor_with (other, db::IgnoreProperties));
return *this;
}
@ -1144,8 +1146,10 @@ public:
*
* This method does not necessarily merge the region. To ensure the region
* is merged, call merge afterwards.
*
* TODO: property constraints are not implemented propertly yet.
*/
Region &bool_xor_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
Region &bool_xor_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->xor_with (other, prop_constraint));
return *this;
@ -1158,15 +1162,17 @@ public:
*/
Region operator| (const Region &other) const
{
return Region (mp_delegate->or_with (other, db::NoPropertyConstraint));
return Region (mp_delegate->or_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean OR operator with options
*
* This method merges the polygons of both regions.
*
* TODO: property constraints are not implemented propertly yet.
*/
Region bool_or (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
Region bool_or (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->or_with (other, prop_constraint));
}
@ -1176,14 +1182,16 @@ public:
*/
Region &operator|= (const Region &other)
{
set_delegate (mp_delegate->or_with (other, db::NoPropertyConstraint));
set_delegate (mp_delegate->or_with (other, db::IgnoreProperties));
return *this;
}
/**
* @brief In-place boolean OR operator
* @brief In-place boolean OR operator with options
*
* TODO: property constraints are not implemented propertly yet.
*/
Region &bool_or_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
Region &bool_or_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->or_with (other, prop_constraint));
return *this;

View File

@ -1595,7 +1595,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) +
method_ext ("andnot", &andnot, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
method_ext ("andnot", &andnot, gsi::arg ("other"), gsi::arg ("property_constraint", db::IgnoreProperties),
"@brief Returns the boolean AND and NOT between self and the other region\n"
"\n"
"@return A two-element array of regions with the first one being the AND result and the second one being the NOT result\n"
@ -1613,7 +1613,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method will compute the boolean AND (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
) +
method ("and", &db::Region::bool_and, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
method ("and", &db::Region::bool_and, gsi::arg ("other"), gsi::arg ("property_constraint", db::IgnoreProperties),
"@brief Returns the boolean AND between self and the other region\n"
"\n"
"@return The result of the boolean AND operation\n"
@ -1633,7 +1633,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method will compute the boolean AND (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
) +
method ("and_with", &db::Region::bool_and_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
method ("and_with", &db::Region::bool_and_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::IgnoreProperties),
"@brief Performs the boolean AND between self and the other region\n"
"\n"
"@return The region after modification (self)\n"
@ -1653,7 +1653,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method will compute the boolean NOT (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
) +
method ("not", &db::Region::bool_not, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
method ("not", &db::Region::bool_not, gsi::arg ("other"), gsi::arg ("property_constraint", db::IgnoreProperties),
"@brief Returns the boolean NOT between self and the other region\n"
"\n"
"@return The result of the boolean NOT operation\n"
@ -1673,7 +1673,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method will compute the boolean NOT (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
) +
method ("not_with", &db::Region::bool_not_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
method ("not_with", &db::Region::bool_not_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::IgnoreProperties),
"@brief Performs the boolean NOT between self and the other region\n"
"\n"
"@return The region after modification (self)\n"
@ -1693,18 +1693,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method will compute the boolean XOR (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
) +
method ("xor", &db::Region::bool_xor, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
"@brief Returns the boolean XOR between self and the other region\n"
"\n"
"@return The result of the boolean XOR operation\n"
"\n"
"This method will compute the boolean XOR (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
"It allows specification of a property constaint - e.g. only performing the boolean operation between "
"shapes with the same user properties.\n"
"\n"
"This variant has been introduced in version 0.28.4."
) +
method ("^=", &db::Region::operator^=, gsi::arg ("other"),
"@brief Performs the boolean XOR between self and the other region\n"
"\n"
@ -1713,18 +1701,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method will compute the boolean XOR (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
) +
method ("xor_with", &db::Region::bool_xor_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
"@brief Performs the boolean XOR between self and the other region\n"
"\n"
"@return The region after modification (self)\n"
"\n"
"This method will compute the boolean XOR (intersection) between two regions. "
"The result is often but not necessarily always merged.\n"
"It allows specification of a property constaint - e.g. only performing the boolean operation between "
"shapes with the same user properties.\n"
"\n"
"This variant has been introduced in version 0.28.4."
) +
method ("\\|", &db::Region::operator|, gsi::arg ("other"),
"@brief Returns the boolean OR between self and the other region\n"
"\n"
@ -1733,18 +1709,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The boolean OR is implemented by merging the polygons of both regions. To simply join the regions "
"without merging, the + operator is more efficient."
) +
method ("or", &db::Region::bool_or, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
"@brief Returns the boolean OR between self and the other region\n"
"\n"
"@return The resulting region\n"
"\n"
"The boolean OR is implemented by merging the polygons of both regions. To simply join the regions "
"without merging, the + operator is more efficient."
"It allows specification of a property constaint - e.g. only performing the boolean operation between "
"shapes with the same user properties.\n"
"\n"
"This variant has been introduced in version 0.28.4."
) +
method ("\\|=", &db::Region::operator|=, gsi::arg ("other"),
"@brief Performs the boolean OR between self and the other region\n"
"\n"
@ -1753,18 +1717,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The boolean OR is implemented by merging the polygons of both regions. To simply join the regions "
"without merging, the + operator is more efficient."
) +
method ("or_with", &db::Region::bool_or_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
"@brief Performs the boolean OR between self and the other region\n"
"\n"
"@return The region after modification (self)\n"
"\n"
"The boolean OR is implemented by merging the polygons of both regions. To simply join the regions "
"without merging, the + operator is more efficient."
"It allows specification of a property constaint - e.g. only performing the boolean operation between "
"shapes with the same user properties.\n"
"\n"
"This variant has been introduced in version 0.28.4."
) +
method ("+", &db::Region::operator+, gsi::arg ("other"),
"@brief Returns the combined region of self and the other region\n"
"\n"
@ -3152,20 +3104,24 @@ gsi::ClassExt<db::Region> inject_Metrics_in_parent (decl_Region_Metrics.defs ())
gsi::ClassExt<db::Edges> inject_Metrics_in_Edges (decl_Region_Metrics.defs ());
gsi::EnumIn<db::Region, db::PropertyConstraint> decl_Region_PropertyConstraint ("db", "PropertyConstraint",
gsi::enum_const ("IgnoreProperties", db::IgnoreProperties,
"@brief Specifies to ignore properties\n"
"When using this constraint - for example on a boolean operation - properties are ignored and are not generated in the output."
) +
gsi::enum_const ("NoPropertyConstraint", db::NoPropertyConstraint,
"@brief Specifies not to apply any property constraint\n"
"When using this constraint - for example on a boolean operation - shapes are considered "
"regardless of their user properties."
"regardless of their user properties. Properties are generated on the output shapes where applicable."
) +
gsi::enum_const ("SamePropertiesConstraint", db::SamePropertiesConstraint,
"@brief Specifies to consider shapes only if their user properties are the same\n"
"When using this constraint - for example on a boolean operation - shapes are considered "
"only if their user properties are the same."
"only if their user properties are the same. Properties are generated on the output shapes where applicable."
) +
gsi::enum_const ("DifferentPropertiesConstraint", db::DifferentPropertiesConstraint,
"@brief Specifies to consider shapes only if their user properties are different\n"
"When using this constraint - for example on a boolean operation - shapes are considered "
"only if their user properties are different."
"only if their user properties are different. Properties are generated on the output shapes where applicable."
),
"@brief This class represents the property constraint for boolean and check functions.\n"
"\n"

View File

@ -137,9 +137,13 @@ TEST(2)
db::RecursiveShapeIterator iter1 (ly, ly.cell (top_cell_index), li1, db::Box (2000, -1000, 6000, 4000));
regions.push_back (std::make_pair (db::Region (iter1), tl));
// TODO: currently, original layer regions don't clip - emulate this
regions.back ().first &= db::Region (iter1.region ());
db::RecursiveShapeIterator iter2 (ly, ly.cell (top_cell_index), li1, db::Box (14000, 0, 20000, 3000));
regions.push_back (std::make_pair (db::Region (iter2), tl));
// TODO: currently, original layer regions don't clip - emulate this
regions.back ().first &= db::Region (iter2.region ());
}
@ -272,7 +276,11 @@ TEST(4_Add)
db::Region r42 (db::RecursiveShapeIterator (ly, top_cell, l42));
db::Region box (db::Box (2000, -1000, 6000, 4000));
db::Region r2box (db::RecursiveShapeIterator (ly, top_cell, l2, box));
// TODO: currently, original layer regions don't clip - emulate this
r2box &= db::Region (box);
db::Region r3box (db::RecursiveShapeIterator (ly, top_cell, l3, box));
// TODO: currently, original layer regions don't clip - emulate this
r3box &= db::Region (box);
// intra-layout