Merge pull request #1849 from KLayout/feature/issue-1836

Implemented solution for issue #1836 (Allow the usage of Cell.shapes(…
This commit is contained in:
Matthias Köfferlein 2024-09-08 22:24:40 +02:00 committed by GitHub
commit 53b7c985f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 185 additions and 4 deletions

View File

@ -1802,6 +1802,39 @@ read_simple (db::Cell *cell, const std::string &path)
return read_options (cell, path, db::LoadLayoutOptions ());
}
static db::Shapes &shapes_with_layer_info (db::Cell *cell, const db::LayerProperties &info)
{
if (! cell->layout ()) {
throw tl::Exception (tl::to_string (tr ("Cell is not associated with a layout")));
}
unsigned int li = cell->layout ()->get_layer (info);
return cell->shapes (li);
}
static const db::Shapes &shapes_with_layer_info_const (const db::Cell *cell, const db::LayerProperties &info)
{
if (! cell->layout ()) {
throw tl::Exception (tl::to_string (tr ("Cell is not associated with a layout")));
}
int li = cell->layout ()->get_layer_maybe (info);
if (li < 0) {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("%s is not a valid layer within the layout of the cell")), info.to_string ()));
}
return cell->shapes ((unsigned int) li);
}
static void clear_layer_with_info (db::Cell *cell, const db::LayerProperties &info)
{
if (cell->layout ()) {
int layer = cell->layout ()->get_layer_maybe (info);
if (layer >= 0) {
cell->clear ((unsigned int) layer);
}
}
}
static db::Point default_origin;
@ -1992,22 +2025,46 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"This method gives access to the shapes list on a certain layer.\n"
"If the layer does not exist yet, it is created.\n"
"\n"
"@param index The layer index of the shapes list to retrieve\n"
"@param layer_index The layer index of the shapes list to retrieve\n"
"\n"
"@return A reference to the shapes list\n"
) +
gsi::method_ext ("shapes", shapes_with_layer_info, gsi::arg ("layer"),
"@brief Returns the shapes list of the given layer\n"
"\n"
"This version takes a \\LayerInfo object and will look up the layer index. If no layer exists "
"with these attributes, it will be created.\n"
"\n"
"@param layer The layer attributes\n"
"\n"
"@return A reference to the shapes list\n"
"\n"
"This variant has been introduced in version 0.29.7.\n"
) +
gsi::method_ext ("shapes", &shapes_of_cell_const, gsi::arg ("layer_index"),
"@brief Returns the shapes list of the given layer (const version)\n"
"\n"
"This method gives access to the shapes list on a certain layer. This is the const version - only const (reading) methods "
"can be called on the returned object.\n"
"\n"
"@param index The layer index of the shapes list to retrieve\n"
"@param layer_index The layer index of the shapes list to retrieve\n"
"\n"
"@return A reference to the shapes list\n"
"\n"
"This variant has been introduced in version 0.26.4.\n"
) +
gsi::method_ext ("shapes", shapes_with_layer_info_const, gsi::arg ("layer"),
"@brief Returns the shapes list of the given layer (const version)\n"
"\n"
"This version takes a \\LayerInfo object and will look up the layer index. An error is raised if "
"no layer with these attributes exists.\n"
"\n"
"@param layer The layer attributes\n"
"\n"
"@return A reference to the shapes list\n"
"\n"
"This variant has been introduced in version 0.29.7.\n"
) +
gsi::method ("clear_shapes", &db::Cell::clear_shapes,
"@brief Clears all shapes in the cell\n"
) +
@ -2082,6 +2139,13 @@ Class<db::Cell> decl_Cell ("db", "Cell",
gsi::method ("clear", &db::Cell::clear, gsi::arg ("layer_index"),
"@brief Clears the shapes on the given layer\n"
) +
gsi::method_ext ("clear", &clear_layer_with_info, gsi::arg ("layer"),
"@brief Clears the shapes on the given layer\n"
"\n"
"This version takes a \\LayerInfo object for the layer. If no such layer exists, this method does nothing.\n"
"\n"
"This variant has been introduced in version 0.29.7.\n"
) +
gsi::method_ext ("clear", &clear_all,
"@brief Clears the cell (deletes shapes and instances)\n"
"This method has been introduced in version 0.23.\n"

View File

@ -1103,6 +1103,30 @@ void break_polygons1 (db::Layout *layout, size_t max_vertex_count, double max_ar
db::break_polygons (*layout, max_vertex_count, max_area_ratio);
}
void delete_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
{
int li = layout->get_layer_maybe (info);
if (li >= 0) {
layout->delete_layer ((unsigned int) li);
}
}
void clear_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
{
int li = layout->get_layer_maybe (info);
if (li >= 0) {
layout->clear_layer ((unsigned int) li);
}
}
void clear_layer_from_info_with_flags (db::Layout *layout, const db::LayerProperties &info, unsigned int flags)
{
int li = layout->get_layer_maybe (info);
if (li >= 0) {
layout->clear_layer ((unsigned int) li, flags);
}
}
Class<db::Layout> decl_Layout ("db", "Layout",
gsi::constructor ("new", &layout_ctor_with_manager, gsi::arg ("manager"),
"@brief Creates a layout object attached to a manager\n"
@ -1963,7 +1987,17 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n"
"This method was introduced in version 0.19.\n"
"\n"
"@param layer_index The index of the layer to delete.\n"
"@param layer_index The index of the layer to clear.\n"
) +
gsi::method_ext ("clear_layer", &clear_layer_from_info, gsi::arg ("layer"),
"@brief Clears a layer\n"
"\n"
"This variant takes a \\LayerInfo object to address the layer.\n"
"It does nothing if no layer with these attributes exists.\n"
"\n"
"This variant was introduced in version 0.26.7.\n"
"\n"
"@param layer The attributes of the layer to clear.\n"
) +
gsi::method ("clear_layer", static_cast<void (db::Layout::*) (unsigned int, unsigned int)> (&db::Layout::clear_layer), gsi::arg ("layer_index"), gsi::arg ("flags"),
"@brief Clears a layer (given shape types only)\n"
@ -1972,9 +2006,19 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n"
"This method was introduced in version 0.28.9.\n"
"\n"
"@param layer_index The index of the layer to delete.\n"
"@param layer_index The index of the layer to clear.\n"
"@param flags The type selector for the shapes to delete (see \\Shapes class, S... constants).\n"
) +
gsi::method_ext ("clear_layer", &clear_layer_from_info_with_flags, gsi::arg ("layer"), gsi::arg ("flags"),
"@brief Clears a layer (given shape types only)\n"
"\n"
"This variant takes a \\LayerInfo object to address the layer.\n"
"It does nothing if no layer with these attributes exists.\n"
"\n"
"This variant was introduced in version 0.26.7.\n"
"\n"
"@param layer The attributes of the layer to clear.\n"
) +
gsi::method ("delete_layer", &db::Layout::delete_layer, gsi::arg ("layer_index"),
"@brief Deletes a layer\n"
"\n"
@ -1983,6 +2027,16 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"\n"
"@param layer_index The index of the layer to delete.\n"
) +
gsi::method_ext ("delete_layer", &delete_layer_from_info, gsi::arg ("layer"),
"@brief Deletes a layer\n"
"\n"
"This variant takes a \\LayerInfo object to address the layer.\n"
"It does nothing if no layer with these attributes exists.\n"
"\n"
"This variant was introduced in version 0.26.7.\n"
"\n"
"@param layer The attributes of the layer to delete.\n"
) +
gsi::method_ext ("layer_indexes|#layer_indices", &layer_indexes,
"@brief Gets a list of valid layer's indices\n"
"This method returns an array with layer indices representing valid layers.\n"

View File

@ -98,6 +98,32 @@ class DBCellTests_TestClass < TestBase
end
# methods with LayerInfo instead layer index
def test_3
ly = RBA::Layout::new
top = ly.create_cell("TOP")
l1 = ly.layer(1, 0)
top.shapes(RBA::LayerInfo::new(1, 0)).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(top.shapes(l1).size, 1)
# unknown layers are ignored in clear
top.clear(RBA::LayerInfo::new(2, 0))
assert_equal(top.shapes(l1).size, 1)
# clear with LayerInfo
top.clear(RBA::LayerInfo::new(1, 0))
assert_equal(top.shapes(l1).size, 0)
# layer is created if not there
assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0) ])
top.shapes(RBA::LayerInfo::new(2, 0)).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0), RBA::LayerInfo::new(2, 0) ])
end
end
load("test_epilogue.rb")

