mirror of https://github.com/KLayout/klayout.git
commit
f2fafd1bad
|
|
@ -417,6 +417,19 @@ struct regular_array
|
|||
ab_coord (b.p2 ())
|
||||
};
|
||||
|
||||
// NOTE: we need to take some care we don't overiterate in case of vanishing row
|
||||
// or column vectors. Hence eff_amax and eff_bmax which are 1 in this case.
|
||||
|
||||
unsigned long eff_amax = m_amax;
|
||||
if (m_a.equal (vector_type ())) {
|
||||
eff_amax = 1;
|
||||
}
|
||||
|
||||
unsigned long eff_bmax = m_bmax;
|
||||
if (m_b.equal (vector_type ())) {
|
||||
eff_bmax = 1;
|
||||
}
|
||||
|
||||
double amin = ab [0].first;
|
||||
double amax = ab [0].first;
|
||||
double bmin = ab [0].second;
|
||||
|
|
@ -436,8 +449,8 @@ struct regular_array
|
|||
} else {
|
||||
amini = (unsigned long) (amin + 1.0 - epsilon);
|
||||
}
|
||||
if (amini > m_amax) {
|
||||
amini = m_amax;
|
||||
if (amini > eff_amax) {
|
||||
amini = eff_amax;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -448,8 +461,8 @@ struct regular_array
|
|||
} else {
|
||||
amaxi = (unsigned long) (amax + epsilon) + 1;
|
||||
}
|
||||
if (amaxi > m_amax) {
|
||||
amaxi = m_amax;
|
||||
if (amaxi > eff_amax) {
|
||||
amaxi = eff_amax;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -460,8 +473,8 @@ struct regular_array
|
|||
} else {
|
||||
bmini = (unsigned long) (bmin + 1.0 - epsilon);
|
||||
}
|
||||
if (bmini > m_bmax) {
|
||||
bmini = m_bmax;
|
||||
if (bmini > eff_bmax) {
|
||||
bmini = eff_bmax;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -472,8 +485,8 @@ struct regular_array
|
|||
} else {
|
||||
bmaxi = (unsigned long) (bmax + epsilon) + 1;
|
||||
}
|
||||
if (bmaxi > m_bmax) {
|
||||
bmaxi = m_bmax;
|
||||
if (bmaxi > eff_bmax) {
|
||||
bmaxi = eff_bmax;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -590,16 +603,44 @@ protected:
|
|||
unsigned long m_amax, m_bmax;
|
||||
double m_det;
|
||||
|
||||
inline vector_type eff_a () const
|
||||
{
|
||||
if (m_a.equal (vector_type ())) {
|
||||
if (m_b.equal (vector_type ())) {
|
||||
return vector_type (1, 0);
|
||||
} else {
|
||||
return vector_type (m_b.y (), -m_b.x ());
|
||||
}
|
||||
} else {
|
||||
return m_a;
|
||||
}
|
||||
}
|
||||
|
||||
inline vector_type eff_b () const
|
||||
{
|
||||
if (m_b.equal (vector_type ())) {
|
||||
if (m_a.equal (vector_type ())) {
|
||||
return vector_type (0, 1);
|
||||
} else {
|
||||
return vector_type (-m_a.y (), m_a.x ());
|
||||
}
|
||||
} else {
|
||||
return m_b;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair <double, double> ab_coord (const point_type &p) const
|
||||
{
|
||||
double a = (double (p.x ()) * double (m_b.y ()) - double (p.y ()) * double (m_b.x ())) / m_det;
|
||||
double b = (double (m_a.x ()) * double (p.y ()) - double (m_a.y ()) * double (p.x ())) / m_det;
|
||||
return std::make_pair (a, b);
|
||||
vector_type a = eff_a (), b = eff_b ();
|
||||
double ia = (double (p.x ()) * double (b.y ()) - double (p.y ()) * double (b.x ())) / m_det;
|
||||
double ib = (double (a.x ()) * double (p.y ()) - double (a.y ()) * double (p.x ())) / m_det;
|
||||
return std::make_pair (ia, ib);
|
||||
}
|
||||
|
||||
void compute_det ()
|
||||
{
|
||||
m_det = double (m_a.x ()) * double (m_b.y ()) - double (m_a.y ()) * double (m_b.x ());
|
||||
vector_type a = eff_a (), b = eff_b ();
|
||||
m_det = double (a.x ()) * double (b.y ()) - double (a.y ()) * double (b.x ());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "dbBoxConvert.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbFlatRegion.h"
|
||||
#include "dbEmptyRegion.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
|
|
@ -123,6 +124,125 @@ AsIfFlatEdges::selected_interacting_generic (const Region &other, bool inverse)
|
|||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting_generic (const Edges &edges, bool inverse) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery ee = edges.addressable_edges ();
|
||||
|
||||
for ( ; ! ee.at_end (); ++ee) {
|
||||
scanner.insert (ee.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
|
||||
if (! inverse) {
|
||||
|
||||
edge_interaction_filter<FlatEdges> filter (*output);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
} else {
|
||||
|
||||
std::set<db::Edge> interacting;
|
||||
edge_interaction_filter<std::set<db::Edge> > filter (interacting);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
|
||||
if (interacting.find (*o) == interacting.end ()) {
|
||||
output->insert (*o);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::pull_generic (const Edges &edges) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin (), true);
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 1);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery ee = edges.addressable_merged_edges ();
|
||||
|
||||
for ( ; ! ee.at_end (); ++ee) {
|
||||
scanner.insert (ee.operator-> (), 0);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
edge_interaction_filter<FlatEdges> filter (*output);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatEdges::pull_generic (const Region &other) const
|
||||
{
|
||||
// shortcuts
|
||||
if (other.empty () || empty ()) {
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin (), true);
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressablePolygonDelivery p = other.addressable_merged_polygons ();
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert2 (p.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (true));
|
||||
|
||||
edge_to_region_interaction_filter<FlatRegion> filter (*output);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::pull_interacting (const Edges &other) const
|
||||
{
|
||||
return pull_generic (other);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatEdges::pull_interacting (const Region &other) const
|
||||
{
|
||||
return pull_generic (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting (const Edges &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_not_interacting (const Edges &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting (const Region &other) const
|
||||
{
|
||||
|
|
@ -195,59 +315,6 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
|
|||
}
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting_generic (const Edges &edges, bool inverse) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery ee = edges.addressable_edges ();
|
||||
|
||||
for ( ; ! ee.at_end (); ++ee) {
|
||||
scanner.insert (ee.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
|
||||
if (! inverse) {
|
||||
|
||||
edge_interaction_filter<FlatEdges> filter (*output);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
} else {
|
||||
|
||||
std::set<db::Edge> interacting;
|
||||
edge_interaction_filter<std::set<db::Edge> > filter (interacting);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
|
||||
if (interacting.find (*o) == interacting.end ()) {
|
||||
output->insert (*o);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting (const Edges &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_not_interacting (const Edges &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::in (const Edges &other, bool invert) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ public:
|
|||
|
||||
virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const;
|
||||
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const;
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const;
|
||||
virtual EdgesDelegate *selected_interacting (const Edges &) const;
|
||||
virtual EdgesDelegate *selected_not_interacting (const Edges &) const;
|
||||
virtual EdgesDelegate *selected_interacting (const Region &) const;
|
||||
|
|
@ -173,6 +175,8 @@ protected:
|
|||
void update_bbox (const db::Box &box);
|
||||
void invalidate_bbox ();
|
||||
EdgePairsDelegate *run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &edges) const;
|
||||
virtual RegionDelegate *pull_generic (const Region ®ion) const;
|
||||
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool inverse) const;
|
||||
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool inverse) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbFlatEdges.h"
|
||||
#include "dbEmptyRegion.h"
|
||||
#include "dbEmptyEdgePairs.h"
|
||||
#include "dbEmptyEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbRegionUtils.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
|
|
@ -337,7 +338,7 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse)
|
|||
scanner.reserve2 (other.size ());
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
region_to_edge_interaction_filter<Shapes> filter (output->raw_polygons (), inverse);
|
||||
region_to_edge_interaction_filter<Shapes, db::Polygon> filter (output->raw_polygons (), inverse);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
|
||||
|
||||
|
|
@ -423,6 +424,92 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatRegion::pull_generic (const Edges &other) const
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return other.delegate ()->clone ();
|
||||
} else if (empty ()) {
|
||||
return new EmptyEdges ();
|
||||
}
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (size ());
|
||||
scanner.reserve2 (other.size ());
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (false));
|
||||
region_to_edge_interaction_filter<Shapes, db::Edge> filter (output->raw_edges (), false);
|
||||
|
||||
AddressablePolygonDelivery p (begin (), has_valid_merged_polygons ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery e (other.addressable_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) const
|
||||
{
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
return clone ();
|
||||
} else if (other.empty ()) {
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
size_t n = 1;
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p, ++n) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
if (mode > 0 || p->box ().touches (other.bbox ())) {
|
||||
ep.insert (*p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
db::InteractionDetector id (mode, 0);
|
||||
id.set_include_touching (touching);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
output->reserve (n);
|
||||
|
||||
n = 1;
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p, ++n) {
|
||||
if (selected.find (n) != selected.end ()) {
|
||||
output->raw_polygons ().insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
template <class Trans>
|
||||
void
|
||||
AsIfFlatRegion::produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes)
|
||||
|
|
|
|||
|
|
@ -205,6 +205,26 @@ public:
|
|||
return selected_interacting_generic (other, 0, false, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const
|
||||
{
|
||||
return pull_generic (other, -1, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_interacting (const Region &other) const
|
||||
{
|
||||
return pull_generic (other, 0, true);
|
||||
}
|
||||
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &other) const
|
||||
{
|
||||
return pull_generic (other);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_overlapping (const Region &other) const
|
||||
{
|
||||
return pull_generic (other, 0, false);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *in (const Region &other, bool invert) const;
|
||||
|
||||
virtual bool equals (const Region &other) const;
|
||||
|
|
@ -218,8 +238,10 @@ protected:
|
|||
|
||||
EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
EdgePairsDelegate *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;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
|
||||
template <class Trans>
|
||||
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
|
||||
|
|
|
|||
|
|
@ -108,6 +108,15 @@ DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, con
|
|||
set_merged_semantics (merged_semantics);
|
||||
}
|
||||
|
||||
DeepEdges::DeepEdges (const db::Edges &other, DeepShapeStore &dss)
|
||||
: AsIfFlatEdges (), m_merged_edges ()
|
||||
{
|
||||
m_deep_layer = dss.create_from_flat (other);
|
||||
|
||||
init ();
|
||||
set_merged_semantics (other.merged_semantics ());
|
||||
}
|
||||
|
||||
DeepEdges::DeepEdges ()
|
||||
: AsIfFlatEdges ()
|
||||
{
|
||||
|
|
@ -356,6 +365,17 @@ private:
|
|||
|
||||
}
|
||||
|
||||
const DeepLayer &
|
||||
DeepEdges::merged_deep_layer () const
|
||||
{
|
||||
if (merged_semantics ()) {
|
||||
ensure_merged_edges_valid ();
|
||||
return m_merged_edges;
|
||||
} else {
|
||||
return deep_layer ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeepEdges::ensure_merged_edges_valid () const
|
||||
{
|
||||
|
|
@ -441,18 +461,18 @@ DeepEdges::length_type DeepEdges::length (const db::Box &box) const
|
|||
{
|
||||
if (box.empty ()) {
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
db::MagnificationReducer red;
|
||||
db::cell_variants_collector<db::MagnificationReducer> vars (red);
|
||||
vars.collect (m_merged_edges.layout (), m_merged_edges.initial_cell ());
|
||||
vars.collect (edges.layout (), edges.initial_cell ());
|
||||
|
||||
DeepEdges::length_type l = 0;
|
||||
|
||||
const db::Layout &layout = m_merged_edges.layout ();
|
||||
const db::Layout &layout = edges.layout ();
|
||||
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
|
||||
DeepEdges::length_type lc = 0;
|
||||
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_edges.layer ()).begin (db::ShapeIterator::Edges); ! s.at_end (); ++s) {
|
||||
for (db::ShapeIterator s = layout.cell (*c).shapes (edges.layer ()).begin (db::ShapeIterator::Edges); ! s.at_end (); ++s) {
|
||||
lc += s->edge ().length ();
|
||||
}
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (*c);
|
||||
|
|
@ -544,36 +564,34 @@ template <class Result, class OutputContainer>
|
|||
OutputContainer *
|
||||
DeepEdges::processed_impl (const edge_processor<Result> &filter) const
|
||||
{
|
||||
if (! filter.requires_raw_input ()) {
|
||||
ensure_merged_edges_valid ();
|
||||
}
|
||||
const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ());
|
||||
vars->collect (edges.layout (), edges.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
|
||||
const_cast<db::DeepLayer &> (edges).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
|
||||
db::Layout &layout = const_cast<db::Layout &> (edges.layout ());
|
||||
|
||||
std::vector<Result> heap;
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::auto_ptr<OutputContainer> res (new OutputContainer (m_deep_layer.derived ()));
|
||||
std::auto_ptr<OutputContainer> res (new OutputContainer (edges.derived ()));
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
res->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ());
|
||||
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? edges.layer () : edges.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
|
|
@ -638,30 +656,28 @@ DeepEdges::filter_in_place (const EdgeFilterBase &filter)
|
|||
EdgesDelegate *
|
||||
DeepEdges::filtered (const EdgeFilterBase &filter) const
|
||||
{
|
||||
if (! filter.requires_raw_input ()) {
|
||||
ensure_merged_edges_valid ();
|
||||
}
|
||||
const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ());
|
||||
vars->collect (edges.layout (), edges.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
|
||||
const_cast<db::DeepLayer &> (edges).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
|
||||
db::Layout &layout = const_cast<db::Layout &> (edges.layout ());
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_deep_layer.derived ()));
|
||||
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (edges.derived ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ());
|
||||
const db::Shapes &s = c->shapes (edges.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
|
|
@ -994,31 +1010,28 @@ EdgesDelegate *DeepEdges::outside_part (const Region &other) const
|
|||
|
||||
RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const
|
||||
{
|
||||
ensure_merged_edges_valid ();
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_edges.derived ()));
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (edges.derived ()));
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (m_merged_edges.layout ());
|
||||
db::Cell &top_cell = const_cast<db::Cell &> (m_merged_edges.initial_cell ());
|
||||
db::Layout &layout = const_cast<db::Layout &> (edges.layout ());
|
||||
db::Cell &top_cell = const_cast<db::Cell &> (edges.initial_cell ());
|
||||
|
||||
// TODO: there is a special case when we'd need a MagnificationAndOrientationReducer:
|
||||
// dots formally don't have an orientation, hence the interpretation is x and y.
|
||||
db::MagnificationReducer red;
|
||||
db::cell_variants_collector<db::MagnificationReducer> vars (red);
|
||||
vars.collect (m_merged_edges.layout (), m_merged_edges.initial_cell ());
|
||||
vars.collect (edges.layout (), edges.initial_cell ());
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
if (join) {
|
||||
|
||||
// In joined mode we need to create a special cluster which connects all joined edges
|
||||
db::DeepLayer joined = m_merged_edges.derived ();
|
||||
|
||||
db::hier_clusters<db::Edge> hc;
|
||||
db::Connectivity conn (db::Connectivity::EdgesConnectByPoints);
|
||||
conn.connect (m_merged_edges);
|
||||
conn.connect (edges);
|
||||
hc.set_base_verbosity (base_verbosity () + 10);
|
||||
hc.build (layout, m_merged_edges.initial_cell (), db::ShapeIterator::Edges, conn);
|
||||
hc.build (layout, edges.initial_cell (), db::ShapeIterator::Edges, conn);
|
||||
|
||||
// TODO: iterate only over the called cells?
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
|
@ -1043,7 +1056,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
|
|||
JoinEdgesCluster jec (&ptrans, ext_b, ext_e, ext_o, ext_i);
|
||||
|
||||
std::list<db::Edge> heap;
|
||||
for (db::recursive_cluster_shape_iterator<db::Edge> rcsi (hc, m_merged_edges.layer (), c->cell_index (), *cl); ! rcsi.at_end (); ++rcsi) {
|
||||
for (db::recursive_cluster_shape_iterator<db::Edge> rcsi (hc, edges.layer (), c->cell_index (), *cl); ! rcsi.at_end (); ++rcsi) {
|
||||
heap.push_back (rcsi->transformed (v->first * rcsi.trans ()));
|
||||
jec.add (&heap.back (), 0);
|
||||
}
|
||||
|
|
@ -1072,7 +1085,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
|
|||
out = & to_commit [c->cell_index ()][v->first];
|
||||
}
|
||||
|
||||
for (db::Shapes::shape_iterator si = c->shapes (m_merged_edges.layer ()).begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
|
||||
for (db::Shapes::shape_iterator si = c->shapes (edges.layer ()).begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
|
||||
out->insert (extended_edge (si->edge ().transformed (v->first), ext_b, ext_e, ext_o, ext_i).transformed (v->first.inverted ()));
|
||||
}
|
||||
|
||||
|
|
@ -1101,6 +1114,12 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
|
|
@ -1161,6 +1180,57 @@ private:
|
|||
bool m_inverse;
|
||||
};
|
||||
|
||||
class Edge2EdgePullLocalOperation
|
||||
: public local_operation<db::Edge, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
Edge2EdgePullLocalOperation ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert (&subject, 1);
|
||||
}
|
||||
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), 0);
|
||||
}
|
||||
|
||||
edge_interaction_filter<std::unordered_set<db::Edge> > filter (result);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select interacting edges from other"));
|
||||
}
|
||||
};
|
||||
|
||||
class Edge2PolygonInteractingLocalOperation
|
||||
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
|
||||
{
|
||||
|
|
@ -1171,6 +1241,12 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner;
|
||||
|
|
@ -1232,27 +1308,103 @@ private:
|
|||
bool m_inverse;
|
||||
};
|
||||
|
||||
struct ResultInserter
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
ResultInserter (db::Layout *layout, std::unordered_set<db::PolygonRef> &result)
|
||||
: mp_layout (layout), mp_result (&result)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Polygon &p)
|
||||
{
|
||||
(*mp_result).insert (db::PolygonRef (p, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
std::unordered_set<db::PolygonRef> *mp_result;
|
||||
};
|
||||
|
||||
class Edge2PolygonPullLocalOperation
|
||||
: public local_operation<db::Edge, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
Edge2PolygonPullLocalOperation ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert1 (&subject, 1);
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
heap.push_back (o->obj ().transformed (o->trans ()));
|
||||
scanner.insert2 (& heap.back (), 0);
|
||||
}
|
||||
|
||||
ResultInserter inserter (layout, result);
|
||||
edge_to_region_interaction_filter<ResultInserter> filter (inserter);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> (), db::box_convert<db::Polygon> ());
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select interacting regions"));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepEdges::selected_interacting_generic (const Region &other, bool inverse) const
|
||||
{
|
||||
std::auto_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatEdges::selected_interacting_generic (other, inverse);
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepRegion (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
|
||||
db::Edge2PolygonInteractingLocalOperation op (inverse);
|
||||
|
||||
db::local_processor<db::Edge, db::PolygonRef, db::Edge> 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 ());
|
||||
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.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 ());
|
||||
proc.set_threads (edges.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_edges.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
proc.run (&op, edges.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
|
@ -1260,44 +1412,79 @@ DeepEdges::selected_interacting_generic (const Region &other, bool inverse) cons
|
|||
EdgesDelegate *
|
||||
DeepEdges::selected_interacting_generic (const Edges &other, bool inverse) const
|
||||
{
|
||||
std::auto_ptr<db::DeepEdges> dr_holder;
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatEdges::selected_interacting_generic (other, inverse);
|
||||
// if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
|
||||
db::Edge2EdgeInteractingLocalOperation op (inverse);
|
||||
|
||||
db::local_processor<db::Edge, db::Edge, db::Edge> 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 ());
|
||||
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.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 ());
|
||||
proc.set_threads (edges.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_edges.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
proc.run (&op, edges.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_interacting (const Edges &other) const
|
||||
RegionDelegate *DeepEdges::pull_generic (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
std::auto_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepRegion (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
const db::DeepLayer &edges = deep_layer ();
|
||||
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (other_polygons.derived ());
|
||||
|
||||
db::Edge2PolygonPullLocalOperation op;
|
||||
|
||||
db::local_processor<db::Edge, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edges.store ()->threads ());
|
||||
|
||||
proc.run (&op, edges.layer (), other_polygons.layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepRegion (dl_out);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_not_interacting (const Edges &other) const
|
||||
EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
std::auto_ptr<db::DeepEdges> dr_holder;
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_interacting (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
const db::DeepLayer &edges = deep_layer ();
|
||||
const db::DeepLayer &other_edges = other_deep->merged_deep_layer ();
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_not_interacting (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, true);
|
||||
DeepLayer dl_out (other_edges.derived ());
|
||||
|
||||
db::Edge2EdgePullLocalOperation op;
|
||||
|
||||
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edges.store ()->threads ());
|
||||
|
||||
proc.run (&op, edges.layer (), other_edges.layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
|
||||
|
|
@ -1401,7 +1588,7 @@ DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord
|
|||
}
|
||||
}
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, metrics);
|
||||
check.set_include_zero (false);
|
||||
|
|
@ -1410,19 +1597,19 @@ DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord
|
|||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_edges.derived ()));
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (edges.derived ()));
|
||||
|
||||
db::CheckLocalOperation op (check, other_deep != 0);
|
||||
|
||||
db::local_processor<db::Edge, db::Edge, db::EdgePair> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()),
|
||||
const_cast<db::Cell *> (&m_deep_layer.initial_cell ()),
|
||||
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&m_deep_layer.layout ()),
|
||||
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&m_deep_layer.initial_cell ()));
|
||||
db::local_processor<db::Edge, db::Edge, db::EdgePair> proc (const_cast<db::Layout *> (&edges.layout ()),
|
||||
const_cast<db::Cell *> (&edges.initial_cell ()),
|
||||
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&edges.layout ()),
|
||||
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&edges.initial_cell ()));
|
||||
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
proc.set_threads (edges.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_edges.layer (), other_deep ? other_deep->deep_layer ().layer () : m_merged_edges.layer (), res->deep_layer ().layer ());
|
||||
proc.run (&op, edges.layer (), other_deep ? other_deep->deep_layer ().layer () : edges.layer (), res->deep_layer ().layer ());
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class DB_PUBLIC DeepEdges
|
|||
{
|
||||
public:
|
||||
DeepEdges ();
|
||||
DeepEdges (const db::Edges &other, DeepShapeStore &dss);
|
||||
DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, bool as_edges = true);
|
||||
DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool as_edges = true, bool merged_semantics = true);
|
||||
|
||||
|
|
@ -136,11 +137,6 @@ public:
|
|||
|
||||
virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const;
|
||||
|
||||
virtual EdgesDelegate *selected_interacting (const Edges &) const;
|
||||
virtual EdgesDelegate *selected_not_interacting (const Edges &) const;
|
||||
virtual EdgesDelegate *selected_interacting (const Region &) const;
|
||||
virtual EdgesDelegate *selected_not_interacting (const Region &) const;
|
||||
|
||||
virtual EdgesDelegate *in (const Edges &, bool) const;
|
||||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||
|
|
@ -171,11 +167,14 @@ private:
|
|||
|
||||
void init ();
|
||||
void ensure_merged_edges_valid () const;
|
||||
const DeepLayer &merged_deep_layer () const;
|
||||
DeepLayer and_or_not_with(const DeepEdges *other, bool and_op) const;
|
||||
DeepLayer edge_region_op (const DeepRegion *other, bool outside, bool include_borders) const;
|
||||
EdgePairsDelegate *run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const;
|
||||
EdgesDelegate *selected_interacting_generic (const Region ®ion, bool invert) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &edges) const;
|
||||
virtual RegionDelegate *pull_generic (const Region ®ion) const;
|
||||
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const;
|
||||
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool invert) const;
|
||||
template <class Result, class OutputContainer> OutputContainer *processed_impl (const edge_processor<Result> &filter) const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,15 @@ DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, c
|
|||
set_merged_semantics (merged_semantics);
|
||||
}
|
||||
|
||||
DeepRegion::DeepRegion (const db::Region &other, DeepShapeStore &dss)
|
||||
: AsIfFlatRegion (), m_merged_polygons ()
|
||||
{
|
||||
m_deep_layer = dss.create_from_flat (other, false);
|
||||
|
||||
init ();
|
||||
set_merged_semantics (other.merged_semantics ());
|
||||
}
|
||||
|
||||
DeepRegion::DeepRegion ()
|
||||
: AsIfFlatRegion ()
|
||||
{
|
||||
|
|
@ -393,6 +402,17 @@ private:
|
|||
|
||||
}
|
||||
|
||||
const DeepLayer &
|
||||
DeepRegion::merged_deep_layer () const
|
||||
{
|
||||
if (merged_semantics ()) {
|
||||
ensure_merged_polygons_valid ();
|
||||
return m_merged_polygons;
|
||||
} else {
|
||||
return deep_layer ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeepRegion::ensure_merged_polygons_valid () const
|
||||
{
|
||||
|
|
@ -642,17 +662,17 @@ DeepRegion::area (const db::Box &box) const
|
|||
{
|
||||
if (box.empty ()) {
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
db::cell_variants_collector<db::MagnificationReducer> vars;
|
||||
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
|
||||
vars.collect (polygons.layout (), polygons.initial_cell ());
|
||||
|
||||
DeepRegion::area_type a = 0;
|
||||
|
||||
const db::Layout &layout = m_merged_polygons.layout ();
|
||||
const db::Layout &layout = polygons.layout ();
|
||||
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
|
||||
DeepRegion::area_type ac = 0;
|
||||
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
for (db::ShapeIterator s = layout.cell (*c).shapes (polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
ac += s->area ();
|
||||
}
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (*c);
|
||||
|
|
@ -675,17 +695,17 @@ DeepRegion::perimeter (const db::Box &box) const
|
|||
{
|
||||
if (box.empty ()) {
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
db::cell_variants_collector<db::MagnificationReducer> vars;
|
||||
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
|
||||
vars.collect (polygons.layout (), polygons.initial_cell ());
|
||||
|
||||
DeepRegion::perimeter_type p = 0;
|
||||
|
||||
const db::Layout &layout = m_merged_polygons.layout ();
|
||||
const db::Layout &layout = polygons.layout ();
|
||||
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
|
||||
DeepRegion::perimeter_type pc = 0;
|
||||
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
for (db::ShapeIterator s = layout.cell (*c).shapes (polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
pc += s->perimeter ();
|
||||
}
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (*c);
|
||||
|
|
@ -731,19 +751,18 @@ DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
|
|||
return new EmptyEdgePairs ();
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
db::cell_variants_collector<db::GridReducer> vars (gx);
|
||||
vars.collect (layout, m_merged_polygons.initial_cell ());
|
||||
vars.collect (layout, polygons.initial_cell ());
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &shapes = c->shapes (m_merged_polygons.layer ());
|
||||
const db::Shapes &shapes = c->shapes (polygons.layer ());
|
||||
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (c->cell_index ());
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
|
||||
|
|
@ -777,15 +796,14 @@ DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
|
|||
EdgePairsDelegate *
|
||||
DeepRegion::angle_check (double min, double max, bool inverse) const
|
||||
{
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &shapes = c->shapes (m_merged_polygons.layer ());
|
||||
const db::Shapes &shapes = c->shapes (polygons.layer ());
|
||||
db::Shapes &markers = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
for (db::Shapes::shape_iterator si = shapes.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
|
|
@ -815,19 +833,19 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
|
|||
return this;
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
db::cell_variants_collector<db::GridReducer> vars (gx);
|
||||
|
||||
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
|
||||
vars.collect (polygons.layout (), 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);
|
||||
const_cast<db::DeepLayer &> (polygons).separate_variants (vars);
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
std::vector<db::Point> heap;
|
||||
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (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 ());
|
||||
|
|
@ -835,7 +853,7 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
|
|||
const db::ICplxTrans &tr = v.begin ()->first;
|
||||
db::ICplxTrans trinv = tr.inverted ();
|
||||
|
||||
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
|
||||
const db::Shapes &s = c->shapes (polygons.layer ());
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
db::PolygonRefToShapesGenerator pr (&layout, &st);
|
||||
|
||||
|
|
@ -856,7 +874,7 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
|
|||
EdgesDelegate *
|
||||
DeepRegion::edges (const EdgeFilterBase *filter) const
|
||||
{
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
|
||||
|
|
@ -864,16 +882,16 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
|
|||
|
||||
vars.reset (new db::VariantsCollectorBase (filter->vars ()));
|
||||
|
||||
vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
|
||||
vars->collect (polygons.layout (), 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);
|
||||
const_cast<db::DeepLayer &> (polygons).separate_variants (*vars);
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (polygons.derived ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
db::ICplxTrans tr;
|
||||
|
|
@ -883,7 +901,7 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
|
|||
tr = v.begin ()->first;
|
||||
}
|
||||
|
||||
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
|
||||
const db::Shapes &s = c->shapes (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) {
|
||||
|
|
@ -901,7 +919,7 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
|
|||
|
||||
}
|
||||
|
||||
res->set_is_merged (true);
|
||||
res->set_is_merged (merged_semantics () || is_merged ());
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
|
|
@ -975,36 +993,34 @@ template <class Result, class OutputContainer>
|
|||
OutputContainer *
|
||||
DeepRegion::processed_impl (const polygon_processor<Result> &filter) const
|
||||
{
|
||||
if (! filter.requires_raw_input ()) {
|
||||
ensure_merged_polygons_valid ();
|
||||
}
|
||||
const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ());
|
||||
vars->collect (polygons.layout (), polygons.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
|
||||
const_cast<db::DeepLayer &> (polygons).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
std::vector<Result> heap;
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::auto_ptr<OutputContainer> res (new OutputContainer (m_deep_layer.derived ()));
|
||||
std::auto_ptr<OutputContainer> res (new OutputContainer (polygons.derived ()));
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
res->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_polygons.layer ());
|
||||
const db::Shapes &s = c->shapes (polygons.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
|
|
@ -1075,30 +1091,28 @@ DeepRegion::filter_in_place (const PolygonFilterBase &filter)
|
|||
RegionDelegate *
|
||||
DeepRegion::filtered (const PolygonFilterBase &filter) const
|
||||
{
|
||||
if (! filter.requires_raw_input ()) {
|
||||
ensure_merged_polygons_valid ();
|
||||
}
|
||||
const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
|
||||
|
||||
std::auto_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ());
|
||||
vars->collect (polygons.layout (), polygons.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
|
||||
const_cast<db::DeepLayer &> (polygons).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_deep_layer.derived ()));
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (polygons.derived ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_polygons.layer ());
|
||||
const db::Shapes &s = c->shapes (polygons.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
|
|
@ -1233,17 +1247,17 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
return clone ();
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
db::cell_variants_collector<db::MagnificationReducer> vars;
|
||||
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
|
||||
vars.collect (polygons.layout (), 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);
|
||||
const_cast<db::DeepLayer &> (polygons).separate_variants (vars);
|
||||
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (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 ());
|
||||
|
|
@ -1251,7 +1265,7 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
double mag = v.begin ()->first.mag ();
|
||||
db::Coord d_with_mag = db::coord_traits<db::Coord>::rounded (d / mag);
|
||||
|
||||
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
|
||||
const db::Shapes &s = c->shapes (polygons.layer ());
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
db::PolygonRefToShapesGenerator pr (&layout, &st);
|
||||
|
|
@ -1268,7 +1282,7 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
|
||||
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
|
||||
// overlap after size and are not necessarily merged)
|
||||
if (d < 0) {
|
||||
if (d < 0 && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
|
||||
|
|
@ -1311,17 +1325,17 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
return sized (dx, mode);
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
db::cell_variants_collector<db::XYAnisotropyAndMagnificationReducer> vars;
|
||||
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
|
||||
vars.collect (polygons.layout (), 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);
|
||||
const_cast<db::DeepLayer &> (polygons).separate_variants (vars);
|
||||
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (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 ());
|
||||
|
|
@ -1336,7 +1350,7 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
std::swap (dx_with_mag, dy_with_mag);
|
||||
}
|
||||
|
||||
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
|
||||
const db::Shapes &s = c->shapes (polygons.layer ());
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
db::PolygonRefToShapesGenerator pr (&layout, &st);
|
||||
|
|
@ -1353,7 +1367,7 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
|
||||
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
|
||||
// overlap after size and are not necessarily merged)
|
||||
if (dx < 0 && dy < 0) {
|
||||
if (dx < 0 && dy < 0 && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
|
||||
|
|
@ -1471,7 +1485,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
}
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, metrics);
|
||||
check.set_include_zero (false);
|
||||
|
|
@ -1480,19 +1494,19 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
|
||||
|
||||
db::CheckLocalOperation op (check, different_polygons, other_deep != 0);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()),
|
||||
const_cast<db::Cell *> (&m_deep_layer.initial_cell ()),
|
||||
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&m_deep_layer.layout ()),
|
||||
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&m_deep_layer.initial_cell ()));
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&polygons.layout ()),
|
||||
const_cast<db::Cell *> (&polygons.initial_cell ()),
|
||||
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&polygons.layout ()),
|
||||
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&polygons.initial_cell ()));
|
||||
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_polygons.layer (), other_deep ? other_deep->deep_layer ().layer () : m_merged_polygons.layer (), res->deep_layer ().layer ());
|
||||
proc.run (&op, polygons.layer (), other_deep ? other_deep->deep_layer ().layer () : polygons.layer (), res->deep_layer ().layer ());
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
|
@ -1500,7 +1514,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
EdgePairsDelegate *
|
||||
DeepRegion::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
|
||||
{
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, metrics);
|
||||
check.set_include_zero (false);
|
||||
|
|
@ -1509,12 +1523,12 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, b
|
|||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &shapes = c->shapes (m_merged_polygons.layer ());
|
||||
const db::Shapes &shapes = c->shapes (polygons.layer ());
|
||||
db::Shapes &result = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
|
||||
|
|
@ -1549,9 +1563,14 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
return m_touching ? 1 : 0;
|
||||
}
|
||||
|
||||
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 ();
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
|
@ -1564,20 +1583,20 @@ public:
|
|||
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);
|
||||
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);
|
||||
ep.insert (*e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
db::InteractionDetector id (m_mode, 0);
|
||||
id.set_include_touching (m_touching);
|
||||
db::EdgeSink es;
|
||||
m_ep.process (es, id);
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
n = 0;
|
||||
|
|
@ -1614,11 +1633,88 @@ private:
|
|||
int m_mode;
|
||||
bool m_touching;
|
||||
bool m_inverse;
|
||||
mutable db::EdgeProcessor m_ep;
|
||||
};
|
||||
|
||||
class PullLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
PullLocalOperation (int mode, bool touching)
|
||||
: m_mode (mode), m_touching (touching)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
return m_touching ? 1 : 0;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 1;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o, ++n) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, n);
|
||||
}
|
||||
}
|
||||
|
||||
db::InteractionDetector id (m_mode, 0);
|
||||
id.set_include_touching (m_touching);
|
||||
db::EdgeSink es;
|
||||
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 (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o, ++n) {
|
||||
if (selected.find (n) != selected.end ()) {
|
||||
result.insert (*o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Pull regions by their geometrical relation to first"));
|
||||
}
|
||||
|
||||
private:
|
||||
int m_mode;
|
||||
bool m_touching;
|
||||
};
|
||||
|
||||
struct ResultInserter
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
ResultInserter (db::Layout *layout, std::unordered_set<db::PolygonRef> &result)
|
||||
: mp_layout (layout), mp_result (&result)
|
||||
{
|
||||
|
|
@ -1635,6 +1731,25 @@ private:
|
|||
std::unordered_set<db::PolygonRef> *mp_result;
|
||||
};
|
||||
|
||||
struct EdgeResultInserter
|
||||
{
|
||||
typedef db::Edge value_type;
|
||||
|
||||
EdgeResultInserter (std::unordered_set<db::Edge> &result)
|
||||
: mp_result (&result)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Edge &e)
|
||||
{
|
||||
(*mp_result).insert (e);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_set<db::Edge> *mp_result;
|
||||
};
|
||||
|
||||
class InteractingWithEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::Edge, db::PolygonRef>
|
||||
{
|
||||
|
|
@ -1645,16 +1760,22 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::Edge> &interactions, std::unordered_set<db::PolygonRef> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
m_scanner.clear ();
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner;
|
||||
|
||||
ResultInserter inserter (layout, result);
|
||||
region_to_edge_interaction_filter<ResultInserter> filter (inserter, m_inverse);
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
m_scanner.insert2 (& interactions.intruder_shape (*j), 0);
|
||||
scanner.insert2 (& interactions.intruder_shape (*j), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1664,14 +1785,14 @@ public:
|
|||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
heap.push_back (subject.obj ().transformed (subject.trans ()));
|
||||
|
||||
m_scanner.insert1 (&heap.back (), 0);
|
||||
scanner.insert1 (&heap.back (), 0);
|
||||
if (m_inverse) {
|
||||
filter.preset (&heap.back ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
if (m_inverse) {
|
||||
filter.fill_output ();
|
||||
}
|
||||
|
|
@ -1688,12 +1809,63 @@ public:
|
|||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select regions by their geometric relation (interacting, inside, outside ..)"));
|
||||
return tl::to_string (tr ("Select regions by their geometric relation to edges"));
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
mutable db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> m_scanner;
|
||||
};
|
||||
|
||||
class PullWithEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
PullWithEdgeLocalOperation ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout *, const shape_interactions<db::PolygonRef, db::Edge> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner;
|
||||
|
||||
EdgeResultInserter inserter (result);
|
||||
region_to_edge_interaction_filter<EdgeResultInserter> filter (inserter, false);
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j), 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
heap.push_back (subject.obj ().transformed (subject.trans ()));
|
||||
|
||||
scanner.insert1 (&heap.back (), 0);
|
||||
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Pull edges from second by their geometric relation to first"));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1704,29 +1876,34 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
||||
std::auto_ptr<db::DeepRegion> dr_holder;
|
||||
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);
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepRegion (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
// NOTE: on "inside", the other polygons must be merged
|
||||
const db::DeepLayer &other_polygons = mode < 0 ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
DeepLayer dl_out (polygons.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 ());
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
|
||||
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, m_merged_polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ());
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
if (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res;
|
||||
|
|
@ -1738,32 +1915,103 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
|
|||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
||||
std::auto_ptr<db::DeepEdges> dr_holder;
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatRegion::selected_interacting_generic (other, inverse);
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithEdgeLocalOperation op (inverse);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, 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 ());
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.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 ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
|
||||
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, m_merged_polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (other.is_merged () && (merged_semantics () || is_merged ()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
|
||||
{
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
||||
std::auto_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepRegion (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
// in "inside" mode, the first argument needs to be merged too
|
||||
const db::DeepLayer &polygons = mode < 0 ? merged_deep_layer () : deep_layer ();
|
||||
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::PullLocalOperation op (mode, touching);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ());
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after && ((mode < 0 && merged_semantics ()) || is_merged ()) && (other.merged_semantics () || other.is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepRegion::pull_generic (const Edges &other) const
|
||||
{
|
||||
std::auto_ptr<db::DeepEdges> dr_holder;
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
|
||||
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
// in "inside" mode, the first argument needs to be merged too
|
||||
const db::DeepLayer &polygons = deep_layer ();
|
||||
const db::DeepLayer &other_edges = other_deep->merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::PullWithEdgeLocalOperation op;
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());
|
||||
|
||||
db::DeepEdges *res = new db::DeepEdges (dl_out);
|
||||
res->set_is_merged (is_merged () && (other.merged_semantics () || other.is_merged ()));
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public:
|
|||
typedef polygon_layer_type::iterator polygon_iterator_type;
|
||||
|
||||
DeepRegion ();
|
||||
DeepRegion (const db::Region &other, DeepShapeStore &dss);
|
||||
DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio = 0.0, size_t max_vertex_count = 0);
|
||||
DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics = true, double area_ratio = 0.0, size_t max_vertex_count = 0);
|
||||
|
||||
|
|
@ -154,56 +155,6 @@ public:
|
|||
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
|
||||
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
|
||||
|
||||
virtual RegionDelegate *selected_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, false);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, false);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, false);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, false);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *in (const Region &other, bool invert) const;
|
||||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||
|
|
@ -235,16 +186,14 @@ private:
|
|||
|
||||
void init ();
|
||||
void ensure_merged_polygons_valid () const;
|
||||
const DeepLayer &merged_deep_layer () const;
|
||||
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const;
|
||||
EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
EdgePairsDelegate *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;
|
||||
}
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
|
||||
template <class Result, class OutputContainer> OutputContainer *processed_impl (const polygon_processor<Result> &filter) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -326,6 +326,36 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region ®ion, bool for_n
|
|||
return dl;
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_from_flat (const db::Edges &edges, const db::ICplxTrans &trans)
|
||||
{
|
||||
// reuse existing layer
|
||||
std::pair<bool, DeepLayer> lff = layer_for_flat (tl::id_of (edges.delegate ()));
|
||||
if (lff.first) {
|
||||
return lff.second;
|
||||
}
|
||||
|
||||
require_singular ();
|
||||
|
||||
unsigned int layer = layout ().insert_layer ();
|
||||
|
||||
db::Shapes *shapes = &initial_cell ().shapes (layer);
|
||||
db::Box world = db::Box::world ();
|
||||
|
||||
db::EdgeBuildingHierarchyBuilderShapeReceiver eb (false);
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = edges.begin_iter ();
|
||||
db::ICplxTrans ttop = trans * ii.second;
|
||||
while (! ii.first.at_end ()) {
|
||||
eb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
|
||||
++ii.first;
|
||||
}
|
||||
|
||||
DeepLayer dl (this, 0 /*singular layout index*/, layer);
|
||||
m_layers_for_flat [tl::id_of (edges.delegate ())] = std::make_pair (dl.layout_index (), dl.layer ());
|
||||
m_flat_region_id [std::make_pair (dl.layout_index (), dl.layer ())] = tl::id_of (edges.delegate ());
|
||||
return dl;
|
||||
}
|
||||
|
||||
std::pair<bool, DeepLayer> DeepShapeStore::layer_for_flat (const db::Region ®ion) const
|
||||
{
|
||||
return layer_for_flat (tl::id_of (region.delegate ()));
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace db {
|
|||
|
||||
class DeepShapeStore;
|
||||
class Region;
|
||||
class Edges;
|
||||
|
||||
/**
|
||||
* @brief Represents a shape collection from the deep shape store
|
||||
|
|
@ -274,6 +275,17 @@ public:
|
|||
*/
|
||||
DeepLayer create_from_flat (const db::Region ®ion, bool for_netlist, double max_area_ratio = 0.0, size_t max_vertex_count = 0, const db::ICplxTrans &trans = db::ICplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Creates a new layer from a flat edge collection (or the edge collection is made flat)
|
||||
*
|
||||
* This method is intended for use with singular-created DSS objects (see
|
||||
* singular constructor).
|
||||
*
|
||||
* After a flat layer has been created for a region, it can be retrieved
|
||||
* from the region later with layer_for_flat (region).
|
||||
*/
|
||||
DeepLayer create_from_flat (const db::Edges ®ion, const db::ICplxTrans &trans = db::ICplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Gets the layer for a given flat region.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -191,6 +191,11 @@ void Edges::processed (Region &output, const EdgeToPolygonProcessorBase &filter)
|
|||
output.set_delegate (mp_delegate->processed_to_polygons (filter));
|
||||
}
|
||||
|
||||
void Edges::pull_interacting (Region &output, const Region &other) const
|
||||
{
|
||||
output = Region (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
void Edges::extended (Region &output, coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const
|
||||
{
|
||||
output.set_delegate (mp_delegate->extended (ext_b, ext_e, ext_o, ext_i, join));
|
||||
|
|
|
|||
|
|
@ -1062,6 +1062,25 @@ public:
|
|||
return Edges (mp_delegate->outside_part (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of the other region set which overlap or touch edges from this edge set
|
||||
*
|
||||
* Merged semantics applies for the other region. Merged polygons will be selected from the other region
|
||||
* if merged semantics is enabled.
|
||||
*/
|
||||
void pull_interacting (Region &output, const Region &other) const;
|
||||
|
||||
/**
|
||||
* @brief Selects all edges of the other edge set which overlap or touch edges from this edge set
|
||||
*
|
||||
* Merged semantics applies. If merged semantics is chosen, the connected edge parts will be
|
||||
* selected as a whole from other.
|
||||
*/
|
||||
Edges pull_interacting (const Edges &other) const
|
||||
{
|
||||
return Edges (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edges of this edge set which overlap or touch with polygons from the region
|
||||
*
|
||||
|
|
|
|||
|
|
@ -272,6 +272,8 @@ public:
|
|||
|
||||
virtual EdgesDelegate *inside_part (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *outside_part (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const = 0;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const = 0;
|
||||
virtual EdgesDelegate *selected_interacting (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *selected_not_interacting (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *selected_interacting (const Edges &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbEdges.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "tlSelect.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
|
|
@ -242,7 +243,7 @@ private:
|
|||
*
|
||||
* There is a special box converter which is able to sort that out as well.
|
||||
*/
|
||||
template <class OutputContainer>
|
||||
template <class OutputContainer, class OutputType = typename OutputContainer::value_type>
|
||||
class edge_to_region_interaction_filter
|
||||
: public db::box_scanner_receiver2<db::Edge, size_t, db::Polygon, size_t>
|
||||
{
|
||||
|
|
@ -255,17 +256,20 @@ public:
|
|||
|
||||
void add (const db::Edge *e, size_t, const db::Polygon *p, size_t)
|
||||
{
|
||||
if (m_seen.find (e) == m_seen.end ()) {
|
||||
const OutputType *ep = 0;
|
||||
tl::select (ep, e, p);
|
||||
|
||||
if (m_seen.find (ep) == m_seen.end ()) {
|
||||
if (db::interact (*p, *e)) {
|
||||
m_seen.insert (e);
|
||||
mp_output->insert (*e);
|
||||
m_seen.insert (ep);
|
||||
mp_output->insert (*ep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OutputContainer *mp_output;
|
||||
std::set<const db::Edge *> m_seen;
|
||||
std::set<const OutputType *> m_seen;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ EmptyEdges::extended (coord_type, coord_type, coord_type, coord_type, bool) cons
|
|||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
EmptyEdges::pull_interacting (const Region &) const
|
||||
{
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
EmptyEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ public:
|
|||
|
||||
virtual EdgesDelegate *inside_part (const Region &) const { return new EmptyEdges (); }
|
||||
virtual EdgesDelegate *outside_part (const Region &) const { return new EmptyEdges (); }
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
virtual EdgesDelegate *selected_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
virtual EdgesDelegate *selected_not_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
virtual EdgesDelegate *selected_interacting (const Region &) const { return new EmptyEdges (); }
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "dbCommon.h"
|
||||
#include "dbRegionDelegate.h"
|
||||
#include "dbEmptyEdges.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
|
|
@ -106,6 +107,10 @@ public:
|
|||
virtual RegionDelegate *selected_not_interacting (const Edges &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); }
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
virtual RegionDelegate *pull_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); }
|
||||
|
||||
virtual bool has_valid_polygons () const { return true; }
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ class DB_PUBLIC FlatEdges
|
|||
: public AsIfFlatEdges
|
||||
{
|
||||
public:
|
||||
typedef db::Edge value_type;
|
||||
|
||||
typedef db::layer<db::Edge, db::unstable_layer_tag> edge_layer_type;
|
||||
typedef edge_layer_type::iterator edge_iterator_type;
|
||||
|
||||
|
|
@ -178,6 +180,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
db::Shapes &raw_edges () { return m_edges; }
|
||||
|
||||
protected:
|
||||
virtual void merged_semantics_changed ();
|
||||
virtual Box compute_bbox () const;
|
||||
|
|
@ -187,8 +191,6 @@ protected:
|
|||
private:
|
||||
friend class AsIfFlatEdges;
|
||||
|
||||
db::Shapes &raw_edges () { return m_edges; }
|
||||
|
||||
FlatEdges &operator= (const FlatEdges &other);
|
||||
|
||||
bool m_is_merged;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ class DB_PUBLIC FlatRegion
|
|||
: public AsIfFlatRegion
|
||||
{
|
||||
public:
|
||||
typedef db::Polygon value_type;
|
||||
typedef db::layer<db::Polygon, db::unstable_layer_tag> polygon_layer_type;
|
||||
typedef polygon_layer_type::iterator polygon_iterator_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -441,6 +441,7 @@ local_processor_cell_contexts<TS, TI, TR>::compute_results (const local_processo
|
|||
|
||||
for (typename std::vector<std::pair<const context_key_type *, db::local_processor_cell_context<TS, TI, TR> *> >::const_iterator c = sorted_contexts.begin (); c != sorted_contexts.end (); ++c) {
|
||||
|
||||
proc->next ();
|
||||
++index;
|
||||
|
||||
if (tl::verbosity () >= proc->base_verbosity () + 20) {
|
||||
|
|
@ -1046,14 +1047,14 @@ template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::E
|
|||
|
||||
template <class TS, class TI, class TR>
|
||||
local_processor<TS, TI, TR>::local_processor (db::Layout *layout, db::Cell *top)
|
||||
: mp_subject_layout (layout), mp_intruder_layout (layout), mp_subject_top (top), mp_intruder_top (top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30)
|
||||
: mp_subject_layout (layout), mp_intruder_layout (layout), mp_subject_top (top), mp_intruder_top (top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
local_processor<TS, TI, TR>::local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_top)
|
||||
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), mp_subject_top (subject_top), mp_intruder_top (intruder_top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30)
|
||||
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), mp_subject_top (subject_top), mp_intruder_top (intruder_top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1068,6 +1069,31 @@ std::string local_processor<TS, TI, TR>::description (const local_operation<TS,
|
|||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void local_processor<TS, TI, TR>::next () const
|
||||
{
|
||||
static tl::Mutex s_lock;
|
||||
tl::MutexLocker locker (&s_lock);
|
||||
++m_progress;
|
||||
|
||||
tl::RelativeProgress *rp = dynamic_cast<tl::RelativeProgress *> (mp_progress);
|
||||
if (rp) {
|
||||
rp->set (m_progress);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
size_t local_processor<TS, TI, TR>::get_progress () const
|
||||
{
|
||||
size_t p = 0;
|
||||
{
|
||||
static tl::Mutex s_lock;
|
||||
tl::MutexLocker locker (&s_lock);
|
||||
p = m_progress;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer)
|
||||
{
|
||||
|
|
@ -1235,7 +1261,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
if (subject_cell == intruder_cell) {
|
||||
|
||||
// Use the same id's for same instances - this way we can easily detect same instances
|
||||
// and don't make the self-interacting
|
||||
// and don't make them self-interacting
|
||||
|
||||
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
|
||||
unsigned int iid = ++id;
|
||||
|
|
@ -1327,7 +1353,11 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
db::ICplxTrans tk = (*j)->complex_trans (*k);
|
||||
// NOTE: no self-interactions
|
||||
if (i->first != *j || tn != tk) {
|
||||
intruders_below.first.insert (db::CellInstArray (db::CellInst ((*j)->object ().cell_index ()), tni * tk));
|
||||
// optimize the intruder instance so it will be as low as possible
|
||||
std::pair<bool, db::CellInstArray> ei = effective_instance (contexts, i->first->object ().cell_index (), (*j)->object ().cell_index (), tni * tk, dist);
|
||||
if (ei.first) {
|
||||
intruders_below.first.insert (ei.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1342,6 +1372,64 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a cell instance array suitable for adding as intruder
|
||||
*
|
||||
* The given intruder cell with the transformation ti2s - which transforms the intruder instance into
|
||||
* the coordinate system of the subject cell - is analysed and either this instance or a sub-instance
|
||||
* is chosen.
|
||||
* Sub-instances are chosen if the intruder cell does not have shapes which interact with the subject
|
||||
* cell and there is exactly one sub-instance interacting with the subject cell.
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
std::pair<bool, db::CellInstArray>
|
||||
local_processor<TS, TI, TR>::effective_instance (local_processor_contexts<TS, TI, TR> &contexts, db::cell_index_type subject_cell_index, db::cell_index_type intruder_cell_index, const db::ICplxTrans &ti2s, db::Coord dist) const
|
||||
{
|
||||
db::Box bbox = safe_box_enlarged (mp_subject_layout->cell (subject_cell_index).bbox (contexts.subject_layer ()), dist - 1, dist - 1);
|
||||
if (bbox.empty ()) {
|
||||
// should not happen, but skip if it does
|
||||
return std::make_pair (false, db::CellInstArray ());
|
||||
}
|
||||
|
||||
db::Box ibbox = bbox.transformed (ti2s.inverted ());
|
||||
|
||||
const db::Cell &intruder_cell = mp_intruder_layout->cell (intruder_cell_index);
|
||||
const db::Shapes &intruder_shapes = intruder_cell.shapes (contexts.intruder_layer ());
|
||||
if (! intruder_shapes.empty () && ! intruder_shapes.begin_touching (ibbox, db::ShapeIterator::All).at_end ()) {
|
||||
return std::make_pair (true, db::CellInstArray (db::CellInst (intruder_cell_index), ti2s));
|
||||
}
|
||||
|
||||
db::box_convert <db::CellInst, true> inst_bcii (*mp_intruder_layout, contexts.intruder_layer ());
|
||||
|
||||
size_t ni = 0;
|
||||
db::cell_index_type eff_cell_index = 0;
|
||||
db::ICplxTrans eff_trans;
|
||||
|
||||
for (db::Cell::touching_iterator i = intruder_cell.begin_touching (ibbox); ! i.at_end() && ni < 2; ++i) {
|
||||
const db::CellInstArray &ci = i->cell_inst ();
|
||||
db::Box cbox = mp_intruder_layout->cell (ci.object ().cell_index ()).bbox (contexts.intruder_layer ());
|
||||
for (db::CellInstArray::iterator k = ci.begin_touching (ibbox, inst_bcii); ! k.at_end () && ni < 2; ++k) {
|
||||
db::ICplxTrans tk = ci.complex_trans (*k);
|
||||
if (ibbox.overlaps (cbox.transformed (tk))) {
|
||||
eff_trans = tk;
|
||||
eff_cell_index = ci.object ().cell_index ();
|
||||
++ni;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ni == 0) {
|
||||
// should not happen, but skip if it does
|
||||
return std::make_pair (false, db::CellInstArray ());
|
||||
} else if (ni == 1) {
|
||||
// one instance - dive down
|
||||
return effective_instance (contexts, subject_cell_index, eff_cell_index, ti2s * eff_trans, dist);
|
||||
} else {
|
||||
return std::make_pair (true, db::CellInstArray (db::CellInst (intruder_cell_index), ti2s));
|
||||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
|
|
@ -1354,6 +1442,16 @@ local_processor<TS, TI, TR>::compute_results (local_processor_contexts<TS, TI, T
|
|||
mp_subject_layout->update ();
|
||||
db::LayoutLocker layout_update_locker (mp_subject_layout);
|
||||
|
||||
// prepare a progress for the computation tasks
|
||||
size_t comp_effort = 0;
|
||||
for (typename local_processor_contexts<TS, TI, TR>::iterator c = contexts.begin (); c != contexts.end (); ++c) {
|
||||
comp_effort += c->second.size ();
|
||||
}
|
||||
|
||||
tl::RelativeProgress progress (description (op), comp_effort, 1);
|
||||
m_progress = 0;
|
||||
mp_progress = 0;
|
||||
|
||||
if (m_nthreads > 0) {
|
||||
|
||||
std::auto_ptr<tl::Job<local_processor_result_computation_worker<TS, TI, TR> > > rc_job (new tl::Job<local_processor_result_computation_worker<TS, TI, TR> > (m_nthreads));
|
||||
|
|
@ -1409,22 +1507,44 @@ local_processor<TS, TI, TR>::compute_results (local_processor_contexts<TS, TI, T
|
|||
}
|
||||
|
||||
if (rc_job.get ()) {
|
||||
rc_job->start ();
|
||||
rc_job->wait ();
|
||||
|
||||
try {
|
||||
|
||||
rc_job->start ();
|
||||
while (! rc_job->wait (10)) {
|
||||
progress.set (get_progress ());
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
rc_job->terminate ();
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (db::Layout::bottom_up_const_iterator bu = mp_subject_layout->begin_bottom_up (); bu != mp_subject_layout->end_bottom_up (); ++bu) {
|
||||
try {
|
||||
|
||||
mp_progress = &progress;
|
||||
|
||||
for (db::Layout::bottom_up_const_iterator bu = mp_subject_layout->begin_bottom_up (); bu != mp_subject_layout->end_bottom_up (); ++bu) {
|
||||
|
||||
typename local_processor_contexts<TS, TI, TR>::iterator cpc = contexts.context_map ().find (&mp_subject_layout->cell (*bu));
|
||||
if (cpc != contexts.context_map ().end ()) {
|
||||
cpc->second.compute_results (contexts, cpc->first, op, output_layer, this);
|
||||
contexts.context_map ().erase (cpc);
|
||||
}
|
||||
|
||||
typename local_processor_contexts<TS, TI, TR>::iterator cpc = contexts.context_map ().find (&mp_subject_layout->cell (*bu));
|
||||
if (cpc != contexts.context_map ().end ()) {
|
||||
cpc->second.compute_results (contexts, cpc->first, op, output_layer, this);
|
||||
contexts.context_map ().erase (cpc);
|
||||
}
|
||||
|
||||
mp_progress = 0;
|
||||
|
||||
} catch (...) {
|
||||
mp_progress = 0;
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1616,9 +1736,11 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
|
|||
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbLocalOperation.h"
|
||||
#include "tlThreadedWorkers.h"
|
||||
#include "tlProgress.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -193,6 +194,11 @@ public:
|
|||
db::local_processor_cell_context<TS, TI, TR> *create (const context_key_type &intruders);
|
||||
void compute_results (const local_processor_contexts<TS, TI, TR> &contexts, db::Cell *cell, const local_operation<TS, TI, TR> *op, unsigned int output_layer, const local_processor<TS, TI, TR> *proc);
|
||||
|
||||
size_t size () const
|
||||
{
|
||||
return m_contexts.size ();
|
||||
}
|
||||
|
||||
iterator begin () const
|
||||
{
|
||||
return m_contexts.begin ();
|
||||
|
|
@ -427,13 +433,18 @@ private:
|
|||
double m_area_ratio;
|
||||
int m_base_verbosity;
|
||||
mutable std::auto_ptr<tl::Job<local_processor_context_computation_worker<TS, TI, TR> > > mp_cc_job;
|
||||
mutable size_t m_progress;
|
||||
mutable tl::Progress *mp_progress;
|
||||
|
||||
std::string description (const local_operation<TS, TI, TR> *op) const;
|
||||
void next () const;
|
||||
size_t get_progress () const;
|
||||
void compute_contexts (db::local_processor_contexts<TS, TI, TR> &contexts, db::local_processor_cell_context<TS, TI, TR> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, db::Coord dist) const;
|
||||
void do_compute_contexts (db::local_processor_cell_context<TS, TI, TR> *cell_context, const db::local_processor_contexts<TS, TI, TR> &contexts, db::local_processor_cell_context<TS, TI, TR> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, db::Coord dist) const;
|
||||
void issue_compute_contexts (db::local_processor_contexts<TS, TI, TR> &contexts, db::local_processor_cell_context<TS, TI, TR> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, db::Coord dist) const;
|
||||
void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<TR> &result) const;
|
||||
void compute_local_cell (const db::local_processor_contexts<TS, TI, TR> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI, TR> *op, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, std::unordered_set<TR> &result) const;
|
||||
std::pair<bool, db::CellInstArray> effective_instance (local_processor_contexts<TS, TI, TR> &contexts, db::cell_index_type subject_cell_index, db::cell_index_type intruder_cell_index, const db::ICplxTrans &ti2s, db::Coord dist) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1355,6 +1355,46 @@ public:
|
|||
return Region (mp_delegate->selected_not_overlapping (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of "other" which are inside polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region pull_inside (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->pull_inside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edges of "other" which are interacting (touching or overlapping with) polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Edges pull_interacting (const Edges &other) const
|
||||
{
|
||||
return Edges (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of "other" which are interacting (touching or overlapping with) polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region pull_interacting (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of "other" which are overlapping with polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region pull_overlapping (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->pull_overlapping (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the holes
|
||||
*
|
||||
|
|
|
|||
|
|
@ -294,6 +294,10 @@ public:
|
|||
virtual RegionDelegate *selected_not_interacting (const Edges &other) const = 0;
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_interacting (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0;
|
||||
virtual RegionDelegate *pull_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *in (const Region &other, bool invert) const = 0;
|
||||
|
||||
virtual const db::Polygon *nth (size_t n) const = 0;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
|
||||
#include "dbRegionUtils.h"
|
||||
#include "tlSelect.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -288,22 +289,28 @@ Poly2PolyCheckBase::enter (const db::Polygon &o1, size_t p1, const db::Polygon &
|
|||
// -------------------------------------------------------------------------------------
|
||||
// RegionToEdgeInteractionFilterBase implementation
|
||||
|
||||
RegionToEdgeInteractionFilterBase::RegionToEdgeInteractionFilterBase (bool inverse)
|
||||
template <class OutputType>
|
||||
region_to_edge_interaction_filter_base<OutputType>::region_to_edge_interaction_filter_base (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class OutputType>
|
||||
void
|
||||
RegionToEdgeInteractionFilterBase::preset (const db::Polygon *poly)
|
||||
region_to_edge_interaction_filter_base<OutputType>::preset (const OutputType *s)
|
||||
{
|
||||
m_seen.insert (poly);
|
||||
m_seen.insert (s);
|
||||
}
|
||||
|
||||
template <class OutputType>
|
||||
void
|
||||
RegionToEdgeInteractionFilterBase::add (const db::Polygon *p, size_t, const db::Edge *e, size_t)
|
||||
region_to_edge_interaction_filter_base<OutputType>::add (const db::Polygon *p, size_t, const db::Edge *e, size_t)
|
||||
{
|
||||
if ((m_seen.find (p) == m_seen.end ()) != m_inverse) {
|
||||
const OutputType *o = 0;
|
||||
tl::select (o, p, e);
|
||||
|
||||
if ((m_seen.find (o) == m_seen.end ()) != m_inverse) {
|
||||
|
||||
// A polygon and an edge interact if the edge is either inside completely
|
||||
// of at least one edge of the polygon intersects with the edge
|
||||
|
|
@ -320,23 +327,28 @@ RegionToEdgeInteractionFilterBase::add (const db::Polygon *p, size_t, const db::
|
|||
|
||||
if (interacts) {
|
||||
if (m_inverse) {
|
||||
m_seen.erase (p);
|
||||
m_seen.erase (o);
|
||||
} else {
|
||||
m_seen.insert (p);
|
||||
put (*p);
|
||||
m_seen.insert (o);
|
||||
put (*o);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class OutputType>
|
||||
void
|
||||
RegionToEdgeInteractionFilterBase::fill_output ()
|
||||
region_to_edge_interaction_filter_base<OutputType>::fill_output ()
|
||||
{
|
||||
for (std::set<const db::Polygon *>::const_iterator p = m_seen.begin (); p != m_seen.end (); ++p) {
|
||||
put (**p);
|
||||
for (typename std::set<const OutputType *>::const_iterator s = m_seen.begin (); s != m_seen.end (); ++s) {
|
||||
put (**s);
|
||||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class region_to_edge_interaction_filter_base<db::Polygon>;
|
||||
template class region_to_edge_interaction_filter_base<db::Edge>;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -481,40 +481,41 @@ public:
|
|||
/**
|
||||
* @brief A helper class for the region to edge interaction functionality
|
||||
*/
|
||||
class DB_PUBLIC RegionToEdgeInteractionFilterBase
|
||||
template <class OutputType>
|
||||
class DB_PUBLIC region_to_edge_interaction_filter_base
|
||||
: public db::box_scanner_receiver2<db::Polygon, size_t, db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
RegionToEdgeInteractionFilterBase (bool inverse);
|
||||
region_to_edge_interaction_filter_base (bool inverse);
|
||||
|
||||
void preset (const db::Polygon *poly);
|
||||
void preset (const OutputType *s);
|
||||
void add (const db::Polygon *p, size_t, const db::Edge *e, size_t);
|
||||
void fill_output ();
|
||||
|
||||
protected:
|
||||
virtual void put (const db::Polygon &poly) const = 0;
|
||||
virtual void put (const OutputType &s) const = 0;
|
||||
|
||||
private:
|
||||
std::set<const db::Polygon *> m_seen;
|
||||
std::set<const OutputType *> m_seen;
|
||||
bool m_inverse;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class for the region to edge interaction functionality
|
||||
*/
|
||||
template <class OutputContainer>
|
||||
template <class OutputContainer, class OutputType = typename OutputContainer::value_type>
|
||||
class DB_PUBLIC_TEMPLATE region_to_edge_interaction_filter
|
||||
: public RegionToEdgeInteractionFilterBase
|
||||
: public region_to_edge_interaction_filter_base<OutputType>
|
||||
{
|
||||
public:
|
||||
region_to_edge_interaction_filter (OutputContainer &output, bool inverse)
|
||||
: RegionToEdgeInteractionFilterBase (inverse), mp_output (&output)
|
||||
: region_to_edge_interaction_filter_base<OutputType> (inverse), mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void put (const db::Polygon &poly) const
|
||||
virtual void put (const OutputType &poly) const
|
||||
{
|
||||
mp_output->insert (poly);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,6 +316,13 @@ static db::Region extended (const db::Edges *r, db::Coord b, db::Coord e, db::Co
|
|||
return out;
|
||||
}
|
||||
|
||||
static db::Region pull_interacting (const db::Edges *r, const db::Region &other)
|
||||
{
|
||||
db::Region out;
|
||||
r->pull_interacting (out, other);
|
||||
return out;
|
||||
}
|
||||
|
||||
static db::Region extents2 (const db::Edges *r, db::Coord dx, db::Coord dy)
|
||||
{
|
||||
db::Region e;
|
||||
|
|
@ -913,6 +920,29 @@ Class<db::Edges> dec_Edges ("db", "Edges",
|
|||
"This method does not merge the edges before they are selected. If you want to select coherent "
|
||||
"edges, make sure the edge collection is merged before this method is used.\n"
|
||||
) +
|
||||
method_ext ("pull_interacting", &pull_interacting, gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are interacting with (overlapping, touching) edges of this edge set\n"
|
||||
"The \"pull_...\" methods are similar to \"select_...\" but work the opposite way: they "
|
||||
"select shapes from the argument region rather than self. In a deep (hierarchical) context "
|
||||
"the output region will be hierarchically aligned with self, so the \"pull_...\" methods "
|
||||
"provide a way for rehierarchisation.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("pull_interacting", static_cast<db::Edges (db::Edges::*) (const db::Edges &) const> (&db::Edges::pull_interacting), gsi::arg ("other"),
|
||||
"@brief Returns all edges of \"other\" which are interacting with polygons of this edge set\n"
|
||||
"See the other \\pull_interacting version for more details.\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("inside_part", &db::Edges::inside_part, gsi::arg ("other"),
|
||||
"@brief Returns the parts of the edges of this edge collection which are inside the polygons of the region\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -611,39 +611,33 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"This constructor creates an empty region.\n"
|
||||
) +
|
||||
constructor ("new", &new_a,
|
||||
constructor ("new", &new_a, gsi::arg ("array"),
|
||||
"@brief Constructor from a polygon array\n"
|
||||
"@args array\n"
|
||||
"\n"
|
||||
"This constructor creates a region from an array of polygons.\n"
|
||||
) +
|
||||
constructor ("new", &new_b,
|
||||
constructor ("new", &new_b, gsi::arg ("box"),
|
||||
"@brief Box constructor\n"
|
||||
"@args box\n"
|
||||
"\n"
|
||||
"This constructor creates a region from a box.\n"
|
||||
) +
|
||||
constructor ("new", &new_p,
|
||||
constructor ("new", &new_p, gsi::arg ("polygon"),
|
||||
"@brief Polygon constructor\n"
|
||||
"@args polygon\n"
|
||||
"\n"
|
||||
"This constructor creates a region from a polygon.\n"
|
||||
) +
|
||||
constructor ("new", &new_ps,
|
||||
constructor ("new", &new_ps, gsi::arg ("polygon"),
|
||||
"@brief Simple polygon constructor\n"
|
||||
"@args polygon\n"
|
||||
"\n"
|
||||
"This constructor creates a region from a simple polygon.\n"
|
||||
) +
|
||||
constructor ("new", &new_path,
|
||||
constructor ("new", &new_path, gsi::arg ("path"),
|
||||
"@brief Path constructor\n"
|
||||
"@args path\n"
|
||||
"\n"
|
||||
"This constructor creates a region from a path.\n"
|
||||
) +
|
||||
constructor ("new", &new_shapes,
|
||||
constructor ("new", &new_shapes, gsi::arg ("shapes"),
|
||||
"@brief Shapes constructor\n"
|
||||
"@args shapes\n"
|
||||
"\n"
|
||||
"This constructor creates a region from a \\Shapes collection.\n"
|
||||
"\n"
|
||||
|
|
@ -779,9 +773,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"@hide\n"
|
||||
"This method is provided for DRC implementation only."
|
||||
) +
|
||||
method ("merged_semantics=", &db::Region::set_merged_semantics,
|
||||
method ("merged_semantics=", &db::Region::set_merged_semantics, gsi::arg ("f"),
|
||||
"@brief Enables or disables merged semantics\n"
|
||||
"@args f\n"
|
||||
"If merged semantics is enabled (the default), coherent polygons will be considered\n"
|
||||
"as single regions and artificial edges such as cut-lines will not be considered.\n"
|
||||
"Merged semantics thus is equivalent to considering coherent areas rather than\n"
|
||||
|
|
@ -791,9 +784,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"@brief Gets a flag indicating whether merged semantics is enabled\n"
|
||||
"See \\merged_semantics= for a description of this attribute.\n"
|
||||
) +
|
||||
method ("strict_handling=", &db::Region::set_strict_handling,
|
||||
method ("strict_handling=", &db::Region::set_strict_handling, gsi::arg ("f"),
|
||||
"@brief Enables or disables strict handling\n"
|
||||
"@args f\n"
|
||||
"\n"
|
||||
"Strict handling means to leave away some optimizations. Specifically the \n"
|
||||
"output of boolean operations will be merged even if one input is empty.\n"
|
||||
|
|
@ -810,9 +802,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23.2."
|
||||
) +
|
||||
method ("min_coherence=", &db::Region::set_min_coherence,
|
||||
method ("min_coherence=", &db::Region::set_min_coherence, gsi::arg ("f"),
|
||||
"@brief Enable or disable minimum coherence\n"
|
||||
"@args f\n"
|
||||
"If minimum coherence is set, the merge operations (explicit merge with \\merge or\n"
|
||||
"implicit merge through merged_semantics) are performed using minimum coherence mode.\n"
|
||||
"The coherence mode determines how kissing-corner situations are resolved. If\n"
|
||||
|
|
@ -825,18 +816,16 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"@brief Gets a flag indicating whether minimum coherence is selected\n"
|
||||
"See \\min_coherence= for a description of this attribute.\n"
|
||||
) +
|
||||
method_ext ("with_perimeter", with_perimeter1,
|
||||
method_ext ("with_perimeter", with_perimeter1, gsi::arg ("perimeter"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by perimeter\n"
|
||||
"@args perimeter, inverse\n"
|
||||
"Filters the polygons inside the region by perimeter. If \"inverse\" is false, only "
|
||||
"polygons which have the given perimeter are returned. If \"inverse\" is true, "
|
||||
"polygons not having the given perimeter are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_perimeter", with_perimeter2,
|
||||
method_ext ("with_perimeter", with_perimeter2, gsi::arg ("min_perimeter"), gsi::arg ("max_perimeter"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by perimeter\n"
|
||||
"@args min_perimeter, max_perimeter, inverse\n"
|
||||
"Filters the polygons inside the region by perimeter. If \"inverse\" is false, only "
|
||||
"polygons which have a perimeter larger or equal to \"min_perimeter\" and less than \"max_perimeter\" are "
|
||||
"returned. If \"inverse\" is true, "
|
||||
|
|
@ -847,18 +836,16 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_area", with_area1,
|
||||
method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by area\n"
|
||||
"@args area, inverse\n"
|
||||
"Filters the polygons inside the region by area. If \"inverse\" is false, only "
|
||||
"polygons which have the given area are returned. If \"inverse\" is true, "
|
||||
"polygons not having the given area are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_area", with_area2,
|
||||
method_ext ("with_area", with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by area\n"
|
||||
"@args min_area, max_area, inverse\n"
|
||||
"Filters the polygons inside the region by area. If \"inverse\" is false, only "
|
||||
"polygons which have an area larger or equal to \"min_area\" and less than \"max_area\" are "
|
||||
"returned. If \"inverse\" is true, "
|
||||
|
|
@ -869,18 +856,16 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_width", with_bbox_width1,
|
||||
method_ext ("with_bbox_width", with_bbox_width1, gsi::arg ("width"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width\n"
|
||||
"@args width, inverse\n"
|
||||
"Filters the polygons inside the region by the width of their bounding box. If \"inverse\" is false, only "
|
||||
"polygons whose bounding box has the given width are returned. If \"inverse\" is true, "
|
||||
"polygons whose bounding box does not have the given width are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_width", with_bbox_width2,
|
||||
method_ext ("with_bbox_width", with_bbox_width2, gsi::arg ("min_width"), gsi::arg ("max_width"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width\n"
|
||||
"@args min_width, max_width, inverse\n"
|
||||
"Filters the polygons inside the region by the width of their bounding box. If \"inverse\" is false, only "
|
||||
"polygons whose bounding box has a width larger or equal to \"min_width\" and less than \"max_width\" are "
|
||||
"returned. If \"inverse\" is true, all polygons not matching this criterion are returned."
|
||||
|
|
@ -889,18 +874,16 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_height", with_bbox_height1,
|
||||
method_ext ("with_bbox_height", with_bbox_height1, gsi::arg ("height"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box height\n"
|
||||
"@args height, inverse\n"
|
||||
"Filters the polygons inside the region by the height of their bounding box. If \"inverse\" is false, only "
|
||||
"polygons whose bounding box has the given height are returned. If \"inverse\" is true, "
|
||||
"polygons whose bounding box does not have the given height are returned.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_height", with_bbox_height2,
|
||||
method_ext ("with_bbox_height", with_bbox_height2, gsi::arg ("min_height"), gsi::arg ("max_height"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box height\n"
|
||||
"@args min_height, max_height, inverse\n"
|
||||
"Filters the polygons inside the region by the height of their bounding box. If \"inverse\" is false, only "
|
||||
"polygons whose bounding box has a height larger or equal to \"min_height\" and less than \"max_height\" are "
|
||||
"returned. If \"inverse\" is true, all polygons not matching this criterion are returned."
|
||||
|
|
@ -909,9 +892,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_min", with_bbox_min1,
|
||||
method_ext ("with_bbox_min", with_bbox_min1, gsi::arg ("dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is smaller\n"
|
||||
"@args dim, inverse\n"
|
||||
"Filters the polygons inside the region by the minimum dimension of their bounding box. "
|
||||
"If \"inverse\" is false, only polygons whose bounding box's smaller dimension is equal to the given value "
|
||||
"are returned. "
|
||||
|
|
@ -919,9 +901,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_min", with_bbox_min2,
|
||||
method_ext ("with_bbox_min", with_bbox_min2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is smaller\n"
|
||||
"@args min_dim, max_dim, inverse\n"
|
||||
"Filters the polygons inside the region by the minimum dimension of their bounding box. "
|
||||
"If \"inverse\" is false, only polygons whose bounding box's smaller dimension is larger or equal to \"min_dim\" "
|
||||
"and less than \"max_dim\" are returned. "
|
||||
|
|
@ -931,9 +912,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_max", with_bbox_max1,
|
||||
method_ext ("with_bbox_max", with_bbox_max1, gsi::arg ("dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is larger\n"
|
||||
"@args dim, inverse\n"
|
||||
"Filters the polygons inside the region by the maximum dimension of their bounding box. "
|
||||
"If \"inverse\" is false, only polygons whose bounding box's larger dimension is equal to the given value "
|
||||
"are returned. "
|
||||
|
|
@ -941,9 +921,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_bbox_max", with_bbox_max2,
|
||||
method_ext ("with_bbox_max", with_bbox_max2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width or height, whichever is larger\n"
|
||||
"@args min_dim, max_dim, inverse\n"
|
||||
"Filters the polygons inside the region by the minimum dimension of their bounding box. "
|
||||
"If \"inverse\" is false, only polygons whose bounding box's larger dimension is larger or equal to \"min_dim\" "
|
||||
"and less than \"max_dim\" are returned. "
|
||||
|
|
@ -959,14 +938,12 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics does not apply for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("snapped", &db::Region::snapped,
|
||||
method ("snapped", &db::Region::snapped, gsi::arg ("gx"), gsi::arg ("gy"),
|
||||
"@brief Returns the snapped region\n"
|
||||
"@args gx, gy\n"
|
||||
"This method will snap the region to the given grid and return the snapped region (see \\snap). The original region is not modified.\n"
|
||||
) +
|
||||
method ("snap", &db::Region::snap,
|
||||
method ("snap", &db::Region::snap, gsi::arg ("gx"), gsi::arg ("gy"),
|
||||
"@brief Snaps the region to the given grid\n"
|
||||
"@args gx, gy\n"
|
||||
"This method will snap the region to the given grid - each x or y coordinate is brought on the gx or gy grid by rounding "
|
||||
"to the nearest value which is a multiple of gx or gy.\n"
|
||||
"\n"
|
||||
|
|
@ -974,9 +951,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("grid_check", &db::Region::grid_check,
|
||||
method ("grid_check", &db::Region::grid_check, gsi::arg ("gx"), gsi::arg ("gy"),
|
||||
"@brief Returns a marker for all vertices not being on the given grid\n"
|
||||
"@args gx, gy\n"
|
||||
"This method will return an edge pair object for every vertex whose x coordinate is not a multiple of gx or whose "
|
||||
"y coordinate is not a multiple of gy. The edge pair objects contain two edges consisting of the same single point - the "
|
||||
"original vertex.\n"
|
||||
|
|
@ -985,9 +961,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_angle", angle_check1,
|
||||
method_ext ("with_angle", angle_check1, gsi::arg ("angle"), gsi::arg ("inverse"),
|
||||
"@brief Returns markers on every corner with the given angle (or not with the given angle)\n"
|
||||
"@args angle, inverse\n"
|
||||
"If the inverse flag is false, this method returns an error marker (an \\EdgePair object) for every corner whose connected edges "
|
||||
"form an angle with the given value (in degree). If the inverse flag is true, the method returns markers for every corner whose "
|
||||
"angle is not the given value.\n"
|
||||
|
|
@ -996,9 +971,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("with_angle", angle_check2,
|
||||
method_ext ("with_angle", angle_check2, gsi::arg ("amin"), gsi::arg ("amax"), gsi::arg ("inverse"),
|
||||
"@brief Returns markers on every corner with an angle of more than amin and less than amax (or the opposite)\n"
|
||||
"@args amin, amax, inverse\n"
|
||||
"If the inverse flag is false, this method returns an error marker (an \\EdgePair object) for every corner whose connected edges "
|
||||
"form an angle whose value is more or equal to amin (in degree) or less (but not equal to) amax. If the inverse flag is true, the method returns markers for every corner whose "
|
||||
"angle is not matching that criterion.\n"
|
||||
|
|
@ -1007,67 +981,57 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("insert", (void (db::Region::*)(const db::Box &)) &db::Region::insert,
|
||||
method ("insert", (void (db::Region::*)(const db::Box &)) &db::Region::insert, gsi::arg ("box"),
|
||||
"@brief Inserts a box\n"
|
||||
"@args box\n"
|
||||
"\n"
|
||||
"Inserts a box into the region.\n"
|
||||
) +
|
||||
method ("insert", (void (db::Region::*)(const db::Polygon &)) &db::Region::insert,
|
||||
method ("insert", (void (db::Region::*)(const db::Polygon &)) &db::Region::insert, gsi::arg ("polygon"),
|
||||
"@brief Inserts a polygon\n"
|
||||
"@args polygon\n"
|
||||
"\n"
|
||||
"Inserts a polygon into the region.\n"
|
||||
) +
|
||||
method ("insert", (void (db::Region::*)(const db::SimplePolygon &)) &db::Region::insert,
|
||||
method ("insert", (void (db::Region::*)(const db::SimplePolygon &)) &db::Region::insert, gsi::arg ("polygon"),
|
||||
"@brief Inserts a simple polygon\n"
|
||||
"@args polygon\n"
|
||||
"\n"
|
||||
"Inserts a simple polygon into the region.\n"
|
||||
) +
|
||||
method ("insert", (void (db::Region::*)(const db::Path &)) &db::Region::insert,
|
||||
method ("insert", (void (db::Region::*)(const db::Path &)) &db::Region::insert, gsi::arg ("path"),
|
||||
"@brief Inserts a path\n"
|
||||
"@args path\n"
|
||||
"\n"
|
||||
"Inserts a path into the region.\n"
|
||||
) +
|
||||
method_ext ("insert", &insert_si,
|
||||
method_ext ("insert", &insert_si, gsi::arg ("shape_iterator"),
|
||||
"@brief Inserts all shapes delivered by the recursive shape iterator into this region\n"
|
||||
"@args shape_iterator\n"
|
||||
"\n"
|
||||
"This method will insert all shapes delivered by the shape iterator and insert them into the region.\n"
|
||||
"Text objects and edges are not inserted, because they cannot be converted to polygons.\n"
|
||||
) +
|
||||
method_ext ("insert", &insert_si2,
|
||||
method_ext ("insert", &insert_si2, gsi::arg ("shape_iterator"), gsi::arg ("trans"),
|
||||
"@brief Inserts all shapes delivered by the recursive shape iterator into this region with a transformation\n"
|
||||
"@args shape_iterator, trans\n"
|
||||
"\n"
|
||||
"This method will insert all shapes delivered by the shape iterator and insert them into the region.\n"
|
||||
"Text objects and edges are not inserted, because they cannot be converted to polygons.\n"
|
||||
"This variant will apply the given transformation to the shapes. This is useful to scale the "
|
||||
"shapes to a specific database unit for example.\n"
|
||||
) +
|
||||
method_ext ("insert", &insert_a,
|
||||
method_ext ("insert", &insert_a, gsi::arg ("array"),
|
||||
"@brief Inserts all polygons from the array into this region\n"
|
||||
"@args array\n"
|
||||
) +
|
||||
method_ext ("insert", &insert_r,
|
||||
method_ext ("insert", &insert_r, gsi::arg ("region"),
|
||||
"@brief Inserts all polygons from the other region into this region\n"
|
||||
"@args region\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
method_ext ("insert", &insert_s,
|
||||
method_ext ("insert", &insert_s, gsi::arg ("shapes"),
|
||||
"@brief Inserts all polygons from the shape collection into this region\n"
|
||||
"@args shapes\n"
|
||||
"This method takes each \"polygon-like\" shape from the shape collection and "
|
||||
"insertes this shape into the region. Paths and boxes are converted to polygons during this process. "
|
||||
"Edges and text objects are ignored.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
method_ext ("insert", &insert_st<db::Trans>,
|
||||
method_ext ("insert", &insert_st<db::Trans>, gsi::arg ("shapes"), gsi::arg ("trans"),
|
||||
"@brief Inserts all polygons from the shape collection into this region with transformation\n"
|
||||
"@args shapes\n"
|
||||
"This method takes each \"polygon-like\" shape from the shape collection and "
|
||||
"insertes this shape into the region after applying the given transformation. "
|
||||
"Paths and boxes are converted to polygons during this process. "
|
||||
|
|
@ -1075,9 +1039,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
method_ext ("insert", &insert_st<db::ICplxTrans>,
|
||||
method_ext ("insert", &insert_st<db::ICplxTrans>, gsi::arg ("shapes"), gsi::arg ("trans"),
|
||||
"@brief Inserts all polygons from the shape collection into this region with complex transformation\n"
|
||||
"@args shapes\n"
|
||||
"This method takes each \"polygon-like\" shape from the shape collection and "
|
||||
"insertes this shape into the region after applying the given complex transformation. "
|
||||
"Paths and boxes are converted to polygons during this process. "
|
||||
|
|
@ -1093,9 +1056,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("extents", &extents1,
|
||||
method_ext ("extents", &extents1, gsi::arg ("d"),
|
||||
"@brief Returns a region with the enlarged bounding boxes of the polygons\n"
|
||||
"@args d\n"
|
||||
"This method will return a region consisting of the bounding boxes of the polygons enlarged by the given distance d.\n"
|
||||
"The enlargement is specified per edge, i.e the width and height will be increased by 2*d.\n"
|
||||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
|
|
@ -1103,9 +1065,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("extents", &extents2,
|
||||
method_ext ("extents", &extents2, gsi::arg ("dx"), gsi::arg ("dy"),
|
||||
"@brief Returns a region with the enlarged bounding boxes of the polygons\n"
|
||||
"@args dx, dy\n"
|
||||
"This method will return a region consisting of the bounding boxes of the polygons enlarged by the given distance dx in x direction and dy in y direction.\n"
|
||||
"The enlargement is specified per edge, i.e the width will be increased by 2*dx.\n"
|
||||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
|
|
@ -1151,10 +1112,9 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"Merging removes overlaps and joins touching polygons.\n"
|
||||
"If the region is already merged, this method does nothing\n"
|
||||
) +
|
||||
method_ext ("merge", &merge_ext1,
|
||||
method_ext ("merge", &merge_ext1, gsi::arg ("min_wc"),
|
||||
"@brief Merge the region with options\n"
|
||||
"\n"
|
||||
"@args min_wc\n"
|
||||
"@param min_wc Overlap selection\n"
|
||||
"@return The region after is has been merged (self).\n"
|
||||
"\n"
|
||||
|
|
@ -1165,10 +1125,9 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"This method is equivalent to \"merge(false, min_wc).\n"
|
||||
) +
|
||||
method_ext ("merge", &merge_ext2,
|
||||
method_ext ("merge", &merge_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"),
|
||||
"@brief Merge the region with options\n"
|
||||
"\n"
|
||||
"@args min_coherence, min_wc\n"
|
||||
"@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n"
|
||||
"@param min_wc Overlap selection\n"
|
||||
"@return The region after is has been merged (self).\n"
|
||||
|
|
@ -1188,9 +1147,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"If the region is already merged, this method does nothing.\n"
|
||||
"In contrast to \\merge, this method does not modify the region but returns a merged copy.\n"
|
||||
) +
|
||||
method_ext ("merged", &merged_ext1,
|
||||
method_ext ("merged", &merged_ext1, gsi::arg ("min_wc"),
|
||||
"@brief Returns the merged region (with options)\n"
|
||||
"@args min_wc\n"
|
||||
"\n"
|
||||
"@return The region after is has been merged.\n"
|
||||
"\n"
|
||||
|
|
@ -1202,10 +1160,9 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"In contrast to \\merge, this method does not modify the region but returns a merged copy.\n"
|
||||
) +
|
||||
method_ext ("merged", &merged_ext2,
|
||||
method_ext ("merged", &merged_ext2, gsi::arg ("min_coherence"), gsi::arg ("min_wc"),
|
||||
"@brief Returns the merged region (with options)\n"
|
||||
"\n"
|
||||
"@args min_coherence, min_wc\n"
|
||||
"@param min_coherence A flag indicating whether the resulting polygons shall have minimum coherence\n"
|
||||
"@param min_wc Overlap selection\n"
|
||||
"@return The region after is has been merged (self).\n"
|
||||
|
|
@ -1218,9 +1175,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"In contrast to \\merge, this method does not modify the region but returns a merged copy.\n"
|
||||
) +
|
||||
method ("round_corners", &db::Region::round_corners,
|
||||
method ("round_corners", &db::Region::round_corners, gsi::arg ("r_inner"), gsi::arg ("r_outer"), gsi::arg ("n"),
|
||||
"@brief Corner rounding\n"
|
||||
"@args r_inner, r_outer, n\n"
|
||||
"@param r_inner Inner corner radius (in database units)\n"
|
||||
"@param r_outer Outer corner radius (in database units)\n"
|
||||
"@param n The number of points per circle\n"
|
||||
|
|
@ -1232,9 +1188,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"This method modifies the region. \\rounded_corners is a method that does the same but returns a new "
|
||||
"region without modifying self. Merged semantics applies for this method.\n"
|
||||
) +
|
||||
method ("rounded_corners", &db::Region::rounded_corners,
|
||||
method ("rounded_corners", &db::Region::rounded_corners, gsi::arg ("r_inner"), gsi::arg ("r_outer"), gsi::arg ("n"),
|
||||
"@brief Corner rounding\n"
|
||||
"@args r_inner, r_outer, n\n"
|
||||
"@param r_inner Inner corner radius (in database units)\n"
|
||||
"@param r_outer Outer corner radius (in database units)\n"
|
||||
"@param n The number of points per circle\n"
|
||||
|
|
@ -1242,9 +1197,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"See \\round_corners for a description of this method. This version returns a new region instead of "
|
||||
"modifying self (out-of-place)."
|
||||
) +
|
||||
method ("smooth", &db::Region::smooth,
|
||||
method ("smooth", &db::Region::smooth, gsi::arg ("d"),
|
||||
"@brief Smoothing\n"
|
||||
"@args d\n"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"\n"
|
||||
"This method will simplify the merged polygons of the region by removing vertexes if the "
|
||||
|
|
@ -1254,18 +1208,16 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"This method modifies the region. \\smoothed is a method that does the same but returns a new "
|
||||
"region without modifying self. Merged semantics applies for this method.\n"
|
||||
) +
|
||||
method ("smoothed", &db::Region::smoothed,
|
||||
method ("smoothed", &db::Region::smoothed, gsi::arg ("d"),
|
||||
"@brief Smoothing\n"
|
||||
"@args d\n"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"\n"
|
||||
"See \\smooth for a description of this method. This version returns a new region instead of "
|
||||
"modifying self (out-of-place). It has been introduced in version 0.25."
|
||||
) +
|
||||
method ("size", (db::Region & (db::Region::*) (db::Coord, db::Coord, unsigned int)) &db::Region::size,
|
||||
method ("size", (db::Region & (db::Region::*) (db::Coord, db::Coord, unsigned int)) &db::Region::size, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"),
|
||||
"@brief Anisotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@args dx, dy, mode\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
"\n"
|
||||
"Shifts the contour outwards (dx,dy>0) or inwards (dx,dy<0).\n"
|
||||
|
|
@ -1292,314 +1244,322 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"# r now is (50,-50;50,100;100,100;100,-50)\n"
|
||||
"@/code\n"
|
||||
) +
|
||||
method ("size", (db::Region & (db::Region::*) (db::Coord, unsigned int)) &db::Region::size,
|
||||
method ("size", (db::Region & (db::Region::*) (db::Coord, unsigned int)) &db::Region::size, gsi::arg ("d"), gsi::arg ("mode"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@args d, mode\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
"\n"
|
||||
"This method is equivalent to \"size(d, d, mode)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("size", size_ext,
|
||||
method_ext ("size", size_ext, gsi::arg ("d"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@args d, mode\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
"\n"
|
||||
"This method is equivalent to \"size(d, d, 2)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, db::Coord, unsigned int) const) &db::Region::sized,
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"),
|
||||
"@brief Returns the anisotropically sized region\n"
|
||||
"\n"
|
||||
"@args dx, dy, mode\n"
|
||||
"@return The sized region\n"
|
||||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized,
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("d"), gsi::arg ("mode"),
|
||||
"@brief Returns the isotropically sized region\n"
|
||||
"\n"
|
||||
"@args d, mode\n"
|
||||
"@return The sized region\n"
|
||||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method_ext ("sized", sized_ext,
|
||||
method_ext ("sized", sized_ext, gsi::arg ("d"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@args d, mode\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
"\n"
|
||||
"This method is equivalent to \"sized(d, d, 2)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("&", &db::Region::operator&,
|
||||
method ("&", &db::Region::operator&, gsi::arg ("other"),
|
||||
"@brief Returns the boolean AND between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The result of the boolean AND operation\n"
|
||||
"\n"
|
||||
"This method will compute the boolean AND (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("&=", &db::Region::operator&=,
|
||||
method ("&=", &db::Region::operator&=, gsi::arg ("other"),
|
||||
"@brief Performs the boolean AND between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after modification (self)\n"
|
||||
"\n"
|
||||
"This method will compute the boolean AND (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("-", &db::Region::operator-,
|
||||
method ("-", &db::Region::operator-, gsi::arg ("other"),
|
||||
"@brief Returns the boolean NOT between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The result of the boolean NOT operation\n"
|
||||
"\n"
|
||||
"This method will compute the boolean NOT (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("-=", &db::Region::operator-=,
|
||||
method ("-=", &db::Region::operator-=, gsi::arg ("other"),
|
||||
"@brief Performs the boolean NOT between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after modification (self)\n"
|
||||
"\n"
|
||||
"This method will compute the boolean NOT (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("^", &db::Region::operator^,
|
||||
method ("^", &db::Region::operator^, gsi::arg ("other"),
|
||||
"@brief Returns the boolean NOT between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The result of the boolean XOR operation\n"
|
||||
"\n"
|
||||
"This method will compute the boolean XOR (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("^=", &db::Region::operator^=,
|
||||
method ("^=", &db::Region::operator^=, gsi::arg ("other"),
|
||||
"@brief Performs the boolean XOR between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after modification (self)\n"
|
||||
"\n"
|
||||
"This method will compute the boolean XOR (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("\\|", &db::Region::operator|,
|
||||
method ("\\|", &db::Region::operator|, gsi::arg ("other"),
|
||||
"@brief Returns the boolean OR between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The resulting region\n"
|
||||
"\n"
|
||||
"The boolean OR is implemented by merging the polygons of both regions. To simply join the regions "
|
||||
"without merging, the + operator is more efficient."
|
||||
) +
|
||||
method ("\\|=", &db::Region::operator|=,
|
||||
method ("\\|=", &db::Region::operator|=, gsi::arg ("other"),
|
||||
"@brief Performs the boolean OR between self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after modification (self)\n"
|
||||
"\n"
|
||||
"The boolean OR is implemented by merging the polygons of both regions. To simply join the regions "
|
||||
"without merging, the + operator is more efficient."
|
||||
) +
|
||||
method ("+", &db::Region::operator+,
|
||||
method ("+", &db::Region::operator+, gsi::arg ("other"),
|
||||
"@brief Returns the combined region of self and the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The resulting region\n"
|
||||
"\n"
|
||||
"This operator adds the polygons of the other region to self and returns a new combined region. "
|
||||
"This usually creates unmerged regions and polygons may overlap. Use \\merge if you want to ensure the result region is merged.\n"
|
||||
) +
|
||||
method ("+=", &db::Region::operator+=,
|
||||
method ("+=", &db::Region::operator+=, gsi::arg ("other"),
|
||||
"@brief Adds the polygons of the other region to self\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after modification (self)\n"
|
||||
"\n"
|
||||
"This operator adds the polygons of the other region to self. "
|
||||
"This usually creates unmerged regions and polygons may overlap. Use \\merge if you want to ensure the result region is merged.\n"
|
||||
) +
|
||||
method ("inside", &db::Region::selected_inside,
|
||||
method ("inside", &db::Region::selected_inside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons which are inside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("not_inside", &db::Region::selected_not_inside,
|
||||
method ("not_inside", &db::Region::selected_not_inside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are not completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons which are not inside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_inside", &db::Region::select_inside,
|
||||
method ("select_inside", &db::Region::select_inside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_not_inside", &db::Region::select_not_inside,
|
||||
method ("select_not_inside", &db::Region::select_not_inside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are not completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("outside", &db::Region::selected_outside,
|
||||
method ("outside", &db::Region::selected_outside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons which are outside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("not_outside", &db::Region::selected_not_outside,
|
||||
method ("not_outside", &db::Region::selected_not_outside, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which are not completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons which are not outside polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_outside", &db::Region::select_outside,
|
||||
method ("select_outside", &db::Region::select_outside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_not_outside", &db::Region::select_not_outside,
|
||||
method ("select_not_outside", &db::Region::select_not_outside, gsi::arg ("other"),
|
||||
"@brief Selects the polygons of this region which are not completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Region &) const) &db::Region::selected_interacting,
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Region &) const) &db::Region::selected_interacting, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons overlapping or touching polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Region &) const) &db::Region::selected_not_interacting,
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Region &) const) &db::Region::selected_not_interacting, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which do not overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons not overlapping or touching polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &)) &db::Region::select_interacting,
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &)) &db::Region::select_interacting, gsi::arg ("other"),
|
||||
"@brief Selects the polygons from this region which overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Region &)) &db::Region::select_not_interacting,
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Region &)) &db::Region::select_not_interacting, gsi::arg ("other"),
|
||||
"@brief Selects the polygons from this region which do not overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Edges &) const) &db::Region::selected_interacting,
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Edges &) const) &db::Region::selected_interacting, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons overlapping or touching edges from the edge collection\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
) +
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Edges &) const) &db::Region::selected_not_interacting,
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Edges &) const) &db::Region::selected_not_interacting, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which do not overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons not overlapping or touching edges from the edge collection\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &)) &db::Region::select_interacting,
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &)) &db::Region::select_interacting, gsi::arg ("other"),
|
||||
"@brief Selects the polygons from this region which overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Edges &)) &db::Region::select_not_interacting,
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Edges &)) &db::Region::select_not_interacting, gsi::arg ("other"),
|
||||
"@brief Selects the polygons from this region which do not overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
) +
|
||||
method ("overlapping", &db::Region::selected_overlapping,
|
||||
method ("overlapping", &db::Region::selected_overlapping, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which overlap polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons overlapping polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("not_overlapping", &db::Region::selected_not_overlapping,
|
||||
method ("not_overlapping", &db::Region::selected_not_overlapping, gsi::arg ("other"),
|
||||
"@brief Returns the polygons of this region which do not overlap polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return A new region containing the polygons not overlapping polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_overlapping", &db::Region::select_overlapping,
|
||||
method ("select_overlapping", &db::Region::select_overlapping, gsi::arg ("other"),
|
||||
"@brief Selects the polygons from this region which overlap polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_not_overlapping", &db::Region::select_not_overlapping,
|
||||
method ("select_not_overlapping", &db::Region::select_not_overlapping, gsi::arg ("other"),
|
||||
"@brief Selects the polygons from this region which do not overlap polygons from the other region\n"
|
||||
"\n"
|
||||
"@args other\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("pull_inside", &db::Region::pull_inside, gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are inside polygons of this region\n"
|
||||
"The \"pull_...\" methods are similar to \"select_...\" but work the opposite way: they "
|
||||
"select shapes from the argument region rather than self. In a deep (hierarchical) context "
|
||||
"the output region will be hierarchically aligned with self, so the \"pull_...\" methods "
|
||||
"provide a way for rehierarchisation.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("pull_overlapping", &db::Region::pull_overlapping, gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are overlapping polygons of this region\n"
|
||||
"See \\pull_inside for a description of the \"pull_...\" methods.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("pull_interacting", static_cast<db::Region (db::Region::*) (const db::Region &) const> (&db::Region::pull_interacting), gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are interacting with (overlapping, touching) polygons of this region\n"
|
||||
"See \\pull_inside for a description of the \"pull_...\" methods.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("pull_interacting", static_cast<db::Edges (db::Region::*) (const db::Edges &) const> (&db::Region::pull_interacting), gsi::arg ("other"),
|
||||
"@brief Returns all edges of \"other\" which are interacting with polygons of this region\n"
|
||||
"See \\pull_inside for a description of the \"pull_...\" methods.\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("is_box?", &db::Region::is_box,
|
||||
"@brief Returns true, if the region is a simple box\n"
|
||||
"\n"
|
||||
|
|
@ -1652,9 +1612,8 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
method ("clear", &db::Region::clear,
|
||||
"@brief Clears the region\n"
|
||||
) +
|
||||
method ("swap", &db::Region::swap,
|
||||
method ("swap", &db::Region::swap, gsi::arg ("other"),
|
||||
"@brief Swap the contents of this region with the contents of another region\n"
|
||||
"@args other\n"
|
||||
"This method is useful to avoid excessive memory allocation in some cases. "
|
||||
"For managed memory languages such as Ruby, those cases will be rare. "
|
||||
) +
|
||||
|
|
@ -1676,15 +1635,13 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) "
|
||||
"in order to merge the polygons and detect holes.\n"
|
||||
) +
|
||||
method_ext ("members_of|#in", &in,
|
||||
method_ext ("members_of|#in", &in, gsi::arg ("other"),
|
||||
"@brief Returns all polygons which are members of the other region\n"
|
||||
"@args other\n"
|
||||
"This method returns all polygons in self which can be found in the other region as well with exactly the same "
|
||||
"geometry."
|
||||
) +
|
||||
method_ext ("not_members_of|#not_in", ¬_in,
|
||||
method_ext ("not_members_of|#not_in", ¬_in, gsi::arg ("other"),
|
||||
"@brief Returns all polygons which are not members of the other region\n"
|
||||
"@args other\n"
|
||||
"This method returns all polygons in self which can not be found in the other region with exactly the same "
|
||||
"geometry."
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -463,3 +463,23 @@ TEST(11)
|
|||
EXPECT_EQ (ba1cplx == ba2x3cplx, false);
|
||||
}
|
||||
|
||||
TEST(12_1dArraysX)
|
||||
{
|
||||
db::Vector a (0, 0);
|
||||
db::Vector b (200, 0);
|
||||
BoxArray ba (db::Box (10, 30, 30, 40), db::Trans (db::Vector (0, 0)), new db::regular_array<db::Coord> (a, b, 1, 3));
|
||||
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin ()), "0,0;200,0;400,0");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (0, 0, 200, 100), MyBoxConvert ())), "0,0");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (0, 50, 200, 110), MyBoxConvert ())), "");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (0, 40, 200, 110), MyBoxConvert ())), "0,0");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (31, 40, 210, 130), MyBoxConvert ())), "200,0");
|
||||
|
||||
ba = BoxArray (db::Box (10, 30, 30, 40), db::Trans (db::Vector (0, 0)), new db::regular_array<db::Coord> (b, a, 3, 1));
|
||||
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin ()), "0,0;200,0;400,0");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (0, 0, 200, 100), MyBoxConvert ())), "0,0");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (0, 50, 200, 110), MyBoxConvert ())), "");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (0, 40, 200, 110), MyBoxConvert ())), "0,0");
|
||||
EXPECT_EQ (positions (ba, db::Point (0, 0), ba.begin_touching (db::Box (31, 40, 210, 130), MyBoxConvert ())), "200,0");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,6 +367,20 @@ TEST(8_SelectInteracting)
|
|||
db::Edges e2 = r2.edges ();
|
||||
db::Edges e3 = r3.edges ();
|
||||
|
||||
db::Region r2f (db::RecursiveShapeIterator (ly, top_cell, l2));
|
||||
db::Region r3f (db::RecursiveShapeIterator (ly, top_cell, l3));
|
||||
db::Edges e2f = r2f.edges ();
|
||||
db::Edges e3f = r3f.edges ();
|
||||
|
||||
db::Region r2r = r2;
|
||||
r2r.set_merged_semantics (false);
|
||||
db::Region r3r = r3;
|
||||
r3r.set_merged_semantics (false);
|
||||
db::Edges e2r = r2r.edges ();
|
||||
e2r.set_merged_semantics (false);
|
||||
db::Edges e3r = r3r.edges ();
|
||||
e3r.set_merged_semantics (false);
|
||||
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
||||
|
|
@ -383,6 +397,46 @@ TEST(8_SelectInteracting)
|
|||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), e3.selected_interacting (r2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), e3.selected_not_interacting (r2));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e2.selected_interacting (e3f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e2.selected_not_interacting (e3f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), e3.selected_interacting (e2f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (33, 0)), e3.selected_not_interacting (e2f));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), e2.selected_interacting (r3f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e2.selected_not_interacting (r3f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (42, 0)), e3.selected_interacting (r2f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (43, 0)), e3.selected_not_interacting (r2f));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (50, 0)), e2r.selected_interacting (e3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (51, 0)), e2r.selected_not_interacting (e3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (52, 0)), e3r.selected_interacting (e2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (53, 0)), e3r.selected_not_interacting (e2));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (60, 0)), e2r.selected_interacting (r3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (61, 0)), e2r.selected_not_interacting (r3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (62, 0)), e3r.selected_interacting (r2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (63, 0)), e3r.selected_not_interacting (r2));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (70, 0)), e2.selected_interacting (e3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (71, 0)), e2.selected_not_interacting (e3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (72, 0)), e3.selected_interacting (e2r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (73, 0)), e3.selected_not_interacting (e2r));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (80, 0)), e2.selected_interacting (r3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (81, 0)), e2.selected_not_interacting (r3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (82, 0)), e3.selected_interacting (r2r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (83, 0)), e3.selected_not_interacting (r2r));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (90, 0)), e2r.selected_interacting (e3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (91, 0)), e2r.selected_not_interacting (e3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (92, 0)), e3r.selected_interacting (e2r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (93, 0)), e3r.selected_not_interacting (e2r));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (100, 0)), e2r.selected_interacting (r3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (101, 0)), e2r.selected_not_interacting (r3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (102, 0)), e3r.selected_interacting (r2r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (103, 0)), e3r.selected_not_interacting (r2r));
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au8.gds");
|
||||
}
|
||||
|
|
@ -435,3 +489,82 @@ TEST(9_DRCChecks)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(10_PullInteracting)
|
||||
{
|
||||
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 l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
|
||||
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
|
||||
db::Region r2r = r2;
|
||||
r2r.set_merged_semantics (false);
|
||||
db::Region r2f (db::RecursiveShapeIterator (ly, top_cell, l2));
|
||||
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
|
||||
db::Region r3r = r3;
|
||||
r3r.set_merged_semantics (false);
|
||||
db::Region r3f (db::RecursiveShapeIterator (ly, top_cell, l3));
|
||||
db::Edges e2 = r2.edges ();
|
||||
db::Edges e2r = r2r.edges ();
|
||||
e2r.set_merged_semantics (false);
|
||||
db::Edges e2f = r2f.edges ();
|
||||
db::Edges e3 = r3.edges ();
|
||||
db::Edges e3r = r3r.edges ();
|
||||
e3r.set_merged_semantics (false);
|
||||
db::Edges e3f = r3f.edges ();
|
||||
|
||||
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 (2, 0)), r2);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3);
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e2.pull_interacting (e3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e3.pull_interacting (e2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), e2.pull_interacting (e3f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), e3.pull_interacting (e2f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), e2.pull_interacting (e3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), e3.pull_interacting (e2r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (16, 0)), e2r.pull_interacting (e3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (17, 0)), e3r.pull_interacting (e2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (18, 0)), e2r.pull_interacting (e3r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (19, 0)), e3r.pull_interacting (e2r));
|
||||
|
||||
db::Region o;
|
||||
e2.pull_interacting (o, r3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), o);
|
||||
e3.pull_interacting (o, r2);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), o);
|
||||
e2.pull_interacting (o, r3f);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), o);
|
||||
e3.pull_interacting (o, r2f);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), o);
|
||||
e2.pull_interacting (o, r3r);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), o);
|
||||
e3.pull_interacting (o, r2r);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), o);
|
||||
e2r.pull_interacting (o, r3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), o);
|
||||
e3r.pull_interacting (o, r2);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (27, 0)), o);
|
||||
e2r.pull_interacting (o, r3r);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (28, 0)), o);
|
||||
e3r.pull_interacting (o, r2r);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (29, 0)), o);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au10.gds");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -784,6 +784,15 @@ TEST(14_Interacting)
|
|||
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::Region r1f (db::RecursiveShapeIterator (ly, top_cell, l1));
|
||||
db::Region r2f (db::RecursiveShapeIterator (ly, top_cell, l2));
|
||||
db::Region r6f (db::RecursiveShapeIterator (ly, top_cell, l6));
|
||||
db::Region r1r = r1;
|
||||
r1r.set_merged_semantics (false);
|
||||
db::Region r2r = r2;
|
||||
r2r.set_merged_semantics (false);
|
||||
db::Region r6r = r6;
|
||||
r6r.set_merged_semantics (false);
|
||||
|
||||
{
|
||||
db::Layout target;
|
||||
|
|
@ -807,13 +816,57 @@ TEST(14_Interacting)
|
|||
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));
|
||||
|
||||
EXPECT_EQ (r2.selected_interacting (r1).is_merged (), true);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.selected_interacting (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.selected_not_interacting (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), r2.selected_inside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (33, 0)), r2.selected_not_inside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (34, 0)), r2.selected_outside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (35, 0)), r2.selected_not_outside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (36, 0)), r2.selected_overlapping (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (37, 0)), r2.selected_not_overlapping (r1f));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r6.selected_interacting (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r6.selected_not_interacting (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (42, 0)), r6.selected_inside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (43, 0)), r6.selected_not_inside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (44, 0)), r6.selected_outside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (45, 0)), r6.selected_not_outside (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (46, 0)), r6.selected_overlapping (r1f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (47, 0)), r6.selected_not_overlapping (r1f));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (50, 0)), r2r.selected_interacting (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (51, 0)), r2r.selected_not_interacting (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (52, 0)), r2r.selected_inside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (53, 0)), r2r.selected_not_inside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (54, 0)), r2r.selected_outside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (55, 0)), r2r.selected_not_outside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (56, 0)), r2r.selected_overlapping (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (57, 0)), r2r.selected_not_overlapping (r1r));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (60, 0)), r6r.selected_interacting (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (61, 0)), r6r.selected_not_interacting (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (62, 0)), r6r.selected_inside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (63, 0)), r6r.selected_not_inside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (64, 0)), r6r.selected_outside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (65, 0)), r6r.selected_not_outside (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (66, 0)), r6r.selected_overlapping (r1r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (67, 0)), r6r.selected_not_overlapping (r1r));
|
||||
|
||||
EXPECT_EQ (r2.selected_interacting (r1).is_merged (), false);
|
||||
EXPECT_EQ (r2.selected_interacting (r1.merged ()).is_merged (), true);
|
||||
EXPECT_EQ (r2.selected_inside (r1).is_merged (), true);
|
||||
EXPECT_EQ (r2r.selected_interacting (r1).is_merged (), false);
|
||||
EXPECT_EQ (r2.selected_interacting (r1r).is_merged (), false);
|
||||
EXPECT_EQ (r2r.selected_interacting (r1r).is_merged (), false);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au14a.gds");
|
||||
}
|
||||
|
||||
db::Edges r1e = r1.edges ();
|
||||
db::Edges r1ef = r1f.edges ();
|
||||
db::Edges r1er = r1r.edges ();
|
||||
r1er.set_merged_semantics (false);
|
||||
|
||||
{
|
||||
db::Layout target;
|
||||
|
|
@ -823,8 +876,15 @@ TEST(14_Interacting)
|
|||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1e);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r6.selected_interacting (r1e));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r6.selected_not_interacting (r1e));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r6.selected_interacting (r1ef));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), r6.selected_not_interacting (r1ef));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), r6r.selected_interacting (r1er));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (33, 0)), r6r.selected_not_interacting (r1er));
|
||||
|
||||
EXPECT_EQ (r6.selected_interacting (r1e).is_merged (), true);
|
||||
EXPECT_EQ (r6.selected_interacting (r1er).is_merged (), false);
|
||||
EXPECT_EQ (r6r.selected_interacting (r1e).is_merged (), false);
|
||||
EXPECT_EQ (r6r.selected_interacting (r1er).is_merged (), false);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au14b.gds");
|
||||
|
|
@ -857,7 +917,6 @@ TEST(15_Filtered)
|
|||
EXPECT_EQ (af1_filtered.is_merged (), true);
|
||||
EXPECT_EQ (af1_else.is_merged (), true);
|
||||
|
||||
|
||||
{
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
|
@ -1283,6 +1342,116 @@ TEST(24_TextsFromDeep)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(25_Pull)
|
||||
{
|
||||
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::Region r1f (db::RecursiveShapeIterator (ly, top_cell, l1));
|
||||
db::Region r2f (db::RecursiveShapeIterator (ly, top_cell, l2));
|
||||
db::Region r6f (db::RecursiveShapeIterator (ly, top_cell, l6));
|
||||
db::Region r1r = r1;
|
||||
r1r.set_merged_semantics (false);
|
||||
db::Region r2r = r2;
|
||||
r2r.set_merged_semantics (false);
|
||||
db::Region r6r = r6;
|
||||
r6r.set_merged_semantics (false);
|
||||
|
||||
{
|
||||
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.pull_interacting (r2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1.pull_inside (r2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r1.pull_overlapping (r2));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2.pull_interacting (r6));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2.pull_inside (r6));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r2.pull_overlapping (r6));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r1.pull_interacting (r2f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r1.pull_inside (r2f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), r1.pull_overlapping (r2f));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2.pull_interacting (r6f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2.pull_inside (r6f));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (42, 0)), r2.pull_overlapping (r6f));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (50, 0)), r1r.pull_interacting (r2r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (51, 0)), r1r.pull_inside (r2r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (52, 0)), r1r.pull_overlapping (r2r));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (60, 0)), r2r.pull_interacting (r6r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (61, 0)), r2r.pull_inside (r6r));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (62, 0)), r2r.pull_overlapping (r6r));
|
||||
|
||||
EXPECT_EQ (r2.pull_inside (r6).is_merged (), true);
|
||||
EXPECT_EQ (r2.pull_interacting (r6).is_merged (), false);
|
||||
EXPECT_EQ (r2r.pull_interacting (r6).is_merged (), false);
|
||||
EXPECT_EQ (r2.pull_interacting (r6r).is_merged (), false);
|
||||
EXPECT_EQ (r2r.pull_interacting (r6r).is_merged (), false);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au25a.gds");
|
||||
}
|
||||
|
||||
db::Edges r1e = r1.edges ();
|
||||
db::Edges r1ef = r1f.edges ();
|
||||
db::Edges r1er = r1r.edges ();
|
||||
r1er.set_merged_semantics (false);
|
||||
|
||||
db::Edges r6e = r6.edges ();
|
||||
db::Edges r6ef = r6f.edges ();
|
||||
db::Edges r6er = r6r.edges ();
|
||||
r6er.set_merged_semantics (false);
|
||||
|
||||
{
|
||||
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)), r6);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1e);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r6.pull_interacting (r1e));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r6.pull_interacting (r1ef));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r6r.pull_interacting (r1e));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r6.pull_interacting (r1er));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (16, 0)), r6r.pull_interacting (r1er));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r1.pull_interacting (r6e));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), r1.pull_interacting (r6ef));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r1r.pull_interacting (r6e));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), r1.pull_interacting (r6er));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), r1r.pull_interacting (r6er));
|
||||
|
||||
EXPECT_EQ (r6.pull_interacting (r1e).is_merged (), false);
|
||||
EXPECT_EQ (r6.merged ().pull_interacting (r1e).is_merged (), true);
|
||||
EXPECT_EQ (r6r.pull_interacting (r1er).is_merged (), false);
|
||||
EXPECT_EQ (r6r.pull_interacting (r1e).is_merged (), false);
|
||||
EXPECT_EQ (r6.pull_interacting (r1er).is_merged (), false);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au25b.gds");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(100_Integration)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
@ -1433,3 +1602,4 @@ TEST(issue_277)
|
|||
r.set_min_coherence (false); // needs to merge again
|
||||
EXPECT_EQ (r.sized (1).merged (false, 1).to_string (), "");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -854,8 +854,40 @@ TEST(22)
|
|||
EXPECT_EQ ((e & ee).to_string (), "(400,0;-2000,0);(500,-174;400,0);(1000,0;900,-173);(4000,0;1000,0)");
|
||||
}
|
||||
|
||||
// GitHub issue #72 (Edges/Region NOT issue)
|
||||
TEST(23)
|
||||
{
|
||||
db::Edges e;
|
||||
e.insert (db::Edge (db::Point (0, 0), db::Point (0, 200)));
|
||||
e.insert (db::Edge (db::Point (250, 200), db::Point (300, 0)));
|
||||
|
||||
db::Edges e2;
|
||||
e2.insert (db::Edge (db::Point (0, 100), db::Point (100, 100)));
|
||||
|
||||
EXPECT_EQ (e2.pull_interacting (e).to_string (), "(0,0;0,200)");
|
||||
|
||||
e2.clear ();
|
||||
e2.insert (db::Edge (db::Point (0, 100), db::Point (0, 100)));
|
||||
|
||||
EXPECT_EQ (e2.pull_interacting (e).to_string (), "(0,0;0,200)");
|
||||
|
||||
e2.clear ();
|
||||
e2.insert (db::Edge (db::Point (100, 0), db::Point (0, 0)));
|
||||
|
||||
EXPECT_EQ (e2.pull_interacting (e).to_string (), "(0,0;0,200)");
|
||||
|
||||
e2.clear ();
|
||||
e2.insert (db::Edge (db::Point (-100, -1), db::Point (100, -1)));
|
||||
|
||||
EXPECT_EQ (e2.pull_interacting (e).to_string (), "");
|
||||
|
||||
e2.clear ();
|
||||
e2.insert (db::Edge (db::Point (-100, 0), db::Point (100, 0)));
|
||||
|
||||
EXPECT_EQ (e2.pull_interacting (e).to_string (), "(0,0;0,200)");
|
||||
}
|
||||
|
||||
// GitHub issue #72 (Edges/Region NOT issue)
|
||||
TEST(100)
|
||||
{
|
||||
db::Edges e;
|
||||
e.insert (db::Edge (0, 0, 0, 1000));
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ TEST(10c)
|
|||
EXPECT_EQ (r.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
}
|
||||
|
||||
TEST(11)
|
||||
TEST(11)
|
||||
{
|
||||
db::Box bb[3] = { db::Box (db::Point (0, 0), db::Point (10, 10)), db::Box (), db::Box (db::Point (20, 20), db::Point (40, 50)) };
|
||||
EXPECT_EQ (db::Region (bb + 0, bb + 3).to_string (), "(0,0;0,10;10,10;10,0);(20,20;20,50;40,50;40,20)");
|
||||
|
|
@ -861,7 +861,33 @@ TEST(18c)
|
|||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
}
|
||||
|
||||
TEST(19)
|
||||
TEST(18d)
|
||||
{
|
||||
db::Region r;
|
||||
r.set_merged_semantics (false);
|
||||
r.insert (db::Box (db::Point (0, 0), db::Point (10, 10)));
|
||||
r.insert (db::Box (db::Point (20, 30), db::Point (40, 50)));
|
||||
r.insert (db::Box (db::Point (50, 10), db::Point (70, 30)));
|
||||
r.insert (db::Box (db::Point (70, 60), db::Point (90, 80)));
|
||||
r.insert (db::Box (db::Point (0, 60), db::Point (60, 80)));
|
||||
r.insert (db::Box (db::Point (0, 100), db::Point (30, 130)));
|
||||
|
||||
db::Region rr;
|
||||
rr.insert (db::Box (db::Point (10, 0), db::Point (20, 10)));
|
||||
rr.insert (db::Box (db::Point (10, 10), db::Point (50, 90)));
|
||||
rr.insert (db::Box (db::Point (10, 110), db::Point (20, 120)));
|
||||
|
||||
EXPECT_EQ (r.pull_inside (rr).to_string (), "(10,110;10,120;20,120;20,110)");
|
||||
|
||||
EXPECT_EQ (r.pull_interacting (rr).to_string (), "(10,0;10,90;50,90;50,10;20,10;20,0);(10,110;10,120;20,120;20,110)");
|
||||
EXPECT_EQ (r.pull_overlapping (rr).to_string (), "(10,0;10,90;50,90;50,10;20,10;20,0);(10,110;10,120;20,120;20,110)");
|
||||
|
||||
rr.set_merged_semantics (false);
|
||||
EXPECT_EQ (r.pull_interacting (rr).to_string (), "(10,0;10,10;20,10;20,0);(10,10;10,90;50,90;50,10);(10,110;10,120;20,120;20,110)");
|
||||
EXPECT_EQ (r.pull_overlapping (rr).to_string (), "(10,10;10,90;50,90;50,10);(10,110;10,120;20,120;20,110)");
|
||||
}
|
||||
|
||||
TEST(19)
|
||||
{
|
||||
db::Region r1;
|
||||
r1.insert (db::Box (db::Point (0, 0), db::Point (10, 20)));
|
||||
|
|
@ -1341,6 +1367,30 @@ TEST(30c)
|
|||
EXPECT_EQ (r.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
}
|
||||
|
||||
TEST(31)
|
||||
{
|
||||
db::Region r;
|
||||
EXPECT_EQ (r.pull_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "");
|
||||
r.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
r.insert (db::Box (db::Point (-100, -100), db::Point (0, 0)));
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
EXPECT_EQ (r.pull_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(20,20;20,30;30,30;30,20)");
|
||||
EXPECT_EQ (r.pull_interacting (db::Region (db::Box (db::Point (-20, -20), db::Point (30, 30)))).to_string (), "(-20,-20;-20,30;30,30;30,-20)");
|
||||
EXPECT_EQ (r.pull_interacting (db::Region (db::Box (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
|
||||
|
||||
r.clear ();
|
||||
r.insert(db::Box (db::Point (1000, 0), db::Point (6000, 4000)));
|
||||
EXPECT_EQ (r.pull_overlapping (db::Region (db::Box (db::Point (0, 4000), db::Point (2000, 6000)))).to_string (), "");
|
||||
EXPECT_EQ (db::Region (db::Box (db::Point (0, 4000), db::Point (2000, 6000))).pull_overlapping (r).to_string (), "");
|
||||
EXPECT_EQ (r.pull_overlapping (db::Region (db::Box (db::Point (0, 4000), db::Point (1000, 6000)))).to_string (), "");
|
||||
EXPECT_EQ (db::Region (db::Box (db::Point (0, 4000), db::Point (1000, 6000))).pull_overlapping (r).to_string (), "");
|
||||
EXPECT_EQ (r.pull_overlapping (db::Region (db::Box (db::Point (0, 4001), db::Point (2000, 6000)))).to_string (), "");
|
||||
EXPECT_EQ (db::Region (db::Box (db::Point (0, 4001), db::Point (2000, 6000))).pull_overlapping (r).to_string (), "");
|
||||
EXPECT_EQ (r.pull_overlapping (db::Region (db::Box (db::Point (0, 3999), db::Point (1001, 6000)))).to_string (), "(0,3999;0,6000;1001,6000;1001,3999)");
|
||||
EXPECT_EQ (db::Region (db::Box (db::Point (0, 3999), db::Point (1001, 6000))).pull_overlapping (r).to_string (), "(1000,0;1000,4000;6000,4000;6000,0)");
|
||||
}
|
||||
|
||||
TEST(100_Processors)
|
||||
{
|
||||
db::Region r;
|
||||
|
|
|
|||
|
|
@ -1296,10 +1296,16 @@ CODE
|
|||
end
|
||||
|
||||
else
|
||||
|
||||
if @dss
|
||||
@dss.threads = (@tt || 1)
|
||||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method, *args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# enable progress
|
||||
|
|
@ -1333,10 +1339,16 @@ CODE
|
|||
res = res.value
|
||||
|
||||
else
|
||||
|
||||
if @dss
|
||||
@dss.threads = (@tt || 1)
|
||||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# enable progress
|
||||
|
|
|
|||
|
|
@ -1287,7 +1287,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which overlap shapes from the other region
|
||||
# @synopsis layer.overlapping(other)
|
||||
# This method selects all shapes or regions from self which overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It returns a new layer containing the selected shapes. A version which modifies self
|
||||
# is \select_overlapping.
|
||||
|
|
@ -1308,7 +1308,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which do not overlap shapes from the other region
|
||||
# @synopsis layer.not_overlapping(other)
|
||||
# This method selects all shapes or regions from self which do not overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
#
|
||||
# The "not_overlapping" method is equivalent to the \outside method. It is provided
|
||||
|
|
@ -1324,7 +1324,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which overlap shapes from the other region
|
||||
# @synopsis layer.select_overlapping(other)
|
||||
# This method selects all shapes or regions from self which overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \overlapping.
|
||||
|
|
@ -1337,7 +1337,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which do not overlap shapes from the other region
|
||||
# @synopsis layer.select_not_overlapping(other)
|
||||
# This method selects all shapes or regions from self which do not overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \not_overlapping.
|
||||
|
|
@ -1538,7 +1538,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which touch or overlap shapes from the other region
|
||||
# @synopsis layer.interacting(other)
|
||||
# This method selects all shapes or regions from self which touch or overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It returns a new layer containing the selected shapes. A version which modifies self
|
||||
# is \select_interacting.
|
||||
|
|
@ -1559,7 +1559,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which do not touch or overlap shapes from the other region
|
||||
# @synopsis layer.not_interacting(other)
|
||||
# This method selects all shapes or regions from self which do not touch or overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It returns a new layer containing the selected shapes. A version which modifies self
|
||||
# is \select_not_interacting.
|
||||
|
|
@ -1580,7 +1580,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which touch or overlap shapes from the other region
|
||||
# @synopsis layer.select_interacting(other)
|
||||
# This method selects all shapes or regions from self which touch or overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \interacting.
|
||||
|
|
@ -1593,7 +1593,7 @@ CODE
|
|||
# @brief Selects shapes or regions of self which do not touch or overlap shapes from the other region
|
||||
# @synopsis layer.select_interacting(other)
|
||||
# This method selects all shapes or regions from self which do not touch or overlap shapes from the other
|
||||
# region. If self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \not_interacting.
|
||||
|
|
@ -1633,6 +1633,66 @@ CODE
|
|||
# @/tr
|
||||
# @/table
|
||||
|
||||
# %DRC%
|
||||
# @name pull_interacting
|
||||
# @brief Selects shapes or edges of other which touch or overlap shapes from the this region
|
||||
# @synopsis layer.pull_interacting(other)
|
||||
# This method selects all shapes or regions from other which touch or overlap shapes from this
|
||||
# region. Unless other is in raw mode (see \raw), coherent regions are selected from other,
|
||||
# otherwise individual shapes are selected.
|
||||
#
|
||||
# The functionality is similar to select_interacting, but chosing shapes from other rather
|
||||
# than from self. Because in deep mode the hierarchy reference comes from self, this method
|
||||
# provides a way to pull shapes from other to the hierarchy to self.
|
||||
#
|
||||
# This method will neither modify self nor other.
|
||||
#
|
||||
# This method is available for polygon layers. Other can be an edge or polygon layer.
|
||||
# Edges or polygons can be selected with respect to polygons of self.
|
||||
|
||||
# %DRC%
|
||||
# @name pull_overlapping
|
||||
# @brief Selects shapes or regions of other which overlap shapes from the this region
|
||||
# @synopsis layer.pull_overlapping(other)
|
||||
# This method selects all shapes or regions from other which overlap shapes from this
|
||||
# region. Unless other is in raw mode (see \raw), coherent regions are selected from other,
|
||||
# otherwise individual shapes are selected.
|
||||
#
|
||||
# The functionality is similar to select_overlapping, but chosing shapes from other rather
|
||||
# than from self. Because in deep mode the hierarchy reference comes from self, this method
|
||||
# provides a way to pull shapes from other to the hierarchy to self.
|
||||
#
|
||||
# This method is available for polygon layers. Other needs to be a polygon layer too.
|
||||
|
||||
# %DRC%
|
||||
# @name pull_inside
|
||||
# @brief Selects shapes or regions of other which are inside polygons from the this region
|
||||
# @synopsis layer.pull_inside(other)
|
||||
# This method selects all shapes or regions from other which are inside polygons from this
|
||||
# region. Unless other is in raw mode (see \raw), coherent regions are selected from other,
|
||||
# otherwise individual shapes are selected.
|
||||
#
|
||||
# The functionality is similar to select_inside, but chosing shapes from other rather
|
||||
# than from self. Because in deep mode the hierarchy reference comes from self, this method
|
||||
# provides a way to pull shapes from other to the hierarchy to self.
|
||||
#
|
||||
# This method is available for polygon layers. Other needs to be a polygon layer too.
|
||||
|
||||
%w(pull_interacting pull_overlapping pull_inside).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
if :#{f} != :pull_interacting
|
||||
requires_region("#{f}")
|
||||
other.requires_region("#{f}")
|
||||
else
|
||||
requires_edges_or_region("#{f}")
|
||||
other.requires_edges_or_region("#{f}")
|
||||
end
|
||||
DRCLayer::new(@engine, @engine._tcmd(@data, 0, @data.class, :#{f}, other.data))
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
%w(& | ^ - + interacting not_interacting overlapping not_overlapping inside not_inside outside not_outside in not_in).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
|
|
|||
|
|
@ -102,7 +102,8 @@ HEADERS = \
|
|||
tlList.h \
|
||||
tlEquivalenceClusters.h \
|
||||
tlUniqueName.h \
|
||||
tlRecipe.h
|
||||
tlRecipe.h \
|
||||
tlSelect.h
|
||||
|
||||
equals(HAVE_CURL, "1") {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_tlSelect
|
||||
#define HDR_tlSelect
|
||||
|
||||
#include "tlCommon.h"
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
template<class Q, class X>
|
||||
struct try_assign
|
||||
{
|
||||
bool operator() (Q &, const X &) { return false; }
|
||||
};
|
||||
|
||||
template<class Q>
|
||||
struct try_assign<Q, Q>
|
||||
{
|
||||
bool operator() (Q &q, const Q &x) { q = x; return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Copies either value a or b into q, whichever type matches
|
||||
*
|
||||
* Returns true, if type A or B match with Q and q has been assigned.
|
||||
*/
|
||||
template <class Q, class A, class B>
|
||||
bool select (Q &q, const A &a, const B &b)
|
||||
{
|
||||
return try_assign<Q, A> () (q, a) || try_assign<Q, B> () (q, b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -47,7 +47,7 @@ def run_testsuite(dm, ic, tiled = false, hier = false)
|
|||
a.join(b).xor(a + b).is_empty? || raise("xor not empty")
|
||||
|
||||
if !tiled
|
||||
expect_eq(a.join(b).data.size, 16 * ic)
|
||||
expect_eq(a.join(b).data.size, 17 * ic)
|
||||
end
|
||||
|
||||
# NOTE: there is no clean/raw semantics in deep mode
|
||||
|
|
@ -572,6 +572,22 @@ def run_testsuite(dm, ic, tiled = false, hier = false)
|
|||
message "--- odd polygon check #{lb}"
|
||||
|
||||
y.odd_polygons.output(lb, dm)
|
||||
|
||||
lb += 10 #430
|
||||
message "--- pull_inside, pull_overlapping, pull_interacting #{lb}"
|
||||
|
||||
p = c.pull_inside(b)
|
||||
p.output(lb, dm)
|
||||
p = c.pull_interacting(b)
|
||||
p.output(lb + 1, dm)
|
||||
p = c.pull_overlapping(b)
|
||||
p.output(lb + 2, dm)
|
||||
p = c.pull_interacting(b.edges)
|
||||
p.output(lb + 3, dm)
|
||||
p = c.edges.pull_interacting(b)
|
||||
p.output(lb + 4, dm)
|
||||
p = c.edges.pull_interacting(b.edges)
|
||||
p.output(lb + 5, dm)
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
Binary file not shown.
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