WIP: support for properties in deep andnot, tests

This commit is contained in:
Matthias Koefferlein 2023-01-16 01:00:03 +01:00
parent fad85e4260
commit bf47805b29
13 changed files with 388 additions and 45 deletions

View File

@ -1641,7 +1641,7 @@ AsIfFlatRegion::andnot_with (const Region &other, PropertyConstraint property_co
}
RegionDelegate *
AsIfFlatRegion::xor_with (const Region &other) const
AsIfFlatRegion::xor_with (const Region &other, PropertyConstraint prop_constraint) const
{
if (empty () && ! other.strict_handling ()) {
@ -1654,10 +1654,12 @@ AsIfFlatRegion::xor_with (const Region &other) const
} else if (! bbox ().overlaps (other.bbox ()) && ! strict_handling () && ! other.strict_handling ()) {
// Simplified handling for disjunct case
return or_with (other);
return or_with (other, prop_constraint);
} else {
// @@@ TODO: implement property constraint
// Generic case
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
@ -1694,7 +1696,7 @@ AsIfFlatRegion::xor_with (const Region &other) const
}
RegionDelegate *
AsIfFlatRegion::or_with (const Region &other) const
AsIfFlatRegion::or_with (const Region &other, PropertyConstraint prop_constraint) const
{
if (empty () && ! other.strict_handling ()) {
@ -1712,6 +1714,8 @@ AsIfFlatRegion::or_with (const Region &other) const
} else {
// @@@ TODO: implement property constraint
// Generic case
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());

View File

@ -124,8 +124,8 @@ public:
virtual RegionDelegate *and_with (const Region &other, PropertyConstraint property_constraint) const;
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint property_constraint) const;
virtual RegionDelegate *xor_with (const Region &other) const;
virtual RegionDelegate *or_with (const Region &other) const;
virtual RegionDelegate *xor_with (const Region &other, PropertyConstraint prop_constraint) const;
virtual RegionDelegate *or_with (const Region &other, PropertyConstraint prop_constraint) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other, PropertyConstraint property_constraint) const;
virtual RegionDelegate *add_in_place (const Region &other)

View File

@ -743,8 +743,9 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain
}
RegionDelegate *
DeepRegion::or_with (const Region &other) const
DeepRegion::or_with (const Region &other, db::PropertyConstraint /*property_constraint*/) const
{
// @@@ TODO: implement property_constraint
RegionDelegate *res = add (other);
return res->merged_in_place ();
}
@ -815,35 +816,58 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyC
std::pair<DeepLayer, DeepLayer>
DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const
{
// @@@ TODO: implement property_constraint
DeepLayer dl_out1 (deep_layer ().derived ());
DeepLayer dl_out2 (deep_layer ().derived ());
db::TwoBoolAndNotLocalOperation op;
if (property_constraint == db::NoPropertyConstraint) {
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
db::TwoBoolAndNotLocalOperation op;
std::vector<unsigned int> il;
il.push_back (other->deep_layer ().layer ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
std::vector<unsigned int> ol;
ol.push_back (dl_out1.layer ());
ol.push_back (dl_out2.layer ());
std::vector<unsigned int> il;
il.push_back (other->deep_layer ().layer ());
proc.run (&op, deep_layer ().layer (), il, ol);
std::vector<unsigned int> ol;
ol.push_back (dl_out1.layer ());
ol.push_back (dl_out2.layer ());
proc.run (&op, deep_layer ().layer (), il, ol);
} else {
db::TwoBoolAndNotLocalOperationWithProperties op (&deep_layer ().layout (), &other->deep_layer ().layout (), property_constraint);
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
std::vector<unsigned int> il;
il.push_back (other->deep_layer ().layer ());
std::vector<unsigned int> ol;
ol.push_back (dl_out1.layer ());
ol.push_back (dl_out2.layer ());
proc.run (&op, deep_layer ().layer (), il, ol);
}
return std::make_pair (dl_out1, dl_out2);
}
RegionDelegate *
DeepRegion::xor_with (const Region &other) const
DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_constraint) const
{
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
@ -859,14 +883,14 @@ DeepRegion::xor_with (const Region &other) const
} else if (! other_deep) {
return AsIfFlatRegion::xor_with (other);
return AsIfFlatRegion::xor_with (other, property_constraint);
} else {
// Implement XOR as (A-B)+(B-A) - only this implementation
// is compatible with the local processor scheme
DeepLayer n1 (and_or_not_with (other_deep, false, db::NoPropertyConstraint));
DeepLayer n2 (other_deep->and_or_not_with (this, false, db::NoPropertyConstraint));
DeepLayer n1 (and_or_not_with (other_deep, false, property_constraint));
DeepLayer n2 (other_deep->and_or_not_with (this, false, property_constraint));
n1.add_from (n2);
return new DeepRegion (n1);

View File

@ -101,8 +101,8 @@ public:
virtual RegionDelegate *and_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *not_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *xor_with (const Region &other) const;
virtual RegionDelegate *or_with (const Region &other) const;
virtual RegionDelegate *xor_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *or_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *add_in_place (const Region &other);

View File

@ -67,19 +67,20 @@ EmptyRegion::add (const Region &other) const
}
RegionDelegate *
EmptyRegion::xor_with (const Region &other) const
EmptyRegion::xor_with (const Region &other, db::PropertyConstraint prop_constraint) const
{
return or_with (other);
return or_with (other, prop_constraint);
}
RegionDelegate *
EmptyRegion::or_with (const Region &other) const
EmptyRegion::or_with (const Region &other, db::PropertyConstraint /*prop_constraint*/) const
{
if (other.empty ()) {
return new EmptyRegion ();
} else if (! other.strict_handling ()) {
return other.delegate ()->clone ();
} else {
// @@@ TODO: implement prop_constraint
return other.delegate ()->merged ();
}
}

View File

@ -101,8 +101,8 @@ public:
virtual RegionDelegate *and_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }
virtual RegionDelegate *not_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &, db::PropertyConstraint) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *xor_with (const Region &other) const;
virtual RegionDelegate *or_with (const Region &other) const;
virtual RegionDelegate *xor_with (const Region &other, db::PropertyConstraint prop_constraint) const;
virtual RegionDelegate *or_with (const Region &other, db::PropertyConstraint prop_constraint) const;
virtual RegionDelegate *add_in_place (const Region &other);
virtual RegionDelegate *add (const Region &other) const;

View File

@ -171,7 +171,7 @@ BoolAndOrNotLocalOperation::do_compute_local (db::Layout *layout, const shape_in
}
if (! others.empty () || p1 > 0) {
if (! others.empty () && p1 > 0) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
@ -217,8 +217,6 @@ BoolAndOrNotLocalOperationWithProperties::do_compute_local (db::Layout *layout,
db::PropertyMapper pms (*layout, *mp_subject_layout);
db::PropertyMapper pmi (*layout, *mp_intruder_layout);
// @@@ TODO: implement different property constraint etc.
tl_assert (results.size () == 1);
std::unordered_set<db::PolygonRefWithProperties> &result = results.front ();
@ -356,7 +354,7 @@ TwoBoolAndNotLocalOperation::do_compute_local (db::Layout *layout, const shape_i
}
if (! others.empty () || p1 > 0) {
if (! others.empty () && p1 > 0) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
@ -391,6 +389,128 @@ std::string TwoBoolAndNotLocalOperation::description () const
return tl::to_string (tr ("ANDNOT operation"));
}
// ---------------------------------------------------------------------------------------------
// TwoBoolAndNotLocalOperationWithProperties implementation
TwoBoolAndNotLocalOperationWithProperties::TwoBoolAndNotLocalOperationWithProperties (const db::Layout *subject_layout, const db::Layout *intruder_layout, db::PropertyConstraint property_constraint)
: db::local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> (),
m_property_constraint (property_constraint), mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout)
{
// .. nothing yet ..
}
void
TwoBoolAndNotLocalOperationWithProperties::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::PolygonRefWithProperties> > &results, size_t max_vertex_count, double area_ratio) const
{
db::PropertyMapper pms (*layout, *mp_subject_layout);
db::PropertyMapper pmi (*layout, *mp_intruder_layout);
tl_assert (results.size () == 2);
std::unordered_set<db::PolygonRefWithProperties> &result0 = results [0];
std::unordered_set<db::PolygonRefWithProperties> &result1 = results [1];
db::EdgeProcessor ep;
std::map<db::properties_id_type, std::pair<tl::slist<db::PolygonRef>, std::set<db::PolygonRef> > > by_prop_id;
for (shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::PolygonRefWithProperties &subject = interactions.subject_shape (i->first);
if (i->second.empty ()) {
result1.insert (db::PolygonRefWithProperties (subject, pms (subject.properties_id ())));
} else {
db::properties_id_type prop_id_s = (m_property_constraint != db::NoPropertyConstraint ? pms (subject.properties_id ()) : 0);
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);
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
shapes_by_prop.second.insert (intruder);
}
}
}
}
for (auto p2s = by_prop_id.begin (); p2s != by_prop_id.end (); ++p2s) {
ep.clear ();
size_t p1 = 0, p2 = 1;
const std::set<db::PolygonRef> &others = p2s->second.second;
db::properties_id_type prop_id = p2s->first;
for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) {
const db::PolygonRef &subject = *s;
if (others.find (subject) != others.end ()) {
result0.insert (db::PolygonRefWithProperties (subject, prop_id));
} else if (others.empty ()) {
// shortcut (not: keep, and: drop)
result1.insert (db::PolygonRefWithProperties (subject, prop_id));
} else {
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p1);
}
p1 += 2;
}
}
if (! others.empty () && p1 > 0) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p2);
}
p2 += 2;
}
std::unordered_set<db::PolygonRef> result0_wo_props;
std::unordered_set<db::PolygonRef> result1_wo_props;
db::BooleanOp op0 (db::BooleanOp::And);
db::PolygonRefGenerator pr0 (layout, result0_wo_props);
db::PolygonSplitter splitter0 (pr0, area_ratio, max_vertex_count);
db::PolygonGenerator pg0 (splitter0, true, true);
db::BooleanOp op1 (db::BooleanOp::ANotB);
db::PolygonRefGenerator pr1 (layout, result1_wo_props);
db::PolygonSplitter splitter1 (pr1, area_ratio, max_vertex_count);
db::PolygonGenerator pg1 (splitter1, true, true);
ep.set_base_verbosity (50);
std::vector<std::pair<db::EdgeSink *, db::EdgeEvaluatorBase *> > procs;
procs.push_back (std::make_pair (&pg0, &op0));
procs.push_back (std::make_pair (&pg1, &op1));
ep.process (procs);
for (auto r = result0_wo_props.begin (); r != result0_wo_props.end (); ++r) {
result0.insert (db::PolygonRefWithProperties (*r, prop_id));
}
for (auto r = result1_wo_props.begin (); r != result1_wo_props.end (); ++r) {
result1.insert (db::PolygonRefWithProperties (*r, prop_id));
}
}
}
}
std::string TwoBoolAndNotLocalOperationWithProperties::description () const
{
return tl::to_string (tr ("ANDNOT operation"));
}
// ---------------------------------------------------------------------------------------------
SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wrap_count)