View File

@ -2144,6 +2144,43 @@ class DBLayoutTests1_TestClass < TestBase
end
# Methods taking LayoutInfo instead of layer index
def test_26
ly = RBA::Layout::new
top = ly.create_cell("TOP")
l1 = ly.layer(1, 0)
# ignored
ly.clear_layer(RBA::LayerInfo::new(2, 0))
top.shapes(l1).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(top.shapes(l1).size, 1)
ly.clear_layer(RBA::LayerInfo::new(1, 0))
assert_equal(top.shapes(l1).size, 0)
top.shapes(l1).insert(RBA::Box::new(0, 0, 100, 200))
assert_equal(top.shapes(l1).size, 1)
ly.clear_layer(RBA::LayerInfo::new(1, 0), RBA::Shapes::SPolygons)
assert_equal(top.shapes(l1).size, 1)
ly.clear_layer(RBA::LayerInfo::new(1, 0), RBA::Shapes::SBoxes)
assert_equal(top.shapes(l1).size, 0)
assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0) ])
# ignored
ly.delete_layer(RBA::LayerInfo::new(2, 0))
assert_equal(ly.layer_infos, [ RBA::LayerInfo::new(1, 0) ])
ly.delete_layer(RBA::LayerInfo::new(1, 0))
assert_equal(ly.layer_infos, [ ])
end
# Iterating while flatten
def test_issue200