mirror of https://github.com/KLayout/klayout.git
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:
parent
10f9de8b66
commit
b0fc2be96e
|
|
@ -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 ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue