WIP: hardening FlatRegion against min_coherence toggles (IHP PDK optimization)

This commit is contained in:
Matthias Koefferlein 2026-07-22 22:30:09 +02:00
parent 7ed80e6dd8
commit 51f39d71e2
5 changed files with 213 additions and 29 deletions

View File

@ -1349,7 +1349,7 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
} }
RegionDelegate * RegionDelegate *
AsIfFlatRegion::merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) const AsIfFlatRegion::merged (bool min_coh, unsigned int min_wc, bool join_properties_on_merge) const
{ {
if (empty ()) { if (empty ()) {
@ -1366,8 +1366,8 @@ AsIfFlatRegion::merged (bool min_coherence, unsigned int min_wc, bool join_prope
} else { } else {
std::unique_ptr<FlatRegion> new_region (new FlatRegion (true)); std::unique_ptr<FlatRegion> new_region (new FlatRegion (true, 0, 0, min_coh));
merge_polygons_to (new_region->raw_polygons (), min_coherence, min_wc, join_properties_on_merge); merge_polygons_to (new_region->raw_polygons (), min_coh, min_wc, join_properties_on_merge);
return new_region.release (); return new_region.release ();

View File

@ -45,34 +45,43 @@ FlatRegion::FlatRegion (const FlatRegion &other)
m_area_ratio (other.m_area_ratio), m_max_vertex_count (other.m_max_vertex_count) m_area_ratio (other.m_area_ratio), m_max_vertex_count (other.m_max_vertex_count)
{ {
init (); init ();
set_min_coherence (other.min_coherence ());
m_is_merged = other.m_is_merged; m_is_merged = other.m_is_merged;
m_is_merged_min_coherence = other.m_is_merged_min_coherence;
m_merged_polygons_valid = other.m_merged_polygons_valid; m_merged_polygons_valid = other.m_merged_polygons_valid;
m_merged_polygons_min_coherence = other.m_merged_polygons_min_coherence;
} }
FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged, double area_ratio, size_t max_vertex_count) FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged, double area_ratio, size_t max_vertex_count, bool min_coh)
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)), : MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)),
m_area_ratio (area_ratio), m_max_vertex_count (max_vertex_count) m_area_ratio (area_ratio), m_max_vertex_count (max_vertex_count)
{ {
init (); init ();
set_min_coherence (min_coh);
m_is_merged = is_merged; m_is_merged = is_merged;
m_is_merged_min_coherence = min_coh;
} }
FlatRegion::FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged, double area_ratio, size_t max_vertex_count) FlatRegion::FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged, double area_ratio, size_t max_vertex_count, bool min_coh)
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)), : MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)),
m_area_ratio (area_ratio), m_max_vertex_count (max_vertex_count) m_area_ratio (area_ratio), m_max_vertex_count (max_vertex_count)
{ {
init (); init ();
set_min_coherence (min_coh);
m_is_merged = is_merged; m_is_merged = is_merged;
m_is_merged_min_coherence = min_coh;
transform_generic (trans); transform_generic (trans);
set_merged_semantics (merged_semantics); set_merged_semantics (merged_semantics);
} }
FlatRegion::FlatRegion (bool is_merged, double area_ratio, size_t max_vertex_count) FlatRegion::FlatRegion (bool is_merged, double area_ratio, size_t max_vertex_count, bool min_coh)
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false)), : MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false)),
m_area_ratio (area_ratio), m_max_vertex_count (max_vertex_count) m_area_ratio (area_ratio), m_max_vertex_count (max_vertex_count)
{ {
init (); init ();
set_min_coherence (min_coh);
m_is_merged = is_merged; m_is_merged = is_merged;
m_is_merged_min_coherence = min_coh;
} }
FlatRegion::~FlatRegion () FlatRegion::~FlatRegion ()
@ -83,6 +92,7 @@ FlatRegion::~FlatRegion ()
void FlatRegion::set_is_merged (bool m) void FlatRegion::set_is_merged (bool m)
{ {
m_is_merged = m; m_is_merged = m;
m_is_merged_min_coherence = min_coherence ();
} }
void FlatRegion::invalidate_cache () void FlatRegion::invalidate_cache ()
@ -95,7 +105,9 @@ void FlatRegion::invalidate_cache ()
void FlatRegion::init () void FlatRegion::init ()
{ {
m_is_merged = false; m_is_merged = false;
m_is_merged_min_coherence = false;
m_merged_polygons_valid = false; m_merged_polygons_valid = false;
m_merged_polygons_min_coherence = false;
} }
void FlatRegion::merged_semantics_changed () void FlatRegion::merged_semantics_changed ()
@ -112,9 +124,7 @@ void FlatRegion::join_properties_on_merge_changed ()
void FlatRegion::min_coherence_changed () void FlatRegion::min_coherence_changed ()
{ {
m_is_merged = false; // merged status is tracked in separate variables and is validated on inquiry
mp_merged_polygons->clear ();
m_merged_polygons_valid = false;
} }
void FlatRegion::reserve (size_t n) void FlatRegion::reserve (size_t n)
@ -122,12 +132,25 @@ void FlatRegion::reserve (size_t n)
mp_polygons->reserve (db::Polygon::tag (), n); mp_polygons->reserve (db::Polygon::tag (), n);
} }
bool
FlatRegion::merged_polygons_valid () const
{
return m_merged_polygons_valid && m_merged_polygons_min_coherence == min_coherence ();
}
bool
FlatRegion::merged_polygons_available () const
{
return is_merged () || merged_polygons_valid ();
}
void void
FlatRegion::ensure_merged_polygons_valid () const FlatRegion::ensure_merged_polygons_valid () const
{ {
if (! m_merged_polygons_valid) { if (! merged_polygons_valid ()) {
merge_polygons_to (*mp_merged_polygons, min_coherence (), 0, join_properties_on_merge ()); merge_polygons_to (*mp_merged_polygons, min_coherence (), 0, join_properties_on_merge ());
m_merged_polygons_valid = true; m_merged_polygons_valid = true;
m_merged_polygons_min_coherence = min_coherence ();
} }
} }
@ -140,7 +163,9 @@ FlatRegion::ensure_unmerged_polygons_valid () const
mp_merged_polygons.reset (new db::Shapes (*mp_polygons)); mp_merged_polygons.reset (new db::Shapes (*mp_polygons));
m_merged_polygons_valid = true; m_merged_polygons_valid = true;
m_merged_polygons_min_coherence = m_is_merged_min_coherence;
m_is_merged = false; m_is_merged = false;
m_is_merged_min_coherence = min_coherence ();
break_polygons (*mp_polygons, m_max_vertex_count, m_area_ratio); break_polygons (*mp_polygons, m_max_vertex_count, m_area_ratio);
} }
@ -152,7 +177,7 @@ RegionIteratorDelegate *FlatRegion::begin () const
RegionIteratorDelegate *FlatRegion::begin_merged () const RegionIteratorDelegate *FlatRegion::begin_merged () const
{ {
if (! merged_semantics () || m_is_merged) { if (! merged_semantics () || is_merged ()) {
return begin (); return begin ();
} else { } else {
ensure_merged_polygons_valid (); ensure_merged_polygons_valid ();
@ -173,7 +198,7 @@ std::pair<db::RecursiveShapeIterator, db::ICplxTrans> FlatRegion::begin_iter ()
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> FlatRegion::begin_merged_iter () const std::pair<db::RecursiveShapeIterator, db::ICplxTrans> FlatRegion::begin_merged_iter () const
{ {
if (! merged_semantics () || m_is_merged) { if (! merged_semantics () || is_merged ()) {
return begin_iter (); return begin_iter ();
} else { } else {
ensure_merged_polygons_valid (); ensure_merged_polygons_valid ();
@ -204,7 +229,7 @@ size_t FlatRegion::hier_count () const
bool FlatRegion::is_merged () const bool FlatRegion::is_merged () const
{ {
return m_is_merged; return m_is_merged && m_is_merged_min_coherence == min_coherence ();
} }
Box FlatRegion::compute_bbox () const Box FlatRegion::compute_bbox () const
@ -246,6 +271,7 @@ RegionDelegate *FlatRegion::filter_in_place (const PolygonFilterBase &filter)
mp_merged_polygons->clear (); mp_merged_polygons->clear ();
invalidate_cache (); invalidate_cache ();
m_is_merged = filter.requires_raw_input () ? false : merged_semantics (); m_is_merged = filter.requires_raw_input () ? false : merged_semantics ();
m_is_merged_min_coherence = min_coherence ();
return this; return this;
} }
@ -276,6 +302,7 @@ RegionDelegate *FlatRegion::process_in_place (const PolygonProcessorBase &filter
mp_merged_polygons->clear (); mp_merged_polygons->clear ();
invalidate_cache (); invalidate_cache ();
m_is_merged = filter.result_is_merged () && merged_semantics (); m_is_merged = filter.result_is_merged () && merged_semantics ();
m_is_merged_min_coherence = min_coherence ();
if (filter.result_must_not_be_merged ()) { if (filter.result_must_not_be_merged ()) {
set_merged_semantics (false); set_merged_semantics (false);
@ -286,14 +313,15 @@ RegionDelegate *FlatRegion::process_in_place (const PolygonProcessorBase &filter
RegionDelegate *FlatRegion::merged_in_place () RegionDelegate *FlatRegion::merged_in_place ()
{ {
if (! m_is_merged) { if (! is_merged ()) {
if (m_merged_polygons_valid) { if (merged_polygons_valid ()) {
db::Shapes &merged_polygons = *mp_merged_polygons; db::Shapes &merged_polygons = *mp_merged_polygons;
mp_polygons->swap (merged_polygons); mp_polygons->swap (merged_polygons);
merged_polygons.clear (); merged_polygons.clear ();
m_is_merged = true; m_is_merged = true;
m_is_merged_min_coherence = min_coherence ();
return this; return this;
} else { } else {
@ -305,7 +333,7 @@ RegionDelegate *FlatRegion::merged_in_place ()
} }
} }
RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) RegionDelegate *FlatRegion::merged_in_place (bool min_coh, unsigned int min_wc, bool join_properties_on_merge)
{ {
if (empty ()) { if (empty ()) {
@ -322,9 +350,11 @@ RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int mi
} else { } else {
invalidate_cache (); invalidate_cache ();
merge_polygons_to (*mp_polygons, min_coherence, min_wc, join_properties_on_merge); merge_polygons_to (*mp_polygons, min_coh, min_wc, join_properties_on_merge);
set_min_coherence (min_coh);
m_is_merged = true; m_is_merged = true;
m_is_merged_min_coherence = min_coh;
} }
@ -333,19 +363,35 @@ RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int mi
RegionDelegate *FlatRegion::merged () const RegionDelegate *FlatRegion::merged () const
{ {
if (! m_is_merged) { if (! is_merged ()) {
if (m_merged_polygons_valid) { if (! merged_polygons_valid ()) {
return new FlatRegion (*mp_merged_polygons, true); ensure_merged_polygons_valid ();
} else {
return AsIfFlatRegion::merged (min_coherence (), 0, join_properties_on_merge ());
} }
std::unique_ptr<FlatRegion> new_region (new FlatRegion (*mp_merged_polygons, true, 0, 0, min_coherence ()));
new_region->set_max_vertex_count (m_max_vertex_count);
new_region->set_area_ratio (m_area_ratio);
return new_region.release ();
} else { } else {
return clone (); return clone ();
} }
} }
RegionDelegate *FlatRegion::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);
new_region->set_max_vertex_count (m_max_vertex_count);
new_region->set_area_ratio (m_area_ratio);
return new_region.release ();
}
RegionDelegate *FlatRegion::add (const Region &other) const RegionDelegate *FlatRegion::add (const Region &other) const
{ {
std::unique_ptr<FlatRegion> new_region (new FlatRegion (*this)); std::unique_ptr<FlatRegion> new_region (new FlatRegion (*this));

View File

@ -52,9 +52,9 @@ public:
typedef polygon_layer_wp_type::iterator polygon_iterator_wp_type; typedef polygon_layer_wp_type::iterator polygon_iterator_wp_type;
FlatRegion (double area_ratio = 0.0, size_t max_vertex_count = 0); FlatRegion (double area_ratio = 0.0, size_t max_vertex_count = 0);
FlatRegion (const db::Shapes &polygons, bool is_merged = false, double area_ratio = 0.0, size_t max_vertex_count = 0); FlatRegion (const db::Shapes &polygons, bool is_merged = false, double area_ratio = 0.0, size_t max_vertex_count = 0, bool min_coh = false);
FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged = false, double area_ratio = 0.0, size_t max_vertex_count = 0); FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged = false, double area_ratio = 0.0, size_t max_vertex_count = 0, bool min_coh = false);
FlatRegion (bool is_merged, double area_ratio = 0.0, size_t max_vertex_count = 0); FlatRegion (bool is_merged, double area_ratio = 0.0, size_t max_vertex_count = 0, bool min_coh = false);
FlatRegion (const FlatRegion &other); FlatRegion (const FlatRegion &other);
@ -85,10 +85,9 @@ public:
virtual RegionDelegate *merged_in_place (); virtual RegionDelegate *merged_in_place ();
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge); virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge);
virtual RegionDelegate *merged () const; virtual RegionDelegate *merged () const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc, bool join_properties_on_merge) 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, join_properties_on_merge); bool merged_polygons_available () const;
}
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter); virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter);
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter); virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter);
@ -138,6 +137,7 @@ protected:
virtual Box compute_bbox () const; virtual Box compute_bbox () const;
void invalidate_cache (); void invalidate_cache ();
void set_is_merged (bool m); void set_is_merged (bool m);
bool merged_polygons_valid () const;
private: private:
friend class AsIfFlatRegion; friend class AsIfFlatRegion;
@ -146,9 +146,11 @@ private:
FlatRegion &operator= (const FlatRegion &other); FlatRegion &operator= (const FlatRegion &other);
mutable bool m_is_merged; mutable bool m_is_merged;
mutable bool m_is_merged_min_coherence;
mutable tl::copy_on_write_ptr<db::Shapes> mp_polygons; mutable tl::copy_on_write_ptr<db::Shapes> mp_polygons;
mutable tl::copy_on_write_ptr<db::Shapes> mp_merged_polygons; mutable tl::copy_on_write_ptr<db::Shapes> mp_merged_polygons;
mutable bool m_merged_polygons_valid; mutable bool m_merged_polygons_valid;
mutable bool m_merged_polygons_min_coherence;
double m_area_ratio; double m_area_ratio;
size_t m_max_vertex_count; size_t m_max_vertex_count;
@ -156,6 +158,16 @@ private:
void ensure_merged_polygons_valid () const; void ensure_merged_polygons_valid () const;
void ensure_unmerged_polygons_valid () const; void ensure_unmerged_polygons_valid () const;
void set_area_ratio (double ar)
{
m_area_ratio = ar;
}
void set_max_vertex_count (size_t mc)
{
m_max_vertex_count = mc;
}
template <class Trans> template <class Trans>
void transform_generic (const Trans &trans) void transform_generic (const Trans &trans)
{ {

View File

@ -2033,6 +2033,131 @@ TEST(44_SizeWithProperties)
db::compare_layouts (_this, target, tl::testdata () + "/algo/flat_region_au44.gds"); db::compare_layouts (_this, target, tl::testdata () + "/algo/flat_region_au44.gds");
} }
TEST(45_min_coherence_and_merge)
{
// NOTE: with an explicit area ratio and max vertex count we can play with unmerged input
db::Region r1 (new db::FlatRegion (3.0, 32));
r1.insert (db::Box (0, 0, 1000, 2000));
r1.insert (db::Box (1000, 2000, 10000, 3000));
r1.insert (db::Box (9000, 3000, 10000, 10000));
EXPECT_EQ (r1.min_coherence (), false);
EXPECT_EQ (r1.is_merged (), false);
EXPECT_EQ (dynamic_cast<const db::FlatRegion *> (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::FlatRegion *> (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::FlatRegion *> (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::FlatRegion *> (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::FlatRegion *> (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::FlatRegion *> (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::FlatRegion *> (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)");
// unmerge after resetting min coherence
r3 = r2;
r3.set_min_coherence (false);
EXPECT_EQ (r3.is_merged (), true);
r3.begin_unmerged ();
EXPECT_EQ (r3.is_merged (), false);
EXPECT_EQ (r3.to_string (), "(1000,2000;1000,3000;10000,3000;10000,2000);(9000,3000;9000,10000;10000,10000;10000,3000);(0,0;0,2000;1000,2000;1000,0)");
// r2 still remembers it is merged, even though it does not say so and
// will unmerge
r3 = r2;
EXPECT_EQ (r3.is_merged (), false);
// unmerge
r3.begin_unmerged ();
EXPECT_EQ (r3.is_merged (), false);
EXPECT_EQ (r3.to_string (), "(1000,2000;1000,3000;10000,3000;10000,2000);(9000,3000;9000,10000;10000,10000;10000,3000);(0,0;0,2000;1000,2000;1000,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) TEST(100_Issue1275)
{ {
db::Point pts[] = { db::Point pts[] = {

View File

@ -3400,6 +3400,7 @@ TEST(min_coherence_and_merge)
// inserting a box into the region will reset the merged valid flag and not bring it back by resetting min_coherence // 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; db::Region r3 = r1;
EXPECT_EQ (r3.min_coherence (), true);
r3.insert (db::Box (0, 0, 100, 100)); r3.insert (db::Box (0, 0, 100, 100));
r3.set_min_coherence (false); r3.set_min_coherence (false);
EXPECT_EQ (r3.is_merged (), false); EXPECT_EQ (r3.is_merged (), false);