mirror of https://github.com/KLayout/klayout.git
Convenience 'each' for recursive shape iterator / recursive instance iterator
This commit is contained in:
parent
e49b189f64
commit
1a53cd00d2
|
|
@ -30,6 +30,31 @@
|
|||
namespace gsi
|
||||
{
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief A wrapper that allows using "each" on the iterator
|
||||
*/
|
||||
class IteratorIterator
|
||||
{
|
||||
public:
|
||||
typedef db::RecursiveInstanceIterator value_type;
|
||||
typedef db::RecursiveInstanceIterator &reference;
|
||||
typedef db::RecursiveInstanceIterator *pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef void difference_type;
|
||||
|
||||
IteratorIterator (db::RecursiveInstanceIterator *iter) : mp_iter (iter) { }
|
||||
bool at_end () const { return mp_iter->at_end (); }
|
||||
reference operator* () const { return *mp_iter; }
|
||||
void operator++ () { ++*mp_iter; }
|
||||
|
||||
private:
|
||||
db::RecursiveInstanceIterator *mp_iter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// db::RecursiveInstanceIterator binding
|
||||
|
||||
|
|
@ -48,6 +73,11 @@ static db::RecursiveInstanceIterator *new_si2a (const db::Layout &layout, const
|
|||
return new db::RecursiveInstanceIterator (layout, cell, region, overlapping);
|
||||
}
|
||||
|
||||
static IteratorIterator each (db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
return IteratorIterator (r);
|
||||
}
|
||||
|
||||
static db::DCplxTrans si_dtrans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
|
|
@ -184,6 +214,21 @@ Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "Recu
|
|||
"bounding box touches the search region are reported. The bounding box of instances is measured taking all layers "
|
||||
"of the target cell into account.\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each", &each,
|
||||
"@brief Native iteration\n"
|
||||
"This method enables native iteration, e.g.\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
" iter = ... # RecursiveInstanceIterator\n"
|
||||
" iter.each do |i|\n"
|
||||
" ... i is the iterator itself\n"
|
||||
" end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This is slightly more convenient than the 'at_end' .. 'next' loop.\n"
|
||||
"\n"
|
||||
"This feature has been introduced in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveInstanceIterator::*) (int)) &db::RecursiveInstanceIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
|
|
@ -468,6 +513,12 @@ Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "Recu
|
|||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"# or shorter:\n"
|
||||
"cell.begin_instances_rec.each do |iter|\n"
|
||||
" puts \"Instance of #{iter.inst_cell.name} in #{cell.name}: \" + (iter.dtrans * iter.inst_dtrans).to_s\n"
|
||||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Here, a target cell is specified which confines the search to instances of this particular cell.\n"
|
||||
"'iter.dtrans' gives us the accumulated transformation of all parents up to the top cell. "
|
||||
"'iter.inst_dtrans' gives us the transformation from the current instance. "
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
#
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
|
|
@ -27,12 +27,39 @@
|
|||
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// db::RecursiveShapeIterator binding
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief A wrapper that allows using "each" on the iterator
|
||||
*/
|
||||
class IteratorIterator
|
||||
{
|
||||
public:
|
||||
typedef db::RecursiveShapeIterator value_type;
|
||||
typedef db::RecursiveShapeIterator &reference;
|
||||
typedef db::RecursiveShapeIterator *pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef void difference_type;
|
||||
|
||||
IteratorIterator (db::RecursiveShapeIterator *iter) : mp_iter (iter) { }
|
||||
bool at_end () const { return mp_iter->at_end (); }
|
||||
reference operator* () const { return *mp_iter; }
|
||||
void operator++ () { ++*mp_iter; }
|
||||
|
||||
private:
|
||||
db::RecursiveShapeIterator *mp_iter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static db::RecursiveShapeIterator *new_si1 (const db::Layout &layout, const db::Cell &cell, unsigned int layer)
|
||||
{
|
||||
return new db::RecursiveShapeIterator (layout, cell, layer);
|
||||
|
|
@ -63,6 +90,11 @@ static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db:
|
|||
return new db::RecursiveShapeIterator (layout, cell, layers, region, overlapping);
|
||||
}
|
||||
|
||||
static IteratorIterator each (db::RecursiveShapeIterator *r)
|
||||
{
|
||||
return IteratorIterator (r);
|
||||
}
|
||||
|
||||
static db::DCplxTrans si_dtrans (const db::RecursiveShapeIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
|
|
@ -236,6 +268,21 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each", &each,
|
||||
"@brief Native iteration\n"
|
||||
"This method enables native iteration, e.g.\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
" iter = ... # RecursiveShapeIterator\n"
|
||||
" iter.each do |i|\n"
|
||||
" ... i is the iterator itself\n"
|
||||
" end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This is slightly more convenient than the 'at_end' .. 'next' loop.\n"
|
||||
"\n"
|
||||
"This feature has been introduced in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveShapeIterator::*) (int)) &db::RecursiveShapeIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
|
|
@ -560,6 +607,15 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
" end\n"
|
||||
" iter.next\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"# or shorter:\n"
|
||||
"iter = cell.begin_shapes_rec(layer)\n"
|
||||
"iter.each do |iter|\n"
|
||||
" if iter.shape.renders_polygon?\n"
|
||||
" polygon = iter.shape.polygon.transformed(iter.itrans)\n"
|
||||
" puts \"In cell #{iter.cell.name}: \" + polygon.to_s\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"\\Cell offers three methods to get these iterators: begin_shapes_rec, begin_shapes_rec_touching and begin_shapes_rec_overlapping.\n"
|
||||
|
|
|
|||
|
|
@ -27,7 +27,16 @@ class DBLayout_TestClass < TestBase
|
|||
|
||||
def collect(s, l)
|
||||
|
||||
# check native iteration here too ..
|
||||
res2 = []
|
||||
s.each do |s|
|
||||
r = "[#{s.inst_cell.name}]"
|
||||
r += (s.trans * s.inst_trans).to_s
|
||||
res2.push(r)
|
||||
end
|
||||
|
||||
res = []
|
||||
s.reset
|
||||
while !s.at_end?
|
||||
r = "[#{s.inst_cell.name}]"
|
||||
r += (s.trans * s.inst_trans).to_s
|
||||
|
|
@ -35,6 +44,8 @@ class DBLayout_TestClass < TestBase
|
|||
s.next
|
||||
end
|
||||
|
||||
assert_equal(res, res2)
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,21 @@ class DBRecursiveShapeIterator_TestClass < TestBase
|
|||
|
||||
def collect(s, l)
|
||||
|
||||
# check native iteration here too ..
|
||||
res2 = []
|
||||
s.each do |s|
|
||||
r = "[#{l.cell_name(s.cell_index)}]"
|
||||
if s.shape.is_box?
|
||||
box = s.shape.box
|
||||
r += box.transformed(s.trans).to_s
|
||||
else
|
||||
r += "X";
|
||||
end
|
||||
res2.push(r)
|
||||
end
|
||||
|
||||
res = []
|
||||
s.reset
|
||||
while !s.at_end?
|
||||
r = "[#{l.cell_name(s.cell_index)}]"
|
||||
if s.shape.is_box?
|
||||
|
|
@ -40,6 +54,8 @@ class DBRecursiveShapeIterator_TestClass < TestBase
|
|||
res.push(r)
|
||||
end
|
||||
|
||||
assert_equal(res, res2)
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue