From 50ee44b6e26af9d1172e2f50d16c39c374edb45e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 28 Oct 2020 23:01:54 +0100 Subject: [PATCH] Addressed issue #663 by internal merging of the intruders. --- src/db/db/dbAsIfFlatRegion.cc | 26 ++++++------ src/db/db/dbDeepRegion.cc | 2 +- src/db/db/dbLocalOperationUtils.cc | 15 ------- src/db/db/dbLocalOperationUtils.h | 47 ++++++++++++++++++++-- src/db/db/dbRegionLocalOperations.cc | 53 ++++++++++++++++++++++++- src/db/db/dbRegionLocalOperations.h | 4 +- src/db/unit_tests/dbDeepRegionTests.cc | 37 +++++++++++++++++ testdata/algo/deep_region_au663.gds | Bin 0 -> 874 bytes testdata/algo/issue-663.oas.gz | Bin 0 -> 161 bytes 9 files changed, 149 insertions(+), 35 deletions(-) create mode 100644 testdata/algo/deep_region_au663.gds create mode 100644 testdata/algo/issue-663.oas.gz diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 7c45f04c0..03a5e4e29 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -42,7 +42,7 @@ #include -#define USE_LOCAL_PROCESSOR // @@@ +#define USE_LOCAL_PROCESSOR // comment out for original implementation based on a single scan namespace db { @@ -419,8 +419,8 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, ResultCountingInserter inserter (counted_results); db::box_scanner2 scanner (report_progress (), progress_desc ()); - scanner.reserve1 (size ()); - scanner.reserve2 (other.size ()); + scanner.reserve1 (count ()); + scanner.reserve2 (other.count ()); std::auto_ptr output (new FlatRegion (false)); region_to_edge_interaction_filter filter (inserter, false, counting /*get all in counting mode*/); @@ -497,10 +497,10 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, ResultCountingInserter inserter (counted_results); db::box_scanner2 scanner (report_progress (), progress_desc ()); - scanner.reserve1 (size ()); - scanner.reserve2 (other.size ()); + scanner.reserve1 (count ()); + scanner.reserve2 (other.count ()); - region_to_text_interaction_filter filter (inserter, false, counting /*get all in counting mode*/); + region_to_text_interaction_filter filter (inserter, false, counting /*get all in counting mode*/); AddressablePolygonDelivery p (begin_merged ()); @@ -694,8 +694,8 @@ AsIfFlatRegion::pull_generic (const Edges &other) const #else db::box_scanner2 scanner (report_progress (), progress_desc ()); - scanner.reserve1 (size ()); - scanner.reserve2 (other.size ()); + scanner.reserve1 (count ()); + scanner.reserve2 (other.count ()); std::auto_ptr output (new FlatEdges (false)); region_to_edge_interaction_filter filter (output->raw_edges (), false); @@ -749,8 +749,8 @@ AsIfFlatRegion::pull_generic (const Texts &other) const } db::box_scanner2 scanner (report_progress (), progress_desc ()); - scanner.reserve1 (size ()); - scanner.reserve2 (other.size ()); + scanner.reserve1 (count ()); + scanner.reserve2 (other.count ()); std::auto_ptr output (new FlatTexts (false)); region_to_text_interaction_filter filter (output->raw_texts (), false); @@ -1030,7 +1030,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, check.set_min_projection (min_projection); check.set_max_projection (max_projection); - db::check_local_operation op (check, different_polygons, other != 0, shielded); + db::check_local_operation op (check, different_polygons, other != 0, other->is_merged (), shielded); db::local_processor proc; proc.set_base_verbosity (base_verbosity ()); @@ -1050,7 +1050,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, std::auto_ptr result (new FlatEdgePairs ()); db::box_scanner scanner (report_progress (), progress_desc ()); - scanner.reserve (size () + (other ? other->size () : 0)); + scanner.reserve (count () + (other ? other->count () : 0)); AddressablePolygonDelivery p (begin_merged ()); @@ -1082,7 +1082,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, check.set_max_projection (max_projection); edge2edge_check edge_check (check, *result, different_polygons, other != 0 /*requires different layers*/, shielded); - poly2poly_check poly_check (edge_check); + poly2poly_check poly_check (edge_check); do { scanner.process (poly_check, d, db::box_convert ()); diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 770bde3a7..eb9f95fa9 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1364,7 +1364,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons std::auto_ptr res (new db::DeepEdgePairs (polygons.derived ())); - db::CheckLocalOperation op (check, different_polygons, other_deep != 0, shielded); + db::CheckLocalOperation op (check, different_polygons, other_deep != 0, other->is_merged (), shielded); db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), diff --git a/src/db/db/dbLocalOperationUtils.cc b/src/db/db/dbLocalOperationUtils.cc index c4424af25..c4c248270 100644 --- a/src/db/db/dbLocalOperationUtils.cc +++ b/src/db/db/dbLocalOperationUtils.cc @@ -27,21 +27,6 @@ namespace db { -// ----------------------------------------------------------------------------------------------- -// class PolygonRefGenerator - -PolygonRefGenerator::PolygonRefGenerator (db::Layout *layout, std::unordered_set &polyrefs) - : PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs) -{ - // .. nothing yet .. -} - -void PolygonRefGenerator::put (const db::Polygon &polygon) -{ - tl::MutexLocker locker (&mp_layout->lock ()); - mp_polyrefs->insert (db::PolygonRef (polygon, mp_layout->shape_repository ())); -} - // ----------------------------------------------------------------------------------------------- // class EdgeToEdgeSetGenerator diff --git a/src/db/db/dbLocalOperationUtils.h b/src/db/db/dbLocalOperationUtils.h index d20f50043..1b46b2d92 100644 --- a/src/db/db/dbLocalOperationUtils.h +++ b/src/db/db/dbLocalOperationUtils.h @@ -30,6 +30,7 @@ #include "dbLayout.h" #include "dbPolygonGenerators.h" #include "dbHash.h" +#include "tlThreads.h" #include @@ -63,25 +64,65 @@ private: const Trans m_trans; }; -class DB_PUBLIC PolygonRefGenerator +template +class DB_PUBLIC polygon_ref_generator; + +template <> +class DB_PUBLIC polygon_ref_generator : public PolygonSink { public: /** * @brief Constructor */ - PolygonRefGenerator (db::Layout *layout, std::unordered_set &polyrefs); + polygon_ref_generator (db::Layout *layout, std::unordered_set &polyrefs) + : PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs) + { + // .. nothing yet .. + } /** * @brief Implementation of the PolygonSink interface */ - virtual void put (const db::Polygon &polygon); + void put (const db::Polygon &polygon) + { + tl::MutexLocker locker (&mp_layout->lock ()); + mp_polyrefs->insert (db::PolygonRef (polygon, mp_layout->shape_repository ())); + } private: db::Layout *mp_layout; std::unordered_set *mp_polyrefs; }; +template <> +class DB_PUBLIC polygon_ref_generator + : public PolygonSink +{ +public: + /** + * @brief Constructor + */ + polygon_ref_generator (db::Layout *, std::unordered_set &polygons) + : mp_polygons (&polygons) + { + // .. nothing yet .. + } + + /** + * @brief Implementation of the PolygonSink interface + */ + virtual void put (const db::Polygon &polygon) + { + mp_polygons->insert (polygon); + } + +private: + std::unordered_set *mp_polygons; +}; + +typedef polygon_ref_generator PolygonRefGenerator; + class DB_PUBLIC EdgeToEdgeSetGenerator : public EdgeSink { diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 35322f17b..74d4a8add 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -46,6 +46,31 @@ static inline const db::PolygonRef *push_polygon_to_heap (db::Layout *layout, co return &heap.back (); } +static inline bool needs_merge (const std::unordered_set &polygons) +{ + if (polygons.empty ()) { + return false; + } else if (polygons.size () > 1) { + return true; + } else if (polygons.begin ()->obj ().is_box ()) { + return false; + } else { + return true; + } +} + +static inline bool needs_merge (const std::unordered_set &polygons) +{ + if (polygons.empty ()) { + return false; + } else if (polygons.size () > 1) { + return true; + } else if (polygons.begin ()->is_box ()) { + return false; + } else { + return true; + } +} struct ResultInserter { @@ -117,8 +142,8 @@ private: // --------------------------------------------------------------------------------------------------------------- template -check_local_operation::check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool shielded) - : m_check (check), m_different_polygons (different_polygons), m_has_other (has_other), m_shielded (shielded) +check_local_operation::check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool other_is_merged, bool shielded) + : m_check (check), m_different_polygons (different_polygons), m_has_other (has_other), m_other_is_merged (other_is_merged), m_shielded (shielded) { // .. nothing yet .. } @@ -152,6 +177,30 @@ check_local_operation::compute_local (db::Layout *layout, const shap n += 2; } + // merge the intruders to remove inner edges + + if (! m_other_is_merged && needs_merge (polygons)) { + + db::EdgeProcessor ep; + + ep.clear (); + size_t i = 0; + for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { + for (typename TI::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) { + ep.insert (*e, i); + } + ++i; + } + + polygons.clear (); + + db::polygon_ref_generator ps (layout, polygons); + db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (pg, op); + + } + n = 1; for (typename std::unordered_set::const_iterator o = polygons.begin (); o != polygons.end (); ++o) { scanner.insert (push_polygon_to_heap (layout, *o, heap), n); diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index eed1a9a04..a37e0a8b0 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -27,6 +27,7 @@ #include "dbCommon.h" #include "dbEdgePairRelations.h" #include "dbLocalOperation.h" +#include "dbEdgeProcessor.h" namespace db { @@ -36,7 +37,7 @@ class check_local_operation : public local_operation { public: - check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool shielded); + check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool has_other, bool other_is_merged, bool shielded); virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const; @@ -48,6 +49,7 @@ private: EdgeRelationFilter m_check; bool m_different_polygons; bool m_has_other; + bool m_other_is_merged; bool m_shielded; }; diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index af16aa5a6..1960dcc81 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2228,3 +2228,40 @@ TEST(issue_400_with_region) CHECKPOINT(); db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au400c.gds"); } + +TEST(issue_663_separation_from_inside) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/issue-663.oas.gz"; + 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); + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l10 = ly.get_layer (db::LayerProperties (10, 0)); + unsigned int l11 = ly.get_layer (db::LayerProperties (11, 0)); + + db::DeepShapeStore dss; + + db::Region r1_flat (db::RecursiveShapeIterator (ly, top_cell, l1)); + db::Region r2_flat (db::RecursiveShapeIterator (ly, top_cell, l2)); + + db::Region r1_deep (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::Region r2_deep (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + + db::EdgePairs ep_flat = r1_flat.separation_check (r2_flat, 2000); + db::EdgePairs ep_deep = r1_deep.separation_check (r2_deep, 2000); + + ep_flat.insert_into_as_polygons (&ly, top_cell_index, l10, 0); + ep_deep.insert_into_as_polygons (&ly, top_cell_index, l11, 0); + + CHECKPOINT(); + db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au663.gds"); +} diff --git a/testdata/algo/deep_region_au663.gds b/testdata/algo/deep_region_au663.gds new file mode 100644 index 0000000000000000000000000000000000000000..7832e1081c92ad76f2957371258d0ffa0136ad7b GIT binary patch literal 874 zcmbu7Jxc>Y5I|q{l1oU?M35+Wr6PzJ5b+BP7)0;`3}O)l!NS7Q!XIGkKM-uLOKX|Z zO8g0y78WTiEG>ldCUfhp;044j?j1Atc4lV}A7eTMIa7S4OhBCmGwwSjQ=4&1_uVJdATzG-qRj{=2nEA0^ z{U~}r1Fx^FhEeo636?hQ^|O3fd=g(-4YdzT8z1H$#)pzVg|js{eMo8J+5N-Zhn`os zehbU@DP;~xKI8lhmUyzZ;~`giDQ!Ha>l=6etqXO96PIxOoKiALKGRoQpVF)NmQK#~ z%Wi%BM(<7TOYcvk_4Dr?GX3c#t(VMcFh7~w#+AmCyz5u~S^tOsm-@x{AI|dya$9Z@2gEzO`uOlL16j-