Avoid turning DeepRegions into flat ones as this spoils hierarchical processing.

This commit is contained in:
Matthias Koefferlein 2021-03-28 22:33:24 +02:00
parent de4454a0d6
commit 6df333a05e
9 changed files with 332 additions and 130 deletions

View File

@ -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 \

View File

@ -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 <class Trans>
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
{

View File

@ -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<db::Polygon, db::unstable_layer_tag> 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;

View File

@ -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 ();
}
}
}

View File

@ -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<db::Polygon> 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 <class T>
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 <class Iter>
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 <class Iter>
void insert_seq (const Iter &seq)
{
for (Iter i = seq; ! i.at_end (); ++i) {
insert (*i);
}
}
template <class Trans>
void transform (const Trans &trans)
{
if (! trans.is_unity ()) {
db::Shapes &polygons = *mp_polygons;
for (polygon_iterator_type p = polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().begin (); p != polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end (); ++p) {
polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().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 <class Trans>
void transform_generic (const Trans &trans)
{
if (! trans.is_unity ()) {
db::Shapes &polygons = *mp_polygons;
for (polygon_iterator_type p = polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().begin (); p != polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end (); ++p) {
polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
}
invalidate_cache ();
}
}
};
}

View File

@ -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 ());
}
}
}

101
src/db/db/dbMutableRegion.h Normal file
View File

@ -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 <set>
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 <class T>
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 <class Iter>
void insert (const Iter &b, const Iter &e)
{
reserve (count () + (e - b));
for (Iter i = b; i != e; ++i) {
insert (*i);
}
}
template <class Iter>
void insert_seq (const Iter &seq)
{
for (Iter i = seq; ! i.at_end (); ++i) {
insert (*i);
}
}
};
}
#endif

View File

@ -131,13 +131,13 @@ Region::clear ()
void
Region::reserve (size_t n)
{
flat_region ()->reserve (n);
mutable_region ()->reserve (n);
}
template <class T>
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 <class Sh>
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 <class T>
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<FlatRegion *> (mp_delegate);
MutableRegion *region = dynamic_cast<MutableRegion *> (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)
{

View File

@ -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();
};
/**