mirror of https://github.com/KLayout/klayout.git
WIP: support for properties in deep andnot, tests
This commit is contained in:
parent
fad85e4260
commit
bf47805b29
|
|
@ -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 ());
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue