From 58d489b39a9ecee1b4bf8518ac3de52c0b6da8ed Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 24 Jul 2024 22:54:47 +0200 Subject: [PATCH] Added Region#being_shapes_rec and Region#begin_merged_shapes_rec, mainly for being able to retrieve shapes with properties from Region#nets --- src/db/db/gsiDeclDbRegion.cc | 45 ++++++++++++++++++++++++++++++++- testdata/python/dbRegionTest.py | 25 ++++++++++++++++++ testdata/ruby/dbRegionTest.rb | 27 ++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 059dd4d67..886a52ff6 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -1132,6 +1132,24 @@ rasterize1 (const db::Region *region, const db::Point &origin, const db::Vector return rasterize2 (region, origin, pixel_size, pixel_size, nx, ny); } +static tl::Variant begin_shapes_rec (const db::Region *region) +{ + auto res = region->begin_iter (); + tl::Variant r = tl::Variant (std::vector ()); + r.push (tl::Variant (res.first)); + r.push (tl::Variant (res.second)); + return r; +} + +static tl::Variant begin_merged_shapes_rec (const db::Region *region) +{ + auto res = region->begin_merged_iter (); + tl::Variant r = tl::Variant (std::vector ()); + r.push (tl::Variant (res.first)); + r.push (tl::Variant (res.second)); + return r; +} + static db::Point default_origin; // provided by gsiDeclDbPolygon.cc: @@ -3757,7 +3775,32 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "metal1_all_nets = metal1.nets\n" "@/code\n" "\n" - "This method was introduced in version 0.28.4" + "This method was introduced in version 0.28.4." + ) + + gsi::method_ext ("begin_shapes_rec", &begin_shapes_rec, + "@brief Returns a recursive shape iterator plus a transformation for the shapes constituting this region.\n" + "This method returns a pair consisting of a \\RecursiveShapeIterator plus a \\ICplxTrans transformation. " + "Both objects allow accessing the shapes (polygons) of the region in a detailed fashion. To iterate the " + "the polygons use a code like this:\n" + "\n" + "@code\n" + "iter, trans = region.begin_shapes_rec\n" + "iter.each do |i|\n" + " polygon = trans * iter.trans * i.shape.polygon\n" + " ...\n" + "end\n" + "@/code\n" + "\n" + "This method is the most powerful way of accessing the shapes inside the region. I allows for example to obtain the " + "properties attached to the polygons of the region. It is primarily intended for special applications like iterating net-annotated shapes.\n" + "\n" + "This speciality method was introduced in version 0.29.5." + ) + + gsi::method_ext ("begin_merged_shapes_rec", &begin_merged_shapes_rec, + "@brief Returns a recursive shape iterator plus a transformation for the shapes constituting the merged region.\n" + "It can be used like \\begin_shapes_rec, but delivers shapes from the merged polygons pool.\n" + "\n" + "This speciality method was introduced in version 0.29.5." ) + gsi::make_property_methods () , diff --git a/testdata/python/dbRegionTest.py b/testdata/python/dbRegionTest.py index 7a2e3af3c..3384f933a 100644 --- a/testdata/python/dbRegionTest.py +++ b/testdata/python/dbRegionTest.py @@ -81,6 +81,31 @@ class DBRegionTest(unittest.TestCase): dss = None self.assertEqual(pya.DeepShapeStore.instance_count(), 0) + # begin_shapes_rec and begin_shapes_merged_rec + def test_extended_iter(self): + + r = pya.Region() + + # NOTE: this also tests the copy semantics of the RecursiveShape to Variant binding in RBA: + it, trans = r.begin_shapes_rec() + s = ",".join([ str(trans*i.trans()*i.shape().polygon) for i in it.each() ]) + self.assertEqual(s, "") + + it, trans = r.begin_merged_shapes_rec() + s = ",".join([ str(trans*i.trans()*i.shape().polygon) for i in it.each() ]) + self.assertEqual(s, "") + + r.insert(pya.Box(0, 0, 100, 100)) + r.insert(pya.Box(50, 50, 200, 200)) + + it, trans = r.begin_shapes_rec() + s = ",".join([ str(trans*i.trans()*i.shape().polygon) for i in it.each() ]) + self.assertEqual(s, "(0,0;0,100;100,100;100,0),(50,50;50,200;200,200;200,50)") + + it, trans = r.begin_merged_shapes_rec() + s = ",".join([ str(trans*i.trans()*i.shape().polygon) for i in it.each() ]) + self.assertEqual(s, "(0,0;0,100;50,100;50,200;200,200;200,50;100,50;100,0)") + # run unit tests if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(DBRegionTest) diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index cd4546c7c..149c23171 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -1471,6 +1471,33 @@ class DBRegion_TestClass < TestBase end + # begin_shapes_rec and begin_shapes_merged_rec + def test_extended_iter + + r = RBA::Region::new() + + # NOTE: this also tests the copy semantics of the RecursiveShape to Variant binding in RBA: + iter, trans = r.begin_shapes_rec + str = iter.each.collect { |i| (trans*i.trans*i.shape.polygon).to_s }.join(",") + assert_equal(str, "") + + iter, trans = r.begin_merged_shapes_rec + str = iter.each.collect { |i| (trans*i.trans*i.shape.polygon).to_s }.join(",") + assert_equal(str, "") + + r.insert(RBA::Box::new(0, 0, 100, 100)) + r.insert(RBA::Box::new(50, 50, 200, 200)) + + iter, trans = r.begin_shapes_rec + str = iter.each.collect { |i| (trans*i.trans*i.shape.polygon).to_s }.join(",") + assert_equal(str, "(0,0;0,100;100,100;100,0),(50,50;50,200;200,200;200,50)") + + iter, trans = r.begin_merged_shapes_rec + str = iter.each.collect { |i| (trans*i.trans*i.shape.polygon).to_s }.join(",") + assert_equal(str, "(0,0;0,100;50,100;50,200;200,200;200,50;100,50;100,0)") + + end + end load("test_epilogue.rb")