From 320e96f6da7a7781b41e7cb37b0f899f7ac5489a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 15 Feb 2017 00:53:39 +0100 Subject: [PATCH] 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 --- src/db/dbRecursiveShapeIterator.cc | 283 ++++++++++++--------- src/db/dbRecursiveShapeIterator.h | 130 ++++------ src/db/dbTilingProcessor.cc | 2 +- src/db/gsiDeclDbRecursiveShapeIterator.cc | 114 ++++----- src/unit_tests/dbRecursiveShapeIterator.cc | 57 ++++- 5 files changed, 329 insertions(+), 257 deletions(-) diff --git a/src/db/dbRecursiveShapeIterator.cc b/src/db/dbRecursiveShapeIterator.cc index c86fd8399..65334c4ce 100644 --- a/src/db/dbRecursiveShapeIterator.cc +++ b/src/db/dbRecursiveShapeIterator.cc @@ -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 &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 &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 &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 &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 &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 &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 &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 &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 ()); -} - -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 ()); -} - 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 ()); + } if (mp_shapes) { diff --git a/src/db/dbRecursiveShapeIterator.h b/src/db/dbRecursiveShapeIterator.h index c9c8e2e8d..a1ffff1af 100644 --- a/src/db/dbRecursiveShapeIterator.h +++ b/src/db/dbRecursiveShapeIterator.h @@ -28,6 +28,7 @@ #include "dbLayout.h" #include "dbInstElement.h" +#include "tlAssert.h" #include #include @@ -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 &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 &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 &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 &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 mp_complex_region; db::box_convert 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; diff --git a/src/db/dbTilingProcessor.cc b/src/db/dbTilingProcessor.cc index 2d4f7e7e8..67a7b82f7 100644 --- a/src/db/dbTilingProcessor.cc +++ b/src/db/dbTilingProcessor.cc @@ -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) { diff --git a/src/db/gsiDeclDbRecursiveShapeIterator.cc b/src/db/gsiDeclDbRecursiveShapeIterator.cc index 5df1c9edd..ce6ccec08 100644 --- a/src/db/gsiDeclDbRecursiveShapeIterator.cc +++ b/src/db/gsiDeclDbRecursiveShapeIterator.cc @@ -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 &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 &layers, const db::Region ®ion, bool overlapping) +static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db::Cell &cell, const std::vector &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 decl_RecursiveShapeIterator ("RecursiveShapeIterator", gsi::constructor ("new", &new_si1, @@ -160,29 +158,6 @@ Class 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 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 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" diff --git a/src/unit_tests/dbRecursiveShapeIterator.cc b/src/unit_tests/dbRecursiveShapeIterator.cc index 2db048433..4dcb94f4b 100644 --- a/src/unit_tests/dbRecursiveShapeIterator.cc +++ b/src/unit_tests/dbRecursiveShapeIterator.cc @@ -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)"); }