diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index e3d1edba8..203a89e9f 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -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 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 output (new FlatEdges (true)); + + if (! inverse) { + + edge_interaction_filter filter (*output); + scanner.process (filter, 1, db::box_convert ()); + + } else { + + std::set interacting; + edge_interaction_filter > filter (interacting); + scanner.process (filter, 1, db::box_convert ()); + + 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 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 output (new FlatEdges (true)); + edge_interaction_filter filter (*output); + scanner.process (filter, 1, db::box_convert ()); + + return output.release (); +} + +RegionDelegate * +AsIfFlatEdges::pull_generic (const Region &other) const +{ + // shortcuts + if (other.empty () || empty ()) { + return new EmptyRegion (); + } + + db::box_scanner2 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 output (new FlatRegion (true)); + + edge_to_region_interaction_filter filter (*output); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + 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 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 output (new FlatEdges (true)); - - if (! inverse) { - - edge_interaction_filter filter (*output); - scanner.process (filter, 1, db::box_convert ()); - - } else { - - std::set interacting; - edge_interaction_filter > filter (interacting); - scanner.process (filter, 1, db::box_convert ()); - - 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 { diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index ffc1150b7..c47cf8409 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -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; diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index a80066242..0b8682b67 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -440,13 +440,13 @@ AsIfFlatRegion::pull_generic (const Edges &other) const std::auto_ptr output (new FlatEdges (false)); region_to_edge_interaction_filter 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); } diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 61a88d447..7aa1b108d 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -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 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 &vv = vars.variants (*c); @@ -553,36 +564,34 @@ template OutputContainer * DeepEdges::processed_impl (const edge_processor &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 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 (m_deep_layer).separate_variants (*vars); + const_cast (edges).separate_variants (*vars); } } - db::Layout &layout = const_cast (m_deep_layer.layout ()); + db::Layout &layout = const_cast (edges.layout ()); std::vector heap; std::map > to_commit; - std::auto_ptr res (new OutputContainer (m_deep_layer.derived ())); + std::auto_ptr 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 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 (m_deep_layer).separate_variants (*vars); + const_cast (edges).separate_variants (*vars); } } - db::Layout &layout = const_cast (m_deep_layer.layout ()); + db::Layout &layout = const_cast (edges.layout ()); std::map > to_commit; - std::auto_ptr res (new db::DeepEdges (m_deep_layer.derived ())); + std::auto_ptr 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 res (new db::DeepRegion (m_merged_edges.derived ())); + std::auto_ptr res (new db::DeepRegion (edges.derived ())); - db::Layout &layout = const_cast (m_merged_edges.layout ()); - db::Cell &top_cell = const_cast (m_merged_edges.initial_cell ()); + db::Layout &layout = const_cast (edges.layout ()); + db::Cell &top_cell = const_cast (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 vars (red); - vars.collect (m_merged_edges.layout (), m_merged_edges.initial_cell ()); + vars.collect (edges.layout (), edges.initial_cell ()); std::map > 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 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 heap; - for (db::recursive_cluster_shape_iterator rcsi (hc, m_merged_edges.layer (), c->cell_index (), *cl); ! rcsi.at_end (); ++rcsi) { + for (db::recursive_cluster_shape_iterator 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 +{ +public: + Edge2EdgePullLocalOperation () + { + // .. nothing yet .. + } + + virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + { + db::box_scanner scanner; + + std::set others; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j)); + } + } + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::Edge &subject = interactions.subject_shape (i->first); + scanner.insert (&subject, 1); + } + + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert (o.operator-> (), 0); + } + + edge_interaction_filter > filter (result); + scanner.process (filter, 1, db::box_convert ()); + + } + + 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 { @@ -1241,27 +1290,97 @@ private: bool m_inverse; }; +struct ResultInserter +{ + typedef db::Polygon value_type; + + ResultInserter (db::Layout *layout, std::unordered_set &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 *mp_result; +}; + +class Edge2PolygonPullLocalOperation + : public local_operation +{ +public: + Edge2PolygonPullLocalOperation () + { + // .. nothing yet .. + } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + { + db::box_scanner2 scanner; + + std::set others; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j)); + } + } + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::Edge &subject = interactions.subject_shape (i->first); + scanner.insert1 (&subject, 1); + } + + std::list heap; + for (std::set::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 filter (inserter); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + } + + 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 dr_holder; const db::DeepRegion *other_deep = dynamic_cast (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 (*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 proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&edges.layout ()), const_cast (&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 dr_holder; const db::DeepEdges *other_deep = dynamic_cast (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 (*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 proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&edges.layout ()), const_cast (&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 dr_holder; + const db::DeepRegion *other_deep = dynamic_cast (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 (*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 proc (const_cast (&edges.layout ()), const_cast (&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 dr_holder; + const db::DeepEdges *other_deep = dynamic_cast (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 (*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 proc (const_cast (&edges.layout ()), const_cast (&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 res (new db::DeepEdgePairs (m_merged_edges.derived ())); + std::auto_ptr res (new db::DeepEdgePairs (edges.derived ())); db::CheckLocalOperation op (check, other_deep != 0); - db::local_processor proc (const_cast (&m_deep_layer.layout ()), - const_cast (&m_deep_layer.initial_cell ()), - other_deep ? &other_deep->deep_layer ().layout () : const_cast (&m_deep_layer.layout ()), - other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&m_deep_layer.initial_cell ())); + db::local_processor proc (const_cast (&edges.layout ()), + const_cast (&edges.initial_cell ()), + other_deep ? &other_deep->deep_layer ().layout () : const_cast (&edges.layout ()), + other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&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 (); } diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index dd70bd590..e60bab2b1 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -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 ®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 OutputContainer *processed_impl (const edge_processor &filter) const; }; diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 2eb962283..c189c9c46 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -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 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 &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 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 &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 (polygons.layout ()); db::cell_variants_collector vars (gx); - vars.collect (layout, m_merged_polygons.initial_cell ()); + vars.collect (layout, polygons.initial_cell ()); std::map > to_commit; - std::auto_ptr res (new db::DeepEdgePairs (m_merged_polygons.derived ())); + std::auto_ptr 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 &vv = vars.variants (c->cell_index ()); for (std::map::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 (polygons.layout ()); - db::Layout &layout = m_merged_polygons.layout (); - - std::auto_ptr res (new db::DeepEdgePairs (m_merged_polygons.derived ())); + std::auto_ptr 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 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 (m_merged_polygons).separate_variants (vars); + const_cast (polygons).separate_variants (vars); - db::Layout &layout = m_merged_polygons.layout (); + db::Layout &layout = const_cast (polygons.layout ()); std::vector heap; - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); + std::auto_ptr res (new db::DeepRegion (polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const std::map &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 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 (m_merged_polygons).separate_variants (*vars); + const_cast (polygons).separate_variants (*vars); } - db::Layout &layout = m_merged_polygons.layout (); + db::Layout &layout = const_cast (polygons.layout ()); - std::auto_ptr res (new db::DeepEdges (m_merged_polygons.derived ())); + std::auto_ptr 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 OutputContainer * DeepRegion::processed_impl (const polygon_processor &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 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 (m_deep_layer).separate_variants (*vars); + const_cast (polygons).separate_variants (*vars); } } - db::Layout &layout = const_cast (m_deep_layer.layout ()); + db::Layout &layout = const_cast (polygons.layout ()); std::vector heap; std::map > to_commit; - std::auto_ptr res (new OutputContainer (m_deep_layer.derived ())); + std::auto_ptr 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 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 (m_deep_layer).separate_variants (*vars); + const_cast (polygons).separate_variants (*vars); } } - db::Layout &layout = const_cast (m_deep_layer.layout ()); + db::Layout &layout = const_cast (polygons.layout ()); std::map > to_commit; - std::auto_ptr res (new db::DeepRegion (m_deep_layer.derived ())); + std::auto_ptr 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 (polygons.layout ()); db::cell_variants_collector 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 (m_merged_polygons).separate_variants (vars); + const_cast (polygons).separate_variants (vars); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); + std::auto_ptr res (new db::DeepRegion (polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const std::map &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::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 (polygons.layout ()); db::cell_variants_collector 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 (m_merged_polygons).separate_variants (vars); + const_cast (polygons).separate_variants (vars); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); + std::auto_ptr res (new db::DeepRegion (polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const std::map &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 res (new db::DeepEdgePairs (m_merged_polygons.derived ())); + std::auto_ptr res (new db::DeepEdgePairs (polygons.derived ())); db::CheckLocalOperation op (check, different_polygons, other_deep != 0); - db::local_processor proc (const_cast (&m_deep_layer.layout ()), - const_cast (&m_deep_layer.initial_cell ()), - other_deep ? &other_deep->deep_layer ().layout () : const_cast (&m_deep_layer.layout ()), - other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&m_deep_layer.initial_cell ())); + db::local_processor proc (const_cast (&polygons.layout ()), + const_cast (&polygons.initial_cell ()), + other_deep ? &other_deep->deep_layer ().layout () : const_cast (&polygons.layout ()), + other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&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 (polygons.layout ()); - std::auto_ptr res (new db::DeepEdgePairs (m_merged_polygons.derived ())); + std::auto_ptr 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 proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&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 proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&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 proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&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 proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&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; } } diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 4e49de744..276b0bf83 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -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 OutputContainer *processed_impl (const polygon_processor &filter) const; }; diff --git a/src/db/db/dbEdges.cc b/src/db/db/dbEdges.cc index aca8c0baf..e51827627 100644 --- a/src/db/db/dbEdges.cc +++ b/src/db/db/dbEdges.cc @@ -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)); diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 9ca70a5fe..a2c236d54 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -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 * diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 420e406e1..42564daca 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -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; diff --git a/src/db/db/dbEdgesUtils.h b/src/db/db/dbEdgesUtils.h index a2db45117..0be253eeb 100644 --- a/src/db/db/dbEdgesUtils.h +++ b/src/db/db/dbEdgesUtils.h @@ -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 +template class edge_to_region_interaction_filter : public db::box_scanner_receiver2 { @@ -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 m_seen; + std::set m_seen; }; /** diff --git a/src/db/db/dbEmptyEdges.cc b/src/db/db/dbEmptyEdges.cc index 211172085..8667ed923 100644 --- a/src/db/db/dbEmptyEdges.cc +++ b/src/db/db/dbEmptyEdges.cc @@ -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 { diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index 8f590bc32..243bd56a3 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -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 (); } diff --git a/src/db/db/dbFlatEdges.h b/src/db/db/dbFlatEdges.h index 415a0ca54..429950c4e 100644 --- a/src/db/db/dbFlatEdges.h +++ b/src/db/db/dbFlatEdges.h @@ -81,6 +81,8 @@ class DB_PUBLIC FlatEdges : public AsIfFlatEdges { public: + typedef db::Edge value_type; + typedef db::layer edge_layer_type; typedef edge_layer_type::iterator edge_iterator_type; diff --git a/src/db/db/dbFlatRegion.h b/src/db/db/dbFlatRegion.h index 5f7d2d2cd..34d8d67c0 100644 --- a/src/db/db/dbFlatRegion.h +++ b/src/db/db/dbFlatRegion.h @@ -81,6 +81,7 @@ class DB_PUBLIC FlatRegion : public AsIfFlatRegion { public: + typedef db::Polygon value_type; typedef db::layer polygon_layer_type; typedef polygon_layer_type::iterator polygon_iterator_type; diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index da7a55c6b..d53769649 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -1616,6 +1616,7 @@ local_processor::compute_local_cell (const db::local_processor_conte template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; diff --git a/src/db/db/dbRegionUtils.cc b/src/db/db/dbRegionUtils.cc index 90afa9148..bfdda2990 100644 --- a/src/db/db/dbRegionUtils.cc +++ b/src/db/db/dbRegionUtils.cc @@ -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 -struct edge_or_polygon; - -template <> -struct edge_or_polygon -{ - const db::Polygon *operator() (const db::Polygon *p, const db::Edge *) const { return p; } -}; - -template <> -struct edge_or_polygon -{ - const db::Edge *operator() (const db::Polygon *, const db::Edge *e) const { return e; } -}; - -} - template region_to_edge_interaction_filter_base::region_to_edge_interaction_filter_base (bool inverse) : m_inverse (inverse) @@ -326,7 +307,8 @@ template void region_to_edge_interaction_filter_base::add (const db::Polygon *p, size_t, const db::Edge *e, size_t) { - const OutputType *o = edge_or_polygon () (p, e); + const OutputType *o = 0; + tl::select (o, p, e); if ((m_seen.find (o) == m_seen.end ()) != m_inverse) { diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 0ab75e021..2f6d5c35c 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -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 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::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" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 75e81430b..7e60ba869 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -1519,7 +1519,7 @@ Class 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" diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 5bdb28766..2e8aa35ab 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -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 (), ""); } + diff --git a/src/db/unit_tests/dbRegion.cc b/src/db/unit_tests/dbRegion.cc index 31d939d4a..cca3d4d08 100644 --- a/src/db/unit_tests/dbRegion.cc +++ b/src/db/unit_tests/dbRegion.cc @@ -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))); diff --git a/src/tl/tl/tl.pro b/src/tl/tl/tl.pro index 39184f182..c63c2ec55 100644 --- a/src/tl/tl/tl.pro +++ b/src/tl/tl/tl.pro @@ -102,7 +102,8 @@ HEADERS = \ tlList.h \ tlEquivalenceClusters.h \ tlUniqueName.h \ - tlRecipe.h + tlRecipe.h \ + tlSelect.h equals(HAVE_CURL, "1") { diff --git a/src/tl/tl/tlSelect.h b/src/tl/tl/tlSelect.h new file mode 100644 index 000000000..e7ae4c3be --- /dev/null +++ b/src/tl/tl/tlSelect.h @@ -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 +struct try_assign +{ + bool operator() (Q &, const X &) { return false; } +}; + +template +struct try_assign +{ + 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 +bool select (Q &q, const A &a, const B &b) +{ + return try_assign () (q, a) || try_assign () (q, b); +} + +} + +#endif +