WIP: deep edges and edge pairs.

This commit is contained in:
Matthias Koefferlein 2019-02-10 10:22:47 +01:00
parent 4abc38a5cc
commit f22217b6c4
16 changed files with 1107 additions and 31 deletions

View File

@ -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") {

View File

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

View File

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

View File

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

673
src/db/db/dbDeepEdges.cc Normal file
View File

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

175
src/db/db/dbDeepEdges.h Normal file
View File

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

View File

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

View File

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

View File

@ -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 ()
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 &region, 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);
}
}
// ---------------------------------------------------------------------------------------------
}

View File

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