mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-08 04:08:14 +02:00
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:
@@ -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 ();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 ());
|
||||
}
|
||||
|
||||
+247
-50
@@ -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 *
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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 ()
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
+60
-6
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Reference in New Issue
Block a user