Fixed several issues with raw mode/merged semantics and many Region and Edges methods. Added edge/edge pull and edge/polygon pull.

This commit is contained in:
Matthias Koefferlein 2019-10-03 01:46:49 +02:00
parent 77c8ff50ed
commit 76b8bd3279
23 changed files with 717 additions and 262 deletions

View File

@ -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
{

View File

@ -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 &region) const;
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool inverse) const;
virtual EdgesDelegate *selected_interacting_generic (const Region &region, bool inverse) const;

View File

@ -440,13 +440,13 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
std::auto_ptr<FlatEdges> output (new FlatEdges (false));
region_to_edge_interaction_filter<Shapes, db::Edge> filter (output->raw_edges (), false);
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
AddressablePolygonDelivery p (begin (), has_valid_merged_polygons ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
}
AddressableEdgeDelivery e (other.addressable_edges ());
AddressableEdgeDelivery e (other.addressable_merged_edges ());
for ( ; ! e.at_end (); ++e) {
scanner.insert2 (e.operator-> (), 0);
@ -471,13 +471,13 @@ AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) cons
}
size_t n = 1;
for (RegionIterator p = other.begin (); ! p.at_end (); ++p, ++n) {
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p, ++n) {
if (p->box ().touches (bbox ())) {
ep.insert (*p, n);
}
}
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
if (mode > 0 || p->box ().touches (other.bbox ())) {
ep.insert (*p, 0);
}
@ -501,7 +501,7 @@ AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) cons
output->reserve (n);
n = 1;
for (RegionIterator p = other.begin (); ! p.at_end (); ++p, ++n) {
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p, ++n) {
if (selected.find (n) != selected.end ()) {
output->raw_polygons ().insert (*p);
}

View File

@ -365,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
{
@ -450,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);
@ -553,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 ()) {
@ -647,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 ()) {
@ -1003,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) {
@ -1052,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);
}
@ -1081,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 ()));
}
@ -1170,6 +1174,51 @@ private:
bool m_inverse;
};
class Edge2EdgePullLocalOperation
: public local_operation<db::Edge, db::Edge, db::Edge>
{
public:
Edge2EdgePullLocalOperation ()
{
// .. nothing yet ..
}
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>
{
@ -1241,27 +1290,97 @@ 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 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);
}
@ -1269,44 +1388,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 = 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
@ -1410,7 +1564,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);
@ -1419,19 +1573,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 ();
}

View File

@ -137,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;
@ -172,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 &region, bool invert) const;
virtual EdgesDelegate *pull_generic (const Edges &edges) const;
virtual RegionDelegate *pull_generic (const Region &region) const;
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const;
virtual EdgesDelegate *selected_interacting_generic (const Region &region, bool invert) const;
template <class Result, class OutputContainer> OutputContainer *processed_impl (const edge_processor<Result> &filter) const;
};

View File

@ -402,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
{
@ -651,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);
@ -684,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);
@ -740,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) {
@ -786,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) {
@ -824,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 ());
@ -844,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);
@ -865,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;
@ -873,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;
@ -892,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) {
@ -984,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 ()) {
@ -1084,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 ()) {
@ -1242,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 ());
@ -1260,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);
@ -1320,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 ());
@ -1345,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);
@ -1480,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);
@ -1489,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 ();
}
@ -1509,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);
@ -1518,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) {
@ -1863,21 +1868,23 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
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) {
@ -1900,21 +1907,21 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
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) {
@ -1937,21 +1944,23 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
other_deep = dr_holder.get ();
}
ensure_merged_polygons_valid ();
// 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 (m_deep_layer.derived ());
DeepLayer dl_out (polygons.derived ());
db::PullLocalOperation op (mode, touching);
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) {
@ -1971,18 +1980,22 @@ DeepRegion::pull_generic (const Edges &other) const
other_deep = dr_holder.get ();
}
ensure_merged_polygons_valid ();
// 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 (m_deep_layer.derived ());
DeepLayer dl_out (polygons.derived ());
db::PullWithEdgeLocalOperation op;
db::local_processor<db::PolygonRef, 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::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 (m_deep_layer.store ()->threads ());
proc.run (&op, m_merged_polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());
return new db::DeepEdges (dl_out);
db::DeepEdges *res = new db::DeepEdges (dl_out);
res->set_is_merged (true);
return res;
}
}

View File

@ -186,6 +186,7 @@ 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;
@ -194,11 +195,6 @@ private:
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
const DeepLayer &merged_deep_layer () const
{
return m_merged_polygons;
}
template <class Result, class OutputContainer> OutputContainer *processed_impl (const polygon_processor<Result> &filter) const;
};

View File

@ -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));

View File

@ -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
*

View File

@ -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;

View File

@ -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;
};
/**

View File

@ -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
{

View File

@ -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 (); }

View File

@ -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;

View File

@ -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;

View File

@ -1616,6 +1616,7 @@ 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>;

View File

@ -22,6 +22,7 @@
#include "dbRegionUtils.h"
#include "tlSelect.h"
namespace db
{
@ -288,26 +289,6 @@ Poly2PolyCheckBase::enter (const db::Polygon &o1, size_t p1, const db::Polygon &
// -------------------------------------------------------------------------------------
// RegionToEdgeInteractionFilterBase implementation
namespace
{
template <class OutputType>
struct edge_or_polygon;
template <>
struct edge_or_polygon<db::Polygon>
{
const db::Polygon *operator() (const db::Polygon *p, const db::Edge *) const { return p; }
};
template <>
struct edge_or_polygon<db::Edge>
{
const db::Edge *operator() (const db::Polygon *, const db::Edge *e) const { return e; }
};
}
template <class OutputType>
region_to_edge_interaction_filter_base<OutputType>::region_to_edge_interaction_filter_base (bool inverse)
: m_inverse (inverse)
@ -326,7 +307,8 @@ template <class OutputType>
void
region_to_edge_interaction_filter_base<OutputType>::add (const db::Polygon *p, size_t, const db::Edge *e, size_t)
{
const OutputType *o = edge_or_polygon<OutputType> () (p, e);
const OutputType *o = 0;
tl::select (o, p, e);
if ((m_seen.find (o) == m_seen.end ()) != m_inverse) {

View File

@ -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"

View File

@ -1519,7 +1519,7 @@ Class<db::Region> decl_Region ("db", "Region",
) +
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 \"selected_...\" but work the opposite way: they "
"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"

View File

@ -1283,6 +1283,65 @@ 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::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));
EXPECT_EQ (r2.pull_interacting (r6).is_merged (), true);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au25a.gds");
}
db::Edges r1e = r1.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 (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));
EXPECT_EQ (r6.pull_interacting (r1e).is_merged (), true);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au25b.gds");
}
}
TEST(100_Integration)
{
db::Layout ly;
@ -1433,3 +1492,4 @@ TEST(issue_277)
r.set_min_coherence (false); // needs to merge again
EXPECT_EQ (r.sized (1).merged (false, 1).to_string (), "");
}

View File

@ -391,7 +391,31 @@ 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(10d)
{
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(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 +885,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)));

View File

@ -102,7 +102,8 @@ HEADERS = \
tlList.h \
tlEquivalenceClusters.h \
tlUniqueName.h \
tlRecipe.h
tlRecipe.h \
tlSelect.h
equals(HAVE_CURL, "1") {

58
src/tl/tl/tlSelect.h Normal file
View File

@ -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