From 6df333a05efb1ea4b09643ffb9affa04957013bd Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 28 Mar 2021 22:33:24 +0200 Subject: [PATCH] Avoid turning DeepRegions into flat ones as this spoils hierarchical processing. --- src/db/db/db.pro | 2 + src/db/db/dbDeepRegion.cc | 80 ++++++++++++++++++++++++--- src/db/db/dbDeepRegion.h | 13 ++++- src/db/db/dbFlatRegion.cc | 66 ++--------------------- src/db/db/dbFlatRegion.h | 62 ++++++++------------- src/db/db/dbMutableRegion.cc | 90 +++++++++++++++++++++++++++++++ src/db/db/dbMutableRegion.h | 101 +++++++++++++++++++++++++++++++++++ src/db/db/dbRegion.cc | 38 ++++++++----- src/db/db/dbRegion.h | 10 ++-- 9 files changed, 332 insertions(+), 130 deletions(-) create mode 100644 src/db/db/dbMutableRegion.cc create mode 100644 src/db/db/dbMutableRegion.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index bd6371526..02e4e20ad 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -50,6 +50,7 @@ SOURCES = \ dbManager.cc \ dbMatrix.cc \ dbMemStatistics.cc \ + dbMutableRegion.cc \ dbObject.cc \ dbPath.cc \ dbPCellDeclaration.cc \ @@ -258,6 +259,7 @@ HEADERS = \ dbMatrix.h \ dbMemStatistics.h \ dbMetaInfo.h \ + dbMutableRegion.h \ dbObject.h \ dbObjectTag.h \ dbObjectWithProperties.h \ diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index db74b18ff..2d6aa848d 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -127,14 +127,14 @@ private: // DeepRegion implementation DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio, size_t max_vertex_count) - : AsIfFlatRegion (), m_merged_polygons () + : MutableRegion (), m_merged_polygons () { set_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)); init (); } DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics, double area_ratio, size_t max_vertex_count) - : AsIfFlatRegion (), m_merged_polygons () + : MutableRegion (), m_merged_polygons () { set_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count, trans)); init (); @@ -142,7 +142,7 @@ DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, c } DeepRegion::DeepRegion (const db::Region &other, DeepShapeStore &dss) - : AsIfFlatRegion (), m_merged_polygons () + : MutableRegion (), m_merged_polygons () { set_deep_layer (dss.create_from_flat (other, false)); @@ -151,13 +151,13 @@ DeepRegion::DeepRegion (const db::Region &other, DeepShapeStore &dss) } DeepRegion::DeepRegion () - : AsIfFlatRegion () + : MutableRegion () { init (); } DeepRegion::DeepRegion (const DeepLayer &dl) - : AsIfFlatRegion () + : MutableRegion () { set_deep_layer (dl); init (); @@ -169,7 +169,7 @@ DeepRegion::~DeepRegion () } DeepRegion::DeepRegion (const DeepRegion &other) - : AsIfFlatRegion (other), DeepShapeCollectionDelegateBase (other), + : MutableRegion (other), DeepShapeCollectionDelegateBase (other), m_merged_polygons_valid (other.m_merged_polygons_valid), m_is_merged (other.m_is_merged) { @@ -220,6 +220,74 @@ void DeepRegion::min_coherence_changed () set_is_merged (false); } +void DeepRegion::do_insert (const db::Polygon &polygon) +{ + db::Layout &layout = deep_layer ().layout (); + if (layout.begin_top_down () != layout.end_top_down ()) { + db::Cell &top_cell = layout.cell (*layout.begin_top_down ()); + top_cell.shapes (deep_layer ().layer ()).insert (db::PolygonRef (polygon, layout.shape_repository ())); + } + + invalidate_bbox (); + set_is_merged (false); +} + +template +static void transform_deep_layer (db::DeepLayer &deep_layer, const Trans &t) +{ + // TODO: this is a pretty cheap implementation. At least a plain move can be done with orientation variants. + + db::Layout &layout = deep_layer.layout (); + if (layout.begin_top_down () != layout.end_top_down ()) { + + db::Cell &top_cell = layout.cell (*layout.begin_top_down ()); + + db::Shapes flat_shapes; + for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer.layer ()); !iter.at_end (); ++iter) { + flat_shapes.insert (iter->polygon ().transformed (t)); + } + + layout.clear_layer (deep_layer.layer ()); + top_cell.shapes (deep_layer.layer ()).swap (flat_shapes); + + } +} + +void DeepRegion::do_transform (const db::Trans &t) +{ + transform_deep_layer (deep_layer (), t); + invalidate_bbox (); +} + +void DeepRegion::do_transform (const db::ICplxTrans &t) +{ + transform_deep_layer (deep_layer (), t); + invalidate_bbox (); +} + +void DeepRegion::reserve (size_t) +{ + // Not implemented for deep regions +} + +void DeepRegion::flatten () +{ + db::Layout &layout = deep_layer ().layout (); + if (layout.begin_top_down () != layout.end_top_down ()) { + + db::Cell &top_cell = layout.cell (*layout.begin_top_down ()); + + db::Shapes flat_shapes; + for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer ().layer ()); !iter.at_end (); ++iter) { + flat_shapes.insert (iter->polygon ()); + } + + layout.clear_layer (deep_layer ().layer ()); + top_cell.shapes (deep_layer ().layer ()).swap (flat_shapes); + + } +} + RegionIteratorDelegate * DeepRegion::begin () const { diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index c15913f2c..a2c0f06ef 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -26,7 +26,7 @@ #include "dbCommon.h" -#include "dbAsIfFlatRegion.h" +#include "dbMutableRegion.h" #include "dbDeepShapeStore.h" namespace db { @@ -35,7 +35,7 @@ namespace db { * @brief A deep, polygon-set delegate */ class DB_PUBLIC DeepRegion - : public AsIfFlatRegion, public DeepShapeCollectionDelegateBase + : public MutableRegion, public DeepShapeCollectionDelegateBase { public: typedef db::layer polygon_layer_type; @@ -53,6 +53,15 @@ public: RegionDelegate *clone () const; + virtual void do_insert (const db::Polygon &polygon); + + virtual void do_transform (const db::Trans &t); + virtual void do_transform (const db::ICplxTrans &t); + + virtual void flatten (); + + virtual void reserve (size_t); + virtual RegionIteratorDelegate *begin () const; virtual RegionIteratorDelegate *begin_merged () const; diff --git a/src/db/db/dbFlatRegion.cc b/src/db/db/dbFlatRegion.cc index 01f3a954a..71e240cd3 100644 --- a/src/db/db/dbFlatRegion.cc +++ b/src/db/db/dbFlatRegion.cc @@ -33,7 +33,7 @@ namespace db // FlatRegion implementation FlatRegion::FlatRegion () - : AsIfFlatRegion (), 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)) { init (); } @@ -44,7 +44,7 @@ FlatRegion::~FlatRegion () } FlatRegion::FlatRegion (const FlatRegion &other) - : AsIfFlatRegion (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) { init (); @@ -53,7 +53,7 @@ FlatRegion::FlatRegion (const FlatRegion &other) } FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged) - : AsIfFlatRegion (), 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)) { init (); @@ -61,7 +61,7 @@ FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged) } FlatRegion::FlatRegion (bool is_merged) - : AsIfFlatRegion (), 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)) { init (); @@ -410,39 +410,7 @@ void FlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, uns } void -FlatRegion::insert (const db::Box &box) -{ - if (! box.empty () && box.width () > 0 && box.height () > 0) { - - if (empty ()) { - - mp_polygons->insert (db::Polygon (box)); - m_is_merged = true; - update_bbox (box); - - } else { - - mp_polygons->insert (db::Polygon (box)); - m_is_merged = false; - invalidate_cache (); - - } - - } -} - -void -FlatRegion::insert (const db::Path &path) -{ - if (path.points () > 0) { - mp_polygons->insert (path.polygon ()); - m_is_merged = false; - invalidate_cache (); - } -} - -void -FlatRegion::insert (const db::Polygon &polygon) +FlatRegion::do_insert (const db::Polygon &polygon) { if (polygon.holes () > 0 || polygon.vertices () > 0) { mp_polygons->insert (polygon); @@ -451,29 +419,5 @@ FlatRegion::insert (const db::Polygon &polygon) } } -void -FlatRegion::insert (const db::SimplePolygon &polygon) -{ - if (polygon.vertices () > 0) { - db::Polygon poly; - poly.assign_hull (polygon.begin_hull (), polygon.end_hull ()); - mp_polygons->insert (poly); - m_is_merged = false; - invalidate_cache (); - } -} - -void -FlatRegion::insert (const db::Shape &shape) -{ - if (shape.is_polygon () || shape.is_path () || shape.is_box ()) { - db::Polygon poly; - shape.polygon (poly); - mp_polygons->insert (poly); - m_is_merged = false; - invalidate_cache (); - } -} - } diff --git a/src/db/db/dbFlatRegion.h b/src/db/db/dbFlatRegion.h index 87342eb13..09095cc0b 100644 --- a/src/db/db/dbFlatRegion.h +++ b/src/db/db/dbFlatRegion.h @@ -26,7 +26,7 @@ #include "dbCommon.h" -#include "dbAsIfFlatRegion.h" +#include "dbMutableRegion.h" #include "dbShapes.h" #include "dbShapes2.h" #include "tlCopyOnWrite.h" @@ -42,7 +42,7 @@ typedef generic_shapes_iterator_delegate FlatRegionIterator; * @brief A flat, polygon-set delegate */ class DB_PUBLIC FlatRegion - : public AsIfFlatRegion + : public MutableRegion { public: typedef db::Polygon value_type; @@ -62,7 +62,7 @@ public: return new FlatRegion (*this); } - void reserve (size_t); + virtual void reserve (size_t); virtual RegionIteratorDelegate *begin () const; virtual RegionIteratorDelegate *begin_merged () const; @@ -97,51 +97,19 @@ public: virtual const db::RecursiveShapeIterator *iter () const; - void insert (const db::Box &box); - void insert (const db::Path &path); - void insert (const db::SimplePolygon &polygon); - void insert (const db::Polygon &polygon); - void insert (const db::Shape &shape); + void do_insert (const db::Polygon &polygon); - template - void insert (const db::Shape &shape, const T &trans) + void do_transform (const db::Trans &t) { - if (shape.is_polygon () || shape.is_path () || shape.is_box ()) { - db::Polygon poly; - shape.polygon (poly); - poly.transform (trans); - insert (poly); - } + transform_generic (t); } - template - void insert (const Iter &b, const Iter &e) + void do_transform (const db::ICplxTrans &t) { - reserve (count () + (e - b)); - for (Iter i = b; i != e; ++i) { - insert (*i); - } + transform_generic (t); } - template - void insert_seq (const Iter &seq) - { - for (Iter i = seq; ! i.at_end (); ++i) { - insert (*i); - } - } - - template - void transform (const Trans &trans) - { - if (! trans.is_unity ()) { - db::Shapes &polygons = *mp_polygons; - for (polygon_iterator_type p = polygons.get_layer ().begin (); p != polygons.get_layer ().end (); ++p) { - polygons.get_layer ().replace (p, p->transformed (trans)); - } - invalidate_cache (); - } - } + void flatten () { } db::Shapes &raw_polygons () { return *mp_polygons; } const db::Shapes &raw_polygons () const { return *mp_polygons; } @@ -166,6 +134,18 @@ private: void init (); void ensure_merged_polygons_valid () const; + + template + void transform_generic (const Trans &trans) + { + if (! trans.is_unity ()) { + db::Shapes &polygons = *mp_polygons; + for (polygon_iterator_type p = polygons.get_layer ().begin (); p != polygons.get_layer ().end (); ++p) { + polygons.get_layer ().replace (p, p->transformed (trans)); + } + invalidate_cache (); + } + } }; } diff --git a/src/db/db/dbMutableRegion.cc b/src/db/db/dbMutableRegion.cc new file mode 100644 index 000000000..8f55558f5 --- /dev/null +++ b/src/db/db/dbMutableRegion.cc @@ -0,0 +1,90 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbMutableRegion.h" + +namespace db +{ + +// ------------------------------------------------------------------------------------------------------------- +// FlatRegion implementation + +MutableRegion::MutableRegion () + : AsIfFlatRegion () +{ + // .. nothing yet .. +} + +MutableRegion::MutableRegion (const MutableRegion &other) + : AsIfFlatRegion (other) +{ + // .. nothing yet .. +} + +MutableRegion::~MutableRegion () +{ + // .. nothing yet .. +} + +void +MutableRegion::insert (const db::Box &box) +{ + if (! box.empty () && box.width () > 0 && box.height () > 0) { + do_insert (db::Polygon (box)); + } +} + +void +MutableRegion::insert (const db::Path &path) +{ + if (path.points () > 0) { + do_insert (path.polygon ()); + } +} + +void +MutableRegion::insert (const db::SimplePolygon &polygon) +{ + if (polygon.vertices () > 0) { + db::Polygon poly; + poly.assign_hull (polygon.begin_hull (), polygon.end_hull ()); + do_insert (poly); + } +} + +void +MutableRegion::insert (const db::Shape &shape) +{ + if (shape.is_polygon () || shape.is_path () || shape.is_box ()) { + db::Polygon poly; + shape.polygon (poly); + insert (poly); + } else if (shape.is_path ()) { + insert (shape.path ()); + } else if (shape.is_box ()) { + insert (shape.box ()); + } +} + +} + diff --git a/src/db/db/dbMutableRegion.h b/src/db/db/dbMutableRegion.h new file mode 100644 index 000000000..ea00278cf --- /dev/null +++ b/src/db/db/dbMutableRegion.h @@ -0,0 +1,101 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbMutableRegion +#define HDR_dbMutableRegion + +#include "dbCommon.h" + +#include "dbAsIfFlatRegion.h" + +#include + +namespace db { + +/** + * @brief An interface representing mutable regions + * + * Mutable Regions offer insert, transform, flatten and other manipulation functions. + */ +class DB_PUBLIC MutableRegion + : public AsIfFlatRegion +{ +public: + MutableRegion (); + MutableRegion (const MutableRegion &other); + virtual ~MutableRegion (); + + virtual void do_insert (const db::Polygon &polygon) = 0; + + void transform (const db::UnitTrans &) { } + void transform (const db::Disp &t) { do_transform (db::Trans (t)); } + void transform (const db::Trans &t) { do_transform (t); } + void transform (const db::ICplxTrans &t) { do_transform (t); } + + virtual void do_transform (const db::Trans &t) = 0; + virtual void do_transform (const db::ICplxTrans &t) = 0; + + virtual void flatten () = 0; + + virtual void reserve (size_t n) = 0; + + void insert (const db::Polygon &polygon) { do_insert (polygon); } + void insert (const db::Box &box); + void insert (const db::Path &path); + void insert (const db::SimplePolygon &polygon); + + void insert (const db::Shape &shape); + + template + void insert (const db::Shape &shape, const T &trans) + { + if (shape.is_polygon () || shape.is_path () || shape.is_box ()) { + db::Polygon poly; + shape.polygon (poly); + poly.transform (trans); + insert (poly); + } + } + + template + void insert (const Iter &b, const Iter &e) + { + reserve (count () + (e - b)); + for (Iter i = b; i != e; ++i) { + insert (*i); + } + } + + template + void insert_seq (const Iter &seq) + { + for (Iter i = seq; ! i.at_end (); ++i) { + insert (*i); + } + } +}; + +} + +#endif + diff --git a/src/db/db/dbRegion.cc b/src/db/db/dbRegion.cc index 605fb1671..1cacb17f3 100644 --- a/src/db/db/dbRegion.cc +++ b/src/db/db/dbRegion.cc @@ -131,13 +131,13 @@ Region::clear () void Region::reserve (size_t n) { - flat_region ()->reserve (n); + mutable_region ()->reserve (n); } template Region &Region::transform (const T &trans) { - flat_region ()->transform (trans); + mutable_region ()->transform (trans); return *this; } @@ -149,7 +149,7 @@ template DB_PUBLIC Region &Region::transform (const db::Disp &); template void Region::insert (const Sh &shape) { - flat_region ()->insert (shape); + mutable_region ()->insert (shape); } template DB_PUBLIC void Region::insert (const db::Box &); @@ -159,31 +159,36 @@ template DB_PUBLIC void Region::insert (const db::Path &); void Region::insert (const db::Shape &shape) { - flat_region ()->insert (shape); + mutable_region ()->insert (shape); } template void Region::insert (const db::Shape &shape, const T &trans) { - flat_region ()->insert (shape, trans); + mutable_region ()->insert (shape, trans); } template DB_PUBLIC void Region::insert (const db::Shape &, const db::ICplxTrans &); template DB_PUBLIC void Region::insert (const db::Shape &, const db::Trans &); template DB_PUBLIC void Region::insert (const db::Shape &, const db::Disp &); -FlatRegion * -Region::flat_region () +MutableRegion * +Region::mutable_region () { - FlatRegion *region = dynamic_cast (mp_delegate); + MutableRegion *region = dynamic_cast (mp_delegate); if (! region) { - region = new FlatRegion (); + + FlatRegion *flat_region = new FlatRegion (); + region = flat_region; + if (mp_delegate) { - region->RegionDelegate::operator= (*mp_delegate); // copy basic flags - region->insert_seq (begin ()); - region->set_is_merged (mp_delegate->is_merged ()); + flat_region->RegionDelegate::operator= (*mp_delegate); // copy basic flags + flat_region->insert_seq (begin ()); + flat_region->set_is_merged (mp_delegate->is_merged ()); } - set_delegate (region); + + set_delegate (flat_region); + } return region; @@ -274,6 +279,13 @@ Region::smoothed (coord_type d, bool keep_hv) const return processed (SmoothingProcessor (d, keep_hv)); } +db::Region & +Region::flatten () +{ + mutable_region ()->flatten (); + return *this; +} + void Region::snap (db::Coord gx, db::Coord gy) { diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index fea1d8e8b..a14761c42 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -37,7 +37,7 @@ namespace db { class EdgeFilterBase; -class FlatRegion; +class MutableRegion; class EmptyRegion; class DeepShapeStore; class TransformationReducer; @@ -1644,11 +1644,7 @@ public: * * This method will turn any region into a flat shape collection. */ - db::Region &flatten () - { - flat_region (); - return *this; - } + db::Region &flatten (); /** * @brief Returns true, if the region has valid polygons stored within itself @@ -1776,7 +1772,7 @@ private: RegionDelegate *mp_delegate; void set_delegate (RegionDelegate *delegate, bool keep_attributes = true); - FlatRegion *flat_region (); + db::MutableRegion *mutable_region(); }; /**