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 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
|
// 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);
|
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)
|
static db::DCplxTrans si_dtrans (const db::RecursiveInstanceIterator *r)
|
||||||
{
|
{
|
||||||
const db::Layout *ly = r->layout ();
|
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 "
|
"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"
|
"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"),
|
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"
|
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -468,6 +513,12 @@ Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "Recu
|
||||||
"end\n"
|
"end\n"
|
||||||
"@/code\n"
|
"@/code\n"
|
||||||
"\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"
|
"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.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. "
|
"'iter.inst_dtrans' gives us the transformation from the current instance. "
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
|
#
|
||||||
/*
|
/*
|
||||||
|
|
||||||
KLayout Layout Viewer
|
KLayout Layout Viewer
|
||||||
|
|
@ -27,12 +27,39 @@
|
||||||
|
|
||||||
#include "tlGlobPattern.h"
|
#include "tlGlobPattern.h"
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
namespace gsi
|
namespace gsi
|
||||||
{
|
{
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// db::RecursiveShapeIterator binding
|
// 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)
|
static db::RecursiveShapeIterator *new_si1 (const db::Layout &layout, const db::Cell &cell, unsigned int layer)
|
||||||
{
|
{
|
||||||
return new db::RecursiveShapeIterator (layout, cell, 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);
|
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)
|
static db::DCplxTrans si_dtrans (const db::RecursiveShapeIterator *r)
|
||||||
{
|
{
|
||||||
const db::Layout *ly = r->layout ();
|
const db::Layout *ly = r->layout ();
|
||||||
|
|
@ -236,6 +268,21 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
||||||
"\n"
|
"\n"
|
||||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\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"),
|
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"
|
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -560,6 +607,15 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
||||||
" end\n"
|
" end\n"
|
||||||
" iter.next\n"
|
" iter.next\n"
|
||||||
"end\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"
|
"@/code\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\\Cell offers three methods to get these iterators: begin_shapes_rec, begin_shapes_rec_touching and begin_shapes_rec_overlapping.\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)
|
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 = []
|
res = []
|
||||||
|
s.reset
|
||||||
while !s.at_end?
|
while !s.at_end?
|
||||||
r = "[#{s.inst_cell.name}]"
|
r = "[#{s.inst_cell.name}]"
|
||||||
r += (s.trans * s.inst_trans).to_s
|
r += (s.trans * s.inst_trans).to_s
|
||||||
|
|
@ -35,6 +44,8 @@ class DBLayout_TestClass < TestBase
|
||||||
s.next
|
s.next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert_equal(res, res2)
|
||||||
|
|
||||||
return res.join("/")
|
return res.join("/")
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,21 @@ class DBRecursiveShapeIterator_TestClass < TestBase
|
||||||
|
|
||||||
def collect(s, l)
|
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 = []
|
res = []
|
||||||
|
s.reset
|
||||||
while !s.at_end?
|
while !s.at_end?
|
||||||
r = "[#{l.cell_name(s.cell_index)}]"
|
r = "[#{l.cell_name(s.cell_index)}]"
|
||||||
if s.shape.is_box?
|
if s.shape.is_box?
|
||||||
|
|
@ -40,6 +54,8 @@ class DBRecursiveShapeIterator_TestClass < TestBase
|
||||||
res.push(r)
|
res.push(r)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert_equal(res, res2)
|
||||||
|
|
||||||
return res.join("/")
|
return res.join("/")
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue