From 124c4eb61c80d1ebf952d5a09ae50984ca63140c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 20 Feb 2019 09:45:38 +0100 Subject: [PATCH] Refactoring: generalization of filter/processor for edges, region --- src/db/db/dbAsIfFlatEdges.cc | 46 ++++++++ src/db/db/dbAsIfFlatEdges.h | 2 + src/db/db/dbAsIfFlatRegion.cc | 51 +++++++++ src/db/db/dbAsIfFlatRegion.h | 2 + src/db/db/dbDeepEdges.cc | 193 ++++++++++++++++++++++++-------- src/db/db/dbDeepEdges.h | 3 + src/db/db/dbDeepRegion.cc | 89 ++++++++++++--- src/db/db/dbDeepRegion.h | 6 + src/db/db/dbEdgePairsDelegate.h | 6 + src/db/db/dbEdges.cc | 6 + src/db/db/dbEdges.h | 25 +++++ src/db/db/dbEdgesDelegate.h | 106 +++++++++++++++++- src/db/db/dbEdgesUtils.h | 32 ++++++ src/db/db/dbEmptyEdges.cc | 13 +++ src/db/db/dbEmptyEdges.h | 2 + src/db/db/dbEmptyRegion.cc | 14 +++ src/db/db/dbEmptyRegion.h | 2 + src/db/db/dbFlatRegion.cc | 4 + src/db/db/dbRegion.cc | 5 + src/db/db/dbRegion.h | 26 +++++ src/db/db/dbRegionDelegate.h | 54 ++++++++- 21 files changed, 615 insertions(+), 72 deletions(-) diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index c2b0b4c45..2ed17d5f7 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -23,6 +23,8 @@ #include "dbAsIfFlatEdges.h" #include "dbFlatEdges.h" +#include "dbFlatEdgePairs.h" +#include "dbFlatRegion.h" #include "dbEmptyEdges.h" #include "dbEdges.h" #include "dbEdgesUtils.h" @@ -362,6 +364,50 @@ AsIfFlatEdges::processed (const EdgeProcessorBase &filter) const return edges.release (); } +EdgePairsDelegate * +AsIfFlatEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const +{ + std::auto_ptr edge_pairs (new FlatEdgePairs ()); + + if (filter.result_must_not_be_merged ()) { + edge_pairs->set_merged_semantics (false); + } + + std::vector res_edge_pairs; + + for (EdgesIterator e (filter.requires_raw_input () ? begin () : begin_merged ()); ! e.at_end (); ++e) { + res_edge_pairs.clear (); + filter.process (*e, res_edge_pairs); + for (std::vector::const_iterator epr = res_edge_pairs.begin (); epr != res_edge_pairs.end (); ++epr) { + edge_pairs->insert (*epr); + } + } + + return edge_pairs.release (); +} + +RegionDelegate * +AsIfFlatEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const +{ + std::auto_ptr region (new FlatRegion ()); + + if (filter.result_must_not_be_merged ()) { + region->set_merged_semantics (false); + } + + std::vector res_polygons; + + for (EdgesIterator e (filter.requires_raw_input () ? begin () : begin_merged ()); ! e.at_end (); ++e) { + res_polygons.clear (); + filter.process (*e, res_polygons); + for (std::vector::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) { + region->insert (*pr); + } + } + + return region.release (); +} + EdgesDelegate * AsIfFlatEdges::filtered (const EdgeFilterBase &filter) const { diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index a4de96326..2b19fdf1a 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -88,6 +88,8 @@ public: } virtual EdgesDelegate *processed (const EdgeProcessorBase &filter) const; + virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &) const; + virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &) const; virtual EdgesDelegate *filter_in_place (const EdgeFilterBase &filter) { diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 1980af561..2ebd71ec0 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -24,6 +24,7 @@ #include "dbAsIfFlatRegion.h" #include "dbFlatRegion.h" #include "dbFlatEdgePairs.h" +#include "dbFlatEdges.h" #include "dbEmptyRegion.h" #include "dbRegion.h" #include "dbRegionUtils.h" @@ -252,6 +253,10 @@ RegionDelegate * AsIfFlatRegion::processed (const PolygonProcessorBase &filter) const { std::auto_ptr new_region (new FlatRegion ()); + if (filter.result_must_not_be_merged ()) { + new_region->set_merged_semantics (false); + } + std::vector poly_res; for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) { @@ -267,6 +272,52 @@ AsIfFlatRegion::processed (const PolygonProcessorBase &filter) const return new_region.release (); } +EdgesDelegate * +AsIfFlatRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const +{ + std::auto_ptr new_edges (new FlatEdges ()); + if (filter.result_must_not_be_merged ()) { + new_edges->set_merged_semantics (false); + } + + std::vector edge_res; + + for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) { + + edge_res.clear (); + filter.process (*p, edge_res); + for (std::vector::const_iterator er = edge_res.begin (); er != edge_res.end (); ++er) { + new_edges->insert (*er); + } + + } + + return new_edges.release (); +} + +EdgePairsDelegate * +AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const +{ + std::auto_ptr new_edge_pairs (new FlatEdgePairs ()); + if (filter.result_must_not_be_merged ()) { + new_edge_pairs->set_merged_semantics (false); + } + + std::vector edge_pair_res; + + for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) { + + edge_pair_res.clear (); + filter.process (*p, edge_pair_res); + for (std::vector::const_iterator epr = edge_pair_res.begin (); epr != edge_pair_res.end (); ++epr) { + new_edge_pairs->insert (*epr); + } + + } + + return new_edge_pairs.release (); +} + RegionDelegate * AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse) const { diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index 21ad83c0f..974c105c2 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -113,6 +113,8 @@ public: } virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const; + virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &filter) const; + virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const; virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter) { diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 7211b3b43..2e4a7dfd8 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -483,59 +483,136 @@ EdgesDelegate *DeepEdges::process_in_place (const EdgeProcessorBase &filter) return processed (filter); } -EdgesDelegate *DeepEdges::processed (const EdgeProcessorBase &filter) const +EdgesDelegate * +DeepEdges::processed (const EdgeProcessorBase &filter) const +{ + return processed_impl (filter); +} + +EdgePairsDelegate * +DeepEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const +{ + return processed_impl (filter); +} + +RegionDelegate * +DeepEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const +{ + return processed_impl (filter); +} + +namespace +{ + +template struct delivery; + +template <> +struct delivery +{ + delivery (db::Layout *layout, db::Shapes *shapes) + : mp_layout (layout), mp_shapes (shapes) + { } + + void put (const db::Polygon &result) + { + tl::MutexLocker locker (&mp_layout->lock ()); + mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ())); + } + +private: + db::Layout *mp_layout; + db::Shapes *mp_shapes; +}; + +template +struct delivery +{ + delivery (db::Layout *, db::Shapes *shapes) + : mp_shapes (shapes) + { } + + void put (const Result &result) + { + mp_shapes->insert (result); + } + +private: + db::Shapes *mp_shapes; +}; + +} + +template +OutputContainer * +DeepEdges::processed_impl (const edge_processor &filter) const { if (! filter.requires_raw_input ()) { ensure_merged_edges_valid (); } std::auto_ptr vars; - if (filter.vars ()) { vars.reset (new db::VariantsCollectorBase (filter.vars ())); vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ()); - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (m_deep_layer).separate_variants (*vars); + if (filter.wants_variants ()) { + const_cast (m_deep_layer).separate_variants (*vars); + } } db::Layout &layout = const_cast (m_deep_layer.layout ()); - std::vector res_edges; - std::auto_ptr res (new db::DeepEdges (m_deep_layer.derived ())); + std::vector heap; + std::map > to_commit; + + std::auto_ptr res (new OutputContainer (m_deep_layer.derived ())); + if (filter.result_must_not_be_merged ()) { + res->set_merged_semantics (false); + } + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ()); + if (vars.get ()) { - const std::map &v = vars->variants (c->cell_index ()); - tl_assert (v.size () == size_t (1)); - const db::ICplxTrans &tr = v.begin ()->first; - db::ICplxTrans trinv = tr.inverted (); + const std::map &vv = vars->variants (c->cell_index ()); + for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) { - const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ()); - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); - - for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { - res_edges.clear (); - filter.process (si->edge ().transformed (tr), res_edges); - for (std::vector::const_iterator er = res_edges.begin (); er != res_edges.end (); ++er) { - st.insert (er->transformed (trinv)); + db::Shapes *st; + if (vv.size () == 1) { + st = & c->shapes (res->deep_layer ().layer ()); + } else { + st = & to_commit [c->cell_index ()] [v->first]; } + + delivery delivery (&layout, st); + + const db::ICplxTrans &tr = v->first; + db::ICplxTrans trinv = tr.inverted (); + + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { + heap.clear (); + filter.process (si->edge ().transformed (tr), heap); + for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { + delivery.put (i->transformed (trinv)); + } + } + } } else { - const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ()); db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + delivery delivery (&layout, &st); for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { - res_edges.clear (); - filter.process (si->edge (), res_edges); - for (std::vector::const_iterator er = res_edges.begin (); er != res_edges.end (); ++er) { - st.insert (*er); + filter.process (si->edge (), heap); + for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { + delivery.put (*i); } } @@ -543,66 +620,80 @@ EdgesDelegate *DeepEdges::processed (const EdgeProcessorBase &filter) const } + if (! to_commit.empty () && vars.get ()) { + res->deep_layer ().commit_shapes (*vars, to_commit); + } + if (filter.result_is_merged ()) { res->set_is_merged (true); } - return res.release (); } -EdgesDelegate *DeepEdges::filter_in_place (const EdgeFilterBase &filter) +EdgesDelegate * +DeepEdges::filter_in_place (const EdgeFilterBase &filter) { // TODO: implement to be really in-place return filtered (filter); } -EdgesDelegate *DeepEdges::filtered (const EdgeFilterBase &filter) const +EdgesDelegate * +DeepEdges::filtered (const EdgeFilterBase &filter) const { - ensure_merged_edges_valid (); + if (! filter.requires_raw_input ()) { + ensure_merged_edges_valid (); + } std::auto_ptr vars; - if (filter.vars ()) { vars.reset (new db::VariantsCollectorBase (filter.vars ())); - vars->collect (m_merged_edges.layout (), m_merged_edges.initial_cell ()); + vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ()); - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? - const_cast (m_merged_edges).separate_variants (*vars); + if (filter.wants_variants ()) { + const_cast (m_deep_layer).separate_variants (*vars); + } } - db::Layout &layout = m_merged_edges.layout (); + db::Layout &layout = const_cast (m_deep_layer.layout ()); + std::map > to_commit; - std::auto_ptr res (new db::DeepEdges (m_merged_edges.derived ())); + std::auto_ptr res (new db::DeepEdges (m_deep_layer.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ()); + if (vars.get ()) { - const std::map &v = vars->variants (c->cell_index ()); - tl_assert (v.size () == size_t (1)); - const db::ICplxTrans &tr = v.begin ()->first; + const std::map &vv = vars->variants (c->cell_index ()); + for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) { - const db::Shapes &s = c->shapes (m_merged_edges.layer ()); - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); - - for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { - db::Edge edge = si->edge (); - if (filter.selected (edge.transformed (tr))) { - st.insert (edge); + db::Shapes *st; + if (vv.size () == 1) { + st = & c->shapes (res->deep_layer ().layer ()); + } else { + st = & to_commit [c->cell_index ()] [v->first]; } + + const db::ICplxTrans &tr = v->first; + + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { + if (filter.selected (si->edge ().transformed (tr))) { + st->insert (*si); + } + } + } } else { - const db::Shapes &s = c->shapes (m_merged_edges.layer ()); db::Shapes &st = c->shapes (res->deep_layer ().layer ()); for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { - db::Edge edge = si->edge (); - if (filter.selected (edge)) { - st.insert (edge); + if (filter.selected (si->edge ())) { + st.insert (*si); } } @@ -610,7 +701,13 @@ EdgesDelegate *DeepEdges::filtered (const EdgeFilterBase &filter) const } - res->set_is_merged (true); + if (! to_commit.empty () && vars.get ()) { + res->deep_layer ().commit_shapes (*vars, to_commit); + } + + if (! filter.requires_raw_input ()) { + res->set_is_merged (true); + } return res.release (); } diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index f61a9f027..c72a8c9d9 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -112,6 +112,8 @@ public: virtual EdgesDelegate *filtered (const EdgeFilterBase &) const; virtual EdgesDelegate *process_in_place (const EdgeProcessorBase &); virtual EdgesDelegate *processed (const EdgeProcessorBase &) const; + virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const; + virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const; virtual EdgesDelegate *merged_in_place (); virtual EdgesDelegate *merged () const; @@ -174,6 +176,7 @@ private: EdgePairs run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const; EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const; EdgesDelegate *selected_interacting_generic (const Region ®ion, bool invert) const; + template OutputContainer *processed_impl (const edge_processor &filter) const; }; } diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 9fdb131f6..7f2221c0c 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -912,8 +912,68 @@ DeepRegion::process_in_place (const PolygonProcessorBase &filter) return processed (filter); } +EdgesDelegate * +DeepRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const +{ + return processed_impl (filter); +} + +EdgePairsDelegate * +DeepRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const +{ + return processed_impl (filter); +} + RegionDelegate * DeepRegion::processed (const PolygonProcessorBase &filter) const +{ + return processed_impl (filter); +} + +namespace +{ + +template struct delivery; + +template <> +struct delivery +{ + delivery (db::Layout *layout, db::Shapes *shapes) + : mp_layout (layout), mp_shapes (shapes) + { } + + void put (const db::Polygon &result) + { + tl::MutexLocker locker (&mp_layout->lock ()); + mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ())); + } + +private: + db::Layout *mp_layout; + db::Shapes *mp_shapes; +}; + +template +struct delivery +{ + delivery (db::Layout *, db::Shapes *shapes) + : mp_shapes (shapes) + { } + + void put (const Result &result) + { + mp_shapes->insert (result); + } + +private: + db::Shapes *mp_shapes; +}; + +} + +template +OutputContainer * +DeepRegion::processed_impl (const polygon_processor &filter) const { if (! filter.requires_raw_input ()) { ensure_merged_polygons_valid (); @@ -934,10 +994,14 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const db::Layout &layout = const_cast (m_deep_layer.layout ()); - std::vector poly_res; + std::vector heap; std::map > to_commit; - std::auto_ptr res (new db::DeepRegion (m_deep_layer.derived ())); + std::auto_ptr res (new OutputContainer (m_deep_layer.derived ())); + if (filter.result_must_not_be_merged ()) { + res->set_merged_semantics (false); + } + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_polygons.layer ()); @@ -954,7 +1018,7 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const st = & to_commit [c->cell_index ()] [v->first]; } - db::PolygonRefToShapesGenerator pr (&layout, st); + delivery delivery (&layout, st); const db::ICplxTrans &tr = v->first; db::ICplxTrans trinv = tr.inverted (); @@ -963,10 +1027,10 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const db::Polygon poly; si->polygon (poly); poly.transform (tr); - poly_res.clear (); - filter.process (poly, poly_res); - for (std::vector::const_iterator p = poly_res.begin (); p != poly_res.end (); ++p) { - pr.put (p->transformed (trinv)); + heap.clear (); + filter.process (poly, heap); + for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { + delivery.put (i->transformed (trinv)); } } @@ -975,15 +1039,15 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const } else { db::Shapes &st = c->shapes (res->deep_layer ().layer ()); - db::PolygonRefToShapesGenerator pr (&layout, &st); + delivery delivery (&layout, &st); for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { db::Polygon poly; si->polygon (poly); - poly_res.clear (); - filter.process (poly, poly_res); - for (std::vector::const_iterator p = poly_res.begin (); p != poly_res.end (); ++p) { - pr.put (*p); + heap.clear (); + filter.process (poly, heap); + for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { + delivery.put (*i); } } @@ -1022,7 +1086,6 @@ DeepRegion::filtered (const PolygonFilterBase &filter) const vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ()); - // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? if (filter.wants_variants ()) { const_cast (m_deep_layer).separate_variants (*vars); } diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 83dee241a..76e9cb1a1 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -140,6 +140,8 @@ public: virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter); virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const; + virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &filter) const; + virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const; virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter); virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const; @@ -221,6 +223,8 @@ protected: void set_is_merged (bool f); private: + friend class DeepEdges; + DeepRegion &operator= (const DeepRegion &other); DeepLayer m_deep_layer; @@ -240,6 +244,8 @@ private: { return m_merged_polygons; } + + template OutputContainer *processed_impl (const polygon_processor &filter) const; }; } diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h index 42fd86522..d894013b4 100644 --- a/src/db/db/dbEdgePairsDelegate.h +++ b/src/db/db/dbEdgePairsDelegate.h @@ -78,6 +78,12 @@ public: void enable_progress (const std::string &progress_desc); void disable_progress (); + // dummy features to harmonize the interface of region, edges and edge pair delegates + void set_merged_semantics (bool) { } + bool merged_semantics () const { return false; } + void set_is_merged (bool) { } + bool is_merged () const { return false; } + virtual std::string to_string (size_t nmax) const = 0; virtual EdgePairsIteratorDelegate *begin () const = 0; diff --git a/src/db/db/dbEdges.cc b/src/db/db/dbEdges.cc index 272f1a604..8f56087d4 100644 --- a/src/db/db/dbEdges.cc +++ b/src/db/db/dbEdges.cc @@ -70,6 +70,7 @@ public: virtual bool result_is_merged () const { return false; } virtual bool requires_raw_input () const { return false; } virtual bool result_must_not_be_merged () const { return m_length <= 0; } + virtual bool wants_variants () const { return true; } private: int m_mode; @@ -185,6 +186,11 @@ Edges::reserve (size_t n) flat_edges ()->reserve (n); } +void Edges::processed (Region &output, const EdgeToPolygonProcessorBase &filter) const +{ + output.set_delegate (mp_delegate->processed_to_polygons (filter)); +} + void Edges::extended (Region &output, coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const { output.set_delegate (mp_delegate->extended (ext_b, ext_e, ext_o, ext_i, join)); diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 34a17a2c4..2dadfa51d 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -623,6 +623,31 @@ public: return Edges (mp_delegate->processed (filter)); } + /** + * @brief Processes the edges into polygons + * + * This method will run the processor over all edges and return a region + * with the outputs of the processor. + * + * Merged semantics applies. In merged semantics, the filter will run over + * all merged edges. + */ + void processed (Region &output, const EdgeToPolygonProcessorBase &filter) const; + + /** + * @brief Processes the edges into edge pairs + * + * This method will run the processor over all edges and return an edge pair collection + * with the outputs of the processor. + * + * Merged semantics applies. In merged semantics, the filter will run over + * all merged edges. + */ + EdgePairs processed (const EdgeToEdgePairProcessorBase &filter) const + { + return EdgePairs (mp_delegate->processed_to_edge_pairs (filter)); + } + /** * @brief Applies a width check and returns EdgePairs which correspond to violation markers * diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 75809b135..0986e2604 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -40,27 +40,118 @@ namespace db { class DB_PUBLIC EdgeFilterBase { public: + /** + * @brief Constructor + */ EdgeFilterBase () { } + virtual ~EdgeFilterBase () { } + /** + * @brief Filters the edge + * If this method returns true, the polygon is kept. Otherwise it's discarded. + */ virtual bool selected (const db::Edge &edge) 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 = 0; + + /** + * @brief Returns true, if the filter wants raw (not merged) input + */ + virtual bool requires_raw_input () const = 0; + + /** + * @brief Returns true, if the filter wants to build variants + * If not true, the filter accepts shape propagation as variant resolution. + */ + virtual bool wants_variants () const = 0; }; /** - * @brief A base class for polygon processors + * @brief A template base class for edge processors + * + * A polygon processor can turn a edge into something else. */ -class DB_PUBLIC EdgeProcessorBase +template +class DB_PUBLIC edge_processor { public: - EdgeProcessorBase () { } - virtual ~EdgeProcessorBase () { } + /** + * @brief Constructor + */ + edge_processor () { } - virtual void process (const db::Edge &polygon, std::vector &res) const = 0; + /** + * @brief Destructor + */ + virtual ~edge_processor () { } + + /** + * @brief Performs the actual processing + * This method will take the input edge from "edge" and puts the results into "res". + * "res" can be empty - in this case, the edge will be skipped. + */ + virtual void process (const db::Edge &edge, std::vector &res) 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 = 0; + + /** + * @brief Returns true, if the result of this operation can be regarded "merged" always. + */ virtual bool result_is_merged () const = 0; - virtual bool requires_raw_input () const = 0; + + /** + * @brief Returns true, if the result of this operation must not be merged. + * This feature can be used, if the result represents "degenerated" objects such + * as point-like edges. These must not be merged. Otherwise they disappear. + */ virtual bool result_must_not_be_merged () const = 0; + + /** + * @brief Returns true, if the processor wants raw (not merged) input + */ + virtual bool requires_raw_input () const = 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 = 0; +}; + +/** + * @brief A edge processor base class + */ +class DB_PUBLIC EdgeProcessorBase + : public edge_processor +{ + // .. nothing yet .. +}; + +/** + * @brief An edge-to-polygon processor base class + */ +class DB_PUBLIC EdgeToPolygonProcessorBase + : public edge_processor +{ + // .. nothing yet .. +}; + +/** + * @brief An edge-to-edge pair processor base class + */ +class DB_PUBLIC EdgeToEdgePairProcessorBase + : public edge_processor +{ + // .. nothing yet .. }; /** @@ -70,6 +161,7 @@ enum EdgeBoolOp { EdgeOr, EdgeNot, EdgeXor, EdgeAnd }; class RecursiveShapeIterator; class EdgeFilterBase; +class EdgePairsDelegate; class RegionDelegate; /** @@ -159,6 +251,8 @@ public: virtual EdgesDelegate *filtered (const EdgeFilterBase &filter) const = 0; virtual EdgesDelegate *process_in_place (const EdgeProcessorBase &filter) = 0; virtual EdgesDelegate *processed (const EdgeProcessorBase &filter) const = 0; + virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const = 0; + virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const = 0; virtual EdgesDelegate *merged_in_place () = 0; virtual EdgesDelegate *merged () const = 0; diff --git a/src/db/db/dbEdgesUtils.h b/src/db/db/dbEdgesUtils.h index 33812c2f8..8377bdde6 100644 --- a/src/db/db/dbEdgesUtils.h +++ b/src/db/db/dbEdgesUtils.h @@ -80,6 +80,22 @@ struct DB_PUBLIC EdgeLengthFilter return &m_vars; } + /** + * @brief Requires merged input + */ + virtual bool requires_raw_input () const + { + return false; + } + + /** + * @brief Wants to build variants + */ + virtual bool wants_variants () const + { + return true; + } + private: length_type m_lmin, m_lmax; bool m_inverse; @@ -161,6 +177,22 @@ struct DB_PUBLIC EdgeOrientationFilter return &m_vars; } + /** + * @brief Requires merged input + */ + virtual bool requires_raw_input () const + { + return false; + } + + /** + * @brief Wants to build variants + */ + virtual bool wants_variants () const + { + return true; + } + private: db::DVector m_emin, m_emax; bool m_inverse; diff --git a/src/db/db/dbEmptyEdges.cc b/src/db/db/dbEmptyEdges.cc index fb1dfbc8a..78dbd6576 100644 --- a/src/db/db/dbEmptyEdges.cc +++ b/src/db/db/dbEmptyEdges.cc @@ -22,6 +22,7 @@ #include "dbEmptyEdges.h" +#include "dbEmptyEdgePairs.h" #include "dbEmptyRegion.h" #include "dbEdges.h" @@ -59,6 +60,18 @@ EmptyEdges::extended (coord_type, coord_type, coord_type, coord_type, bool) cons return new EmptyRegion (); } +EdgePairsDelegate * +EmptyEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &) const +{ + return new EmptyEdgePairs (); +} + +RegionDelegate * +EmptyEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &) const +{ + return new EmptyRegion (); +} + EdgesDelegate * EmptyEdges::add_in_place (const Edges &other) { diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index 30644503b..83251d92a 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -67,6 +67,8 @@ public: virtual EdgesDelegate *filtered (const EdgeFilterBase &) const { return new EmptyEdges (); } virtual EdgesDelegate *process_in_place (const EdgeProcessorBase &) { return this; } virtual EdgesDelegate *processed (const EdgeProcessorBase &) const { return new EmptyEdges (); } + virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &) const; + virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &) const; virtual EdgesDelegate *merged_in_place () { return this; } virtual EdgesDelegate *merged () const { return new EmptyEdges (); } diff --git a/src/db/db/dbEmptyRegion.cc b/src/db/db/dbEmptyRegion.cc index 35e09021d..fa42cdb71 100644 --- a/src/db/db/dbEmptyRegion.cc +++ b/src/db/db/dbEmptyRegion.cc @@ -22,6 +22,8 @@ #include "dbEmptyRegion.h" +#include "dbEmptyEdges.h" +#include "dbEmptyEdgePairs.h" #include "dbRegion.h" namespace db @@ -82,6 +84,18 @@ EmptyRegion::or_with (const Region &other) const } } +EdgesDelegate * +EmptyRegion::processed_to_edges (const PolygonToEdgeProcessorBase &) const +{ + return new EmptyEdges (); +} + +EdgePairsDelegate * +EmptyRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &) const +{ + return new EmptyEdgePairs (); +} + bool EmptyRegion::equals (const Region &other) const { diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h index 78cfceffb..107448b97 100644 --- a/src/db/db/dbEmptyRegion.h +++ b/src/db/db/dbEmptyRegion.h @@ -78,6 +78,8 @@ public: virtual RegionDelegate *filtered (const PolygonFilterBase &) const { return new EmptyRegion (); } virtual RegionDelegate *process_in_place (const PolygonProcessorBase &) { return this; } virtual RegionDelegate *processed (const PolygonProcessorBase &) const { return new EmptyRegion (); } + virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &) const; + virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &) const; virtual RegionDelegate *merged_in_place () { return this; } virtual RegionDelegate *merged_in_place (bool, unsigned int) { return this; } diff --git a/src/db/db/dbFlatRegion.cc b/src/db/db/dbFlatRegion.cc index fe1979706..1ab7ebaa9 100644 --- a/src/db/db/dbFlatRegion.cc +++ b/src/db/db/dbFlatRegion.cc @@ -230,6 +230,10 @@ RegionDelegate *FlatRegion::process_in_place (const PolygonProcessorBase &filter m_merged_polygons.clear (); m_is_merged = filter.result_is_merged () && merged_semantics (); + if (filter.result_must_not_be_merged ()) { + set_merged_semantics (false); + } + return this; } diff --git a/src/db/db/dbRegion.cc b/src/db/db/dbRegion.cc index 323b6c601..c957c419a 100644 --- a/src/db/db/dbRegion.cc +++ b/src/db/db/dbRegion.cc @@ -70,6 +70,7 @@ public: virtual bool result_is_merged () const { return false; } virtual bool requires_raw_input () const { return true; } virtual bool wants_variants () const { return true; } + virtual bool result_must_not_be_merged () const { return false; } }; // ------------------------------------------------------------------------------------------------------------- @@ -90,6 +91,7 @@ public: virtual bool result_is_merged () const { return false; } virtual bool requires_raw_input () const { return false; } virtual bool wants_variants () const { return true; } + virtual bool result_must_not_be_merged () const { return false; } private: db::Coord m_d; @@ -116,6 +118,7 @@ public: virtual bool result_is_merged () const { return true; } // we believe so ... virtual bool requires_raw_input () const { return false; } virtual bool wants_variants () const { return true; } + virtual bool result_must_not_be_merged () const { return false; } private: double m_rinner, m_router; @@ -144,6 +147,7 @@ public: virtual bool result_is_merged () const { return true; } // we believe so ... virtual bool requires_raw_input () const { return false; } virtual bool wants_variants () const { return true; } + virtual bool result_must_not_be_merged () const { return false; } }; // ------------------------------------------------------------------------------------------------------------- @@ -165,6 +169,7 @@ public: virtual bool result_is_merged () const { return true; } // we believe so ... virtual bool requires_raw_input () const { return false; } virtual bool wants_variants () const { return true; } + virtual bool result_must_not_be_merged () const { return false; } }; } diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index 3d6544454..6b28f7ec3 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -660,6 +660,32 @@ public: return Region (mp_delegate->processed (filter)); } + /** + * @brief Processes the polygons into edges + * + * This method applies a processor returning edges for the polygons. + * + * Merged semantics applies. In merged semantics, the filter will run over + * all merged polygons. + */ + Edges processed (const PolygonToEdgeProcessorBase &filter) const + { + return Edges (mp_delegate->processed_to_edges (filter)); + } + + /** + * @brief Processes the polygons into edge pairs + * + * This method applies a processor returning edge pairs for the polygons. + * + * Merged semantics applies. In merged semantics, the filter will run over + * all merged polygons. + */ + EdgePairs processed (const PolygonToEdgePairProcessorBase &filter) const + { + return EdgePairs (mp_delegate->processed_to_edge_pairs (filter)); + } + /** * @brief Applies a width check and returns EdgePairs which correspond to violation markers * diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index 9c2d5a294..17108cf18 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -37,6 +37,8 @@ namespace db { class RecursiveShapeIterator; class EdgeFilterBase; +class EdgesDelegate; +class EdgePairsDelegate; /** * @brief A base class for polygon filters @@ -76,24 +78,30 @@ public: }; /** - * @brief A base class for polygon processors + * @brief A template base class for polygon processors + * + * A polygon processor can turn a polygon into something else. */ -class DB_PUBLIC PolygonProcessorBase +template +class DB_PUBLIC polygon_processor { public: /** * @brief Constructor */ - PolygonProcessorBase () { } + polygon_processor () { } - virtual ~PolygonProcessorBase () { } + /** + * @brief Destructor + */ + virtual ~polygon_processor () { } /** * @brief Performs the actual processing * This method will take the input polygon from "polygon" and puts the results into "res". * "res" can be empty - in this case, the polygon will be skipped. */ - virtual void process (const db::Polygon &polygon, std::vector &res) const = 0; + virtual void process (const db::Polygon &polygon, std::vector &res) const = 0; /** * @brief Returns the transformation reducer for building cell variants @@ -106,6 +114,13 @@ public: */ virtual bool result_is_merged () const = 0; + /** + * @brief Returns true, if the result of this operation must not be merged. + * This feature can be used, if the result represents "degenerated" objects such + * as point-like edges. These must not be merged. Otherwise they disappear. + */ + virtual bool result_must_not_be_merged () const = 0; + /** * @brief Returns true, if the processor wants raw (not merged) input */ @@ -118,6 +133,33 @@ public: virtual bool wants_variants () const = 0; }; +/** + * @brief A polygon-to-polygon processor base class + */ +class DB_PUBLIC PolygonProcessorBase + : public polygon_processor +{ + // .. nothing yet .. +}; + +/** + * @brief A polygon-to-edge processor base class + */ +class DB_PUBLIC PolygonToEdgeProcessorBase + : public polygon_processor +{ + // .. nothing yet .. +}; + +/** + * @brief A polygon-to-edge pair processor base class + */ +class DB_PUBLIC PolygonToEdgePairProcessorBase + : public polygon_processor +{ + // .. nothing yet .. +}; + /** * @brief The region iterator delegate */ @@ -222,6 +264,8 @@ public: virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const = 0; virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter) = 0; virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const = 0; + virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &filter) const = 0; + virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const = 0; virtual RegionDelegate *merged_in_place () = 0; virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc) = 0;