diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 47a87419e..e0bb9dd4e 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -1037,7 +1037,11 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, { #if defined(USE_LOCAL_PROCESSOR) - db::RegionIterator polygons (begin_merged ()); + bool needs_merged_primary = different_polygons || options.needs_merged (); +needs_merged_primary = true; // @@@ + + db::RegionIterator polygons (needs_merged_primary ? begin_merged () : begin ()); + bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); EdgeRelationFilter check (rel, d, options.metrics); check.set_include_zero (false); @@ -1059,9 +1063,12 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, if (other == subject_regionptr () || other == foreign_regionptr ()) { foreign.push_back (other == foreign_regionptr ()); others.push_back (begin_merged ()); + other_is_merged = primary_is_merged; } else { foreign.push_back (false); - if (options.whole_edges) { + if (! other->merged_semantics ()) { + other_is_merged = true; + } else if (options.whole_edges) { // NOTE: whole edges needs both inputs merged others.push_back (other->begin_merged ()); other_is_merged = true; @@ -1072,7 +1079,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, has_other = true; } - db::check_local_operation op (check, different_polygons, has_other, other_is_merged, options); + db::check_local_operation op (check, different_polygons, primary_is_merged, has_other, other_is_merged, options); std::unique_ptr output (new FlatEdgePairs ()); std::vector results; diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index 1a569a7b9..11122a2ae 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -1555,10 +1555,13 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi m_check.set_max_projection (options.max_projection); } -CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode * /*input*/, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options) +CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode *input, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options) : CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options) { + tl_assert (input == 0); // input is a dummy parameter + m_has_other = other->has_external_inputs (); +// @@@ needs a concept to deal with merged/non-merged inputs m_is_other_merged = other->is_merged (); set_description ("check"); @@ -1585,7 +1588,9 @@ CompoundRegionCheckOperationNode::computed_dist () const void CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const { - db::check_local_operation op (m_check, m_different_polygons, m_has_other, m_is_other_merged, m_options); +// @@@ needs a concept to deal with merged/non-merged primary +bool is_merged = true; + db::check_local_operation op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); tl_assert (results.size () == 1); if (results.front ().empty ()) { @@ -1601,7 +1606,9 @@ CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache void CompoundRegionCheckOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const { - db::check_local_operation op (m_check, m_different_polygons, m_has_other, m_is_other_merged, m_options); +// @@@ needs a concept to deal with merged/non-merged primary +bool is_merged = true; + db::check_local_operation op (m_check, m_different_polygons, is_merged, m_has_other, m_is_other_merged, m_options); tl_assert (results.size () == 1); if (results.front ().empty ()) { diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index f0886c723..f38d94228 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1647,16 +1647,23 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons unsigned int other_layer = 0; bool other_is_merged = true; + bool needs_merged_primary = different_polygons || options.needs_merged (); + bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); + if (other == subject_regionptr ()) { other_layer = subject_idlayer (); + other_is_merged = primary_is_merged; } else if (other == foreign_regionptr ()) { other_layer = foreign_idlayer (); + other_is_merged = primary_is_merged; } else { other_deep = dynamic_cast (other->delegate ()); if (! other_deep) { return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, options); } - if (options.whole_edges) { + if (! other->merged_semantics ()) { + other_is_merged = true; + } else if (options.whole_edges) { // NOTE: whole edges needs both inputs merged other_layer = other_deep->merged_deep_layer ().layer (); other_is_merged = true; @@ -1666,7 +1673,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons } } - const db::DeepLayer &polygons = merged_deep_layer (); + const db::DeepLayer &polygons = needs_merged_primary ? merged_deep_layer () : deep_layer (); EdgeRelationFilter check (rel, d, options.metrics); check.set_include_zero (false); @@ -1677,7 +1684,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons std::unique_ptr res (new db::DeepEdgePairs (polygons.derived ())); - db::CheckLocalOperation op (check, different_polygons, other_deep != 0, other_is_merged, options); + db::CheckLocalOperation op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options); db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), diff --git a/src/db/db/dbHash.h b/src/db/db/dbHash.h index 6d511285b..9ed98ae0b 100644 --- a/src/db/db/dbHash.h +++ b/src/db/db/dbHash.h @@ -252,8 +252,15 @@ namespace std h = hfunc_coord (o.bgn_ext (), h); h = hfunc_coord (o.end_ext (), h); h = hfunc_coord (o.width (), h); + // NOTE: using too many points for the hash function just slows down the code. + unsigned int n = 20; for (typename db::path::iterator p = o.begin (); p != o.end (); ++p) { - h = hfunc (*p, h); + if (--n == 0) { + h = hfunc (o.points (), h); + break; + } else { + h = hfunc (*p, h); + } } return h; } @@ -280,8 +287,15 @@ namespace std template size_t hfunc (const db::polygon_contour &o, size_t h) { + // NOTE: using too many points for the hash function just slows down the code. + unsigned int n = 20; for (typename db::polygon_contour::simple_iterator i = o.begin (); i != o.end (); ++i) { - h = hfunc (*i, h); + if (--n == 0) { + h = hfunc (o.size (), h); + break; + } else { + h = hfunc (*i, h); + } } return h; } @@ -309,8 +323,15 @@ namespace std size_t hfunc (const db::polygon &o, size_t h) { h = hfunc (o.hull (), h); + // NOTE: using too many points for the hash function just slows down the code. + unsigned int n = 20; for (size_t i = 0; i < o.holes (); ++i) { - h = hfunc (o.hole (int (i)), h); + if (--n == 0) { + h = hfunc (o.holes (), h); + break; + } else { + h = hfunc (o.hole (int (i)), h); + } } return h; } diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index a52f8bef2..35582d39b 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -189,15 +189,22 @@ public: typedef typename Ref::shape_type shape_type; typedef typename Ref::trans_type ref_trans_type; - shape_reference_translator_with_trans_from_shape_ref (db::Layout *target_layout, const Trans &trans) - : mp_layout (target_layout), m_trans (trans), m_ref_trans (trans), m_bare_trans (Trans (m_ref_trans.inverted ()) * trans) + shape_reference_translator_with_trans_from_shape_ref (db::Layout *target_layout) + : mp_layout (target_layout) { // .. nothing yet .. } + void set_trans (const Trans &trans) + { + m_trans = trans; + m_ref_trans = ref_trans_type (trans); + m_bare_trans = Trans (m_ref_trans.inverted ()) * trans; + } + Ref operator() (const Ref &ref) const { - typename std::unordered_map >::const_iterator m = m_cache.find (ref.ptr ()); + auto m = m_cache.find (std::make_pair (ref.ptr (), m_bare_trans)); if (m != m_cache.end ()) { return Ref (m->second.first, ref_trans_type (m_trans * Trans (ref.trans ())) * m->second.second); @@ -214,7 +221,7 @@ public: ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (sh); } - m_cache[ref.ptr ()] = std::make_pair (ptr, red_trans); + m_cache[std::make_pair (ref.ptr (), m_bare_trans)] = std::make_pair (ptr, red_trans); return Ref (ptr, ref_trans_type (m_trans * Trans (ref.trans ())) * red_trans); @@ -226,7 +233,7 @@ private: Trans m_trans; ref_trans_type m_ref_trans; Trans m_bare_trans; - mutable std::unordered_map > m_cache; + mutable std::unordered_map, std::pair > m_cache; }; template @@ -234,8 +241,8 @@ class shape_reference_translator_with_trans : public shape_reference_translator_with_trans_from_shape_ref { public: - shape_reference_translator_with_trans (db::Layout *target_layout, const Trans &trans) - : shape_reference_translator_with_trans_from_shape_ref (target_layout, trans) + shape_reference_translator_with_trans (db::Layout *target_layout) + : shape_reference_translator_with_trans_from_shape_ref (target_layout) { // .. nothing yet .. } @@ -247,12 +254,16 @@ class shape_reference_translator_with_trans public: typedef Sh shape_type; - shape_reference_translator_with_trans (db::Layout * /*target_layout*/, const Trans &trans) - : m_trans (trans) + shape_reference_translator_with_trans (db::Layout * /*target_layout*/) { // .. nothing yet .. } + void set_trans (const Trans &trans) + { + m_trans = trans; + } + shape_type operator() (const shape_type &s) const { return s.transformed (m_trans); @@ -331,11 +342,11 @@ template local_processor_cell_context & local_processor_cell_context::operator= (const local_processor_cell_context &other) { - if (this != &other) { - m_propagated = other.m_propagated; - m_drops = other.m_drops; - } - return *this; + if (this != &other) { + m_propagated = other.m_propagated; + m_drops = other.m_drops; + } + return *this; } template @@ -353,13 +364,20 @@ local_processor_cell_context::propagate (unsigned int output_layer, return; } + db::Layout *subject_layout = 0; + shape_reference_translator_with_trans rt (subject_layout); + for (typename std::vector >::const_iterator d = m_drops.begin (); d != m_drops.end (); ++d) { tl_assert (d->parent_context != 0); tl_assert (d->parent != 0); - db::Layout *subject_layout = d->parent->layout (); - shape_reference_translator_with_trans rt (subject_layout, d->cell_inst); + if (subject_layout != d->parent->layout ()) { + subject_layout = d->parent->layout (); + rt = shape_reference_translator_with_trans (subject_layout); + } + + rt.set_trans (d->cell_inst); std::vector new_refs; new_refs.reserve (res.size ()); for (typename std::unordered_set::const_iterator r = res.begin (); r != res.end (); ++r) { @@ -1180,7 +1198,7 @@ public: typedef std::unordered_map, interactions_value_type> interactions_type; interaction_registration_inst2shape (db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, interactions_type *result) - : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result) + : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result), m_rt (subject_layout) { // nothing yet .. } @@ -1195,6 +1213,7 @@ private: unsigned int m_subject_layer; db::Coord m_dist; interactions_type *mp_result; + db::shape_reference_translator_with_trans m_rt; void collect_instance_shape_interactions (const db::CellInstArray *inst, unsigned int layer, const TI &ref, db::Coord dist) @@ -1211,7 +1230,7 @@ private: if (! cbox.empty ()) { db::ICplxTrans tni = tn.inverted (); - db::shape_reference_translator_with_trans rt (mp_subject_layout, tni); + m_rt.set_trans (tni); std::set *shapes = 0; @@ -1223,7 +1242,7 @@ private: if (! shapes) { shapes = & (*mp_result) [std::make_pair (cell.cell_index (), tn)].second [layer]; } - shapes->insert (rt (ref)); + shapes->insert (m_rt (ref)); } } diff --git a/src/db/db/dbPolygon.h b/src/db/db/dbPolygon.h index 3d7657ba2..d715f8c4b 100644 --- a/src/db/db/dbPolygon.h +++ b/src/db/db/dbPolygon.h @@ -3076,6 +3076,7 @@ public: typedef typename Poly::coord_type coord_type; typedef typename Poly::point_type point_type; typedef typename Poly::box_type box_type; + typedef typename Poly::edge_type edge_type; typedef Trans trans_type; typedef Poly polygon_type; typedef db::polygon_edge_iterator polygon_edge_iterator; diff --git a/src/db/db/dbRegionCheckUtils.cc b/src/db/db/dbRegionCheckUtils.cc index c8183fa46..e09fa60ee 100644 --- a/src/db/db/dbRegionCheckUtils.cc +++ b/src/db/db/dbRegionCheckUtils.cc @@ -468,6 +468,14 @@ poly2poly_check::enter (const PolygonType &o, size_t p) } } +template +void +poly2poly_check::enter (const poly2poly_check::edge_type &e, size_t p) +{ + m_edge_heap.push_back (e); + m_scanner.insert (& m_edge_heap.back (), p); +} + // TODO: move to generic header static bool interact (const db::Box &box, const db::Edge &e) { @@ -496,6 +504,16 @@ poly2poly_check::enter (const PolygonType &o, size_t p, const poly2 } } +template +void +poly2poly_check::enter (const poly2poly_check::edge_type &e, size_t p, const poly2poly_check::box_type &box) +{ + if (! box.empty () && interact (box, e)) { + m_edge_heap.push_back (e); + m_scanner.insert (& m_edge_heap.back (), p); + } +} + template void poly2poly_check::process () diff --git a/src/db/db/dbRegionCheckUtils.h b/src/db/db/dbRegionCheckUtils.h index 6c19ed0c3..41ad724d6 100644 --- a/src/db/db/dbRegionCheckUtils.h +++ b/src/db/db/dbRegionCheckUtils.h @@ -310,6 +310,7 @@ class DB_PUBLIC poly2poly_check { public: typedef typename PolygonType::box_type box_type; + typedef typename PolygonType::edge_type edge_type; poly2poly_check (Edge2EdgeCheckBase &output); poly2poly_check (); @@ -321,6 +322,8 @@ public: void connect (Edge2EdgeCheckBase &output); void enter (const PolygonType &o, size_t p); void enter (const PolygonType &o, size_t p, const box_type &search_box); + void enter (const edge_type &o, size_t p); + void enter (const edge_type &o, size_t p, const box_type &search_box); void process (); private: diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index c2a399411..d6aa19b9e 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -122,8 +122,8 @@ static bool shields_interaction (const db::EdgePair &ep, const P &poly) } template -check_local_operation::check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options) - : m_check (check), m_different_polygons (different_polygons), m_has_other (has_other), m_other_is_merged (other_is_merged), m_options (options) +check_local_operation::check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options) + : m_check (check), m_different_polygons (different_polygons), m_is_merged (is_merged), m_has_other (has_other), m_other_is_merged (other_is_merged), m_options (options) { // .. nothing yet .. } @@ -208,12 +208,15 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape edge2edge_check_negative_or_positive > edge_check (m_check, result, intra_polygon_result, m_options.negative, m_different_polygons, m_has_other, m_options.shielded, symmetric_edge_pairs); poly2poly_check poly_check (edge_check); - std::list heap; std::unordered_set polygons; + std::unordered_set spolygons; + + db::EdgeProcessor ep; + ep.set_base_verbosity (50); std::set ids; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + for (auto j = i->second.begin (); j != i->second.end (); ++j) { ids.insert (*j); } } @@ -226,13 +229,13 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape db::Vector e (edge_check.distance (), edge_check.distance ()); db::Box subject_box; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { subject_box += db::box_convert () (interactions.subject_shape (i->first)); } if (edge_check.requires_different_layers ()) { db::Box intruder_box; - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + for (auto id = ids.begin (); id != ids.end (); ++id) { intruder_box += db::box_convert () (interactions.intruder_shape (*id).second); } common_box = subject_box.enlarged (e) & intruder_box.enlarged (e); @@ -245,14 +248,50 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape if (m_has_other) { size_t n = 0; - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const TS &subject = interactions.subject_shape (i->first); - if (! take_all) { - poly_check.enter (subject, n, common_box); - } else { - poly_check.enter (subject, n); + + if (m_is_merged || (interactions.size () == 1 && interactions.subject_shape (interactions.begin ()->first).is_box ())) { + + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &subject = interactions.subject_shape (i->first); + if (! take_all) { + poly_check.enter (subject, n, common_box); + } else { + poly_check.enter (subject, n); + } + n += 2; } - n += 2; + + } else { + + // merge needed for the subject shapes + + ep.clear (); + size_t nn = 0; + + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &is = interactions.subject_shape (i->first); + for (typename TS::polygon_edge_iterator e = is.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + + spolygons.clear (); + + db::polygon_ref_generator ps (layout, spolygons); + db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (pg, op); + + for (auto o = spolygons.begin (); o != spolygons.end (); ++o) { + if (! take_all) { + poly_check.enter (*o, n, common_box); + } else { + poly_check.enter (*o, n); + } + n += 2; + } + } // merge the intruders to remove inner edges @@ -266,20 +305,19 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape // NOTE: this local merge is not necessarily giving the same results than a global merge before running // the processor. Reason: the search range is limited, hence not all necessary components may have been // captured. - db::EdgeProcessor ep; - ep.set_base_verbosity (50); ep.clear (); - size_t i = 0; + size_t nn = 0; - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + for (auto id = ids.begin (); id != ids.end (); ++id) { const TI &is = interactions.intruder_shape (*id).second; - for (typename TI::polygon_edge_iterator e = is.begin_edge (); ! e.at_end (); ++e) { - ep.insert (*e, i); + for (auto e = is.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); } - ++i; + ++nn; } +// @@@ Use edges directly polygons.clear (); db::polygon_ref_generator ps (layout, polygons); @@ -288,7 +326,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ep.process (pg, op); n = 1; - for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { + for (auto o = polygons.begin (); o != polygons.end (); ++o) { if (! take_all) { poly_check.enter (*o, n, common_box); } else { @@ -300,7 +338,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape } else { n = 1; - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { + for (auto id = ids.begin (); id != ids.end (); ++id) { if (! take_all) { poly_check.enter (interactions.intruder_shape (*id).second, n, common_box); } else { @@ -313,34 +351,155 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape } else { - // NOTE: we need to eliminate identical shapes from intruders and subjects because those will shield + if (m_is_merged || (interactions.size () == 1 && ids.empty () && interactions.subject_shape (interactions.begin ()->first).is_box ())) { - size_t n = 0; + // no merge required - for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - // we can't directly insert because TS may be != TI - const TS &ts = interactions.subject_shape (i->first); - insert_into_hash (polygons, ts); - if (! take_all) { - poly_check.enter (ts, n, common_box); - } else { - poly_check.enter (ts, n); - } - n += 2; - } + // NOTE: we need to eliminate identical shapes from intruders and subjects because those will shield - n = 1; + size_t n = 0; + std::unordered_set subjects; - for (std::set::const_iterator id = ids.begin (); id != ids.end (); ++id) { - const TI &ti = interactions.intruder_shape (*id).second; - if (polygons.find (ti) == polygons.end ()) { + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + // we can't directly insert because TS may be != TI + const TS &ts = interactions.subject_shape (i->first); + insert_into_hash (subjects, ts); if (! take_all) { - poly_check.enter (ti, n, common_box); + poly_check.enter (ts, n, common_box); } else { - poly_check.enter (ti, n); + poly_check.enter (ts, n); } n += 2; } + + n = 1; + + for (auto id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + if (subjects.find (ti) == subjects.end ()) { + if (! take_all) { + poly_check.enter (ti, n, common_box); + } else { + poly_check.enter (ti, n); + } + } + } + + } else if (ids.empty ()) { + + // merge needed for the subject shapes - no intruders present so this is the simple case + + size_t n = 0; + + ep.clear (); + size_t nn = 0; + + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + for (auto e = ts.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + +// @@@ Use edges directly + spolygons.clear (); + + db::polygon_ref_generator ps (layout, spolygons); + db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (pg, op); + + for (auto o = spolygons.begin (); o != spolygons.end (); ++o) { + if (! take_all) { + poly_check.enter (*o, n, common_box); + } else { + poly_check.enter (*o, n); + } + n += 2; + } + + } else { + + // merge needed for the subject and intruder shapes - we merge both and then + // separate edges into those from the subject and those from intruder shapes. + + ep.clear (); + size_t nn = 0; + + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + for (auto e = ts.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + + for (auto id = ids.begin (); id != ids.end (); ++id) { + const TI &ti = interactions.intruder_shape (*id).second; + for (auto e = ti.begin_edge (); ! e.at_end (); ++e) { + ep.insert (*e, nn); + } + ++nn; + } + + std::vector edges; + + db::EdgeContainer ee (edges); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (ee, op); + ep.clear (); + + std::vector subject_edges; + + size_t sz = 0; + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + sz += ts.vertices (); + } + + subject_edges.reserve (sz); + + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + const TS &ts = interactions.subject_shape (i->first); + for (auto e = ts.begin_edge (); ! e.at_end (); ++e) { + subject_edges.push_back (*e); + } + } + + for (size_t n = 0; n <= 1; ++n) { + + std::set partial_edges; + + EdgeBooleanClusterCollector > cluster_collector (&partial_edges, n == 0 ? db::EdgeAnd : db::EdgeNot); + + db::box_scanner scanner; + scanner.reserve (edges.size () + subject_edges.size ()); + + for (auto i = edges.begin (); i != edges.end (); ++i) { + if (! i->is_degenerate ()) { + scanner.insert (i.operator-> (), 0); + } + } + + for (auto i = subject_edges.begin (); i != subject_edges.end (); ++i) { + if (! i->is_degenerate ()) { + scanner.insert (i.operator-> (), 1); + } + } + + scanner.process (cluster_collector, 1, db::box_convert ()); + + for (auto e = partial_edges.begin (); e != partial_edges.end (); ++e) { + if (! take_all) { + poly_check.enter (*e, n, common_box); + } else { + poly_check.enter (*e, n); + } + } + + } + } } diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index d5734850f..6d81c2b0d 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -197,6 +197,19 @@ struct DB_PUBLIC RegionCheckOptions * @brief Specifies whether to produce negative output */ bool negative; + + /** + * @brief Gets a value indicating whether merged primary input is required + */ + bool needs_merged () const + { + return negative + || rect_filter != NoRectFilter + || opposite_filter != NoOppositeFilter + || max_projection != std::numeric_limits::max () + || min_projection != 0 + || whole_edges; + } }; template @@ -204,7 +217,7 @@ class check_local_operation : public local_operation { public: - check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options); + check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options); virtual db::Coord dist () const; virtual OnEmptyIntruderHint on_empty_intruder_hint () const; @@ -216,6 +229,7 @@ public: private: EdgeRelationFilter m_check; bool m_different_polygons; + bool m_is_merged; bool m_has_other; bool m_other_is_merged; db::RegionCheckOptions m_options; diff --git a/src/db/db/gsiDeclDbCompoundOperation.cc b/src/db/db/gsiDeclDbCompoundOperation.cc index 2fc3924fd..84468d936 100644 --- a/src/db/db/gsiDeclDbCompoundOperation.cc +++ b/src/db/db/gsiDeclDbCompoundOperation.cc @@ -390,7 +390,7 @@ static db::CompoundRegionOperationNode *new_edge_pair_to_second_edges (db::Compo static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) { check_non_null (other, "other"); - return new db::CompoundRegionCheckOperationNode (new_primary (), other, rel, different_polygons, d, + return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d, db::RegionCheckOptions (whole_edges, metrics, ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),