This commit is contained in:
Matthias Koefferlein 2025-07-31 21:16:35 +02:00
parent 1ff6f36076
commit 653384fce5
13 changed files with 162 additions and 51 deletions

View File

@ -325,7 +325,8 @@ struct ComparePolygonsWithProperties
}
void AsIfFlatRegion::merge_polygons_to (db::Shapes &output, bool min_coherence, unsigned int min_wc) const
// @@@
void AsIfFlatRegion::merge_polygons_to (db::Shapes &output, bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const
{
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
@ -1241,7 +1242,7 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
}
RegionDelegate *
AsIfFlatRegion::merged (bool min_coherence, unsigned int min_wc) const
AsIfFlatRegion::merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const
{
if (empty ()) {
@ -1259,7 +1260,7 @@ AsIfFlatRegion::merged (bool min_coherence, unsigned int min_wc) const
} else {
std::unique_ptr<FlatRegion> new_region (new FlatRegion (true));
merge_polygons_to (new_region->raw_polygons (), min_coherence, min_wc);
merge_polygons_to (new_region->raw_polygons (), min_coherence, min_wc, join_properties_on_merge);
return new_region.release ();

View File

@ -108,17 +108,17 @@ public:
return merged ();
}
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc)
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge)
{
return merged (min_coherence, min_wc);
return merged (min_coherence, min_wc, join_properties_on_merge);
}
virtual RegionDelegate *merged () const
{
return merged (min_coherence (), 0);
return merged (min_coherence (), 0, join_properties_on_merge ());
}
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const;
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
@ -288,7 +288,7 @@ public:
protected:
void update_bbox (const db::Box &box);
void invalidate_bbox ();
void merge_polygons_to (db::Shapes &output, bool min_coherence, unsigned int min_wc) const;
void merge_polygons_to (db::Shapes &output, bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const;
RegionDelegate *and_or_not_with (bool is_and, const Region &other, PropertyConstraint property_constraint) const;
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;

View File

@ -231,6 +231,11 @@ void DeepRegion::min_coherence_changed ()
set_is_merged (false);
}
void DeepRegion::join_properties_on_merge_changed ()
{
set_is_merged (false);
}
void DeepRegion::do_insert (const db::Polygon &polygon, db::properties_id_type prop_id)
{
db::Layout &layout = deep_layer ().layout ();
@ -1742,10 +1747,10 @@ DeepRegion::merged_in_place ()
}
RegionDelegate *
DeepRegion::merged_in_place (bool min_coherence, unsigned int min_wc)
DeepRegion::merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge)
{
// TODO: implement to be really in-place
return merged (min_coherence, min_wc);
return merged (min_coherence, min_wc, join_properties_on_merge);
}
RegionDelegate *
@ -1770,8 +1775,9 @@ DeepRegion::merged () const
return res.release ();
}
// @@@
RegionDelegate *
DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
DeepRegion::merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const
{
if (empty ()) {
return clone ();

View File

@ -128,10 +128,10 @@ public:
virtual std::pair<RegionDelegate *, RegionDelegate *> filtered_pair (const PolygonFilterBase &filter) const;
virtual RegionDelegate *merged_in_place ();
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc);
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge);
virtual RegionDelegate *merged () const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const;
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
@ -155,6 +155,7 @@ public:
protected:
virtual void merged_semantics_changed ();
virtual void min_coherence_changed ();
virtual void join_properties_on_merge_changed ();
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;
virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;

View File

@ -92,9 +92,9 @@ public:
virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &) const;
virtual RegionDelegate *merged_in_place () { return this; }
virtual RegionDelegate *merged_in_place (bool, unsigned int) { return this; }
virtual RegionDelegate *merged_in_place (bool, unsigned int, bool) { return this; }
virtual RegionDelegate *merged () const { return new EmptyRegion (); }
virtual RegionDelegate *merged (bool, unsigned int) const { return new EmptyRegion (); }
virtual RegionDelegate *merged (bool, unsigned int, bool) const { return new EmptyRegion (); }
virtual RegionDelegate *sized (coord_type, unsigned int) const { return new EmptyRegion (); }
virtual RegionDelegate *sized (coord_type, coord_type, unsigned int) const { return new EmptyRegion (); }

