mirror of https://github.com/KLayout/klayout.git
WIP: some refactoring.
This commit is contained in:
parent
2fa0d21615
commit
0bb45dd092
|
|
@ -34,171 +34,38 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// BoolAndOrNotLocalOperation implementation
|
||||
// Shape reference translator
|
||||
|
||||
namespace {
|
||||
|
||||
class PolygonRefGenerator
|
||||
: public PolygonSink
|
||||
template <class Ref>
|
||||
class shape_reference_translator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor specifying an external vector for storing the polygons
|
||||
*/
|
||||
PolygonRefGenerator (db::Layout *layout, std::set<db::PolygonRef> &polyrefs)
|
||||
: PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs)
|
||||
{ }
|
||||
typedef typename Ref::shape_type shape_type;
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
virtual void put (const db::Polygon &polygon)
|
||||
shape_reference_translator (db::Layout *target_layout)
|
||||
: mp_layout (target_layout)
|
||||
{
|
||||
mp_polyrefs->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Ref operator() (const Ref &ref) const
|
||||
{
|
||||
shape_type sh = ref.obj ().transformed (ref.trans ());
|
||||
return Ref (sh, mp_layout->shape_repository ());
|
||||
}
|
||||
|
||||
template <class Trans>
|
||||
Ref operator() (const Ref &ref, const Trans &tr) const
|
||||
{
|
||||
shape_type sh = ref.obj ().transformed (tr * Trans (ref.trans ()));
|
||||
return Ref (sh, mp_layout->shape_repository ());
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
std::set<db::PolygonRef> *mp_polyrefs;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and)
|
||||
: m_is_and (is_and)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
LocalOperation::on_empty_intruder_mode
|
||||
BoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? LocalOperation::Drop : LocalOperation::Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
BoolAndOrNotLocalOperation::description () const
|
||||
{
|
||||
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
|
||||
}
|
||||
|
||||
void
|
||||
BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const
|
||||
{
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (ShapeInteractions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &subject = interactions.shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || p1 > 0) {
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonGenerator pg (pr, true, true);
|
||||
ep.process (pg, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wrap_count)
|
||||
: m_wrap_count (wrap_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const
|
||||
{
|
||||
if (m_wrap_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
std::set<unsigned int> seen;
|
||||
|
||||
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
if (seen.find (i->first) == seen.end ()) {
|
||||
seen.insert (i->first);
|
||||
const db::PolygonRef &subject = interactions.shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
for (db::ShapeInteractions::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
|
||||
// don't take the same (really the same, not an identical one) shape twice - the interaction
|
||||
// set does not take care to list just one copy of the same item on the intruder side.
|
||||
if (seen.find (*o) == seen.end ()) {
|
||||
seen.insert (*o);
|
||||
const db::PolygonRef &intruder = interactions.shape (*o);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::MergeOp op (m_wrap_count - 1);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonGenerator pg (pr, true, true);
|
||||
ep.process (pg, op);
|
||||
}
|
||||
|
||||
SelfOverlapMergeLocalOperation::on_empty_intruder_mode SelfOverlapMergeLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_wrap_count > 1 ? LocalOperation::Drop : LocalOperation::Copy;
|
||||
}
|
||||
|
||||
std::string SelfOverlapMergeLocalOperation::description () const
|
||||
{
|
||||
return tl::sprintf (tl::to_string (tr ("Self-overlap (wrap count %d)")), int (m_wrap_count));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// LocalProcessorCellContext implementation
|
||||
|
||||
|
|
@ -226,10 +93,9 @@ LocalProcessorCellContext::propagate (const std::set<db::PolygonRef> &res)
|
|||
tl_assert (d->parent != 0);
|
||||
|
||||
db::Layout *subject_layout = d->parent->layout ();
|
||||
|
||||
shape_reference_translator<db::PolygonRef> rt (subject_layout);
|
||||
for (std::set<db::PolygonRef>::const_iterator r = res.begin (); r != res.end (); ++r) {
|
||||
db::Polygon poly = r->obj ().transformed (d->cell_inst * db::ICplxTrans (r->trans ()));
|
||||
d->parent_context->propagated ().insert (db::PolygonRef (poly, subject_layout->shape_repository ()));
|
||||
d->parent_context->propagated ().insert (rt (*r, d->cell_inst));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -411,8 +277,8 @@ public:
|
|||
// In order to guarantee the refs come from the subject layout, we'd need to
|
||||
// rewrite them to the subject layout if required.
|
||||
if (!mp_result->has_shape_id (id2)) {
|
||||
db::Polygon poly = ref2->obj ().transformed (ref2->trans ());
|
||||
mp_result->add_shape (id2, db::PolygonRef (poly, mp_layout->shape_repository ()));
|
||||
db::shape_reference_translator<db::PolygonRef> rt (mp_layout);
|
||||
mp_result->add_shape (id2, rt (*ref2));
|
||||
}
|
||||
} else {
|
||||
mp_result->add_shape (id2, *ref2);
|
||||
|
|
@ -463,42 +329,14 @@ public:
|
|||
db::box_convert <db::CellInst, true> inst_bc (*mp_intruder_layout, m_intruder_layer);
|
||||
mp_result->add_shape (id1, *ref);
|
||||
|
||||
// Find all instance array members that potentially interact with the shape and use
|
||||
// add_shapes_from_intruder_inst on them
|
||||
for (db::CellInstArray::iterator n = inst->begin_touching (ref->box ().enlarged (db::Vector (m_dist - 1, m_dist - 1)), inst_bc); !n.at_end (); ++n) {
|
||||
|
||||
db::ICplxTrans tn = inst->complex_trans (*n);
|
||||
|
||||
db::Box region = ref->box ().transformed (tn.inverted ()).enlarged (db::Vector (m_dist, m_dist)) & intruder_cell.bbox (m_intruder_layer).enlarged (db::Vector (m_dist, m_dist));
|
||||
if (! region.empty ()) {
|
||||
|
||||
// @@@ TODO: should be lighter, cache, handle arrays ..
|
||||
db::RecursiveShapeIterator si (*mp_intruder_layout, intruder_cell, m_intruder_layer, region);
|
||||
si.shape_flags (polygon_ref_flags ());
|
||||
while (! si.at_end ()) {
|
||||
|
||||
const db::PolygonRef *ref2 = si.shape ().basic_ptr (db::PolygonRef::tag ());
|
||||
|
||||
// reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on
|
||||
// the intruder side.
|
||||
std::map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2));
|
||||
if (k == m_inst_shape_ids.end ()) {
|
||||
|
||||
k = m_inst_shape_ids.insert (std::make_pair (std::make_pair (inst_id, ref2), mp_result->next_id ())).first;
|
||||
|
||||
db::Polygon poly = ref2->obj ().transformed (tn * si.trans () * db::ICplxTrans (ref2->trans ()));
|
||||
// NOTE: we intentionally rewrite to the subject layout - this way polygon refs in the context come from the
|
||||
// subject, not from the intruder.
|
||||
mp_result->add_shape (k->second, db::PolygonRef (poly, mp_subject_layout->shape_repository()));
|
||||
|
||||
}
|
||||
|
||||
mp_result->add_interaction (id1, k->second);
|
||||
|
||||
++si;
|
||||
|
||||
}
|
||||
|
||||
add_shapes_from_intruder_inst (id1, intruder_cell, tn, inst_id, region);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -509,6 +347,39 @@ private:
|
|||
db::Coord m_dist;
|
||||
ShapeInteractions *mp_result;
|
||||
std::map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int> m_inst_shape_ids;
|
||||
|
||||
void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int inst_id, const db::Box ®ion)
|
||||
{
|
||||
db::shape_reference_translator<db::PolygonRef> rt (mp_subject_layout);
|
||||
|
||||
// Look up all shapes from the intruder instance which interact with the subject shape
|
||||
// (given through region)
|
||||
// @@@ TODO: should be lighter, cache, handle arrays ..
|
||||
db::RecursiveShapeIterator si (*mp_intruder_layout, intruder_cell, m_intruder_layer, region);
|
||||
si.shape_flags (polygon_ref_flags ());
|
||||
while (! si.at_end ()) {
|
||||
|
||||
const db::PolygonRef *ref2 = si.shape ().basic_ptr (db::PolygonRef::tag ());
|
||||
|
||||
// reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on
|
||||
// the intruder side.
|
||||
std::map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2));
|
||||
if (k == m_inst_shape_ids.end ()) {
|
||||
|
||||
k = m_inst_shape_ids.insert (std::make_pair (std::make_pair (inst_id, ref2), mp_result->next_id ())).first;
|
||||
|
||||
// NOTE: we intentionally rewrite to the *subject* layout - this way polygon refs in the context come from the
|
||||
// subject, not from the intruder.
|
||||
mp_result->add_shape (k->second, rt (*ref2, tn * si.trans ()));
|
||||
|
||||
}
|
||||
|
||||
mp_result->add_interaction (id1, k->second);
|
||||
|
||||
++si;
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static bool
|
||||
|
|
@ -842,6 +713,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
|
|||
for (std::map<const db::CellInstArray *, interaction_value_type>::const_iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
db::Cell &subject_child_cell = mp_subject_layout->cell (i->first->object ().cell_index ());
|
||||
db::shape_reference_translator<db::PolygonRef> rt (mp_subject_layout);
|
||||
|
||||
for (db::CellInstArray::iterator n = i->first->begin (); ! n.at_end (); ++n) {
|
||||
|
||||
|
|
@ -856,10 +728,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
|
|||
// @@@ transformation of polygon refs - can this be done more efficiently?
|
||||
for (std::set<db::PolygonRef>::const_iterator p = i->second.second.begin (); p != i->second.second.end (); ++p) {
|
||||
if (nbox.overlaps (p->box ())) {
|
||||
db::Polygon poly = p->obj ().transformed (tni * db::ICplxTrans (p->trans ()));
|
||||
// NOTE: we intentionally transform into the *subject* layout so the intruders are local to
|
||||
// the subject layout.
|
||||
intruders_below.second.insert (db::PolygonRef (poly, mp_subject_layout->shape_repository ()));
|
||||
intruders_below.second.insert (rt (*p, tni));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "dbLayout.h"
|
||||
#include "dbPluginCommon.h"
|
||||
#include "dbLocalOperation.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -77,50 +78,6 @@ private:
|
|||
unsigned int m_id;
|
||||
};
|
||||
|
||||
class DB_PLUGIN_PUBLIC LocalOperation
|
||||
{
|
||||
public:
|
||||
enum on_empty_intruder_mode {
|
||||
Ignore = 0, Copy, Drop
|
||||
};
|
||||
|
||||
LocalOperation () { }
|
||||
virtual ~LocalOperation () { }
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const = 0;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const = 0;
|
||||
virtual std::string description () const = 0;
|
||||
virtual db::Coord dist () const { return 0; }
|
||||
};
|
||||
|
||||
class DB_PLUGIN_PUBLIC BoolAndOrNotLocalOperation
|
||||
: public LocalOperation
|
||||
{
|
||||
public:
|
||||
BoolAndOrNotLocalOperation (bool is_and);
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
};
|
||||
|
||||
class DB_PLUGIN_PUBLIC SelfOverlapMergeLocalOperation
|
||||
: public LocalOperation
|
||||
{
|
||||
public:
|
||||
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
unsigned int m_wrap_count;
|
||||
};
|
||||
|
||||
// @@@ TODO: should be hidden (private data?)
|
||||
struct DB_PLUGIN_PUBLIC LocalProcessorCellDrop
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "dbHierProcessor.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlInternational.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// BoolAndOrNotLocalOperation implementation
|
||||
|
||||
namespace {
|
||||
|
||||
class PolygonRefGenerator
|
||||
: public PolygonSink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor specifying an external vector for storing the polygons
|
||||
*/
|
||||
PolygonRefGenerator (db::Layout *layout, std::set<db::PolygonRef> &polyrefs)
|
||||
: PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
virtual void put (const db::Polygon &polygon)
|
||||
{
|
||||
mp_polyrefs->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
std::set<db::PolygonRef> *mp_polyrefs;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and)
|
||||
: m_is_and (is_and)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
LocalOperation::on_empty_intruder_mode
|
||||
BoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? LocalOperation::Drop : LocalOperation::Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
BoolAndOrNotLocalOperation::description () const
|
||||
{
|
||||
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
|
||||
}
|
||||
|
||||
void
|
||||
BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const
|
||||
{
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (ShapeInteractions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &subject = interactions.shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || p1 > 0) {
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonGenerator pg (pr, true, true);
|
||||
ep.process (pg, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wrap_count)
|
||||
: m_wrap_count (wrap_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const
|
||||
{
|
||||
if (m_wrap_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
std::set<unsigned int> seen;
|
||||
|
||||
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
if (seen.find (i->first) == seen.end ()) {
|
||||
seen.insert (i->first);
|
||||
const db::PolygonRef &subject = interactions.shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
for (db::ShapeInteractions::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
|
||||
// don't take the same (really the same, not an identical one) shape twice - the interaction
|
||||
// set does not take care to list just one copy of the same item on the intruder side.
|
||||
if (seen.find (*o) == seen.end ()) {
|
||||
seen.insert (*o);
|
||||
const db::PolygonRef &intruder = interactions.shape (*o);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::MergeOp op (m_wrap_count - 1);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonGenerator pg (pr, true, true);
|
||||
ep.process (pg, op);
|
||||
}
|
||||
|
||||
SelfOverlapMergeLocalOperation::on_empty_intruder_mode SelfOverlapMergeLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_wrap_count > 1 ? LocalOperation::Drop : LocalOperation::Copy;
|
||||
}
|
||||
|
||||
std::string SelfOverlapMergeLocalOperation::description () const
|
||||
{
|
||||
return tl::sprintf (tl::to_string (tr ("Self-overlap (wrap count %d)")), int (m_wrap_count));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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_dbLocalOperation
|
||||
#define HDR_dbLocalOperation
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbPluginCommon.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class ShapeInteractions;
|
||||
|
||||
/**
|
||||
* @brief A base class for "local operations"
|
||||
* A local operation is any operation whose result can be computed by
|
||||
* combining the results derived from individual shape pairs.
|
||||
* The shape pairs can originate from different or the same layer.
|
||||
* If the layers are different, one layer is the subject layer, the
|
||||
* other layer is the "intruder" layer. Subject shapes are always
|
||||
* considered, intruder shapes only if they interact with subject shapes.
|
||||
* This class implements the actual operation. It receives a
|
||||
* cluster of subject shapes vs. corresponding intruder shapes.
|
||||
*/
|
||||
class DB_PLUGIN_PUBLIC LocalOperation
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Indicates the desired behaviour for subject shapes for which there is no intruder
|
||||
*/
|
||||
enum on_empty_intruder_mode {
|
||||
/**
|
||||
* @brief Don't imply a specific behaviour
|
||||
*/
|
||||
Ignore = 0,
|
||||
|
||||
/**
|
||||
* @brief Copy the subject shape
|
||||
*/
|
||||
Copy,
|
||||
|
||||
/**
|
||||
* @brief Drop the subject shape
|
||||
*/
|
||||
Drop
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
LocalOperation () { }
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~LocalOperation () { }
|
||||
|
||||
/**
|
||||
* @brief Computes the results from a given set of interacting shapes
|
||||
* @param layout The layout to which the shapes belong
|
||||
* @param interactions The interaction set
|
||||
* @param result The container to which the results are written
|
||||
*/
|
||||
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Indicates the desired behaviour when a shape does not have an intruder
|
||||
*/
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const { return Ignore; }
|
||||
|
||||
/**
|
||||
* @brief Gets a description text for this operation
|
||||
*/
|
||||
virtual std::string description () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Gets the interaction distance
|
||||
* A distance of means the shapes must overlap in order to interact.
|
||||
*/
|
||||
virtual db::Coord dist () const { return 0; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation
|
||||
*/
|
||||
class DB_PLUGIN_PUBLIC BoolAndOrNotLocalOperation
|
||||
: public LocalOperation
|
||||
{
|
||||
public:
|
||||
BoolAndOrNotLocalOperation (bool is_and);
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a merge operation with an overlap count
|
||||
* With a given wrap_count, the result will only contains shapes where
|
||||
* the original shapes overlap at least "wrap_count" times.
|
||||
*/
|
||||
class DB_PLUGIN_PUBLIC SelfOverlapMergeLocalOperation
|
||||
: public LocalOperation
|
||||
{
|
||||
public:
|
||||
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
unsigned int m_wrap_count;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -7,10 +7,12 @@ include($$PWD/../../../db_plugin.pri)
|
|||
HEADERS = \
|
||||
dbNetExtractor.h \
|
||||
dbHierProcessor.h \
|
||||
dbLocalOperation.h
|
||||
|
||||
SOURCES = \
|
||||
dbNetExtractor.cc \
|
||||
dbHierProcessor.cc \
|
||||
dbNetExtractorPlugin.cc \
|
||||
gsiDeclDbNetExtractor.cc \
|
||||
dbLocalOperation.cc
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue