WIP: some refactoring of the flat local processor mode for generalization

This commit is contained in:
Matthias Koefferlein 2020-09-26 21:45:26 +02:00
parent ec01c9b72b
commit f05fd28a94
4 changed files with 352 additions and 80 deletions

View File

@ -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<size_t>::max ()) const;
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;

View File

@ -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;

View File

@ -670,26 +670,6 @@ template class DB_PUBLIC shape_interactions<db::TextRef, db::PolygonRef>;
namespace
{
template <class T> unsigned int shape_flags ();
template <>
inline unsigned int shape_flags<db::PolygonRef> ()
{
return 1 << db::ShapeIterator::PolygonRef;
}
template <>
inline unsigned int shape_flags<db::Edge> ()
{
return db::ShapeIterator::Edges;
}
template <>
inline unsigned int shape_flags<db::TextRef> ()
{
return db::ShapeIterator::Texts;
}
template <class TS, class TI>
struct interaction_registration_shape2shape
: db::box_scanner_receiver2<TS, unsigned int, TI, unsigned int>
@ -1657,7 +1637,7 @@ struct scan_shape2shape_same_layer
}
void
operator () (const db::Shapes *, unsigned int, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
operator () (const shapes_iterator<TS> &, unsigned int, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
{
// cannot have different types on the same layer
tl_assert (false);
@ -1688,15 +1668,14 @@ struct scan_shape2shape_same_layer<T, T>
}
void
operator () (const db::Shapes *shapes, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
operator () (const shapes_iterator<T> &subjects, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
{
db::box_scanner<T, int> scanner;
interaction_registration_shape1<T, T> rec (&interactions, intruder_layer);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = shapes->begin (shape_flags<T> ()); !i.at_end (); ++i) {
const T *ref = i->basic_ptr (typename T::tag ());
scanner.insert (ref, id++);
for (shapes_iterator<T> i = subjects; !i.at_end (); ++i) {
scanner.insert (i.operator-> (), id++);
}
scanner.process (rec, dist, db::box_convert<T> ());
@ -1734,6 +1713,44 @@ struct scan_shape2shape_different_layers
scanner.process (rec, dist, db::box_convert<TS> (), db::box_convert<TI> ());
}
void
operator () (db::Layout *layout, const shapes_iterator<TS> &subjects, const shapes_iterator<TI> &intruders, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
{
db::box_scanner2<TS, int, TI, int> scanner;
interaction_registration_shape2shape<TS, TI> 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<TS> is = subjects;
is.reset (common_box, true);
for ( ; !is.at_end (); ++is) {
scanner.insert1 (is.operator-> (), id++);
}
shapes_iterator<TI> 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<TS> (), db::box_convert<TI> ());
}
};
template <class TS, class TI, class TR>
@ -1853,32 +1870,43 @@ template <class TS, class TI, class TR>
void
local_processor<TS, TI, TR>::run_flat (const db::Shapes *subject_shapes, const db::Shapes *intruders, const local_operation<TS, TI, TR> *op, db::Shapes *result_shapes) const
{
std::vector<const db::Shapes *> is;
is.push_back (intruders);
std::vector<shapes_iterator<TI> > is;
is.push_back (shapes_iterator<TI> (intruders));
std::vector<db::Shapes *> os;
os.push_back (result_shapes);
run_flat (subject_shapes, is, op, os);
run_flat (shapes_iterator<TS> (subject_shapes), is, op, os);
}
template <class TS, class TI, class TR>
void
local_processor<TS, TI, TR>::run_flat (const db::Shapes *subject_shapes, const std::vector<const db::Shapes *> &intruders, const local_operation<TS, TI, TR> *op, const std::vector<db::Shapes *> &result_shapes) const
{
std::vector<shapes_iterator<TI> > is;
is.reserve (intruders.size ());
for (std::vector<const db::Shapes *>::const_iterator i = intruders.begin (); i != intruders.end (); ++i) {
is.push_back (shapes_iterator<TI> (*i));
}
run_flat (shapes_iterator<TS> (subject_shapes), is, op, result_shapes);
}
template <class TS, class TI, class TR>
void
local_processor<TS, TI, TR>::run_flat (const shapes_iterator<TS> &subjects, const std::vector<shapes_iterator<TI> > &intruders, const local_operation<TS, TI, TR> *op, const std::vector<db::Shapes *> &result_shapes) const
{
tl_assert (mp_subject_top == 0);
tl_assert (mp_intruder_top == 0);
shape_interactions<TS, TI> interactions;
for (std::vector<const db::Shapes *>::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
const db::Shapes *intruder_shapes = *il;
for (typename std::vector<shapes_iterator<TI> >::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<TS> ()); !i.at_end (); ++i) {
for (shapes_iterator<TS> i = subjects; !i.at_end (); ++i) {
unsigned int id = interactions.next_id ();
if (subject_id0 == 0) {
@ -1886,20 +1914,19 @@ local_processor<TS, TI, TR>::run_flat (const db::Shapes *subject_shapes, const s
}
if (op->on_empty_intruder_hint () != local_operation<TS, TI, TR>::Drop) {
const TS *ref = i->basic_ptr (typename TS::tag ());
interactions.add_subject (id, *ref);
interactions.add_subject (id, *i);
}
}
static std::set<TI> empty_intruders;
if (! subject_shapes->empty () && intruder_shapes) {
if (! subjects.at_end ()) {
if (intruder_shapes == subject_shapes) {
scan_shape2shape_same_layer<TS, TI> () (subject_shapes, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
if (*il == subjects) {
scan_shape2shape_same_layer<TS, TI> () (subjects, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
} else {
scan_shape2shape_different_layers<TS, TI> () (0 /*layout*/, subject_shapes, intruder_shapes, subject_id0, 0 /*ext. intruders*/, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
scan_shape2shape_different_layers<TS, TI> () (0 /*layout*/, subjects, *il, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
}
}

View File

@ -371,6 +371,290 @@ public:
}
};
template <class T> unsigned int shape_flags ();
template <>
inline unsigned int shape_flags<db::PolygonRef> ()
{
return 1 << db::ShapeIterator::PolygonRef;
}
template <>
inline unsigned int shape_flags<db::Edge> ()
{
return db::ShapeIterator::Edges;
}
template <>
inline unsigned int shape_flags<db::TextRef> ()
{
return db::ShapeIterator::Texts;
}
template <class T>
class DB_PUBLIC iterator_delegate_base
{
public:
iterator_delegate_base () { }
virtual ~iterator_delegate_base () { }
virtual void do_reset (const db::Box &region, 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<T> *clone () const = 0;
virtual bool equals (const iterator_delegate_base<T> *other) const = 0;
};
template <class Iter>
class DB_PUBLIC iterator_delegate2
: public iterator_delegate_base<typename Iter::value_type>
{
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<value_type> *clone () const
{
return new iterator_delegate2<Iter> (*this);
}
virtual bool equals (const iterator_delegate_base<value_type> *other) const
{
const iterator_delegate2<Iter> *o = dynamic_cast<const iterator_delegate2<Iter> *> (other);
return o && o->m_iter == m_iter;
}
private:
Iter m_iter, m_from, m_to;
};
template <class Iter>
class DB_PUBLIC iterator_delegate1
: public iterator_delegate_base<typename Iter::value_type>
{
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<value_type> *clone () const
{
return new iterator_delegate1<Iter> (*this);
}
virtual bool equals (const iterator_delegate_base<value_type> *other) const
{
const iterator_delegate1<Iter> *o = dynamic_cast<const iterator_delegate1<Iter> *> (other);
return o && o->m_iter == m_iter;
}
private:
Iter m_iter, m_from;
};
template <class T>
class DB_PUBLIC shapes_iterator_delegate
: public iterator_delegate_base<T>
{
public:
shapes_iterator_delegate (const db::Shapes *shapes)
: mp_shapes (shapes), m_iter (mp_shapes->begin (shape_flags<T> ()))
{
// .. nothing yet ..
}
virtual void do_reset (const db::Box &box, bool overlapping)
{
if (box == db::Box::world ()) {
m_iter = mp_shapes->begin (shape_flags<T> ());
} else {
if (mp_shapes->is_bbox_dirty ()) {
const_cast<db::Shapes *> (mp_shapes)->update ();
}
if (overlapping) {
m_iter = mp_shapes->begin_overlapping (box, shape_flags<T> ());
} else {
m_iter = mp_shapes->begin_touching (box, shape_flags<T> ());
}
}
}
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<T> *clone () const
{
return new shapes_iterator_delegate<T> (*this);
}
virtual db::Box bbox () const
{
if (mp_shapes->is_bbox_dirty ()) {
const_cast<db::Shapes *> (mp_shapes)->update ();
}
return mp_shapes->bbox ();
}
virtual bool equals (const iterator_delegate_base<T> *other) const
{
const shapes_iterator_delegate<T> *o = dynamic_cast<const shapes_iterator_delegate<T> *> (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 T>
class DB_PUBLIC shapes_iterator
{
public:
template <class Iter>
shapes_iterator (const Iter &from, const Iter &to)
: mp_delegate (new iterator_delegate2<Iter> (from, to))
{ }
template <class Iter>
shapes_iterator (const Iter &from)
: mp_delegate (new iterator_delegate1<Iter> (from))
{ }
shapes_iterator (const db::Shapes *shapes)
: mp_delegate (new shapes_iterator_delegate<T> (shapes))
{ }
shapes_iterator (const shapes_iterator<T> &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<T> &other) const
{
return mp_delegate->equals (other.mp_delegate);
}
template <class TO>
bool operator== (const shapes_iterator<TO> &) 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<T> *mp_delegate;
};
template <class TS, class TI, class TR>
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<TS, TI, TR> *op, db::Shapes *result_shapes) const;
void run_flat (const db::Shapes *subjects, const std::vector<const db::Shapes *> &intruders, const local_operation<TS, TI, TR> *op, const std::vector<db::Shapes *> &result_shapes) const;
void run_flat (const shapes_iterator<TS> &subjects, const std::vector<shapes_iterator<TI> > &intruders, const local_operation<TS, TI, TR> *op, const std::vector<db::Shapes *> &result_shapes) const;
void set_description (const std::string &d)
{