View File

@ -148,7 +148,7 @@ private:
};
/**
* @brief Implements a boolean AND or NOT operation
* @brief Implements a boolean AND or NOT operation with property handling
*/
class DB_PUBLIC BoolAndOrNotLocalOperationWithProperties
: public local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>
@ -182,6 +182,26 @@ public:
virtual std::string description () const;
};
/**
* @brief Implements a boolean AND plus NOT operation
*
* This processor delivers two outputs: the first one having the AND result, the second
* one having the NOT result.
*/
class DB_PUBLIC TwoBoolAndNotLocalOperationWithProperties
: public local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>
{
public:
TwoBoolAndNotLocalOperationWithProperties (const db::Layout *subject_layout, const db::Layout *intruder_layout, db::PropertyConstraint property_constraint);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::PolygonRefWithProperties> > &result, size_t max_vertex_count, double area_ratio) const;
virtual std::string description () const;
private:
db::PropertyConstraint m_property_constraint;
const db::Layout *mp_subject_layout, *mp_intruder_layout;
};
/**
* @brief Implements a merge operation with an overlap count
* With a given wrap_count, the result will only contains shapes where

View File

@ -1116,7 +1116,15 @@ public:
*/
Region operator^ (const Region &other) const
{
return Region (mp_delegate->xor_with (other));
return Region (mp_delegate->xor_with (other, db::NoPropertyConstraint));
}
/**
* @brief Boolean XOR operator with options
*/
Region bool_xor (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
{
return Region (mp_delegate->xor_with (other, prop_constraint));
}
/**
@ -1127,7 +1135,19 @@ public:
*/
Region &operator^= (const Region &other)
{
set_delegate (mp_delegate->xor_with (other));
set_delegate (mp_delegate->xor_with (other, db::NoPropertyConstraint));
return *this;
}
/**
* @brief In-place boolean XOR operator with options
*
* This method does not necessarily merge the region. To ensure the region
* is merged, call merge afterwards.
*/
Region &bool_xor_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
{
set_delegate (mp_delegate->xor_with (other, prop_constraint));
return *this;
}
@ -1138,7 +1158,17 @@ public:
*/
Region operator| (const Region &other) const
{
return Region (mp_delegate->or_with (other));
return Region (mp_delegate->or_with (other, db::NoPropertyConstraint));
}
/**
* @brief Boolean OR operator with options
*
* This method merges the polygons of both regions.
*/
Region bool_or (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
{
return Region (mp_delegate->or_with (other, prop_constraint));
}
/**
@ -1146,7 +1176,16 @@ public:
*/
Region &operator|= (const Region &other)
{
set_delegate (mp_delegate->or_with (other));
set_delegate (mp_delegate->or_with (other, db::NoPropertyConstraint));
return *this;
}
/**
* @brief In-place boolean OR operator
*/
Region &bool_or_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
{
set_delegate (mp_delegate->or_with (other, prop_constraint));
return *this;
}

View File

@ -275,8 +275,8 @@ public:
virtual RegionDelegate *and_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *xor_with (const Region &other) const = 0;
virtual RegionDelegate *or_with (const Region &other) const = 0;
virtual RegionDelegate *xor_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *or_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *add_in_place (const Region &other) = 0;
virtual RegionDelegate *add (const Region &other) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other, PropertyConstraint prop_constraint) const = 0;

View File

@ -1660,6 +1660,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"This method will compute the boolean NOT (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 NOT between self and the other region\n"
@ -1676,6 +1680,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"This method will compute the boolean NOT (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 XOR between self and the other region\n"
@ -1685,6 +1693,18 @@ 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"
@ -1693,6 +1713,18 @@ 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"
@ -1701,6 +1733,18 @@ 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"
@ -1709,6 +1753,18 @@ 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"

View File

@ -2126,6 +2126,84 @@ TEST(31_in_and_out)
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds");
}
TEST(40_BoolWithProperties)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_40.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
db::Region r1 (si1, dss);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
db::Region r2 (si2, dss);
db::RecursiveShapeIterator si3 (ly, top_cell, l3);
si3.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
db::Region r3 (si3, dss);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1.merged ());
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.merged ());
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r1 & r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r1.bool_and (r2, db::NoPropertyConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r1.bool_and (r2, db::SamePropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), r1.bool_and (r2, db::DifferentPropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r3.bool_and (r2, db::SamePropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), r3.bool_and (r2, db::DifferentPropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), r1.bool_and (r3, db::SamePropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (27, 0)), r1.bool_and (r3, db::DifferentPropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r1 - r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r1.bool_not (r2, db::NoPropertyConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), r1.bool_not (r2, db::SamePropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (33, 0)), r1.bool_not (r2, db::DifferentPropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (34, 0)), r3.bool_not (r2, db::SamePropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (35, 0)), r3.bool_not (r2, db::DifferentPropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (36, 0)), r1.bool_not (r3, db::SamePropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (37, 0)), r1.bool_not (r3, db::DifferentPropertiesConstraint));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r1.andnot (r2).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r1.andnot (r2).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (42, 0)), r1.andnot (r2, db::SamePropertiesConstraint).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (43, 0)), r1.andnot (r2, db::SamePropertiesConstraint).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (44, 0)), r1.andnot (r2, db::DifferentPropertiesConstraint).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (45, 0)), r1.andnot (r2, db::DifferentPropertiesConstraint).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (46, 0)), r3.andnot (r2, db::SamePropertiesConstraint).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (47, 0)), r3.andnot (r2, db::SamePropertiesConstraint).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (48, 0)), r3.andnot (r2, db::DifferentPropertiesConstraint).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (49, 0)), r3.andnot (r2, db::DifferentPropertiesConstraint).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (50, 0)), r1.andnot (r3, db::SamePropertiesConstraint).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (51, 0)), r1.andnot (r3, db::SamePropertiesConstraint).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (52, 0)), r1.andnot (r3, db::DifferentPropertiesConstraint).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (53, 0)), r1.andnot (r3, db::DifferentPropertiesConstraint).second);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au40.gds");
}
TEST(100_Integration)
{
db::Layout ly;

View File

@ -83,7 +83,8 @@ SOURCES = \
dbArrayTests.cc \
dbDeepTextsTests.cc \
dbNetShapeTests.cc \
dbHierNetsProcessorTests.cc
dbHierNetsProcessorTests.cc \
dbAsIfFlatRegionTests.cc
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC