Hierarchical implementation of edge to region operations.

This commit is contained in:
Matthias Koefferlein 2019-02-17 16:05:39 +01:00
parent e6ee1c064e
commit 61d766bd4c
8 changed files with 273 additions and 9 deletions

View File

@ -21,7 +21,9 @@
*/
#include "dbEdges.h"
#include "dbRegion.h"
#include "dbDeepEdges.h"
#include "dbDeepRegion.h"
#include "dbHierNetworkProcessor.h"
#include "dbCellGraphUtils.h"
#include "dbCellVariants.h"
@ -527,6 +529,24 @@ DeepEdges::and_or_not_with (const DeepEdges *other, bool and_op) const
return dl_out;
}
DeepLayer
DeepEdges::edge_region_op (const DeepRegion *other, bool outside, bool include_borders) const
{
DeepLayer dl_out (m_deep_layer.derived ());
db::EdgeToPolygonLocalOperation op (outside, include_borders);
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (m_deep_layer.store ()->threads ());
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
proc.run (&op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
return dl_out;
}
EdgesDelegate *DeepEdges::and_with (const Edges &other) const
{
const DeepEdges *other_deep = dynamic_cast <const DeepEdges *> (other.delegate ());
@ -549,8 +569,27 @@ EdgesDelegate *DeepEdges::and_with (const Edges &other) const
EdgesDelegate *DeepEdges::and_with (const Region &other) const
{
// TODO: implement
return AsIfFlatEdges::and_with (other);
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (empty ()) {
// Nothing to do
return new EmptyEdges ();
} else if (other.empty ()) {
// Nothing to do
return clone ();
} else if (! other_deep) {
return AsIfFlatEdges::not_with (other);
} else {
return new DeepEdges (edge_region_op (other_deep, false /*outside*/, true /*include borders*/));
}
}
EdgesDelegate *DeepEdges::not_with (const Edges &other) const
@ -580,8 +619,27 @@ EdgesDelegate *DeepEdges::not_with (const Edges &other) const
EdgesDelegate *DeepEdges::not_with (const Region &other) const
{
// TODO: implement
return AsIfFlatEdges::not_with (other);
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (empty ()) {
// Nothing to do
return new EmptyEdges ();
} else if (other.empty ()) {
// Nothing to do
return clone ();
} else if (! other_deep) {
return AsIfFlatEdges::not_with (other);
} else {
return new DeepEdges (edge_region_op (other_deep, true /*outside*/, true /*include borders*/));
}
}
EdgesDelegate *DeepEdges::xor_with (const Edges &other) const
@ -663,14 +721,52 @@ EdgesDelegate *DeepEdges::add (const Edges &other) const
EdgesDelegate *DeepEdges::inside_part (const Region &other) const
{
// TODO: implement
return AsIfFlatEdges::inside_part (other);
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (empty ()) {
// Nothing to do
return new EmptyEdges ();
} else if (other.empty ()) {
// Nothing to do
return clone ();
} else if (! other_deep) {
return AsIfFlatEdges::not_with (other);
} else {
return new DeepEdges (edge_region_op (other_deep, false /*outside*/, false /*include borders*/));
}
}
EdgesDelegate *DeepEdges::outside_part (const Region &other) const
{
// TODO: implement
return AsIfFlatEdges::outside_part (other);
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (empty ()) {
// Nothing to do
return new EmptyEdges ();
} else if (other.empty ()) {
// Nothing to do
return clone ();
} else if (! other_deep) {
return AsIfFlatEdges::not_with (other);
} else {
return new DeepEdges (edge_region_op (other_deep, true /*outside*/, false /*include borders*/));
}
}
RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const

View File

@ -33,6 +33,7 @@
namespace db {
class Edges;
class DeepRegion;
/**
* @brief Provides hierarchical edges implementation
@ -170,6 +171,7 @@ private:
void init ();
void ensure_merged_edges_valid () const;
DeepLayer and_or_not_with(const DeepEdges *other, bool and_op) const;
DeepLayer edge_region_op (const DeepRegion *other, bool outside, bool include_borders) const;
EdgePairs run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
};

View File

@ -241,5 +241,70 @@ EdgeBoolAndOrNotLocalOperation::compute_local (db::Layout * /*layout*/, const sh
}
}
// ---------------------------------------------------------------------------------------------
// EdgeToPolygonLocalOperation implementation
EdgeToPolygonLocalOperation::EdgeToPolygonLocalOperation (bool outside, bool include_borders)
: m_outside (outside), m_include_borders (include_borders)
{
// .. nothing yet ..
}
local_operation<db::Edge, db::PolygonRef, db::Edge>::on_empty_intruder_mode
EdgeToPolygonLocalOperation::on_empty_intruder_hint () const
{
return m_outside ? local_operation::Copy : local_operation::Drop;
}
std::string
EdgeToPolygonLocalOperation::description () const
{
return tl::to_string (m_outside ? tr ("Edge to polygon AND/INSIDE") : tr ("Edge to polygons NOT/OUTSIDE"));
}
void
EdgeToPolygonLocalOperation::compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
db::EdgeProcessor ep;
std::set<db::PolygonRef> others;
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j));
}
}
bool any_subject = false;
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
if (i->second.empty ()) {
// shortcut (outside: keep, otherwise: drop)
if (m_outside) {
result.insert (subject);
}
} else {
ep.insert (subject, 1);
any_subject = true;
}
}
if (! others.empty () || any_subject) {
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, 0);
}
}
db::EdgeToEdgeSetGenerator cc (result);
db::EdgePolygonOp op (m_outside, m_include_borders);
ep.process (cc, op);
}
}
}

