mirror of https://github.com/KLayout/klayout.git
Potential performance improvement for deep-mode DRC
The idea is to use broken regions for certain operations such as booleans in deep mode (local operations). These polygons are more efficient. To support this, a "broken polygon" view is supplied similar for "merged" view. The translation is handled automatically. As a side effect, regions may appear to be composed in broken polygons now when they have been merged before.
This commit is contained in:
parent
95f2335fc4
commit
42a008efd1
|
|
@ -401,6 +401,13 @@ DeepRegion::begin_merged () const
|
|||
}
|
||||
}
|
||||
|
||||
RegionIteratorDelegate *
|
||||
DeepRegion::begin_unmerged () const
|
||||
{
|
||||
ensure_unmerged_polygons_valid ();
|
||||
return begin ();
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
|
||||
DeepRegion::begin_iter () const
|
||||
{
|
||||
|
|
@ -445,6 +452,13 @@ DeepRegion::begin_merged_iter () const
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
|
||||
DeepRegion::begin_unmerged_iter () const
|
||||
{
|
||||
ensure_unmerged_polygons_valid ();
|
||||
return begin_iter ();
|
||||
}
|
||||
|
||||
bool
|
||||
DeepRegion::empty () const
|
||||
{
|
||||
|
|
@ -787,6 +801,46 @@ DeepRegion::ensure_merged_polygons_valid () const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeepRegion::ensure_unmerged_polygons_valid () const
|
||||
{
|
||||
if (! m_is_merged ||
|
||||
(deep_layer ().store ()->max_area_ratio () == 0.0 && deep_layer ().store ()->max_vertex_count () == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_merged_polygons = deep_layer ().derived ();
|
||||
db::DeepLayer &polygons = const_cast<db::DeepLayer &> (deep_layer ());
|
||||
|
||||
m_merged_polygons_valid = true;
|
||||
m_is_merged = false;
|
||||
m_merged_polygons_boc_hash = deep_layer ().breakout_cells_hash ();
|
||||
|
||||
db::Layout &layout = polygons.layout ();
|
||||
polygons.swap (m_merged_polygons);
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
|
||||
db::Shapes &st = c->shapes (deep_layer ().layer ());
|
||||
|
||||
db::PolygonRefToShapesGenerator pr (&layout, &st);
|
||||
db::PolygonSplitter splitter (pr, polygons.store ()->max_area_ratio (), polygons.store ()->max_vertex_count ());
|
||||
|
||||
splitter.start ();
|
||||
for (auto p = s.begin (db::ShapeIterator::All); ! p.at_end (); ++p) {
|
||||
if (p->is_polygon ()) {
|
||||
pr.set_prop_id (p->prop_id ());
|
||||
db::Polygon poly;
|
||||
p->polygon (poly);
|
||||
splitter.put (poly);
|
||||
}
|
||||
}
|
||||
splitter.flush ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeepRegion::set_is_merged (bool f)
|
||||
{
|
||||
|
|
@ -922,6 +976,10 @@ DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constr
|
|||
DeepLayer
|
||||
DeepRegion::and_with_impl (const DeepRegion *other, db::PropertyConstraint property_constraint) const
|
||||
{
|
||||
// booleans run better on simple polygons
|
||||
ensure_unmerged_polygons_valid ();
|
||||
other->ensure_unmerged_polygons_valid ();
|
||||
|
||||
DeepLayer dl_out (deep_layer ().derived ());
|
||||
|
||||
if (pc_skip (property_constraint)) {
|
||||
|
|
@ -956,6 +1014,10 @@ DeepRegion::and_with_impl (const DeepRegion *other, db::PropertyConstraint prope
|
|||
DeepLayer
|
||||
DeepRegion::not_with_impl (const DeepRegion *other, db::PropertyConstraint property_constraint) const
|
||||
{
|
||||
// booleans run better on simple polygons
|
||||
ensure_unmerged_polygons_valid ();
|
||||
other->ensure_unmerged_polygons_valid ();
|
||||
|
||||
DeepLayer dl_out (deep_layer ().derived ());
|
||||
DeepLayer dl_prep;
|
||||
|
||||
|
|
@ -1059,6 +1121,10 @@ DeepRegion::not_with_impl (const DeepRegion *other, db::PropertyConstraint prope
|
|||
std::pair<DeepLayer, DeepLayer>
|
||||
DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
// booleans run better on simple polygons
|
||||
ensure_unmerged_polygons_valid ();
|
||||
other->ensure_unmerged_polygons_valid ();
|
||||
|
||||
DeepLayer dl_out1 (deep_layer ().derived ());
|
||||
DeepLayer dl_out2 (deep_layer ().derived ());
|
||||
|
||||
|
|
@ -1179,6 +1245,10 @@ DeepRegion::add_in_place (const Region &other)
|
|||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
if (other_deep) {
|
||||
|
||||
// NOTE: as we don't benefit from merged shapes here, we prefer unmerged ones
|
||||
// for potentially better performance.
|
||||
other_deep->ensure_unmerged_polygons_valid ();
|
||||
|
||||
deep_layer ().add_from (other_deep->deep_layer ());
|
||||
|
||||
} else {
|
||||
|
|
@ -1885,6 +1955,10 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
return clone ();
|
||||
}
|
||||
|
||||
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
|
||||
// overlap after size and are not necessarily merged)
|
||||
bool will_be_merged = (d < 0 && (merged_semantics () || is_merged ()));
|
||||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
|
@ -1904,7 +1978,8 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
db::PolygonRefToShapesGenerator pr (&layout, &st);
|
||||
db::PolygonGenerator pg2 (pr, false /*don't resolve holes*/, true /*min. coherence*/);
|
||||
db::PolygonSplitter splitter (pr, will_be_merged ? 0.0 : polygons.store ()->max_area_ratio (), will_be_merged ? 0 : polygons.store ()->max_vertex_count ());
|
||||
db::PolygonGenerator pg2 (splitter, false /*don't resolve holes*/, true /*min. coherence*/);
|
||||
db::SizingPolygonFilter siz (pg2, d_with_mag, d_with_mag, mode);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
|
|
@ -1916,11 +1991,7 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
|
||||
}
|
||||
|
||||
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
|
||||
// overlap after size and are not necessarily merged)
|
||||
if (d < 0 && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
res->set_is_merged (will_be_merged);
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
|
@ -1938,6 +2009,10 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
return sized (dx, mode);
|
||||
}
|
||||
|
||||
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
|
||||
// overlap after size and are not necessarily merged)
|
||||
bool will_be_merged = (dx < 0 && dy < 0 && (merged_semantics () || is_merged ()));
|
||||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
|
@ -1964,7 +2039,8 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
db::PolygonRefToShapesGenerator pr (&layout, &st);
|
||||
db::PolygonGenerator pg2 (pr, false /*don't resolve holes*/, true /*min. coherence*/);
|
||||
db::PolygonSplitter splitter (pr, will_be_merged ? 0.0 : polygons.store ()->max_area_ratio (), will_be_merged ? 0 : polygons.store ()->max_vertex_count ());
|
||||
db::PolygonGenerator pg2 (splitter, false /*don't resolve holes*/, true /*min. coherence*/);
|
||||
db::SizingPolygonFilter siz (pg2, dx_with_mag, dy_with_mag, mode);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
|
|
@ -1976,11 +2052,7 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
|
||||
}
|
||||
|
||||
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
|
||||
// overlap after size and are not necessarily merged)
|
||||
if (dx < 0 && dy < 0 && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
res->set_is_merged (will_be_merged);
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,9 +66,11 @@ public:
|
|||
|
||||
virtual RegionIteratorDelegate *begin () const;
|
||||
virtual RegionIteratorDelegate *begin_merged () const;
|
||||
virtual RegionIteratorDelegate *begin_unmerged () const;
|
||||
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const;
|
||||
|
||||
virtual bool empty () const;
|
||||
virtual bool is_merged () const;
|
||||
|
|
@ -176,10 +178,11 @@ private:
|
|||
mutable DeepLayer m_merged_polygons;
|
||||
mutable bool m_merged_polygons_valid;
|
||||
mutable size_t m_merged_polygons_boc_hash;
|
||||
bool m_is_merged;
|
||||
mutable bool m_is_merged;
|
||||
|
||||
void init ();
|
||||
void ensure_merged_polygons_valid () const;
|
||||
void ensure_unmerged_polygons_valid () const;
|
||||
DeepLayer not_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const;
|
||||
DeepLayer and_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const;
|
||||
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const;
|
||||
|
|
|
|||
|
|
@ -232,6 +232,14 @@ bool DeepLayer::operator== (const DeepLayer &other) const
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DeepLayer::swap (DeepLayer &other)
|
||||
{
|
||||
tl_assert (mp_store.get () == other.mp_store.get ());
|
||||
std::swap (m_layer, other.m_layer);
|
||||
std::swap (m_layout, other.m_layout);
|
||||
}
|
||||
|
||||
db::Layout &
|
||||
DeepLayer::layout ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -120,6 +120,11 @@ public:
|
|||
*/
|
||||
bool operator== (const DeepLayer &other) const;
|
||||
|
||||
/**
|
||||
* @brief Swap two layers
|
||||
*/
|
||||
void swap (DeepLayer &other);
|
||||
|
||||
/**
|
||||
* @brief Gets the layout object
|
||||
* The return value is guaranteed to be non-null.
|
||||
|
|
|
|||
|
|
@ -46,9 +46,11 @@ public:
|
|||
|
||||
virtual RegionIteratorDelegate *begin () const { return 0; }
|
||||
virtual RegionIteratorDelegate *begin_merged () const { return 0; }
|
||||
virtual RegionIteratorDelegate *begin_unmerged () const { return 0; }
|
||||
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const { return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ()); }
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const { return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ()); }
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const { return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ()); }
|
||||
|
||||
virtual bool empty () const { return true; }
|
||||
virtual size_t count () const { return 0; }
|
||||
|
|
|
|||
|
|
@ -33,29 +33,33 @@ namespace db
|
|||
// -------------------------------------------------------------------------------------------------------------
|
||||
// FlatRegion implementation
|
||||
|
||||
FlatRegion::FlatRegion ()
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false))
|
||||
FlatRegion::FlatRegion (double area_ratio, size_t max_vertex_count)
|
||||
: 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)
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
FlatRegion::FlatRegion (const FlatRegion &other)
|
||||
: MutableRegion (other), mp_polygons (other.mp_polygons), mp_merged_polygons (other.mp_merged_polygons)
|
||||
: MutableRegion (other), mp_polygons (other.mp_polygons), mp_merged_polygons (other.mp_merged_polygons),
|
||||
m_area_ratio (other.m_area_ratio), m_max_vertex_count (other.m_max_vertex_count)
|
||||
{
|
||||
init ();
|
||||
m_is_merged = other.m_is_merged;
|
||||
m_merged_polygons_valid = other.m_merged_polygons_valid;
|
||||
}
|
||||
|
||||
FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged)
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false))
|
||||
FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged, double area_ratio, size_t max_vertex_count)
|
||||
: 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)
|
||||
{
|
||||
init ();
|
||||
m_is_merged = is_merged;
|
||||
}
|
||||
|
||||
FlatRegion::FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged)
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false))
|
||||
FlatRegion::FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged, double area_ratio, size_t max_vertex_count)
|
||||
: 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)
|
||||
{
|
||||
init ();
|
||||
m_is_merged = is_merged;
|
||||
|
|
@ -63,8 +67,9 @@ FlatRegion::FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans,
|
|||
set_merged_semantics (merged_semantics);
|
||||
}
|
||||
|
||||
FlatRegion::FlatRegion (bool is_merged)
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false))
|
||||
FlatRegion::FlatRegion (bool is_merged, double area_ratio, size_t max_vertex_count)
|
||||
: 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)
|
||||
{
|
||||
init ();
|
||||
m_is_merged = is_merged;
|
||||
|
|
@ -126,6 +131,20 @@ FlatRegion::ensure_merged_polygons_valid () const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
FlatRegion::ensure_unmerged_polygons_valid () const
|
||||
{
|
||||
if (! m_is_merged || (m_area_ratio == 0.0 && m_max_vertex_count == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mp_merged_polygons.reset (new db::Shapes (*mp_polygons));
|
||||
m_merged_polygons_valid = true;
|
||||
m_is_merged = false;
|
||||
|
||||
break_polygons (*mp_polygons, m_max_vertex_count, m_area_ratio);
|
||||
}
|
||||
|
||||
RegionIteratorDelegate *FlatRegion::begin () const
|
||||
{
|
||||
return new FlatRegionIterator (mp_polygons.get_const ());
|
||||
|
|
@ -141,6 +160,12 @@ RegionIteratorDelegate *FlatRegion::begin_merged () const
|
|||
}
|
||||
}
|
||||
|
||||
RegionIteratorDelegate *FlatRegion::begin_unmerged () const
|
||||
{
|
||||
ensure_unmerged_polygons_valid ();
|
||||
return begin ();
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> FlatRegion::begin_iter () const
|
||||
{
|
||||
return std::make_pair (db::RecursiveShapeIterator (*mp_polygons), db::ICplxTrans ());
|
||||
|
|
@ -156,6 +181,12 @@ std::pair<db::RecursiveShapeIterator, db::ICplxTrans> FlatRegion::begin_merged_i
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> FlatRegion::begin_unmerged_iter () const
|
||||
{
|
||||
ensure_unmerged_polygons_valid ();
|
||||
return begin_iter ();
|
||||
}
|
||||
|
||||
bool FlatRegion::empty () const
|
||||
{
|
||||
return mp_polygons->empty ();
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ public:
|
|||
typedef db::layer<db::PolygonWithProperties, db::unstable_layer_tag> polygon_layer_wp_type;
|
||||
typedef polygon_layer_wp_type::iterator polygon_iterator_wp_type;
|
||||
|
||||
FlatRegion ();
|
||||
FlatRegion (const db::Shapes &polygons, bool is_merged = false);
|
||||
FlatRegion (const db::Shapes &polygons, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged = false);
|
||||
FlatRegion (bool is_merged);
|
||||
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, const db::ICplxTrans &trans, bool merged_semantics, bool is_merged = false, 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);
|
||||
|
||||
FlatRegion (const FlatRegion &other);
|
||||
|
||||
|
|
@ -69,9 +69,11 @@ public:
|
|||
|
||||
virtual RegionIteratorDelegate *begin () const;
|
||||
virtual RegionIteratorDelegate *begin_merged () const;
|
||||
virtual RegionIteratorDelegate *begin_unmerged () const;
|
||||
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const;
|
||||
|
||||
virtual bool empty () const;
|
||||
virtual size_t count () const;
|
||||
|
|
@ -143,13 +145,16 @@ private:
|
|||
|
||||
FlatRegion &operator= (const FlatRegion &other);
|
||||
|
||||
bool m_is_merged;
|
||||
mutable bool m_is_merged;
|
||||
mutable tl::copy_on_write_ptr<db::Shapes> mp_polygons;
|
||||
mutable tl::copy_on_write_ptr<db::Shapes> mp_merged_polygons;
|
||||
mutable bool m_merged_polygons_valid;
|
||||
double m_area_ratio;
|
||||
size_t m_max_vertex_count;
|
||||
|
||||
void init ();
|
||||
void ensure_merged_polygons_valid () const;
|
||||
void ensure_unmerged_polygons_valid () const;
|
||||
|
||||
template <class Trans>
|
||||
void transform_generic (const Trans &trans)
|
||||
|
|
|
|||
|
|
@ -317,6 +317,12 @@ OriginalLayerRegion::begin_merged () const
|
|||
}
|
||||
}
|
||||
|
||||
RegionIteratorDelegate *
|
||||
OriginalLayerRegion::begin_unmerged () const
|
||||
{
|
||||
return begin ();
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
|
||||
OriginalLayerRegion::begin_iter () const
|
||||
{
|
||||
|
|
@ -334,6 +340,12 @@ OriginalLayerRegion::begin_merged_iter () const
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
|
||||
OriginalLayerRegion::begin_unmerged_iter () const
|
||||
{
|
||||
return std::make_pair (m_iter, m_iter_trans);
|
||||
}
|
||||
|
||||
bool
|
||||
OriginalLayerRegion::empty () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,9 +51,11 @@ public:
|
|||
|
||||
virtual RegionIteratorDelegate *begin () const;
|
||||
virtual RegionIteratorDelegate *begin_merged () const;
|
||||
virtual RegionIteratorDelegate *begin_unmerged () const;
|
||||
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const;
|
||||
|
||||
virtual bool empty () const;
|
||||
|
||||
|
|
|
|||
|
|
@ -349,6 +349,17 @@ public:
|
|||
return RegionIterator (mp_delegate->begin_merged ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the unmerged polygons
|
||||
*
|
||||
* "unmerged" polygons are polygons which are optimized for local operations,
|
||||
* specifically broken according to the area ratio and max vertex count.
|
||||
*/
|
||||
const_iterator begin_unmerged () const
|
||||
{
|
||||
return RegionIterator (mp_delegate->begin_unmerged ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delivers a RecursiveShapeIterator pointing to the polygons plus the necessary transformation
|
||||
*/
|
||||
|
|
@ -365,6 +376,14 @@ public:
|
|||
return mp_delegate->begin_merged_iter ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delivers a RecursiveShapeIterator pointing to the unmerged polygons plus the necessary transformation
|
||||
*/
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const
|
||||
{
|
||||
return mp_delegate->begin_unmerged_iter ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts the given shape (working object) into the region
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -185,9 +185,11 @@ public:
|
|||
|
||||
virtual RegionIteratorDelegate *begin () const = 0;
|
||||
virtual RegionIteratorDelegate *begin_merged () const = 0;
|
||||
virtual RegionIteratorDelegate *begin_unmerged () const = 0;
|
||||
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const = 0;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const = 0;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const = 0;
|
||||
|
||||
virtual bool empty () const = 0;
|
||||
virtual bool is_box () const = 0;
|
||||
|
|
|
|||
|
|
@ -3158,3 +3158,135 @@ TEST(deep_region_merged_with_pseudo_labels)
|
|||
rr2.merge ();
|
||||
EXPECT_EQ (rr2.to_string (), "(0,0;0,2000;2000,2000;2000,0){A=>17,B=>42};(998,2998;998,3002;1002,3002;1002,2998)");
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class AttachPropertiesProcessor
|
||||
: public db::PolygonProcessorBase
|
||||
{
|
||||
public:
|
||||
AttachPropertiesProcessor (db::properties_id_type pid)
|
||||
: m_pid (pid)
|
||||
{ }
|
||||
|
||||
virtual void process (const db::PolygonWithProperties &s, std::vector<db::PolygonWithProperties> &res) const
|
||||
{
|
||||
res.push_back (db::PolygonWithProperties (s, m_pid));
|
||||
}
|
||||
|
||||
virtual bool result_is_merged () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
db::properties_id_type m_pid;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TEST(deep_unmerged_regions)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
db::Cell &top = ly.cell (ly.add_cell ("TOP"));
|
||||
|
||||
unsigned int l1 = ly.insert_layer (db::LayerProperties (1, 0));
|
||||
unsigned int l2 = ly.insert_layer (db::LayerProperties (2, 0));
|
||||
|
||||
top.shapes (l1).insert (db::Box (0, 0, 2000, 2000));
|
||||
top.shapes (l2).insert (db::Box (200, 200, 1800, 1800));
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_max_area_ratio (2.0);
|
||||
|
||||
db::Region r1 (db::RecursiveShapeIterator (ly, top, l1), dss);
|
||||
db::Region r2 (db::RecursiveShapeIterator (ly, top, l2), dss);
|
||||
|
||||
db::DeepRegion *r1_deep = dynamic_cast<db::DeepRegion *> (r1.delegate ());
|
||||
EXPECT_EQ (r1_deep->is_merged (), false);
|
||||
EXPECT_EQ (r1_deep->merged_polygons_available (), false);
|
||||
|
||||
db::Region r12 = (r1 - r2).merged ();
|
||||
EXPECT_EQ (r12.to_string (), "(0,0;0,2000;2000,2000;2000,0/200,200;1800,200;1800,1800;200,1800)");
|
||||
db::DeepRegion *r12_deep = dynamic_cast<db::DeepRegion *> (r12.delegate ());
|
||||
|
||||
EXPECT_EQ (r12_deep->is_merged (), true);
|
||||
EXPECT_EQ (r12_deep->merged_polygons_available (), true);
|
||||
|
||||
// this will force r12 back into unmerged state, but merged polygons are still available
|
||||
db::Region rx = r1 | r12;
|
||||
|
||||
EXPECT_EQ (r12_deep->is_merged (), false);
|
||||
EXPECT_EQ (r12_deep->merged_polygons_available (), true);
|
||||
EXPECT_EQ (r12.to_string (), "(200,0;200,200;2000,200;2000,0);(1800,200;1800,1000;2000,1000;2000,200);(0,0;0,1000;200,1000;200,0);(1800,1000;1800,2000;2000,2000;2000,1000);(0,1000;0,1800;200,1800;200,1000);(0,1800;0,2000;1800,2000;1800,1800)");
|
||||
EXPECT_EQ (rx.to_string (), "(0,0;0,2000;2000,2000;2000,0)");
|
||||
|
||||
// repeat with properties
|
||||
|
||||
db::PropertiesSet ps;
|
||||
ps.insert (tl::Variant ("n"), tl::Variant (42));
|
||||
auto pid = db::properties_id (ps);
|
||||
AttachPropertiesProcessor ap (pid);
|
||||
r12 = (r1 - r2).merged ().processed (ap);
|
||||
|
||||
EXPECT_EQ (r12.to_string (), "(0,0;0,2000;2000,2000;2000,0/200,200;1800,200;1800,1800;200,1800){n=>42}");
|
||||
r12_deep = dynamic_cast<db::DeepRegion *> (r12.delegate ());
|
||||
|
||||
EXPECT_EQ (r12_deep->is_merged (), true);
|
||||
EXPECT_EQ (r12_deep->merged_polygons_available (), true);
|
||||
|
||||
rx = r1 | r12;
|
||||
|
||||
EXPECT_EQ (r12_deep->is_merged (), false);
|
||||
EXPECT_EQ (r12_deep->merged_polygons_available (), true);
|
||||
EXPECT_EQ (r12.to_string (), "(200,0;200,200;2000,200;2000,0){n=>42};(1800,200;1800,1000;2000,1000;2000,200){n=>42};(0,0;0,1000;200,1000;200,0){n=>42};(1800,1000;1800,2000;2000,2000;2000,1000){n=>42};(0,1000;0,1800;200,1800;200,1000){n=>42};(0,1800;0,2000;1800,2000;1800,1800){n=>42}");
|
||||
EXPECT_EQ (rx.to_string (), "(0,0;0,2000;2000,2000;2000,0);(0,0;0,2000;2000,2000;2000,0/200,200;1800,200;1800,1800;200,1800){n=>42}");
|
||||
|
||||
// now with "+" instead of "|"
|
||||
|
||||
db::Region r12p = (r1 - r2).merged ();
|
||||
db::DeepRegion *r12p_deep = dynamic_cast<db::DeepRegion *> (r12p.delegate ());
|
||||
|
||||
EXPECT_EQ (r12p_deep->is_merged (), true);
|
||||
EXPECT_EQ (r12p_deep->merged_polygons_available (), true);
|
||||
|
||||
// this will also force r12 back into unmerged state, but merged polygons are still available
|
||||
db::Region ry = (r1 + r12p).merged ();
|
||||
|
||||
EXPECT_EQ (r12p_deep->is_merged (), false);
|
||||
EXPECT_EQ (r12p_deep->merged_polygons_available (), true);
|
||||
EXPECT_EQ (r12p.to_string (), "(200,0;200,200;2000,200;2000,0);(1800,200;1800,1000;2000,1000;2000,200);(0,0;0,1000;200,1000;200,0);(1800,1000;1800,2000;2000,2000;2000,1000);(0,1000;0,1800;200,1800;200,1000);(0,1800;0,2000;1800,2000;1800,1800)");
|
||||
EXPECT_EQ (ry.to_string (), "(0,0;0,2000;2000,2000;2000,0)");
|
||||
}
|
||||
|
||||
TEST(processed_delivers_polygon_refs)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
db::Cell &top = ly.cell (ly.add_cell ("TOP"));
|
||||
|
||||
unsigned int l1 = ly.insert_layer (db::LayerProperties (1, 0));
|
||||
unsigned int l2 = ly.insert_layer (db::LayerProperties (2, 0));
|
||||
|
||||
top.shapes (l1).insert (db::Box (0, 0, 2000, 2000));
|
||||
top.shapes (l2).insert (db::Box (200, 200, 1800, 1800));
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
db::Region r1 (db::RecursiveShapeIterator (ly, top, l1), dss);
|
||||
db::Region r2 (db::RecursiveShapeIterator (ly, top, l2), dss);
|
||||
|
||||
db::PropertiesSet ps;
|
||||
ps.insert (tl::Variant ("n"), tl::Variant (42));
|
||||
auto pid = db::properties_id (ps);
|
||||
AttachPropertiesProcessor ap (pid);
|
||||
|
||||
db::Region r12 = (r1 - r2).merged ().processed (ap);
|
||||
|
||||
r12.set_join_properties_on_merge (true);
|
||||
|
||||
db::Region rx = r1 | r12;
|
||||
|
||||
EXPECT_EQ (rx.to_string (), "(0,0;0,2000;2000,2000;2000,0);(0,0;0,2000;2000,2000;2000,0/200,200;1800,200;1800,1800;200,1800){n=>42}");
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue