New RBA/pya methods

More Shapes#insert flavours with Shapes and RecursiveShapeIterator,
RecursiveShapeIterator#dtrans.
This commit is contained in:
Matthias Koefferlein 2018-04-28 00:21:36 +02:00
parent f989b961c1
commit c94723bbce
5 changed files with 230 additions and 5 deletions

View File

@ -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.

View File

@ -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"

View File

@ -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"

View File

@ -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))

View File

@ -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")