diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 91ae32572..7670204ed 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -20,6 +20,7 @@ SOURCES = \ dbClipboardData.cc \ dbClip.cc \ dbCommonReader.cc \ + dbCompoundOperation.cc \ dbEdge.cc \ dbEdgePair.cc \ dbEdgePairRelations.cc \ @@ -217,6 +218,7 @@ HEADERS = \ dbClipboard.h \ dbClip.h \ dbCommonReader.h \ + dbCompoundOperation.h \ dbEdge.h \ dbEdgePair.h \ dbEdgePairRelations.h \ diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc new file mode 100644 index 000000000..81e3a6ad7 --- /dev/null +++ b/src/db/db/dbCompoundOperation.cc @@ -0,0 +1,915 @@ + +#include "dbCompoundOperation.h" +#include "dbRegion.h" + +/*@@@@ + +TODO: + +* Transform variants? +* "result is merged"? +* "requires raw input"? +* Make nodes shared pointers/GSI objects for better compatibility with GSI, at least "keep" them. + +* Edge generation nodes +* Boolean and interaction nodes (interact, bool with edge, bool with polygon ...) + +* Interactions with shapes over some distance for neighborhood analysis + +* Sized subject shapes as inputs for other operations? how to compute distance then? + +*/ + +namespace db +{ + +// --------------------------------------------------------------------------------------------- + +CompoundRegionOperationPrimaryNode::CompoundRegionOperationPrimaryNode () +{ + // .. nothing yet .. +} + +std::vector CompoundRegionOperationPrimaryNode::inputs () const +{ + return std::vector (); +} + +void CompoundRegionOperationPrimaryNode::do_compute_local (db::Layout *, const shape_interactions &interactions, std::vector > &results, size_t, double) const +{ + for (shape_interactions::subject_iterator i = interactions.begin_subjects (); i != interactions.begin_subjects (); ++i) { + results.front ().insert (i->second); + } +} + +void CompoundRegionOperationPrimaryNode::do_compute_local (db::Layout *, const shape_interactions &interactions, std::vector > &results, size_t, double) const +{ + for (shape_interactions::subject_iterator i = interactions.begin_subjects (); i != interactions.begin_subjects (); ++i) { + results.front ().insert (i->second); + } +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionOperationSecondaryNode::CompoundRegionOperationSecondaryNode (db::Region *input) + : mp_input (input) +{ + // .. nothing yet .. +} + +std::vector CompoundRegionOperationSecondaryNode::inputs () const +{ + std::vector iv; + iv.push_back (mp_input); + return iv; +} + +void CompoundRegionOperationSecondaryNode::do_compute_local (db::Layout *, const shape_interactions &interactions, std::vector > &results, size_t, double) const +{ + for (shape_interactions::intruder_iterator i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) { + results.front ().insert (i->second.second); + } +} + +void CompoundRegionOperationSecondaryNode::do_compute_local (db::Layout *, const shape_interactions &interactions, std::vector > &results, size_t, double) const +{ + for (shape_interactions::intruder_iterator i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) { + results.front ().insert (i->second.second); + } +} + +// --------------------------------------------------------------------------------------------- + +CompoundTransformationReducer::CompoundTransformationReducer () +{ + // .. nothing yet .. +} + +void +CompoundTransformationReducer::add (const db::TransformationReducer *reducer) +{ + if (reducer) { + m_vars.push_back (reducer); + } +} + +db::Trans +CompoundTransformationReducer::reduce_trans (const db::Trans &trans) const +{ + db::Trans t = trans; + for (std::vector::const_iterator v = m_vars.begin (); v != m_vars.end (); ++v) { + (*v)->reduce_trans (t); + } + return t; +} + +db::ICplxTrans +CompoundTransformationReducer::reduce_trans (const db::ICplxTrans &trans) const +{ + db::ICplxTrans t = trans; + for (std::vector::const_iterator v = m_vars.begin (); v != m_vars.end (); ++v) { + (*v)->reduce_trans (t); + } + return t; +} + +db::Trans +CompoundTransformationReducer::reduce (const db::Trans &trans) const +{ + db::Trans t = trans; + for (std::vector::const_iterator v = m_vars.begin (); v != m_vars.end (); ++v) { + (*v)->reduce (t); + } + return t; +} + +db::ICplxTrans +CompoundTransformationReducer::reduce (const db::ICplxTrans &trans) const +{ + db::ICplxTrans t = trans; + for (std::vector::const_iterator v = m_vars.begin (); v != m_vars.end (); ++v) { + (*v)->reduce (t); + } + return t; +} + +bool +CompoundTransformationReducer::is_translation_invariant () const +{ + for (std::vector::const_iterator v = m_vars.begin (); v != m_vars.end (); ++v) { + if (! (*v)->is_translation_invariant ()) { + return false; + } + } + return true; +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode (const std::vector &children) +{ + for (std::vector::const_iterator c = children.begin (); c != children.end (); ++c) { + m_children.push_back (*c); + } + init (); +} + +CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *child) +{ + m_children.push_back (child); + init (); +} + +CompoundRegionMultiInputOperationNode::CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b) +{ + m_children.push_back (a); + m_children.push_back (b); + init (); +} + +void +CompoundRegionMultiInputOperationNode::init () +{ + std::map input_index; + + for (tl::shared_collection::iterator i = m_children.begin (); i != m_children.end (); ++i) { + + std::vector child_inputs = i->inputs (); + unsigned int child_index = 0; + for (std::vector::const_iterator ii = child_inputs.begin (); ii != child_inputs.end (); ++ii, ++child_index) { + + std::map::const_iterator im = input_index.find (*ii); + unsigned int li = (unsigned int) m_inputs.size (); + if (im != input_index.end ()) { + li = im->second; + } else { + m_inputs.push_back (*ii); + input_index.insert (std::make_pair (*ii, li)); + } + + m_map_layer_to_child [std::make_pair (child_index, (unsigned int) (ii - child_inputs.begin ()))] = li; + + } + + } + + // build the reducer + for (tl::shared_collection::iterator i = m_children.begin (); i != m_children.end (); ++i) { + m_vars.add (i->vars ()); + } +} + +CompoundRegionMultiInputOperationNode::~CompoundRegionMultiInputOperationNode () +{ + for (tl::shared_collection::iterator i = m_children.begin (); i != m_children.end (); ++i) { + delete i.operator-> (); + } + m_children.clear (); +} + +void +CompoundRegionMultiInputOperationNode::invalidate_cache () const +{ + for (tl::shared_collection::const_iterator i = m_children.begin (); i != m_children.end (); ++i) { + i->invalidate_cache (); + } +} + +db::Coord +CompoundRegionMultiInputOperationNode::dist () const +{ + db::Coord d = 0; + for (tl::shared_collection::const_iterator i = m_children.begin (); i != m_children.end (); ++i) { + d = std::max (d, i->dist ()); + } + return d; +} + +std::string +CompoundRegionMultiInputOperationNode::description () const +{ + std::string r = "("; + for (tl::shared_collection::const_iterator i = m_children.begin (); i != m_children.end (); ++i) { + if (i != m_children.begin ()) { + r += ","; + } + r += i->description (); + } + return r; +} + +CompoundRegionOperationNode * +CompoundRegionMultiInputOperationNode::child (unsigned int index) +{ + tl::shared_collection::iterator c = m_children.begin (); + while (c != m_children.end () && index > 0) { + ++c; + --index; + } + return c == m_children.end () ? 0 : c.operator-> (); +} + +const CompoundRegionOperationNode * +CompoundRegionMultiInputOperationNode::child (unsigned int index) const +{ + return const_cast (this)->child (index); +} + +const TransformationReducer * +CompoundRegionMultiInputOperationNode::vars () const +{ + return (m_vars.is_empty () ? &m_vars : 0); +} + +bool +CompoundRegionMultiInputOperationNode::wants_variants () const +{ + for (tl::shared_collection::const_iterator i = m_children.begin (); i != m_children.end (); ++i) { + if (i->wants_variants ()) { + return true; + } + } + return false; +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionLogicalBoolOperationNode::CompoundRegionLogicalBoolOperationNode (LogicalOp op, bool invert, const std::vector &inputs) + : CompoundRegionMultiInputOperationNode (inputs), m_op (op), m_invert (invert) +{ + // .. nothing yet .. +} + +std::string CompoundRegionLogicalBoolOperationNode::description () const +{ + std::string r; + if (m_invert) { + r = "!"; + } + if (m_op == And) { + r += "and"; + } else if (m_op == Or) { + r += "or"; + } + return r + CompoundRegionMultiInputOperationNode::description (); +} + +template +void CompoundRegionLogicalBoolOperationNode::implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + bool ok = (m_op == And ? true : false); + + const T &subject_shape = interactions.subject_shape (interactions.begin ()->first); + + for (unsigned int ci = 0; ci < children (); ++ci) { + + shape_interactions child_interactions_computed; + const shape_interactions &child_interactions = interactions_for_child (interactions, ci, child_interactions_computed); + + const CompoundRegionOperationNode *node = child (ci); + + bool any = node->compute_local_bool (layout, child_interactions, max_vertex_count, area_ratio); + + if (m_op == And) { + if (! any) { + ok = false; + break; + } + } else if (m_op == Or) { + if (any) { + ok = true; + break; + } + } + + } + + if (ok) { + tl_assert (! results.empty ()); + results.front ().insert (subject_shape); + } +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionGeometricalBoolOperationNode::CompoundRegionGeometricalBoolOperationNode (GeometricalOp op, CompoundRegionOperationNode *a, CompoundRegionOperationNode *b) + : CompoundRegionMultiInputOperationNode (a, b), m_op (op) +{ + // .. nothing yet .. +} + +std::string +CompoundRegionGeometricalBoolOperationNode::description () const +{ + std::string r; + if (m_op == And) { + r = "and"; + } else if (m_op == Or) { + r = "or"; + } else if (m_op == Xor) { + r = "xor"; + } else if (m_op == Not) { + r = "not"; + } + r += CompoundRegionMultiInputOperationNode::description (); + return r; +} + +CompoundRegionGeometricalBoolOperationNode::ResultType +CompoundRegionGeometricalBoolOperationNode::result_type () const +{ + ResultType res_a = child (0)->result_type (); + ResultType res_b = child (1)->result_type (); + + if (res_a == Region && res_b == Edges && m_op == And) { + return Edges; + } else { + return res_a; + } +} + +template +static +void run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp, db::Layout *, const std::unordered_set &, const std::unordered_set &, const std::unordered_set &) +{ + tl_assert (false); +} + +static void +init_region (db::Region &r, const std::unordered_set &p) +{ + for (std::unordered_set::const_iterator i = p.begin (); i != p.end (); ++i) { + r.insert (i->obj ().transformed (i->trans ())); + } +} + +static void +init_region (db::Region &r, const std::unordered_set &p) +{ + for (std::unordered_set::const_iterator i = p.begin (); i != p.end (); ++i) { + r.insert (*i); + } +} + +static void +init_edges (db::Edges &ee, const std::unordered_set &e) +{ + for (std::unordered_set::const_iterator i = e.begin (); i != e.end (); ++i) { + ee.insert (*i); + } +} + +static void +write_result (db::Layout *layout, std::unordered_set &results, const db::Region &r) +{ + for (db::Region::const_iterator p = r.begin (); ! p.at_end (); ++p) { + results.insert (db::PolygonRef (*p, layout->shape_repository ())); + } +} + +static void +write_result (db::Layout *, std::unordered_set &results, const db::Region &r) +{ + for (db::Region::const_iterator p = r.begin (); ! p.at_end (); ++p) { + results.insert (*p); + } +} + +static void +write_result (db::Layout *, std::unordered_set &results, const db::Edges &e) +{ + for (db::Edges::const_iterator i = e.begin (); ! i.at_end (); ++i) { + results.insert (*i); + } +} + +template +static void +run_poly_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + // TODO: it's more efficient to feed the EP directly for polygon-to-polygon bools + db::Region ra, rb; + init_region (ra, a); + init_region (rb, b); + + if (op == CompoundRegionGeometricalBoolOperationNode::And) { + write_result (layout, res, ra & rb); + } else if (op == CompoundRegionGeometricalBoolOperationNode::Or) { + write_result (layout, res, ra + rb); + } else if (op == CompoundRegionGeometricalBoolOperationNode::Xor) { + write_result (layout, res, ra ^ rb); + } else if (op == CompoundRegionGeometricalBoolOperationNode::Not) { + write_result (layout, res, ra - rb); + } +} + +static void +run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + run_poly_bool (op, layout, a, b, res); +} + +static void +run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + run_poly_bool (op, layout, a, b, res); +} + +template +static void +run_poly_vs_edge_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + if (op != CompoundRegionGeometricalBoolOperationNode::And) { + return; + } + + // TODO: it's more efficient to feed the EP directly for polygon-to-polygon bools + db::Region ra; + init_region (ra, a); + + db::Edges eb; + init_edges (eb, b); + + write_result (layout, res, eb & ra); +} + +static void +run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + run_poly_vs_edge_bool (op, layout, a, b, res); +} + +static void +run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + run_poly_vs_edge_bool (op, layout, a, b, res); +} + +template +static void +run_edge_vs_poly_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + if (op != CompoundRegionGeometricalBoolOperationNode::And) { + return; + } + + // TODO: it's more efficient to feed the EP directly for polygon-to-polygon bools + db::Region rb; + init_region (rb, b); + + db::Edges ea; + init_edges (ea, a); + + if (op != CompoundRegionGeometricalBoolOperationNode::And) { + write_result (layout, res, ea & rb); + } else if (op != CompoundRegionGeometricalBoolOperationNode::Not) { + write_result (layout, res, ea - rb); + } +} + +static void +run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + run_edge_vs_poly_bool (op, layout, a, b, res); +} + +static void +run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + run_edge_vs_poly_bool (op, layout, a, b, res); +} + +static void +run_bool (CompoundRegionGeometricalBoolOperationNode::GeometricalOp op, db::Layout *layout, const std::unordered_set &a, const std::unordered_set &b, std::unordered_set &res) +{ + db::Edges ea, eb; + init_edges (ea, a); + init_edges (eb, b); + + if (op == CompoundRegionGeometricalBoolOperationNode::And) { + write_result (layout, res, ea & eb); + } else if (op == CompoundRegionGeometricalBoolOperationNode::Or) { + write_result (layout, res, ea + eb); + } else if (op == CompoundRegionGeometricalBoolOperationNode::Xor) { + write_result (layout, res, ea ^ eb); + } else if (op == CompoundRegionGeometricalBoolOperationNode::Not) { + write_result (layout, res, ea - eb); + } +} + + +template +void +CompoundRegionGeometricalBoolOperationNode::implement_bool (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + std::vector > one_a; + one_a.push_back (std::unordered_set ()); + + shape_interactions computed_a; + child (0)->compute_local (layout, interactions_for_child (interactions, 0, computed_a), one_a, max_vertex_count, area_ratio); + + std::vector > one_b; + one_b.push_back (std::unordered_set ()); + + shape_interactions computed_b; + child (1)->compute_local (layout, interactions_for_child (interactions, 1, computed_b), one_b, max_vertex_count, area_ratio); + + run_bool (m_op, layout, one_a.front (), one_b.front (), results.front ()); +} + +template +void +CompoundRegionGeometricalBoolOperationNode::implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + ResultType res_a = child (0)->result_type (); + ResultType res_b = child (1)->result_type (); + + if (res_a == Region && res_b == Region) { + implement_bool (layout, interactions, results, max_vertex_count, area_ratio); + } else if (res_a == Region && res_b == Edges) { + implement_bool (layout, interactions, results, max_vertex_count, area_ratio); + } else if (res_a == Edges && res_b == Region) { + implement_bool (layout, interactions, results, max_vertex_count, area_ratio); + } else if (res_a == Edges && res_b == Edges) { + implement_bool (layout, interactions, results, max_vertex_count, area_ratio); + } +} + +void +CompoundRegionGeometricalBoolOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionGeometricalBoolOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionGeometricalBoolOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionGeometricalBoolOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + + + +#if 0 // @@@ +// --------------------------------------------------------------------------------------------- + +class DB_PUBLIC CompoundRegionInteractOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum GeometricalOp { And, Not, Or, Xor }; + + CompoundRegionInteractOperationNode (GeometricalOp op, const CompoundRegionOperationNode *a, const CompoundRegionOperationNode *b, size_t min_count = 0, size_t max_count = std::numeric_limits::max ()); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + GeometricalOp m_op; +}; + +// --------------------------------------------------------------------------------------------- + +class DB_PUBLIC CompoundRegionPullOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum GeometricalOp { And, Not, Or, Xor }; + + CompoundRegionPullOperationNode (GeometricalOp op, const CompoundRegionOperationNode *a, const CompoundRegionOperationNode *b); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + GeometricalOp m_op; +}; + +// --------------------------------------------------------------------------------------------- + +class DB_PUBLIC CompoundRegionSizeOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum GeometricalOp { And, Not, Or, Xor }; + + CompoundRegionSizeOperationNode (GeometricalOp op, const CompoundRegionOperationNode *input, db::Coord size_x, db::Coord size_y); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + virtual db::Coord dist () const; + virtual const TransformationReducer *vars () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + GeometricalOp m_op; + CompoundTransformationReducer m_vars; +}; + +class DB_PUBLIC CompoundRegionMergeOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionMergeOperationNode (const CompoundRegionOperationNode *input, size_t min_wrap_count = 1); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; +}; +#endif + +// --------------------------------------------------------------------------------------------- + +CompoundRegionLogicalCaseSelectOperationNode::CompoundRegionLogicalCaseSelectOperationNode (bool multi_layer, const std::vector &inputs) + : CompoundRegionMultiInputOperationNode (inputs), m_multi_layer (multi_layer) +{ + // .. nothing yet .. +} + +std::string CompoundRegionLogicalCaseSelectOperationNode::description () const +{ + // TODO: could be nicer ... + std::string r; + r = "if-then"; + return r + CompoundRegionMultiInputOperationNode::description (); +} + +template +void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + bool ok = false; + + for (unsigned int ci = 0; ci < children (); ++ci) { + + if (! ok && ci % 2 == 1) { + // skip false branches + continue; + } + + shape_interactions computed; + const shape_interactions &child_interactions = interactions_for_child (interactions, ci, computed); + + const CompoundRegionOperationNode *node = child (ci); + + if (ci % 2 == 0) { + + ok = node->compute_local_bool (layout, child_interactions, max_vertex_count, area_ratio); + + } else { + + if (m_multi_layer && results.size () > size_t (ci / 2)) { + + std::vector > one; + one.push_back (std::unordered_set ()); + node->compute_local (layout, child_interactions, one, max_vertex_count, area_ratio); + results[ci / 2].swap (one.front ()); + + } else { + + node->compute_local (layout, child_interactions, results, max_vertex_count, area_ratio); + + } + + break; + + } + + } + +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionFilterOperationNode::CompoundRegionFilterOperationNode (PolygonFilterBase *filter, CompoundRegionOperationNode *input) + : CompoundRegionMultiInputOperationNode (input), mp_filter (filter) +{ } + +std::string +CompoundRegionFilterOperationNode::description () const +{ + // TODO: some description? + return "filter"; +} + +void +CompoundRegionFilterOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionFilterOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +bool +CompoundRegionFilterOperationNode::is_selected (const db::Polygon &p) const +{ + return mp_filter->selected (p); +} + +bool +CompoundRegionFilterOperationNode::is_selected (const db::PolygonRef &p) const +{ + return mp_filter->selected (p.obj ().transformed (p.trans ())); +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionProcessingOperationNode::CompoundRegionProcessingOperationNode (PolygonProcessorBase *proc, CompoundRegionOperationNode *input) + : CompoundRegionMultiInputOperationNode (input), mp_proc (proc) +{ } + +std::string +CompoundRegionProcessingOperationNode::description () const +{ + // TODO: some description? + return "processor"; +} + +void +CompoundRegionProcessingOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionProcessingOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionProcessingOperationNode::processed (db::Layout *, const db::Polygon &p, std::vector &res) const +{ + return mp_proc->process (p, res); +} + +void +CompoundRegionProcessingOperationNode::processed (db::Layout *layout, const db::PolygonRef &p, std::vector &res) const +{ + std::vector poly; + mp_proc->process (p.obj ().transformed (p.trans ()), poly); + for (std::vector::const_iterator p = poly.begin (); p != poly.end (); ++p) { + res.push_back (db::PolygonRef (*p, layout->shape_repository ())); + } +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionToEdgeProcessingOperationNode::CompoundRegionToEdgeProcessingOperationNode (PolygonToEdgeProcessorBase *proc, CompoundRegionOperationNode *input) + : CompoundRegionMultiInputOperationNode (input), mp_proc (proc) +{ } + +std::string +CompoundRegionToEdgeProcessingOperationNode::description () const +{ + // TODO: some description? + return "processor"; +} + +void +CompoundRegionToEdgeProcessingOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionToEdgeProcessingOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionToEdgeProcessingOperationNode::processed (db::Layout *, const db::Polygon &p, std::vector &res) const +{ + return mp_proc->process (p, res); +} + +void +CompoundRegionToEdgeProcessingOperationNode::processed (db::Layout *, const db::PolygonRef &p, std::vector &res) const +{ + mp_proc->process (p.obj ().transformed (p.trans ()), res); +} + +// --------------------------------------------------------------------------------------------- + +CompoundRegionToEdgePairProcessingOperationNode::CompoundRegionToEdgePairProcessingOperationNode (PolygonToEdgePairProcessorBase *proc, CompoundRegionOperationNode *input) + : CompoundRegionMultiInputOperationNode (input), mp_proc (proc) +{ } + +std::string +CompoundRegionToEdgePairProcessingOperationNode::description () const +{ + // TODO: some description? + return "processor"; +} + +void +CompoundRegionToEdgePairProcessingOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionToEdgePairProcessingOperationNode::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +{ + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); +} + +void +CompoundRegionToEdgePairProcessingOperationNode::processed (db::Layout *, const db::Polygon &p, std::vector &res) const +{ + return mp_proc->process (p, res); +} + +void +CompoundRegionToEdgePairProcessingOperationNode::processed (db::Layout *, const db::PolygonRef &p, std::vector &res) const +{ + mp_proc->process (p.obj ().transformed (p.trans ()), res); +} + +} diff --git a/src/db/db/dbCompoundOperation.h b/src/db/db/dbCompoundOperation.h new file mode 100644 index 000000000..428f503cd --- /dev/null +++ b/src/db/db/dbCompoundOperation.h @@ -0,0 +1,776 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_dbCompoundOperation +#define HDR_dbCompoundOperation + +#include "dbLocalOperation.h" +#include "dbHierProcessor.h" +#include "dbRegionDelegate.h" +#include "dbRegion.h" +#include "dbEdges.h" +#include "dbEdgePairs.h" + +#include "gsiObject.h" +#include "tlObject.h" + +#include + +namespace db +{ + +class DB_PUBLIC CompoundRegionOperationNode + : public gsi::ObjectBase, public tl::Object +{ +public: + enum ResultType { Region, Edges, EdgePairs }; + + CompoundRegionOperationNode () + { + invalidate_cache (); + } + + virtual ~CompoundRegionOperationNode () { } + + virtual db::Coord dist () const = 0; + virtual std::string description () const = 0; + virtual std::vector inputs () const = 0; + + // specifies the result type + virtual ResultType result_type () const = 0; + + /** + * @brief Returns the transformation reducer for building cell variants + * This method may return 0. In this case, not cell variants are built. + */ + virtual const TransformationReducer *vars () const { return 0; } + + /** + * @brief Returns true, if the processor wants to build variants + * If not true, the processor accepts shape propagation as variant resolution. + */ + virtual bool wants_variants () const { return false; } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + do_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + do_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + do_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + do_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + do_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + do_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + template + bool compute_local_bool (db::Layout *layout, const shape_interactions &interactions, size_t max_vertex_count, double area_ratio) const + { + if (result_type () == Region) { + + std::vector > res; + compute_local (layout, interactions, res, max_vertex_count, area_ratio); + return ! res.empty (); + + } else if (result_type () == Edges) { + + std::vector > res; + compute_local (layout, interactions, res, max_vertex_count, area_ratio); + return ! res.empty (); + + } else if (result_type () == EdgePairs) { + + std::vector > res; + compute_local (layout, interactions, res, max_vertex_count, area_ratio); + return ! res.empty (); + + } else { + return false; + } + } + + virtual void invalidate_cache () const + { + m_cache_polyref.clear (); + m_cache_polyref_valid = false; + m_cache_poly.clear (); + m_cache_poly_valid = false; + m_cache_edge.clear (); + m_cache_edge_valid = false; + m_cache_edge_pair.clear (); + m_cache_edge_pair_valid = false; + } + +protected: + // the different computation slots + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { } + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { } + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { } + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { } + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { } + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions & /*interactions*/, std::vector > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { } + +private: + mutable std::vector > m_cache_polyref; + mutable bool m_cache_polyref_valid; + mutable std::vector > m_cache_poly; + mutable bool m_cache_poly_valid; + mutable std::vector > m_cache_edge; + mutable bool m_cache_edge_valid; + mutable std::vector > m_cache_edge_pair; + mutable bool m_cache_edge_pair_valid; + + void get_cache (std::vector > *&cache_ptr, bool *&valid) const { cache_ptr = &m_cache_polyref; valid = &m_cache_polyref_valid; } + void get_cache (std::vector > *&cache_ptr, bool *&valid) const { cache_ptr = &m_cache_poly; valid = &m_cache_poly_valid; } + void get_cache (std::vector > *&cache_ptr, bool *&valid) const { cache_ptr = &m_cache_edge; valid = &m_cache_edge_valid; } + void get_cache (std::vector > *&cache_ptr, bool *&valid) const { cache_ptr = &m_cache_edge_pair; valid = &m_cache_edge_pair_valid; } + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + std::vector > *cache = 0; + bool *valid = 0; + get_cache (cache, valid); + if (*valid) { + results = *cache; + } else { + do_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + *cache = results; + } + } +}; + + +template +struct compound_operation_type_traits; + +template <> +struct compound_operation_type_traits +{ + typedef db::Region container_type; + static CompoundRegionOperationNode::ResultType type () { return CompoundRegionOperationNode::Region; } +}; + +template <> +struct compound_operation_type_traits +{ + typedef db::Region container_type; + static CompoundRegionOperationNode::ResultType type () { return CompoundRegionOperationNode::Region; } +}; + +template <> +struct compound_operation_type_traits +{ + typedef db::Edges container_type; + static CompoundRegionOperationNode::ResultType type () { return CompoundRegionOperationNode::Edges; } +}; + +template <> +struct compound_operation_type_traits +{ + typedef db::EdgePairs container_type; + static CompoundRegionOperationNode::ResultType type () { return CompoundRegionOperationNode::EdgePairs; } +}; + + +class DB_PUBLIC CompoundRegionOperationPrimaryNode + : public CompoundRegionOperationNode +{ +public: + CompoundRegionOperationPrimaryNode (); + + virtual std::string description () const; + + virtual std::vector inputs () const; + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; +}; + + +class DB_PUBLIC CompoundRegionOperationSecondaryNode + : public CompoundRegionOperationNode +{ +public: + CompoundRegionOperationSecondaryNode (db::Region *input); + + virtual std::string description () const; + + virtual std::vector inputs () const; + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + db::Region *mp_input; +}; + + +class DB_PUBLIC CompoundTransformationReducer + : public db::TransformationReducer +{ +public: + CompoundTransformationReducer (); + + void add (const db::TransformationReducer *reducer); + bool is_empty () const { return m_vars.empty (); } + + virtual db::Trans reduce_trans (const db::Trans &trans) const; + virtual db::ICplxTrans reduce_trans (const db::ICplxTrans &trans) const; + virtual db::Trans reduce (const db::Trans &trans) const; + virtual db::ICplxTrans reduce (const db::ICplxTrans &trans) const; + virtual bool is_translation_invariant () const; + +private: + std::vector m_vars; +}; + +class DB_PUBLIC CompoundRegionMultiInputOperationNode + : public CompoundRegionOperationNode +{ +public: + CompoundRegionMultiInputOperationNode (const std::vector &children); + CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *child); + CompoundRegionMultiInputOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b); + ~CompoundRegionMultiInputOperationNode (); + + virtual db::Coord dist () const; + virtual std::string description () const; + + virtual std::vector inputs () const + { + return m_inputs; + } + + virtual const TransformationReducer *vars () const; + virtual bool wants_variants () const; + + virtual void invalidate_cache () const; + +protected: + bool needs_reduce_interactions (unsigned int child_index) const + { + if (m_children.size () < 2 || child (child_index)->inputs ().empty ()) { + return false; + } else { + return true; + } + } + + template + const shape_interactions &interactions_for_child (const shape_interactions &interactions, unsigned int child_index, shape_interactions &child_interactions) const + { + if (! needs_reduce_interactions (child_index)) { + return interactions; + } + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + + child_interactions.add_subject_shape (i->first, interactions.subject_shape (i->first)); + + for (typename shape_interactions::iterator2 ii = i->second.begin (); ii != i->second.end (); ++ii) { + + const std::pair &is = interactions.intruder_shape (*ii); + + std::map, unsigned int>::const_iterator lm = m_map_layer_to_child.find (std::make_pair (child_index, is.first)); + if (lm != m_map_layer_to_child.end ()) { + child_interactions.add_intruder_shape (*ii, lm->second, is.second); + child_interactions.add_interaction (i->first, *ii); + } + + } + + } + + return child_interactions; + } + + unsigned int children () const + { + return m_children.size (); + } + + CompoundRegionOperationNode *child (unsigned int index); + const CompoundRegionOperationNode *child (unsigned int index) const; + +private: + tl::shared_collection m_children; + // maps child#,layer# to layer# of child: + std::map, unsigned int> m_map_layer_to_child; + std::vector m_inputs; + CompoundTransformationReducer m_vars; + + void init (); +}; + + +class DB_PUBLIC CompoundRegionLogicalBoolOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum LogicalOp { And, Or }; + + CompoundRegionLogicalBoolOperationNode (LogicalOp op, bool invert, const std::vector &inputs); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const { return Region; } + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + +private: + LogicalOp m_op; + bool m_invert; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; +}; + + +class DB_PUBLIC CompoundRegionGeometricalBoolOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum GeometricalOp { And, Not, Or, Xor }; + + CompoundRegionGeometricalBoolOperationNode (GeometricalOp op, CompoundRegionOperationNode *a, CompoundRegionOperationNode *b); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + GeometricalOp m_op; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + template + void implement_bool (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; +}; + + +class DB_PUBLIC CompoundRegionInteractOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum GeometricalOp { And, Not, Or, Xor }; + + CompoundRegionInteractOperationNode (GeometricalOp op, const CompoundRegionOperationNode *a, const CompoundRegionOperationNode *b, size_t min_count = 0, size_t max_count = std::numeric_limits::max ()); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + GeometricalOp m_op; +}; + + +class DB_PUBLIC CompoundRegionPullOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum GeometricalOp { And, Not, Or, Xor }; + + CompoundRegionPullOperationNode (GeometricalOp op, const CompoundRegionOperationNode *a, const CompoundRegionOperationNode *b); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + GeometricalOp m_op; +}; + + +class DB_PUBLIC CompoundRegionSizeOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + enum GeometricalOp { And, Not, Or, Xor }; + + CompoundRegionSizeOperationNode (GeometricalOp op, const CompoundRegionOperationNode *input, db::Coord size_x, db::Coord size_y); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + virtual db::Coord dist () const; + virtual const TransformationReducer *vars () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + GeometricalOp m_op; + CompoundTransformationReducer m_vars; +}; + + +class DB_PUBLIC CompoundRegionMergeOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionMergeOperationNode (const CompoundRegionOperationNode *input, size_t min_wrap_count = 1); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const; + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; +}; + + +... either all or no input ... + +template +class DB_PUBLIC compound_region_generic_operation_node + : public CompoundRegionMultiInputOperationNode +{ +public: + compound_region_generic_operation_node (const db::local_operation &op, const std::vector &inputs, const db::TransformationReducer *vars = 0, bool want_variants = false, const std::string &description = "generic") + : CompoundRegionMultiInputOperationNode (inputs), m_op (op), m_description (description), mp_vars (vars), m_wants_variants (want_variants) + { + // .. nothing yet .. + } + + virtual std::string description () const { return m_description; } + virtual ResultType result_type () const { return compound_operation_type_traits::type (); } + virtual const db::TransformationReducer *vars () const { return mp_vars; } + virtual bool wants_variants () const { return m_wants_variants; } + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + + + +private: + db::local_operation m_op; + std::string m_description; + const db::TransformationReducer *mp_vars; + bool m_wants_variants; +}; + + +/** + * @brief Implements the case selection + * + * Case selection is a sequence of if/then nodes: + * (if1 then1 if2 then2 ... default) or (if1 then1 if2 then2 ...) + * The first condition is tested. If true, the "then1" result is taken. Otherwise, the + * "if2" condition is tested and "then2" is taken if true etc. At the end the + * default is evaluated if no other condition matched. + */ + +class DB_PUBLIC CompoundRegionLogicalCaseSelectOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionLogicalCaseSelectOperationNode (bool multi_layer, const std::vector &inputs); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const { return Region; } + + // the different computation slots + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + +private: + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + + bool m_multi_layer; +}; + + +class DB_PUBLIC CompoundRegionFilterOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionFilterOperationNode (PolygonFilterBase *filter, CompoundRegionOperationNode *input); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const { return Region; } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + + virtual const TransformationReducer *vars () const { return mp_filter->vars (); } + virtual bool wants_variants () const { return mp_filter->wants_variants (); } + +private: + PolygonFilterBase *mp_filter; + + bool is_selected (const db::Polygon &p) const; + bool is_selected (const db::PolygonRef &p) const; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + std::vector > one; + one.push_back (std::unordered_set ()); + + child (0)->compute_local (layout, interactions, one, max_vertex_count, area_ratio); + + for (typename std::unordered_set::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) { + if (is_selected (*p)) { + results.front ().insert (*p); + } + } + } +}; + + +class DB_PUBLIC CompoundRegionProcessingOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionProcessingOperationNode (PolygonProcessorBase *proc, CompoundRegionOperationNode *input); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const { return Region; } + + virtual const TransformationReducer *vars () const { return mp_proc->vars (); } + virtual bool wants_variants () const { return mp_proc->wants_variants (); } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + PolygonProcessorBase *mp_proc; + + void processed (db::Layout *, const db::Polygon &p, std::vector &res) const; + void processed (db::Layout *layout, const db::PolygonRef &p, std::vector &res) const; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + std::vector > one; + one.push_back (std::unordered_set ()); + + child (0)->compute_local (layout, interactions, one, max_vertex_count, area_ratio); + + for (typename std::unordered_set::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) { + std::vector res; + processed (layout, *p, res); + results.front ().insert (res.begin (), res.end ()); + } + } +}; + +class DB_PUBLIC CompoundRegionToEdgeProcessingOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionToEdgeProcessingOperationNode (PolygonToEdgeProcessorBase *proc, CompoundRegionOperationNode *input); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const { return Edges; } + + virtual const TransformationReducer *vars () const { return mp_proc->vars (); } + virtual bool wants_variants () const { return mp_proc->wants_variants (); } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + PolygonToEdgeProcessorBase *mp_proc; + + void processed (db::Layout *, const db::Polygon &p, std::vector &res) const; + void processed (db::Layout *layout, const db::PolygonRef &p, std::vector &res) const; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + std::vector > one; + one.push_back (std::unordered_set ()); + + child (0)->compute_local (layout, interactions, one, max_vertex_count, area_ratio); + + for (typename std::unordered_set::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) { + std::vector res; + processed (layout, *p, res); + results.front ().insert (res.begin (), res.end ()); + } + } +}; + +class DB_PUBLIC CompoundRegionToEdgePairProcessingOperationNode + : public CompoundRegionMultiInputOperationNode +{ +public: + CompoundRegionToEdgePairProcessingOperationNode (PolygonToEdgePairProcessorBase *proc, CompoundRegionOperationNode *input); + + virtual std::string description () const; + + // specifies the result type + virtual ResultType result_type () const { return EdgePairs; } + + virtual const TransformationReducer *vars () const { return mp_proc->vars (); } + virtual bool wants_variants () const { return mp_proc->wants_variants (); } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + +private: + PolygonToEdgePairProcessorBase *mp_proc; + + void processed (db::Layout *, const db::Polygon &p, std::vector &res) const; + void processed (db::Layout *layout, const db::PolygonRef &p, std::vector &res) const; + + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + std::vector > one; + one.push_back (std::unordered_set ()); + + child (0)->compute_local (layout, interactions, one, max_vertex_count, area_ratio); + + for (typename std::unordered_set::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) { + std::vector res; + processed (layout, *p, res); + results.front ().insert (res.begin (), res.end ()); + } + } +}; + + +template +class DB_PUBLIC compound_local_operation + : public local_operation +{ +public: + compound_local_operation (CompoundRegionOperationNode *node) + : mp_node (node) + { } + + virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + + const TS &subject_shape = interactions.subject_shape (i->first); + + shape_interactions single_interactions; + + single_interactions.add_subject_shape (i->first, subject_shape); + const std::vector &intruders = single_interactions.intruders_for (i->first); + for (typename std::vector::const_iterator ii = intruders.begin (); ii != intruders.end (); ++ii) { + const std::pair &is = interactions.intruder_shape (*ii); + single_interactions.add_intruder_shape (*ii, is.first, is.second); + single_interactions.add_interaction (i->first, *ii); + } + + mp_node->compute_local (layout, single_interactions, results, max_vertex_count, area_ratio); + + } + } + + virtual db::Coord dist () const; + virtual typename local_operation::on_empty_intruder_mode on_empty_intruder_hint () const; + virtual std::string description () const; + + const TransformationReducer *vars () const { return mp_node->vars (); } + bool wants_variants () const { return mp_node->wants_variants (); } + +private: + std::auto_ptr mp_node; +}; + +} + +#endif