Preparations: recursive shape iterator shortcuts if hierarchy traversal, needs testing.

This commit is contained in:
Matthias Koefferlein 2024-03-24 19:01:36 +01:00
parent 1673c472f2
commit b9bdcf6fac
11 changed files with 307 additions and 62 deletions

View File

@ -219,6 +219,8 @@ AsIfFlatRegion::area (const db::Box &box) const
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
if (box.empty () || p->box ().inside (box)) {
a += p->area ();
} else if (p->is_box ()) {
a += (p->box () & box).area ();
} else {
std::vector<db::Polygon> clipped;
clip_poly (*p, box, clipped);

View File

@ -43,7 +43,6 @@ FlatRegion::FlatRegion (const FlatRegion &other)
: MutableRegion (other), mp_polygons (other.mp_polygons), mp_merged_polygons (other.mp_merged_polygons), mp_properties_repository (other.mp_properties_repository)
{
init ();
m_is_merged = other.m_is_merged;
m_merged_polygons_valid = other.m_merged_polygons_valid;
}
@ -52,15 +51,22 @@ FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged)
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
m_is_merged = is_merged;
}
FlatRegion::FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged)
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
m_is_merged = is_merged;
transform_generic (trans);
set_merged_semantics (merged_semantics);
}
FlatRegion::FlatRegion (bool is_merged)
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
m_is_merged = is_merged;
}

View File

@ -52,7 +52,8 @@ public:
typedef polygon_layer_wp_type::iterator polygon_iterator_wp_type;
FlatRegion ();
FlatRegion (const db::Shapes &polygons, bool is_merged);
FlatRegion (const db::Shapes &polygons, bool is_merged = false);
FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged = false);
FlatRegion (bool is_merged);
FlatRegion (const FlatRegion &other);

View File

@ -48,6 +48,8 @@ RecursiveShapeIterator &RecursiveShapeIterator::operator= (const RecursiveShapeI
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_for_merged_input = d.m_for_merged_input;
m_start = d.m_start;
m_stop = d.m_stop;
@ -99,6 +101,7 @@ RecursiveShapeIterator::RecursiveShapeIterator ()
mp_cell = 0;
m_current_layer = 0;
m_overlapping = false;
m_for_merged_input = false;
m_max_depth = std::numeric_limits<int>::max (); // all
m_min_depth = 0;
m_shape_flags = shape_iterator::All;
@ -116,6 +119,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes)
mp_shapes = &shapes;
mp_top_cell = 0;
m_overlapping = false;
m_for_merged_input = false;
init ();
init_region (box_type::world ());
}
@ -127,6 +131,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const
mp_shapes = &shapes;
mp_top_cell = 0;
m_overlapping = overlapping;
m_for_merged_input = false;
init ();
init_region (region);
}
@ -138,11 +143,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const
mp_shapes = &shapes;
mp_top_cell = 0;
m_overlapping = overlapping;
m_for_merged_input = false;
init ();
init_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, bool overlapping)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, bool overlapping, bool for_merged_input)
: m_box_convert (layout, layer)
{
m_layer = layer;
@ -151,11 +157,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
m_for_merged_input = for_merged_input;
init ();
init_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type &region, bool overlapping)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type &region, bool overlapping, bool for_merged_input)
: m_box_convert (layout, layer)
{
m_layer = layer;
@ -164,11 +171,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
m_for_merged_input = for_merged_input;
init ();
init_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, bool for_merged_input)
: m_box_convert (layout, layer)
{
m_layer = layer;
@ -177,11 +185,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = false;
m_for_merged_input = for_merged_input;
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)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type &region, bool overlapping, bool for_merged_input)
: m_box_convert (layout)
{
m_layer = 0;
@ -191,11 +200,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
m_for_merged_input = for_merged_input;
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)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type &region, bool overlapping, bool for_merged_input)
: m_box_convert (layout)
{
m_layer = 0;
@ -205,11 +215,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
m_for_merged_input = for_merged_input;
init ();
init_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, bool for_merged_input)
: m_box_convert (layout)
{
m_layer = 0;
@ -219,11 +230,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = false;
m_for_merged_input = for_merged_input;
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)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type &region, bool overlapping, bool for_merged_input)
: m_box_convert (layout)
{
m_layer = 0;
@ -233,11 +245,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
m_for_merged_input = for_merged_input;
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)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type &region, bool overlapping, bool for_merged_input)
: m_box_convert (layout)
{
m_layer = 0;
@ -247,11 +260,12 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = overlapping;
m_for_merged_input = for_merged_input;
init ();
init_region (region);
}
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers)
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, bool for_merged_input)
: m_box_convert (layout)
{
m_layer = 0;
@ -261,6 +275,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
mp_shapes = 0;
mp_top_cell = &cell;
m_overlapping = false;
m_for_merged_input = for_merged_input;
init ();
init_region (box_type::world ());
}
@ -721,13 +736,9 @@ RecursiveShapeIterator::next_shape (RecursiveShapeReceiver *receiver) const
}
if (is_empty) {
if (is_empty || !down (receiver)) {
++m_inst;
new_inst (receiver);
} else {
down (receiver);
}
} else {
@ -755,7 +766,7 @@ RecursiveShapeIterator::next_shape (RecursiveShapeReceiver *receiver) const
}
}
void
bool
RecursiveShapeIterator::down (RecursiveShapeReceiver *receiver) const
{
tl_assert (mp_layout);
@ -783,6 +794,40 @@ RecursiveShapeIterator::down (RecursiveShapeReceiver *receiver) const
new_region = m_trans.inverted () * m_region;
new_region &= cell_bbox (cell_index ());
}
// try some optimization - only consider optimizing by dropping the shape-covered area under certain circumstances:
// - single layer
// - less than 32 shapes to consider
// - total shape bbox in current region covers at least a third of it
// - total area of shapes in current region is at least a third of it
// TODO: the current implementation does not touch the complex search region
if (m_for_merged_input && (! m_has_layers || m_layers.size () == 1) && ! new_region.empty ()) {
unsigned int l = m_has_layers ? m_layers.front () : m_layer;
const shapes_type &shapes = m_cells.back ()->shapes (l);
box_type region_in_parent = m_inst->complex_trans (*m_inst_array) * new_region;
// NOTE: new_region is already in the coordinate system of the child cell
if (shapes.size () < 32 &&
3 * (shapes.bbox () & region_in_parent).area () > region_in_parent.area ()) {
region_type shapes_region (shapes);
if (3 * shapes_region.area (region_in_parent) > region_in_parent.area ()) {
shapes_region.transform (m_inst->complex_trans (*m_inst_array).inverted ());
// reduce the search region for less instances to look up
region_type new_complex_region = region_type (new_region) - shapes_region;
new_region = new_complex_region.bbox ();
}
}
}
m_local_region_stack.push_back (new_region);
if (! m_local_complex_region_stack.empty ()) {
@ -817,11 +862,25 @@ RecursiveShapeIterator::down (RecursiveShapeReceiver *receiver) const
}
if (receiver) {
receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
}
// do not descend if the box is empty
new_cell (receiver);
if (m_local_region_stack.back ().empty ()) {
pop ();
return false;
} else {
if (receiver) {
receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
}
new_cell (receiver);
return true;
}
}
void
@ -831,6 +890,12 @@ RecursiveShapeIterator::up (RecursiveShapeReceiver *receiver) const
receiver->leave_cell (this, cell ());
}
pop ();
}
void
RecursiveShapeIterator::pop () const
{
m_shape = shape_iterator ();
m_shape_quad_id = 0;

View File

@ -122,12 +122,13 @@ public:
* @param layer The layer from which to deliver the shapes
* @param region The region from which to select the shapes
* @param overlapping Specify overlapping mode
* @param for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*
* 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.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, bool overlapping = false);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type &region, bool overlapping = false, bool for_merged_input = false);
/**
* @brief Standard constructor
@ -137,13 +138,14 @@ public:
* @param layer The layer from which to deliver the shapes
* @param region The complex region from which to select the shapes
* @param overlapping Specify overlapping mode
* @param for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*
* 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.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type &region, bool overlapping = false);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type &region, bool overlapping = false, bool for_merged_input = false);
/**
* @brief Standard constructor for "world" iteration
@ -153,8 +155,9 @@ public:
* @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 for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, bool for_merged_input = false);
/**
* @brief Standard constructor with a layer selection
@ -164,12 +167,13 @@ public:
* @param layers The layers from which to deliver the shapes
* @param region The region from which to select the shapes
* @param overlapping Specify overlapping mode
* @param for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*
* 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.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type &region, bool overlapping = false);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type &region, bool overlapping = false, bool for_merged_input = false);
/**
* @brief Standard constructor with a layer selection
@ -179,13 +183,14 @@ public:
* @param layers The layers from which to deliver the shapes
* @param region The complex region from which to select the shapes
* @param overlapping Specify overlapping mode
* @param for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*
* 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.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type &region, bool overlapping = false);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type &region, bool overlapping = false, bool for_merged_input = false);
/**
* @brief Standard constructor with a layer selection
@ -195,12 +200,13 @@ public:
* @param layers The layers from which to deliver the shapes
* @param region The region from which to select the shapes
* @param overlapping Specify overlapping mode
* @param for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*
* 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.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type &region, bool overlapping = false);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type &region, bool overlapping = false, bool for_merged_input = false);
/**
* @brief Standard constructor with a layer selection
@ -210,13 +216,14 @@ public:
* @param layers The layers from which to deliver the shapes
* @param region The complex region from which to select the shapes
* @param overlapping Specify overlapping mode
* @param for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*
* 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.
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type &region, bool overlapping = false);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type &region, bool overlapping = false, bool for_merged_input = false);
/**
* @brief Standard constructor for "world" iteration with a layer set
@ -226,8 +233,9 @@ public:
* @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 for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, bool for_merged_input = false);
/**
* @brief Standard constructor for "world" iteration with a layer set
@ -237,8 +245,9 @@ public:
* @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 for_merged_input Optimize for merged input - drop shapes that are completely covered by others
*/
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers);
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, bool for_merged_input = false);
/**
* @brief Destructor
@ -427,6 +436,25 @@ public:
}
}
/**
* @brief Gets a flag indicating whether optimizing for merged input
*/
bool for_merged_input () const
{
return m_for_merged_input;
}
/**
* @brief Sets a flag indicating whether optimizing for merged input
*/
void set_for_merged_input (bool f)
{
if (m_for_merged_input != f) {
m_for_merged_input = f;
m_needs_reinit = true;
}
}
/**
* @brief Sets a global transformation
*
@ -812,7 +840,7 @@ private:
unsigned int m_shape_flags;
const shape_iterator::property_selector *mp_shape_prop_sel;
bool m_shape_inv_prop_sel;
bool m_overlapping;
bool m_overlapping, m_for_merged_input;
std::set<db::cell_index_type> m_start, m_stop;
cplx_trans_type m_global_trans;
db::PropertiesTranslator m_property_translator;
@ -858,7 +886,8 @@ private:
void new_cell (RecursiveShapeReceiver *receiver) const;
void new_layer () const;
void up (RecursiveShapeReceiver *receiver) const;
void down (RecursiveShapeReceiver *receiver) const;
bool down (RecursiveShapeReceiver *receiver) const;
void pop () const;
bool is_outside_complex_region (const db::Box &box) const;

View File

@ -74,14 +74,42 @@ Region &Region::operator= (const Region &other)
return *this;
}
Region::Region (const RecursiveShapeIterator &si)
Region::Region (const RecursiveShapeIterator &si, bool merged_semantics, bool is_merged)
{
mp_delegate = new OriginalLayerRegion (si);
mp_delegate = new OriginalLayerRegion (si, db::ICplxTrans (), merged_semantics, is_merged);
}
Region::Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics)
Region::Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged)
{
mp_delegate = new OriginalLayerRegion (si, trans, merged_semantics);
mp_delegate = new OriginalLayerRegion (si, trans, merged_semantics, is_merged);
}
Region::Region (const Shapes &shapes, bool merged_semantics, bool is_merged)
{
db::FlatRegion *flat_region = new FlatRegion (is_merged);
flat_region->reserve (shapes.size (db::ShapeIterator::Regions));
// NOTE: we need to normalize the shapes to polygons because this is what the flat region expects
for (auto s = shapes.begin (db::ShapeIterator::Regions); ! s.at_end (); ++s) {
flat_region->insert (*s);
}
mp_delegate = flat_region;
mp_delegate->set_merged_semantics (merged_semantics);
}
Region::Region (const Shapes &shapes, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged)
{
db::FlatRegion *flat_region = new FlatRegion (is_merged);
flat_region->reserve (shapes.size (db::ShapeIterator::Regions));
// NOTE: we need to normalize the shapes to polygons because this is what the flat region expects
for (auto s = shapes.begin (db::ShapeIterator::Regions); ! s.at_end (); ++s) {
flat_region->insert (*s, trans);
}
mp_delegate = flat_region;
mp_delegate->set_merged_semantics (merged_semantics);
}
Region::Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)

View File

@ -199,7 +199,7 @@ public:
* Creates a region from a recursive shape iterator. This allows feeding a region
* from a hierarchy of cells.
*/
explicit Region (const RecursiveShapeIterator &si);
explicit Region (const RecursiveShapeIterator &si, bool merged_semantics = true, bool is_merged = false);
/**
* @brief Constructor from a RecursiveShapeIterator with a transformation
@ -208,7 +208,23 @@ public:
* from a hierarchy of cells. The transformation is useful to scale to a specific
* DBU for example.
*/
explicit Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics = true);
explicit Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics = true, bool is_merged = false);
/**
* @brief Constructor from a Shapes container
*
* Creates a region from a shapes container.
*/
explicit Region (const Shapes &si, bool merged_semantics = true, bool is_merged = false);
/**
* @brief Constructor from a Shapes container with a transformation
*
* Creates a region from a recursive shape iterator. This allows feeding a region
* from a hierarchy of cells. The transformation is useful to scale to a specific
* DBU for example.
*/
explicit Region (const Shapes &si, const db::ICplxTrans &trans, bool merged_semantics = true, bool is_merged = false);
/**
* @brief Constructor from a RecursiveShapeIterator providing a deep representation

View File

@ -476,13 +476,29 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
"\n"
"This method has been introduced in version 0.23.\n"
) +
gsi::method ("overlapping=", &db::RecursiveShapeIterator::set_overlapping, gsi::arg ("region"),
gsi::method ("overlapping=", &db::RecursiveShapeIterator::set_overlapping, gsi::arg ("flag"),
"@brief Sets a flag indicating whether overlapping shapes are selected when a region is used\n"
"\n"
"If this flag is false, shapes touching the search region are returned.\n"
"\n"
"This method has been introduced in version 0.23.\n"
) +
gsi::method ("for_merged_input?", &db::RecursiveShapeIterator::for_merged_input,
"@brief Gets a flag indicating whether iterator optimizes for merged input\n"
"\n"
"see \\for_merged_input= for details of this attribute.\n"
"\n"
"This method has been introduced in version 0.29.\n"
) +
gsi::method ("for_merged_input=", &db::RecursiveShapeIterator::set_for_merged_input, gsi::arg ("flag"),
"@brief Sets a flag indicating whether iterator optimizes for merged input\n"
"\n"
"If this flag is set to true, the iterator is allowed to skip shapes it deems irrelevant "
"because they are covered entirely by other shapes. This allows shortcutting hierarchy traversal in "
"some cases.\n"
"\n"
"This method has been introduced in version 0.29.\n"
) +
gsi::method ("unselect_all_cells", &db::RecursiveShapeIterator::unselect_all_cells,
"@brief Unselects all cells.\n"
"\n"

View File

@ -270,15 +270,6 @@ static db::Region *new_path (const db::Path &o)
return new db::Region (o);
}
static db::Region *new_shapes (const db::Shapes &s)
{
db::Region *r = new db::Region ();
for (db::Shapes::shape_iterator i = s.begin (db::ShapeIterator::All); !i.at_end (); ++i) {
r->insert (*i);
}
return r;
}
static db::Region *new_texts_as_boxes1 (const db::RecursiveShapeIterator &si, const std::string &pat, bool pattern, db::Coord enl)
{
return new db::Region (db::Region (si).texts_as_boxes (pat, pattern, enl));
@ -329,16 +320,26 @@ static db::Region *new_si (const db::RecursiveShapeIterator &si)
return new db::Region (si);
}
static db::Region *new_sid (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
{
return new db::Region (si, dss, area_ratio, max_vertex_count);
}
static db::Region *new_si2 (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
{
return new db::Region (si, trans);
}
static db::Region *new_sis (const db::Shapes &si)
{
return new db::Region (si);
}
static db::Region *new_sis2 (const db::Shapes &si, const db::ICplxTrans &trans)
{
return new db::Region (si, trans);
}
static db::Region *new_sid (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
{
return new db::Region (si, dss, area_ratio, max_vertex_count);
}
static db::Region *new_sid2 (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, const db::ICplxTrans &trans, double area_ratio, size_t max_vertex_count)
{
return new db::Region (si, dss, trans, true, area_ratio, max_vertex_count);
@ -1088,13 +1089,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"This constructor creates a region from a path.\n"
) +
constructor ("new", &new_shapes, gsi::arg ("shapes"),
"@brief Shapes constructor\n"
"\n"
"This constructor creates a region from a \\Shapes collection.\n"
"\n"
"This constructor has been introduced in version 0.25."
) +
constructor ("new", &new_si, gsi::arg ("shape_iterator"),
"@brief Constructor from a hierarchical shape set\n"
"\n"
@ -1126,6 +1120,24 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"r = RBA::Region::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / dbu))\n"
"@/code\n"
) +
constructor ("new", &new_sis, gsi::arg ("shapes"),
"@brief Constructor from a shapes container\n"
"\n"
"This constructor creates a region from the shapes container.\n"
"Text objects and edges are not inserted, because they cannot be converted to polygons.\n"
"This method allows feeding the shapes from a hierarchy of cells into the region.\n"
"\n"
"This constructor has been introduced in version 0.25 and extended in version 0.29."
) +
constructor ("new", &new_sis2, gsi::arg ("shapes"), gsi::arg ("trans"),
"@brief Constructor from a shapes container with a transformation\n"
"\n"
"This constructor creates a region from the shapes container after applying the transformation.\n"
"Text objects and edges are not inserted, because they cannot be converted to polygons.\n"
"This method allows feeding the shapes from a hierarchy of cells into the region.\n"
"\n"
"This constructor variant has been introduced in version 0.29."
) +
constructor ("new", &new_sid, gsi::arg ("shape_iterator"), gsi::arg ("deep_shape_store"), gsi::arg ("area_ratio", 0.0), gsi::arg ("max_vertex_count", size_t (0)),
"@brief Constructor for a deep region from a hierarchical shape set\n"
"\n"

View File

@ -2537,6 +2537,35 @@ TEST(55_PropertiesFilterFlat)
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
}
TEST(56_RegionsFromShapes)
{
db::Shapes shapes;
shapes.insert (db::Box (0, 0, 100, 200));
shapes.insert (db::Box (50, 50, 150, 250));
EXPECT_EQ (db::Region (shapes).area (), 32500);
EXPECT_EQ (db::Region (shapes, false).area (), 40000);
EXPECT_EQ (db::Region (shapes, db::ICplxTrans (0.5)).area (), 8125);
EXPECT_EQ (db::Region (shapes, db::ICplxTrans (0.5), false).area (), 10000);
// for cross-checking: same for RecursiveShapeIterator
db::Layout layout;
unsigned int l1 = layout.insert_layer ();
db::Cell &top = layout.cell (layout.add_cell ("TOP"));
top.shapes (l1).insert (db::Box (0, 0, 100, 200));
top.shapes (l1).insert (db::Box (50, 50, 150, 250));
db::RecursiveShapeIterator si (layout, top, l1);
EXPECT_EQ (db::Region (si).area (), 32500);
EXPECT_EQ (db::Region (si, false).area (), 40000);
EXPECT_EQ (db::Region (si, db::ICplxTrans (0.5)).area (), 8125);
EXPECT_EQ (db::Region (si, db::ICplxTrans (0.5), false).area (), 10000);
}
TEST(100_Processors)
{
db::Region r;

View File

@ -1066,6 +1066,47 @@ class DBRegion_TestClass < TestBase
end
# regions from Shapes
def test_regions_from_shapes
shapes = RBA::Shapes::new;
shapes.insert(RBA::Box::new(0, 0, 100, 200))
shapes.insert(RBA::Box::new(50, 50, 150, 250))
assert_equal(RBA::Region::new(shapes).area, 32500)
region = RBA::Region::new(shapes)
region.merged_semantics = false
assert_equal(region.area, 40000)
assert_equal(RBA::Region::new(shapes, RBA::ICplxTrans::new(0.5)).area, 8125)
region = RBA::Region::new(shapes, RBA::ICplxTrans::new(0.5))
region.merged_semantics = false
assert_equal(region.area, 10000)
# for cross-checking: same for RecursiveShapeIterator
layout = RBA::Layout::new
l1 = layout.insert_layer(RBA::LayerInfo::new(1, 0))
top = layout.create_cell("TOP")
top.shapes(l1).insert (RBA::Box::new(0, 0, 100, 200))
top.shapes(l1).insert (RBA::Box::new(50, 50, 150, 250))
si = RBA::RecursiveShapeIterator::new(layout, top, l1)
assert_equal(RBA::Region::new(si).area, 32500)
region = RBA::Region::new(si)
region.merged_semantics = false
assert_equal(region.area, 40000)
assert_equal(RBA::Region::new(si, RBA::ICplxTrans::new(0.5)).area, 8125)
region = RBA::Region::new(si, RBA::ICplxTrans::new(0.5))
region.merged_semantics = false
assert_equal(region.area, 10000)
end
# deep region tests
def test_deep1