diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 20be32979..7b249ef60 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -619,6 +619,40 @@ static inline db::Coord snap_to_grid (db::Coord c, db::Coord g) return c; } +db::Polygon +AsIfFlatRegion::snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector &heap) +{ + db::Polygon pnew; + + for (size_t i = 0; i < poly.holes () + 1; ++i) { + + heap.clear (); + + db::Polygon::polygon_contour_iterator b, e; + + if (i == 0) { + b = poly.begin_hull (); + e = poly.end_hull (); + } else { + b = poly.begin_hole ((unsigned int) (i - 1)); + e = poly.end_hole ((unsigned int) (i - 1)); + } + + for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) { + heap.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy))); + } + + if (i == 0) { + pnew.assign_hull (heap.begin (), heap.end ()); + } else { + pnew.insert_hole (heap.begin (), heap.end ()); + } + + } + + return pnew; +} + RegionDelegate * AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy) { @@ -627,40 +661,10 @@ AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy) gx = std::max (db::Coord (1), gx); gy = std::max (db::Coord (1), gy); - std::vector pts; + std::vector heap; for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) { - - db::Polygon pnew; - - for (size_t i = 0; i < p->holes () + 1; ++i) { - - pts.clear (); - - db::Polygon::polygon_contour_iterator b, e; - - if (i == 0) { - b = p->begin_hull (); - e = p->end_hull (); - } else { - b = p->begin_hole ((unsigned int) (i - 1)); - e = p->end_hole ((unsigned int) (i - 1)); - } - - for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) { - pts.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy))); - } - - if (i == 0) { - pnew.assign_hull (pts.begin (), pts.end ()); - } else { - pnew.insert_hole (pts.begin (), pts.end ()); - } - - } - - new_region->raw_polygons ().insert (pnew); - + new_region->raw_polygons ().insert (snapped_polygon (*p, gx, gy, heap)); } return new_region.release (); @@ -677,22 +681,25 @@ struct DB_PUBLIC StrangePolygonInsideFunc } }; +void +AsIfFlatRegion::produce_shape_for_strange_polygon (const db::Polygon &poly, db::Shapes &shapes) +{ + EdgeProcessor ep; + ep.insert (poly); + + StrangePolygonInsideFunc inside; + db::GenericMerge op (inside); + db::ShapeGenerator pc (shapes, false); + db::PolygonGenerator pg (pc, false, false); + ep.process (pg, op); +} + RegionDelegate * AsIfFlatRegion::strange_polygon_check () const { - EdgeProcessor ep; std::auto_ptr new_region (new FlatRegion (merged_semantics ())); - for (RegionIterator p (begin ()); ! p.at_end (); ++p) { - - ep.clear (); - ep.insert (*p); - - StrangePolygonInsideFunc inside; - db::GenericMerge op (inside); - db::ShapeGenerator pc (new_region->raw_polygons (), false); - db::PolygonGenerator pg (pc, false, false); - ep.process (pg, op); + produce_shape_for_strange_polygon (*p, new_region->raw_polygons ()); } return new_region.release (); diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index c8d5cf92e..7235781e5 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -212,6 +212,9 @@ protected: RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const; RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const; + static void produce_shape_for_strange_polygon (const db::Polygon &poly, db::Shapes &shapes); + static db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector &heap); + private: AsIfFlatRegion &operator= (const AsIfFlatRegion &other); diff --git a/src/db/db/dbCellVariants.h b/src/db/db/dbCellVariants.h index 94e11a34f..11f2fde8d 100644 --- a/src/db/db/dbCellVariants.h +++ b/src/db/db/dbCellVariants.h @@ -87,6 +87,28 @@ struct DB_PUBLIC MagnificationReducer } }; +/** + * @brief A magnification and orientation reducer + * + * This reducer incarnation reduces the transformation to it's rotation/mirror/magnification part (2d matrix) + */ +struct DB_PUBLIC MagnificationAndOrientationReducer +{ + typedef tl::true_tag is_translation_invariant; + + db::ICplxTrans operator () (const db::ICplxTrans &trans) const + { + db::ICplxTrans res (trans); + res.disp (db::Vector ()); + return res; + } + + db::Trans operator () (const db::Trans &trans) const + { + return db::Trans (trans.fp_trans ()); + } +}; + /** * @brief A grid reducer * @@ -125,13 +147,32 @@ private: inline db::Coord mod (db::Coord c) const { if (c < 0) { - return m_grid - (-c) % m_grid; + c = m_grid - (-c) % m_grid; + if (c == m_grid) { + return 0; + } else { + return c; + } } else { return c % m_grid; } } }; +/** + * @brief A base class for the variants collector + */ +class DB_PUBLIC VariantsCollectorBase +{ +public: + VariantsCollectorBase () { } + virtual ~VariantsCollectorBase () { } + + virtual void collect (const db::Layout &layout, const db::Cell &top_cell) = 0; + virtual void separate_variants (db::Layout &layout, db::Cell &top_cell, std::map > *var_table = 0) = 0; + virtual const std::map &variants (db::cell_index_type ci) const = 0; +}; + /** * @brief A class computing variants for cells according to a given criterion * @@ -149,10 +190,20 @@ private: */ template class DB_PUBLIC cell_variants_collector + : public VariantsCollectorBase { public: typedef cell_variants_reduce_traits compare_traits; + /** + * @brief Creates a variant extractor + */ + cell_variants_collector () + : m_red () + { + // .. nothing yet .. + } + /** * @brief Creates a variant extractor */ @@ -165,7 +216,7 @@ public: /** * @brief Collects cell variants for the given layout starting from the top cell */ - void collect (const db::Layout &layout, const db::Cell &top_cell) + virtual void collect (const db::Layout &layout, const db::Cell &top_cell) { // The top cell gets a "variant" with unit transformation m_variants [top_cell.cell_index ()].insert (std::make_pair (db::ICplxTrans (), 1)); @@ -207,7 +258,7 @@ public: * If given, *var_table will be filled with a map giving the new cell and variant against * the old cell for all cells with more than one variant. */ - void separate_variants (db::Layout &layout, db::Cell &top_cell, std::map > *var_table = 0) + virtual void separate_variants (db::Layout &layout, db::Cell &top_cell, std::map > *var_table = 0) { db::LayoutLocker locker (&layout); @@ -309,7 +360,7 @@ public: * The keys of the map are the variants, the values is the instance count of the variant * (as seen from the top cell). */ - const std::map &variants (db::cell_index_type ci) const + virtual const std::map &variants (db::cell_index_type ci) const { std::map >::const_iterator v = m_variants.find (ci); static std::map empty_set; diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc index a07449d89..62f95a4f2 100644 --- a/src/db/db/dbDeepEdgePairs.cc +++ b/src/db/db/dbDeepEdgePairs.cc @@ -243,7 +243,7 @@ EdgePairsDelegate *DeepEdgePairs::filtered (const EdgePairFilterBase &filter) co RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const { - db::DeepLayer new_layer = m_deep_layer.new_layer (); + db::DeepLayer new_layer = m_deep_layer.derived (); db::Layout &layout = const_cast (m_deep_layer.layout ()); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { @@ -261,7 +261,7 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const { - db::DeepLayer new_layer = m_deep_layer.new_layer (); + db::DeepLayer new_layer = m_deep_layer.derived (); db::Layout &layout = const_cast (m_deep_layer.layout ()); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 8ecaef032..e7d1eea13 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -354,7 +354,7 @@ DeepEdges::ensure_merged_edges_valid () const { if (! m_merged_edges_valid) { - m_merged_edges = m_deep_layer.new_layer (); + m_merged_edges = m_deep_layer.derived (); tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons"); @@ -480,7 +480,7 @@ EdgesDelegate *DeepEdges::merged () const db::Layout &layout = const_cast (m_merged_edges.layout ()); - std::auto_ptr res (new db::DeepEdges (m_merged_edges.new_layer ())); + std::auto_ptr res (new db::DeepEdges (m_merged_edges.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { c->shapes (res->deep_layer ().layer ()) = c->shapes (m_merged_edges.layer ()); } diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 14516effb..133e45c2a 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -25,6 +25,7 @@ #include "dbDeepShapeStore.h" #include "dbEmptyRegion.h" #include "dbRegion.h" +#include "dbDeepEdges.h" #include "dbShapeProcessor.h" #include "dbFlatRegion.h" #include "dbHierProcessor.h" @@ -367,7 +368,7 @@ DeepRegion::ensure_merged_polygons_valid () const { if (! m_merged_polygons_valid) { - m_merged_polygons = m_deep_layer.new_layer (); + m_merged_polygons = m_deep_layer.derived (); tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons"); @@ -598,8 +599,7 @@ DeepRegion::area (const db::Box &box) const ensure_merged_polygons_valid (); - db::MagnificationReducer red; - db::cell_variants_collector vars (red); + db::cell_variants_collector vars; vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); DeepRegion::area_type a = 0; @@ -632,8 +632,7 @@ DeepRegion::perimeter (const db::Box &box) const ensure_merged_polygons_valid (); - db::MagnificationReducer red; - db::cell_variants_collector vars (red); + db::cell_variants_collector vars; vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); DeepRegion::perimeter_type p = 0; @@ -688,50 +687,148 @@ DeepRegion::angle_check (double min, double max, bool inverse) const RegionDelegate * DeepRegion::snapped (db::Coord gx, db::Coord gy) { - // NOTE: snap be optimized by forming grid variants etc. - return db::AsIfFlatRegion::snapped (gx, gy); + if (gx <= 0 || gy <= 0) { + throw tl::Exception (tl::to_string (tr ("Snapping requires a positive grid value"))); + } + + if (gx != gy) { + // no way doing this hierarchically ? + return db::AsIfFlatRegion::snapped (gx, gy); + } + + ensure_merged_polygons_valid (); + + db::cell_variants_collector vars (gx); + + vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); + + // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? + const_cast (m_merged_polygons).separate_variants (vars); + + db::Layout &layout = m_merged_polygons.layout (); + std::vector heap; + + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + + 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 db::Shapes &s = c->shapes (m_merged_polygons.layer ()); + db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { + + db::Polygon poly; + si->polygon (poly); + poly.transform (tr); + st.insert (snapped_polygon (poly, gx, gy, heap).transformed (trinv)); + + } + + } + + return res.release (); } Edges DeepRegion::edges (const EdgeFilterBase *filter) const { - // NOTE: needs a deep edge set for optimizing for hierarchy. - // At least the length filter is easy to optimize in the hierarchical case. - return db::AsIfFlatRegion::edges (filter); -} + ensure_merged_polygons_valid (); -RegionDelegate * -DeepRegion::filtered (const PolygonFilterBase &filter) const -{ - if (filter.isotropic ()) { + std::auto_ptr vars; - ensure_merged_polygons_valid (); + if (filter) { - // @@@ scaled instances! + if (filter->isotropic ()) { + vars.reset (new db::cell_variants_collector ()); + } else { + vars.reset (new db::cell_variants_collector ()); + } - db::Layout &layout = m_merged_polygons.layout (); + vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); - for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? + const_cast (m_merged_polygons).separate_variants (*vars); - const db::Shapes &s = c->shapes (m_merged_polygons.layer ()); - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + } - for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { - db::Polygon poly; - si->polygon (poly); - if (filter.selected (poly)) { - st.insert (poly); + db::Layout &layout = m_merged_polygons.layout (); + + std::auto_ptr res (new db::DeepEdges (m_merged_polygons.derived ())); + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + + db::ICplxTrans tr; + if (vars.get ()) { + const std::map &v = vars->variants (c->cell_index ()); + tl_assert (v.size () == size_t (1)); + tr = v.begin ()->first; + } + + const db::Shapes &s = c->shapes (m_merged_polygons.layer ()); + db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { + + db::Polygon poly; + si->polygon (poly); + + for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) { + if (! filter || filter->selected ((*e).transformed (tr))) { + st.insert (*e); } } } - return res.release (); - - } else { - return db::AsIfFlatRegion::filtered (filter); } + + return db::Edges (res.release ()); +} + +RegionDelegate * +DeepRegion::filtered (const PolygonFilterBase &filter) const +{ + ensure_merged_polygons_valid (); + + std::auto_ptr vars; + + if (filter.isotropic ()) { + vars.reset (new db::cell_variants_collector ()); + } else { + vars.reset (new db::cell_variants_collector ()); + } + + vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); + + // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? + const_cast (m_merged_polygons).separate_variants (*vars); + + db::Layout &layout = m_merged_polygons.layout (); + + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + + const std::map &v = vars->variants (c->cell_index ()); + tl_assert (v.size () == size_t (1)); + const db::ICplxTrans &tr = v.begin ()->first; + + const db::Shapes &s = c->shapes (m_merged_polygons.layer ()); + db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { + db::Polygon poly; + si->polygon (poly); + if (filter.selected (poly.transformed (tr))) { + st.insert (poly); + } + } + + } + + return res.release (); } RegionDelegate * @@ -759,7 +856,7 @@ DeepRegion::merged () const db::Layout &layout = const_cast (m_merged_polygons.layout ()); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { c->shapes (res->deep_layer ().layer ()) = c->shapes (m_merged_polygons.layer ()); } @@ -779,8 +876,7 @@ DeepRegion::merged (bool min_coherence, unsigned int min_wc) const RegionDelegate * DeepRegion::strange_polygon_check () const { - // TODO: can probably be optimized - return db::AsIfFlatRegion::strange_polygon_check (); + throw tl::Exception (tl::to_string (tr ("A strange polygon check does not make sense on a processed region - polygons are already normalized"))); } RegionDelegate * @@ -790,14 +886,13 @@ DeepRegion::sized (coord_type d, unsigned int mode) const db::Layout &layout = m_merged_polygons.layout (); - db::MagnificationReducer red; - db::cell_variants_collector vars (red); + db::cell_variants_collector vars; vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? const_cast (m_merged_polygons).separate_variants (vars); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const std::map &v = vars.variants (c->cell_index ()); @@ -858,14 +953,13 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const db::Layout &layout = m_merged_polygons.layout (); - db::XYAnisotropyAndMagnificationReducer red; - db::cell_variants_collector vars (red); + db::cell_variants_collector vars; vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? const_cast (m_merged_polygons).separate_variants (vars); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const std::map &v = vars.variants (c->cell_index ()); @@ -907,7 +1001,7 @@ DeepRegion::holes () const std::vector pts; - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const db::Shapes &s = c->shapes (m_merged_polygons.layer ()); @@ -940,7 +1034,7 @@ DeepRegion::hulls () const std::vector pts; - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const db::Shapes &s = c->shapes (m_merged_polygons.layer ()); @@ -974,8 +1068,7 @@ DeepRegion::rounded_corners (double rinner, double router, unsigned int n) const { ensure_merged_polygons_valid (); - db::MagnificationReducer red; - db::cell_variants_collector vars (red); + db::cell_variants_collector vars; vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? @@ -983,7 +1076,7 @@ DeepRegion::rounded_corners (double rinner, double router, unsigned int n) const db::Layout &layout = m_merged_polygons.layout (); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const std::map &v = vars.variants (c->cell_index ()); @@ -1012,8 +1105,7 @@ DeepRegion::smoothed (coord_type d) const { ensure_merged_polygons_valid (); - db::MagnificationReducer red; - db::cell_variants_collector vars (red); + db::cell_variants_collector vars; vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ()); // NOTE: m_merged_polygons is mutable, so why is the const_cast needed? @@ -1021,7 +1113,7 @@ DeepRegion::smoothed (coord_type d) const db::Layout &layout = m_merged_polygons.layout (); - std::auto_ptr res (new db::DeepRegion (m_merged_polygons.new_layer ())); + std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const std::map &v = vars.variants (c->cell_index ()); @@ -1058,11 +1150,116 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, b return db::AsIfFlatRegion::run_single_polygon_check (rel, d, whole_edges, metrics, ignore_angle, min_projection, max_projection); } +namespace +{ + +class InteractingLocalOperation + : public local_operation +{ +public: + InteractingLocalOperation (int mode, bool touching, bool inverse) + : m_mode (mode), m_touching (touching), m_inverse (inverse) + { + // .. nothing yet .. + } + + virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + { + m_ep.clear (); + + std::set others; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j)); + } + } + + size_t n = 1; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) { + const db::PolygonRef &subject = interactions.subject_shape (i->first); + for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) { + m_ep.insert (*e, n); + } + } + + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) { + m_ep.insert (*e, 0); + } + } + + db::InteractionDetector id (m_mode, 0); + id.set_include_touching (m_touching); + db::EdgeSink es; + m_ep.process (es, id); + id.finish (); + + n = 0; + std::set selected; + for (db::InteractionDetector::iterator i = id.begin (); i != id.end () && i->first == 0; ++i) { + ++n; + selected.insert (i->second); + } + + n = 1; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) { + if ((selected.find (n) == selected.end ()) == m_inverse) { + const db::PolygonRef &subject = interactions.subject_shape (i->first); + result.insert (subject); + } + } + } + + virtual on_empty_intruder_mode on_empty_intruder_hint () const + { + if ((m_mode <= 0) != m_inverse) { + return Drop; + } else { + return Copy; + } + } + + virtual std::string description () const + { + return tl::to_string (tr ("Select regions by their geometric relation (interacting, inside, outside ..)")); + } + +private: + int m_mode; + bool m_touching; + bool m_inverse; + mutable db::EdgeProcessor m_ep; +}; + +} + RegionDelegate * DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const { - // TODO: implement hierarchically - return db::AsIfFlatRegion::selected_interacting_generic (other, mode, touching, inverse); + const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); + if (! other_deep) { + return db::AsIfFlatRegion::selected_interacting_generic (other, mode, touching, inverse); + } + + ensure_merged_polygons_valid (); + + DeepLayer dl_out (m_deep_layer.derived ()); + + db::InteractingLocalOperation op (mode, touching, inverse); + + db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (m_deep_layer.store ()->threads ()); +#if 0 + // with these settings, the resulting polygons are broken again ... + proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ()); + proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ()); +#endif + + proc.run (&op, m_merged_polygons.layer (), other_deep->merged_deep_layer ().layer (), dl_out.layer ()); + + // TODO: mark the results as merged (unless we split - see above) + return new db::DeepRegion (dl_out); } RegionDelegate * diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 3b686d9f7..8eec5ab51 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -241,6 +241,11 @@ private: EdgePairs run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const; RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const; RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const; + + const DeepLayer &merged_deep_layer () const + { + return m_merged_polygons; + } }; } diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index 9dfe32119..fa4f9d355 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -174,13 +174,6 @@ bool DeepLayer::operator== (const DeepLayer &other) const return true; } -DeepLayer -DeepLayer::new_layer() const -{ - db::DeepShapeStore *store = const_cast (mp_store.get ()); - return DeepLayer (store, m_layout, store->layout (m_layout).insert_layer ()); -} - db::Layout & DeepLayer::layout () { diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index d7b792e0f..96dc17af3 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -93,11 +93,6 @@ public: */ bool operator== (const DeepLayer &other) const; - /** - * @brief Creates a new empty layer based on this one - */ - DeepLayer new_layer () const; - /** * @brief Gets the layout object * The return value is guaranteed to be non-null. diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index ee7a5385c..e4cac3b67 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -209,6 +209,7 @@ public: virtual ~EdgeFilterBase () { } virtual bool selected (const db::Edge &edge) const = 0; + virtual bool isotropic () const = 0; }; /** @@ -251,6 +252,11 @@ struct DB_PUBLIC EdgeLengthFilter } } + bool isotropic () const + { + return true; + } + private: length_type m_lmin, m_lmax; bool m_inverse; @@ -274,7 +280,7 @@ struct DB_PUBLIC EdgeOrientationFilter * * @param amin The minimum angle (measured against the x axis) * @param amax The maximum angle (measured against the x axis) - * @param inverse If set to true, only polygons not matching this criterion will be filtered + * @param inverse If set to true, only edges not matching this criterion will be filtered * * This filter will filter out all edges whose angle against x axis * is larger or equal to amin and less than amax. @@ -290,7 +296,7 @@ struct DB_PUBLIC EdgeOrientationFilter * @brief Constructor * * @param a The angle (measured against the x axis) - * @param inverse If set to true, only polygons not matching this criterion will be filtered + * @param inverse If set to true, only edges not matching this criterion will be filtered * * This filter will filter out all edges whose angle against x axis * is equal to a. @@ -323,6 +329,11 @@ struct DB_PUBLIC EdgeOrientationFilter } } + bool isotropic () const + { + return false; + } + private: db::DVector m_emin, m_emax; bool m_inverse; @@ -387,12 +398,55 @@ public: Edges &operator= (const Edges &other); /** - * @brief Constructor from an object + * @brief Constructor from a box * - * Creates an edge set representing a single instance of that object + * Creates an edge set representing the contour of the box */ - template - explicit Edges (const Sh &s) + explicit Edges (const db::Box &s) + : mp_delegate (0) + { + insert (s); + } + + /** + * @brief Constructor from a simple polygon + * + * Creates an edge set representing the contour of the polygon + */ + explicit Edges (const db::SimplePolygon &s) + : mp_delegate (0) + { + insert (s); + } + + /** + * @brief Constructor from a polygon + * + * Creates an edge set representing the contour of the polygon + */ + explicit Edges (const db::Polygon &s) + : mp_delegate (0) + { + insert (s); + } + + /** + * @brief Constructor from a path + * + * Creates an edge set representing the contour of the path + */ + explicit Edges (const db::Path &s) + : mp_delegate (0) + { + insert (s); + } + + /** + * @brief Constructor from an edge + * + * Creates an edge set representing the single edge + */ + explicit Edges (const db::Edge &s) : mp_delegate (0) { insert (s); diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 4130f5d3c..648c39d24 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -25,6 +25,7 @@ #include "dbReader.h" #include "dbTestSupport.h" #include "dbRegion.h" +#include "dbEdges.h" #include "dbDeepShapeStore.h" #include "tlUnitTest.h" #include "tlStream.h" @@ -652,6 +653,178 @@ TEST(11_RoundAndSmoothed) db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au11.gds"); } +TEST(12_GridSnap) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + db::Region r3snapped = r3.snapped (50, 50); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3snapped); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au12.gds"); +} + +TEST(13_Edges) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + db::Edges r3edges = r3.edges (); + + db::EdgeLengthFilter f (0, 500, true); + db::Edges r3edges_filtered = r3.edges (f); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r3edges); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r3edges_filtered); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au13.gds"); +} + +TEST(14_Interacting) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l6 = ly.get_layer (db::LayerProperties (6, 0)); + + db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.selected_interacting (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.selected_not_interacting (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.selected_inside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.selected_not_inside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r2.selected_outside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r2.selected_not_outside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (16, 0)), r2.selected_overlapping (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (17, 0)), r2.selected_not_overlapping (r1)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r6.selected_interacting (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r6.selected_not_interacting (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r6.selected_inside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), r6.selected_not_inside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r6.selected_outside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), r6.selected_not_outside (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), r6.selected_overlapping (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (27, 0)), r6.selected_not_overlapping (r1)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au14.gds"); +} + +TEST(15_Filtered) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_area_peri_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + + db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::RegionAreaFilter af1 (0, 1000000000, false); + db::Region af1_filtered = r1.filtered (af1); + db::RegionAreaFilter af1inv (0, 1000000000, true); + db::Region af1_else = r1.filtered (af1inv); + + { + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), af1_filtered); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), af1_else); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au15a.gds"); + } + + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::RegionBBoxFilter bwf (0, 50000, false, db::RegionBBoxFilter::BoxWidth); + db::RegionBBoxFilter bhf (0, 50000, false, db::RegionBBoxFilter::BoxHeight); + db::Region r2_bwf = r2.filtered (bwf); + db::Region r2_bhf = r2.filtered (bhf); + + { + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2_bwf); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2_bhf); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au15b.gds"); + } +} + TEST(100_Integration) { db::Layout ly; diff --git a/testdata/algo/deep_region_area_peri_l1.gds b/testdata/algo/deep_region_area_peri_l1.gds index e56fc403e..a4064f66a 100644 Binary files a/testdata/algo/deep_region_area_peri_l1.gds and b/testdata/algo/deep_region_area_peri_l1.gds differ diff --git a/testdata/algo/deep_region_au12.gds b/testdata/algo/deep_region_au12.gds new file mode 100644 index 000000000..3c98029ba Binary files /dev/null and b/testdata/algo/deep_region_au12.gds differ diff --git a/testdata/algo/deep_region_au13.gds b/testdata/algo/deep_region_au13.gds new file mode 100644 index 000000000..ade409f90 Binary files /dev/null and b/testdata/algo/deep_region_au13.gds differ diff --git a/testdata/algo/deep_region_au14.gds b/testdata/algo/deep_region_au14.gds new file mode 100644 index 000000000..7a3109d50 Binary files /dev/null and b/testdata/algo/deep_region_au14.gds differ diff --git a/testdata/algo/deep_region_au15a.gds b/testdata/algo/deep_region_au15a.gds new file mode 100644 index 000000000..65b5dd96d Binary files /dev/null and b/testdata/algo/deep_region_au15a.gds differ diff --git a/testdata/algo/deep_region_au15b.gds b/testdata/algo/deep_region_au15b.gds new file mode 100644 index 000000000..da172280c Binary files /dev/null and b/testdata/algo/deep_region_au15b.gds differ