mirror of https://github.com/KLayout/klayout.git
WIP on complex regions for RecursiveShapeIterator
- Added some tests - Performance improvements for insert of regions into shapes - Added LayoutLocker for that purpose (locks a layout against updates temporarily) - Improved implementation on RecursiveShapeIterator with complex regions: will now check if a shape is really inside the region.
This commit is contained in:
parent
282c6f70e2
commit
fb6cf92b15
|
|
@ -1672,6 +1672,45 @@ private:
|
|||
void do_prune_cells_or_subcells (const std::set<cell_index_type> &ids, int levels, bool subcells);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A nice helper class that employs RAII for locking the layout against updates
|
||||
*
|
||||
* If a layout shall be locked against internal updates temporarily, use this locker:
|
||||
* @code
|
||||
* Layout *ly = ...;
|
||||
* {
|
||||
* db::LayoutLocker locker (ly);
|
||||
* // the layout is not updated here
|
||||
* ... modify the layout
|
||||
* }
|
||||
* // now only the layout gets updated
|
||||
* @endcode
|
||||
*/
|
||||
class DB_PUBLIC LayoutLocker
|
||||
{
|
||||
public:
|
||||
explicit LayoutLocker (db::Layout *layout = 0)
|
||||
: mp_layout (layout)
|
||||
{
|
||||
if (mp_layout) {
|
||||
mp_layout->start_changes ();
|
||||
}
|
||||
}
|
||||
|
||||
~LayoutLocker ()
|
||||
{
|
||||
if (mp_layout) {
|
||||
mp_layout->end_changes ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
LayoutLocker (const LayoutLocker &);
|
||||
LayoutLocker &operator= (const LayoutLocker &);
|
||||
|
||||
db::Layout *mp_layout;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -497,6 +497,60 @@ RecursiveShapeIterator::bbox () const
|
|||
return box;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::skip_shape_iter_for_complex_region () const
|
||||
{
|
||||
while (! m_shape.at_end ()) {
|
||||
|
||||
// skip shape quad if possible
|
||||
while (! m_shape.at_end ()) {
|
||||
if (is_outside_complex_region (m_shape.quad_box ())) {
|
||||
m_shape.skip_quad ();
|
||||
} else {
|
||||
m_shape_quad_id = m_shape.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// skip shapes outside the complex region
|
||||
if (! m_shape.at_end ()) {
|
||||
if (! is_outside_complex_region (m_shape->bbox ())) {
|
||||
break;
|
||||
} else {
|
||||
++m_shape;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::skip_inst_iter_for_complex_region () const
|
||||
{
|
||||
while (! m_inst.at_end ()) {
|
||||
|
||||
// skip inst quad if possible
|
||||
while (! m_inst.at_end ()) {
|
||||
if (is_outside_complex_region (m_inst.quad_box ())) {
|
||||
m_inst.skip_quad ();
|
||||
} else {
|
||||
m_inst_quad_id = m_inst.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// skip insts outside the complex region
|
||||
if (! m_inst.at_end ()) {
|
||||
if (! is_outside_complex_region (m_inst->bbox ())) {
|
||||
break;
|
||||
} else {
|
||||
++m_inst;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::next ()
|
||||
{
|
||||
|
|
@ -504,16 +558,8 @@ RecursiveShapeIterator::next ()
|
|||
|
||||
++m_shape;
|
||||
|
||||
// skip shape quad if possible
|
||||
if (! m_local_complex_region_stack.empty () && m_shape_quad_id != m_shape.quad_id ()) {
|
||||
while (! m_shape.at_end ()) {
|
||||
if (is_outside_complex_region (m_shape.quad_box ())) {
|
||||
m_shape.skip_quad ();
|
||||
} else {
|
||||
m_shape_quad_id = m_shape.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
skip_shape_iter_for_complex_region ();
|
||||
}
|
||||
|
||||
if (! mp_shapes && m_shape.at_end ()) {
|
||||
|
|
@ -626,9 +672,8 @@ RecursiveShapeIterator::down () const
|
|||
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
|
||||
const box_tree_type &pcl = m_local_complex_region_stack.back ();
|
||||
|
||||
m_local_complex_region_stack.push_back (box_tree_type ());
|
||||
const box_tree_type &pcl = m_local_complex_region_stack.end ()[-2];
|
||||
|
||||
if (! new_region.empty ()) {
|
||||
|
||||
|
|
@ -694,16 +739,8 @@ RecursiveShapeIterator::start_shapes () const
|
|||
|
||||
m_shape_quad_id = 0;
|
||||
|
||||
// skip instance quad if possible
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
while (! m_shape.at_end ()) {
|
||||
if (is_outside_complex_region (m_shape.quad_box ())) {
|
||||
m_shape.skip_quad ();
|
||||
} else {
|
||||
m_shape_quad_id = m_shape.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
skip_shape_iter_for_complex_region ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -722,14 +759,7 @@ RecursiveShapeIterator::new_layer () const
|
|||
|
||||
// skip instance quad if possible
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
while (! m_shape.at_end ()) {
|
||||
if (is_outside_complex_region (m_shape.quad_box ())) {
|
||||
m_shape.skip_quad ();
|
||||
} else {
|
||||
m_shape_quad_id = m_shape.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
skip_shape_iter_for_complex_region ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -755,14 +785,7 @@ RecursiveShapeIterator::new_cell () const
|
|||
|
||||
// skip instance quad if possible
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
while (! m_inst.at_end ()) {
|
||||
if (is_outside_complex_region (m_inst.quad_box ())) {
|
||||
m_inst.skip_quad ();
|
||||
} else {
|
||||
m_inst_quad_id = m_inst.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
skip_inst_iter_for_complex_region ();
|
||||
}
|
||||
|
||||
new_inst ();
|
||||
|
|
@ -777,21 +800,11 @@ RecursiveShapeIterator::new_inst () const
|
|||
while (! m_inst.at_end ()) {
|
||||
|
||||
// skip instance quad if possible
|
||||
if (! m_local_complex_region_stack.empty () && m_inst_quad_id != m_inst.quad_id ()) {
|
||||
|
||||
while (! m_inst.at_end ()) {
|
||||
if (is_outside_complex_region (m_inst.quad_box ())) {
|
||||
m_inst.skip_quad ();
|
||||
} else {
|
||||
m_inst_quad_id = m_inst.quad_id ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! m_local_complex_region_stack.empty ()) {
|
||||
skip_inst_iter_for_complex_region ();
|
||||
if (m_inst.at_end ()) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (m_local_region_stack.back () != box_type::world ()) {
|
||||
|
|
|
|||
|
|
@ -694,6 +694,8 @@ private:
|
|||
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 skip_shape_iter_for_complex_region () const;
|
||||
void skip_inst_iter_for_complex_region () const;
|
||||
void validate () const;
|
||||
void start_shapes () const;
|
||||
void next_shape () const;
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
) +
|
||||
gsi::constructor ("new", &new_si3a,
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layer, box, overlapping\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"
|
||||
|
|
@ -184,7 +184,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
) +
|
||||
gsi::constructor ("new", &new_si3b,
|
||||
"@brief Creates a recursive, single-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layer, box, overlapping\n"
|
||||
"@args layout, cell, layer, 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"
|
||||
|
|
@ -222,7 +222,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
) +
|
||||
gsi::constructor ("new", &new_si4a,
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layers, box, overlapping\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"
|
||||
|
|
@ -246,7 +246,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
) +
|
||||
gsi::constructor ("new", &new_si4b,
|
||||
"@brief Creates a recursive, multi-layer shape iterator with a region.\n"
|
||||
"@args layout, cell, layers, box, overlapping\n"
|
||||
"@args layout, cell, layers, 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"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
*/
|
||||
|
||||
|
||||
#include "gsiDecl.h"
|
||||
|
||||
#include "dbRegion.h"
|
||||
|
|
|
|||
|
|
@ -207,6 +207,9 @@ static db::Shape insert_shape_with_dcplx_trans (db::Shapes *s, const db::Shape &
|
|||
|
||||
static void insert_region (db::Shapes *sh, const db::Region &r)
|
||||
{
|
||||
// NOTE: if the source (r) is from the same layout than the shapes live in, we better
|
||||
// lock the layout against updates while inserting
|
||||
db::LayoutLocker locker (sh->layout ());
|
||||
for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) {
|
||||
sh->insert (*s);
|
||||
}
|
||||
|
|
@ -214,6 +217,9 @@ static void insert_region (db::Shapes *sh, const db::Region &r)
|
|||
|
||||
static void insert_region_with_trans (db::Shapes *sh, const db::Region &r, const db::ICplxTrans &trans)
|
||||
{
|
||||
// NOTE: if the source (r) is from the same layout than the shapes live in, we better
|
||||
// lock the layout against updates while inserting
|
||||
db::LayoutLocker locker (sh->layout ());
|
||||
for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) {
|
||||
sh->insert (s->transformed (trans));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbRegion.h"
|
||||
#include "tlString.h"
|
||||
#include "utHead.h"
|
||||
|
||||
|
|
@ -274,6 +275,10 @@ TEST(1a)
|
|||
|
||||
std::string x;
|
||||
|
||||
db::RecursiveShapeIterator i0 (g, c0, 0, db::Box ());
|
||||
x = collect(i0, g);
|
||||
EXPECT_EQ (x, "");
|
||||
|
||||
db::RecursiveShapeIterator i1 (g, c0, 0, db::Box (0, 0, 100, 100));
|
||||
x = collect(i1, g);
|
||||
EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)");
|
||||
|
|
@ -393,6 +398,10 @@ TEST(2)
|
|||
|
||||
std::string x;
|
||||
|
||||
db::RecursiveShapeIterator i0 (g, c0, 0, db::Box ());
|
||||
x = collect(i0, g);
|
||||
EXPECT_EQ (x, "");
|
||||
|
||||
db::RecursiveShapeIterator i (g, c0, 0, db::Box::world ());
|
||||
x = collect(i, g);
|
||||
EXPECT_EQ (x, "[$3](1000,-500;2000,500)/[$3](1000,1500;2000,2500)/[$3](4000,500;5000,1500)/[$3](4000,2500;5000,3500)/[$3](1000,5500;2000,6500)/[$3](1000,7500;2000,8500)/[$3](4000,6500;5000,7500)/[$3](4000,8500;5000,9500)/[$3](7000,-500;8000,500)/[$3](7000,1500;8000,2500)/[$3](10000,500;11000,1500)/[$3](10000,2500;11000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)/[$3](10000,8500;11000,9500)");
|
||||
|
|
@ -414,4 +423,59 @@ TEST(2)
|
|||
EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
}
|
||||
|
||||
TEST(3)
|
||||
{
|
||||
db::Manager m;
|
||||
db::Layout g (&m);
|
||||
g.insert_layer(0);
|
||||
|
||||
db::Cell &c0 (g.cell (g.add_cell ()));
|
||||
db::Cell &c1 (g.cell (g.add_cell ()));
|
||||
db::Cell &c2 (g.cell (g.add_cell ()));
|
||||
|
||||
db::Box b (1000, -500, 2000, 500);
|
||||
c2.shapes (0).insert (b);
|
||||
|
||||
db::Trans tt;
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt, db::Vector (0, 6000), db::Vector (6000, 0), 2, 2));
|
||||
c1.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), tt, db::Vector (0, 2000), db::Vector (3000, 1000), 2, 2));
|
||||
|
||||
std::string x;
|
||||
|
||||
db::RecursiveShapeIterator i (g, c0, 0, db::Box::world ());
|
||||
x = collect(i, g);
|
||||
EXPECT_EQ (x, "[$3](1000,-500;2000,500)/[$3](1000,1500;2000,2500)/[$3](4000,500;5000,1500)/[$3](4000,2500;5000,3500)/[$3](1000,5500;2000,6500)/[$3](1000,7500;2000,8500)/[$3](4000,6500;5000,7500)/[$3](4000,8500;5000,9500)/[$3](7000,-500;8000,500)/[$3](7000,1500;8000,2500)/[$3](10000,500;11000,1500)/[$3](10000,2500;11000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)/[$3](10000,8500;11000,9500)");
|
||||
|
||||
db::RecursiveShapeIterator i2 (g, c0, 0, db::Region (db::Box (3400, 3450, 5600, 6500)));
|
||||
x = collect(i2, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)");
|
||||
|
||||
db::RecursiveShapeIterator i3 (g, c0, 0, db::Region (db::Box (6650, 5300, 10000, 7850)));
|
||||
x = collect(i3, g);
|
||||
EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)");
|
||||
|
||||
db::Region rr;
|
||||
rr.insert (db::Box (3400, 3450, 5600, 6500));
|
||||
rr.insert (db::Box (6650, 5300, 10000, 7850));
|
||||
|
||||
db::RecursiveShapeIterator i23 (g, c0, 0, rr);
|
||||
x = collect(i23, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](4000,6500;5000,7500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)/[$3](10000,6500;11000,7500)");
|
||||
|
||||
db::RecursiveShapeIterator i2o (g, c0, 0, db::Region (db::Box (3400, 3450, 5600, 6500)), true);
|
||||
x = collect(i2o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)");
|
||||
|
||||
db::RecursiveShapeIterator i3o (g, c0, 0, db::Region (db::Box (6650, 5300, 10000, 7850)), true);
|
||||
x = collect(i3o, g);
|
||||
EXPECT_EQ (x, "[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
|
||||
db::Region rro;
|
||||
rro.insert (db::Box (3400, 3450, 5600, 6500));
|
||||
rro.insert (db::Box (6650, 5300, 10000, 7850));
|
||||
|
||||
db::RecursiveShapeIterator i23o (g, c0, 0, rro);
|
||||
x = collect(i23o, g);
|
||||
EXPECT_EQ (x, "[$3](4000,2500;5000,3500)/[$3](7000,5500;8000,6500)/[$3](7000,7500;8000,8500)");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue