diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index 7e998ef45..fec2ea37f 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -259,8 +259,8 @@ protected: void update_bbox (const db::Box &box); void invalidate_bbox (); - 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, bool shielded) 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, bool shielded) const; + virtual 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, bool shielded) const; + virtual 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, bool shielded) const; virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const; virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const; virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const; diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index e5e2adda2..56f3cef3a 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -88,46 +88,6 @@ public: virtual RegionDelegate *add_in_place (const Region &other); virtual RegionDelegate *add (const Region &other) const; - EdgePairsDelegate *width_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_single_polygon_check (db::WidthRelation, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - - EdgePairsDelegate *space_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_check (db::SpaceRelation, false, 0, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - - EdgePairsDelegate *isolated_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_check (db::SpaceRelation, true, 0, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - - EdgePairsDelegate *notch_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_single_polygon_check (db::SpaceRelation, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - - EdgePairsDelegate *enclosing_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_check (db::OverlapRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - - EdgePairsDelegate *overlap_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_check (db::WidthRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - - EdgePairsDelegate *separation_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_check (db::SpaceRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - - EdgePairsDelegate *inside_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const - { - return run_check (db::InsideRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded); - } - virtual EdgePairsDelegate *grid_check (db::Coord gx, db::Coord gy) const; virtual EdgePairsDelegate *angle_check (double min, double max, bool inverse) const; diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 595ad3ff6..62f35a489 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -670,26 +670,6 @@ template class DB_PUBLIC shape_interactions; namespace { -template unsigned int shape_flags (); - -template <> -inline unsigned int shape_flags () -{ - return 1 << db::ShapeIterator::PolygonRef; -} - -template <> -inline unsigned int shape_flags () -{ - return db::ShapeIterator::Edges; -} - -template <> -inline unsigned int shape_flags () -{ - return db::ShapeIterator::Texts; -} - template struct interaction_registration_shape2shape : db::box_scanner_receiver2 @@ -1657,7 +1637,7 @@ struct scan_shape2shape_same_layer } void - operator () (const db::Shapes *, unsigned int, unsigned int, shape_interactions &, db::Coord) const + operator () (const shapes_iterator &, unsigned int, unsigned int, shape_interactions &, db::Coord) const { // cannot have different types on the same layer tl_assert (false); @@ -1688,15 +1668,14 @@ struct scan_shape2shape_same_layer } void - operator () (const db::Shapes *shapes, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions &interactions, db::Coord dist) const + operator () (const shapes_iterator &subjects, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions &interactions, db::Coord dist) const { db::box_scanner scanner; interaction_registration_shape1 rec (&interactions, intruder_layer); unsigned int id = subject_id0; - for (db::Shapes::shape_iterator i = shapes->begin (shape_flags ()); !i.at_end (); ++i) { - const T *ref = i->basic_ptr (typename T::tag ()); - scanner.insert (ref, id++); + for (shapes_iterator i = subjects; !i.at_end (); ++i) { + scanner.insert (i.operator-> (), id++); } scanner.process (rec, dist, db::box_convert ()); @@ -1734,6 +1713,44 @@ struct scan_shape2shape_different_layers scanner.process (rec, dist, db::box_convert (), db::box_convert ()); } + + void + operator () (db::Layout *layout, const shapes_iterator &subjects, const shapes_iterator &intruders, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions &interactions, db::Coord dist) const + { + db::box_scanner2 scanner; + interaction_registration_shape2shape rec (layout, &interactions, intruder_layer); + + db::Box subjects_box = subjects.bbox (); + if (subjects_box != db::Box::world ()) { + subjects_box.enlarge (db::Vector (dist, dist)); + } + + db::Box intruders_box = intruders.bbox (); + if (intruders_box != db::Box::world ()) { + intruders_box.enlarge (db::Vector (dist, dist)); + } + + db::Box common_box = intruders_box & subjects_box; + if (common_box.empty ()) { + return; + } + + unsigned int id = subject_id0; + + shapes_iterator is = subjects; + is.reset (common_box, true); + for ( ; !is.at_end (); ++is) { + scanner.insert1 (is.operator-> (), id++); + } + + shapes_iterator ii = intruders; + ii.reset (common_box, true); + for (; !ii.at_end (); ++ii) { + scanner.insert2 (ii.operator-> (), interactions.next_id ()); + } + + scanner.process (rec, dist, db::box_convert (), db::box_convert ()); + } }; template @@ -1853,32 +1870,43 @@ template void local_processor::run_flat (const db::Shapes *subject_shapes, const db::Shapes *intruders, const local_operation *op, db::Shapes *result_shapes) const { - std::vector is; - is.push_back (intruders); + std::vector > is; + is.push_back (shapes_iterator (intruders)); std::vector os; os.push_back (result_shapes); - run_flat (subject_shapes, is, op, os); + run_flat (shapes_iterator (subject_shapes), is, op, os); } template void local_processor::run_flat (const db::Shapes *subject_shapes, const std::vector &intruders, const local_operation *op, const std::vector &result_shapes) const +{ + std::vector > is; + is.reserve (intruders.size ()); + for (std::vector::const_iterator i = intruders.begin (); i != intruders.end (); ++i) { + is.push_back (shapes_iterator (*i)); + } + + run_flat (shapes_iterator (subject_shapes), is, op, result_shapes); +} + +template +void +local_processor::run_flat (const shapes_iterator &subjects, const std::vector > &intruders, const local_operation *op, const std::vector &result_shapes) const { tl_assert (mp_subject_top == 0); tl_assert (mp_intruder_top == 0); shape_interactions interactions; - for (std::vector::const_iterator il = intruders.begin (); il != intruders.end (); ++il) { - - const db::Shapes *intruder_shapes = *il; + for (typename std::vector >::const_iterator il = intruders.begin (); il != intruders.end (); ++il) { // insert dummy interactions to accommodate subject vs. nothing and assign an ID // range for the subject shapes. unsigned int subject_id0 = 0; - for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags ()); !i.at_end (); ++i) { + for (shapes_iterator i = subjects; !i.at_end (); ++i) { unsigned int id = interactions.next_id (); if (subject_id0 == 0) { @@ -1886,20 +1914,19 @@ local_processor::run_flat (const db::Shapes *subject_shapes, const s } if (op->on_empty_intruder_hint () != local_operation::Drop) { - const TS *ref = i->basic_ptr (typename TS::tag ()); - interactions.add_subject (id, *ref); + interactions.add_subject (id, *i); } } static std::set empty_intruders; - if (! subject_shapes->empty () && intruder_shapes) { + if (! subjects.at_end ()) { - if (intruder_shapes == subject_shapes) { - scan_shape2shape_same_layer () (subject_shapes, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ()); + if (*il == subjects) { + scan_shape2shape_same_layer () (subjects, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ()); } else { - scan_shape2shape_different_layers () (0 /*layout*/, subject_shapes, intruder_shapes, subject_id0, 0 /*ext. intruders*/, (unsigned int) (il - intruders.begin ()), interactions, op->dist ()); + scan_shape2shape_different_layers () (0 /*layout*/, subjects, *il, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ()); } } diff --git a/src/db/db/dbHierProcessor.h b/src/db/db/dbHierProcessor.h index 33a75eeac..72e5f5525 100644 --- a/src/db/db/dbHierProcessor.h +++ b/src/db/db/dbHierProcessor.h @@ -371,6 +371,290 @@ public: } }; +template unsigned int shape_flags (); + +template <> +inline unsigned int shape_flags () +{ + return 1 << db::ShapeIterator::PolygonRef; +} + +template <> +inline unsigned int shape_flags () +{ + return db::ShapeIterator::Edges; +} + +template <> +inline unsigned int shape_flags () +{ + return db::ShapeIterator::Texts; +} + +template +class DB_PUBLIC iterator_delegate_base +{ +public: + iterator_delegate_base () { } + virtual ~iterator_delegate_base () { } + + virtual void do_reset (const db::Box ®ion, bool overlapping) = 0; + virtual db::Box bbox () const { return db::Box::world (); } + virtual bool at_end () const = 0; + virtual void inc () = 0; + virtual const T *get () const = 0; + virtual iterator_delegate_base *clone () const = 0; + virtual bool equals (const iterator_delegate_base *other) const = 0; +}; + +template +class DB_PUBLIC iterator_delegate2 + : public iterator_delegate_base +{ +public: + typedef typename Iter::value_type value_type; + + iterator_delegate2 (const Iter &from, const Iter &to) + : m_iter (from), m_from (from), m_to (to) + { } + + virtual void do_reset (const db::Box &, bool) + { + m_iter = m_from; + } + + virtual bool at_end () const + { + return m_iter == m_to; + } + + virtual void inc () + { + ++m_iter; + } + + virtual const value_type *get () const + { + return m_iter.operator-> (); + } + + iterator_delegate_base *clone () const + { + return new iterator_delegate2 (*this); + } + + virtual bool equals (const iterator_delegate_base *other) const + { + const iterator_delegate2 *o = dynamic_cast *> (other); + return o && o->m_iter == m_iter; + } + +private: + Iter m_iter, m_from, m_to; +}; + +template +class DB_PUBLIC iterator_delegate1 + : public iterator_delegate_base +{ +public: + typedef typename Iter::value_type value_type; + + iterator_delegate1 (const Iter &from) + : m_iter (from), m_from (from) + { } + + virtual void do_reset (const db::Box &, bool) + { + m_iter = m_from; + } + + virtual bool at_end () const + { + return m_iter.at_end (); + } + + virtual void inc () + { + ++m_iter; + } + + virtual const value_type &get () const + { + return *m_iter; + } + + iterator_delegate_base *clone () const + { + return new iterator_delegate1 (*this); + } + + virtual bool equals (const iterator_delegate_base *other) const + { + const iterator_delegate1 *o = dynamic_cast *> (other); + return o && o->m_iter == m_iter; + } + +private: + Iter m_iter, m_from; +}; + +template +class DB_PUBLIC shapes_iterator_delegate + : public iterator_delegate_base +{ +public: + shapes_iterator_delegate (const db::Shapes *shapes) + : mp_shapes (shapes), m_iter (mp_shapes->begin (shape_flags ())) + { + // .. nothing yet .. + } + + virtual void do_reset (const db::Box &box, bool overlapping) + { + if (box == db::Box::world ()) { + m_iter = mp_shapes->begin (shape_flags ()); + } else { + if (mp_shapes->is_bbox_dirty ()) { + const_cast (mp_shapes)->update (); + } + if (overlapping) { + m_iter = mp_shapes->begin_overlapping (box, shape_flags ()); + } else { + m_iter = mp_shapes->begin_touching (box, shape_flags ()); + } + } + } + + virtual bool at_end () const + { + return m_iter.at_end (); + } + + virtual void inc () + { + ++m_iter; + } + + virtual const T *get () const + { + return m_iter->basic_ptr (typename T::tag ()); + } + + iterator_delegate_base *clone () const + { + return new shapes_iterator_delegate (*this); + } + + virtual db::Box bbox () const + { + if (mp_shapes->is_bbox_dirty ()) { + const_cast (mp_shapes)->update (); + } + return mp_shapes->bbox (); + } + + virtual bool equals (const iterator_delegate_base *other) const + { + const shapes_iterator_delegate *o = dynamic_cast *> (other); + return o && o->mp_shapes == mp_shapes && o->m_iter.at_end () == m_iter.at_end () && (m_iter.at_end () || o->m_iter->basic_ptr (typename T::tag ()) == m_iter->basic_ptr (typename T::tag ())); + } + +private: + const db::Shapes *mp_shapes; + db::Shapes::shape_iterator m_iter; + + shapes_iterator_delegate (const shapes_iterator_delegate &other) + : mp_shapes (other.mp_shapes), m_iter (other.m_iter) + { + // .. nothing yet .. + } +}; + +template +class DB_PUBLIC shapes_iterator +{ +public: + template + shapes_iterator (const Iter &from, const Iter &to) + : mp_delegate (new iterator_delegate2 (from, to)) + { } + + template + shapes_iterator (const Iter &from) + : mp_delegate (new iterator_delegate1 (from)) + { } + + shapes_iterator (const db::Shapes *shapes) + : mp_delegate (new shapes_iterator_delegate (shapes)) + { } + + shapes_iterator (const shapes_iterator &other) + : mp_delegate (other.mp_delegate->clone ()) + { } + + shapes_iterator &operator= (const shapes_iterator &other) + { + delete mp_delegate; + mp_delegate = other.mp_delegate->clone (); + } + + bool operator== (const shapes_iterator &other) const + { + return mp_delegate->equals (other.mp_delegate); + } + + template + bool operator== (const shapes_iterator &) const + { + return false; + } + + ~shapes_iterator () + { + delete mp_delegate; + } + + const T &operator* () const + { + return *mp_delegate->get (); + } + + const T *operator-> () const + { + return mp_delegate->get (); + } + + shapes_iterator &operator++ () + { + mp_delegate->inc (); + return *this; + } + + bool at_end () const + { + return mp_delegate->at_end (); + } + + void reset () + { + mp_delegate->do_reset (db::Box::world (), false); + } + + void reset (const db::Box &box, bool overlapping) + { + mp_delegate->do_reset (box, overlapping); + } + + db::Box bbox () const + { + return mp_delegate->bbox (); + } + +public: + iterator_delegate_base *mp_delegate; +}; + template class DB_PUBLIC local_processor { @@ -385,6 +669,7 @@ public: void run_flat (const db::Shapes *subject_shapes, const db::Shapes *intruders, const local_operation *op, db::Shapes *result_shapes) const; void run_flat (const db::Shapes *subjects, const std::vector &intruders, const local_operation *op, const std::vector &result_shapes) const; + void run_flat (const shapes_iterator &subjects, const std::vector > &intruders, const local_operation *op, const std::vector &result_shapes) const; void set_description (const std::string &d) {