View File

@ -164,6 +164,30 @@ private:
bool m_is_and;
};
/**
* @brief Implements a boolean AND or NOT operation between edges and polygons (polygons as intruders)
*
* "AND" is implemented by "outside == false", "NOT" by "outside == true" with "include_borders == true".
* With "include_borders == false" the operations are "INSIDE" and "OUTSIDE".
*/
class DB_PUBLIC EdgeToPolygonLocalOperation
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
{
public:
EdgeToPolygonLocalOperation (bool outside, bool include_borders);
virtual void compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::unordered_set<db::Edge> &result, size_t max_vertex_count, double area_ratio) const;
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
virtual std::string description () const;
// edge interaction distance is 1 to force overlap between edges and edge/boxes
virtual db::Coord dist () const { return m_include_borders ? 1 : 0; }
private:
bool m_outside;
bool m_include_borders;
};
}
#endif

View File

@ -42,6 +42,20 @@ void PolygonRefGenerator::put (const db::Polygon &polygon)
mp_polyrefs->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
}
// -----------------------------------------------------------------------------------------------
// class EdgeToEdgeSetGenerator
EdgeToEdgeSetGenerator::EdgeToEdgeSetGenerator (std::unordered_set<db::Edge> &edges)
: mp_edges (&edges)
{
// .. nothing yet ..
}
void EdgeToEdgeSetGenerator::put (const db::Edge &edge)
{
mp_edges->insert (edge);
}
// -----------------------------------------------------------------------------------------------
// class PolygonRefGenerator

View File

@ -41,7 +41,7 @@ class PolygonRefGenerator
{
public:
/**
* @brief Constructor specifying an external vector for storing the polygons
* @brief Constructor
*/
PolygonRefGenerator (db::Layout *layout, std::unordered_set<db::PolygonRef> &polyrefs);
@ -55,6 +55,24 @@ private:
std::unordered_set<db::PolygonRef> *mp_polyrefs;
};
class EdgeToEdgeSetGenerator
: public EdgeSink
{
public:
/**
* @brief Constructor
*/
EdgeToEdgeSetGenerator (std::unordered_set<db::Edge> &edges);
/**
* @brief Implementation of the PolygonSink interface
*/
virtual void put (const db::Edge &edge);
private:
std::unordered_set<db::Edge> *mp_edges;
};
class PolygonRefToShapesGenerator
: public PolygonSink
{

View File

@ -148,3 +148,48 @@ TEST(3_Edge2EdgeBooleans)
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au3.gds");
}
TEST(4_Edge2PolygonBooleans)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/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));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Region r2and3 = r2 & r3;
db::Edges e3 = r3.edges ();
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 (2, 0)), r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e3 & r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e3 & r2and3);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), e3 - r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), e3 - r2and3);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e3.inside_part (r2));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), e3.inside_part (r2and3));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), e3.outside_part (r2));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), e3.outside_part (r2and3));
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au4.gds");
}

BIN
testdata/algo/deep_edges_au4.gds vendored Normal file

Binary file not shown.