Adding 'merge_props' and 'merged_props' to DRC

This commit is contained in:
Matthias Koefferlein 2025-08-02 16:12:49 +02:00
parent f9ea9af466
commit ffafebcaae
10 changed files with 109 additions and 33 deletions

View File

@ -33,7 +33,7 @@ RegionDelegate::RegionDelegate ()
m_base_verbosity = 30;
m_report_progress = false;
m_merged_semantics = true;
m_join_properties_on_merge = true;
m_join_properties_on_merge = false;
m_strict_handling = false;
m_merge_min_coherence = false;
}

View File

@ -1059,9 +1059,9 @@ static void break_polygons (db::Region *r, size_t max_vertex_count, double max_a
r->process (db::PolygonBreaker (max_vertex_count, max_area_ratio));
}
static db::Region &merge_ext1 (db::Region *r, int min_wc, bool jpm)
static db::Region &merge_ext1 (db::Region *r, int min_wc)
{
r->merge (false, std::max (0, min_wc - 1), jpm);
r->merge (false, std::max (0, min_wc - 1));
return *r;
}
@ -1071,9 +1071,9 @@ static db::Region &merge_ext2 (db::Region *r, bool min_coherence, int min_wc, bo
return *r;
}
static db::Region merged_ext1 (db::Region *r, int min_wc, bool jpm)
static db::Region merged_ext1 (db::Region *r, int min_wc)
{
return r->merged (false, std::max (0, min_wc - 1), jpm);
return r->merged (false, std::max (0, min_wc - 1));
}
static db::Region merged_ext2 (db::Region *r, bool min_coherence, int min_wc, bool jpm)
@ -1747,14 +1747,13 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
method ("join_properties_on_merge=", &db::Region::set_join_properties_on_merge, gsi::arg ("f"),
"@brief Sets a flag indication whether to join properties on merge\n"
"\n"
"When this flag is set to true (the default), properties are joined on 'merge'.\n"
"When this flag is set to true, properties are joined on 'merge'.\n"
"That is: shapes merging into bigger shapes will have their properties joined.\n"
"With the flag set to false, 'merge' will not join properties and return merged\n"
"With the flag set to false (the default), 'merge' will not join properties and return merged\n"
"shapes only if the sub-shapes have the same properties - i.e. properties form\n"
"different classes on merge.\n"
"\n"
"This attribute has been introduced in version 0.30.3. The default has changed from 'don't join properties' to "
"'join properties' in that version."
"This attribute has been introduced in version 0.30.3."
) +
method ("join_properties_on_merge?", &db::Region::join_properties_on_merge,
"@brief Gets a flag indication whether to join properties on merge\n"
@ -2398,13 +2397,13 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"@return The region after it has been merged (self).\n"
"\n"
"Merging removes overlaps and joins touching polygons.\n"
"If the region is already merged, this method does nothing\n"
"If the region is already merged, this method does nothing.\n"
"This method will behave according to the settings of the \\min_coherence and \\join_properties_on_merge attributes."
) +
method_ext ("merge", &merge_ext1, gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
method_ext ("merge", &merge_ext1, gsi::arg ("min_wc"),
"@brief Merge the region with options\n"
"\n"
"@param min_wc Overlap selection\n"
"@param join_properties_on_merge See below\n"
"@return The region after it has been merged (self).\n"
"\n"
"Merging removes overlaps and joins touching polygons.\n"
@ -2412,16 +2411,9 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"polygons overlap. The value specifies the number of polygons that need to overlap. A value of 2 "
"means that output is only produced if two or more polygons overlap.\n"
"\n"
"The 'join_properties_on_merge' argument indicates how properties should be handled: if true, "
"the properties of the constituents are joined and attached to the merged shape. If false, "
"only shapes with the same properties are merged - i.e. different properties form shape classes "
"that are merged individually.\n"
"\n"
"This method is equivalent to \"merge(false, min_wc, join_properties_on_merge).\n"
"\n"
"'join_properties_on_merge' has been added in version 0.30.3."
"This method is equivalent to \"merge(false, min_wc, false).\n"
) +
method_ext ("merge", &merge_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
method_ext ("merge", &merge_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", false),
"@brief Merge the region with options\n"
"\n"
"@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n"
@ -2449,24 +2441,24 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"Merging removes overlaps and joins touching polygons.\n"
"If the region is already merged, this method does nothing.\n"
"This method will behave according to the settings of the \\min_coherence and \\join_properties_on_merge attributes.\n"
"In contrast to \\merge, this method does not modify the region but returns a merged copy.\n"
) +
method_ext ("merged", &merged_ext1, gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
method_ext ("merged", &merged_ext1, gsi::arg ("min_wc"),
"@brief Returns the merged region (with options)\n"
"\n"
"@param min_wc Overlap selection\n"
"@param join_properties_on_merge See below\n"
"@return The region after it has been merged.\n"
"\n"
"This version provides one additional options: \"min_wc\" controls whether output is only produced if multiple "
"polygons overlap. The value specifies the number of polygons that need to overlap. A value of 2 "
"means that output is only produced if two or more polygons overlap.\n"
"\n"
"This method is equivalent to \"merged(false, min_wc, join_properties_on_merge)\".\n"
"This method is equivalent to \"merged(false, min_wc, false)\".\n"
"\n"
"In contrast to \\merge, this method does not modify the region but returns a merged copy.\n"
) +
method_ext ("merged", &merged_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
method_ext ("merged", &merged_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", false),
"@brief Returns the merged region (with options)\n"
"\n"
"@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n"

View File

@ -2151,6 +2151,8 @@ TEST(40_BoolWithProperties)
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1, dss);
EXPECT_EQ (r1.join_properties_on_merge (), false);
r1.set_join_properties_on_merge (true);
EXPECT_EQ (r1.join_properties_on_merge (), true);
r1.set_join_properties_on_merge (false);
EXPECT_EQ (r1.join_properties_on_merge (), false);

View File

@ -5103,18 +5103,66 @@ CODE
# Like \merged, but modifies the input and returns a reference to the
# new layer.
def merged(*args)
def merged(overlap_count = 1)
@engine._context("merged") do
requires_edges_or_region
aa = args.collect { |a| @engine._prep_value(a) }
aa = [ @engine._prep_value(overlap_count) ]
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :merged, *aa))
end
end
def merge(*args)
def merge(overlap_count = 1)
@engine._context("merge") do
requires_edges_or_region
aa = args.collect { |a| @engine._prep_value(a) }
aa = [ @engine._prep_value(overlap_count) ]
if @engine.is_tiled?
# in tiled mode, no modifying versions are available
self.data = @engine._tcmd(self.data, 0, self.data.class, :merged, *aa)
else
@engine._tcmd(self.data, 0, self.data.class, :merge, *aa)
end
self
end
end
# %DRC%
# @name merged_props
# @brief Merges and joins properties of the shapes
# @synopsis layer.merged_props([overlap_count])
#
# Returns the merged input. Unlike the plain \merged method, this version
# will join properties on merged shapes. Properties with the same name
# will be merged by computing the maximum value of the parts.
#
# For example:
# Properties @tt { "A" => 17, "C" => 2.5 } @/tt merged with @tt { "A" => 1, "B" => "a text" } @/tt will give
# @tt { "A" => 17, "B" => "a text", "C" => 2.5 } @/tt.
#
# The plain \merged method will treat shapes with different properties as
# separate entities and will not merge them.
#
# Currently, this method is available for polygon layers only.
# %DRC%
# @name merge_props
# @brief Merges the layer and joins the properties (modifies the layer)
# @synopsis layer.merge_props([overlap_count])
#
# Like \merged_props, but modifies the input and returns a reference to the
# new layer.
def merged_props(overlap_count = 1)
@engine._context("merged") do
requires_region
aa = [ self.data.min_coherence, @engine._prep_value(overlap_count), true ]
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :merged, *aa))
end
end
def merge_props(overlap_count = 1)
@engine._context("merge") do
requires_region
aa = [ self.data.min_coherence, @engine._prep_value(overlap_count), true ]
if @engine.is_tiled?
# in tiled mode, no modifying versions are available
self.data = @engine._tcmd(self.data, 0, self.data.class, :merged, *aa)

View File

@ -2003,3 +2003,13 @@ TEST(140d_target_modification)
{
run_test (_this, "140", true);
}
TEST(141_merge_properties)
{
run_test (_this, "141", false);
}
TEST(141d_merge_properties)
{
run_test (_this, "141", true);
}

24
testdata/drc/drcSimpleTests_141.drc vendored Normal file
View File

@ -0,0 +1,24 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
l1 = input(1, 0, enable_props)
l1.output(1, 0)
l1.merged_props.output(10, 0)
l1d = l1.dup
l1d.merge_props
l1d.output(11, 0)
l1.merged_props(2).output(20, 0)
l1d = l1.dup
l1d.merge_props(2)
l1d.output(21, 0)

BIN
testdata/drc/drcSimpleTests_141.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au141.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au141d.gds vendored Normal file

Binary file not shown.

View File

@ -1637,12 +1637,12 @@ class DBRegion_TestClass < TestBase
s = r.each.collect(&:to_s).join(";")
assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}")
rr = r.dup
rr.join_properties_on_merge = false
assert_equal(rr.join_properties_on_merge, false)
rr.join_properties_on_merge = true
assert_equal(rr.join_properties_on_merge, true)
s = rr.each_merged.collect(&:to_s).join(";")
assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}")
s = r.each_merged.collect(&:to_s).join(";")
assert_equal(s, "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0) props={1=>one}")
s = r.each_merged.collect(&:to_s).join(";")
assert_equal(s, "(10,20;10,220;110,220;110,20) props={};(0,0;0,200;100,200;100,0) props={1=>one}")
r = RBA::Region::new
r.insert(RBA::BoxWithProperties::new(RBA::Box::new(0, 0, 100, 200), { 1 => "one" }))