mirror of https://github.com/KLayout/klayout.git
WIP complex regions for RecursiveShapeIterator
* Refactoring: no more "box+exclude" regions - they can be emulated using a NOT with the same result * "confinement" of regions inside recursive shape iterators * setters and getters for complex regions in GSI, confinement * more unit tests, some bug fixes
This commit is contained in:
parent
fb6cf92b15
commit
320e96f6da
|
|
@ -31,6 +31,62 @@ namespace db
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Recursive shape iterator implementation
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const RecursiveShapeIterator &d)
|
||||
{
|
||||
operator= (d);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator &RecursiveShapeIterator::operator= (const RecursiveShapeIterator &d)
|
||||
{
|
||||
if (&d != this) {
|
||||
|
||||
m_layers = d.m_layers;
|
||||
m_has_layers = d.m_has_layers;
|
||||
m_max_depth = d.m_max_depth;
|
||||
m_min_depth = d.m_min_depth;
|
||||
m_shape_flags = d.m_shape_flags;
|
||||
mp_shape_prop_sel = d.mp_shape_prop_sel;
|
||||
m_shape_inv_prop_sel = d.m_shape_inv_prop_sel;
|
||||
m_overlapping = d.m_overlapping;
|
||||
m_start = d.m_start;
|
||||
m_stop = d.m_stop;
|
||||
|
||||
mp_layout = d.mp_layout;
|
||||
mp_top_cell = d.mp_top_cell;
|
||||
mp_shapes = d.mp_shapes;
|
||||
|
||||
m_region = d.m_region;
|
||||
if (d.mp_complex_region.get () != 0) {
|
||||
mp_complex_region.reset (new region_type (*d.mp_complex_region.get ()));
|
||||
} else {
|
||||
mp_complex_region.reset (0);
|
||||
}
|
||||
|
||||
m_box_convert = d.m_box_convert;
|
||||
|
||||
m_inst = d.m_inst;
|
||||
m_inst_array = d.m_inst_array;
|
||||
m_empty_cells_cache = d.m_empty_cells_cache;
|
||||
m_layer = d.m_layer;
|
||||
mp_cell = d.mp_cell;
|
||||
m_current_layer = d.m_current_layer;
|
||||
m_shape = d.m_shape;
|
||||
m_trans = d.m_trans;
|
||||
m_trans_stack = d.m_trans_stack;
|
||||
m_inst_iterators = d.m_inst_iterators;
|
||||
m_inst_array_iterators = d.m_inst_array_iterators;
|
||||
m_cells = d.m_cells;
|
||||
m_local_complex_region_stack = d.m_local_complex_region_stack;
|
||||
m_local_region_stack = d.m_local_region_stack;
|
||||
m_needs_reinit = d.m_needs_reinit;
|
||||
m_inst_quad_id = d.m_inst_quad_id;
|
||||
m_inst_quad_id_stack = d.m_inst_quad_id_stack;
|
||||
m_shape_quad_id = d.m_shape_quad_id;
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator ()
|
||||
{
|
||||
// anything. Not necessary reasonable.
|
||||
|
|
@ -54,50 +110,36 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes)
|
|||
{
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
m_region = box_type::world ();
|
||||
mp_layout = 0;
|
||||
mp_shapes = &shapes;
|
||||
mp_top_cell = 0;
|
||||
m_overlapping = false;
|
||||
init ();
|
||||
init_region (box_type::world ());
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const box_type ®ion, bool overlapping)
|
||||
{
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
m_region = region;
|
||||
mp_layout = 0;
|
||||
mp_shapes = &shapes;
|
||||
mp_top_cell = 0;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const region_type ®ion, bool overlapping)
|
||||
{
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
m_region = region.bbox ();
|
||||
mp_layout = 0;
|
||||
mp_shapes = &shapes;
|
||||
mp_top_cell = 0;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const box_type ®ion, const region_type &excl_region, bool overlapping)
|
||||
{
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
m_region = region;
|
||||
mp_layout = 0;
|
||||
mp_shapes = &shapes;
|
||||
mp_top_cell = 0;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region, excl_region);
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type ®ion, bool overlapping)
|
||||
|
|
@ -105,12 +147,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
{
|
||||
m_layer = layer;
|
||||
m_has_layers = false;
|
||||
m_region = region;
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type ®ion, bool overlapping)
|
||||
|
|
@ -118,27 +160,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
{
|
||||
m_layer = layer;
|
||||
m_has_layers = false;
|
||||
m_region = region.bbox ();
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type ®ion, const region_type &excl_region, bool overlapping)
|
||||
: m_box_convert (layout, layer)
|
||||
{
|
||||
m_layer = layer;
|
||||
m_has_layers = false;
|
||||
m_region = region;
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region, excl_region);
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer)
|
||||
|
|
@ -146,12 +173,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
{
|
||||
m_layer = layer;
|
||||
m_has_layers = false;
|
||||
m_region = box_type::world ();
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
init ();
|
||||
init_region (box_type::world ());
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type ®ion, bool overlapping)
|
||||
|
|
@ -160,12 +187,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers = layers;
|
||||
m_has_layers = true;
|
||||
m_region = region;
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type ®ion, bool overlapping)
|
||||
|
|
@ -174,28 +201,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers = layers;
|
||||
m_has_layers = true;
|
||||
m_region = region.bbox ();
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type ®ion, const region_type &excl_region, bool overlapping)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
m_layer = 0;
|
||||
m_layers = layers;
|
||||
m_has_layers = true;
|
||||
m_region = region;
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region, excl_region);
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers)
|
||||
|
|
@ -204,12 +215,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers = layers;
|
||||
m_has_layers = true;
|
||||
m_region = box_type::world ();
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
init ();
|
||||
init_region (box_type::world ());
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type ®ion, bool overlapping)
|
||||
|
|
@ -218,12 +229,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
|
||||
m_has_layers = true;
|
||||
m_region = region;
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type ®ion, bool overlapping)
|
||||
|
|
@ -232,28 +243,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
|
||||
m_has_layers = true;
|
||||
m_region = region.bbox ();
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type ®ion, const region_type &excl_region, bool overlapping)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
m_layer = 0;
|
||||
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
|
||||
m_has_layers = true;
|
||||
m_region = region;
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
init_complex_region (region, excl_region);
|
||||
init_region (region);
|
||||
}
|
||||
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers)
|
||||
|
|
@ -262,12 +257,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
|
||||
m_has_layers = true;
|
||||
m_region = box_type::world ();
|
||||
mp_layout = &layout;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
init ();
|
||||
init_region (box_type::world ());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -283,6 +278,78 @@ RecursiveShapeIterator::init ()
|
|||
m_shape_quad_id = 0;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::init_region (const RecursiveShapeIterator::box_type ®ion)
|
||||
{
|
||||
m_region = region;
|
||||
mp_complex_region.reset (0);
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::init_region (const RecursiveShapeIterator::region_type ®ion)
|
||||
{
|
||||
if (region.empty ()) {
|
||||
|
||||
m_region = box_type ();
|
||||
mp_complex_region.reset (0);
|
||||
|
||||
} else if (region.is_box ()) {
|
||||
|
||||
m_region = region.bbox ();
|
||||
mp_complex_region.reset (0);
|
||||
|
||||
} else {
|
||||
|
||||
mp_complex_region.reset (new region_type (region));
|
||||
m_region = region.bbox ();
|
||||
// A small optimization. We can do this since we merge and translate to trapezoids anyway.
|
||||
mp_complex_region->set_strict_handling (false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::set_region (const box_type ®ion)
|
||||
{
|
||||
if (m_region != region || mp_complex_region.get () != 0) {
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::set_region (const region_type ®ion)
|
||||
{
|
||||
init_region (region);
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::confine_region (const box_type ®ion)
|
||||
{
|
||||
if (m_region.empty ()) {
|
||||
// no more confinement
|
||||
} else if (mp_complex_region.get ()) {
|
||||
init_region (*mp_complex_region & region_type (region));
|
||||
} else {
|
||||
init_region (m_region & region);
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::confine_region (const region_type ®ion)
|
||||
{
|
||||
if (m_region.empty ()) {
|
||||
// no more confinement
|
||||
} else if (mp_complex_region.get ()) {
|
||||
init_region (*mp_complex_region & region);
|
||||
} else {
|
||||
init_region (region & region_type (m_region));
|
||||
}
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct BoxTreePusher
|
||||
|
|
@ -305,48 +372,6 @@ private:
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::init_complex_region (const RecursiveShapeIterator::box_type &box, const RecursiveShapeIterator::region_type &excl_region)
|
||||
{
|
||||
// Use a boolean NOT and the trapezoid generator to produce a decomposition that goes into the complex region
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
ep.insert (db::Polygon (box), 0);
|
||||
size_t n = 1;
|
||||
for (region_type::const_iterator p = excl_region.begin (); !p.at_end (); ++p) {
|
||||
ep.insert (*p, n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
BoxTreePusher btp (&m_complex_region);
|
||||
db::TrapezoidGenerator tg (btp);
|
||||
|
||||
db::BooleanOp op (BooleanOp::ANotB);
|
||||
ep.process (tg, op);
|
||||
|
||||
m_complex_region.sort (db::box_convert <db::Box> ());
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::init_complex_region (const RecursiveShapeIterator::region_type ®ion)
|
||||
{
|
||||
// Use a merge and the trapezoid generator to produce a decomposition that goes into the complex region
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
size_t n = 0;
|
||||
for (region_type::const_iterator p = region.begin (); !p.at_end (); ++p, ++n) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
|
||||
BoxTreePusher btp (&m_complex_region);
|
||||
db::TrapezoidGenerator tg (btp);
|
||||
|
||||
db::MergeOp op (0);
|
||||
ep.process (tg, op);
|
||||
|
||||
m_complex_region.sort (db::box_convert <db::Box> ());
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::validate () const
|
||||
{
|
||||
|
|
@ -366,9 +391,33 @@ RecursiveShapeIterator::validate () const
|
|||
m_trans = cplx_trans_type ();
|
||||
m_current_layer = 0;
|
||||
m_shape = shape_iterator ();
|
||||
m_shape_quad_id = 0;
|
||||
|
||||
m_local_region_stack.clear ();
|
||||
m_local_region_stack.push_back (m_region);
|
||||
if (!m_complex_region.empty ()) {
|
||||
m_local_complex_region_stack.push_back (m_complex_region);
|
||||
|
||||
m_local_complex_region_stack.clear ();
|
||||
if (mp_complex_region.get ()) {
|
||||
|
||||
// prepare a local complex region
|
||||
m_local_complex_region_stack.push_back (box_tree_type ());
|
||||
|
||||
// Use a merge and the trapezoid generator to produce a decomposition that goes into the complex region
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
size_t n = 0;
|
||||
for (region_type::const_iterator p = mp_complex_region->begin (); !p.at_end (); ++p, ++n) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
|
||||
BoxTreePusher btp (&m_local_complex_region_stack.back ());
|
||||
db::TrapezoidGenerator tg (btp);
|
||||
|
||||
db::MergeOp op (0);
|
||||
ep.process (tg, op);
|
||||
|
||||
m_local_complex_region_stack.back ().sort (db::box_convert <db::Box> ());
|
||||
|
||||
}
|
||||
|
||||
if (mp_shapes) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "dbLayout.h"
|
||||
#include "dbInstElement.h"
|
||||
#include "tlAssert.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -67,6 +68,16 @@ public:
|
|||
*/
|
||||
RecursiveShapeIterator ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
RecursiveShapeIterator (const RecursiveShapeIterator &d);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
RecursiveShapeIterator &operator= (const RecursiveShapeIterator &d);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor iterating a single shape container
|
||||
*
|
||||
|
|
@ -101,20 +112,6 @@ public:
|
|||
*/
|
||||
RecursiveShapeIterator (const shapes_type &shapes, const region_type ®ion, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor iterating a single shape container
|
||||
*
|
||||
* @param shapes The shape container to iterate
|
||||
* @param region The basic region from which to select the shapes
|
||||
* @param excl_region A complex region that will be excluded from the rectangular region
|
||||
* @param overlapping Specify overlapping mode
|
||||
*
|
||||
* This iterator will iterate the shapes from the given shapes container using
|
||||
* the given search region in overlapping or touching mode. It allows specification of a complex
|
||||
* search region using a basic region and a complex region that is excluded from the search.
|
||||
*/
|
||||
RecursiveShapeIterator (const shapes_type &shapes, const box_type ®ion, const region_type &excl_region, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor
|
||||
*
|
||||
|
|
@ -146,23 +143,6 @@ public:
|
|||
*/
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type ®ion, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor
|
||||
*
|
||||
* @param layout The layout from which to get the cell hierarchy
|
||||
* @param cell The starting cell
|
||||
* @param layer The layer from which to deliver the shapes
|
||||
* @param region The region from which to select the shapes
|
||||
* @param excl_region A complex region that will be excluded from the rectangular region
|
||||
* @param overlapping Specify overlapping mode
|
||||
*
|
||||
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
|
||||
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
|
||||
* overlap the given region by at least one database unit. It allows specification of a complex
|
||||
* search region using a basic region and a complex region that is excluded from the search.
|
||||
*/
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type ®ion, const region_type &excl_region, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor for "world" iteration
|
||||
*
|
||||
|
|
@ -205,23 +185,6 @@ public:
|
|||
*/
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type ®ion, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor with a layer selection
|
||||
*
|
||||
* @param layout The layout from which to get the cell hierarchy
|
||||
* @param cell The starting cell
|
||||
* @param layers The layers from which to deliver the shapes
|
||||
* @param region The region from which to select the shapes
|
||||
* @param excl_region A complex region that will be excluded from the rectangular region
|
||||
* @param overlapping Specify overlapping mode
|
||||
*
|
||||
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
|
||||
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
|
||||
* overlap the given region by at least one database unit. It allows specification of a complex
|
||||
* search region using a basic region and a complex region that is excluded from the search.
|
||||
*/
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type ®ion, const region_type &excl_region, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor with a layer selection
|
||||
*
|
||||
|
|
@ -253,23 +216,6 @@ public:
|
|||
*/
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type ®ion, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor with a layer selection
|
||||
*
|
||||
* @param layout The layout from which to get the cell hierarchy
|
||||
* @param cell The starting cell
|
||||
* @param layers The layers from which to deliver the shapes
|
||||
* @param region The region from which to select the shapes
|
||||
* @param excl_region A complex region that will be excluded from the rectangular region
|
||||
* @param overlapping Specify overlapping mode
|
||||
*
|
||||
* By default the iterator operates in touching mode - i.e. shapes that touch the given region
|
||||
* are returned. By specifying the "overlapping" flag with a true value, the iterator delivers shapes that
|
||||
* overlap the given region by at least one database unit. It allows specification of a complex
|
||||
* search region using a basic region and a complex region that is excluded from the search.
|
||||
*/
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type ®ion, const region_type &excl_region, bool overlapping = false);
|
||||
|
||||
/**
|
||||
* @brief Standard constructor for "world" iteration with a layer set
|
||||
*
|
||||
|
|
@ -345,7 +291,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the region the iterator is using (will be world if none is set)
|
||||
* @brief Gets the basic region the iterator is using (will be world if none is set)
|
||||
* In addition to the basic region, a complex region may be defined that is further confining the
|
||||
* search to a subregion of the basic region.
|
||||
*/
|
||||
const box_type ®ion () const
|
||||
{
|
||||
|
|
@ -353,16 +301,48 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the region
|
||||
* @brief Returns true if a complex region is given
|
||||
*/
|
||||
void set_region (const box_type ®ion)
|
||||
bool has_complex_region () const
|
||||
{
|
||||
if (m_region != region) {
|
||||
m_region = region;
|
||||
m_needs_reinit = true;
|
||||
}
|
||||
return mp_complex_region.get () != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the complex region the iterator is using
|
||||
*/
|
||||
const region_type &complex_region () const
|
||||
{
|
||||
tl_assert (mp_complex_region.get ());
|
||||
return *mp_complex_region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the region to a basic rectangle
|
||||
* This will reset the iterator.
|
||||
*/
|
||||
void set_region (const box_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Sets a complex search region
|
||||
* This will reset the iterator to the beginning.
|
||||
*/
|
||||
void set_region (const region_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Confines the search further to the given rectangle.
|
||||
* This will reset the iterator and confine the search to the given rectangle
|
||||
* in addition to any region or complex region already defined.
|
||||
*/
|
||||
void confine_region (const box_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Confines the search further to the given complex region.
|
||||
* This will reset the iterator and confine the search to the given region
|
||||
* in addition to any simple region or complex region already defined.
|
||||
*/
|
||||
void confine_region (const region_type ®ion);
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether overlapping shapes are selected when a region is used
|
||||
*/
|
||||
|
|
@ -669,7 +649,7 @@ private:
|
|||
const shapes_type *mp_shapes;
|
||||
|
||||
box_type m_region;
|
||||
box_tree_type m_complex_region;
|
||||
std::auto_ptr<region_type> mp_complex_region;
|
||||
db::box_convert<db::CellInst> m_box_convert;
|
||||
|
||||
mutable inst_iterator m_inst;
|
||||
|
|
@ -692,8 +672,8 @@ private:
|
|||
mutable size_t m_shape_quad_id;
|
||||
|
||||
void init ();
|
||||
void init_complex_region (const box_type &box, const region_type &excl_region);
|
||||
void init_complex_region (const region_type &excl_region);
|
||||
void init_region (const region_type ®ion);
|
||||
void init_region (const box_type ®ion);
|
||||
void skip_shape_iter_for_complex_region () const;
|
||||
void skip_inst_iter_for_complex_region () const;
|
||||
void validate () const;
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ TilingProcessorWorker::do_perform (const TilingProcessorTask *tile_task)
|
|||
db::RecursiveShapeIterator iter;
|
||||
if (! region_dbu.empty ()) {
|
||||
iter = i->iter;
|
||||
iter.set_region (region_dbu);
|
||||
iter.confine_region (region_dbu);
|
||||
}
|
||||
|
||||
if (i->region) {
|
||||
|
|
|
|||
|
|
@ -48,12 +48,7 @@ static db::RecursiveShapeIterator *new_si3 (const db::Layout &layout, const db::
|
|||
return new db::RecursiveShapeIterator (layout, cell, layer, box, overlapping);
|
||||
}
|
||||
|
||||
static db::RecursiveShapeIterator *new_si3a (const db::Layout &layout, const db::Cell &cell, unsigned int layer, const db::Box &box, const db::Region &excl_region, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveShapeIterator (layout, cell, layer, box, excl_region, overlapping);
|
||||
}
|
||||
|
||||
static db::RecursiveShapeIterator *new_si3b (const db::Layout &layout, const db::Cell &cell, unsigned int layer, const db::Region ®ion, bool overlapping)
|
||||
static db::RecursiveShapeIterator *new_si3a (const db::Layout &layout, const db::Cell &cell, unsigned int layer, const db::Region ®ion, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveShapeIterator (layout, cell, layer, region, overlapping);
|
||||
}
|
||||
|
|
@ -63,12 +58,7 @@ static db::RecursiveShapeIterator *new_si4 (const db::Layout &layout, const db::
|
|||
return new db::RecursiveShapeIterator (layout, cell, layers, box, overlapping);
|
||||
}
|
||||
|
||||
static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db::Cell &cell, const std::vector<unsigned int> &layers, const db::Box &box, const db::Region &excl_region, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveShapeIterator (layout, cell, layers, box, excl_region, overlapping);
|
||||
}
|
||||
|
||||
static db::RecursiveShapeIterator *new_si4b (const db::Layout &layout, const db::Cell &cell, const std::vector<unsigned int> &layers, const db::Region ®ion, bool overlapping)
|
||||
static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db::Cell &cell, const std::vector<unsigned int> &layers, const db::Region ®ion, bool overlapping)
|
||||
{
|
||||
return new db::RecursiveShapeIterator (layout, cell, layers, region, overlapping);
|
||||
}
|
||||
|
|
@ -113,6 +103,14 @@ static void unselect_cells2 (db::RecursiveShapeIterator *r, const std::string &p
|
|||
r->unselect_cells (cc);
|
||||
}
|
||||
|
||||
static db::Region complex_region (const db::RecursiveShapeIterator *iter)
|
||||
{
|
||||
if (iter->has_complex_region ()) {
|
||||
return iter->complex_region ();
|
||||
} else {
|
||||
return db::Region (iter->region ());
|
||||
}
|
||||
}
|
||||
|
||||
Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIterator",
|
||||
gsi::constructor ("new", &new_si1,
|
||||
|
|
@ -160,29 +158,6 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si3a,
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layer, box, excl_region, overlapping\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param layer The layer (index) from which the shapes are taken\n"
|
||||
"@param box The basic search region\n"
|
||||
"@param excl_region The region that is excluded from the basic search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layer given by the layer index in the \"layer\" parameter.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" and the \"excl_region\" parameter. "
|
||||
"The box specifies the basic region. From that basic region the parts specified with \"excl_region\" "
|
||||
"are excluded. The excluded region needs to be a rectilinear region.\n"
|
||||
"\n"
|
||||
"If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box is touching the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.25.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si3b,
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layer, region, overlapping\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
|
|
@ -221,30 +196,6 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si4a,
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layers, box, excl_region, overlapping\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
"@param cell The initial cell which shall be iterated (including it's children)\n"
|
||||
"@param layers The layer indexes from which the shapes are taken\n"
|
||||
"@param box The basic search region\n"
|
||||
"@param excl_region The region that is excluded from the basic search region\n"
|
||||
"@param overlapping If set to true, shapes overlapping the search region are reported, otherwise touching is sufficient\n"
|
||||
"\n"
|
||||
"This constructor creates a new recursive shape iterator which delivers the shapes of "
|
||||
"the given cell plus it's children from the layers given by the layer indexes in the \"layers\" parameter.\n"
|
||||
"While iterating use the \\layer method to retrieve the layer of the current shape.\n"
|
||||
"\n"
|
||||
"The search is confined to the region given by the \"box\" and the \"excl_region\" parameter. "
|
||||
"The box specifies the basic region. From that basic region the parts specified with \"excl_region\" "
|
||||
"are excluded. The excluded region needs to be a rectilinear region.\n"
|
||||
"\n"
|
||||
"If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box is touching the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_si4b,
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layers, region, overlapping\n"
|
||||
"@param layout The layout which shall be iterated\n"
|
||||
|
|
@ -305,17 +256,54 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method ("region", &db::RecursiveShapeIterator::region,
|
||||
"@brief Gets the region that is iterator is using\n"
|
||||
"@brief Gets the basic region that is iterator is using\n"
|
||||
"The basic region is the overall box the region iterator iterates over. "
|
||||
"There may be an additional complex region that confines the region iterator. "
|
||||
"See \\complex_region for this attribute.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method ("region=", &db::RecursiveShapeIterator::set_region,
|
||||
"@brief Sets the region that is iterator is using\n"
|
||||
gsi::method_ext ("complex_region", &complex_region,
|
||||
"@brief Gets the complex region that is iterator is using\n"
|
||||
"The complex region is the effective region (a \\Region object) that the "
|
||||
"iterator is selecting from the layout layers. This region can be a single box "
|
||||
"or a complex region.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("region=", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::box_type &)) &db::RecursiveShapeIterator::set_region,
|
||||
"@brief Sets the rectangular region that is iterator is iterating over\n"
|
||||
"@args region\n"
|
||||
"See \\region for a description of this attribute.\n"
|
||||
"Setting a simple region will reset the complex region to a rectangle and reset the iterator to "
|
||||
"the beginning of the sequence."
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method ("overlapping?", &db::RecursiveShapeIterator::overlapping,
|
||||
gsi::method ("region=", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::region_type &)) &db::RecursiveShapeIterator::set_region,
|
||||
"@brief Sets the complex region that is iterator is using\n"
|
||||
"@args complex_region\n"
|
||||
"See \\complex_region for a description of this attribute. Setting the complex region will "
|
||||
"reset the basic region (see \\region) to the bounding box of the complex region and "
|
||||
"reset the iterator to the beginning of the sequence.\n"
|
||||
"\n"
|
||||
"This method overload has been introduced in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("confine_region", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::box_type &)) &db::RecursiveShapeIterator::confine_region,
|
||||
"@brief Confines the region that is iterator is iterating over\n"
|
||||
"@args region\n"
|
||||
"This method is similar to setting the region (see \\region=), but will add to any (complex or simple) region already set. "
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("region=", (void (db::RecursiveShapeIterator::*)(const db::RecursiveShapeIterator::region_type &)) &db::RecursiveShapeIterator::confine_region,
|
||||
"@brief Confines the region that is iterator is iterating over\n"
|
||||
"@args region\n"
|
||||
"This method is similar to setting the complex region (see \\region=), but will add to any (complex or simple) region already set."
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("overlapping?", &db::RecursiveShapeIterator::overlapping,
|
||||
"@brief Gets a flag indicating whether overlapping shapes are selected when a region is used\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
|
|
|
|||
|
|
@ -474,7 +474,62 @@ TEST(3)
|
|||
rro.insert (db::Box (3400, 3450, 5600, 6500));
|
||||
rro.insert (db::Box (6650, 5300, 10000, 7850));
|
||||
|
||||
db::RecursiveShapeIterator i23o (g, c0, 0, rro);
|
||||
db::RecursiveShapeIterator i23o (g, c0, 0, rro, true);
|
||||
db::RecursiveShapeIterator i23ocopy = i23o;
|
||||
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
|
||||
x = collect (i23ocopy, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
|
||||
// reset
|
||||
i23o.reset ();
|
||||
x = collect (i23o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
|
||||
// copy constructor
|
||||
i23ocopy = i23o;
|
||||
i23ocopy.reset ();
|
||||
x = collect (i23ocopy, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
|
||||
// setting of region
|
||||
|
||||
db::Region rg;
|
||||
i23o.set_region (rg);
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "");
|
||||
|
||||
rg.insert (db::Box (3400, 3450, 5600, 6500));
|
||||
rg.insert (db::Box (16650, 5300, 20000, 7850));
|
||||
|
||||
i23o.set_region (rg);
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)");
|
||||
|
||||
i23o.set_region (db::Box (6650, 5300, 10000, 7850));
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
|
||||
// region confinement
|
||||
|
||||
i23o.confine_region (db::Box (3400, 3450, 5600, 6500));
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "");
|
||||
|
||||
i23o.set_region (rro);
|
||||
i23o.confine_region (db::Box (3400, 3450, 5600, 6500));
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)");
|
||||
|
||||
i23o.set_region (db::Box (3400, 3450, 5600, 6500));
|
||||
i23o.confine_region (rro);
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)");
|
||||
|
||||
i23o.set_region (rro);
|
||||
i23o.confine_region (rro);
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue