mirror of https://github.com/KLayout/klayout.git
WIP: deep edges and edge pairs.
This commit is contained in:
parent
4abc38a5cc
commit
f22217b6c4
|
|
@ -167,7 +167,9 @@ SOURCES = \
|
|||
gsiDeclDbDeepShapeStore.cc \
|
||||
dbNetlistSpiceWriter.cc \
|
||||
dbNetlistWriter.cc \
|
||||
dbCellVariants.cc
|
||||
dbCellVariants.cc \
|
||||
dbDeepEdges.cc \
|
||||
dbDeepEdgePairs.cc
|
||||
|
||||
HEADERS = \
|
||||
dbArray.h \
|
||||
|
|
@ -299,7 +301,9 @@ HEADERS = \
|
|||
dbDeepRegion.h \
|
||||
dbNetlistSpiceWriter.h \
|
||||
dbNetlistWriter.h \
|
||||
dbCellVariants.h
|
||||
dbCellVariants.h \
|
||||
dbDeepEdges.h \
|
||||
dbDeepEdgePairs.h
|
||||
|
||||
!equals(HAVE_QT, "0") {
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ public:
|
|||
protected:
|
||||
void update_bbox (const db::Box &box);
|
||||
void invalidate_bbox ();
|
||||
EdgePairs run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
|
||||
private:
|
||||
AsIfFlatEdges &operator= (const AsIfFlatEdges &other);
|
||||
|
|
@ -165,7 +166,6 @@ private:
|
|||
mutable db::Box m_bbox;
|
||||
|
||||
virtual db::Box compute_bbox () const;
|
||||
EdgePairs run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
EdgesDelegate *boolean (const Edges *other, EdgeBoolOp op) const;
|
||||
EdgesDelegate *edge_region_op (const Region &other, bool outside, bool include_borders) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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 "dbDeepEdgePairs.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// @@@ TODO: implement
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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_dbDeepEdgePairs
|
||||
#define HDR_dbDeepEdgePairs
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbAsIfFlatEdgePairs.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
// @@@ TODO: implement
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,673 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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 "dbEdges.h"
|
||||
#include "dbDeepEdges.h"
|
||||
#include "dbHierNetworkProcessor.h"
|
||||
#include "dbCellGraphUtils.h"
|
||||
#include "dbCellVariants.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbCellMapping.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief An iterator delegate for the deep edge collection
|
||||
* TODO: this is kind of redundant with OriginalLayerIterator ..
|
||||
*/
|
||||
class DB_PUBLIC DeepEdgesIterator
|
||||
: public EdgesIteratorDelegate
|
||||
{
|
||||
public:
|
||||
DeepEdgesIterator (const db::RecursiveShapeIterator &iter)
|
||||
: m_iter (iter)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
||||
virtual ~DeepEdgesIterator () { }
|
||||
|
||||
virtual bool at_end () const
|
||||
{
|
||||
return m_iter.at_end ();
|
||||
}
|
||||
|
||||
virtual void increment ()
|
||||
{
|
||||
++m_iter;
|
||||
set ();
|
||||
}
|
||||
|
||||
virtual const value_type *get () const
|
||||
{
|
||||
return &m_edge;
|
||||
}
|
||||
|
||||
virtual EdgesIteratorDelegate *clone () const
|
||||
{
|
||||
return new DeepEdgesIterator (*this);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Edges;
|
||||
|
||||
db::RecursiveShapeIterator m_iter;
|
||||
mutable value_type m_edge;
|
||||
|
||||
void set () const
|
||||
{
|
||||
if (! m_iter.at_end ()) {
|
||||
m_iter.shape ().edge (m_edge);
|
||||
m_edge.transform (m_iter.trans ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------
|
||||
// DeepEdges implementation
|
||||
|
||||
DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss)
|
||||
: AsIfFlatEdges (), m_deep_layer (dss.create_edge_layer (si)), m_merged_edges ()
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics)
|
||||
: AsIfFlatEdges (), m_deep_layer (dss.create_edge_layer (si)), m_merged_edges ()
|
||||
{
|
||||
init ();
|
||||
|
||||
tl_assert (trans.is_unity ()); // TODO: implement
|
||||
set_merged_semantics (merged_semantics);
|
||||
}
|
||||
|
||||
DeepEdges::DeepEdges ()
|
||||
: AsIfFlatEdges ()
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
DeepEdges::DeepEdges (const DeepLayer &dl)
|
||||
: AsIfFlatEdges (), m_deep_layer (dl)
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
DeepEdges::~DeepEdges ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
DeepEdges::DeepEdges (const DeepEdges &other)
|
||||
: AsIfFlatEdges (other),
|
||||
m_deep_layer (other.m_deep_layer.copy ()),
|
||||
m_merged_edges_valid (other.m_merged_edges_valid)
|
||||
{
|
||||
if (m_merged_edges_valid) {
|
||||
m_merged_edges = other.m_merged_edges;
|
||||
}
|
||||
}
|
||||
|
||||
void DeepEdges::init ()
|
||||
{
|
||||
m_merged_edges_valid = false;
|
||||
m_merged_edges = db::DeepLayer ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepEdges::clone () const
|
||||
{
|
||||
return new DeepEdges (*this);
|
||||
}
|
||||
|
||||
void DeepEdges::merged_semantics_changed ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
EdgesIteratorDelegate *
|
||||
DeepEdges::begin () const
|
||||
{
|
||||
return new DeepEdgesIterator (begin_iter ().first);
|
||||
}
|
||||
|
||||
EdgesIteratorDelegate *
|
||||
DeepEdges::begin_merged () const
|
||||
{
|
||||
if (! merged_semantics ()) {
|
||||
return begin ();
|
||||
} else {
|
||||
return new DeepEdgesIterator (begin_merged_iter ().first);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
|
||||
DeepEdges::begin_iter () const
|
||||
{
|
||||
const db::Layout &layout = m_deep_layer.layout ();
|
||||
if (layout.cells () == 0) {
|
||||
|
||||
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
|
||||
|
||||
} else {
|
||||
|
||||
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
|
||||
db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
|
||||
return std::make_pair (iter, db::ICplxTrans ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
|
||||
DeepEdges::begin_merged_iter () const
|
||||
{
|
||||
if (! merged_semantics ()) {
|
||||
|
||||
return begin_iter ();
|
||||
|
||||
} else {
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
|
||||
const db::Layout &layout = m_merged_edges.layout ();
|
||||
if (layout.cells () == 0) {
|
||||
|
||||
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
|
||||
|
||||
} else {
|
||||
|
||||
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
|
||||
db::RecursiveShapeIterator iter (m_merged_edges.layout (), top_cell, m_merged_edges.layer ());
|
||||
return std::make_pair (iter, db::ICplxTrans ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DeepEdges::empty () const
|
||||
{
|
||||
return begin_iter ().first.at_end ();
|
||||
}
|
||||
|
||||
bool
|
||||
DeepEdges::is_merged () const
|
||||
{
|
||||
// TODO: there is no such thing as a "surely merged" state except after merged() maybe
|
||||
return false;
|
||||
}
|
||||
|
||||
const db::Edge *
|
||||
DeepEdges::nth (size_t /*n*/) const
|
||||
{
|
||||
throw tl::Exception (tl::to_string (tr ("Random access to edges is available only for flat edge collections")));
|
||||
}
|
||||
|
||||
bool
|
||||
DeepEdges::has_valid_edges () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DeepEdges::has_valid_merged_edges () const
|
||||
{
|
||||
return merged_semantics ();
|
||||
}
|
||||
|
||||
const db::RecursiveShapeIterator *
|
||||
DeepEdges::iter () const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DeepEdges::equals (const Edges &other) const
|
||||
{
|
||||
const DeepEdges *other_delegate = dynamic_cast<const DeepEdges *> (other.delegate ());
|
||||
if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
|
||||
&& other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
|
||||
return true;
|
||||
} else {
|
||||
return AsIfFlatEdges::equals (other);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeepEdges::less (const Edges &other) const
|
||||
{
|
||||
const DeepEdges *other_delegate = dynamic_cast<const DeepEdges *> (other.delegate ());
|
||||
if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
|
||||
return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
|
||||
} else {
|
||||
return AsIfFlatEdges::less (other);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ClusterMerger
|
||||
{
|
||||
public:
|
||||
ClusterMerger (unsigned int layer, const db::hier_clusters<db::Edge> &hc, bool report_progress, const std::string &progress_desc)
|
||||
: m_layer (layer), mp_hc (&hc), m_scanner (report_progress, progress_desc)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void set_base_verbosity (int /*vb*/)
|
||||
{
|
||||
/* TODO: No such thing currently:
|
||||
m_scanner.set_base_verbosity (vb);
|
||||
*/
|
||||
}
|
||||
|
||||
db::Shapes &merged (size_t cid, db::cell_index_type ci, bool initial = true)
|
||||
{
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes>::iterator s = m_merged_cluster.find (std::make_pair (cid, ci));
|
||||
|
||||
// some sanity checks: initial clusters are single-use, are never generated twice and cannot be retrieved again
|
||||
if (initial) {
|
||||
tl_assert (s == m_merged_cluster.end ());
|
||||
m_done.insert (std::make_pair (cid, ci));
|
||||
} else {
|
||||
tl_assert (m_done.find (std::make_pair (cid, ci)) == m_done.end ());
|
||||
}
|
||||
|
||||
if (s != m_merged_cluster.end ()) {
|
||||
return s->second;
|
||||
}
|
||||
|
||||
s = m_merged_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::Shapes (false))).first;
|
||||
|
||||
const db::connected_clusters<db::Edge> &cc = mp_hc->clusters_per_cell (ci);
|
||||
const db::local_cluster<db::Edge> &c = cc.cluster_by_id (cid);
|
||||
|
||||
std::list<std::pair<const db::Shapes *, db::ICplxTrans> > merged_child_clusters;
|
||||
|
||||
const db::connected_clusters<db::Edge>::connections_type &conn = cc.connections_for_cluster (cid);
|
||||
for (db::connected_clusters<db::Edge>::connections_type::const_iterator i = conn.begin (); i != conn.end (); ++i) {
|
||||
const db::Shapes &cc_shapes = merged (i->id (), i->inst ().inst_ptr.cell_index (), false);
|
||||
merged_child_clusters.push_back (std::make_pair (&cc_shapes, i->inst ().complex_trans ()));
|
||||
}
|
||||
|
||||
// collect the edges to merge ..
|
||||
|
||||
std::list<db::Edge> heap;
|
||||
m_scanner.clear ();
|
||||
|
||||
for (std::list<std::pair<const db::Shapes *, db::ICplxTrans> >::const_iterator i = merged_child_clusters.begin (); i != merged_child_clusters.end (); ++i) {
|
||||
for (db::Shapes::shape_iterator s = i->first->begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
if (s->is_edge ()) {
|
||||
heap.push_back (s->edge ().transformed (i->second));
|
||||
m_scanner.insert (&heap.back (), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (db::local_cluster<db::Edge>::shape_iterator s = c.begin (m_layer); !s.at_end (); ++s) {
|
||||
heap.push_back (*s);
|
||||
m_scanner.insert (&heap.back (), 0);
|
||||
}
|
||||
|
||||
// .. and run the merge operation
|
||||
|
||||
s->second.clear ();
|
||||
EdgeBooleanClusterCollector<db::Shapes> cluster_collector (&s->second, EdgeOr);
|
||||
m_scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
return s->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
|
||||
std::set<std::pair<size_t, db::cell_index_type> > m_done;
|
||||
unsigned int m_layer;
|
||||
const db::hier_clusters<db::Edge> *mp_hc;
|
||||
db::box_scanner<db::Edge, size_t> m_scanner;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
DeepEdges::ensure_merged_edges_valid () const
|
||||
{
|
||||
if (! m_merged_edges_valid) {
|
||||
|
||||
m_merged_edges = m_deep_layer.new_layer ();
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
|
||||
|
||||
db::hier_clusters<db::Edge> hc;
|
||||
db::Connectivity conn;
|
||||
conn.connect (m_deep_layer);
|
||||
// TODO: this uses the wrong verbosity inside ...
|
||||
hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Edges, conn);
|
||||
|
||||
// collect the clusters and merge them into big polygons
|
||||
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
|
||||
// hopefully more efficient that collecting everything and will lead to reuse of parts.
|
||||
|
||||
ClusterMerger cm (m_deep_layer.layer (), hc, report_progress (), progress_desc ());
|
||||
cm.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// TODO: iterate only over the called cells?
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
const db::connected_clusters<db::Edge> &cc = hc.clusters_per_cell (c->cell_index ());
|
||||
for (db::connected_clusters<db::Edge>::all_iterator cl = cc.begin_all (); ! cl.at_end (); ++cl) {
|
||||
if (cc.is_root (*cl)) {
|
||||
db::Shapes &s = cm.merged (*cl, c->cell_index ());
|
||||
c->shapes (m_merged_edges.layer ()).insert (s);
|
||||
s.clear (); // not needed anymore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_merged_edges_valid = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeepEdges::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
||||
{
|
||||
m_deep_layer.insert_into (layout, into_cell, into_layer);
|
||||
}
|
||||
|
||||
size_t DeepEdges::size () const
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
const db::Layout &layout = m_deep_layer.layout ();
|
||||
db::CellCounter cc (&layout);
|
||||
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
|
||||
n += cc.weight (*c) * layout.cell (*c).shapes (m_deep_layer.layer ()).size ();
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
Box DeepEdges::bbox () const
|
||||
{
|
||||
return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
|
||||
}
|
||||
|
||||
DeepEdges::length_type DeepEdges::length (const db::Box &box) const
|
||||
{
|
||||
if (box.empty ()) {
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
|
||||
db::MagnificationReducer red;
|
||||
db::cell_variants_collector<db::MagnificationReducer> vars (red);
|
||||
vars.collect (m_merged_edges.layout (), m_merged_edges.initial_cell ());
|
||||
|
||||
DeepEdges::length_type l = 0;
|
||||
|
||||
const db::Layout &layout = m_merged_edges.layout ();
|
||||
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
|
||||
DeepEdges::length_type lc = 0;
|
||||
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_edges.layer ()).begin (db::ShapeIterator::Edges); ! s.at_end (); ++s) {
|
||||
lc += s->edge ().length ();
|
||||
}
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (*c);
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
|
||||
double mag = v->first.mag ();
|
||||
l += v->second * lc * mag;
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
|
||||
} else {
|
||||
// In the clipped case fall back to flat mode
|
||||
return db::AsIfFlatEdges::length (box);
|
||||
}
|
||||
}
|
||||
|
||||
std::string DeepEdges::to_string (size_t nmax) const
|
||||
{
|
||||
return db::AsIfFlatEdges::to_string (nmax);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::filter_in_place (const EdgeFilterBase &filter)
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::filter_in_place (filter);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::filtered (const EdgeFilterBase &filter) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::filtered (filter);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::merged_in_place ()
|
||||
{
|
||||
ensure_merged_edges_valid ();
|
||||
|
||||
// NOTE: this makes both layers share the same resource
|
||||
m_deep_layer = m_merged_edges;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::merged () const
|
||||
{
|
||||
ensure_merged_edges_valid ();
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (m_merged_edges.layout ());
|
||||
|
||||
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_merged_edges.new_layer ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
c->shapes (res->deep_layer ().layer ()) = c->shapes (m_merged_edges.layer ());
|
||||
}
|
||||
|
||||
res->deep_layer ().layer ();
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::and_with (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::and_with (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::and_with (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::and_with (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::not_with (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::not_with (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::not_with (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::not_with (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::xor_with (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::xor_with (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::or_with (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::or_with (other);
|
||||
}
|
||||
|
||||
void
|
||||
DeepEdges::add_from (const DeepLayer &dl)
|
||||
{
|
||||
if (&dl.layout () == &deep_layer ().layout ()) {
|
||||
|
||||
// intra-layout merge
|
||||
|
||||
deep_layer ().layout ().copy_layer (dl.layer (), deep_layer ().layer ());
|
||||
|
||||
} else {
|
||||
|
||||
// inter-layout merge
|
||||
|
||||
db::cell_index_type into_cell = deep_layer ().initial_cell ().cell_index ();
|
||||
db::Layout *into_layout = &deep_layer ().layout ();
|
||||
db::cell_index_type source_cell = dl.initial_cell ().cell_index ();
|
||||
const db::Layout *source_layout = &dl.layout ();
|
||||
|
||||
db::CellMapping cm;
|
||||
cm.create_from_geometry_full (*into_layout, into_cell, *source_layout, source_cell);
|
||||
|
||||
// Actually copy the shapes
|
||||
|
||||
std::map<unsigned int, unsigned int> lm;
|
||||
lm.insert (std::make_pair (dl.layer (), deep_layer ().layer ()));
|
||||
|
||||
std::vector <db::cell_index_type> source_cells;
|
||||
source_cells.push_back (source_cell);
|
||||
db::copy_shapes (*into_layout, *source_layout, db::ICplxTrans (), source_cells, cm.table (), lm);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepEdges::add_in_place (const Edges &other)
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
const DeepEdges *other_deep = dynamic_cast <const DeepEdges *> (other.delegate ());
|
||||
if (other_deep) {
|
||||
|
||||
add_from (other_deep->deep_layer ());
|
||||
|
||||
} else {
|
||||
|
||||
// non-deep to deep merge (flat)
|
||||
|
||||
db::Shapes &shapes = deep_layer ().initial_cell ().shapes (deep_layer ().layer ());
|
||||
for (db::Edges::const_iterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
shapes.insert (*p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::add (const Edges &other) const
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return clone ();
|
||||
} else if (empty ()) {
|
||||
return other.delegate ()->clone ();
|
||||
} else {
|
||||
DeepEdges *new_edges = dynamic_cast<DeepEdges *> (clone ());
|
||||
new_edges->add_in_place (other);
|
||||
return new_edges;
|
||||
}
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::inside_part (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::inside_part (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::outside_part (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::outside_part (other);
|
||||
}
|
||||
|
||||
RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::extended (ext_b, ext_e, ext_o, ext_i, join);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::start_segments (length_type length, double fraction) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::start_segments (length, fraction);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::end_segments (length_type length, double fraction) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::end_segments (length, fraction);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::centers (length_type length, double fraction) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::centers (length, fraction);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_interacting (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_interacting (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_not_interacting (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_not_interacting (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_interacting (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_interacting (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_not_interacting (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_not_interacting (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::in (other, invert);
|
||||
}
|
||||
|
||||
EdgePairs DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::run_check (rel, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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_dbDeepEdges
|
||||
#define HDR_dbDeepEdges
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbAsIfFlatEdges.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
#include "dbEdgePairs.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
class Edges;
|
||||
|
||||
/**
|
||||
* @brief Provides hierarchical edges implementation
|
||||
*/
|
||||
class DB_PUBLIC DeepEdges
|
||||
: public db::AsIfFlatEdges
|
||||
{
|
||||
public:
|
||||
DeepEdges ();
|
||||
DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss);
|
||||
DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics = true);
|
||||
|
||||
DeepEdges (const DeepEdges &other);
|
||||
DeepEdges (const DeepLayer &dl);
|
||||
|
||||
virtual ~DeepEdges ();
|
||||
|
||||
EdgesDelegate *clone () const;
|
||||
|
||||
virtual EdgesIteratorDelegate *begin () const;
|
||||
virtual EdgesIteratorDelegate *begin_merged () const;
|
||||
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const;
|
||||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
|
||||
|
||||
virtual bool empty () const;
|
||||
virtual bool is_merged () const;
|
||||
|
||||
virtual const db::Edge *nth (size_t n) const;
|
||||
virtual bool has_valid_edges () const;
|
||||
virtual bool has_valid_merged_edges () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
|
||||
virtual bool equals (const Edges &other) const;
|
||||
virtual bool less (const Edges &other) const;
|
||||
|
||||
virtual size_t size () const;
|
||||
virtual Box bbox () const;
|
||||
|
||||
virtual DeepEdges::length_type length (const db::Box &) const;
|
||||
|
||||
virtual std::string to_string (size_t nmax) const;
|
||||
|
||||
virtual EdgePairs width_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
return run_check (db::WidthRelation, 0, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
virtual EdgePairs space_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
return run_check (db::SpaceRelation, 0, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
virtual EdgePairs enclosing_check (const Edges &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
return run_check (db::OverlapRelation, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
virtual EdgePairs overlap_check (const Edges &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
return run_check (db::WidthRelation, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
virtual EdgePairs separation_check (const Edges &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
return run_check (db::SpaceRelation, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
virtual EdgePairs inside_check (const Edges &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
return run_check (db::InsideRelation, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
virtual EdgesDelegate *filter_in_place (const EdgeFilterBase &filter);
|
||||
virtual EdgesDelegate *filtered (const EdgeFilterBase &) const;
|
||||
|
||||
virtual EdgesDelegate *merged_in_place ();
|
||||
virtual EdgesDelegate *merged () const;
|
||||
|
||||
virtual EdgesDelegate *and_with (const Edges &other) const;
|
||||
virtual EdgesDelegate *and_with (const Region &other) const;
|
||||
|
||||
virtual EdgesDelegate *not_with (const Edges &other) const;
|
||||
virtual EdgesDelegate *not_with (const Region &other) const;
|
||||
|
||||
virtual EdgesDelegate *xor_with (const Edges &other) const;
|
||||
|
||||
virtual EdgesDelegate *or_with (const Edges &other) const;
|
||||
|
||||
virtual EdgesDelegate *add_in_place (const Edges &other);
|
||||
virtual EdgesDelegate *add (const Edges &other) const;
|
||||
|
||||
virtual EdgesDelegate *inside_part (const Region &other) const;
|
||||
virtual EdgesDelegate *outside_part (const Region &other) const;
|
||||
|
||||
virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const;
|
||||
virtual EdgesDelegate *start_segments (length_type length, double fraction) const;
|
||||
virtual EdgesDelegate *end_segments (length_type length, double fraction) const;
|
||||
virtual EdgesDelegate *centers (length_type length, double fraction) const;
|
||||
|
||||
virtual EdgesDelegate *selected_interacting (const Edges &) const;
|
||||
virtual EdgesDelegate *selected_not_interacting (const Edges &) const;
|
||||
virtual EdgesDelegate *selected_interacting (const Region &) const;
|
||||
virtual EdgesDelegate *selected_not_interacting (const Region &) const;
|
||||
|
||||
virtual EdgesDelegate *in (const Edges &, bool) const;
|
||||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||
|
||||
const DeepLayer &deep_layer () const
|
||||
{
|
||||
return m_deep_layer;
|
||||
}
|
||||
|
||||
DeepLayer &deep_layer ()
|
||||
{
|
||||
return m_deep_layer;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void merged_semantics_changed ();
|
||||
|
||||
private:
|
||||
DeepEdges &operator= (const DeepEdges &other);
|
||||
|
||||
DeepLayer m_deep_layer;
|
||||
mutable DeepLayer m_merged_edges;
|
||||
mutable bool m_merged_edges_valid;
|
||||
|
||||
void init ();
|
||||
void ensure_merged_edges_valid () const;
|
||||
void add_from (const DeepLayer &dl);
|
||||
EdgePairs run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -225,6 +225,7 @@ DeepRegion::empty () const
|
|||
bool
|
||||
DeepRegion::is_merged () const
|
||||
{
|
||||
// TODO: there is no such thing as a "surely merged" state except after merged() maybe
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -539,7 +540,6 @@ DeepRegion::add_from (const DeepLayer &dl)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::add_in_place (const Region &other)
|
||||
{
|
||||
|
|
@ -564,7 +564,6 @@ DeepRegion::add_in_place (const Region &other)
|
|||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ public:
|
|||
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
|
||||
|
||||
virtual bool empty () const;
|
||||
|
||||
virtual bool is_merged () const;
|
||||
|
||||
virtual const db::Polygon *nth (size_t n) const;
|
||||
|
|
@ -71,13 +70,6 @@ public:
|
|||
virtual bool equals (const Region &other) const;
|
||||
virtual bool less (const Region &other) const;
|
||||
|
||||
virtual RegionDelegate *and_with (const Region &other) const;
|
||||
virtual RegionDelegate *not_with (const Region &other) const;
|
||||
virtual RegionDelegate *xor_with (const Region &other) const;
|
||||
|
||||
virtual RegionDelegate *add_in_place (const Region &other);
|
||||
virtual RegionDelegate *add (const Region &other) const;
|
||||
|
||||
virtual bool is_box () const;
|
||||
virtual size_t size () const;
|
||||
|
||||
|
|
@ -87,6 +79,13 @@ public:
|
|||
|
||||
virtual std::string to_string (size_t nmax) const;
|
||||
|
||||
virtual RegionDelegate *and_with (const Region &other) const;
|
||||
virtual RegionDelegate *not_with (const Region &other) const;
|
||||
virtual RegionDelegate *xor_with (const Region &other) const;
|
||||
|
||||
virtual RegionDelegate *add_in_place (const Region &other);
|
||||
virtual RegionDelegate *add (const Region &other) const;
|
||||
|
||||
EdgePairs width_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
|
||||
{
|
||||
return run_single_polygon_check (db::WidthRelation, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
|
|
|
|||
|
|
@ -330,21 +330,13 @@ void DeepShapeStore::remove_ref (unsigned int layout, unsigned int layer)
|
|||
}
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
|
||||
unsigned int
|
||||
DeepShapeStore::layout_for_iter (const db::RecursiveShapeIterator &si)
|
||||
{
|
||||
if (max_area_ratio == 0.0) {
|
||||
max_area_ratio = m_max_area_ratio;
|
||||
}
|
||||
if (max_vertex_count == 0) {
|
||||
max_vertex_count = m_max_vertex_count;
|
||||
}
|
||||
|
||||
unsigned int layout_index = 0;
|
||||
|
||||
layout_map_type::iterator l = m_layout_map.find (si);
|
||||
if (l == m_layout_map.end ()) {
|
||||
|
||||
layout_index = (unsigned int) m_layouts.size ();
|
||||
unsigned int layout_index = (unsigned int) m_layouts.size ();
|
||||
|
||||
m_layouts.push_back (new LayoutHolder ());
|
||||
|
||||
|
|
@ -355,12 +347,23 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
|
|||
}
|
||||
|
||||
m_layout_map[si] = layout_index;
|
||||
return layout_index;
|
||||
|
||||
} else {
|
||||
|
||||
layout_index = l->second;
|
||||
|
||||
return l->second;
|
||||
}
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
|
||||
{
|
||||
if (max_area_ratio == 0.0) {
|
||||
max_area_ratio = m_max_area_ratio;
|
||||
}
|
||||
if (max_vertex_count == 0) {
|
||||
max_vertex_count = m_max_vertex_count;
|
||||
}
|
||||
|
||||
unsigned int layout_index = layout_for_iter (si);
|
||||
|
||||
db::Layout &layout = m_layouts[layout_index]->layout;
|
||||
db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
|
||||
|
|
@ -376,7 +379,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
|
|||
// Build the working hierarchy from the recursive shape iterator
|
||||
try {
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Building working hierarchy")));
|
||||
tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
|
||||
|
||||
builder.set_shape_receiver (&clip);
|
||||
db::RecursiveShapeIterator (si).push (& builder);
|
||||
|
|
@ -390,6 +393,36 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
|
|||
return DeepLayer (this, layout_index, layer_index);
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si)
|
||||
{
|
||||
unsigned int layout_index = layout_for_iter (si);
|
||||
|
||||
db::Layout &layout = m_layouts[layout_index]->layout;
|
||||
db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
|
||||
|
||||
unsigned int layer_index = layout.insert_layer ();
|
||||
builder.set_target_layer (layer_index);
|
||||
|
||||
// The chain of operators for producing clipped and reduced polygon references
|
||||
db::EdgeBuildingHierarchyBuilderShapeReceiver refs;
|
||||
|
||||
// Build the working hierarchy from the recursive shape iterator
|
||||
try {
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
|
||||
|
||||
builder.set_shape_receiver (&refs);
|
||||
db::RecursiveShapeIterator (si).push (& builder);
|
||||
builder.set_shape_receiver (0);
|
||||
|
||||
} catch (...) {
|
||||
builder.set_shape_receiver (0);
|
||||
throw;
|
||||
}
|
||||
|
||||
return DeepLayer (this, layout_index, layer_index);
|
||||
}
|
||||
|
||||
void
|
||||
DeepShapeStore::invalidate_hier ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -240,6 +240,15 @@ public:
|
|||
*/
|
||||
DeepLayer create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio = 0.0, size_t max_vertex_count = 0);
|
||||
|
||||
/**
|
||||
* @brief Inserts an edge layer into the deep shape store
|
||||
*
|
||||
* This method will create a new layer inside the deep shape store as a
|
||||
* working copy of the original layer. This method creates a layer
|
||||
* for edges.
|
||||
*/
|
||||
DeepLayer create_edge_layer (const db::RecursiveShapeIterator &si);
|
||||
|
||||
/**
|
||||
* @brief Inserts the deep layer's shapes into some target layout
|
||||
*/
|
||||
|
|
@ -459,6 +468,8 @@ private:
|
|||
void add_ref (unsigned int layout, unsigned int layer);
|
||||
void remove_ref (unsigned int layout, unsigned int layer);
|
||||
|
||||
unsigned int layout_for_iter (const db::RecursiveShapeIterator &si);
|
||||
|
||||
void require_singular () const;
|
||||
|
||||
void issue_variants (unsigned int layout, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_map);
|
||||
|
|
|
|||
|
|
@ -439,6 +439,26 @@ public:
|
|||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the base verbosity
|
||||
*
|
||||
* Setting this value will make timing measurements appear at least at
|
||||
* the given verbosity level and more detailed timing at the given level
|
||||
* plus 10. The default level is 30.
|
||||
*/
|
||||
void set_base_verbosity (int vb)
|
||||
{
|
||||
mp_delegate->set_base_verbosity (vb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the base verbosity
|
||||
*/
|
||||
unsigned int base_verbosity () const
|
||||
{
|
||||
return mp_delegate->base_verbosity ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable progress reporting
|
||||
*
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace db
|
|||
|
||||
EdgesDelegate::EdgesDelegate ()
|
||||
{
|
||||
m_base_verbosity = 30;
|
||||
m_report_progress = false;
|
||||
m_merged_semantics = true;
|
||||
m_strict_handling = false;
|
||||
|
|
@ -44,6 +45,7 @@ EdgesDelegate &
|
|||
EdgesDelegate::operator= (const EdgesDelegate &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_base_verbosity = other.m_base_verbosity;
|
||||
m_report_progress = other.m_report_progress;
|
||||
m_merged_semantics = other.m_merged_semantics;
|
||||
m_strict_handling = other.m_strict_handling;
|
||||
|
|
@ -56,6 +58,11 @@ EdgesDelegate::~EdgesDelegate ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void EdgesDelegate::set_base_verbosity (int vb)
|
||||
{
|
||||
m_base_verbosity = vb;
|
||||
}
|
||||
|
||||
void EdgesDelegate::enable_progress (const std::string &progress_desc)
|
||||
{
|
||||
m_report_progress = true;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,12 @@ public:
|
|||
|
||||
virtual EdgesDelegate *clone () const = 0;
|
||||
|
||||
void set_base_verbosity (int vb);
|
||||
int base_verbosity () const
|
||||
{
|
||||
return m_base_verbosity;
|
||||
}
|
||||
|
||||
void enable_progress (const std::string &progress_desc);
|
||||
void disable_progress ();
|
||||
|
||||
|
|
@ -176,6 +182,7 @@ private:
|
|||
bool m_strict_handling;
|
||||
bool m_report_progress;
|
||||
std::string m_progress_desc;
|
||||
int m_base_verbosity;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,20 @@ interaction_test (const db::PolygonRef &a, const db::PolygonRef &b, const db::un
|
|||
}
|
||||
}
|
||||
|
||||
template <class Trans>
|
||||
static bool
|
||||
interaction_test (const db::Edge &a, const db::Edge &b, const Trans &trans)
|
||||
{
|
||||
return a.intersect (b.transformed (trans));
|
||||
}
|
||||
|
||||
template <class C>
|
||||
static bool
|
||||
interaction_test (const db::Edge &a, const db::Edge &b, const db::unit_trans<C> &)
|
||||
{
|
||||
return a.intersect (b);
|
||||
}
|
||||
|
||||
template <class T, class Trans>
|
||||
bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned int lb, const Trans &trans) const
|
||||
{
|
||||
|
|
@ -212,6 +226,8 @@ bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned
|
|||
// explicit instantiations
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::UnitTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::ICplxTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::UnitTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::ICplxTrans &trans) const;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// local_cluster implementation
|
||||
|
|
@ -560,7 +576,9 @@ size_t local_cluster<T>::split (double max_area_ratio, Iter &output) const
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_cluster<db::PolygonRef>;
|
||||
template class DB_PUBLIC local_cluster<db::Edge>;
|
||||
template DB_PUBLIC size_t local_cluster<db::PolygonRef>::split<std::back_insert_iterator<std::list<local_cluster<db::PolygonRef> > > > (double, std::back_insert_iterator<std::list<local_cluster<db::PolygonRef> > > &) const;
|
||||
template DB_PUBLIC size_t local_cluster<db::Edge>::split<std::back_insert_iterator<std::list<local_cluster<db::Edge> > > > (double, std::back_insert_iterator<std::list<local_cluster<db::Edge> > > &) const;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// local_clusters implementation
|
||||
|
|
@ -891,6 +909,7 @@ local_clusters<T>::apply_attr_equivalences (const tl::equivalence_clusters<unsig
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_clusters<db::PolygonRef>;
|
||||
template class DB_PUBLIC local_clusters<db::Edge>;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// connected_clusters_iterator implementation
|
||||
|
|
@ -912,6 +931,7 @@ connected_clusters_iterator<T>::connected_clusters_iterator (const connected_clu
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC connected_clusters_iterator<db::PolygonRef>;
|
||||
template class DB_PUBLIC connected_clusters_iterator<db::Edge>;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// connected_clusters implementation
|
||||
|
|
@ -975,6 +995,7 @@ connected_clusters<T>::find_cluster_with_connection (const ClusterInstance &inst
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC connected_clusters<db::PolygonRef>;
|
||||
template class DB_PUBLIC connected_clusters<db::Edge>;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// connected_clusters implementation
|
||||
|
|
@ -1909,7 +1930,7 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
|
|||
// handle local to instance connections
|
||||
|
||||
{
|
||||
std::list<local_cluster<db::PolygonRef> > heap;
|
||||
std::list<local_cluster<T> > heap;
|
||||
double area_ratio = 10.0;
|
||||
|
||||
static std::string desc = tl::to_string (tr ("Local to instance treatment"));
|
||||
|
|
@ -1922,12 +1943,12 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
|
|||
|
||||
// we do not actually need the original clusters. For a better performance we optimize the
|
||||
// area ratio and split, but we keep the ID the same.
|
||||
std::back_insert_iterator<std::list<local_cluster<db::PolygonRef> > > iout = std::back_inserter (heap);
|
||||
std::back_insert_iterator<std::list<local_cluster<T> > > iout = std::back_inserter (heap);
|
||||
size_t n = c->split (area_ratio, iout);
|
||||
if (n == 0) {
|
||||
bs2.insert1 (c.operator-> (), 0);
|
||||
} else {
|
||||
std::list<local_cluster<db::PolygonRef> >::iterator h = heap.end ();
|
||||
typename std::list<local_cluster<T> >::iterator h = heap.end ();
|
||||
while (n-- > 0) {
|
||||
bs2.insert1 ((--h).operator-> (), 0);
|
||||
}
|
||||
|
|
@ -2053,6 +2074,11 @@ template <class Trans> void insert_transformed (db::Layout &layout, db::Shapes &
|
|||
shapes.insert (db::PolygonRef (poly, layout.shape_repository ()));
|
||||
}
|
||||
|
||||
template <class Trans> void insert_transformed (db::Layout & /*layout*/, db::Shapes &shapes, const db::Edge &s, const Trans &t)
|
||||
{
|
||||
shapes.insert (s.transformed (t));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::return_to_hierarchy (db::Layout &layout, const std::map<unsigned int, unsigned int> &lm) const
|
||||
|
|
@ -2085,6 +2111,7 @@ hier_clusters<T>::return_to_hierarchy (db::Layout &layout, const std::map<unsign
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC hier_clusters<db::PolygonRef>;
|
||||
template class DB_PUBLIC hier_clusters<db::Edge>;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// recursive_cluster_shape_iterator implementation
|
||||
|
|
@ -2199,6 +2226,7 @@ void recursive_cluster_shape_iterator<T>::down (db::cell_index_type ci, typename
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC recursive_cluster_shape_iterator<db::PolygonRef>;
|
||||
template class DB_PUBLIC recursive_cluster_shape_iterator<db::Edge>;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// recursive_cluster_iterator implementation
|
||||
|
|
@ -2271,6 +2299,7 @@ void recursive_cluster_iterator<T>::down (db::cell_index_type ci, typename db::l
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC recursive_cluster_iterator<db::PolygonRef>;
|
||||
template class DB_PUBLIC recursive_cluster_iterator<db::Edge>;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// incoming_cluster_connections implementation
|
||||
|
|
@ -2351,5 +2380,6 @@ incoming_cluster_connections<T>::ensure_computed_parent (db::cell_index_type ci)
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC incoming_cluster_connections<db::PolygonRef>;
|
||||
template class DB_PUBLIC incoming_cluster_connections<db::Edge>;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -598,4 +598,38 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &sha
|
|||
target->insert (db::PolygonRef (shape, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
|
||||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
push (poly, region, complex_region, target);
|
||||
} else if (shape.is_box ()) {
|
||||
push (shape.box (), region, complex_region, target);
|
||||
} else if (shape.is_edge ()) {
|
||||
target->insert (shape.edge ());
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Box &box, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (! box.empty ()) {
|
||||
target->insert (db::Edge (box.p1 (), box.upper_left ()));
|
||||
target->insert (db::Edge (box.upper_left (), box.p2 ()));
|
||||
target->insert (db::Edge (box.p2 (), box.lower_right ()));
|
||||
target->insert (db::Edge (box.lower_right (), box.p1 ()));
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
|
||||
target->insert (*e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,18 @@ private:
|
|||
db::property_names_id_type m_text_prop_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An edge-generating shape receiver that feeds a shapes array after turning the shapes into edges
|
||||
*/
|
||||
class DB_PUBLIC EdgeBuildingHierarchyBuilderShapeReceiver
|
||||
: public HierarchyBuilderShapeReceiver
|
||||
{
|
||||
public:
|
||||
virtual void push (const db::Shape &shape, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class building a hierarchy from a recursive shape iterator in push mode
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue