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:
Matthias Koefferlein 2017-02-15 00:53:39 +01:00
parent fb6cf92b15
commit 320e96f6da
5 changed files with 329 additions and 257 deletions

View File

@ -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 &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_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const region_type &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region)
{
m_region = region;
mp_complex_region.reset (0);
}
void
RecursiveShapeIterator::init_region (const RecursiveShapeIterator::region_type &region)
{
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 &region)
{
if (m_region != region || mp_complex_region.get () != 0) {
init_region (region);
m_needs_reinit = true;
}
}
void
RecursiveShapeIterator::set_region (const region_type &region)
{
init_region (region);
m_needs_reinit = true;
}
void
RecursiveShapeIterator::confine_region (const box_type &region)
{
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 &region)
{
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 &region)
{
// 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) {

View File

@ -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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region, 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 &region () 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 &region)
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 &region);
/**
* @brief Sets a complex search region
* This will reset the iterator to the beginning.
*/
void set_region (const region_type &region);
/**
* @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 &region);
/**
* @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 &region);
/**
* @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 &region);
void init_region (const box_type &region);
void skip_shape_iter_for_complex_region () const;
void skip_inst_iter_for_complex_region () const;
void validate () const;

View File

@ -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) {

View File

@ -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 &region, bool overlapping)
static db::RecursiveShapeIterator *new_si3a (const db::Layout &layout, const db::Cell &cell, unsigned int layer, const db::Region &region, 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 &region, bool overlapping)
static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db::Cell &cell, const std::vector<unsigned int> &layers, const db::Region &region, 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"

View File

@ -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)");
}