diff --git a/src/db/db/dbEdgeNeighborhood.cc b/src/db/db/dbEdgeNeighborhood.cc index 7aab8d821..bfa0be7ad 100644 --- a/src/db/db/dbEdgeNeighborhood.cc +++ b/src/db/db/dbEdgeNeighborhood.cc @@ -22,6 +22,7 @@ #include "dbEdgeNeighborhood.h" #include "dbBoxScanner.h" +#include "dbClip.h" namespace db { @@ -45,16 +46,121 @@ EdgeNeighborhoodCompoundOperationNode::generated_description () const return tl::to_string (tr ("Neighborhood collector")); } +namespace { + +class EdgeCollectorReceiver + : public db::box_scanner_receiver2 +{ +public: + EdgeCollectorReceiver (db::EdgeNeighborhoodVisitor *visitor, const db::Layout *layout, const db::Cell *cell, + db::Coord bext, db::Coord eext, db::Coord din, db::Coord dout) + : mp_visitor (visitor), mp_layout (layout), mp_cell (cell), + m_bext (bext), m_eext (eext), m_din (din), m_dout (dout) + { + // .. nothing yet .. + } + + void add (const db::Edge *o1, const unsigned int & /*p1*/, const db::Polygon *o2, const unsigned int &p2) + { + m_edge_neighbors[o1][p2].push_back (o2); + } + + void finalize (bool) + { + for (auto en = m_edge_neighbors.begin (); en != m_edge_neighbors.end (); ++en) { + commit_edge (*en->first, en->second); + } + } + +private: + std::map > > m_edge_neighbors; + db::EdgeNeighborhoodVisitor *mp_visitor; + const db::Layout *mp_layout; + const db::Cell *mp_cell; + db::Coord m_bext, m_eext, m_din, m_dout; + + void commit_edge (const db::Edge &edge, const std::map > &neighbors) const + { + if (edge.is_degenerate ()) { + return; + } + + db::DVector e = db::DVector (edge.d ()); + e = e * (1.0 / e.double_length ()); + + db::DVector ne (-e.y (), e.x ()); + + // transform on the edge + db::IMatrix2d trans (e.x (), ne.x (), e.y (), ne.y ()); + db::IMatrix2d itrans = trans.inverted (); + + db::Edge ref_edge = itrans * edge; + tl_assert (ref_edge.dy () == 0); + tl_assert (ref_edge.dx () > 0); + + std::set xpos; + db::Coord xmin = -m_bext - 1; + db::Coord xmax = m_eext + 1; + + for (auto n = neighbors.begin (); n != neighbors.end (); ++n) { + for (auto p = n->second.begin (); p != n->second.end (); ++p) { + db::Polygon poly = itrans * **p; + for (auto p = poly.begin_edge (); ! p.at_end (); ++p) { + db::Edge e = *p; + xpos.insert (std::max (xmin, std::min (xmax, e.p1 ().x ()))); + xpos.insert (std::max (xmin, std::min (xmax, e.p2 ().x ()))); + } + } + } + + EdgeNeighborhoodVisitor::neighbors_type binned_neighbors; + + for (auto i = xpos.begin (); i != xpos.end (); ) { + + db::Coord xfrom = *i; + ++i; + if (i == xpos.end ()) { + break; + } + db::Coord xto = *i; + + binned_neighbors.push_back (EdgeNeighborhoodVisitor::neighbors_type::value_type ()); + binned_neighbors.back ().first.first = xfrom; + binned_neighbors.back ().first.second = xto; + + db::Box clip_box (xfrom, -m_din - 1, xto, m_dout + 1); + + EdgeNeighborhoodVisitor::neighbors_per_interval_type &i2n = binned_neighbors.back ().second; + + // NOTE: this could be more efficient if we had a multi-layer capable trapezoid decomposition tool + for (auto n = neighbors.begin (); n != neighbors.end (); ++n) { + for (auto p = n->second.begin (); p != n->second.end (); ++p) { + db::Polygon poly = itrans * **p; + db::clip_poly (poly, clip_box, i2n[n->first], false); + } + } + + } + + mp_visitor->on_edge (mp_layout, mp_cell, edge, binned_neighbors); + } +}; + +} + void EdgeNeighborhoodCompoundOperationNode::do_collect_neighbors (db::box_scanner2 &scanner, const db::Layout *layout, const db::Cell *cell) const { - - + EdgeCollectorReceiver rec (const_cast (mp_visitor.get ()), layout, cell, m_bext, m_eext, m_din, m_dout); + scanner.process (rec, computed_dist (), db::box_convert (), db::box_convert ()); } void EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { + if (! mp_visitor) { + return; + } tl_assert (interactions.num_subjects () == 1); db::box_scanner2 scanner; @@ -81,6 +187,9 @@ EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperation void EdgeNeighborhoodCompoundOperationNode::do_compute_local (CompoundRegionOperationCache * /*cache*/, db::Layout *layout, db::Cell *cell, const shape_interactions &interactions, std::vector > & /*results*/, const db::LocalProcessorBase * /*proc*/) const { + if (! mp_visitor) { + return; + } tl_assert (interactions.num_subjects () == 1); db::box_scanner2 scanner; diff --git a/src/db/db/dbEdgeNeighborhood.h b/src/db/db/dbEdgeNeighborhood.h index cef890085..88c8f6185 100644 --- a/src/db/db/dbEdgeNeighborhood.h +++ b/src/db/db/dbEdgeNeighborhood.h @@ -41,7 +41,7 @@ class DB_PUBLIC EdgeNeighborhoodVisitor public: typedef std::pair position_interval_type; typedef unsigned int input_key_type; - typedef std::list neighbor_shapes_type; + typedef std::vector neighbor_shapes_type; typedef std::map neighbors_per_interval_type; typedef std::vector > neighbors_type;