mirror of https://github.com/KLayout/klayout.git
WIP: generalization of algorithms with local processor, first steps
This commit is contained in:
parent
26028cdeb9
commit
b464279dcf
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ public:
|
|||
set ();
|
||||
}
|
||||
|
||||
virtual bool is_addressable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual const value_type *get () const
|
||||
{
|
||||
return &m_polygon;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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> () ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ namespace
|
|||
set ();
|
||||
}
|
||||
|
||||
virtual bool is_addressable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool at_end () const
|
||||
{
|
||||
return m_rec_iter.at_end ();
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue