WIP: generalization of algorithms with local processor, first steps

This commit is contained in:
Matthias Koefferlein 2020-09-27 23:14:54 +02:00
parent 26028cdeb9
commit b464279dcf
13 changed files with 480 additions and 374 deletions

View File

@ -37,6 +37,8 @@
#include "dbClip.h"
#include "dbPolygonTools.h"
#include "dbHash.h"
#include "dbRegionLocalOperations.h"
#include "dbHierProcessor.h"
#include <sstream>
@ -394,7 +396,7 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
std::auto_ptr<FlatRegion> output (new FlatRegion (false));
region_to_edge_interaction_filter<ResultCountingInserter, db::Polygon> filter (inserter, false, counting /*get all in counting mode*/);
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
AddressablePolygonDelivery p (begin_merged ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
@ -449,7 +451,7 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse,
region_to_text_interaction_filter<ResultCountingInserter, db::Text> filter (inserter, false, counting /*get all in counting mode*/);
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
AddressablePolygonDelivery p (begin_merged ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
@ -485,9 +487,6 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
{
min_count = std::max (size_t (1), min_count);
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
// shortcut
if (empty ()) {
return clone ();
@ -502,6 +501,32 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
}
}
#if 1
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
db::RegionIterator polygons (begin_merged ());
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count);
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
proc.set_base_verbosity (base_verbosity ());
std::vector<generic_shape_iterator<db::Polygon> > others;
others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ());
std::auto_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
std::vector<db::Shapes *> results;
results.push_back (&output->raw_polygons ());
proc.run_flat (polygons, others, &op, results);
return output.release ();
#else
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
size_t nstart = 0;
if (min_count == size_t (1) && max_count == std::numeric_limits<size_t>::max ()) {
@ -582,6 +607,7 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
}
return output.release ();
#endif
}
EdgesDelegate *
@ -600,7 +626,7 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
std::auto_ptr<FlatEdges> output (new FlatEdges (false));
region_to_edge_interaction_filter<Shapes, db::Edge> filter (output->raw_edges (), false);
AddressablePolygonDelivery p (begin (), has_valid_polygons ());
AddressablePolygonDelivery p (begin ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
@ -633,7 +659,7 @@ AsIfFlatRegion::pull_generic (const Texts &other) const
std::auto_ptr<FlatTexts> output (new FlatTexts (false));
region_to_text_interaction_filter<Shapes, db::Text, db::Text> filter (output->raw_texts (), false);
AddressablePolygonDelivery p (begin (), has_valid_polygons ());
AddressablePolygonDelivery p (begin ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
@ -879,7 +905,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons,
db::box_scanner<db::Polygon, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (size () + (other ? other->size () : 0));
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
AddressablePolygonDelivery p (begin_merged ());
size_t n = 0;
for ( ; ! p.at_end (); ++p) {

View File

@ -74,6 +74,11 @@ public:
set ();
}
virtual bool is_addressable() const
{
return false;
}
virtual const value_type *get () const
{
return &m_polygon;

View File

@ -28,6 +28,7 @@
#include "dbShape.h"
#include "dbRecursiveShapeIterator.h"
#include "dbShapeCollection.h"
#include "dbGenericShapeIterator.h"
#include <list>
@ -146,60 +147,7 @@ private:
EdgePairsIteratorDelegate *mp_delegate;
};
/**
* @brief A helper class allowing delivery of addressable edges
*
* In some applications (i.e. box scanner), edges need to be taken
* by address. The edge set cannot always deliver adressable edges.
* This class help providing this ability by keeping a temporary copy
* if required.
*/
class DB_PUBLIC AddressableEdgePairDelivery
{
public:
AddressableEdgePairDelivery ()
: m_iter (), m_valid (false)
{
// .. nothing yet ..
}
AddressableEdgePairDelivery (const EdgePairsIterator &iter, bool valid)
: m_iter (iter), m_valid (valid)
{
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
}
bool at_end () const
{
return m_iter.at_end ();
}
AddressableEdgePairDelivery &operator++ ()
{
++m_iter;
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
return *this;
}
const db::EdgePair *operator-> () const
{
if (m_valid) {
return m_iter.operator-> ();
} else {
return &m_heap.back ();
}
}
private:
EdgePairsIterator m_iter;
bool m_valid;
std::list<db::EdgePair> m_heap;
};
typedef addressable_shape_delivery_gen<EdgePairsIterator> AddressableEdgePairDelivery;
class EdgePairs;

View File

@ -28,6 +28,7 @@
#include "dbRecursiveShapeIterator.h"
#include "dbCellVariants.h"
#include "dbShapeCollection.h"
#include "dbGenericShapeIterator.h"
#include <list>
@ -142,60 +143,7 @@ private:
EdgesIteratorDelegate *mp_delegate;
};
/**
* @brief A helper class allowing delivery of addressable edges
*
* In some applications (i.e. box scanner), edges need to be taken
* by address. The edge set cannot always deliver adressable edges.
* This class help providing this ability by keeping a temporary copy
* if required.
*/
class DB_PUBLIC AddressableEdgeDelivery
{
public:
AddressableEdgeDelivery ()
: m_iter (), m_valid (false)
{
// .. nothing yet ..
}
AddressableEdgeDelivery (const EdgesIterator &iter, bool valid)
: m_iter (iter), m_valid (valid)
{
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
}
bool at_end () const
{
return m_iter.at_end ();
}
AddressableEdgeDelivery &operator++ ()
{
++m_iter;
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
return *this;
}
const db::Edge *operator-> () const
{
if (m_valid) {
return m_iter.operator-> ();
} else {
return &m_heap.back ();
}
}
private:
EdgesIterator m_iter;
bool m_valid;
std::list<db::Edge> m_heap;
};
typedef addressable_shape_delivery_gen<EdgesIterator> AddressableEdgeDelivery;
class Edges;

View File

@ -26,6 +26,7 @@
#include "dbCommon.h"
#include "dbShapes.h"
#include "dbShapeFlags.h"
#include <type_traits>
namespace db
{
@ -41,6 +42,7 @@ public:
virtual void do_reset (const db::Box & /*region*/, bool /*overlapping*/) { }
virtual db::Box bbox () const { return db::Box::world (); }
virtual bool is_addressable () const = 0;
virtual bool at_end () const = 0;
virtual void increment () = 0;
virtual const T *get () const = 0;
@ -48,7 +50,7 @@ public:
virtual bool equals (const generic_shape_iterator_delegate_base<T> *other) const = 0;
};
template <class Iter>
template <class Iter, bool addressable = true>
class DB_PUBLIC generic_shape_iterator_delegate2
: public generic_shape_iterator_delegate_base<typename Iter::value_type>
{
@ -59,6 +61,11 @@ public:
: m_iter (from), m_from (from), m_to (to)
{ }
virtual bool is_addressable () const
{
return addressable;
}
virtual void do_reset (const db::Box &, bool)
{
m_iter = m_from;
@ -94,7 +101,7 @@ private:
Iter m_iter, m_from, m_to;
};
template <class Iter>
template <class Iter, bool addressable = true>
class DB_PUBLIC generic_shape_iterator_delegate1
: public generic_shape_iterator_delegate_base<typename Iter::value_type>
{
@ -105,6 +112,11 @@ public:
: m_iter (from), m_from (from)
{ }
virtual bool is_addressable () const
{
return addressable;
}
virtual void do_reset (const db::Box &, bool)
{
m_iter = m_from;
@ -148,7 +160,13 @@ public:
generic_shapes_iterator_delegate (const db::Shapes *shapes)
: mp_shapes (shapes), m_iter (mp_shapes->begin (shape_flags<T> ()))
{
// .. nothing yet ..
m_is_addressable = shape_flags<T> () == shape_flags_pure<T> () || mp_shapes->begin (shape_flags<T> () - shape_flags_pure<T> ()).at_end ();
set ();
}
virtual bool is_addressable () const
{
return m_is_addressable;
}
virtual void do_reset (const db::Box &box, bool overlapping)
@ -165,6 +183,8 @@ public:
m_iter = mp_shapes->begin_touching (box, shape_flags<T> ());
}
}
set ();
}
virtual bool at_end () const
@ -175,11 +195,16 @@ public:
virtual void increment ()
{
++m_iter;
set ();
}
virtual const T *get () const
{
return m_iter->basic_ptr (typename T::tag ());
if (m_is_addressable) {
return m_iter->basic_ptr (typename T::tag ());
} else {
return m_s2o.get (*m_iter);
}
}
generic_shape_iterator_delegate_base<T> *clone () const
@ -198,17 +223,26 @@ public:
virtual bool equals (const generic_shape_iterator_delegate_base<T> *other) const
{
const generic_shapes_iterator_delegate<T> *o = dynamic_cast<const generic_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 ()));
return o && o->mp_shapes == mp_shapes && o->m_iter.at_end () == m_iter.at_end () && (m_iter.at_end () || *o->m_iter == *m_iter);
}
private:
const db::Shapes *mp_shapes;
db::Shapes::shape_iterator m_iter;
db::shape_to_object<T> m_s2o;
bool m_is_addressable;
generic_shapes_iterator_delegate (const generic_shapes_iterator_delegate &other)
: mp_shapes (other.mp_shapes), m_iter (other.m_iter)
: mp_shapes (other.mp_shapes), m_iter (other.m_iter), m_is_addressable (other.m_is_addressable)
{
// .. nothing yet ..
set ();
}
void set ()
{
if (! m_is_addressable && ! m_iter.at_end ()) {
m_s2o.set (*m_iter);
}
}
};
@ -273,6 +307,11 @@ public:
return false;
}
bool is_addressable () const
{
return ! mp_delegate || mp_delegate->is_addressable ();
}
reference operator* () const
{
return *mp_delegate->get ();
@ -294,6 +333,14 @@ public:
return !mp_delegate || mp_delegate->at_end ();
}
generic_shape_iterator
confined (const db::Box &box, bool overlapping) const
{
generic_shape_iterator copy (*this);
copy.reset (box, overlapping);
return copy;
}
void reset ()
{
if (mp_delegate) {
@ -317,6 +364,105 @@ public:
generic_shape_iterator_delegate_base<T> *mp_delegate;
};
/**
* @brief A helper class allowing delivery of addressable edges
*
* In some applications (i.e. box scanner), shapes need to be taken
* by address. An iterator cannot always deliver adressable objects.
* This class help providing this ability by keeping a temporary copy
* if required.
*/
template <class Iter>
class DB_PUBLIC addressable_shape_delivery_impl
{
public:
typedef typename Iter::value_type value_type;
addressable_shape_delivery_impl ()
: m_iter (), m_iterator_is_addressable (false)
{
// .. nothing yet ..
}
addressable_shape_delivery_impl (const Iter &iter, bool iterator_is_addressable)
: m_iter (iter), m_iterator_is_addressable (iterator_is_addressable)
{
if (! m_iterator_is_addressable && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
}
bool at_end () const
{
return m_iter.at_end ();
}
void inc ()
{
++m_iter;
if (! m_iterator_is_addressable && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
}
const value_type *operator-> () const
{
if (m_iterator_is_addressable) {
return m_iter.operator-> ();
} else {
return &m_heap.back ();
}
}
private:
Iter m_iter;
bool m_iterator_is_addressable;
std::list<value_type> m_heap;
};
template <class Iter>
class DB_PUBLIC addressable_shape_delivery_gen
: public addressable_shape_delivery_impl<Iter>
{
public:
addressable_shape_delivery_gen ()
: addressable_shape_delivery_impl<Iter> ()
{ }
explicit addressable_shape_delivery_gen (const Iter &iter, bool iterator_is_addressable)
: addressable_shape_delivery_impl<Iter> (iter, iterator_is_addressable)
{ }
addressable_shape_delivery_gen &operator++ ()
{
addressable_shape_delivery_impl<Iter>::inc ();
return *this;
}
};
template <class T>
class DB_PUBLIC addressable_shape_delivery
: public addressable_shape_delivery_impl<db::generic_shape_iterator<T> >
{
public:
typedef db::generic_shape_iterator<T> iter_type;
addressable_shape_delivery ()
: addressable_shape_delivery_impl<iter_type> ()
{ }
explicit addressable_shape_delivery (const iter_type &iter)
: addressable_shape_delivery_impl<iter_type> (iter, iter.is_addressable ())
{ }
addressable_shape_delivery &operator++ ()
{
addressable_shape_delivery_impl<iter_type>::inc ();
return *this;
}
};
}
#endif

View File

@ -931,7 +931,7 @@ private:
};
template <class T>
struct addressable_shape_delivery
struct addressable_object_from_shape
{
const T *operator () (const db::Shape &shape)
{
@ -941,7 +941,7 @@ struct addressable_shape_delivery
};
template <>
struct addressable_shape_delivery<db::NetShape>
struct addressable_object_from_shape<db::NetShape>
{
const NetShape *operator () (const db::Shape &shape)
{
@ -1024,7 +1024,7 @@ local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity
db::box_scanner<T, std::pair<unsigned int, size_t> > bs (report_progress, desc);
db::box_convert<T> bc;
addressable_shape_delivery<T> heap;
addressable_object_from_shape<T> heap;
attr_accessor<T> attr;
db::ShapeIterator::flags_type shape_flags = get_shape_flags<T> () ();

View File

@ -158,6 +158,29 @@ public:
}
};
template <>
class shape_reference_translator<db::Polygon>
{
public:
typedef db::Polygon shape_type;
shape_reference_translator (db::Layout * /*target_layout*/)
{
// .. nothing yet ..
}
const shape_type &operator() (const shape_type &s) const
{
return s;
}
template <class Trans>
shape_type operator() (const shape_type &s, const Trans &tr) const
{
return s.transformed (tr);
}
};
template <class Ref, class Trans>
class shape_reference_translator_with_trans_from_shape_ref
{
@ -314,6 +337,7 @@ local_processor_cell_context<TS, TI, TR>::propagate (unsigned int output_layer,
}
}
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::EdgePair>;
@ -559,6 +583,7 @@ local_processor_cell_contexts<TS, TI, TR>::compute_results (const local_processo
}
}
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::EdgePair>;
@ -657,6 +682,7 @@ shape_interactions<TS, TI>::intruder_shape (unsigned int id) const
}
}
template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Edge>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::TextRef>;
@ -1011,6 +1037,7 @@ local_processor_context_computation_task<TS, TI, TR>::perform ()
mp_proc->compute_contexts (*mp_contexts, mp_parent_context, mp_subject_parent, mp_subject_cell, m_subject_cell_inst, mp_intruder_cell, m_intruders, m_dist);
}
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
@ -1058,6 +1085,7 @@ local_processor_result_computation_task<TS, TI, TR>::perform ()
}
}
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
@ -1614,6 +1642,8 @@ local_processor<TS, TI, TR>::compute_results (local_processor_contexts<TS, TI, T
}
}
namespace {
template <class TS, class TI>
struct scan_shape2shape_same_layer
{
@ -1636,13 +1666,6 @@ struct scan_shape2shape_same_layer
scanner.process (rec, dist, db::box_convert<TS> (), db::box_convert<TI> ());
}
void
operator () (const generic_shape_iterator<TS> &, unsigned int, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
{
// cannot have different types on the same layer
tl_assert (false);
}
};
template <class T>
@ -1667,20 +1690,6 @@ struct scan_shape2shape_same_layer<T, T>
scanner.process (rec, dist, db::box_convert<T> ());
}
void
operator () (const generic_shape_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 (generic_shape_iterator<T> i = subjects; !i.at_end (); ++i) {
scanner.insert (i.operator-> (), id++);
}
scanner.process (rec, dist, db::box_convert<T> ());
}
};
template <class TS, class TI>
@ -1714,46 +1723,10 @@ struct scan_shape2shape_different_layers
scanner.process (rec, dist, db::box_convert<TS> (), db::box_convert<TI> ());
}
void
operator () (db::Layout *layout, const generic_shape_iterator<TS> &subjects, const generic_shape_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;
generic_shape_iterator<TS> is = subjects;
is.reset (common_box, true);
for ( ; !is.at_end (); ++is) {
scanner.insert1 (is.operator-> (), id++);
}
generic_shape_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>
void
local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_contexts<TS, TI, TR> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI, TR> *op, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, std::vector<std::unordered_set<TR> > &result) const
@ -1893,45 +1866,142 @@ local_processor<TS, TI, TR>::run_flat (const db::Shapes *subject_shapes, const s
run_flat (generic_shape_iterator<TS> (subject_shapes), is, op, result_shapes);
}
namespace {
template <class TS, class TI>
struct scan_shape2shape_same_layer_flat
{
void
operator () (const generic_shape_iterator<TS> &, bool, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
{
// cannot have different types on the same layer
tl_assert (false);
}
};
template <class T>
struct scan_shape2shape_same_layer_flat<T, T>
{
void
operator () (const generic_shape_iterator<T> &subjects, bool needs_isolated_subjects, 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);
addressable_shape_delivery<T> is (subjects);
for ( ; !is.at_end (); ++is) {
unsigned int id = interactions.next_id ();
const T *shape = is.operator-> ();
scanner.insert (shape, id);
// create subject for subject vs. nothing interactions
if (needs_isolated_subjects) {
interactions.add_subject (id, *shape);
}
}
scanner.process (rec, dist, db::box_convert<T> ());
}
};
template <class TS, class TI>
struct scan_shape2shape_different_layers_flat
{
void
operator () (const generic_shape_iterator<TS> &subjects, const generic_shape_iterator<TI> &intruders, bool needs_isolated_subjects, 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 (0 /*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 ()) {
if (needs_isolated_subjects) {
for (generic_shape_iterator<TS> is = subjects; ! is.at_end (); ++is) {
// create subject for subject vs. nothing interactions
interactions.add_subject (interactions.next_id (), *is);
}
}
return;
}
addressable_shape_delivery<TS> is;
if (needs_isolated_subjects) {
box_convert<TS> bcs;
is = addressable_shape_delivery<TS> (subjects);
for ( ; !is.at_end (); ++is) {
unsigned int id = interactions.next_id ();
const TS *shape = is.operator-> ();
if (bcs (*shape).overlaps (common_box)) {
scanner.insert1 (shape, id);
}
// create subject for subject vs. nothing interactions
interactions.add_subject (id, *shape);
}
} else {
is = addressable_shape_delivery<TS> (subjects.confined (common_box, true));
for ( ; !is.at_end (); ++is) {
scanner.insert1 (is.operator-> (), interactions.next_id ());
}
}
addressable_shape_delivery<TI> ii (intruders.confined (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>
void
local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subjects, const std::vector<generic_shape_iterator<TI> > &intruders, const local_operation<TS, TI, TR> *op, const std::vector<db::Shapes *> &result_shapes) const
{
if (subjects.at_end ()) {
return;
}
tl_assert (mp_subject_top == 0);
tl_assert (mp_intruder_top == 0);
shape_interactions<TS, TI> interactions;
bool needs_isolated_subjects = (op->on_empty_intruder_hint () != local_operation<TS, TI, TR>::Drop);
for (typename std::vector<generic_shape_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 (generic_shape_iterator<TS> i = subjects; !i.at_end (); ++i) {
unsigned int id = interactions.next_id ();
if (subject_id0 == 0) {
subject_id0 = id;
}
if (op->on_empty_intruder_hint () != local_operation<TS, TI, TR>::Drop) {
interactions.add_subject (id, *i);
}
if (*il == subjects) {
scan_shape2shape_same_layer_flat<TS, TI> () (subjects, needs_isolated_subjects, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
} else {
scan_shape2shape_different_layers_flat<TS, TI> () (subjects, *il, needs_isolated_subjects, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
}
static std::set<TI> empty_intruders;
if (! subjects.at_end ()) {
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*/, subjects, *il, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
}
}
}
if (interactions.begin () != interactions.end ()) {
@ -1959,6 +2029,7 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
}
}
template class DB_PUBLIC local_processor<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::Edge>;

View File

@ -50,6 +50,11 @@ namespace
set ();
}
virtual bool is_addressable() const
{
return false;
}
virtual bool at_end () const
{
return m_rec_iter.at_end ();

View File

@ -30,6 +30,7 @@
#include "dbPolygonGenerators.h"
#include "dbCellVariants.h"
#include "dbShapeCollection.h"
#include "dbGenericShapeIterator.h"
#include <list>
@ -97,60 +98,7 @@ public:
}
};
/**
* @brief A helper class allowing delivery of addressable polygons
*
* In some applications (i.e. box scanner), polygons need to be taken
* by address. The region cannot always deliver adressable polygons.
* This class help providing this ability by keeping a temporary copy
* if required.
*/
class DB_PUBLIC AddressablePolygonDelivery
{
public:
AddressablePolygonDelivery ()
: m_iter (), m_valid (false)
{
// .. nothing yet ..
}
AddressablePolygonDelivery (const RegionIterator &iter, bool valid)
: m_iter (iter), m_valid (valid)
{
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
}
bool at_end () const
{
return m_iter.at_end ();
}
AddressablePolygonDelivery &operator++ ()
{
++m_iter;
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
return *this;
}
const db::Polygon *operator-> () const
{
if (m_valid) {
return m_iter.operator-> ();
} else {
return &m_heap.back ();
}
}
private:
RegionIterator m_iter;
bool m_valid;
std::list<db::Polygon> m_heap;
};
typedef addressable_shape_delivery<db::Polygon> AddressablePolygonDelivery;
/**
* @brief A region
@ -1546,7 +1494,7 @@ public:
*/
AddressablePolygonDelivery addressable_polygons () const
{
return AddressablePolygonDelivery (begin (), has_valid_polygons ());
return AddressablePolygonDelivery (begin ());
}
/**
@ -1565,7 +1513,7 @@ public:
*/
AddressablePolygonDelivery addressable_merged_polygons () const
{
return AddressablePolygonDelivery (begin_merged (), has_valid_merged_polygons ());
return AddressablePolygonDelivery (begin_merged ());
}
/**

View File

@ -208,27 +208,30 @@ CheckLocalOperation::description () const
// ---------------------------------------------------------------------------------------------------------------
InteractingLocalOperation::InteractingLocalOperation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
template <class TS, class TI, class TR>
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
{
// .. nothing yet ..
}
db::Coord InteractingLocalOperation::dist () const
template <class TS, class TI, class TR>
db::Coord interacting_local_operation<TS, TI, TR>::dist () const
{
return m_touching ? 1 : 0;
}
void InteractingLocalOperation::compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
template <class TS, class TI, class TR>
void interacting_local_operation<TS, TI, TR>::compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
tl_assert (results.size () == 1);
std::unordered_set<db::PolygonRef> &result = results.front ();
std::unordered_set<TR> &result = results.front ();
db::EdgeProcessor ep;
std::set<db::PolygonRef> others;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
std::set<TI> others;
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (typename shape_interactions<TS, TI>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
@ -237,8 +240,8 @@ void InteractingLocalOperation::compute_local (db::Layout * /*layout*/, const sh
if (m_min_count == size_t (1) && m_max_count == std::numeric_limits<size_t>::max ()) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (typename TI::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, nstart);
}
}
@ -248,8 +251,8 @@ void InteractingLocalOperation::compute_local (db::Layout * /*layout*/, const sh
tl_assert (m_mode == 0);
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (typename TI::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, nstart);
}
nstart++;
@ -258,9 +261,9 @@ void InteractingLocalOperation::compute_local (db::Layout * /*layout*/, const sh
}
size_t n = nstart;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
const db::PolygonRef &subject = interactions.subject_shape (i->first);
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
const TS &subject = interactions.subject_shape (i->first);
for (typename TS::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, n);
}
}
@ -279,34 +282,40 @@ void InteractingLocalOperation::compute_local (db::Layout * /*layout*/, const sh
}
n = nstart;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
size_t count = 0;
std::map <size_t, size_t>::const_iterator c = interaction_counts.find (n);
if (c != interaction_counts.end ()) {
count = c->second;
}
if ((count >= m_min_count && count <= m_max_count) != m_inverse) {
const db::PolygonRef &subject = interactions.subject_shape (i->first);
const TS &subject = interactions.subject_shape (i->first);
result.insert (subject);
}
}
}
InteractingLocalOperation::on_empty_intruder_mode
InteractingLocalOperation::on_empty_intruder_hint () const
template <class TS, class TI, class TR>
typename local_operation<TS, TI, TR>::on_empty_intruder_mode
interacting_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
{
if ((m_mode <= 0) != m_inverse) {
return Drop;
return local_operation<TS, TI, TR>::Drop;
} else {
return Copy;
return local_operation<TS, TI, TR>::Copy;
}
}
std::string InteractingLocalOperation::description () const
template <class TS, class TI, class TR>
std::string interacting_local_operation<TS, TI, TR>::description () const
{
return tl::to_string (tr ("Select regions by their geometric relation (interacting, inside, outside ..)"));
}
// explicit instantiations
template class interacting_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class interacting_local_operation<db::Polygon, db::Polygon, db::Polygon>;
// ---------------------------------------------------------------------------------------------------------------
PullLocalOperation::PullLocalOperation (int mode, bool touching)

View File

@ -50,15 +50,16 @@ private:
bool m_shielded;
};
class InteractingLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
template <class TS, class TI, class TR>
class interacting_local_operation
: public local_operation<TS, TI, TR>
{
public:
InteractingLocalOperation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count);
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count);
virtual db::Coord dist () const;
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
virtual typename local_operation<TS, TI, TR>::on_empty_intruder_mode on_empty_intruder_hint () const;
virtual std::string description () const;
private:
@ -68,6 +69,8 @@ private:
size_t m_min_count, m_max_count;
};
typedef interacting_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> InteractingLocalOperation;
class PullLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
{

View File

@ -31,48 +31,97 @@ namespace db
{
template <class T> unsigned int shape_flags ();
template <class T> unsigned int shape_flags_pure ();
template <> inline unsigned int shape_flags<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags_pure<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags_pure<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags<db::Box> () { return db::ShapeIterator::Boxes; }
template <> inline unsigned int shape_flags_pure<db::Box> () { return 1 << db::ShapeIterator::Box; }
template <> inline unsigned int shape_flags<db::Path> () { return db::ShapeIterator::Paths; }
template <> inline unsigned int shape_flags_pure<db::Path> () { return 1 << db::ShapeIterator::Path; }
template <> inline unsigned int shape_flags<db::Polygon> () { return db::ShapeIterator::Polygons; }
template <> inline unsigned int shape_flags_pure<db::Polygon> () { return 1 << db::ShapeIterator::Polygon; }
template <> inline unsigned int shape_flags<db::Edge> () { return db::ShapeIterator::Edges; }
template <> inline unsigned int shape_flags_pure<db::Edge> () { return 1 << db::ShapeIterator::Edge; }
template <> inline unsigned int shape_flags<db::Text> () { return db::ShapeIterator::Texts; }
template <> inline unsigned int shape_flags_pure<db::Text> () { return 1 << db::ShapeIterator::Text; }
template <class T>
struct DB_PUBLIC shape_to_object
{
void set (const db::Shape &) { }
const T *get (const db::Shape &s) const { return s.basic_ptr (typename T::tag ()); }
};
template <>
inline unsigned int shape_flags<db::PolygonRef> ()
struct DB_PUBLIC shape_to_object<db::Polygon>
{
return 1 << db::ShapeIterator::PolygonRef;
}
typedef db::Polygon value_type;
void set (const db::Shape &s) { s.polygon (m_shape); }
const value_type *get (const db::Shape &) const { return &m_shape; }
private:
value_type m_shape;
};
template <>
inline unsigned int shape_flags<db::Box> ()
struct DB_PUBLIC shape_to_object<db::SimplePolygon>
{
return 1 << db::ShapeIterator::Box;
}
typedef db::SimplePolygon value_type;
void set (const db::Shape &s) { s.simple_polygon (m_shape); }
const value_type *get (const db::Shape &) const { return &m_shape; }
private:
value_type m_shape;
};
template <>
inline unsigned int shape_flags<db::Path> ()
struct DB_PUBLIC shape_to_object<db::Path>
{
return 1 << db::ShapeIterator::Path;
}
typedef db::Path value_type;
void set (const db::Shape &s) { s.path (m_shape); }
const value_type *get (const db::Shape &) const { return &m_shape; }
private:
value_type m_shape;
};
template <>
inline unsigned int shape_flags<db::Polygon> ()
struct DB_PUBLIC shape_to_object<db::Text>
{
return 1 << db::ShapeIterator::Polygon;
}
typedef db::Text value_type;
void set (const db::Shape &s) { s.text (m_shape); }
const value_type *get (const db::Shape &) const { return &m_shape; }
private:
value_type m_shape;
};
template <>
inline unsigned int shape_flags<db::Edge> ()
struct DB_PUBLIC shape_to_object<db::Box>
{
return 1 << db::ShapeIterator::Edge;
}
typedef db::Box value_type;
template <>
inline unsigned int shape_flags<db::Text> ()
{
return 1 << db::ShapeIterator::Text;
}
void set (const db::Shape *s) { s->box (m_shape); }
const value_type *get (const db::Shape *) const { return &m_shape; }
template <>
inline unsigned int shape_flags<db::TextRef> ()
{
return 1 << db::ShapeIterator::TextRef;
}
private:
value_type m_shape;
};
}

View File

@ -28,6 +28,7 @@
#include "dbShape.h"
#include "dbRecursiveShapeIterator.h"
#include "dbShapeCollection.h"
#include "dbGenericShapeIterator.h"
#include <list>
@ -146,60 +147,7 @@ private:
TextsIteratorDelegate *mp_delegate;
};
/**
* @brief A helper class allowing delivery of addressable texts
*
* In some applications (i.e. box scanner), texts need to be taken
* by address. The text set cannot always deliver adressable edges.
* This class help providing this ability by keeping a temporary copy
* if required.
*/
class DB_PUBLIC AddressableTextDelivery
{
public:
AddressableTextDelivery ()
: m_iter (), m_valid (false)
{
// .. nothing yet ..
}
AddressableTextDelivery (const TextsIterator &iter, bool valid)
: m_iter (iter), m_valid (valid)
{
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
}
bool at_end () const
{
return m_iter.at_end ();
}
AddressableTextDelivery &operator++ ()
{
++m_iter;
if (! m_valid && ! m_iter.at_end ()) {
m_heap.push_back (*m_iter);
}
return *this;
}
const db::Text *operator-> () const
{
if (m_valid) {
return m_iter.operator-> ();
} else {
return &m_heap.back ();
}
}
private:
TextsIterator m_iter;
bool m_valid;
std::list<db::Text> m_heap;
};
typedef addressable_shape_delivery_gen<TextsIterator> AddressableTextDelivery;
class Texts;