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