View File

@ -99,6 +99,12 @@ void FlatRegion::merged_semantics_changed ()
m_merged_polygons_valid = false;
}
void FlatRegion::join_properties_on_merge_changed ()
{
mp_merged_polygons->clear ();
m_merged_polygons_valid = false;
}
void FlatRegion::min_coherence_changed ()
{
m_is_merged = false;
@ -115,7 +121,7 @@ void
FlatRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
merge_polygons_to (*mp_merged_polygons, min_coherence (), 0);
merge_polygons_to (*mp_merged_polygons, min_coherence (), 0, join_properties_on_merge ());
m_merged_polygons_valid = true;
}
}
@ -260,7 +266,7 @@ RegionDelegate *FlatRegion::merged_in_place ()
return this;
} else {
return merged_in_place (min_coherence (), 0);
return merged_in_place (min_coherence (), 0, join_properties_on_merge ());
}
} else {
@ -268,7 +274,8 @@ RegionDelegate *FlatRegion::merged_in_place ()
}
}
RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int min_wc)
// @@@
RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge)
{
if (empty ()) {
@ -285,7 +292,7 @@ RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int mi
} else {
invalidate_cache ();
merge_polygons_to (*mp_polygons, min_coherence, min_wc);
merge_polygons_to (*mp_polygons, min_coherence, min_wc, join_properties_on_merge);
m_is_merged = true;
@ -301,7 +308,7 @@ RegionDelegate *FlatRegion::merged () const
if (m_merged_polygons_valid) {
return new FlatRegion (*mp_merged_polygons, true);
} else {
return AsIfFlatRegion::merged (min_coherence (), 0);
return AsIfFlatRegion::merged (min_coherence (), 0, join_properties_on_merge ());
}
} else {

View File

@ -81,11 +81,11 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual RegionDelegate *merged_in_place ();
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc);
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge);
virtual RegionDelegate *merged () const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const
{
return db::AsIfFlatRegion::merged (min_coherence, min_wc);
return db::AsIfFlatRegion::merged (min_coherence, min_wc, join_properties_on_merge);
}
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter);
@ -131,6 +131,7 @@ public:
protected:
virtual void merged_semantics_changed ();
virtual void join_properties_on_merge_changed ();
virtual void min_coherence_changed ();
virtual Box compute_bbox () const;
void invalidate_cache ();

View File

@ -185,6 +185,13 @@ OriginalLayerRegion::merged_semantics_changed ()
m_merged_polygons_valid = false;
}
void
OriginalLayerRegion::join_properties_on_merge_changed ()
{
m_merged_polygons.clear ();
m_merged_polygons_valid = false;
}
void
OriginalLayerRegion::min_coherence_changed ()
{
@ -446,7 +453,7 @@ OriginalLayerRegion::ensure_merged_polygons_valid () const
if (! m_merged_polygons_valid) {
m_merged_polygons.clear ();
merge_polygons_to (m_merged_polygons, min_coherence (), 0);
merge_polygons_to (m_merged_polygons, min_coherence (), 0, join_properties_on_merge ());
m_merged_polygons_valid = true;

View File

@ -76,6 +76,7 @@ public:
protected:
virtual void merged_semantics_changed ();
virtual void join_properties_on_merge_changed ();
virtual void min_coherence_changed ();
private:

View File

@ -469,6 +469,28 @@ public:
return mp_delegate->merged_semantics ();
}
/**
* @brief Sets a flag indication whether to join properties on merge
*
* When this flag is set to true (the default), properties are joined on "merge".
* That is: shapes merging into bigger shapes will have their properties joined.
* With the flag set to false, "merge" will not join properties and return merged
* shapes only if the sub-shapes have the same properties - i.e. properties form
* different classes on merge.
*/
void set_join_properties_on_merge (bool f)
{
mp_delegate->set_join_properties_on_merge (f);
}
/**
* @brief Gets a flag indication whether to join properties on merge
*/
bool join_properties_on_merge () const
{
return mp_delegate->join_properties_on_merge ();
}
/**
* @brief Enables or disables strict handling
*
@ -969,12 +991,14 @@ public:
* This method will always execute the merge, even if the region is already merged.
*
* @param min_coherence Set this parameter to true to get minimum polygons (kissing corner problem)
* @param min_wrapcount See the description above
* @param min_wc See the description above
* @param join_properties_on_merge If true, merged shapes carry the joined properties of the constituents. Otherwise, only shapes with same properties get merged.
*
* @return A reference to this region
*/
Region &merge (bool min_coherence, unsigned int min_wc = 0)
Region &merge (bool min_coherence, unsigned int min_wc = 0, bool join_properties_on_merge = true)
{
set_delegate (mp_delegate->merged_in_place (min_coherence, min_wc));
set_delegate (mp_delegate->merged_in_place (min_coherence, min_wc, join_properties_on_merge));
return *this;
}
@ -983,9 +1007,9 @@ public:
*
* This is the out-of-place version of "merge" with options (see there).
*/
Region merged (bool min_coherence, unsigned int min_wc = 0) const
Region merged (bool min_coherence, unsigned int min_wc = 0, bool join_properties_on_merge = true) const
{
return Region (mp_delegate->merged (min_coherence, min_wc));
return Region (mp_delegate->merged (min_coherence, min_wc, join_properties_on_merge));
}
/**

View File

@ -33,6 +33,7 @@ RegionDelegate::RegionDelegate ()
m_base_verbosity = 30;
m_report_progress = false;
m_merged_semantics = true;
m_join_properties_on_merge = true;
m_strict_handling = false;
m_merge_min_coherence = false;
}
@ -50,6 +51,7 @@ RegionDelegate::operator= (const RegionDelegate &other)
m_base_verbosity = other.m_base_verbosity;
m_report_progress = other.m_report_progress;
m_merged_semantics = other.m_merged_semantics;
m_join_properties_on_merge = other.m_join_properties_on_merge;
m_strict_handling = other.m_strict_handling;
m_merge_min_coherence = other.m_merge_min_coherence;
}
@ -93,6 +95,14 @@ void RegionDelegate::set_merged_semantics (bool f)
}
}
void RegionDelegate::set_join_properties_on_merge (bool f)
{
if (f != m_join_properties_on_merge) {
m_join_properties_on_merge = f;
join_properties_on_merge_changed ();
}
}
void RegionDelegate::set_strict_handling (bool f)
{
m_strict_handling = f;

View File

@ -169,6 +169,12 @@ public:
return m_merged_semantics;
}
void set_join_properties_on_merge (bool f);
bool join_properties_on_merge () const
{
return m_join_properties_on_merge;
}
void set_strict_handling (bool f);
bool strict_handling () const
{
@ -223,9 +229,9 @@ public:
virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const = 0;
virtual RegionDelegate *merged_in_place () = 0;
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc) = 0;
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) = 0;
virtual RegionDelegate *merged () const = 0;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const = 0;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const = 0;
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const = 0;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const = 0;
@ -298,9 +304,11 @@ public:
protected:
virtual void merged_semantics_changed () { }
virtual void min_coherence_changed () { }
virtual void join_properties_on_merge_changed () { }
private:
bool m_merged_semantics;
bool m_join_properties_on_merge;
bool m_strict_handling;
bool m_merge_min_coherence;
bool m_report_progress;

View File

@ -1059,26 +1059,26 @@ 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)
static db::Region &merge_ext1 (db::Region *r, int min_wc, bool jpm)
{
r->merge (false, std::max (0, min_wc - 1));
r->merge (false, std::max (0, min_wc - 1), jpm);
return *r;
}
static db::Region &merge_ext2 (db::Region *r, bool min_coherence, int min_wc)
static db::Region &merge_ext2 (db::Region *r, bool min_coherence, int min_wc, bool jpm)
{
r->merge (min_coherence, std::max (0, min_wc - 1));
r->merge (min_coherence, std::max (0, min_wc - 1), jpm);
return *r;
}
static db::Region merged_ext1 (db::Region *r, int min_wc)
static db::Region merged_ext1 (db::Region *r, int min_wc, bool jpm)
{
return r->merged (false, std::max (0, min_wc - 1));
return r->merged (false, std::max (0, min_wc - 1), jpm);
}
static db::Region merged_ext2 (db::Region *r, bool min_coherence, int min_wc)
static db::Region merged_ext2 (db::Region *r, bool min_coherence, int min_wc, bool jpm)
{
return r->merged (min_coherence, std::max (0, min_wc - 1));
return r->merged (min_coherence, std::max (0, min_wc - 1), jpm);
}
static db::EdgePairs width2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
@ -1744,6 +1744,24 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"@brief Gets a flag indicating whether merged semantics is enabled\n"
"See \\merged_semantics= for a description of this attribute.\n"
) +
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"
"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"
"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."
) +
method ("join_properties_on_merge?", &db::Region::join_properties_on_merge,
"@brief Gets a flag indication whether to join properties on merge\n"
"See \\join_properties_on_merge= for a description of this attribute.\n"
"\n"
"This attribute has been introduced in version 0.30.3."
) +
method ("strict_handling=", &db::Region::set_strict_handling, gsi::arg ("f"),
"@brief Enables or disables strict handling\n"
"\n"
@ -2377,65 +2395,84 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
method ("merge", (db::Region &(db::Region::*) ()) &db::Region::merge,
"@brief Merge the region\n"
"\n"
"@return The region after is has been merged (self).\n"
"@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"
) +
method_ext ("merge", &merge_ext1, gsi::arg ("min_wc"),
method_ext ("merge", &merge_ext1, gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
"@brief Merge the region with options\n"
"\n"
"@param min_wc Overlap selection\n"
"@return The region after is has been merged (self).\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"
"This version provides one additional option: \"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 \"merge(false, min_wc).\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."
) +
method_ext ("merge", &merge_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"),
method_ext ("merge", &merge_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
"@brief Merge the region with options\n"
"\n"
"@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n"
"@param min_wc Overlap selection\n"
"@return The region after is has been merged (self).\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"
"This version provides two additional options: if \"min_coherence\" is set to true, \"kissing corners\" are "
"resolved by producing separate polygons. \"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"
"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"
"'join_properties_on_merge' has been added in version 0.30.3."
) +
method ("merged", (db::Region (db::Region::*) () const) &db::Region::merged,
"@brief Returns the merged region\n"
"\n"
"@return The region after is has been merged.\n"
"@return The region after it has been merged.\n"
"\n"
"Merging removes overlaps and joins touching polygons.\n"
"If the region is already merged, this method does nothing.\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"),
method_ext ("merged", &merged_ext1, gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
"@brief Returns the merged region (with options)\n"
"\n"
"@return The region after is has been merged.\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)\".\n"
"This method is equivalent to \"merged(false, min_wc, join_properties_on_merge)\".\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"),
method_ext ("merged", &merged_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"), gsi::arg ("join_properties_on_merge", true),
"@brief Returns the merged region (with options)\n"
"\n"
"@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n"
"@param min_wc Overlap selection\n"
"@return The region after is has been merged (self).\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"
"This version provides two additional options: if \"min_coherence\" is set to true, \"kissing corners\" are "
@ -2443,7 +2480,15 @@ 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"
"\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"
"In contrast to \\merge, this method does not modify the region but returns a merged copy.\n"
"\n"
"'join_properties_on_merge' has been added in version 0.30.3."
) +
method ("round_corners", &db::Region::round_corners, gsi::arg ("r_inner"), gsi::arg ("r_outer"), gsi::arg ("n"),
"@brief Corner rounding\n"