mirror of https://github.com/KLayout/klayout.git
Preparations: recursive shape iterator shortcuts if hierarchy traversal, needs testing.
This commit is contained in:
parent
1673c472f2
commit
b9bdcf6fac
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ®ion, bool overlapping)
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type ®ion, 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 ®ion, bool overlapping)
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type ®ion, 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 ®ion, bool overlapping)
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type ®ion, 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 ®ion, bool overlapping)
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type ®ion, 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 ®ion, bool overlapping)
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type ®ion, 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 ®ion, bool overlapping)
|
||||
RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type ®ion, 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ®ion, bool overlapping = false);
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const box_type ®ion, 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 ®ion, bool overlapping = false);
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, unsigned int layer, const region_type ®ion, 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 ®ion, bool overlapping = false);
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const box_type ®ion, 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 ®ion, bool overlapping = false);
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::vector<unsigned int> &layers, const region_type ®ion, 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 ®ion, bool overlapping = false);
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const box_type ®ion, 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 ®ion, bool overlapping = false);
|
||||
RecursiveShapeIterator (const layout_type &layout, const cell_type &cell, const std::set<unsigned int> &layers, const region_type ®ion, 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue