mirror of https://github.com/KLayout/klayout.git
New RBA/pya methods
More Shapes#insert flavours with Shapes and RecursiveShapeIterator, RecursiveShapeIterator#dtrans.
This commit is contained in:
parent
f989b961c1
commit
c94723bbce
|
|
@ -3,6 +3,12 @@
|
|||
* Enhancement: New "split" method for polygons
|
||||
This method will fragment the polygons into two or more
|
||||
smaller parts for reducing their vertex count.
|
||||
* Enhancement: New "dtrans" method for RecursiveShapeIterator
|
||||
This method delivers the transformation in micron unit space
|
||||
* Enhancement: New "insert" methods for Shapes
|
||||
Shapes can now insert from another Shapes container and
|
||||
from a RecursiveShapeIterator. Possible applications are
|
||||
fast flattening and fast region selection.
|
||||
* Enhancement: DXF and CIF "keep layer names"
|
||||
If this option is set in the reader options, layer names
|
||||
are not translated into GDS layer/datatype pairs.
|
||||
|
|
|
|||
|
|
@ -63,6 +63,13 @@ static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db:
|
|||
return new db::RecursiveShapeIterator (layout, cell, layers, region, overlapping);
|
||||
}
|
||||
|
||||
static db::DCplxTrans si_dtrans (const db::RecursiveShapeIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
tl_assert (ly != 0);
|
||||
return db::CplxTrans (ly->dbu ()) * r->trans () * db::VCplxTrans (1.0 / ly->dbu ());
|
||||
}
|
||||
|
||||
static void select_cells1 (db::RecursiveShapeIterator *r, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
std::set<db::cell_index_type> cc;
|
||||
|
|
@ -153,7 +160,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box is touching the search region are reported.\n"
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
|
|
@ -172,7 +179,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
"If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box is touching the search region are reported.\n"
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.25.\n"
|
||||
) +
|
||||
|
|
@ -191,7 +198,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"\n"
|
||||
"The search is confined to the region given by the \"box\" parameter. If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box is touching the search region are reported.\n"
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
|
|
@ -211,7 +218,7 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"The search is confined to the region given by the \"region\" parameter. The region needs to be a rectilinear region.\n"
|
||||
"If \"overlapping\" is true, shapes whose "
|
||||
"bounding box is overlapping the search region are reported. If \"overlapping\" is false, shapes whose "
|
||||
"bounding box is touching the search region are reported.\n"
|
||||
"bounding box touches the search region are reported.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.23.\n"
|
||||
) +
|
||||
|
|
@ -415,7 +422,15 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("RecursiveShapeIt
|
|||
"Starting with version 0.25, this transformation is a int-to-int transformation the 'itrans' method "
|
||||
"which was providing this transformation before is deprecated."
|
||||
) +
|
||||
gsi::method ("shape", &db::RecursiveShapeIterator::shape,
|
||||
gsi::method_ext ("dtrans", &gsi::si_dtrans,
|
||||
"@brief Gets transformation into the initial cell applicable to floating point types\n"
|
||||
"\n"
|
||||
"This transformation corresponds to the one deliverd by \\trans, but is applicable to "
|
||||
"the floating-point shape types in micron unit space.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3."
|
||||
) +
|
||||
gsi::method ("shape", &db::RecursiveShapeIterator::shape,
|
||||
"@brief Gets the current shape\n"
|
||||
"\n"
|
||||
"Returns the shape currently referred to by the recursive iterator. \n"
|
||||
|
|
|
|||
|
|
@ -205,6 +205,70 @@ static db::Shape insert_shape_with_dcplx_trans (db::Shapes *s, const db::Shape &
|
|||
return s->insert (shape, dbu_trans.inverted () * trans * dbu_trans, pm);
|
||||
}
|
||||
|
||||
static void insert_iter (db::Shapes *sh, const db::RecursiveShapeIterator &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::RecursiveShapeIterator i = r; !i.at_end (); ++i) {
|
||||
tl::ident_map<db::properties_id_type> pm;
|
||||
sh->insert (*i, i.trans (), pm);
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_iter_with_trans (db::Shapes *sh, const db::RecursiveShapeIterator &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::RecursiveShapeIterator i = r; !i.at_end (); ++i) {
|
||||
tl::ident_map<db::properties_id_type> pm;
|
||||
sh->insert (*i, trans * i.trans (), pm);
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_shapes (db::Shapes *sh, const db::Shapes &s)
|
||||
{
|
||||
// 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::Shapes::shape_iterator i = s.begin (db::ShapeIterator::All); !i.at_end(); ++i) {
|
||||
sh->insert (*i);
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_shapes_with_flags (db::Shapes *sh, const db::Shapes &s, unsigned int flags)
|
||||
{
|
||||
// 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::Shapes::shape_iterator i = s.begin (flags); !i.at_end(); ++i) {
|
||||
sh->insert (*i);
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_shapes_with_trans (db::Shapes *sh, const db::Shapes &s, 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::Shapes::shape_iterator i = s.begin (db::ShapeIterator::All); !i.at_end(); ++i) {
|
||||
tl::ident_map<db::properties_id_type> pm;
|
||||
sh->insert (*i, trans, pm);
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_shapes_with_flag_and_trans (db::Shapes *sh, const db::Shapes &s, unsigned int flags, 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::Shapes::shape_iterator i = s.begin (flags); !i.at_end(); ++i) {
|
||||
tl::ident_map<db::properties_id_type> pm;
|
||||
sh->insert (*i, trans, pm);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -360,6 +424,62 @@ Class<db::Shapes> decl_Shapes ("Shapes",
|
|||
"@return A reference (a \\Shape object) to the newly created shape\n"
|
||||
"This method has been introduced in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("insert", &insert_iter, gsi::arg ("iter"),
|
||||
"@brief Inserts the shapes taken from a recursive shape iterator\n"
|
||||
"@param iter The iterator from which to take the shapes from\n"
|
||||
"\n"
|
||||
"This method iterates over all shapes from the iterator and inserts them into the container.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("insert", &insert_iter_with_trans, gsi::arg ("iter"), gsi::arg ("trans"),
|
||||
"@brief Inserts the shapes taken from a recursive shape iterator with a transformation\n"
|
||||
"@param iter The iterator from which to take the shapes from\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"\n"
|
||||
"This method iterates over all shapes from the iterator and inserts them into the container.\n"
|
||||
"The given transformation is applied before the shapes are inserted.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("insert", &insert_shapes, gsi::arg ("shapes"),
|
||||
"@brief Inserts the shapes taken from another shape container\n"
|
||||
"@param shapes The other container from which to take the shapes from\n"
|
||||
"\n"
|
||||
"This method takes all shapes from the given container and inserts them into this one.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("insert", &insert_shapes_with_trans, gsi::arg ("shapes"), gsi::arg ("trans"),
|
||||
"@brief Inserts the shapes taken from another shape container with a transformation\n"
|
||||
"@param shapes The other container from which to take the shapes from\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"\n"
|
||||
"This method takes all shapes from the given container and inserts them into this one "
|
||||
"after applying the given transformation.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("insert", &insert_shapes_with_flags, gsi::arg ("shapes"), gsi::arg ("flags"),
|
||||
"@brief Inserts the shapes taken from another shape container\n"
|
||||
"@param shapes The other container from which to take the shapes from\n"
|
||||
"@param flags The filter flags for taking the shapes from the input container\n"
|
||||
"\n"
|
||||
"This method takes all selected shapes from the given container and inserts them into this one.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("insert", &insert_shapes_with_flag_and_trans, gsi::arg ("shapes"), gsi::arg ("flags"), gsi::arg ("trans"),
|
||||
"@brief Inserts the shapes taken from another shape container with a transformation\n"
|
||||
"@param shapes The other container from which to take the shapes from\n"
|
||||
"@param iter The other container from which to take the shapes from\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"\n"
|
||||
"This method takes all selected shapes from the given container and inserts them into this one "
|
||||
"after applying the given transformation.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("insert", &insert_region, gsi::arg ("region"),
|
||||
"@brief Inserts the polygons from the region into this shape container\n"
|
||||
"@param region The region to insert\n"
|
||||
|
|
|
|||
|
|
@ -263,6 +263,25 @@ class DBLayout_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
def dcollect(s, l)
|
||||
|
||||
res = []
|
||||
while !s.at_end?
|
||||
r = "[#{l.cell_name(s.cell_index)}]"
|
||||
if s.shape.is_box?
|
||||
box = s.shape.dbox
|
||||
r += box.transformed(s.dtrans).to_s
|
||||
else
|
||||
r += "X";
|
||||
end
|
||||
s.next
|
||||
res.push(r)
|
||||
end
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
||||
def test_5
|
||||
|
||||
# Recursive shape iterator tests
|
||||
|
|
@ -294,6 +313,8 @@ class DBLayout_TestClass < TestBase
|
|||
i1copy = i1.dup
|
||||
assert_equal(i1copy.overlapping?, false)
|
||||
assert_equal(collect(i1, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
i1.reset
|
||||
assert_equal(dcollect(i1, l), "[c0](0,0.1;1,1.2)/[c1](0,0.1;1,1.2)/[c2](0.1,0;1.1,1.1)")
|
||||
assert_equal(collect(i1copy, l), "[c0](0,100;1000,1200)/[c1](0,100;1000,1200)/[c2](100,0;1100,1100)")
|
||||
|
||||
i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::DBox.new(0, 0, 0.100, 0.100))
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ end
|
|||
|
||||
load("test_prologue.rb")
|
||||
|
||||
# cool stuff ...
|
||||
class RBA::Shapes
|
||||
include Enumerable
|
||||
end
|
||||
|
||||
class DBShapes_TestClass < TestBase
|
||||
|
||||
# Shapes
|
||||
|
|
@ -1314,6 +1319,64 @@ class DBShapes_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# Shapes (insert from recursive shape iterator and other shape container)
|
||||
def test_9
|
||||
|
||||
l = RBA::Layout.new
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
l.insert_layer_at(1, RBA::LayerInfo.new(2, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
c2 = l.cell(l.add_cell("c2"))
|
||||
c3 = l.cell(l.add_cell("c3"))
|
||||
|
||||
tt = RBA::Trans.new
|
||||
c0.insert(RBA::CellInstArray.new(c1.cell_index, tt))
|
||||
c0.insert(RBA::CellInstArray.new(c2.cell_index, RBA::Trans.new(RBA::Point.new(100, -100))))
|
||||
c0.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(1)))
|
||||
c2.insert(RBA::CellInstArray.new(c3.cell_index, RBA::Trans.new(RBA::Point.new(1100, 0))))
|
||||
|
||||
b = RBA::Box.new(0, 100, 1000, 1200)
|
||||
c0.shapes(0).insert(b)
|
||||
c1.shapes(0).insert(b)
|
||||
c2.shapes(0).insert(b)
|
||||
c3.shapes(0).insert(b)
|
||||
|
||||
shapes = RBA::Shapes::new
|
||||
i1 = l.begin_shapes_touching(c0.cell_index, 0, RBA::Box.new(0, 0, 100, 100))
|
||||
shapes.insert(i1)
|
||||
assert_equal(shapes.collect { |s| s.to_s }.join(","), "box (0,100;1000,1200),box (0,100;1000,1200),box (100,0;1100,1100)")
|
||||
|
||||
shapes.clear
|
||||
shapes.insert(i1, RBA::ICplxTrans::new(2.0))
|
||||
assert_equal(shapes.collect { |s| s.to_s }.join(","), "box (0,200;2000,2400),box (0,200;2000,2400),box (200,0;2200,2200)")
|
||||
|
||||
shapes2 = RBA::Shapes::new
|
||||
shapes2.insert(shapes)
|
||||
assert_equal(shapes2.collect { |s| s.to_s }.join(","), "box (0,200;2000,2400),box (0,200;2000,2400),box (200,0;2200,2200)")
|
||||
|
||||
shapes2.clear
|
||||
shapes2.insert(shapes, RBA::ICplxTrans::new(0.5))
|
||||
assert_equal(shapes2.collect { |s| s.to_s }.join(","), "box (0,100;1000,1200),box (0,100;1000,1200),box (100,0;1100,1100)")
|
||||
|
||||
shapes2.clear
|
||||
shapes2.insert(shapes, RBA::Shapes::SPolygons, RBA::ICplxTrans::new(0.5))
|
||||
assert_equal(shapes2.collect { |s| s.to_s }.join(","), "")
|
||||
|
||||
shapes2.clear
|
||||
shapes2.insert(shapes, RBA::Shapes::SAll, RBA::ICplxTrans::new(0.5))
|
||||
assert_equal(shapes2.collect { |s| s.to_s }.join(","), "box (0,100;1000,1200),box (0,100;1000,1200),box (100,0;1100,1100)")
|
||||
|
||||
shapes2.clear
|
||||
shapes2.insert(shapes, RBA::Shapes::SPolygons)
|
||||
assert_equal(shapes2.collect { |s| s.to_s }.join(","), "")
|
||||
|
||||
shapes2.clear
|
||||
shapes2.insert(shapes, RBA::Shapes::SAll)
|
||||
assert_equal(shapes2.collect { |s| s.to_s }.join(","), "box (0,200;2000,2400),box (0,200;2000,2400),box (200,0;2200,2200)")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue