Adding support for min_coherence toggling in OriginalLayerRegion

This commit is contained in:
Matthias Koefferlein 2026-07-22 23:11:26 +02:00
parent 51f39d71e2
commit 9382e259ce
3 changed files with 181 additions and 12 deletions

View File

@ -142,28 +142,34 @@ OriginalLayerRegion::OriginalLayerRegion ()
OriginalLayerRegion::OriginalLayerRegion (const OriginalLayerRegion &other)
: AsIfFlatRegion (other),
m_is_merged (other.m_is_merged),
m_is_merged_min_coherence (other.m_is_merged_min_coherence),
m_merged_polygons (other.m_merged_polygons),
m_merged_polygons_valid (other.m_merged_polygons_valid),
m_merged_polygons_min_coherence (other.m_merged_polygons_min_coherence),
m_iter (other.m_iter),
m_iter_trans (other.m_iter_trans)
{
// .. nothing yet ..
}
OriginalLayerRegion::OriginalLayerRegion (const RecursiveShapeIterator &si, bool is_merged)
OriginalLayerRegion::OriginalLayerRegion (const RecursiveShapeIterator &si, bool is_merged, bool min_coh)
: AsIfFlatRegion (), m_merged_polygons (false), m_iter (si)
{
init ();
set_min_coherence (min_coh);
m_is_merged = is_merged;
m_is_merged_min_coherence = min_coh;
}
OriginalLayerRegion::OriginalLayerRegion (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged)
OriginalLayerRegion::OriginalLayerRegion (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged, bool min_coh)
: AsIfFlatRegion (), m_merged_polygons (false), m_iter (si), m_iter_trans (trans)
{
init ();
set_min_coherence (min_coh);
m_is_merged = is_merged;
m_is_merged_min_coherence = min_coh;
set_merged_semantics (merged_semantics);
}
@ -183,6 +189,7 @@ OriginalLayerRegion::merged_semantics_changed ()
{
m_merged_polygons.clear ();
m_merged_polygons_valid = false;
m_merged_polygons_min_coherence = false;
}
void
@ -190,14 +197,13 @@ OriginalLayerRegion::join_properties_on_merge_changed ()
{
m_merged_polygons.clear ();
m_merged_polygons_valid = false;
m_merged_polygons_min_coherence = false;
}
void
OriginalLayerRegion::min_coherence_changed ()
{
m_is_merged = false;
m_merged_polygons.clear ();
m_merged_polygons_valid = false;
// merged status is tracked in separate variables and is validated on inquiry
}
size_t
@ -309,7 +315,7 @@ OriginalLayerRegion::begin () const
RegionIteratorDelegate *
OriginalLayerRegion::begin_merged () const
{
if (! merged_semantics () || m_is_merged) {
if (! merged_semantics () || is_merged ()) {
return begin ();
} else {
ensure_merged_polygons_valid ();
@ -332,7 +338,7 @@ OriginalLayerRegion::begin_iter () const
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
OriginalLayerRegion::begin_merged_iter () const
{
if (! merged_semantics () || m_is_merged) {
if (! merged_semantics () || is_merged ()) {
return begin_iter ();
} else {
ensure_merged_polygons_valid ();
@ -346,6 +352,33 @@ OriginalLayerRegion::begin_unmerged_iter () const
return std::make_pair (m_iter, m_iter_trans);
}
RegionDelegate *
OriginalLayerRegion::merged () const
{
if (! is_merged ()) {
if (! merged_polygons_valid ()) {
ensure_merged_polygons_valid ();
}
std::unique_ptr<FlatRegion> new_region (new FlatRegion (m_merged_polygons, true, 0, 0, min_coherence ()));
return new_region.release ();
} else {
return clone ();
}
}
RegionDelegate *
OriginalLayerRegion::merged (bool min_coh, unsigned int min_wc, bool jp) const
{
std::unique_ptr<FlatRegion> new_region (new FlatRegion (true, 0, 0, min_coh));
merge_polygons_to (new_region->raw_polygons (), min_coh, min_wc, jp);
return new_region.release ();
}
bool
OriginalLayerRegion::empty () const
{
@ -355,7 +388,13 @@ OriginalLayerRegion::empty () const
bool
OriginalLayerRegion::is_merged () const
{
return m_is_merged;
return m_is_merged && m_is_merged_min_coherence == min_coherence ();
}
bool
OriginalLayerRegion::merged_polygons_valid () const
{
return m_merged_polygons_valid && m_merged_polygons_min_coherence == min_coherence ();
}
const db::Polygon *
@ -379,7 +418,7 @@ OriginalLayerRegion::has_valid_polygons () const
bool
OriginalLayerRegion::has_valid_merged_polygons () const
{
return merged_semantics () && ! m_is_merged;
return merged_semantics () && ! is_merged ();
}
const db::RecursiveShapeIterator *
@ -394,6 +433,7 @@ OriginalLayerRegion::apply_property_translator (const db::PropertiesTranslator &
m_iter.apply_property_translator (pt);
m_merged_polygons_valid = false;
m_merged_polygons_min_coherence = false;
m_merged_polygons.clear ();
}
@ -423,7 +463,9 @@ void
OriginalLayerRegion::init ()
{
m_is_merged = false;
m_is_merged_min_coherence = false;
m_merged_polygons_valid = false;
m_merged_polygons_min_coherence = false;
}
namespace {
@ -459,15 +501,22 @@ OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell,
}
}
bool
OriginalLayerRegion::merged_polygons_available () const
{
return is_merged () || merged_polygons_valid ();
}
void
OriginalLayerRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
if (! merged_polygons_valid ()) {
m_merged_polygons.clear ();
merge_polygons_to (m_merged_polygons, min_coherence (), 0, join_properties_on_merge ());
m_merged_polygons_valid = true;
m_merged_polygons_min_coherence = min_coherence ();
}
}

View File

@ -43,8 +43,8 @@ class DB_PUBLIC OriginalLayerRegion
public:
OriginalLayerRegion ();
OriginalLayerRegion (const OriginalLayerRegion &other);
OriginalLayerRegion (const RecursiveShapeIterator &si, bool is_merged = false);
OriginalLayerRegion (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged = false);
OriginalLayerRegion (const RecursiveShapeIterator &si, bool is_merged = false, bool min_coh = false);
OriginalLayerRegion (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged = false, bool min_coh = false);
virtual ~OriginalLayerRegion ();
RegionDelegate *clone () const;
@ -57,6 +57,11 @@ public:
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const;
virtual RegionDelegate *merged () const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const;
bool merged_polygons_available () const;
virtual bool empty () const;
virtual bool is_merged () const;
@ -85,13 +90,16 @@ private:
OriginalLayerRegion &operator= (const OriginalLayerRegion &other);
bool m_is_merged;
mutable bool m_is_merged_min_coherence;
mutable db::Shapes m_merged_polygons;
mutable bool m_merged_polygons_valid;
mutable bool m_merged_polygons_min_coherence;
mutable db::RecursiveShapeIterator m_iter;
db::ICplxTrans m_iter_trans;
void init ();
void ensure_merged_polygons_valid () const;
bool merged_polygons_valid () const;
};
}

View File

@ -2158,6 +2158,118 @@ TEST(45_min_coherence_and_merge)
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
}
TEST(46_min_coherence_and_merge_from_original)
{
db::Layout ly;
auto &top = ly.cell (ly.add_cell ("TOP"));
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
top.shapes (l1).insert (db::Box (0, 0, 1000, 2000));
top.shapes (l1).insert (db::Box (1000, 2000, 10000, 3000));
top.shapes (l1).insert (db::Box (9000, 3000, 10000, 10000));
db::Region r1 (db::RecursiveShapeIterator (ly, top, l1));
EXPECT_EQ (r1.min_coherence (), false);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::OriginalLayerRegion *> (r1.delegate ())->merged_polygons_available (), false);
EXPECT_EQ (r1.to_string (), "(0,0;0,2000;1000,2000;1000,0);(1000,2000;1000,3000;10000,3000;10000,2000);(9000,3000;9000,10000;10000,10000;10000,3000)");
// forces merged status
r1.sized (1);
EXPECT_EQ (r1.min_coherence (), false);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::OriginalLayerRegion *> (r1.delegate ())->merged_polygons_available (), true);
db::Region r2 = r1.merged ();
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
EXPECT_EQ (r2.min_coherence (), false);
EXPECT_EQ (r1.min_coherence (), false);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::OriginalLayerRegion *> (r1.delegate ())->merged_polygons_available (), true);
r1.set_min_coherence (true);
// valid_merged_polygons is invalidated
EXPECT_EQ (r1.min_coherence (), true);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::OriginalLayerRegion *> (r1.delegate ())->merged_polygons_available (), false);
r1.set_min_coherence (false);
// setting min_coherence to false will bring the validation back
EXPECT_EQ (r1.min_coherence (), false);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::OriginalLayerRegion *> (r1.delegate ())->merged_polygons_available (), true);
r1.set_min_coherence (true);
// valid_merged_polygons is invalidated again by setting min_coherence to true
EXPECT_EQ (r1.min_coherence (), true);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::OriginalLayerRegion *> (r1.delegate ())->merged_polygons_available (), false);
// inserting a box into the region will reset the merged valid flag and not bring it back by resetting min_coherence
db::Region r3 = r1;
r3.insert (db::Box (0, 0, 100, 100));
EXPECT_EQ (r3.min_coherence (), true);
r3.set_min_coherence (false);
EXPECT_EQ (r3.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::FlatRegion *> (r3.delegate ())->merged_polygons_available (), false);
// creates a intrinsically merged copy and tests if the min_coherence
// flag is inherited
r3 = r1.merged ();
EXPECT_EQ (r3.to_string (), "(0,0;0,2000;1000,2000;1000,0);(1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000)");
EXPECT_EQ (r3.is_merged (), true);
EXPECT_EQ (r3.min_coherence (), true);
// merged polygons are validated against min_coherence = true during r1.merged() before, so
// resetting min_coherence to false will invalidat them
r1.set_min_coherence (false);
EXPECT_EQ (r1.min_coherence (), false);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::OriginalLayerRegion *> (r1.delegate ())->merged_polygons_available (), false);
// creates a intrinsically merged copy and tests if the min_coherence
// flag is inherited
r3 = r1.merged ();
EXPECT_EQ (r3.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
EXPECT_EQ (r3.is_merged (), true);
EXPECT_EQ (r3.min_coherence (), false);
// r2 is an intrinsically merged region (with min coherence false)
EXPECT_EQ (r2.min_coherence (), false);
EXPECT_EQ (r2.is_merged (), true);
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
// after changing min_coherence, the merged status is no longer true
r2.set_min_coherence (true);
EXPECT_EQ (r2.min_coherence (), true);
EXPECT_EQ (r2.is_merged (), false);
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
// read-only experiments with r2
// inserting a box into the region will reset the merged state
// and not bring it back by resetting min_coherence
r3 = r2;
r3.insert (db::Box (0, 0, 100, 100));
r3.set_min_coherence (false);
EXPECT_EQ (r3.is_merged (), false);
EXPECT_EQ (r3.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0);(0,0;0,100;100,100;100,0)");
// r2 merged state it can be restored by resetting min_coherence to false
r2.set_min_coherence (false);
EXPECT_EQ (r2.min_coherence (), false);
EXPECT_EQ (r2.is_merged (), true);
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
}
TEST(100_Issue1275)
{
db::Point pts[] = {