From 47c9243c044f421a6750a2f72e7693aa1e8ccc63 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 26 Jun 2022 21:16:34 +0200 Subject: [PATCH] WIP --- src/db/db/dbPolygon.h | 1 + src/db/db/dbRegionCheckUtils.cc | 18 ++++ src/db/db/dbRegionCheckUtils.h | 3 + src/db/db/dbRegionLocalOperations.cc | 153 ++++++++++++++++----------- 4 files changed, 113 insertions(+), 62 deletions(-) diff --git a/src/db/db/dbPolygon.h b/src/db/db/dbPolygon.h index 1b59dfc5f..d00a099c7 100644 --- a/src/db/db/dbPolygon.h +++ b/src/db/db/dbPolygon.h @@ -3075,6 +3075,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 fcd0e98da..d6aa19b9e 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -210,7 +210,6 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape std::unordered_set polygons; std::unordered_set spolygons; - std::unordered_set subjects; db::EdgeProcessor ep; ep.set_base_verbosity (50); @@ -318,6 +317,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ++nn; } +// @@@ Use edges directly polygons.clear (); db::polygon_ref_generator ps (layout, polygons); @@ -351,13 +351,14 @@ 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 ())) { - // subject handling + // no merge required - size_t n = 0; + // NOTE: we need to eliminate identical shapes from intruders and subjects because those will shield - if (m_is_merged || (interactions.size () == 1 && interactions.subject_shape (interactions.begin ()->first).is_box ())) { + size_t n = 0; + std::unordered_set subjects; for (auto i = interactions.begin (); i != interactions.end (); ++i) { // we can't directly insert because TS may be != TI @@ -371,9 +372,24 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape n += 2; } - } else { + n = 1; - // merge needed for the subject shapes + 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; @@ -386,6 +402,7 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ++nn; } +// @@@ Use edges directly spolygons.clear (); db::polygon_ref_generator ps (layout, spolygons); @@ -394,7 +411,6 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape ep.process (pg, op); for (auto o = spolygons.begin (); o != spolygons.end (); ++o) { - insert_into_hash (subjects, *o); if (! take_all) { poly_check.enter (*o, n, common_box); } else { @@ -403,72 +419,85 @@ check_local_operation::do_compute_local (db::Layout *layout, const shape n += 2; } - } + } else { - // intruder handling - - n = 1; - - if (ids.empty ()) { - - // nothing to supply - - } else if (! m_is_merged) { - - // merge needed for intruders - we do a boolean NOT with the subject shape to - // avoid shielding + // 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 id = ids.begin (); id != ids.end (); ++id) { - const TI &ti = interactions.intruder_shape (*id).second; - if (subjects.find (ti) == subjects.end ()) { - for (auto e = ti.begin_edge (); ! e.at_end (); ++e) { - ep.insert (*e, nn); - } - nn += 2; + 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; } - if (nn > 0) { - - nn = 1; - for (auto i = subjects.begin (); i != subjects.end (); ++i) { - for (auto e = i->begin_edge (); ! e.at_end (); ++e) { - ep.insert (*e, nn); - } - nn += 2; - } - - polygons.clear (); - - db::polygon_ref_generator ps (layout, polygons); - db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); - db::BooleanOp op (db::BooleanOp::ANotB); - ep.process (pg, op); - - for (auto o = polygons.begin (); o != polygons.end (); ++o) { - if (! take_all) { - poly_check.enter (*o, n, common_box); - } else { - poly_check.enter (*o, n); - } - } - - } - - } else { - 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); + 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); + } + } + } }