WIP: introducing Region#in_and_out and Edges#in_and_out, support for hierachical Edges#in, Tests updated

This commit is contained in:
Matthias Koefferlein 2022-11-27 14:53:30 +01:00
parent 25e61205d2
commit 0304930136
19 changed files with 247 additions and 35 deletions

View File

@ -530,6 +530,28 @@ AsIfFlatEdges::in (const Edges &other, bool invert) const
return new_region.release ();
}
std::pair<EdgesDelegate *, EdgesDelegate *>
AsIfFlatEdges::in_and_out (const Edges &other) const
{
std::set <db::Edge> op;
for (EdgesIterator o (other.begin_merged ()); ! o.at_end (); ++o) {
op.insert (*o);
}
std::unique_ptr<FlatEdges> in (new FlatEdges (false));
std::unique_ptr<FlatEdges> out (new FlatEdges (false));
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
if (op.find (*o) != op.end ()) {
in->insert (*o);
} else {
out->insert (*o);
}
}
return std::make_pair (in.release (), out.release ());
}
size_t
AsIfFlatEdges::count () const
{

View File

@ -204,6 +204,7 @@ public:
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_inside_pair (const Region &other) const;
virtual EdgesDelegate *in (const Edges &, bool) const;
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const;
virtual bool equals (const Edges &other) const;
virtual bool less (const Edges &other) const;

View File

@ -148,25 +148,6 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter) const
return result.release ();
}
RegionDelegate *
AsIfFlatRegion::in (const Region &other, bool invert) const
{
std::set <db::Polygon> op;
for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) {
op.insert (*o);
}
std::unique_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) {
if ((op.find (*o) == op.end ()) == invert) {
new_region->insert (*o);
}
}
return new_region.release ();
}
bool
AsIfFlatRegion::is_box () const
{
@ -400,6 +381,56 @@ private:
}
std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const
{
OutputPairHolder oph (output_mode, merged_semantics ());
if (output_mode == None) {
return oph.region_pair ();
}
// shortcut
if (empty ()) {
if (output_mode == Positive || output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), clone ());
}
} else if (other.empty ()) {
if (output_mode == Positive) {
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new EmptyRegion (), clone ());
}
}
std::set <db::Polygon> op;
for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) {
op.insert (*o);
}
std::unique_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) {
if (op.find (*o) != op.end ()) {
if (output_mode == Positive || output_mode == PositiveAndNegative) {
oph.results () [0]->insert (*o);
}
} else {
if (output_mode == Negative) {
oph.results () [0]->insert (*o);
} else if (output_mode == PositiveAndNegative) {
oph.results () [1]->insert (*o);
}
}
}
return oph.region_pair ();
}
std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{

View File

@ -265,7 +265,15 @@ public:
return pull_generic (other, 0, false);
}
virtual RegionDelegate *in (const Region &other, bool invert) const;
virtual RegionDelegate *in (const Region &other, bool invert) const
{
return in_and_out_generic (other, invert ? Negative : Positive).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &other) const
{
return in_and_out_generic (other, PositiveAndNegative);
}
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
@ -284,6 +292,7 @@ protected:
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
virtual TextsDelegate *pull_generic (const Texts &other) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const;
template <class Trans>
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);

View File

