mirror of https://github.com/KLayout/klayout.git
Added tests for Region's andnot.
This commit is contained in:
parent
966c351958
commit
d141c0895d
|
|
@ -1115,6 +1115,71 @@ AsIfFlatRegion::not_with (const Region &other) const
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
AsIfFlatRegion::andnot_with (const Region &other) const
|
||||
{
|
||||
if (empty ()) {
|
||||
|
||||
// Nothing to do
|
||||
return std::make_pair (new EmptyRegion (), new EmptyRegion ());
|
||||
|
||||
} else if (other.empty () && ! strict_handling ()) {
|
||||
|
||||
// Nothing to do
|
||||
return std::make_pair (new EmptyRegion (), clone ());
|
||||
|
||||
} else if (! bbox ().overlaps (other.bbox ()) && ! strict_handling ()) {
|
||||
|
||||
// Nothing to do
|
||||
return std::make_pair (new EmptyRegion (), clone ());
|
||||
|
||||
} else {
|
||||
|
||||
// Generic case
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// count edges and reserve memory
|
||||
size_t n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
n += p->vertices ();
|
||||
}
|
||||
for (RegionIterator p (other.begin ()); ! p.at_end (); ++p) {
|
||||
n += p->vertices ();
|
||||
}
|
||||
ep.reserve (n);
|
||||
|
||||
// insert the polygons into the processor
|
||||
n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p, n += 2) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
n = 1;
|
||||
for (RegionIterator p (other.begin ()); ! p.at_end (); ++p, n += 2) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatRegion> new_region1 (new FlatRegion (true));
|
||||
db::BooleanOp op1 (db::BooleanOp::And);
|
||||
db::ShapeGenerator pc1 (new_region1->raw_polygons (), true /*clear*/);
|
||||
db::PolygonGenerator pg1 (pc1, false /*don't resolve holes*/, min_coherence ());
|
||||
|
||||
std::auto_ptr<FlatRegion> new_region2 (new FlatRegion (true));
|
||||
db::BooleanOp op2 (db::BooleanOp::ANotB);
|
||||
db::ShapeGenerator pc2 (new_region2->raw_polygons (), true /*clear*/);
|
||||
db::PolygonGenerator pg2 (pc2, false /*don't resolve holes*/, min_coherence ());
|
||||
|
||||
std::vector<std::pair<db::EdgeSink *, db::EdgeEvaluatorBase *> > procs;
|
||||
procs.push_back (std::make_pair (&pg1, &op1));
|
||||
procs.push_back (std::make_pair (&pg2, &op2));
|
||||
ep.process (procs);
|
||||
|
||||
return std::make_pair (new_region1.release (), new_region2.release ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::xor_with (const Region &other) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ public:
|
|||
virtual RegionDelegate *not_with (const Region &other) const;
|
||||
virtual RegionDelegate *xor_with (const Region &other) const;
|
||||
virtual RegionDelegate *or_with (const Region &other) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const;
|
||||
|
||||
virtual RegionDelegate *add_in_place (const Region &other)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -542,6 +542,31 @@ DeepRegion::not_with (const Region &other) const
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
DeepRegion::andnot_with (const Region &other) const
|
||||
{
|
||||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
|
||||
if (empty ()) {
|
||||
|
||||
return std::make_pair (clone (), clone ());
|
||||
|
||||
} else if (other.empty ()) {
|
||||
|
||||
return std::make_pair (other.delegate ()->clone (), clone ());
|
||||
|
||||
} else if (! other_deep) {
|
||||
|
||||
return AsIfFlatRegion::andnot_with (other);
|
||||
|
||||
} else {
|
||||
|
||||
std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep);
|
||||
return std::make_pair (new DeepRegion (res.first), new DeepRegion (res.second));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DeepLayer
|
||||
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
||||
{
|
||||
|
|
@ -560,6 +585,32 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
|||
return dl_out;
|
||||
}
|
||||
|
||||
std::pair<DeepLayer, DeepLayer>
|
||||
DeepRegion::and_and_not_with (const DeepRegion *other) const
|
||||
{
|
||||
DeepLayer dl_out1 (deep_layer ().derived ());
|
||||
DeepLayer dl_out2 (deep_layer ().derived ());
|
||||
|
||||
db::TwoBoolAndNotLocalOperation op;
|
||||
|
||||
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_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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ public:
|
|||
virtual RegionDelegate *and_with (const Region &other) const;
|
||||
virtual RegionDelegate *not_with (const Region &other) const;
|
||||
virtual RegionDelegate *xor_with (const Region &other) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const;
|
||||
|
||||
virtual RegionDelegate *add_in_place (const Region &other);
|
||||
virtual RegionDelegate *add (const Region &other) const;
|
||||
|
|
@ -184,6 +185,7 @@ private:
|
|||
void ensure_merged_polygons_valid () const;
|
||||
const DeepLayer &merged_deep_layer () const;
|
||||
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const;
|
||||
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other) const;
|
||||
EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ public:
|
|||
|
||||
virtual RegionDelegate *and_with (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *not_with (const Region &) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) 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 *add_in_place (const Region &other);
|
||||
|
|
|
|||
|
|
@ -1145,6 +1145,17 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Two-bool ANDNOT operation
|
||||
*
|
||||
* The first region delivered will be the AND result, the second one the NOT result.
|
||||
*/
|
||||
std::pair<Region, Region> andnot (const Region &other) const
|
||||
{
|
||||
std::pair<RegionDelegate *, RegionDelegate *> res = mp_delegate->andnot_with (other);
|
||||
return std::make_pair (Region (res.first), Region (res.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of this region which are completly outside polygons from the other region
|
||||
*
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ public:
|
|||
virtual RegionDelegate *or_with (const Region &other) 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) const = 0;
|
||||
|
||||
virtual RegionDelegate *selected_outside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_outside (const Region &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -548,6 +548,17 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other,
|
|||
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> ());
|
||||
}
|
||||
|
||||
static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other)
|
||||
{
|
||||
std::pair<db::Region, db::Region> rp = r->andnot (other);
|
||||
|
||||
std::vector<db::Region> res;
|
||||
res.resize (2, db::Region ());
|
||||
res [0] = rp.first;
|
||||
res [1] = rp.second;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int euclidian_metrics ()
|
||||
{
|
||||
return db::Euclidian;
|
||||
|
|
@ -1311,6 +1322,16 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("andnot", &andnot, gsi::arg ("other"),
|
||||
"@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"
|
||||
"\n"
|
||||
"This method will compute the boolean AND and NOT between two regions simultaneously. "
|
||||
"Because this requires a single sweep only, using this method is faster than doing AND and NOT separately.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.\n"
|
||||
) +
|
||||
method ("&", &db::Region::operator&, gsi::arg ("other"),
|
||||
"@brief Returns the boolean AND between self and the other region\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -172,6 +172,13 @@ TEST(3_BoolAndNot)
|
|||
db::Region r42minus3 = r42 - r3;
|
||||
db::Region r42minus42 = r42 - r42;
|
||||
|
||||
db::Region tr2minus3 = r2.andnot (r3).second;
|
||||
db::Region tr2minusbox = r2.andnot (box).second;
|
||||
db::Region tr2minus42 = r2.andnot (r42).second;
|
||||
db::Region trboxminus3 = box.andnot (r3).second;
|
||||
db::Region tr42minus3 = r42.andnot (r3).second;
|
||||
db::Region tr42minus42 = r42.andnot (r42).second;
|
||||
|
||||
db::Region r2and3 = r2 & r3;
|
||||
db::Region r2andbox = r2 & box;
|
||||
db::Region r2and42 = r2 & r42;
|
||||
|
|
@ -179,27 +186,58 @@ TEST(3_BoolAndNot)
|
|||
db::Region r42and3 = r42 & r3;
|
||||
db::Region r42and42 = r42 & r42;
|
||||
|
||||
db::Region tr2and3 = r2.andnot (r3).first;
|
||||
db::Region tr2andbox = r2.andnot (box).first;
|
||||
db::Region tr2and42 = r2.andnot (r42).first;
|
||||
db::Region trboxand3 = box.andnot (r3).first;
|
||||
db::Region tr42and3 = r42.andnot (r3).first;
|
||||
db::Region tr42and42 = r42.andnot (r42).first;
|
||||
|
||||
EXPECT_EQ (r2and3.is_merged (), false);
|
||||
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
{
|
||||
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 (10, 0)), r2minus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2minusbox);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2minus42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), rboxminus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r42minus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r42minus42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2minus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2minusbox);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2minus42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), rboxminus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r42minus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r42minus42);
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2and3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2andbox);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r2and42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), rboxand3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r42and3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), r42and42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2and3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2andbox);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r2and42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), rboxand3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r42and3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), r42and42);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au3.gds");
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au3.gds");
|
||||
}
|
||||
|
||||
{
|
||||
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 (10, 0)), tr2minus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), tr2minusbox);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), tr2minus42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), trboxminus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), tr42minus3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), tr42minus42);
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), tr2and3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), tr2andbox);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), tr2and42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), trboxand3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), tr42and3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), tr42and42);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au3b.gds");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(4_Add)
|
||||
|
|
|
|||
|
|
@ -202,6 +202,13 @@ TEST(3)
|
|||
EXPECT_EQ ((db::Region () & r).to_string (), "");
|
||||
EXPECT_EQ ((db::Region () & r).empty (), true);
|
||||
|
||||
EXPECT_EQ (r.andnot(rr).first.to_string (), "(10,20;10,220;110,220;110,20)");
|
||||
EXPECT_EQ (rr.andnot(r).first.to_string (), "(10,20;10,220;110,220;110,20)");
|
||||
EXPECT_EQ (r.andnot(db::Region ()).first.to_string (), "");
|
||||
EXPECT_EQ (r.andnot(db::Region ()).first.empty (), true);
|
||||
EXPECT_EQ (db::Region ().andnot(r).first.to_string (), "");
|
||||
EXPECT_EQ (db::Region ().andnot(r).first.empty (), true);
|
||||
|
||||
r &= rr;
|
||||
EXPECT_EQ (r.is_box (), true);
|
||||
EXPECT_EQ (r.empty (), false);
|
||||
|
|
@ -289,6 +296,14 @@ TEST(7)
|
|||
EXPECT_EQ ((db::Region () - r).empty (), true);
|
||||
EXPECT_EQ ((db::Region () - r).is_merged (), true);
|
||||
|
||||
EXPECT_EQ (r.andnot(db::Region (db::Box (db::Point (10, 20), db::Point (110, 220)))).second.to_string (), "(-100,-100;-100,400;200,400;200,-100/10,20;110,20;110,220;10,220)");
|
||||
EXPECT_EQ (r.andnot(db::Region ()).second.to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,400;200,400;200,-100)");
|
||||
EXPECT_EQ (r.andnot(db::Region ()).second.empty (), false);
|
||||
EXPECT_EQ (r.andnot(db::Region ()).second.is_merged (), false);
|
||||
EXPECT_EQ (db::Region ().andnot(r).second.to_string (), "");
|
||||
EXPECT_EQ (db::Region ().andnot(r).second.empty (), true);
|
||||
EXPECT_EQ (db::Region ().andnot(r).second.is_merged (), true);
|
||||
|
||||
r -= db::Region (db::Box (db::Point (10, 20), db::Point (110, 220)));
|
||||
EXPECT_EQ (r.is_box (), false);
|
||||
EXPECT_EQ (r.empty (), false);
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue