Deep regions: some more operations implemented hierarchically

- snap (!) - but only for gx == gy
- filtering
- interact/inside/outside/overlap + not_... variants
- edges
This commit is contained in:
Matthias Koefferlein 2019-02-13 01:07:32 +01:00
parent 10f9de8b66
commit b0fc2be96e
17 changed files with 597 additions and 119 deletions

View File

@ -619,6 +619,40 @@ static inline db::Coord snap_to_grid (db::Coord c, db::Coord g)
return c;
}
db::Polygon
AsIfFlatRegion::snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap)
{
db::Polygon pnew;
for (size_t i = 0; i < poly.holes () + 1; ++i) {
heap.clear ();
db::Polygon::polygon_contour_iterator b, e;
if (i == 0) {
b = poly.begin_hull ();
e = poly.end_hull ();
} else {
b = poly.begin_hole ((unsigned int) (i - 1));
e = poly.end_hole ((unsigned int) (i - 1));
}
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
heap.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy)));
}
if (i == 0) {
pnew.assign_hull (heap.begin (), heap.end ());
} else {
pnew.insert_hole (heap.begin (), heap.end ());
}
}
return pnew;
}
RegionDelegate *
AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy)
{
@ -627,40 +661,10 @@ AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy)
gx = std::max (db::Coord (1), gx);
gy = std::max (db::Coord (1), gy);
std::vector<db::Point> pts;
std::vector<db::Point> heap;
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
db::Polygon pnew;
for (size_t i = 0; i < p->holes () + 1; ++i) {
pts.clear ();
db::Polygon::polygon_contour_iterator b, e;
if (i == 0) {
b = p->begin_hull ();
e = p->end_hull ();
} else {
b = p->begin_hole ((unsigned int) (i - 1));
e = p->end_hole ((unsigned int) (i - 1));
}
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
pts.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy)));
}
if (i == 0) {
pnew.assign_hull (pts.begin (), pts.end ());
} else {
pnew.insert_hole (pts.begin (), pts.end ());
}
}
new_region->raw_polygons ().insert (pnew);
new_region->raw_polygons ().insert (snapped_polygon (*p, gx, gy, heap));
}
return new_region.release ();
@ -677,22 +681,25 @@ struct DB_PUBLIC StrangePolygonInsideFunc
}
};
void
AsIfFlatRegion::produce_shape_for_strange_polygon (const db::Polygon &poly, db::Shapes &shapes)
{
EdgeProcessor ep;
ep.insert (poly);
StrangePolygonInsideFunc inside;
db::GenericMerge<StrangePolygonInsideFunc> op (inside);
db::ShapeGenerator pc (shapes, false);
db::PolygonGenerator pg (pc, false, false);
ep.process (pg, op);
}
RegionDelegate *
AsIfFlatRegion::strange_polygon_check () const
{
EdgeProcessor ep;
std::auto_ptr<FlatRegion> new_region (new FlatRegion (merged_semantics ()));
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
ep.clear ();
ep.insert (*p);
StrangePolygonInsideFunc inside;
db::GenericMerge<StrangePolygonInsideFunc> op (inside);
db::ShapeGenerator pc (new_region->raw_polygons (), false);
db::PolygonGenerator pg (pc, false, false);
ep.process (pg, op);
produce_shape_for_strange_polygon (*p, new_region->raw_polygons ());
}
return new_region.release ();

View File

@ -212,6 +212,9 @@ protected:
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
static void produce_shape_for_strange_polygon (const db::Polygon &poly, db::Shapes &shapes);
static db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap);
private:
AsIfFlatRegion &operator= (const AsIfFlatRegion &other);

View File

@ -87,6 +87,28 @@ struct DB_PUBLIC MagnificationReducer
}
};
/**
* @brief A magnification and orientation reducer
*
* This reducer incarnation reduces the transformation to it's rotation/mirror/magnification part (2d matrix)
*/
struct DB_PUBLIC MagnificationAndOrientationReducer
{
typedef tl::true_tag is_translation_invariant;
db::ICplxTrans operator () (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
res.disp (db::Vector ());
return res;
}
db::Trans operator () (const db::Trans &trans) const
{
return db::Trans (trans.fp_trans ());
}
};
/**
* @brief A grid reducer
*
@ -125,13 +147,32 @@ private:
inline db::Coord mod (db::Coord c) const
{
if (c < 0) {
return m_grid - (-c) % m_grid;
c = m_grid - (-c) % m_grid;
if (c == m_grid) {
return 0;
} else {
return c;
}
} else {
return c % m_grid;
}
}
};
/**
* @brief A base class for the variants collector
*/
class DB_PUBLIC VariantsCollectorBase
{
public:
VariantsCollectorBase () { }
virtual ~VariantsCollectorBase () { }
virtual void collect (const db::Layout &layout, const db::Cell &top_cell) = 0;
virtual void separate_variants (db::Layout &layout, db::Cell &top_cell, std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > *var_table = 0) = 0;
virtual const std::map<db::ICplxTrans, size_t> &variants (db::cell_index_type ci) const = 0;
};
/**
* @brief A class computing variants for cells according to a given criterion
*
@ -149,10 +190,20 @@ private:
*/
template <class Reduce>
class DB_PUBLIC cell_variants_collector
: public VariantsCollectorBase
{
public:
typedef cell_variants_reduce_traits<Reduce> compare_traits;
/**
* @brief Creates a variant extractor
*/
cell_variants_collector ()
: m_red ()
{
// .. nothing yet ..
}
/**
* @brief Creates a variant extractor
*/
@ -165,7 +216,7 @@ public:
/**
* @brief Collects cell variants for the given layout starting from the top cell
*/
void collect (const db::Layout &layout, const db::Cell &top_cell)
virtual void collect (const db::Layout &layout, const db::Cell &top_cell)
{
// The top cell gets a "variant" with unit transformation
m_variants [top_cell.cell_index ()].insert (std::make_pair (db::ICplxTrans (), 1));
@ -207,7 +258,7 @@ public:
* If given, *var_table will be filled with a map giving the new cell and variant against
* the old cell for all cells with more than one variant.
*/
void separate_variants (db::Layout &layout, db::Cell &top_cell, std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > *var_table = 0)
virtual void separate_variants (db::Layout &layout, db::Cell &top_cell, std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > *var_table = 0)
{
db::LayoutLocker locker (&layout);
@ -309,7 +360,7 @@ public:
* The keys of the map are the variants, the values is the instance count of the variant
* (as seen from the top cell).
*/
const std::map<db::ICplxTrans, size_t> &variants (db::cell_index_type ci) const
virtual const std::map<db::ICplxTrans, size_t> &variants (db::cell_index_type ci) const
{
std::map<db::cell_index_type, std::map<db::ICplxTrans, size_t> >::const_iterator v = m_variants.find (ci);
static std::map<db::ICplxTrans, size_t> empty_set;

View File

@ -243,7 +243,7 @@ EdgePairsDelegate *DeepEdgePairs::filtered (const EdgePairFilterBase &filter) co
RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
{
db::DeepLayer new_layer = m_deep_layer.new_layer ();
db::DeepLayer new_layer = m_deep_layer.derived ();
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
@ -261,7 +261,7 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const
{
db::DeepLayer new_layer = m_deep_layer.new_layer ();
db::DeepLayer new_layer = m_deep_layer.derived ();
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {

View File

@ -354,7 +354,7 @@ DeepEdges::ensure_merged_edges_valid () const
{
if (! m_merged_edges_valid) {
m_merged_edges = m_deep_layer.new_layer ();
m_merged_edges = m_deep_layer.derived ();
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
@ -480,7 +480,7 @@ EdgesDelegate *DeepEdges::merged () const
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 ()));
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_merged_edges.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
c->shapes (res->deep_layer ().layer ()) = c->shapes (m_merged_edges.layer ());
}

View File

@ -25,6 +25,7 @@
#include "dbDeepShapeStore.h"
#include "dbEmptyRegion.h"
#include "dbRegion.h"
#include "dbDeepEdges.h"
#include "dbShapeProcessor.h"
#include "dbFlatRegion.h"
#include "dbHierProcessor.h"
@ -367,7 +368,7 @@ DeepRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
m_merged_polygons = m_deep_layer.new_layer ();
m_merged_polygons = m_deep_layer.derived ();
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
@ -598,8 +599,7 @@ DeepRegion::area (const db::Box &box) const
ensure_merged_polygons_valid ();
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
db::cell_variants_collector<db::MagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
DeepRegion::area_type a = 0;
@ -632,8 +632,7 @@ DeepRegion::perimeter (const db::Box &box) const
ensure_merged_polygons_valid ();
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
db::cell_variants_collector<db::MagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
DeepRegion::perimeter_type p = 0;
@ -688,50 +687,148 @@ DeepRegion::angle_check (double min, double max, bool inverse) const
RegionDelegate *
DeepRegion::snapped (db::Coord gx, db::Coord gy)
{
// NOTE: snap be optimized by forming grid variants etc.
return db::AsIfFlatRegion::snapped (gx, gy);
if (gx <= 0 || gy <= 0) {
throw tl::Exception (tl::to_string (tr ("Snapping requires a positive grid value")));
}
if (gx != gy) {
// no way doing this hierarchically ?
return db::AsIfFlatRegion::snapped (gx, gy);
}
ensure_merged_polygons_valid ();
db::cell_variants_collector<db::GridReducer> vars (gx);
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (vars);
db::Layout &layout = m_merged_polygons.layout ();
std::vector<db::Point> heap;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
db::ICplxTrans trinv = tr.inverted ();
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
poly.transform (tr);
st.insert (snapped_polygon (poly, gx, gy, heap).transformed (trinv));
}
}
return res.release ();
}
Edges
DeepRegion::edges (const EdgeFilterBase *filter) const
{
// NOTE: needs a deep edge set for optimizing for hierarchy.
// At least the length filter is easy to optimize in the hierarchical case.
return db::AsIfFlatRegion::edges (filter);
}
ensure_merged_polygons_valid ();
RegionDelegate *
DeepRegion::filtered (const PolygonFilterBase &filter) const
{
if (filter.isotropic ()) {
std::auto_ptr<VariantsCollectorBase> vars;
ensure_merged_polygons_valid ();
if (filter) {
// @@@ scaled instances!
if (filter->isotropic ()) {
vars.reset (new db::cell_variants_collector<db::MagnificationReducer> ());
} else {
vars.reset (new db::cell_variants_collector<db::MagnificationAndOrientationReducer> ());
}
db::Layout &layout = m_merged_polygons.layout ();
vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (*vars);
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
}
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly)) {
st.insert (poly);
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
db::ICplxTrans tr;
if (vars.get ()) {
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
tr = v.begin ()->first;
}
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
if (! filter || filter->selected ((*e).transformed (tr))) {
st.insert (*e);
}
}
}
return res.release ();
} else {
return db::AsIfFlatRegion::filtered (filter);
}
return db::Edges (res.release ());
}
RegionDelegate *
DeepRegion::filtered (const PolygonFilterBase &filter) const
{
ensure_merged_polygons_valid ();
std::auto_ptr<VariantsCollectorBase> vars;
if (filter.isotropic ()) {
vars.reset (new db::cell_variants_collector<db::MagnificationReducer> ());
} else {
vars.reset (new db::cell_variants_collector<db::MagnificationAndOrientationReducer> ());
}
vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (*vars);
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly.transformed (tr))) {
st.insert (poly);
}
}
}
return res.release ();
}
RegionDelegate *
@ -759,7 +856,7 @@ DeepRegion::merged () const
db::Layout &layout = const_cast<db::Layout &> (m_merged_polygons.layout ());
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
c->shapes (res->deep_layer ().layer ()) = c->shapes (m_merged_polygons.layer ());
}
@ -779,8 +876,7 @@ DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
RegionDelegate *
DeepRegion::strange_polygon_check () const
{
// TODO: can probably be optimized
return db::AsIfFlatRegion::strange_polygon_check ();
throw tl::Exception (tl::to_string (tr ("A strange polygon check does not make sense on a processed region - polygons are already normalized")));
}
RegionDelegate *
@ -790,14 +886,13 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
db::Layout &layout = m_merged_polygons.layout ();
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
db::cell_variants_collector<db::MagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (vars);
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
@ -858,14 +953,13 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
db::Layout &layout = m_merged_polygons.layout ();
db::XYAnisotropyAndMagnificationReducer red;
db::cell_variants_collector<db::XYAnisotropyAndMagnificationReducer> vars (red);
db::cell_variants_collector<db::XYAnisotropyAndMagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (vars);
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
@ -907,7 +1001,7 @@ DeepRegion::holes () const
std::vector<db::Point> pts;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
@ -940,7 +1034,7 @@ DeepRegion::hulls () const
std::vector<db::Point> pts;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
@ -974,8 +1068,7 @@ DeepRegion::rounded_corners (double rinner, double router, unsigned int n) const
{
ensure_merged_polygons_valid ();
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
db::cell_variants_collector<db::MagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
@ -983,7 +1076,7 @@ DeepRegion::rounded_corners (double rinner, double router, unsigned int n) const
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
@ -1012,8 +1105,7 @@ DeepRegion::smoothed (coord_type d) const
{
ensure_merged_polygons_valid ();
db::MagnificationReducer red;
db::cell_variants_collector<db::MagnificationReducer> vars (red);
db::cell_variants_collector<db::MagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
@ -1021,7 +1113,7 @@ DeepRegion::smoothed (coord_type d) const
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
@ -1058,11 +1150,116 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, b
return db::AsIfFlatRegion::run_single_polygon_check (rel, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
namespace
{
class InteractingLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
{
public:
InteractingLocalOperation (int mode, bool touching, bool inverse)
: m_mode (mode), m_touching (touching), m_inverse (inverse)
{
// .. nothing yet ..
}
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
m_ep.clear ();
std::set<db::PolygonRef> others;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j));
}
}
size_t n = 1;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
const db::PolygonRef &subject = interactions.subject_shape (i->first);
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
m_ep.insert (*e, n);
}
}
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) {
m_ep.insert (*e, 0);
}
}
db::InteractionDetector id (m_mode, 0);
id.set_include_touching (m_touching);
db::EdgeSink es;
m_ep.process (es, id);
id.finish ();
n = 0;
std::set <size_t> selected;
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () && i->first == 0; ++i) {
++n;
selected.insert (i->second);
}
n = 1;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
if ((selected.find (n) == selected.end ()) == m_inverse) {
const db::PolygonRef &subject = interactions.subject_shape (i->first);
result.insert (subject);
}
}
}
virtual on_empty_intruder_mode on_empty_intruder_hint () const
{
if ((m_mode <= 0) != m_inverse) {
return Drop;
} else {
return Copy;
}
}
virtual std::string description () const
{
return tl::to_string (tr ("Select regions by their geometric relation (interacting, inside, outside ..)"));
}
private:
int m_mode;
bool m_touching;
bool m_inverse;
mutable db::EdgeProcessor m_ep;
};
}
RegionDelegate *
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const
{
// TODO: implement hierarchically
return db::AsIfFlatRegion::selected_interacting_generic (other, mode, touching, inverse);
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
if (! other_deep) {
return db::AsIfFlatRegion::selected_interacting_generic (other, mode, touching, inverse);
}
ensure_merged_polygons_valid ();
DeepLayer dl_out (m_deep_layer.derived ());
db::InteractingLocalOperation op (mode, touching, inverse);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (m_deep_layer.store ()->threads ());
#if 0
// with these settings, the resulting polygons are broken again ...
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
#endif
proc.run (&op, m_merged_polygons.layer (), other_deep->merged_deep_layer ().layer (), dl_out.layer ());
// TODO: mark the results as merged (unless we split - see above)
return new db::DeepRegion (dl_out);
}
RegionDelegate *

