Merge pull request #1661 from KLayout/issue-1643

Issue 1643
This commit is contained in:
Matthias Köfferlein 2024-03-29 08:58:03 +01:00 committed by GitHub
commit 974756536f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 241 additions and 5 deletions

View File

@ -1052,6 +1052,10 @@ EdgesDelegate *DeepEdges::and_with (const Edges &other) const
return AsIfFlatEdges::and_with (other);
} else if (deep_layer () == other_deep->deep_layer ()) {
return clone ();
} else {
return new DeepEdges (and_or_not_with (other_deep, EdgeAnd).first);
@ -1071,6 +1075,10 @@ EdgesDelegate *DeepEdges::not_with (const Edges &other) const
return AsIfFlatEdges::not_with (other);
} else if (deep_layer () == other_deep->deep_layer ()) {
return new DeepEdges (deep_layer ().derived ());
} else {
return new DeepEdges (and_or_not_with (other_deep, EdgeNot).first);
@ -1164,6 +1172,10 @@ DeepEdges::andnot_with (const Edges &other) const
return AsIfFlatEdges::andnot_with (other);
} else if (deep_layer () == other_deep->deep_layer ()) {
return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ()));
} else {
auto res = and_or_not_with (other_deep, EdgeAndNot);
@ -1188,6 +1200,10 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const
return AsIfFlatEdges::xor_with (other);
} else if (deep_layer () == other_deep->deep_layer ()) {
return new DeepEdges (deep_layer ().derived ());
} else {
// Implement XOR as (A-B)+(B-A) - only this implementation
@ -1203,6 +1219,11 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const
EdgesDelegate *DeepEdges::or_with (const Edges &other) const
{
const DeepEdges *other_deep = dynamic_cast <const DeepEdges *> (other.delegate ());
if (other_deep && other_deep->deep_layer () == deep_layer ()) {
return clone ();
}
// NOTE: in the hierarchical case we don't do a merge on "or": just map to add
return add (other);
}
@ -1503,8 +1524,19 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer () && !counting) {
if ((mode == EdgesOutside) == inverse) {
return clone ();
} else {
return new DeepEdges (deep_layer ().derived ());
}
}
const db::DeepLayer &edges = merged_deep_layer ();
// NOTE: with counting the other region needs to be merged
const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ());
DeepLayer dl_out (edges.derived ());
db::Edge2EdgeInteractingLocalOperation op (mode, inverse ? db::Edge2EdgeInteractingLocalOperation::Inverse : db::Edge2EdgeInteractingLocalOperation::Normal, min_count, max_count);
@ -1513,8 +1545,13 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
// NOTE: with counting the other region needs to be merged
proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ());
if (edges == other_edges) {
// with counting and two identical inputs, a copy needs to be made
db::DeepLayer copy (other_edges.copy ());
proc.run (&op, edges.layer (), copy.layer (), dl_out.layer ());
} else {
proc.run (&op, edges.layer (), other_edges.layer (), dl_out.layer ());
}
return new db::DeepEdges (dl_out);
}
@ -1533,8 +1570,19 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer () && !counting) {
if (mode != EdgesOutside) {
return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ()));
} else {
return std::make_pair (new DeepEdges (deep_layer ().derived ()), clone ());
}
}
const db::DeepLayer &edges = merged_deep_layer ();
// NOTE: with counting the other region needs to be merged
const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ());
DeepLayer dl_out (edges.derived ());
DeepLayer dl_out2 (edges.derived ());
@ -1550,7 +1598,13 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio
proc.set_threads (edges.store ()->threads ());
// NOTE: with counting the other region needs to be merged
proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers);
if (edges == other_edges) {
// with counting and two identical inputs, a copy needs to be made
db::DeepLayer copy (other_edges.copy ());
proc.run (&op, edges.layer (), copy.layer (), output_layers);
} else {
proc.run (&op, edges.layer (), other_edges.layer (), output_layers);
}
return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2));
}
@ -1591,6 +1645,10 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer ()) {
return clone ();
}
const db::DeepLayer &edges = deep_layer ();
const db::DeepLayer &other_edges = other_deep->merged_deep_layer ();
@ -1617,6 +1675,10 @@ EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer ()) {
return invert ? new db::DeepEdges (deep_layer ().derived ()) : clone ();
}
const db::DeepLayer &edges = merged_deep_layer ();
DeepLayer dl_out (edges.derived ());
@ -1646,6 +1708,10 @@ std::pair<EdgesDelegate *, EdgesDelegate *> DeepEdges::in_and_out (const Edges &
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer ()) {
return std::make_pair (clone (), new db::DeepEdges (deep_layer ().derived ()));
}
const db::DeepLayer &edges = merged_deep_layer ();
DeepLayer dl_out (edges.derived ());

View File

@ -797,6 +797,10 @@ DeepRegion::and_with (const Region &other, PropertyConstraint property_constrain
return AsIfFlatRegion::and_with (other, property_constraint);
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
return clone ();
} else {
return new DeepRegion (and_or_not_with (other_deep, true, property_constraint));
@ -817,6 +821,10 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain
return AsIfFlatRegion::not_with (other, property_constraint);
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
return new DeepRegion (deep_layer ().derived ());
} else {
return new DeepRegion (and_or_not_with (other_deep, false, property_constraint));
@ -825,8 +833,13 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain
}
RegionDelegate *
DeepRegion::or_with (const Region &other, db::PropertyConstraint /*property_constraint*/) const
DeepRegion::or_with (const Region &other, db::PropertyConstraint property_constraint) const
{
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (other_deep && other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
return clone ();
}
// TODO: implement property_constraint
RegionDelegate *res = add (other);
return res->merged_in_place ();
@ -849,6 +862,10 @@ DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constr
return AsIfFlatRegion::andnot_with (other, property_constraint);
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
} else {
std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep, property_constraint);
@ -962,6 +979,10 @@ DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_const
return AsIfFlatRegion::xor_with (other, property_constraint);
} else if (other_deep->deep_layer () == deep_layer () && pc_skip (property_constraint)) {
return new DeepRegion (deep_layer ().derived ());
} else {
// Implement XOR as (A-B)+(B-A) - only this implementation
@ -2127,6 +2148,16 @@ DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode outpu
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
} else if (output_mode == Negative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
}
const db::DeepLayer &polygons = merged_deep_layer ();
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
@ -2188,6 +2219,26 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer () && !counting) {
if (mode <= 0 /*inside or interacting*/) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
} else if (output_mode == Negative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
} else {
if (output_mode == PositiveAndNegative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ());
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
}
}
}
const db::DeepLayer &polygons = merged_deep_layer ();
// NOTE: with counting, the other polygons must be merged
const db::DeepLayer &other_polygons = counting ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
@ -2205,7 +2256,13 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
if (polygons == other_polygons) {
// with counting and two identical inputs we need to create a layer copy
db::DeepLayer other_copy (other_polygons.copy ());
proc.run (&op, polygons.layer (), other_copy.layer (), orh.layers ());
} else {
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
}
return orh.result_pair ();
}
@ -2285,6 +2342,10 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
other_deep = dr_holder.get ();
}
if (deep_layer () == other_deep->deep_layer ()) {
return clone ();
}
// in "inside" mode, the first argument needs to be merged too
const db::DeepLayer &polygons = mode < 0 ? merged_deep_layer () : deep_layer ();
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();

View File

@ -1505,6 +1505,55 @@ TEST(22_InteractingWithCount)
EXPECT_EQ (db::compare (e.selected_interacting_differential (r2, size_t (2), size_t(3)).second, "(0,0;200,0)"), true);
}
TEST(23_SameInputs)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l1.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 l2 = ly.get_layer (db::LayerProperties (2, 0));
db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ());
EXPECT_EQ ((e2 & e2).to_string (), e2.to_string ());
EXPECT_EQ ((e2 - e2).to_string (), "");
EXPECT_EQ (e2.andnot (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.andnot (e2).second.to_string (), "");
EXPECT_EQ ((e2 | e2).to_string (), e2.to_string ());
EXPECT_EQ ((e2 ^ e2).to_string (), "");
EXPECT_EQ (e2.in (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.in (e2, true).to_string (), "");
EXPECT_EQ (e2.in_and_out (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.in_and_out (e2).second.to_string (), "");
EXPECT_EQ (e2.selected_interacting (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_not_interacting (e2).to_string (), "");
EXPECT_EQ (e2.selected_interacting_differential (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_interacting_differential (e2).second.to_string (), "");
EXPECT_EQ ((e2.selected_interacting (e2, (size_t) 1, (size_t) 3) ^ e2).to_string (), "");
EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).first ^ e2).to_string (), "");
EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).second.to_string (), "");
EXPECT_EQ (e2.selected_interacting (e2, (size_t) 4).to_string (), "");
EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 4).first.to_string (), "");
EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 4).second ^ e2).to_string (), "");
EXPECT_EQ (e2.selected_inside (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_not_inside (e2).to_string (), "");
EXPECT_EQ (e2.selected_inside_differential (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_inside_differential (e2).second.to_string (), "");
EXPECT_EQ (e2.selected_outside (e2).to_string (), "");
EXPECT_EQ (e2.selected_not_outside (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_outside_differential (e2).first.to_string (), "");
EXPECT_EQ (e2.selected_outside_differential (e2).second.to_string (), e2.to_string ());
EXPECT_EQ (e2.pull_interacting (e2).to_string (), e2.to_string ());
}
TEST(deep_edges_and_cheats)
{

View File

@ -2649,6 +2649,66 @@ TEST(101_DeepFlatCollaboration)
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au101.gds");
}
TEST(102_SameInputs)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l1.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 l2 = ly.get_layer (db::LayerProperties (2, 0));
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
EXPECT_EQ ((r2 & r2).to_string (), r2.to_string ());
EXPECT_EQ ((r2 - r2).to_string (), "");
EXPECT_EQ (r2.andnot (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.andnot (r2).second.to_string (), "");
EXPECT_EQ ((r2 | r2).to_string (), r2.to_string ());
EXPECT_EQ ((r2 ^ r2).to_string (), "");
EXPECT_EQ (r2.in (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.in (r2, true).to_string (), "");
EXPECT_EQ (r2.in_and_out (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.in_and_out (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_enclosing (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_enclosing (r2).to_string (), "");
EXPECT_EQ (r2.selected_enclosing_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_enclosing_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_interacting (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_interacting (r2).to_string (), "");
EXPECT_EQ (r2.selected_interacting_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_interacting_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_interacting (r2, (size_t) 1, (size_t) 2).to_string (), r2.merged ().to_string ());
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).first.to_string (), r2.merged ().to_string ());
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).second.to_string (), "");
EXPECT_EQ (r2.selected_interacting (r2, (size_t) 2).to_string (), "");
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).first.to_string (), "");
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).second.to_string (), r2.merged ().to_string ());
EXPECT_EQ (r2.selected_inside (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_inside (r2).to_string (), "");
EXPECT_EQ (r2.selected_inside_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_inside_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_outside (r2).to_string (), "");
EXPECT_EQ (r2.selected_not_outside (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_outside_differential (r2).first.to_string (), "");
EXPECT_EQ (r2.selected_outside_differential (r2).second.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_overlapping (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_overlapping (r2).to_string (), "");
EXPECT_EQ (r2.selected_overlapping_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_overlapping_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.pull_inside (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.pull_overlapping (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.pull_interacting (r2).to_string (), r2.to_string ());
}
TEST(issue_277)
{
db::Layout ly;