@ -34,6 +34,7 @@
#include "dbLayoutUtils.h"
#include "dbLocalOperation.h"
#include "dbLocalOperationUtils.h"
#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation
#include "dbHierProcessor.h"
#include "dbEmptyEdges.h"
@ -1741,8 +1742,62 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const
EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
{
// TODO: is there a cheaper way?
return AsIfFlatEdges::in (other, invert);
std::unique_ptr<db::DeepEdges> dr_holder;
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
if (! other_deep) {
// if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchization
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
other_deep = dr_holder.get ();
}
const db::DeepLayer &edges = merged_deep_layer ();
DeepLayer dl_out (edges.derived ());
std::vector<unsigned int> output_layers;
output_layers.reserve (1);
output_layers.push_back (dl_out.layer ());
db::ContainedEdgesLocalOperation op (invert ? Negative : Positive);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers);
return new db::DeepEdges (dl_out);
}
std::pair<EdgesDelegate *, EdgesDelegate *> DeepEdges::in_and_out (const Edges &other) const
{
std::unique_ptr<db::DeepEdges> dr_holder;
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
if (! other_deep) {
// if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchization
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
other_deep = dr_holder.get ();
}
const db::DeepLayer &edges = merged_deep_layer ();
DeepLayer dl_out (edges.derived ());
DeepLayer dl_out2 (edges.derived ());
std::vector<unsigned int> output_layers;
output_layers.reserve (2);
output_layers.push_back (dl_out.layer ());
output_layers.push_back (dl_out2.layer ());
db::ContainedEdgesLocalOperation op (PositiveAndNegative);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers);
return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2));
}
namespace

View File

@ -156,6 +156,7 @@ public:
virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const;
virtual EdgesDelegate *in (const Edges &, bool) const;
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;

View File

@ -1789,16 +1789,8 @@ private:
}
RegionDelegate *
DeepRegion::in (const Region &other, bool invert) const
{
// TODO: we could offer in_and_not_it (both at once)
InteractingOutputMode output_mode = invert ? Negative : Positive;
return in_and_out (other, output_mode).first;
}
std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::in_and_out (const Region &other, InteractingOutputMode output_mode) const
DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const
{
std::unique_ptr<db::DeepRegion> dr_holder;
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());

View File

@ -133,8 +133,6 @@ public:
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
virtual RegionDelegate *in (const Region &other, bool invert) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual DeepShapeCollectionDelegateBase *deep ()
@ -155,10 +153,10 @@ protected:
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &other, InteractingOutputMode output_mode) const;
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
virtual TextsDelegate *pull_generic (const Texts &other) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const;
private:
friend class DeepEdges;

View File

@ -1390,6 +1390,19 @@ public:
return Edges (mp_delegate->in (other, invert));
}
/**
* @brief Returns all edges which are in the other edge set and which are not.
*
* This method is equivalent to calling in with invert = false and true, but more efficient.
*
* Merged semantics applies.
*/
std::pair<Edges, Edges> in_and_out (const Edges &other) const
{
std::pair<db::EdgesDelegate *, db::EdgesDelegate *> p = mp_delegate->in_and_out (other);
return std::pair<Edges, Edges> (Edges (p.first), Edges (p.second));
}
/**
* @brief Returns the nth edge
*

View File

@ -333,6 +333,7 @@ public:
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_inside_pair (const Edges &other) const = 0;
virtual EdgesDelegate *in (const Edges &other, bool invert) const = 0;
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const = 0;
virtual const db::Edge *nth (size_t n) const = 0;
virtual bool has_valid_edges () const = 0;

View File

@ -115,6 +115,7 @@ public:
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_inside_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); }
virtual EdgesDelegate *in (const Edges &, bool) const { return new EmptyEdges (); }
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); }
virtual const db::Edge *nth (size_t) const { tl_assert (false); }
virtual bool has_valid_edges () const { return true; }

View File

@ -133,6 +133,7 @@ public:
virtual TextsDelegate *pull_interacting (const Texts &) const { return new EmptyTexts (); }
virtual RegionDelegate *pull_overlapping (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual bool has_valid_polygons () const { return true; }
virtual bool has_valid_merged_polygons () const { return true; }

View File

@ -1602,6 +1602,19 @@ public:
return Region (mp_delegate->in (other, invert));
}
/**
* @brief Returns all polygons which are in the other region plus the ones which are not
*
* This method is similar to calling in with inverse = false and true, but more efficient.
*
* Merged semantics applies.
*/
std::pair<Region, Region> in_and_out (const Region &other) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->in_and_out (other);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/**
* @brief Round corners (in-place)
*

View File

@ -308,6 +308,7 @@ public:
virtual RegionDelegate *pull_overlapping (const Region &other) const = 0;
virtual TextsDelegate *pull_interacting (const Texts &other) const = 0;
virtual RegionDelegate *in (const Region &other, bool invert) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &other) const = 0;
virtual const db::Polygon *nth (size_t n) const = 0;
virtual bool has_valid_polygons () const = 0;

View File

@ -986,6 +986,7 @@ std::string contained_local_operation<TS, TI, TR>::description () const
// explicit instantiations
template class DB_PUBLIC contained_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC contained_local_operation<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC contained_local_operation<db::Edge, db::Edge, db::Edge>;
// ---------------------------------------------------------------------------------------------------------------

View File

@ -368,6 +368,8 @@ private:
};
typedef contained_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> ContainedLocalOperation;
// the implementation is type-agnostic and can be used for edges too
typedef contained_local_operation<db::Edge, db::Edge, db::Edge> ContainedEdgesLocalOperation;
} // namespace db

View File

@ -2036,10 +2036,11 @@ TEST(31_in)
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));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Region r1r = r1;
r1r.set_merged_semantics (false);
db::Region r2r = r2;
@ -2053,6 +2054,10 @@ TEST(31_in)
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.in (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in (r1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in (r3, false));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in (r3, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in (r1, false));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in (r1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in (r1, true));
@ -2067,6 +2072,61 @@ TEST(31_in)
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds");
}
TEST(31_in_and_out)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l31.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::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Region r1r = r1;
r1r.set_merged_semantics (false);
db::Region r2r = r2;
r2r.set_merged_semantics (false);
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)), r2.in_and_out (r1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in_and_out (r1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in_and_out (r3).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in_and_out (r3).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in_and_out (r1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in_and_out (r1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in_and_out (r1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in_and_out (r1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.in_and_out (r1r).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.in_and_out (r1r).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2r.in_and_out (r1r).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2r.in_and_out (r1r).second);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds");
}
TEST(100_Integration)
{
db::Layout ly;

View File

@ -1095,15 +1095,25 @@ TEST(19)
r2.insert (db::Box (db::Point (0, 0), db::Point (20, 30)));
EXPECT_EQ (r1.in (r2, false).to_string (), "(0,0;0,30;20,30;20,0)");
EXPECT_EQ (r1.in_and_out (r2).first.to_string (), "(0,0;0,30;20,30;20,0)");
EXPECT_EQ (r1.in (r2, true).to_string (), "");
EXPECT_EQ (r1.in (r1, false).to_string (), "(0,0;0,30;20,30;20,0)");
EXPECT_EQ (r1.in (r1, true).to_string (), "");
EXPECT_EQ (r1.in_and_out (r2).second.to_string (), "");
EXPECT_EQ (r2.in (r1, true).to_string (), "");
r1.set_merged_semantics (false);
r2.set_merged_semantics (false);
EXPECT_EQ (db::compare (r1.in (r2, false), "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true);
EXPECT_EQ (db::compare (r1.in_and_out (r2).first, "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true);
EXPECT_EQ (r1.in (r2, true).to_string (), "(0,0;0,20;10,20;10,0)");
EXPECT_EQ (r1.in_and_out (r2).second.to_string (), "(0,0;0,20;10,20;10,0)");
EXPECT_EQ (r2.in (r1, true).to_string (), "(0,0;0,10;20,10;20,0)");
EXPECT_EQ (r1.in (db::Region (), false).to_string (), "");
EXPECT_EQ (db::compare (r1.in (db::Region (), true), "(0,0;0,20;10,20;10,0);(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true);
EXPECT_EQ (db::Region ().in (r1, false).to_string (), "");
EXPECT_EQ (db::Region ().in (r1, true).to_string (), "");
}
TEST(20)

Binary file not shown.