View File

@ -241,6 +241,11 @@ private:
EdgePairs run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
const DeepLayer &merged_deep_layer () const
{
return m_merged_polygons;
}
};
}

View File

@ -174,13 +174,6 @@ bool DeepLayer::operator== (const DeepLayer &other) const
return true;
}
DeepLayer
DeepLayer::new_layer() const
{
db::DeepShapeStore *store = const_cast<db::DeepShapeStore *> (mp_store.get ());
return DeepLayer (store, m_layout, store->layout (m_layout).insert_layer ());
}
db::Layout &
DeepLayer::layout ()
{

View File

@ -93,11 +93,6 @@ public:
*/
bool operator== (const DeepLayer &other) const;
/**
* @brief Creates a new empty layer based on this one
*/
DeepLayer new_layer () const;
/**
* @brief Gets the layout object
* The return value is guaranteed to be non-null.

View File

@ -209,6 +209,7 @@ public:
virtual ~EdgeFilterBase () { }
virtual bool selected (const db::Edge &edge) const = 0;
virtual bool isotropic () const = 0;
};
/**
@ -251,6 +252,11 @@ struct DB_PUBLIC EdgeLengthFilter
}
}
bool isotropic () const
{
return true;
}
private:
length_type m_lmin, m_lmax;
bool m_inverse;
@ -274,7 +280,7 @@ struct DB_PUBLIC EdgeOrientationFilter
*
* @param amin The minimum angle (measured against the x axis)
* @param amax The maximum angle (measured against the x axis)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
* @param inverse If set to true, only edges not matching this criterion will be filtered
*
* This filter will filter out all edges whose angle against x axis
* is larger or equal to amin and less than amax.
@ -290,7 +296,7 @@ struct DB_PUBLIC EdgeOrientationFilter
* @brief Constructor
*
* @param a The angle (measured against the x axis)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
* @param inverse If set to true, only edges not matching this criterion will be filtered
*
* This filter will filter out all edges whose angle against x axis
* is equal to a.
@ -323,6 +329,11 @@ struct DB_PUBLIC EdgeOrientationFilter
}
}
bool isotropic () const
{
return false;
}
private:
db::DVector m_emin, m_emax;
bool m_inverse;
@ -387,12 +398,55 @@ public:
Edges &operator= (const Edges &other);
/**
* @brief Constructor from an object
* @brief Constructor from a box
*
* Creates an edge set representing a single instance of that object
* Creates an edge set representing the contour of the box
*/
template <class Sh>
explicit Edges (const Sh &s)
explicit Edges (const db::Box &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a simple polygon
*
* Creates an edge set representing the contour of the polygon
*/
explicit Edges (const db::SimplePolygon &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a polygon
*
* Creates an edge set representing the contour of the polygon
*/
explicit Edges (const db::Polygon &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a path
*
* Creates an edge set representing the contour of the path
*/
explicit Edges (const db::Path &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from an edge
*
* Creates an edge set representing the single edge
*/
explicit Edges (const db::Edge &s)
: mp_delegate (0)
{
insert (s);

View File

@ -25,6 +25,7 @@
#include "dbReader.h"
#include "dbTestSupport.h"
#include "dbRegion.h"
#include "dbEdges.h"
#include "dbDeepShapeStore.h"
#include "tlUnitTest.h"
#include "tlStream.h"
@ -652,6 +653,178 @@ TEST(11_RoundAndSmoothed)
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au11.gds");
}
TEST(12_GridSnap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_l1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Region r3snapped = r3.snapped (50, 50);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r3);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3snapped);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au12.gds");
}
TEST(13_Edges)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_l1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Edges r3edges = r3.edges ();
db::EdgeLengthFilter f (0, 500, true);
db::Edges r3edges_filtered = r3.edges (f);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r3);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3edges);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r3edges_filtered);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au13.gds");
}
TEST(14_Interacting)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_l1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l6 = ly.get_layer (db::LayerProperties (6, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.selected_interacting (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.selected_not_interacting (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.selected_inside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.selected_not_inside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r2.selected_outside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r2.selected_not_outside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (16, 0)), r2.selected_overlapping (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (17, 0)), r2.selected_not_overlapping (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r6.selected_interacting (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r6.selected_not_interacting (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r6.selected_inside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), r6.selected_not_inside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r6.selected_outside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), r6.selected_not_outside (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), r6.selected_overlapping (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (27, 0)), r6.selected_not_overlapping (r1));
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au14.gds");
}
TEST(15_Filtered)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_area_peri_l1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::RegionAreaFilter af1 (0, 1000000000, false);
db::Region af1_filtered = r1.filtered (af1);
db::RegionAreaFilter af1inv (0, 1000000000, true);
db::Region af1_else = r1.filtered (af1inv);
{
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), af1_filtered);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), af1_else);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au15a.gds");
}
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::RegionBBoxFilter bwf (0, 50000, false, db::RegionBBoxFilter::BoxWidth);
db::RegionBBoxFilter bhf (0, 50000, false, db::RegionBBoxFilter::BoxHeight);
db::Region r2_bwf = r2.filtered (bwf);
db::Region r2_bhf = r2.filtered (bhf);
{
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2_bwf);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2_bhf);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au15b.gds");
}
}
TEST(100_Integration)
{
db::Layout ly;

Binary file not shown.

BIN
testdata/algo/deep_region_au12.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au13.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au14.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au15a.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au15b.gds vendored Normal file

Binary file not shown.