diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 9547a71cf..f2fa65d1b 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -378,28 +378,77 @@ AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &f return new_edge_pairs.release (); } -RegionDelegate * -AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const +namespace { + +class OutputPairHolder { +public: + OutputPairHolder (InteractingOutputMode output_mode, bool merged_semantics) + { + if (output_mode == None) { + return; + } + + if (output_mode == Positive || output_mode == Negative || output_mode == PositiveAndNegative) { + m_positive.reset (new FlatRegion (merged_semantics)); + m_results.push_back (& m_positive->raw_polygons ()); + } else { + m_results.push_back ((db::Shapes *) 0); + } + + if (output_mode == PositiveAndNegative) { + m_negative.reset (new FlatRegion (merged_semantics)); + m_results.push_back (& m_negative->raw_polygons ()); + } + } + + std::pair region_pair () + { + return std::make_pair (m_positive.release (), m_negative.release ()); + } + + const std::vector &results () { return m_results; } + +private: + std::unique_ptr m_positive, m_negative; + std::vector m_results; +}; + +} + +std::pair +AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const +{ + OutputPairHolder oph (output_mode, merged_semantics ()); + + if (output_mode == None) { + return oph.region_pair (); + } + min_count = std::max (size_t (1), min_count); - if (max_count < min_count || other.empty ()) { - if (! inverse) { - return new EmptyRegion (); + // shortcut + if (empty ()) { + if (output_mode == Positive || output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); } else { - return clone (); + return std::make_pair (clone (), clone ()); + } + } else if (max_count < min_count || other.empty ()) { + if (output_mode == Positive) { + return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new EmptyRegion (), clone ()); } - } else if (empty ()) { - return clone (); } bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); -#if defined(USE_LOCAL_PROCESSOR) - db::RegionIterator polygons (begin_merged ()); - db::interacting_with_edge_local_operation op (inverse, min_count, max_count, true); + db::interacting_with_edge_local_operation op (output_mode, min_count, max_count, true); db::local_processor proc; proc.set_base_verbosity (base_verbosity ()); @@ -413,71 +462,42 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, std::vector results; results.push_back (&output->raw_polygons ()); - proc.run_flat (polygons, others, std::vector (), &op, results); + proc.run_flat (polygons, others, std::vector (), &op, oph.results ()); - return output.release (); - -#else - std::unordered_map > counted_results; - ResultCountingInserter inserter (counted_results); - - db::box_scanner2 scanner (report_progress (), progress_desc ()); - scanner.reserve1 (count ()); - scanner.reserve2 (other.count ()); - - std::unique_ptr output (new FlatRegion (false)); - region_to_edge_interaction_filter filter (inserter, false, counting /*get all in counting mode*/); - - AddressablePolygonDelivery p (begin_merged ()); - - for ( ; ! p.at_end (); ++p) { - scanner.insert1 (p.operator-> (), 0); - if (inverse) { - inserter.init (p.operator-> ()); - } - } - - AddressableEdgeDelivery e (counting ? other.addressable_merged_edges () : other.addressable_edges ()); - - for ( ; ! e.at_end (); ++e) { - scanner.insert2 (e.operator-> (), 0); - } - - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - - // select hits based on their count - - for (std::unordered_map >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) { - bool hit = r->second >= min_count && r->second <= max_count; - if (hit != inverse) { - output->insert (*r->first); - } - } - - return output.release (); -#endif + return oph.region_pair (); } -RegionDelegate * -AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const +std::pair +AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { - min_count = std::max (size_t (1), min_count); + OutputPairHolder oph (output_mode, merged_semantics ()); - if (max_count < min_count || other.empty ()) { - if (! inverse) { - return new EmptyRegion (); - } else { - return clone (); - } - } else if (empty ()) { - return clone (); + if (output_mode == None) { + return oph.region_pair (); } -#if defined(USE_LOCAL_PROCESSOR) + min_count = std::max (size_t (1), min_count); + + // shortcut + if (empty ()) { + if (output_mode == Positive || output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (clone (), clone ()); + } + } else if (max_count < min_count || other.empty ()) { + if (output_mode == Positive) { + return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new EmptyRegion (), clone ()); + } + } db::RegionIterator polygons (begin_merged ()); - db::interacting_with_text_local_operation op (inverse, min_count, max_count); + db::interacting_with_text_local_operation op (output_mode, min_count, max_count); db::local_processor proc; proc.set_base_verbosity (base_verbosity ()); @@ -487,84 +507,58 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, std::vector > others; others.push_back (other.begin ()); - std::unique_ptr output (new FlatRegion (merged_semantics ())); - std::vector results; - results.push_back (&output->raw_polygons ()); + proc.run_flat (polygons, others, std::vector (), &op, oph.results ()); - proc.run_flat (polygons, others, std::vector (), &op, results); - - return output.release (); - -#else - bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); - - std::unordered_map > counted_results; - ResultCountingInserter inserter (counted_results); - - db::box_scanner2 scanner (report_progress (), progress_desc ()); - scanner.reserve1 (count ()); - scanner.reserve2 (other.count ()); - - region_to_text_interaction_filter filter (inserter, false, counting /*get all in counting mode*/); - - AddressablePolygonDelivery p (begin_merged ()); - - for ( ; ! p.at_end (); ++p) { - scanner.insert1 (p.operator-> (), 0); - if (inverse) { - inserter.init (p.operator-> ()); - } - } - - AddressableTextDelivery e (other.addressable_texts ()); - - for ( ; ! e.at_end (); ++e) { - scanner.insert2 (e.operator-> (), 0); - } - - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - - // select hits based on their count - - std::unique_ptr output (new FlatRegion (true)); - - for (std::unordered_map >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) { - bool hit = r->second >= min_count && r->second <= max_count; - if (hit != inverse) { - output->insert (*r->first); - } - } - - return output.release (); -#endif + return oph.region_pair (); } -RegionDelegate * -AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const + +std::pair +AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { + OutputPairHolder oph (output_mode, merged_semantics ()); + + if (output_mode == None) { + return oph.region_pair (); + } + min_count = std::max (size_t (1), min_count); // shortcut if (empty ()) { - return clone (); + if (output_mode == Positive || output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (clone (), clone ()); + } } else if (max_count < min_count || other.empty ()) { // clear, if b is empty and // * mode is inside, enclosing or interacting and inverse is false ("inside" or "interacting") // * mode is outside and inverse is true ("not outside") - if ((mode <= 0) != inverse) { - return new EmptyRegion (); + if ((mode <= 0)) { + if (output_mode == Positive) { + return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new EmptyRegion (), clone ()); + } } else { - return clone (); + if (output_mode == Positive) { + return std::make_pair (clone(), (RegionDelegate *) 0); + } else if (output_mode == Negative) { + return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0); + } else { + return std::make_pair (clone (), new EmptyRegion ()); + } } } -#if defined(USE_LOCAL_PROCESSOR) - bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); db::RegionIterator polygons (begin_merged ()); - db::interacting_local_operation op (mode, touching, inverse, min_count, max_count, true); + db::interacting_local_operation op (mode, touching, output_mode, min_count, max_count, true); db::local_processor proc; proc.set_base_verbosity (base_verbosity ()); @@ -574,121 +568,9 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo std::vector > others; others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ()); - std::unique_ptr output (new FlatRegion (merged_semantics ())); - std::vector results; - results.push_back (&output->raw_polygons ()); + proc.run_flat (polygons, others, std::vector (), &op, oph.results ()); - proc.run_flat (polygons, others, std::vector (), &op, results); - - return output.release (); - -#else - db::EdgeProcessor ep (report_progress (), progress_desc ()); - ep.set_base_verbosity (base_verbosity ()); - - size_t n = 0; - size_t nstart = 0; - - if (mode < -1) { - - // in enclosing mode self must be primary and other the secondary. For other - // modes it's the other way round - - for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) { - if (mode > 0 || p->box ().touches (other.bbox ())) { - ep.insert (*p, n); - } - } - - nstart = n; - - } - - if (min_count == size_t (1) && max_count == std::numeric_limits::max ()) { - - if (mode < 0) { - - // NOTE: on "inside" or "enclosing", the other region must be merged - for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) { - if (p->box ().touches (bbox ())) { - ep.insert (*p, n); - } - } - - } else { - - for (RegionIterator p = other.begin (); ! p.at_end (); ++p) { - if (p->box ().touches (bbox ())) { - ep.insert (*p, n); - } - } - - } - - ++n; - - } else { - - // with counting we need to separate the other polygons by different properties - - // cannot only have min_count/max_count in outside mode - tl_assert (mode <= 0); - - for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) { - if (p->box ().touches (bbox ())) { - ep.insert (*p, n); - } - ++n; - } - - } - - if (mode >= -1) { - - nstart = n; - - for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) { - if (mode > 0 || p->box ().touches (other.bbox ())) { - ep.insert (*p, n); - } - } - - } - - // there should be at least one element to look at for primary - tl_assert (nstart > 0); - - db::InteractionDetector id (mode, nstart - 1); - id.set_include_touching (touching); - db::EdgeSink es; - ep.process (es, id); - id.finish (); - - std::unique_ptr output (new FlatRegion (false)); - - std::map interaction_counts; - for (db::InteractionDetector::iterator i = id.begin (); i != id.end () ; ++i) { - if (i->first < nstart && i->second >= nstart) { - interaction_counts [mode < -1 ? i->first : i->second] += 1; - } - } - - output->reserve (n); - - n = (mode < -1 ? 0 : nstart); - for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) { - size_t count = 0; - std::map ::const_iterator c = interaction_counts.find (n); - if (c != interaction_counts.end ()) { - count = c->second; - } - if ((count >= min_count && count <= max_count) != inverse) { - output->insert (*p); - } - } - - return output.release (); -#endif + return oph.region_pair (); } EdgesDelegate * diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index eecec66d3..d2b8ff9e3 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -139,72 +139,107 @@ public: virtual RegionDelegate *selected_outside (const Region &other) const { - return selected_interacting_generic (other, 1, false, false); + return selected_interacting_generic (other, 1, false, Positive, size_t (0), std::numeric_limits::max ()).first; } virtual RegionDelegate *selected_not_outside (const Region &other) const { - return selected_interacting_generic (other, 1, false, true); + return selected_interacting_generic (other, 1, false, Negative, size_t (0), std::numeric_limits::max ()).first; + } + + virtual std::pair selected_outside_pair (const Region &other) const + { + return selected_interacting_generic (other, 1, false, PositiveAndNegative, size_t (0), std::numeric_limits::max ()); } virtual RegionDelegate *selected_inside (const Region &other) const { - return selected_interacting_generic (other, -1, true, false); + return selected_interacting_generic (other, -1, true, Positive, size_t (0), std::numeric_limits::max ()).first; } virtual RegionDelegate *selected_not_inside (const Region &other) const { - return selected_interacting_generic (other, -1, true, true); + return selected_interacting_generic (other, -1, true, Negative, size_t (0), std::numeric_limits::max ()).first; + } + + virtual std::pair selected_inside_pair (const Region &other) const + { + return selected_interacting_generic (other, -1, true, PositiveAndNegative, size_t (0), std::numeric_limits::max ()); } virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, -2, false, false, min_count, max_count); + return selected_interacting_generic (other, -2, false, Positive, min_count, max_count).first; } virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, -2, false, true, min_count, max_count); + return selected_interacting_generic (other, -2, false, Negative, min_count, max_count).first; + } + + virtual std::pair selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const + { + return selected_interacting_generic (other, -2, false, PositiveAndNegative, min_count, max_count); } virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, 0, true, false, min_count, max_count); + return selected_interacting_generic (other, 0, true, Positive, min_count, max_count).first; } virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, 0, true, true, min_count, max_count); + return selected_interacting_generic (other, 0, true, Negative, min_count, max_count).first; + } + + virtual std::pair selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const + { + return selected_interacting_generic (other, 0, true, PositiveAndNegative, min_count, max_count); } virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, false, min_count, max_count); + return selected_interacting_generic (other, Positive, min_count, max_count).first; } virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, true, min_count, max_count); + return selected_interacting_generic (other, Negative, min_count, max_count).first; + } + + virtual std::pair selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const + { + return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count); } virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, false, min_count, max_count); + return selected_interacting_generic (other, Positive, min_count, max_count).first; } virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, true, min_count, max_count); + return selected_interacting_generic (other, Negative, min_count, max_count).first; + } + + virtual std::pair selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const + { + return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count); } virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, 0, false, false, min_count, max_count); + return selected_interacting_generic (other, 0, false, Positive, min_count, max_count).first; } virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, 0, false, true, min_count, max_count); + return selected_interacting_generic (other, 0, false, Negative, min_count, max_count).first; + } + + virtual std::pair selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const + { + return selected_interacting_generic (other, 0, false, PositiveAndNegative, min_count, max_count); } virtual RegionDelegate *pull_inside (const Region &other) const @@ -245,9 +280,9 @@ protected: virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const; virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const; - virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const; - virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const; - virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const; + virtual std::pair selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const; virtual EdgesDelegate *pull_generic (const Edges &other) const; virtual TextsDelegate *pull_generic (const Texts &other) const; diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index d0d175149..db4aedd84 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -1060,13 +1060,13 @@ template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_lo // --------------------------------------------------------------------------------------------- CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) - : compound_region_generic_operation_node (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ()) + : compound_region_generic_operation_node (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, min_count, max_count, b->is_merged ()) { // .. nothing yet .. } CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) - : compound_region_generic_operation_node (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ()) + : compound_region_generic_operation_node (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, min_count, max_count, b->is_merged ()) { // .. nothing yet .. } @@ -1080,7 +1080,7 @@ CompoundRegionInteractOperationNode::generated_description () const // --------------------------------------------------------------------------------------------- CompoundRegionInteractWithEdgeOperationNode::CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count, size_t max_count) - : compound_region_generic_operation_node (&m_op, a, b), m_op (inverse, min_count, max_count, b->is_merged ()) + : compound_region_generic_operation_node (&m_op, a, b), m_op (inverse ? Negative : Positive, min_count, max_count, b->is_merged ()) { // .. nothing yet .. } diff --git a/src/db/db/dbCompoundOperation.h b/src/db/db/dbCompoundOperation.h index 4f211a239..c7d285465 100644 --- a/src/db/db/dbCompoundOperation.h +++ b/src/db/db/dbCompoundOperation.h @@ -753,7 +753,8 @@ public: 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::interacting_local_operation m_op; + typedef db::interacting_local_operation op_type; + op_type m_op; }; class DB_PUBLIC CompoundRegionInteractWithEdgeOperationNode diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index bc49410e9..db74b18ff 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1519,9 +1519,67 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c return res.release (); } -RegionDelegate * -DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const +namespace { + +class InteractingResultHolder +{ +public: + InteractingResultHolder (InteractingOutputMode output_mode, bool is_merged, const db::DeepLayer &polygons) + : m_output_mode (output_mode), m_is_merged (is_merged) + { + if (m_output_mode == Positive || m_output_mode == Negative) { + m_dl1 = db::DeepLayer (polygons.derived ()); + } else if (m_output_mode == PositiveAndNegative) { + m_dl1 = db::DeepLayer (polygons.derived ()); + m_dl2 = db::DeepLayer (polygons.derived ()); + } + } + + std::vector layers () const + { + std::vector l; + if (m_output_mode == Positive || m_output_mode == Negative) { + l.push_back (m_dl1.layer ()); + } else if (m_output_mode == PositiveAndNegative) { + l.push_back (m_dl1.layer ()); + l.push_back (m_dl2.layer ()); + } + return l; + } + + std::pair result_pair () + { + if (m_output_mode == Positive || m_output_mode == Negative) { + db::DeepRegion *res = new db::DeepRegion (m_dl1); + res->set_is_merged (m_is_merged); + return std::pair (res, 0); + } else if (m_output_mode == PositiveAndNegative) { + db::DeepRegion *res1 = new db::DeepRegion (m_dl1); + res1->set_is_merged (m_is_merged); + db::DeepRegion *res2 = new db::DeepRegion (m_dl2); + res2->set_is_merged (m_is_merged); + return std::pair (res1, res2); + } else { + return std::pair (0, 0); + } + } + +private: + InteractingOutputMode m_output_mode; + bool m_is_merged; + DeepLayer m_dl1, m_dl2; +}; + +} + +std::pair +DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const +{ + if (output_mode == None) { + return std::pair (0, 0); + } + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); // with these flag set to true, the resulting polygons are broken again. @@ -1539,9 +1597,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to // NOTE: on "inside" or with counting, the other polygons must be merged const db::DeepLayer &other_polygons = (mode < 0 || counting) ? other_deep->merged_deep_layer () : other_deep->deep_layer (); - DeepLayer dl_out (polygons.derived ()); - - db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count, true); + db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true); db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ()); proc.set_description (progress_desc ()); @@ -1553,17 +1609,16 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); } - proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ()); + bool result_is_merged = (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())); + InteractingResultHolder orh (output_mode, result_is_merged, polygons); - db::DeepRegion *res = new db::DeepRegion (dl_out); - if (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())) { - res->set_is_merged (true); - } - return res; + proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ()); + + return orh.result_pair (); } -RegionDelegate * -DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const +std::pair +DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); @@ -1580,9 +1635,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size const db::DeepLayer &polygons = merged_deep_layer (); - DeepLayer dl_out (polygons.derived ()); - - db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count, true); + db::InteractingWithEdgeLocalOperation op (output_mode, min_count, max_count, true); db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); proc.set_description (progress_desc ()); @@ -1594,13 +1647,12 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); } - proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), dl_out.layer ()); + bool result_is_merged = (! split_after && other.is_merged () && (merged_semantics () || is_merged ())); + InteractingResultHolder orh (output_mode, result_is_merged, polygons); - db::DeepRegion *res = new db::DeepRegion (dl_out); - if (! split_after) { - res->set_is_merged (other.is_merged () && (merged_semantics () || is_merged ())); - } - return res; + proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), orh.layers ()); + + return orh.result_pair (); } RegionDelegate * @@ -1706,8 +1758,9 @@ DeepRegion::pull_generic (const Texts &other) const return res; } -RegionDelegate * -DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const + +std::pair +DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { // with these flag set to true, the resulting polygons are broken again. bool split_after = false; @@ -1722,9 +1775,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size const db::DeepLayer &polygons = merged_deep_layer (); - DeepLayer dl_out (polygons.derived ()); - - db::InteractingWithTextLocalOperation op (inverse, min_count, max_count); + db::InteractingWithTextLocalOperation op (output_mode, min_count, max_count); db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); proc.set_description (progress_desc ()); @@ -1736,13 +1787,12 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); } - proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ()); + bool result_is_merged = (! split_after && (merged_semantics () || is_merged ())); + InteractingResultHolder orh (output_mode, result_is_merged, polygons); - db::DeepRegion *res = new db::DeepRegion (dl_out); - if (! split_after) { - res->set_is_merged (merged_semantics () || is_merged ()); - } - return res; + proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), orh.layers ()); + + return orh.result_pair (); } } diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 138350c07..c15913f2c 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -140,9 +140,9 @@ protected: virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const; virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const; - virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const; - virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const; - virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const; virtual EdgesDelegate *pull_generic (const Edges &other) const; virtual TextsDelegate *pull_generic (const Texts &other) const; diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h index 6e99c8938..89e82c68a 100644 --- a/src/db/db/dbEmptyRegion.h +++ b/src/db/db/dbEmptyRegion.h @@ -108,18 +108,25 @@ public: virtual RegionDelegate *selected_outside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_outside (const Region &) const { return new EmptyRegion (); } + virtual std::pair selected_outside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *selected_inside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_inside (const Region &) const { return new EmptyRegion (); } + virtual std::pair selected_inside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *selected_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); } + virtual std::pair selected_enclosing_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); } + virtual std::pair selected_interacting_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); } + virtual std::pair selected_interacting_pair (const Edges &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *selected_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); } + virtual std::pair selected_interacting_pair (const Texts &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *selected_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); } + virtual std::pair selected_overlapping_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); } virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); } diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 6b534eabb..df90ff1ba 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -1280,6 +1280,14 @@ void local_processor::run (local_operation *op, unsigned run (op, subject_layer, il, ol); } +template +void local_processor::run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector &output_layers) +{ + std::vector ol, il; + il.push_back (intruder_layer); + run (op, subject_layer, il, output_layers); +} + template void local_processor::run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, unsigned int output_layer) { diff --git a/src/db/db/dbHierProcessor.h b/src/db/db/dbHierProcessor.h index 71ecdb311..c65da727f 100644 --- a/src/db/db/dbHierProcessor.h +++ b/src/db/db/dbHierProcessor.h @@ -419,6 +419,7 @@ public: local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set *breakout_cells = 0); local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set *subject_breakout_cells = 0, const std::set *intruder_breakout_cells = 0); void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers); + void run (local_operation *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector &output_layers); void run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, const std::vector &output_layers); void run (local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers, unsigned int output_layer); void compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers) const; diff --git a/src/db/db/dbLocalOperation.h b/src/db/db/dbLocalOperation.h index abf6b4165..972e36c96 100644 --- a/src/db/db/dbLocalOperation.h +++ b/src/db/db/dbLocalOperation.h @@ -54,6 +54,11 @@ enum OnEmptyIntruderHint { */ Copy, + /** + * @brief Copy the subject shape to the second result + */ + CopyToSecond, + /** * @brief Drop the subject shape */ diff --git a/src/db/db/dbPolygonTools.cc b/src/db/db/dbPolygonTools.cc index 1895d69b9..0aa4839d1 100644 --- a/src/db/db/dbPolygonTools.cc +++ b/src/db/db/dbPolygonTools.cc @@ -725,7 +725,7 @@ template DB_PUBLIC void split_polygon<> (const db::DSimplePolygon &polygon, std: // Smoothing tools void -smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector &points, db::Coord d) +smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector &points, db::Coord d, bool keep_hv) { points.clear (); points.reserve (std::distance (from, to)); @@ -781,7 +781,9 @@ smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon bool can_drop = false; - if (db::Coord (p1.distance(p0)) <= d && db::sprod_sign (p2 - p1, p0 - pm1) > 0 && std::abs (db::vprod (p2 - p1, p0 - pm1)) < 0.8 * p2.distance (p1) * p0.distance (pm1)) { + if (keep_hv && (p1.x () == p0.x () || p1.y () == p0.y () || p2.x () == p1.x () || p2.y () == p1.y ())) { + // keep points which participate in either a vertical or horizontal edge + } else if (db::Coord (p1.distance(p0)) <= d && db::sprod_sign (p2 - p1, p0 - pm1) > 0 && std::abs (db::vprod (p2 - p1, p0 - pm1)) < 0.8 * p2.distance (p1) * p0.distance (pm1)) { // jog configurations with small edges are candidates can_drop = true; } else if (db::vprod_sign (p2 - p1, p1 - p0) < 0) { @@ -839,19 +841,19 @@ smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon } db::Polygon -smooth (const db::Polygon &polygon, db::Coord d) +smooth (const db::Polygon &polygon, db::Coord d, bool keep_hv) { db::Polygon new_poly; std::vector new_pts; - smooth_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, d); + smooth_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, d, keep_hv); if (new_pts.size () >= 3) { new_poly.assign_hull (new_pts.begin (), new_pts.end (), false /*don't compress*/); for (unsigned int h = 0; h < polygon.holes (); ++h) { new_pts.clear (); - smooth_contour (polygon.begin_hole (h), polygon.end_hole (h), new_pts, d); + smooth_contour (polygon.begin_hole (h), polygon.end_hole (h), new_pts, d, keep_hv); if (new_pts.size () >= 3) { new_poly.insert_hole (new_pts.begin (), new_pts.end (), false /*don't compress*/); } diff --git a/src/db/db/dbPolygonTools.h b/src/db/db/dbPolygonTools.h index 26f963039..d59188163 100644 --- a/src/db/db/dbPolygonTools.h +++ b/src/db/db/dbPolygonTools.h @@ -449,6 +449,8 @@ db::Polygon DB_PUBLIC compute_rounded (const db::Polygon &poly, double rinner, d */ db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner, double router, unsigned int n); +#define KLAYOUT_SMOOTH_HAS_KEEP_HV 1 + /** * @brief Smooth a contour * @@ -458,13 +460,14 @@ db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner, * @param to The end of the contour * @param new_pts The points that make up the new contour * @param d The distance that determines the smoothing "roughness" + * @param keep_hv If true, vertical and horizontal edges are maintained */ -void DB_PUBLIC smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector &new_pts, db::Coord d); +void DB_PUBLIC smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector &new_pts, db::Coord d, bool keep_hv); /** * @brief Smooth a polygon (apply smoothing to the whole polygon) */ -db::Polygon DB_PUBLIC smooth (const db::Polygon &poly, db::Coord d); +db::Polygon DB_PUBLIC smooth (const db::Polygon &poly, db::Coord d, bool keep_hv); /** * @brief Returns a value indicating whether the polygon is an "strange polygon" diff --git a/src/db/db/dbRegion.cc b/src/db/db/dbRegion.cc index 72f8742c7..605fb1671 100644 --- a/src/db/db/dbRegion.cc +++ b/src/db/db/dbRegion.cc @@ -263,15 +263,15 @@ Region::rounded_corners (double rinner, double router, unsigned int n) const } void -Region::smooth (coord_type d) +Region::smooth (coord_type d, bool keep_hv) { - process (SmoothingProcessor (d)); + process (SmoothingProcessor (d, keep_hv)); } Region -Region::smoothed (coord_type d) const +Region::smoothed (coord_type d, bool keep_hv) const { - return processed (SmoothingProcessor (d)); + return processed (SmoothingProcessor (d, keep_hv)); } void diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index 3ee137c7c..fea1d8e8b 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -267,6 +267,16 @@ public: return mp_delegate; } + /** + * @brief Takes the underlying delegate object + */ + RegionDelegate *take_delegate () + { + RegionDelegate *delegate = mp_delegate; + mp_delegate = 0; + return delegate; + } + /** * @brief Sets the base verbosity * @@ -1132,6 +1142,19 @@ public: return Region (mp_delegate->selected_not_outside (other)); } + /** + * @brief Returns all polygons of this which are completly outside polygons from the other region and the opposite ones at the same time + * + * This method is equivalent to calling selected_outside and selected_not_outside, but faster. + * + * Merged semantics applies. + */ + std::pair selected_outside_differential (const Region &other) const + { + std::pair p = mp_delegate->selected_outside_pair (other); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Selects all polygons of this region which are completly inside polygons from the other region * @@ -1178,6 +1201,19 @@ public: return Region (mp_delegate->selected_not_inside (other)); } + /** + * @brief Returns all polygons of this which are completly inside polygons from the other region and the opposite ones at the same time + * + * This method is equivalent to calling selected_inside and selected_not_inside, but faster. + * + * Merged semantics applies. + */ + std::pair selected_inside_differential (const Region &other) const + { + std::pair p = mp_delegate->selected_inside_pair (other); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Returns all polygons of this which are enclosing polygons from the other region * @@ -1224,6 +1260,19 @@ public: return Region (mp_delegate->selected_not_enclosing (other, min_count, max_count)); } + /** + * @brief Returns all polygons of this which are completly enclosing polygons from the other region and the opposite ones at the same time + * + * This method is equivalent to calling selected_enclosing and selected_not_enclosing, but faster. + * + * Merged semantics applies. + */ + std::pair selected_enclosing_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + std::pair p = mp_delegate->selected_enclosing_pair (other, min_count, max_count); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Selects all polygons of this region which overlap or touch polygons from the other region * @@ -1278,6 +1327,19 @@ public: return Region (mp_delegate->selected_not_interacting (other, min_count, max_count)); } + /** + * @brief Returns all polygons of this which are interacting with polygons from the other region and the opposite ones at the same time + * + * This method is equivalent to calling selected_interacting and selected_not_interacting, but faster. + * + * Merged semantics applies. + */ + std::pair selected_interacting_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + std::pair p = mp_delegate->selected_interacting_pair (other, min_count, max_count); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Selects all polygons of this region which overlap or touch edges from the given edge collection * @@ -1324,6 +1386,19 @@ public: return Region (mp_delegate->selected_not_interacting (other, min_count, max_count)); } + /** + * @brief Returns all polygons of this which are interacting with edges from the other region and the opposite ones at the same time + * + * This method is equivalent to calling selected_interacting and selected_not_interacting, but faster. + * + * Merged semantics applies. + */ + std::pair selected_interacting_differential (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + std::pair p = mp_delegate->selected_interacting_pair (other, min_count, max_count); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Selects all polygons of this region which overlap or touch texts from the text collection * @@ -1370,6 +1445,19 @@ public: return Region (mp_delegate->selected_not_interacting (other, min_count, max_count)); } + /** + * @brief Returns all polygons of this which are interacting with texts from the other region and the opposite ones at the same time + * + * This method is equivalent to calling selected_interacting and selected_not_interacting, but faster. + * + * Merged semantics applies. + */ + std::pair selected_interacting_differential (const Texts &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + std::pair p = mp_delegate->selected_interacting_pair (other, min_count, max_count); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Selects all polygons of this region which overlap polygons from the other region * @@ -1416,6 +1504,19 @@ public: return Region (mp_delegate->selected_not_overlapping (other, min_count, max_count)); } + /** + * @brief Returns all polygons of this which are overlapping polygons from the other region and the opposite ones at the same time + * + * This method is equivalent to calling selected_overlapping and selected_not_overlapping, but faster. + * + * Merged semantics applies. + */ + std::pair selected_overlapping_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + std::pair p = mp_delegate->selected_overlapping_pair (other, min_count, max_count); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Returns all polygons of "other" which are inside polygons of this region * @@ -1518,14 +1619,14 @@ public: /** * @brief Smoothes the region (in-place) */ - void smooth (coord_type d); + void smooth (coord_type d, bool keep_hv); /** * @brief Returns the smoothed region * * @param d The smoothing accuracy */ - Region smoothed (coord_type d) const; + Region smoothed (coord_type d, bool keep_hv) const; /** * @brief Returns the nth polygon diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index 593e4ed1d..a5178f606 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -281,18 +281,25 @@ public: virtual RegionDelegate *selected_outside (const Region &other) const = 0; virtual RegionDelegate *selected_not_outside (const Region &other) const = 0; + virtual std::pair selected_outside_pair (const Region &other) const = 0; virtual RegionDelegate *selected_inside (const Region &other) const = 0; virtual RegionDelegate *selected_not_inside (const Region &other) const = 0; + virtual std::pair selected_inside_pair (const Region &other) const = 0; virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual std::pair selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual std::pair selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0; + virtual std::pair selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0; + virtual std::pair selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual std::pair selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *pull_inside (const Region &other) const = 0; virtual RegionDelegate *pull_interacting (const Region &other) const = 0; virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0; diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 0b5f68c42..4ce824442 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -537,8 +537,8 @@ private: } template -interacting_local_operation::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged) - : m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged) +interacting_local_operation::interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged) + : m_mode (mode), m_touching (touching), m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged) { // .. nothing yet .. } @@ -552,8 +552,13 @@ db::Coord interacting_local_operation::dist () const template void interacting_local_operation::do_compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const { - tl_assert (results.size () == 1); - std::unordered_set &result = results.front (); + if (m_output_mode == None) { + return; + } else if (m_output_mode == Positive || m_output_mode == Negative) { + tl_assert (results.size () == 1); + } else { + tl_assert (results.size () == 2); + } db::EdgeProcessor ep; @@ -652,9 +657,21 @@ void interacting_local_operation::do_compute_local (db::Layout * /*l if (c != interaction_counts.end ()) { count = c->second; } - if ((count >= m_min_count && count <= m_max_count) != m_inverse) { - const TS &subject = interactions.subject_shape (i->first); - result.insert (subject); + bool good = (count >= m_min_count && count <= m_max_count); + if (good) { + if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) { + const TS &subject = interactions.subject_shape (i->first); + results [0].insert (subject); + } + } else { + if (m_output_mode == Negative) { + const TS &subject = interactions.subject_shape (i->first); + // Yes, it's "positive_result" as this is the first one. + results [0].insert (subject); + } else if (m_output_mode == PositiveAndNegative) { + const TS &subject = interactions.subject_shape (i->first); + results [1].insert (subject); + } } } } @@ -663,11 +680,22 @@ template OnEmptyIntruderHint interacting_local_operation::on_empty_intruder_hint () const { - if ((m_mode <= 0) != m_inverse) { - return OnEmptyIntruderHint::Drop; + if ((m_mode <= 0)) { + if (m_output_mode == Positive) { + return OnEmptyIntruderHint::Drop; + } else if (m_output_mode == Negative) { + return OnEmptyIntruderHint::Copy; + } else if (m_output_mode == PositiveAndNegative) { + return OnEmptyIntruderHint::CopyToSecond; + } } else { - return OnEmptyIntruderHint::Copy; + if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) { + return OnEmptyIntruderHint::Copy; + } else if (m_output_mode == Negative) { + return OnEmptyIntruderHint::Drop; + } } + return OnEmptyIntruderHint::Ignore; } template @@ -761,8 +789,8 @@ template class DB_PUBLIC pull_local_operation -interacting_with_edge_local_operation::interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged) - : m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged) +interacting_with_edge_local_operation::interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged) + : m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged) { // .. nothing yet .. } @@ -777,6 +805,14 @@ db::Coord interacting_with_edge_local_operation::dist () const template void interacting_with_edge_local_operation::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const { + if (m_output_mode == None) { + return; + } else if (m_output_mode == Positive || m_output_mode == Negative) { + tl_assert (results.size () == 1); + } else { + tl_assert (results.size () == 2); + } + std::unordered_map counted_results; bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits::max ()); @@ -829,7 +865,7 @@ void interacting_with_edge_local_operation::do_compute_local (db::La const TR *addressable = push_polygon_to_heap (layout, subject, heap); scanner.insert1 (addressable, 0); - if (m_inverse) { + if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) { inserter.init (*addressable); } @@ -839,13 +875,18 @@ void interacting_with_edge_local_operation::do_compute_local (db::La // select hits based on their count - tl_assert (results.size () == 1); - std::unordered_set &result = results.front (); - for (typename std::unordered_map::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) { bool hit = r->second >= m_min_count && r->second <= m_max_count; - if (hit != m_inverse) { - result.insert (r->first); + if (hit) { + if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) { + results [0].insert (r->first); + } + } else { + if (m_output_mode == Negative) { + results [0].insert (r->first); + } else if (m_output_mode == PositiveAndNegative) { + results [1].insert (r->first); + } } } } @@ -853,10 +894,14 @@ void interacting_with_edge_local_operation::do_compute_local (db::La template OnEmptyIntruderHint interacting_with_edge_local_operation::on_empty_intruder_hint () const { - if (!m_inverse) { + if (m_output_mode == Positive) { return OnEmptyIntruderHint::Drop; - } else { + } else if (m_output_mode == Negative) { return OnEmptyIntruderHint::Copy; + } else if (m_output_mode == PositiveAndNegative) { + return OnEmptyIntruderHint::CopyToSecond; + } else { + return OnEmptyIntruderHint::Ignore; } } @@ -1000,8 +1045,8 @@ template class DB_PUBLIC pull_with_text_local_operation -interacting_with_text_local_operation::interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count) - : m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count) +interacting_with_text_local_operation::interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count) + : m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count) { // .. nothing yet .. } @@ -1017,6 +1062,14 @@ db::Coord interacting_with_text_local_operation::dist () const template void interacting_with_text_local_operation::do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const { + if (m_output_mode == None) { + return; + } else if (m_output_mode == Positive || m_output_mode == Negative) { + tl_assert (results.size () == 1); + } else { + tl_assert (results.size () == 2); + } + std::unordered_map counted_results; bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits::max ()); @@ -1042,7 +1095,7 @@ void interacting_with_text_local_operation::do_compute_local (db::La const TR *addressable = push_polygon_to_heap (layout, interactions.subject_shape (i->first), heap); scanner.insert1 (addressable, 0); - if (m_inverse) { + if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) { inserter.init (*addressable); } @@ -1052,13 +1105,19 @@ void interacting_with_text_local_operation::do_compute_local (db::La // select hits based on their count - tl_assert (results.size () == 1); - std::unordered_set &result = results.front (); - for (typename std::unordered_map::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) { bool hit = r->second >= m_min_count && r->second <= m_max_count; - if (hit != m_inverse) { - result.insert (r->first); + if (hit) { + if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) { + results [0].insert (r->first); + } + } else { + if (m_output_mode == Negative) { + // Yes. It's "positive"! This is the first output. + results [0].insert (r->first); + } else if (m_output_mode == PositiveAndNegative) { + results [1].insert (r->first); + } } } } @@ -1066,10 +1125,14 @@ void interacting_with_text_local_operation::do_compute_local (db::La template OnEmptyIntruderHint interacting_with_text_local_operation::on_empty_intruder_hint () const { - if (!m_inverse) { + if (m_output_mode == Positive) { return OnEmptyIntruderHint::Drop; - } else { + } else if (m_output_mode == Negative) { return OnEmptyIntruderHint::Copy; + } else if (m_output_mode == PositiveAndNegative) { + return OnEmptyIntruderHint::CopyToSecond; + } else { + return OnEmptyIntruderHint::Ignore; } } diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 2b3977c25..d3958e15e 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -222,12 +222,16 @@ private: typedef check_local_operation CheckLocalOperation; +enum InteractingOutputMode { + None = 0, Positive = 1, Negative = 2, PositiveAndNegative = 3 +}; + template class interacting_local_operation : public local_operation { public: - interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged); + interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged); virtual db::Coord dist () 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; @@ -237,7 +241,7 @@ public: private: int m_mode; bool m_touching; - bool m_inverse; + InteractingOutputMode m_output_mode; size_t m_min_count, m_max_count; bool m_other_is_merged; }; @@ -268,7 +272,7 @@ class interacting_with_edge_local_operation : public local_operation { public: - interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged); + interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged); virtual db::Coord dist () 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; @@ -276,7 +280,7 @@ public: virtual std::string description () const; private: - bool m_inverse; + InteractingOutputMode m_output_mode; size_t m_min_count, m_max_count; bool m_other_is_merged; }; @@ -303,7 +307,7 @@ class interacting_with_text_local_operation : public local_operation { public: - interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count); + interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count); virtual db::Coord dist () 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; @@ -311,7 +315,7 @@ public: virtual std::string description () const; private: - bool m_inverse; + InteractingOutputMode m_output_mode; size_t m_min_count, m_max_count; }; diff --git a/src/db/db/dbRegionUtils.cc b/src/db/db/dbRegionUtils.cc index 0d2ed0de1..9f0e6f513 100644 --- a/src/db/db/dbRegionUtils.cc +++ b/src/db/db/dbRegionUtils.cc @@ -868,14 +868,14 @@ StrangePolygonCheckProcessor::process (const db::Polygon &poly, std::vector &res) const { - res.push_back (db::smooth (poly, m_d)); + res.push_back (db::smooth (poly, m_d, m_keep_hv)); } // ------------------------------------------------------------------------------------------------------------- diff --git a/src/db/db/dbRegionUtils.h b/src/db/db/dbRegionUtils.h index 89392bd0d..f1da9196d 100644 --- a/src/db/db/dbRegionUtils.h +++ b/src/db/db/dbRegionUtils.h @@ -504,7 +504,7 @@ class DB_PUBLIC SmoothingProcessor : public PolygonProcessorBase { public: - SmoothingProcessor (db::Coord d); + SmoothingProcessor (db::Coord d, bool keep_hv); ~SmoothingProcessor (); virtual void process (const db::Polygon &poly, std::vector &res) const; @@ -517,6 +517,7 @@ public: private: db::Coord m_d; + bool m_keep_hv; db::MagnificationReducer m_vars; }; diff --git a/src/db/db/gsiDeclDbCompoundOperation.cc b/src/db/db/gsiDeclDbCompoundOperation.cc index 05ff115a0..e9699eed7 100644 --- a/src/db/db/gsiDeclDbCompoundOperation.cc +++ b/src/db/db/gsiDeclDbCompoundOperation.cc @@ -185,10 +185,10 @@ static db::CompoundRegionOperationNode *new_strange_polygons_filter (db::Compoun return new db::CompoundRegionProcessingOperationNode (new db::StrangePolygonCheckProcessor (), input, true /*processor is owned*/); } -static db::CompoundRegionOperationNode *new_smoothed (db::CompoundRegionOperationNode *input, db::Coord d) +static db::CompoundRegionOperationNode *new_smoothed (db::CompoundRegionOperationNode *input, db::Coord d, bool keep_hv) { check_non_null (input, "input"); - return new db::CompoundRegionProcessingOperationNode (new db::SmoothingProcessor (d), input, true /*processor is owned*/, d); + return new db::CompoundRegionProcessingOperationNode (new db::SmoothingProcessor (d, keep_hv), input, true /*processor is owned*/, d); } static db::CompoundRegionOperationNode *new_rounded_corners (db::CompoundRegionOperationNode *input, double rinner, double router, unsigned int n) @@ -572,9 +572,10 @@ Class decl_CompoundRegionOperationNode ("db", " "@brief Creates a node extracting strange polygons.\n" "'strange polygons' are ones which cannot be oriented - e.g. '8' shape polygons." ) + - gsi::constructor ("new_smoothed", &new_smoothed, gsi::arg ("input"), gsi::arg ("d"), + gsi::constructor ("new_smoothed", &new_smoothed, gsi::arg ("input"), gsi::arg ("d"), gsi::arg ("keep_hv", false), "@brief Creates a node smoothing the polygons.\n" - "@param d The tolerance to be applied for the smoothing." + "@param d The tolerance to be applied for the smoothing.\n" + "@param keep_hv If true, horizontal and vertical edges are maintained.\n" ) + gsi::constructor ("new_rounded_corners", &new_rounded_corners, gsi::arg ("input"), gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"), "@brief Creates a node generating rounded corners.\n" diff --git a/src/db/db/gsiDeclDbPolygon.cc b/src/db/db/gsiDeclDbPolygon.cc index 76f3315c9..c597112f5 100644 --- a/src/db/db/gsiDeclDbPolygon.cc +++ b/src/db/db/gsiDeclDbPolygon.cc @@ -1602,9 +1602,9 @@ static db::Polygon transformed_icplx_dp (const db::Polygon *p, const db::ICplxTr return p->transformed (t, false /*don't compress*/); } -static db::Polygon smooth (const db::Polygon *p, db::Coord d) +static db::Polygon smooth (const db::Polygon *p, db::Coord d, bool keep_hv) { - return db::smooth (*p, d); + return db::smooth (*p, d, keep_hv); } static db::Polygon minkowsky_sum_pe (const db::Polygon *p, const db::Edge &e, bool rh) @@ -1787,17 +1787,18 @@ Class decl_Polygon ("db", "Polygon", "\n" "This method was introduced in version 0.22.\n" ) + - method_ext ("smooth", &smooth, gsi::arg ("d"), + method_ext ("smooth", &smooth, gsi::arg ("d"), gsi::arg ("keep_hv", false), "@brief Smoothes a polygon\n" "\n" "Remove vertices that deviate by more than the distance d from the average contour.\n" "The value d is basically the roughness which is removed.\n" "\n" "@param d The smoothing \"roughness\".\n" + "@param keep_hv If true, horizontal and vertical edges will be preserved always.\n" "\n" "@return The smoothed polygon.\n" "\n" - "This method was introduced in version 0.23.\n" + "This method was introduced in version 0.23. The 'keep_hv' optional parameter was added in version 0.27.\n" ) + method_ext ("minkowsky_sum", &minkowsky_sum_pe, gsi::arg ("e"), gsi::arg ("resolve_holes"), "@brief Computes the Minkowsky sum of the polygon and an edge\n" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 91ee1dfec..d1e7cdd87 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -610,15 +610,53 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other, ); } +static inline std::vector as_2region_vector (const std::pair &rp) +{ + std::vector res; + res.reserve (2); + res.push_back (db::Region (const_cast (rp.first).take_delegate ())); + res.push_back (db::Region (const_cast (rp.second).take_delegate ())); + return res; +} + static std::vector andnot (const db::Region *r, const db::Region &other) { - std::pair rp = r->andnot (other); + return as_2region_vector (r->andnot (other)); +} - std::vector res; - res.resize (2, db::Region ()); - res [0] = rp.first; - res [1] = rp.second; - return res; +static std::vector split_inside (const db::Region *r, const db::Region &other) +{ + return as_2region_vector (r->selected_inside_differential (other)); +} + +static std::vector split_outside (const db::Region *r, const db::Region &other) +{ + return as_2region_vector (r->selected_outside_differential (other)); +} + +static std::vector split_overlapping (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count) +{ + return as_2region_vector (r->selected_overlapping_differential (other, min_count, max_count)); +} + +static std::vector split_covering (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count) +{ + return as_2region_vector (r->selected_enclosing_differential (other, min_count, max_count)); +} + +static std::vector split_interacting_with_region (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count) +{ + return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count)); +} + +static std::vector split_interacting_with_edges (const db::Region *r, const db::Edges &other, size_t min_count, size_t max_count) +{ + return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count)); +} + +static std::vector split_interacting_with_texts (const db::Region *r, const db::Texts &other, size_t min_count, size_t max_count) +{ + return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count)); } template @@ -681,6 +719,7 @@ int po_any (); extern Class decl_dbShapeCollection; + Class decl_Region (decl_dbShapeCollection, "db", "Region", constructor ("new", &new_v, "@brief Default constructor\n" @@ -903,7 +942,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "polygons which have the given perimeter are returned. If \"inverse\" is true, " "polygons not having the given perimeter are returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_perimeter", with_perimeter2, gsi::arg ("min_perimeter"), gsi::arg ("max_perimeter"), gsi::arg ("inverse"), "@brief Filter the polygons by perimeter\n" @@ -915,7 +954,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"), "@brief Filter the polygons by area\n" @@ -923,7 +962,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "polygons which have the given area are returned. If \"inverse\" is true, " "polygons not having the given area are returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_area", with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), gsi::arg ("inverse"), "@brief Filter the polygons by area\n" @@ -935,7 +974,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_holes", with_holes1, gsi::arg ("nholes"), gsi::arg ("inverse"), "@brief Filters the polygons by their number of holes\n" @@ -943,7 +982,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "polygons which have the given number of holes are returned. If \"inverse\" is true, " "polygons not having the given of holes are returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -957,7 +996,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -967,7 +1006,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "polygons whose bounding box has the given width are returned. If \"inverse\" is true, " "polygons whose bounding box does not have the given width are returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_width", with_bbox_width2, gsi::arg ("min_width"), gsi::arg ("max_width"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width\n" @@ -977,7 +1016,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_height", with_bbox_height1, gsi::arg ("height"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box height\n" @@ -985,7 +1024,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "polygons whose bounding box has the given height are returned. If \"inverse\" is true, " "polygons whose bounding box does not have the given height are returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_height", with_bbox_height2, gsi::arg ("min_height"), gsi::arg ("max_height"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box height\n" @@ -995,7 +1034,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_min", with_bbox_min1, gsi::arg ("dim"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width or height, whichever is smaller\n" @@ -1004,7 +1043,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "are returned. " "If \"inverse\" is true, all polygons not matching this criterion are returned." "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_min", with_bbox_min2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width or height, whichever is smaller\n" @@ -1015,7 +1054,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_max", with_bbox_max1, gsi::arg ("dim"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width or height, whichever is larger\n" @@ -1024,7 +1063,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "are returned. " "If \"inverse\" is true, all polygons not matching this criterion are returned." "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_max", with_bbox_max2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width or height, whichever is larger\n" @@ -1035,7 +1074,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_bbox_aspect_ratio", with_bbox_aspect_ratio1, gsi::arg ("ratio"), gsi::arg ("inverse"), "@brief Filters the polygons by the aspect ratio of their bounding boxes\n" @@ -1046,7 +1085,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "With 'inverse' set to false, this version filters polygons which have a bounding box aspect ratio equal to the given value. " "With 'inverse' set to true, all other polygons will be returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -1062,7 +1101,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -1075,7 +1114,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "With 'inverse' set to false, this version filters polygons which have an area ratio equal to the given value. " "With 'inverse' set to true, all other polygons will be returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -1091,7 +1130,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -1105,7 +1144,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "With 'inverse' set to false, this version filters polygons which have a relative height equal to the given value. " "With 'inverse' set to true, all other polygons will be returned.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -1122,7 +1161,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + @@ -1130,7 +1169,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@brief Returns a region containing those parts of polygons which are \"strange\"\n" "Strange parts of polygons are self-overlapping parts or non-orientable parts (i.e. in the \"8\" configuration).\n" "\n" - "Merged semantics does not apply for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics does not apply for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("snapped", &db::Region::snapped, gsi::arg ("gx"), gsi::arg ("gy"), "@brief Returns the snapped region\n" @@ -1143,7 +1182,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If gx or gy is 0, no snapping happens in that direction.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("scaled_and_snapped", &db::Region::scaled_and_snapped, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"), "@brief Returns the scaled and snapped region\n" @@ -1159,7 +1198,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If gx or gy is 0, the result is brought on a grid of 1.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.26.1." ) + @@ -1171,7 +1210,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "If gx or gy is 0 or less, the grid is not checked in that direction.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_angle", angle_check1, gsi::arg ("angle"), gsi::arg ("inverse"), "@brief Returns markers on every corner with the given angle (or not with the given angle)\n" @@ -1181,7 +1220,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "The edge pair objects returned will contain both edges forming the angle.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("with_angle", angle_check2, gsi::arg ("amin"), gsi::arg ("amax"), gsi::arg ("inverse"), "@brief Returns markers on every corner with an angle of more than amin and less than amax (or the opposite)\n" @@ -1191,7 +1230,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "The edge pair objects returned will contain both edges forming the angle.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("insert", (void (db::Region::*)(const db::Box &)) &db::Region::insert, gsi::arg ("box"), "@brief Inserts a box\n" @@ -1266,7 +1305,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "The boxes will not be merged, so it is possible to determine overlaps " "of these boxes for example.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("extents", &extents1, gsi::arg ("d"), "@brief Returns a region with the enlarged bounding boxes of the polygons\n" @@ -1275,7 +1314,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "The boxes will not be merged, so it is possible to determine overlaps " "of these boxes for example.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("extents", &extents2, gsi::arg ("dx"), gsi::arg ("dy"), "@brief Returns a region with the enlarged bounding boxes of the polygons\n" @@ -1284,7 +1323,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "The boxes will not be merged, so it is possible to determine overlaps " "of these boxes for example.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("extent_refs", &extent_refs, "@hide\n" @@ -1412,9 +1451,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "See \\round_corners for a description of this method. This version returns a new region instead of " "modifying self (out-of-place)." ) + - method ("smooth", &db::Region::smooth, gsi::arg ("d"), + method ("smooth", &db::Region::smooth, gsi::arg ("d"), gsi::arg ("keep_hv", false), "@brief Smoothing\n" "@param d The smoothing tolerance (in database units)\n" + "@param keep_hv If true, horizontal and vertical edges are maintained\n" "\n" "This method will simplify the merged polygons of the region by removing vertexes if the " "resulting polygon stays equivalent with the original polygon. Equivalence is measured " @@ -1423,9 +1463,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "This method modifies the region. \\smoothed is a method that does the same but returns a new " "region without modifying self. Merged semantics applies for this method.\n" ) + - method ("smoothed", &db::Region::smoothed, gsi::arg ("d"), + method ("smoothed", &db::Region::smoothed, gsi::arg ("d"), gsi::arg ("keep_hv", false), "@brief Smoothing\n" "@param d The smoothing tolerance (in database units)\n" + "@param keep_hv If true, horizontal and vertical edges are maintained\n" "\n" "See \\smooth for a description of this method. This version returns a new region instead of " "modifying self (out-of-place). It has been introduced in version 0.25." @@ -1444,7 +1485,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "The mode defines at which bending angle cutoff occurs \n" "(0:>0, 1:>45, 2:>90, 3:>135, 4:>approx. 168, other:>approx. 179)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The result is a set of polygons which may be overlapping, but are not self-\n" "intersecting. Polygons may overlap afterwards because they grew big enough to overlap their neighbors.\n" @@ -1466,7 +1507,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method is equivalent to \"size(d, d, mode)\".\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("size", size_ext, gsi::arg ("d"), "@brief Isotropic sizing (biasing)\n" @@ -1475,7 +1516,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method is equivalent to \"size(d, d, 2)\".\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("sized", (db::Region (db::Region::*) (db::Coord, db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"), "@brief Returns the anisotropically sized region\n" @@ -1484,7 +1525,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method is returns the sized region (see \\size), but does not modify self.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("d"), gsi::arg ("mode"), "@brief Returns the isotropically sized region\n" @@ -1493,7 +1534,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method is returns the sized region (see \\size), but does not modify self.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("sized", sized_ext, gsi::arg ("d"), "@brief Isotropic sizing (biasing)\n" @@ -1502,7 +1543,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method is equivalent to \"sized(d, d, 2)\".\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("andnot", &andnot, gsi::arg ("other"), "@brief Returns the boolean AND and NOT between self and the other region\n" @@ -1599,7 +1640,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons which are covering polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "\n" @@ -1610,18 +1651,28 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons which are not covering polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "\n" "This method has been introduced in version 0.27." ) + + method_ext ("split_covering", &split_covering, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), + "@brief Returns the polygons of this region which are completely covering polygons from the other region and the ones which are not at the same time\n" + "\n" + "@return Two new regions: the first containing the result of \\covering, the second the result of \\not_covering\n" + "\n" + "This method is equivalent to calling \\covering and \\not_covering, but is faster when both results are required.\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n" + "\n" + "This method has been introduced in version 0.27." + ) + method ("select_covering", &db::Region::select_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the polygons of this region which are completely covering polygons from the other region\n" "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "\n" @@ -1632,7 +1683,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "\n" @@ -1643,56 +1694,76 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons which are inside polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("not_inside", &db::Region::selected_not_inside, gsi::arg ("other"), "@brief Returns the polygons of this region which are not completely inside polygons from the other region\n" "\n" "@return A new region containing the polygons which are not inside polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_inside", &split_inside, gsi::arg ("other"), + "@brief Returns the polygons of this region which are completely inside polygons from the other region and the ones which are not at the same time\n" + "\n" + "@return Two new regions: the first containing the result of \\inside, the second the result of \\not_inside\n" + "\n" + "This method is equivalent to calling \\inside and \\not_inside, but is faster when both results are required.\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n" + "\n" + "This method has been introduced in version 0.27." + ) + method ("select_inside", &db::Region::select_inside, gsi::arg ("other"), "@brief Selects the polygons of this region which are completely inside polygons from the other region\n" "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("select_not_inside", &db::Region::select_not_inside, gsi::arg ("other"), "@brief Selects the polygons of this region which are not completely inside polygons from the other region\n" "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("outside", &db::Region::selected_outside, gsi::arg ("other"), "@brief Returns the polygons of this region which are completely outside polygons from the other region\n" "\n" "@return A new region containing the polygons which are outside polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("not_outside", &db::Region::selected_not_outside, gsi::arg ("other"), "@brief Returns the polygons of this region which are not completely outside polygons from the other region\n" "\n" "@return A new region containing the polygons which are not outside polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_outside", &split_outside, gsi::arg ("other"), + "@brief Returns the polygons of this region which are completely outside polygons from the other region and the ones which are not at the same time\n" + "\n" + "@return Two new regions: the first containing the result of \\outside, the second the result of \\not_outside\n" + "\n" + "This method is equivalent to calling \\outside and \\not_outside, but is faster when both results are required.\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n" + "\n" + "This method has been introduced in version 0.27." + ) + method ("select_outside", &db::Region::select_outside, gsi::arg ("other"), "@brief Selects the polygons of this region which are completely outside polygons from the other region\n" "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("select_not_outside", &db::Region::select_not_outside, gsi::arg ("other"), "@brief Selects the polygons of this region which are not completely outside polygons from the other region\n" "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method ("interacting", (db::Region (db::Region::*) (const db::Region &, size_t, size_t) const) &db::Region::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Returns the polygons of this region which overlap or touch polygons from the other region\n" @@ -1704,7 +1775,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons overlapping or touching polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The min_count and max_count arguments have been added in version 0.27.\n" ) + @@ -1718,10 +1789,20 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons not overlapping or touching polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The min_count and max_count arguments have been added in version 0.27.\n" ) + + method_ext ("split_interacting", &split_interacting_with_region, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), + "@brief Returns the polygons of this region which are interacting with polygons from the other region and the ones which are not at the same time\n" + "\n" + "@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n" + "\n" + "This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n" + "\n" + "This method has been introduced in version 0.27." + ) + method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the polygons from this region which overlap or touch polygons from the other region\n" "\n" @@ -1732,7 +1813,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The min_count and max_count arguments have been added in version 0.27.\n" ) + @@ -1746,7 +1827,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The min_count and max_count arguments have been added in version 0.27.\n" ) + @@ -1760,7 +1841,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons overlapping or touching edges from the edge collection\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.25.\n" "The min_count and max_count arguments have been added in version 0.27.\n" @@ -1775,11 +1856,21 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons not overlapping or touching edges from the edge collection\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.25\n" "The min_count and max_count arguments have been added in version 0.27.\n" ) + + method_ext ("split_interacting", &split_interacting_with_edges, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), + "@brief Returns the polygons of this region which are interacting with edges from the other edge collection and the ones which are not at the same time\n" + "\n" + "@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n" + "\n" + "This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n" + "\n" + "This method has been introduced in version 0.27." + ) + method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the polygons from this region which overlap or touch edges from the edge collection\n" "\n" @@ -1790,7 +1881,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.25\n" "The min_count and max_count arguments have been added in version 0.27.\n" @@ -1805,7 +1896,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.25\n" "The min_count and max_count arguments have been added in version 0.27.\n" @@ -1820,7 +1911,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons overlapping or touching texts\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27\n" ) + @@ -1834,10 +1925,20 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons not overlapping or touching texts\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27\n" ) + + method_ext ("split_interacting", &split_interacting_with_texts, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), + "@brief Returns the polygons of this region which are interacting with texts from the other text collection and the ones which are not at the same time\n" + "\n" + "@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n" + "\n" + "This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n" + "\n" + "This method has been introduced in version 0.27." + ) + method ("select_interacting", (db::Region &(db::Region::*) (const db::Texts &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the polygons of this region which overlap or touch texts\n" "\n" @@ -1848,7 +1949,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "selected by this method if the number of texts interacting with the polygon is between min_count and max_count " "(including max_count).\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27\n" ) + @@ -1862,7 +1963,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27\n" ) + @@ -1871,7 +1972,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons overlapping polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The count options have been introduced in version 0.27." ) + @@ -1880,16 +1981,26 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return A new region containing the polygons not overlapping polygons from the other region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The count options have been introduced in version 0.27." ) + + method_ext ("split_overlapping", &split_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), + "@brief Returns the polygons of this region which are overlapping with polygons from the other region and the ones which are not at the same time\n" + "\n" + "@return Two new regions: the first containing the result of \\overlapping, the second the result of \\not_overlapping\n" + "\n" + "This method is equivalent to calling \\overlapping and \\not_overlapping, but is faster when both results are required.\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n" + "\n" + "This method has been introduced in version 0.27." + ) + method ("select_overlapping", &db::Region::select_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the polygons from this region which overlap polygons from the other region\n" "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The count options have been introduced in version 0.27." ) + @@ -1898,7 +2009,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (self)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The count options have been introduced in version 0.27." ) + @@ -1911,7 +2022,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (from other)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.26.1\n" ) + @@ -1921,7 +2032,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (from other)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.26.1\n" ) + @@ -1931,7 +2042,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The region after the polygons have been selected (from other)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.26.1\n" ) + @@ -1941,7 +2052,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The edge collection after the edges have been selected (from other)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.26.1\n" ) + @@ -1951,7 +2062,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "@return The text collection after the texts have been selected (from other)\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27\n" ) + @@ -1972,7 +2083,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "The edge collection returned can be manipulated in various ways. See \\Edges for a description of the " "possibilities of the edge collection.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + factory_ext ("decompose_convex", &decompose_convex, gsi::arg ("preferred_orientation", po_any (), "\\Polygon#PO_any"), "@brief Decomposes the region into convex pieces.\n" @@ -2016,7 +2127,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@brief Returns the holes of the region\n" "This method returns all holes as filled polygons.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "If merge semantics is not enabled, the holes may not be detected if the polygons " "are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) " "in order to merge the polygons and detect holes.\n" @@ -2025,7 +2136,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@brief Returns the hulls of the region\n" "This method returns all hulls as polygons. The holes will be removed (filles). " "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "If merge semantics is not enabled, the hull may also enclose holes if the polygons " "are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) " "in order to merge the polygons and detect holes.\n" @@ -2043,36 +2154,36 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", method_ext ("rectangles", &rectangles, "@brief Returns all polygons which are rectangles\n" "This method returns all polygons in self which are rectangles." - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("non_rectangles", &non_rectangles, "@brief Returns all polygons which are not rectangles\n" "This method returns all polygons in self which are not rectangles." - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("squares", &squares, "@brief Returns all polygons which are squares\n" "This method returns all polygons in self which are squares." - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + method_ext ("non_squares", &non_squares, "@brief Returns all polygons which are not squares\n" "This method returns all polygons in self which are not squares." - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "\n" "This method has been introduced in version 0.27.\n" ) + method_ext ("rectilinear", &rectilinear, "@brief Returns all polygons which are rectilinear\n" "This method returns all polygons in self which are rectilinear." - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("non_rectilinear", &non_rectilinear, "@brief Returns all polygons which are not rectilinear\n" "This method returns all polygons in self which are not rectilinear." - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("break", &break_polygons, gsi::arg ("max_vertex_count"), gsi::arg ("max_area_ratio", 0.0), "@brief Breaks the polygons of the region into smaller ones\n" @@ -2101,7 +2212,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "with a pencil that has the shape of the given region.\n" "\n" "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("minkowsky_sum", &minkowsky_sum_pp, gsi::arg ("p"), "@brief Compute the Minkowsky sum of the region and a polygon\n" @@ -2114,7 +2225,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "the region with a pen that has the shape of the second polygon.\n" "\n" "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("minkowsky_sum", &minkowsky_sum_pb, gsi::arg ("b"), "@brief Compute the Minkowsky sum of the region and a box\n" @@ -2127,7 +2238,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "as the second polygon.\n" "\n" "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("minkowsky_sum", &minkowsky_sum_pc, gsi::arg ("b"), "@brief Compute the Minkowsky sum of the region and a contour of points (a trace)\n" @@ -2141,7 +2252,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "with a pencil that has the shape of the given region.\n" "\n" "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" ) + method_ext ("move", &move_p, gsi::arg ("v"), "@brief Moves the region\n" @@ -2266,7 +2377,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to " "false. In general, this will improve performance somewhat.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded' and 'negative' options have been introduced in version 0.27." ) + @@ -2308,7 +2419,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." ) + @@ -2349,7 +2460,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to " "false. In general, this will improve performance somewhat.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded' and 'negative' options have been introduced in version 0.27." ) + @@ -2391,7 +2502,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." ) + @@ -2434,7 +2545,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." ) + @@ -2477,7 +2588,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." ) + @@ -2520,7 +2631,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." ) + @@ -2563,27 +2674,27 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\n" - "Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." ) + method_ext ("area", &area1, "@brief The area of the region\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "If merged semantics is not enabled, overlapping areas are counted twice.\n" ) + method_ext ("area", &area2, gsi::arg ("rect"), "@brief The area of the region (restricted to a rectangle)\n" "This version will compute the area of the shapes, restricting the computation to the given rectangle.\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "If merged semantics is not enabled, overlapping areas are counted twice.\n" ) + method_ext ("perimeter", &perimeter1, "@brief The total perimeter of the polygons\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "If merged semantics is not enabled, internal edges are counted as well.\n" ) + method_ext ("perimeter", &perimeter2, gsi::arg ("rect"), @@ -2592,7 +2703,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "Edges along the border are handled in a special way: they are counted when they are oriented with their inside " "side toward the rectangle (in other words: outside edges must coincide with the rectangle's border in order to be counted).\n" "\n" - "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "If merged semantics is not enabled, internal edges are counted as well.\n" ) + method ("bbox", &db::Region::bbox, diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 02391876b..46b57bf22 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -733,7 +733,8 @@ TEST(11_RoundAndSmoothed) r1_sized -= r1; db::Region rounded = r1_sized.rounded_corners (3000, 5000, 100); - db::Region smoothed = rounded.smoothed (100); + db::Region smoothed = rounded.smoothed (100, false); + db::Region smoothed_keep_hv = rounded.smoothed (100, true); db::Layout target; unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); @@ -741,6 +742,7 @@ TEST(11_RoundAndSmoothed) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1_sized); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), rounded); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), smoothed); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), smoothed_keep_hv); CHECKPOINT(); db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au11.gds"); diff --git a/src/db/unit_tests/dbPolygonToolsTests.cc b/src/db/unit_tests/dbPolygonToolsTests.cc index 156aa6a8d..1764fd4e7 100644 --- a/src/db/unit_tests/dbPolygonToolsTests.cc +++ b/src/db/unit_tests/dbPolygonToolsTests.cc @@ -1188,8 +1188,8 @@ TEST(100) db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); - EXPECT_EQ (smooth (p, 5).to_string (), "(0,-100;0,0;50,10;100,-10;150,0;150,-100)"); - EXPECT_EQ (smooth (p, 20).to_string (), "(0,-100;0,0;150,0;150,-100)"); + EXPECT_EQ (smooth (p, 5, true).to_string (), "(0,-100;0,0;50,10;100,-10;150,0;150,-100)"); + EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,-100;0,0;150,0;150,-100)"); } // smoothing @@ -1207,8 +1207,8 @@ TEST(101) db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); - EXPECT_EQ (smooth (p, 5).to_string (), "(100,-10;50,10;0,0;0,100;150,100;150,0)"); - EXPECT_EQ (smooth (p, 20).to_string (), "(0,0;0,100;150,100;150,0)"); + EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;50,10;0,0;0,100;150,100;150,0)"); + EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,0;0,100;150,100;150,0)"); } // smoothing @@ -1224,8 +1224,8 @@ TEST(102) db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); - EXPECT_EQ (smooth (p, 20).to_string (), "()"); - EXPECT_EQ (smooth (p, 5).to_string (), "(100,-10;150,0;0,0;50,10)"); + EXPECT_EQ (smooth (p, 20, true).to_string (), "()"); + EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;150,0;0,0;50,10)"); } // smoothing @@ -1251,9 +1251,9 @@ TEST(103) db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); - EXPECT_EQ (smooth (p, 0).to_string (), "(59881,-249925;56852,-237283;56961,-237258;60061,-236492;63152,-235686;66231,-234839;69300,-233952;69407,-233919;73105,-246382;72992,-246417;69760,-247351;66516,-248243;63261,-249092;59995,-249899)"); - EXPECT_EQ (smooth (p, 50).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)"); - EXPECT_EQ (smooth (p, 5000).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)"); + EXPECT_EQ (smooth (p, 0, true).to_string (), "(59881,-249925;56852,-237283;56961,-237258;60061,-236492;63152,-235686;66231,-234839;69300,-233952;69407,-233919;73105,-246382;72992,-246417;69760,-247351;66516,-248243;63261,-249092;59995,-249899)"); + EXPECT_EQ (smooth (p, 50, true).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)"); + EXPECT_EQ (smooth (p, 5000, true).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)"); } // smoothing @@ -1272,7 +1272,8 @@ TEST(104) db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); - EXPECT_EQ (smooth (p, 12).to_string (), "(-244,-942;-942,-246;248,943;943,246)"); + EXPECT_EQ (smooth (p, 12, false).to_string (), "(-244,-942;-942,-246;248,943;943,246)"); + EXPECT_EQ (smooth (p, 12, true).to_string (), "(-245,-942;-942,-247;-942,-246;247,943;248,943;943,246;-244,-942)"); } // smoothing @@ -1292,11 +1293,46 @@ TEST(105) db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); - EXPECT_EQ (smooth (p, 0).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); - EXPECT_EQ (smooth (p, 50).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); - EXPECT_EQ (smooth (p, 80).to_string (), "(0,0;0,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); - EXPECT_EQ (smooth (p, 90).to_string (), "(0,0;100,1100;800,1100;800,1000;2000,1000;2000,0)"); - EXPECT_EQ (smooth (p, 100).to_string (), "(0,0;0,1000;2000,1000;2000,0)"); + EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); + EXPECT_EQ (smooth (p, 50, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); + EXPECT_EQ (smooth (p, 80, false).to_string (), "(0,0;0,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); + EXPECT_EQ (smooth (p, 90, false).to_string (), "(0,0;100,1100;800,1100;800,1000;2000,1000;2000,0)"); + EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;0,1000;2000,1000;2000,0)"); + EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); +} + +// smoothing +TEST(106) +{ + db::Point pattern [] = { + db::Point (0, 0), + db::Point (0, 73235), + db::Point (100, 74568), + db::Point (700, 82468), + db::Point (1200, 90468), + db::Point (2000, 106468), + db::Point (2300, 114468), + db::Point (2700, 130468), + db::Point (2800, 138468), + db::Point (2800, 154468), + db::Point (2700, 162468), + db::Point (2300, 178468), + db::Point (2000, 186468), + db::Point (1200, 202468), + db::Point (700, 210468), + db::Point (100, 218368), + db::Point (0, 219701), + db::Point (0, 272971), + db::Point (126450, 272971), + db::Point (126450, 0), + }; + + db::Polygon p; + p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); + + EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,73235;100,74568;700,82468;1200,90468;2000,106468;2300,114468;2700,130468;2800,138468;2800,154468;2700,162468;2300,178468;2000,186468;1200,202468;700,210468;100,218368;0,219701;0,272971;126450,272971;126450,0)"); + EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;100,74568;1200,90468;2300,114468;2800,138468;2700,162468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)"); + EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,73235;1200,90468;2300,114468;2800,138468;2800,154468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)"); } // rounding @@ -1501,7 +1537,7 @@ TEST(203) in.push_back (pp); ep.simple_merge (in, out, false /*no cut line*/); pp = out.front (); - pp = smooth (pp, 1); + pp = smooth (pp, 1, true); EXPECT_EQ (pp.hull ().size (), size_t (300)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); @@ -1547,7 +1583,7 @@ TEST(204) in.push_back (pp); ep.simple_merge (in, out, false /*no cut line*/); pp = out.front (); - pp = smooth (pp, 1); + pp = smooth (pp, 1, true); EXPECT_EQ (pp.hull ().size (), size_t (200)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); diff --git a/src/db/unit_tests/dbRegionTests.cc b/src/db/unit_tests/dbRegionTests.cc index c8b2334fa..b1a6c41a0 100644 --- a/src/db/unit_tests/dbRegionTests.cc +++ b/src/db/unit_tests/dbRegionTests.cc @@ -354,6 +354,8 @@ TEST(10a) r.set_merged_semantics (false); EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)"); EXPECT_EQ (r.selected_not_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).first.to_string (), "(0,0;0,200;100,200;100,0)"); + EXPECT_EQ (r.selected_interacting_differential (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)"); EXPECT_EQ (db::compare (r.selected_interacting (db::Region (db::Box (db::Point (-20, -20), db::Point (30, 30)))), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), ""); db::Region rr = r; @@ -836,6 +838,8 @@ TEST(18a) EXPECT_EQ (db::compare (o, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true); o = r; EXPECT_EQ (db::compare (o.selected_not_outside (rr), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); + EXPECT_EQ (db::compare (o.selected_outside_differential (rr).first, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true); + EXPECT_EQ (db::compare (o.selected_outside_differential (rr).second, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); EXPECT_EQ (o.selected_outside (rr).count () + o.selected_not_outside (rr).count (), size_t (6)); EXPECT_EQ (o.selected_outside (rr).hier_count () + o.selected_not_outside (rr).hier_count (), size_t (6)); o.select_not_outside (rr); @@ -848,6 +852,8 @@ TEST(18a) EXPECT_EQ (o.to_string (), "(20,30;20,50;40,50;40,30)"); o = r; EXPECT_EQ (db::compare (o.selected_not_inside (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); + EXPECT_EQ (db::compare (o.selected_inside_differential (rr).first, "(20,30;20,50;40,50;40,30)"), true); + EXPECT_EQ (db::compare (o.selected_inside_differential (rr).second, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); EXPECT_EQ (o.selected_inside (rr).count () + o.selected_not_inside (rr).count (), size_t (6)); EXPECT_EQ (o.selected_inside (rr).hier_count () + o.selected_not_inside (rr).hier_count (), size_t (6)); o.select_not_inside (rr); @@ -860,6 +866,8 @@ TEST(18a) EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); o = r; EXPECT_EQ (o.selected_not_interacting (rr).to_string (), "(70,60;70,80;90,80;90,60)"); + EXPECT_EQ (db::compare (o.selected_interacting_differential (rr).first, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); + EXPECT_EQ (db::compare (o.selected_interacting_differential (rr).second, "(70,60;70,80;90,80;90,60)"), true); EXPECT_EQ (o.selected_interacting (rr).count () + o.selected_not_interacting (rr).count (), size_t (6)); EXPECT_EQ (o.selected_interacting (rr).hier_count () + o.selected_not_interacting (rr).hier_count (), size_t (6)); o.select_not_interacting (rr); @@ -872,6 +880,8 @@ TEST(18a) EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); o = r; EXPECT_EQ (db::compare (o.selected_not_overlapping (rr), "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true); + EXPECT_EQ (db::compare (o.selected_overlapping_differential (rr).first, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); + EXPECT_EQ (db::compare (o.selected_overlapping_differential (rr).second, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true); EXPECT_EQ (o.selected_overlapping (rr).count () + o.selected_not_overlapping (rr).count (), size_t (6)); EXPECT_EQ (o.selected_overlapping (rr).hier_count () + o.selected_not_overlapping (rr).hier_count (), size_t (6)); o.select_not_overlapping (rr); @@ -884,6 +894,8 @@ TEST(18a) EXPECT_EQ (o.to_string (), "(0,100;0,130;30,130;30,100)"); o = r; EXPECT_EQ (db::compare (o.selected_not_enclosing (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)"), true); + EXPECT_EQ (db::compare (o.selected_enclosing_differential (rr).first, "(0,100;0,130;30,130;30,100)"), true); + EXPECT_EQ (db::compare (o.selected_enclosing_differential (rr).second, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)"), true); EXPECT_EQ (o.selected_enclosing (rr).count () + o.selected_not_enclosing (rr).count (), size_t (6)); EXPECT_EQ (o.selected_enclosing (rr).hier_count () + o.selected_not_enclosing (rr).hier_count (), size_t (6)); o.select_not_enclosing (rr); @@ -1506,6 +1518,8 @@ TEST(30a) r.set_merged_semantics (false); EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)"); EXPECT_EQ (r.selected_not_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).first.to_string (), "(0,0;0,200;100,200;100,0)"); + EXPECT_EQ (r.selected_interacting_differential (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)"); EXPECT_EQ (db::compare (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)"), true); EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), ""); db::Region rr = r; @@ -1689,6 +1703,8 @@ TEST(34a) r.set_merged_semantics (false); EXPECT_EQ (r.selected_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(0,0;0,200;100,200;100,0)"); EXPECT_EQ (r.selected_not_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(-100,-100;-100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).first.to_string (), "(0,0;0,200;100,200;100,0)"); + EXPECT_EQ (r.selected_interacting_differential (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)"); db::Texts tt; tt.insert (db::Text ("abc", db::Trans (db::Vector (30, 30)))); tt.insert (db::Text ("xyz", db::Trans (db::Vector (-100, 0)))); @@ -1782,6 +1798,7 @@ TEST(35a_interact_with_count_region) EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (rr, 1, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); @@ -1797,6 +1814,7 @@ TEST(35a_interact_with_count_region) EXPECT_EQ (r.selected_not_interacting (rr).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), ""); EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); @@ -1855,6 +1873,7 @@ TEST(35b_interact_with_count_edge) EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (rr, 2, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); @@ -1869,6 +1888,7 @@ TEST(35b_interact_with_count_edge) EXPECT_EQ (r.selected_not_interacting (rr).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), ""); EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); @@ -1926,6 +1946,7 @@ TEST(35c_interact_with_count_text) EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (rr, 2, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); @@ -1940,6 +1961,7 @@ TEST(35c_interact_with_count_text) EXPECT_EQ (r.selected_not_interacting (rr).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), ""); EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); diff --git a/src/drc/drc/built-in-macros/_drc_complex_ops.rb b/src/drc/drc/built-in-macros/_drc_complex_ops.rb index db5607c5b..6e24ce748 100644 --- a/src/drc/drc/built-in-macros/_drc_complex_ops.rb +++ b/src/drc/drc/built-in-macros/_drc_complex_ops.rb @@ -739,16 +739,18 @@ CODE # %DRC% # @name smoothed # @brief Applies smoothing - # @synopsis expression.smoothed(d) + # @synopsis expression.smoothed(d [, keep_hv ]) # - # This operation acts on polygons and applies polygon smoothing with the tolerance d. See \Layer#smoothed for more details. + # This operation acts on polygons and applies polygon smoothing with the tolerance d. 'keep_hv' indicates + # whether horizontal and vertical edges are maintained. Default is 'no' which means such edges may be distorted. + # See \Layer#smoothed for more details. # # The "smoothed" method is available as a plain function or as a method on \DRC# expressions. # The plain function is equivalent to "primary.smoothed". - def smoothed(d) + def smoothed(d, keep_hv = false) @engine._context("smoothed") do - DRCOpNodeFilter::new(@engine, self, :new_smoothed, "smoothed", @engine._make_value(d)) + DRCOpNodeFilter::new(@engine, self, :new_smoothed, "smoothed", @engine._make_value(d), keep_hv) end end diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 8cb066c0b..f6efed20e 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -48,6 +48,8 @@ module DRC @deep = false @netter = nil @netter_data = nil + @total_timer = nil + @drc_progress = nil # initialize the defaults for max_area_ratio, max_vertex_count dss = RBA::DeepShapeStore::new @@ -58,7 +60,7 @@ module DRC @verbose = false - @in_context = false + @in_context = nil end @@ -93,7 +95,7 @@ module DRC def transparent DRCShielded::new(false) end - + def projection_limits(*args) self._context("projection_limits") do if args.size == 0 @@ -211,6 +213,27 @@ module DRC end end + def tile_size(x, y = nil) + DRCTileSize::new(_make_value(x) * self.dbu, _make_value(y || x) * self.dbu) + end + + def tile_step(x, y = nil) + DRCTileStep::new(_make_value(x) * self.dbu, _make_value(y || x) * self.dbu) + end + + def tile_origin(x, y) + DRCTileOrigin::new(_make_value(x) * self.dbu, _make_value(y) * self.dbu) + end + + def tile_count(x, y) + DRCTileCount::new(_make_numeric_value(x), _make_numeric_value(y)) + end + + def tile_boundary(b) + b.is_a?(DRCLayer) || raise("'tile_boundary' requires a layer argument") + DRCTileBoundary::new(b) + end + # %DRC% # @brief Defines SPICE output format (with options) # @name write_spice @@ -455,15 +478,20 @@ module DRC # %DRC% # @name info - # @brief Outputs as message to the logger window + # @brief Outputs as message to the logger or progress window # @synopsis info(message) # @synopsis info(message, indent) # Prints the message to the log window in verbose mode. - # In non-verbose more, nothing is printed. + # In non-verbose more, nothing is printed but a statement is put into the progress window. # \log is a function that always prints a message. def info(arg, indent = 0) - @verbose && log(arg, indent) + if @verbose + log(arg, indent) + else + str = (" " * indent) + arg + RBA::Logger::log(str) + end end # %DRC% @@ -476,7 +504,7 @@ module DRC # verbose mode is enabled. def log(arg, indent = 0) - str = (" " * indent) + arg + str = (" " * indent) + arg if @log_file @log_file.puts(str) else @@ -1828,7 +1856,7 @@ CODE def _wrapper_context(func, *args, &proc) in_context_outer = @in_context begin - @in_context = true + @in_context = func return yield(*args) rescue => ex raise("'" + func + "': " + ex.to_s) @@ -1842,22 +1870,40 @@ CODE return yield(*args) else begin - @in_context = true + @in_context = func return yield(*args) rescue => ex raise("'" + func + "': " + ex.to_s) ensure - @in_context = false + @in_context = nil end end end + def _result_info(res, indent, prefix = "") + if res.is_a?(Array) + res.each_with_index do |a, index| + _result_info(a, indent, "[#{index + 1}] ") + end + elsif res.is_a?(RBA::Region) + info(prefix + "Polygons (raw): #{res.count} (flat) #{res.hier_count} (hierarchical)", indent) + elsif res.is_a?(RBA::Edges) + info(prefix + "Edges: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent) + elsif res.is_a?(RBA::EdgePairs) + info(prefix + "Edge pairs: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent) + elsif res.is_a?(RBA::Texts) + info(prefix + "Texts: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent) + end + end + def run_timed(desc, obj) - log(desc) + info(desc) # enable progress + disable_progress = false if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts) + disable_progress = true obj.enable_progress(desc) end @@ -1867,39 +1913,37 @@ CODE res = yield t.stop - if @verbose + begin + + if @verbose + + # Report result statistics + _result_info(res, 1) + + mem = RBA::Timer::memory_size + if mem > 0 + info("Elapsed: #{'%.3f'%(t.sys+t.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M", 1) + else + info("Elapsed: #{'%.3f'%(t.sys+t.user)}s", 1) + end - # Report result statistics - if res.is_a?(RBA::Region) - info("Polygons (raw): #{res.count} (flat) #{res.hier_count} (hierarchical)", 1) - elsif res.is_a?(RBA::Edges) - info("Edges: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1) - elsif res.is_a?(RBA::EdgePairs) - info("Edge pairs: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1) - elsif res.is_a?(RBA::Texts) - info("Texts: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1) end - mem = RBA::Timer::memory_size - if mem > 0 - info("Elapsed: #{'%.3f'%(t.sys+t.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M", 1) - else - info("Elapsed: #{'%.3f'%(t.sys+t.user)}s", 1) + ensure + + # disable progress again + if disable_progress + obj.disable_progress end end - - # disable progress - if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts) - obj.disable_progress - end res end def _cmd(obj, method, *args) - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do obj.send(method, *args) end end @@ -1929,8 +1973,9 @@ CODE end av = args.size.times.collect { |i| "a#{i}" }.join(", ") tp.queue("_output(res, self.#{method}(#{av}))") - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do tp.execute("Tiled \"#{method}\" in: #{src_line}") + res end else @@ -1940,17 +1985,12 @@ CODE end res = nil - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do res = obj.send(method, *args) end end - # disable progress again - if obj.is_a?(RBA::Region) - obj.disable_progress - end - res end @@ -1984,8 +2024,9 @@ CODE end av = args.size.times.collect { |i| "a#{i}" }.join(", ") tp.queue("var rr = self.#{method}(#{av}); _output(res1, rr[0]); _output(res2, rr[1])") - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do tp.execute("Tiled \"#{method}\" in: #{src_line}") + res end else @@ -1995,17 +2036,12 @@ CODE end res = nil - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do res = obj.send(method, *args) end end - # disable progress again - if obj.is_a?(RBA::Region) - obj.disable_progress - end - res end @@ -2025,8 +2061,9 @@ CODE tp.input("self", obj) tp.threads = (@tt || 1) tp.queue("_output(res, _tile ? self.#{method}(_tile.bbox) : self.#{method})") - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do tp.execute("Tiled \"#{method}\" in: #{src_line}") + res end res = res.value @@ -2038,39 +2075,40 @@ CODE end res = nil - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do res = obj.send(method) end end - # disable progress again - if obj.is_a?(RBA::Region) - obj.disable_progress - end - res end def _rcmd(obj, method, *args) - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do RBA::Region::new(obj.send(method, *args)) end end def _vcmd(obj, method, *args) - run_timed("\"#{method}\" in: #{src_line}", obj) do + run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do obj.send(method, *args) end end - def _start + def _start(macro_path) # clearing the selection avoids some nasty problems view = RBA::LayoutView::current view && view.cancel + @total_timer = RBA::Timer::new + @total_timer.start + + @drc_progress = RBA::AbstractProgress::new("DRC: " + macro_path) + + end def _flush @@ -2210,6 +2248,18 @@ CODE @netter = nil @netter_data = nil + if final + @total_timer.stop + if @verbose + mem = RBA::Timer::memory_size + if mem > 0 + info("Total elapsed: #{'%.3f'%(@total_timer.sys+@total_timer.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M") + else + info("Total elapsed: #{'%.3f'%(@total_timer.sys+@total_timer.user)}s") + end + end + end + if final && @log_file @log_file.close @log_file = nil @@ -2218,6 +2268,10 @@ CODE # force garbage collection GC.start + # unlocks the UI + @drc_progress._destroy + @drc_progress = nil + end end @@ -2526,6 +2580,9 @@ CODE end end + + data + end def make_source(layout, cell = nil, path = nil) diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index b5fa7a3df..f13b8b9c6 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -983,8 +983,8 @@ CODE # @name corners # @brief Selects corners of polygons # @synopsis layer.corners([ options ]) - # @synopsis layer.corners(angle, [ options ]) - # @synopsis layer.corners(amin .. amax, [ options ]) + # @synopsis layer.corners(angle [, options ]) + # @synopsis layer.corners(amin .. amax [, options ]) # # This method produces markers on the corners of the polygons. An angle criterion can be given which # selects corners based on the angle of the connecting edges. Positive angles indicate a left turn @@ -1263,6 +1263,7 @@ CODE self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object| block.call(object.transformed(t)) && new_data.insert(object) end + new_data end DRCLayer::new(@engine, new_data) @@ -1285,7 +1286,7 @@ CODE @engine._wrapper_context("each") do t = RBA::CplxTrans::new(@engine.dbu) - @engine.run_timed("\"select\" in: #{@engine.src_line}", self.data) do + @engine.run_timed("\"each\" in: #{@engine.src_line}", self.data) do self.data.send(self.data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object| block.call(object.transformed(t)) end @@ -1368,10 +1369,11 @@ CODE t = RBA::CplxTrans::new(@engine.dbu) dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu) - @engine.run_timed("\\"select\\" in: " + @engine.src_line, self.data) do + @engine.run_timed("\\"#{f}\\" in: " + @engine.src_line, self.data) do self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object| insert_object_into(new_data, block.call(object.transformed(t)), dbu_trans) end + new_data end DRCLayer::new(@engine, new_data) @@ -1660,6 +1662,7 @@ CODE @engine._context("andnot") do + check_is_layer(other) requires_region other.requires_region @@ -1773,6 +1776,21 @@ CODE # It returns a new layer containing the selected shapes. A version which modifies self # is \select_not_covering. + # %DRC% + # @name split_covering + # @brief Returns the results of \covering and \not_covering at the same time + # @synopsis (a, b) = layer.split_covering(other [, options ]) + # + # This method returns the polygons covering polygons from the other layer in + # one layer and all others in a second layer. This method is equivalent to calling + # \covering and \not_covering, but is faster than doing this in separate steps: + # + # @code + # (covering, not_covering) = l1.split_covering(l2) + # @/code + # + # The options of this method are the same than \covering. + # %DRC% # @name select_covering # @brief Selects shapes or regions of self which completely cover (enclose) one or more shapes from the other region @@ -1849,6 +1867,21 @@ CODE # It returns a new layer containing the selected shapes. A version which modifies self # is \select_not_overlapping. + # %DRC% + # @name split_overlapping + # @brief Returns the results of \overlapping and \not_overlapping at the same time + # @synopsis (a, b) = layer.split_overlapping(other [, options ]) + # + # This method returns the polygons overlapping polygons from the other layer in + # one layer and all others in a second layer. This method is equivalent to calling + # \overlapping and \not_overlapping, but is faster than doing this in separate steps: + # + # @code + # (overlapping, not_overlapping) = l1.split_overlapping(l2) + # @/code + # + # The options of this method are the same than \overlapping. + # %DRC% # @name select_overlapping # @brief Selects shapes or regions of self which overlap shapes from the other region @@ -1923,6 +1956,19 @@ CODE # @/tr # @/table + # %DRC% + # @name split_inside + # @brief Returns the results of \inside and \not_inside at the same time + # @synopsis (a, b) = layer.split_inside(other) + # + # This method returns the polygons inside of polygons from the other layer in + # one layer and all others in a second layer. This method is equivalent to calling + # \inside and \not_inside, but is faster than doing this in separate steps: + # + # @code + # (inside, not_inside) = l1.split_inside(l2) + # @/code + # %DRC% # @name select_inside # @brief Selects shapes or regions of self which are inside the other region @@ -1995,6 +2041,19 @@ CODE # @/tr # @/table + # %DRC% + # @name split_outside + # @brief Returns the results of \outside and \not_outside at the same time + # @synopsis (a, b) = layer.split_outside(other) + # + # This method returns the polygons outside of polygons from the other layer in + # one layer and all others in a second layer. This method is equivalent to calling + # \outside and \not_outside, but is faster than doing this in separate steps: + # + # @code + # (outside, not_outside) = l1.split_outside(l2) + # @/code + # %DRC% # @name select_outside # @brief Selects shapes or regions of self which are outside the other region @@ -2149,6 +2208,21 @@ CODE # @/tr # @/table + # %DRC% + # @name split_interacting + # @brief Returns the results of \interacting and \not_interacting at the same time + # @synopsis (a, b) = layer.split_interacting(other [, options ]) + # + # This method returns the polygons interacting with objects from the other container in + # one layer and all others in a second layer. This method is equivalent to calling + # \interacting and \not_interacting, but is faster than doing this in separate steps: + # + # @code + # (interacting, not_interacting) = l1.split_interacting(l2) + # @/code + # + # The options of this method are the same than \interacting. + # %DRC% # @name select_interacting # @brief Selects shapes or regions of self which touch or overlap shapes from the other region @@ -2192,7 +2266,7 @@ CODE # number of (different) shapes from the other layer. If a min and max count is given, shapes from # self are selected only if they interact with less than min_count or more than max_count different shapes # from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions. - + # %DRC% # @name intersections # @brief Returns the intersection points of intersecting edge segments for two edge collections @@ -2285,6 +2359,7 @@ CODE @engine._context("#{f}") do + check_is_layer(other) if :#{f} != :pull_interacting requires_region other.requires_region @@ -2310,11 +2385,16 @@ CODE %w(| ^ inside not_inside outside not_outside in not_in).each do |f| eval <<"CODE" def #{f}(other) + @engine._context("#{f}") do + requires_same_type(other) requires_edges_or_region + DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) + end + end CODE end @@ -2325,12 +2405,14 @@ CODE @engine._context("#{f}") do + check_is_layer(other) other.requires_edges_texts_or_region if self.data.is_a?(RBA::Texts) other.requires_region else other.requires_edges_or_region end + DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) end @@ -2342,10 +2424,14 @@ CODE %w(+).each do |f| eval <<"CODE" def #{f}(other) + @engine._context("#{f}") do + requires_same_type(other) DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) + end + end CODE end @@ -2356,7 +2442,7 @@ CODE @engine._context("#{f}") do - other.requires_edges_texts_or_region + check_is_layer(other) if self.data.is_a?(RBA::Text) other.requires_region elsif self.data.is_a?(RBA::Region) @@ -2381,6 +2467,7 @@ CODE @engine._context("#{f}") do + check_is_layer(other) requires_edges_texts_or_region if self.data.is_a?(RBA::Text) other.requires_region @@ -2389,6 +2476,7 @@ CODE else other.requires_edges_or_region end + if @engine.is_tiled? self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args)) DRCLayer::new(@engine, self.data) @@ -2402,14 +2490,39 @@ CODE CODE end - %w(overlapping not_overlapping covering not_covering).each do |f| + %w(split_interacting).each do |f| eval <<"CODE" def #{f}(other, *args) + @engine._context("#{f}") do + + check_is_layer(other) + requires_region + other.requires_edges_texts_or_region + + res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args)) + [ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ] + + end + + end +CODE + end + + %w(overlapping not_overlapping covering not_covering).each do |f| + eval <<"CODE" + + def #{f}(other, *args) + + @engine._context("#{f}") do + requires_same_type(other) requires_region + DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(*args))) + end + end CODE end @@ -2424,6 +2537,7 @@ CODE requires_region requires_same_type(other) + if @engine.is_tiled? self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args)) DRCLayer::new(@engine, self.data) @@ -2437,6 +2551,24 @@ CODE CODE end + %w(split_overlapping split_covering).each do |f| + eval <<"CODE" + def #{f}(other, *args) + + @engine._context("#{f}") do + + requires_region + other.requires_region + + res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args)) + [ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ] + + end + + end +CODE + end + %w(inside not_inside outside not_outside).each do |fi| f = "select_" + fi # In tiled mode, there are no modifying versions. Emulate using the non-modifying one. @@ -2447,6 +2579,7 @@ CODE requires_region requires_same_type(other) + if @engine.is_tiled? self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data) DRCLayer::new(@engine, self.data) @@ -2460,14 +2593,39 @@ CODE CODE end + %w(split_inside split_outside).each do |f| + eval <<"CODE" + def #{f}(other) + + @engine._context("#{f}") do + + check_is_layer(other) + requires_region + other.requires_region + + res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data) + [ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ] + + end + + end +CODE + end + %w(inside_part outside_part).each do |f| eval <<"CODE" def #{f}(other) + @engine._context("#{f}") do + + check_is_layer(other) other.requires_region requires_edges + DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) + end + end CODE end @@ -2475,11 +2633,17 @@ CODE %w(intersections).each do |f| eval <<"CODE" def #{f}(other) + @engine._context("#{f}") do + + check_is_layer(other) other.requires_edges requires_edges + DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) + end + end CODE end @@ -3496,6 +3660,180 @@ CODE end CODE end + + # %DRC% + # @name with_density + # @brief Returns tiles whose density is within a given range + # @synopsis layer.with_density(min_value, max_value [, options ]) + # @synopsis layer.with_density(min_value .. max_value [, options ]) + # + # This method runs a tiled analysis over the current layout. It reports the tiles whose density + # is between "min_value" and "max_value". "min_value" and "max_value" are given in + # relative units, i.e. within the range of 0 to 1.0 corresponding to a density of 0 to 100%. + # + # "min_value" or "max_value" can be nil or omitted in the ".." range notation. + # In this case, they are taken as "0" and "100%". + # + # The tile size must be specified with the "tile_size" option: + # + # @code + # # reports areas where layer 1/0 density is below 10% on 20x20 um tiles + # low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um)) + # @/code + # + # Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)". + # The first value is the horizontal tile dimension, the second value is the vertical tile + # dimension. + # + # A tile overlap can be specified using "tile_step". If the tile step is less than the + # tile size, the tiles will overlap. The layout window given by "tile_size" is moved + # in increments of the tile step: + # + # @code + # # reports areas where layer 1/0 density is below 10% on 30x30 um tiles + # # with a tile step of 20x20 um: + # low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um)) + # @/code + # + # For "tile_step", anisotropic values can be given as well by using two values: the first for the + # horizontal and the second for the vertical tile step. + # + # Another option is "tile_origin" which specifies the location of the first tile's position. + # This is the lower left tile's lower left corner. If no origin is given, the tiles are centered over the + # area investigated. + # + # By default, the tiles will cover the bounding box of the input layer. A separate layer + # can be used in addition. This way, the layout's dimensions can be derived from some + # drawn boundary layer. To specify a separate, additional layer included in the bounding box, use the "tile_boundary" option: + # + # @code + # # reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from + # # layer 0/0: + # cell_frame = input(0, 0) + # low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame)) + # @/code + # + # Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box. + # The computed area is at least the area of the input layer. + # + # Computation of the area can be skipped by explicitly giving a tile count in horizontal and vertical + # direction. With the "tile_origin" option this allows full control over the area covered: + # + # @code + # # reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000 + # # (100 and 150 tiles of 20 um each are used in horizontal and vertical direction): + # low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150)) + # @/code + # + # The complementary version of "with_density" is \without_density. + + # %DRC% + # @name without_density + # @brief Returns tiles whose density is not within a given range + # @synopsis layer.without_density(min_value, max_value [, options ]) + # @synopsis layer.without_density(min_value .. max_value [, options ]) + # + # For details about the operations and the operation see \with_density. This version will return the + # tiles where the density is not within the given range. + + def _with_density(method, inverse, *args) + + requires_region + + limits = [ nil, nil ] + nlimits = 0 + tile_size = nil + tile_step = nil + tile_origin = nil + tile_count = nil + tile_boundary = nil + + n = 1 + args.each do |a| + if a.is_a?(DRCTileSize) + tile_size = a.get + elsif a.is_a?(DRCTileStep) + tile_step = a.get + elsif a.is_a?(DRCTileOrigin) + tile_origin = a.get + elsif a.is_a?(DRCTileCount) + tile_count = a.get + elsif a.is_a?(DRCTileBoundary) + tile_boundary = a.get + elsif a.is_a?(Float) || a.is_a?(1.class) || a == nil + nlimits < 2 || raise("Too many values specified") + limits[nlimits] = @engine._make_numeric_value_with_nil(a) + nlimits += 1 + elsif a.is_a?(Range) + nlimits == 0 || raise("Either a range or two limits have to be specified, not both") + limits = [ @engine._make_numeric_value_with_nil(a.begin), @engine._make_numeric_value_with_nil(a.end) ] + nlimits = 2 + else + raise("Parameter #" + n.to_s + " does not have an expected type") + end + n += 1 + end + + tile_size || raise("At least the tile_size option needs to be present") + tile_step ||= tile_size + + tp = RBA::TilingProcessor::new + tp.dbu = @engine.dbu + tp.scale_to_dbu = false + tp.tile_size(*tile_step) + if tile_size != tile_step + xb = 0.5 * (tile_size[0] - tile_step[0]) + yb = 0.5 * (tile_size[1] - tile_step[1]) + tp.tile_border(xb, yb) + tp.var("xoverlap", xb / tp.dbu) + tp.var("yoverlap", yb / tp.dbu) + else + tp.var("xoverlap", 0) + tp.var("yoverlap", 0) + end + if tile_origin + tp.tile_origin(*tile_origin) + end + if tile_count + tp.tiles(*tile_count) + end + + res = RBA::Region.new + tp.output("res", res) + tp.input("input", self.data) + tp.threads = (@engine.threads || 1) + if tile_boundary + tp.input("boundary", tile_boundary.data) + end + + tp.var("vmin", limits[0] || 0.0) + tp.var("vmax", limits[1] || 1.0) + tp.var("inverse", inverse) + tp.queue(<<"TP_SCRIPT") + _tile && ( + var bx = _tile.bbox.enlarged(xoverlap, yoverlap); + var d = to_f(input.area(bx)) / to_f(bx.area); + ((d > vmin - 1e-10 && d < vmax + 1e-10) != inverse) && _output(res, bx, false) + ) +TP_SCRIPT + + @engine.run_timed("\"#{method}\" in: #{@engine.src_line}", self.data) do + tp.execute("Tiled \"#{method}\" in: #{@engine.src_line}") + res + end + + DRCLayer::new(@engine, res) + + end + + def with_density(*args) + self._with_density("with_density", false, *args) + end + + def without_density(*args) + self._with_density("without_density", true, *args) + end + # %DRC% # @name scaled @@ -3915,6 +4253,10 @@ CODE @data = d end + def check_is_layer(other) + other.is_a?(DRCLayer) || raise("Argument needs to be a DRC layer") + end + def requires_region self.data.is_a?(RBA::Region) || raise("Requires a polygon layer") end diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index fb9c051fc..c6070cef1 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -180,6 +180,56 @@ module DRC @value end end + + # A wrapper for the tile_size option + class DRCTileSize + def initialize(*args) + @xy = args + end + def get + @xy + end + end + + # A wrapper for the tile_step option + class DRCTileStep + def initialize(*args) + @xy = args + end + def get + @xy + end + end + + # A wrapper for the tile_origin option + class DRCTileOrigin + def initialize(*args) + @xy = args + end + def get + @xy + end + end + + # A wrapper for the tile_count option + class DRCTileCount + def initialize(*args) + @xy = args + end + def get + @xy + end + end + + # A wrapper for the tile_boundary option + class DRCTileBoundary + def initialize(layer) + @b = layer + end + def get + @b + end + end end diff --git a/src/drc/drc/built-in-macros/drc_interpreters.lym b/src/drc/drc/built-in-macros/drc_interpreters.lym index f1affc3d7..cea344114 100644 --- a/src/drc/drc/built-in-macros/drc_interpreters.lym +++ b/src/drc/drc/built-in-macros/drc_interpreters.lym @@ -19,13 +19,10 @@ module DRC def DRC.execute_drc(macro, generator, rdb_index = nil) - timer = RBA::Timer::new - timer.start drc = DRCEngine::new drc._rdb_index = rdb_index drc._generator = generator - - drc_progress = RBA::AbstractProgress::new("DRC: " + macro.path) + drc._start(macro.path) begin @@ -48,14 +45,8 @@ module DRC # cleans up and creates layout and report views drc._finish - # unlocks the UI - drc_progress._destroy - end - timer.stop - drc.info("Total run time: #{'%.3f'%(timer.sys+timer.user)}s") - end # A DSL implementation for a DRC language (XML format) diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index b3215743f..b1508b821 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1163,3 +1163,8 @@ TEST(29d_holes) run_test (_this, "29", true); } +TEST(30_density) +{ + run_test (_this, "30", false); +} + diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index 50a5ba131..5d44adb74 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -1387,7 +1387,7 @@ MainService::cm_round_corners () std::vector in; ep.merge (primary, in, 0 /*min_wc*/, false /*resolve holes*/, true /*min coherence*/); for (std::vector ::iterator p = in.begin (); p != in.end (); ++p) { - *p = smooth (*p, 1); + *p = smooth (*p, 1, true); } std::vector out = in; diff --git a/src/lay/lay/doc/about/drc_ref_drc.xml b/src/lay/lay/doc/about/drc_ref_drc.xml index 16683f7cb..dc30e7fe4 100644 --- a/src/lay/lay/doc/about/drc_ref_drc.xml +++ b/src/lay/lay/doc/about/drc_ref_drc.xml @@ -72,6 +72,7 @@ The following global functions are relevant for the DRC expressions:
  • space
  • squares
  • width
  • +
  • with_holes
  • The following documentation will list the methods available for DRC expression objects. @@ -921,6 +922,22 @@ out = in.drc(primary.squares) # equivalent This method acts on edge expressions and delivers a specific part of each edge. See layer#start_segments for details about this functionality.

    +

    "with_holes" - Selects all input polygons with the specified number of holes

    + +

    Usage:

    +
      +
    • expression.with_holes (in condition)
    • +
    +

    +This operation can be used as a plain function in which case it acts on primary +shapes or can be used as method on another DRC expression. +The following example selects all polygons with more than 2 holes: +

    +

    +out = in.drc(with_holes > 2)
    +out = in.drc(primary.with_holes > 2)   # equivalent
    +
    +

    "|" - Boolean OR between the results of two expressions

    Usage:

    diff --git a/src/lay/lay/doc/about/drc_ref_global.xml b/src/lay/lay/doc/about/drc_ref_global.xml index 6cff08384..48877b955 100644 --- a/src/lay/lay/doc/about/drc_ref_global.xml +++ b/src/lay/lay/doc/about/drc_ref_global.xml @@ -738,7 +738,7 @@ This function will evaluate the conditions c1 to cn and return the current primary shape if all conditions renders an empty result. See
    if_all for an example how to use the if_... functions.

    -

    "info" - Outputs as message to the logger window

    +

    "info" - Outputs as message to the logger or progress window

    Usage:

    Prints the message to the log window in verbose mode. -In non-verbose more, nothing is printed. +In non-verbose more, nothing is printed but a statement is put into the progress window. log is a function that always prints a message.

    "input" - Fetches the shapes from the specified input from the default source

    @@ -1775,6 +1775,15 @@ In verbose mode, more output is generated in the log file

    In verbose mode, more output is generated in the log file

    +

    "warn" - Prints a warning

    + +

    Usage:

    +
      +
    • warn(message)
    • +
    +

    +Similar to log, but the message is printed formatted as a warning +

    "width" - Performs a width check

    Usage:

    @@ -1847,6 +1856,17 @@ shape.

    +

    "with_holes" - Selects all input polygons according to their number of holes in DRC expressions

    + +

    Usage:

    +
      +
    • with_holes (in condition)
    • +
    +

    +"with_holes" represents a polygon selector for +DRC expressions selecting polygons of the primary by their number of holes +(see Layer#drc and DRC#with_holes for more details). +

    "write_spice" - Defines SPICE output format (with options)

    Usage:

    diff --git a/src/lay/lay/doc/about/drc_ref_layer.xml b/src/lay/lay/doc/about/drc_ref_layer.xml index f0964154e..b0bfbca96 100644 --- a/src/lay/lay/doc/about/drc_ref_layer.xml +++ b/src/lay/lay/doc/about/drc_ref_layer.xml @@ -247,8 +247,8 @@ deliver objects that can be converted into polygons. Such objects are of class <

    Usage:

    • layer.corners([ options ])
    • -
    • layer.corners(angle, [ options ])
    • -
    • layer.corners(amin .. amax, [ options ])
    • +
    • layer.corners(angle [, options ])
    • +
    • layer.corners(amin .. amax [, options ])

    This method produces markers on the corners of the polygons. An angle criterion can be given which @@ -2659,6 +2659,87 @@ The following image shows the effect of the space check:

    +

    "split_covering" - Returns the results of covering and not_covering at the same time

    + +

    Usage:

    +
      +
    • (a, b) = layer.split_covering(other [, options ])
    • +
    +

    +This method returns the polygons covering polygons from the other layer in +one layer and all others in a second layer. This method is equivalent to calling +covering and not_covering, but is faster than doing this in separate steps: +

    +

    +(covering, not_covering) = l1.split_covering(l2)
    +
    +

    +The options of this method are the same than covering. +

    +

    "split_inside" - Returns the results of inside and not_inside at the same time

    + +

    Usage:

    +
      +
    • (a, b) = layer.split_inside(other)
    • +
    +

    +This method returns the polygons inside of polygons from the other layer in +one layer and all others in a second layer. This method is equivalent to calling +inside and not_inside, but is faster than doing this in separate steps: +

    +

    +(inside, not_inside) = l1.split_inside(l2)
    +
    +

    +

    "split_interacting" - Returns the results of interacting and not_interacting at the same time

    + +

    Usage:

    +
      +
    • (a, b) = layer.split_interacting(other [, options ])
    • +
    +

    +This method returns the polygons interacting with objects from the other container in +one layer and all others in a second layer. This method is equivalent to calling +interacting and not_interacting, but is faster than doing this in separate steps: +

    +

    +(interacting, not_interacting) = l1.split_interacting(l2)
    +
    +

    +The options of this method are the same than interacting. +

    +

    "split_outside" - Returns the results of outside and not_outside at the same time

    + +

    Usage:

    +
      +
    • (a, b) = layer.split_outside(other)
    • +
    +

    +This method returns the polygons outside of polygons from the other layer in +one layer and all others in a second layer. This method is equivalent to calling +outside and not_outside, but is faster than doing this in separate steps: +

    +

    +(outside, not_outside) = l1.split_outside(l2)
    +
    +

    +

    "split_overlapping" - Returns the results of overlapping and not_overlapping at the same time

    + +

    Usage:

    +
      +
    • (a, b) = layer.split_overlapping(other [, options ])
    • +
    +

    +This method returns the polygons overlapping polygons from the other layer in +one layer and all others in a second layer. This method is equivalent to calling +overlapping and not_overlapping, but is faster than doing this in separate steps: +

    +

    +(overlapping, not_overlapping) = l1.split_overlapping(l2)
    +
    +

    +The options of this method are the same than overlapping. +

    "squares" - Selects all squares from the input

    Usage:

    @@ -3074,6 +3155,86 @@ bounding box.

    This method is available for polygon layers only.

    +

    "with_density" - Returns tiles whose density is within a given range

    + +

    Usage:

    +
      +
    • layer.with_density(min_value, max_value [, options ])
    • +
    • layer.with_density(min_value .. max_value [, options ])
    • +
    +

    +This method runs a tiled analysis over the current layout. It reports the tiles whose density +is between "min_value" and "max_value". "min_value" and "max_value" are given in +relative units, i.e. within the range of 0 to 1.0 corresponding to a density of 0 to 100%. +

    +"min_value" or "max_value" can be nil or omitted in the ".." range notation. +In this case, they are taken as "0" and "100%". +

    +The tile size must be specified with the "tile_size" option: +

    +

    +# reports areas where layer 1/0 density is below 10% on 20x20 um tiles
    +low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um))
    +
    +

    +Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)". +The first value is the horizontal tile dimension, the second value is the vertical tile +dimension. +

    +A tile overlap can be specified using "tile_step". If the tile step is less than the +tile size, the tiles will overlap. The layout window given by "tile_size" is moved +in increments of the tile step: +

    +

    +# reports areas where layer 1/0 density is below 10% on 30x30 um tiles
    +# with a tile step of 20x20 um:
    +low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
    +
    +

    +For "tile_step", anisotropic values can be given as well by using two values: the first for the +horizontal and the second for the vertical tile step. +

    +Another option is "tile_origin" which specifies the location of the first tile's position. +This is the lower left tile's lower left corner. If no origin is given, the tiles are centered over the +area investigated. +

    +By default, the tiles will cover the bounding box of the input layer. A separate layer +can be used in addition. This way, the layout's dimensions can be derived from some +drawn boundary layer. To specify a separate, additional layer included in the bounding box, use the "tile_boundary" option: +

    +

    +# reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
    +# layer 0/0:
    +cell_frame = input(0, 0)
    +low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
    +
    +

    +Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box. +The computed area is at least the area of the input layer. +

    +Computation of the area can be skipped by explicitly giving a tile count in horizontal and vertical +direction. With the "tile_origin" option this allows full control over the area covered: +

    +

    +# reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
    +# (100 and 150 tiles of 20 um each are used in horizontal and vertical direction):
    +low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
    +
    +

    +The complementary version of "with_density" is without_density. +

    +

    "with_holes" - Selects all polygons with the specified number of holes

    + +

    Usage:

    +
      +
    • layer.with_holes(count)
    • +
    • layer.with_holes(min_count, max_count)
    • +
    • layer.with_holes(min_count .. max_count)
    • +
    +

    +This method is available for polygon layers. It will select all polygons from the input layer +which have the specified number of holes. +

    "with_length" - Selects edges by their length

    Usage:

    @@ -3228,6 +3389,29 @@ bounding box.

    This method is available for polygon layers only.

    +

    "without_density" - Returns tiles whose density is not within a given range

    + +

    Usage:

    +
      +
    • layer.without_density(min_value, max_value [, options ])
    • +
    • layer.without_density(min_value .. max_value [, options ])
    • +
    +

    +For details about the operations and the operation see with_density. This version will return the +tiles where the density is not within the given range. +

    +

    "without_holes" - Selects all polygons with the specified number of holes

    + +

    Usage:

    +
      +
    • layer.without_holes(count)
    • +
    • layer.without_holes(min_count, max_count)
    • +
    • layer.without_holes(min_count .. max_count)
    • +
    +

    +This method is available for polygon layers. It will select all polygons from the input layer +which do not have the specified number of holes. +

    "without_length" - Selects edges by the their length

    Usage:

    diff --git a/src/lay/lay/doc/images/drc_and1.png b/src/lay/lay/doc/images/drc_and1.png index 8f480bfe7..d1f6d3fb9 100644 Binary files a/src/lay/lay/doc/images/drc_and1.png and b/src/lay/lay/doc/images/drc_and1.png differ diff --git a/src/lay/lay/doc/images/drc_and2.png b/src/lay/lay/doc/images/drc_and2.png index 5b8511d14..20592ffce 100644 Binary files a/src/lay/lay/doc/images/drc_and2.png and b/src/lay/lay/doc/images/drc_and2.png differ diff --git a/src/lay/lay/doc/images/drc_and3.png b/src/lay/lay/doc/images/drc_and3.png index 607deea18..81b678059 100644 Binary files a/src/lay/lay/doc/images/drc_and3.png and b/src/lay/lay/doc/images/drc_and3.png differ diff --git a/src/lay/lay/doc/images/drc_centers1.png b/src/lay/lay/doc/images/drc_centers1.png index 909553ab4..11980e56d 100644 Binary files a/src/lay/lay/doc/images/drc_centers1.png and b/src/lay/lay/doc/images/drc_centers1.png differ diff --git a/src/lay/lay/doc/images/drc_centers2.png b/src/lay/lay/doc/images/drc_centers2.png index 69c7ecb7f..e79d76598 100644 Binary files a/src/lay/lay/doc/images/drc_centers2.png and b/src/lay/lay/doc/images/drc_centers2.png differ diff --git a/src/lay/lay/doc/images/drc_corners1.png b/src/lay/lay/doc/images/drc_corners1.png index d1557f3a2..48adba3ca 100644 Binary files a/src/lay/lay/doc/images/drc_corners1.png and b/src/lay/lay/doc/images/drc_corners1.png differ diff --git a/src/lay/lay/doc/images/drc_corners2.png b/src/lay/lay/doc/images/drc_corners2.png index b595ea398..13fbbd89c 100644 Binary files a/src/lay/lay/doc/images/drc_corners2.png and b/src/lay/lay/doc/images/drc_corners2.png differ diff --git a/src/lay/lay/doc/images/drc_corners3.png b/src/lay/lay/doc/images/drc_corners3.png index 00b978bb3..55a909efd 100644 Binary files a/src/lay/lay/doc/images/drc_corners3.png and b/src/lay/lay/doc/images/drc_corners3.png differ diff --git a/src/lay/lay/doc/images/drc_covering.png b/src/lay/lay/doc/images/drc_covering.png index a96d88a7b..a149730c7 100644 Binary files a/src/lay/lay/doc/images/drc_covering.png and b/src/lay/lay/doc/images/drc_covering.png differ diff --git a/src/lay/lay/doc/images/drc_enc1.png b/src/lay/lay/doc/images/drc_enc1.png index 2bef4ab3c..69abadec6 100644 Binary files a/src/lay/lay/doc/images/drc_enc1.png and b/src/lay/lay/doc/images/drc_enc1.png differ diff --git a/src/lay/lay/doc/images/drc_enc1u.png b/src/lay/lay/doc/images/drc_enc1u.png index 5d6e58bb9..02f4d14b0 100644 Binary files a/src/lay/lay/doc/images/drc_enc1u.png and b/src/lay/lay/doc/images/drc_enc1u.png differ diff --git a/src/lay/lay/doc/images/drc_enc2.png b/src/lay/lay/doc/images/drc_enc2.png index df854246d..16bbda855 100644 Binary files a/src/lay/lay/doc/images/drc_enc2.png and b/src/lay/lay/doc/images/drc_enc2.png differ diff --git a/src/lay/lay/doc/images/drc_enc2u.png b/src/lay/lay/doc/images/drc_enc2u.png index 8a56c4e66..a7a70d48c 100644 Binary files a/src/lay/lay/doc/images/drc_enc2u.png and b/src/lay/lay/doc/images/drc_enc2u.png differ diff --git a/src/lay/lay/doc/images/drc_end_segments1.png b/src/lay/lay/doc/images/drc_end_segments1.png index 71fbae69e..d8ac09404 100644 Binary files a/src/lay/lay/doc/images/drc_end_segments1.png and b/src/lay/lay/doc/images/drc_end_segments1.png differ diff --git a/src/lay/lay/doc/images/drc_end_segments2.png b/src/lay/lay/doc/images/drc_end_segments2.png index 63f6feee9..666e81a31 100644 Binary files a/src/lay/lay/doc/images/drc_end_segments2.png and b/src/lay/lay/doc/images/drc_end_segments2.png differ diff --git a/src/lay/lay/doc/images/drc_extended1.png b/src/lay/lay/doc/images/drc_extended1.png index 3ff0f23f4..0acf06f9f 100644 Binary files a/src/lay/lay/doc/images/drc_extended1.png and b/src/lay/lay/doc/images/drc_extended1.png differ diff --git a/src/lay/lay/doc/images/drc_extended2.png b/src/lay/lay/doc/images/drc_extended2.png index 8860625aa..fe016af38 100644 Binary files a/src/lay/lay/doc/images/drc_extended2.png and b/src/lay/lay/doc/images/drc_extended2.png differ diff --git a/src/lay/lay/doc/images/drc_extended3.png b/src/lay/lay/doc/images/drc_extended3.png index a585d84c2..ce7e24be2 100644 Binary files a/src/lay/lay/doc/images/drc_extended3.png and b/src/lay/lay/doc/images/drc_extended3.png differ diff --git a/src/lay/lay/doc/images/drc_extended4.png b/src/lay/lay/doc/images/drc_extended4.png index 47a09728b..7d4bc6d9d 100644 Binary files a/src/lay/lay/doc/images/drc_extended4.png and b/src/lay/lay/doc/images/drc_extended4.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs1.png b/src/lay/lay/doc/images/drc_extent_refs1.png index d3c89b5f9..a0ce25631 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs1.png and b/src/lay/lay/doc/images/drc_extent_refs1.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs10.png b/src/lay/lay/doc/images/drc_extent_refs10.png index fd1785e21..4616764b0 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs10.png and b/src/lay/lay/doc/images/drc_extent_refs10.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs11.png b/src/lay/lay/doc/images/drc_extent_refs11.png index ba28f7c6f..06b354453 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs11.png and b/src/lay/lay/doc/images/drc_extent_refs11.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs12.png b/src/lay/lay/doc/images/drc_extent_refs12.png index ee0848fe8..84569ccad 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs12.png and b/src/lay/lay/doc/images/drc_extent_refs12.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs13.png b/src/lay/lay/doc/images/drc_extent_refs13.png index 90eb6e900..5234c4ccc 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs13.png and b/src/lay/lay/doc/images/drc_extent_refs13.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs20.png b/src/lay/lay/doc/images/drc_extent_refs20.png index c5c7384a8..6f2e21b15 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs20.png and b/src/lay/lay/doc/images/drc_extent_refs20.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs21.png b/src/lay/lay/doc/images/drc_extent_refs21.png index cd7ba9a21..e8a0efae4 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs21.png and b/src/lay/lay/doc/images/drc_extent_refs21.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs22.png b/src/lay/lay/doc/images/drc_extent_refs22.png index 5864bfd3f..cc53d2e58 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs22.png and b/src/lay/lay/doc/images/drc_extent_refs22.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs23.png b/src/lay/lay/doc/images/drc_extent_refs23.png index 753dfadcf..799244e8a 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs23.png and b/src/lay/lay/doc/images/drc_extent_refs23.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs24.png b/src/lay/lay/doc/images/drc_extent_refs24.png index dada72737..5e0fa248d 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs24.png and b/src/lay/lay/doc/images/drc_extent_refs24.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs25.png b/src/lay/lay/doc/images/drc_extent_refs25.png index 97a3e4ffe..e698483b7 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs25.png and b/src/lay/lay/doc/images/drc_extent_refs25.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs26.png b/src/lay/lay/doc/images/drc_extent_refs26.png index a281ba6ad..ffaac3ccc 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs26.png and b/src/lay/lay/doc/images/drc_extent_refs26.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs27.png b/src/lay/lay/doc/images/drc_extent_refs27.png index 580ee7363..0ffd732a0 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs27.png and b/src/lay/lay/doc/images/drc_extent_refs27.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs30.png b/src/lay/lay/doc/images/drc_extent_refs30.png index 8971fe0f2..f10836f89 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs30.png and b/src/lay/lay/doc/images/drc_extent_refs30.png differ diff --git a/src/lay/lay/doc/images/drc_extent_refs31.png b/src/lay/lay/doc/images/drc_extent_refs31.png index 0c1273866..2ecb4b3fc 100644 Binary files a/src/lay/lay/doc/images/drc_extent_refs31.png and b/src/lay/lay/doc/images/drc_extent_refs31.png differ diff --git a/src/lay/lay/doc/images/drc_extents1.png b/src/lay/lay/doc/images/drc_extents1.png index 494f98de6..4da7f777e 100644 Binary files a/src/lay/lay/doc/images/drc_extents1.png and b/src/lay/lay/doc/images/drc_extents1.png differ diff --git a/src/lay/lay/doc/images/drc_extents2.png b/src/lay/lay/doc/images/drc_extents2.png index 849ef4b8f..2d9c743be 100644 Binary files a/src/lay/lay/doc/images/drc_extents2.png and b/src/lay/lay/doc/images/drc_extents2.png differ diff --git a/src/lay/lay/doc/images/drc_holes.png b/src/lay/lay/doc/images/drc_holes.png index f8d0d5767..7234bdc9d 100644 Binary files a/src/lay/lay/doc/images/drc_holes.png and b/src/lay/lay/doc/images/drc_holes.png differ diff --git a/src/lay/lay/doc/images/drc_hulls.png b/src/lay/lay/doc/images/drc_hulls.png index a86927915..05294e60a 100644 Binary files a/src/lay/lay/doc/images/drc_hulls.png and b/src/lay/lay/doc/images/drc_hulls.png differ diff --git a/src/lay/lay/doc/images/drc_in.png b/src/lay/lay/doc/images/drc_in.png index d490a4a25..6abd1f525 100644 Binary files a/src/lay/lay/doc/images/drc_in.png and b/src/lay/lay/doc/images/drc_in.png differ diff --git a/src/lay/lay/doc/images/drc_inside.png b/src/lay/lay/doc/images/drc_inside.png index 61b9f0385..ad110260a 100644 Binary files a/src/lay/lay/doc/images/drc_inside.png and b/src/lay/lay/doc/images/drc_inside.png differ diff --git a/src/lay/lay/doc/images/drc_inside_part.png b/src/lay/lay/doc/images/drc_inside_part.png index 632836c75..4f60b0e88 100644 Binary files a/src/lay/lay/doc/images/drc_inside_part.png and b/src/lay/lay/doc/images/drc_inside_part.png differ diff --git a/src/lay/lay/doc/images/drc_interacting.png b/src/lay/lay/doc/images/drc_interacting.png index b0ca9711d..cf8ccb394 100644 Binary files a/src/lay/lay/doc/images/drc_interacting.png and b/src/lay/lay/doc/images/drc_interacting.png differ diff --git a/src/lay/lay/doc/images/drc_interacting2.png b/src/lay/lay/doc/images/drc_interacting2.png index c924a17d1..a67ed9efc 100644 Binary files a/src/lay/lay/doc/images/drc_interacting2.png and b/src/lay/lay/doc/images/drc_interacting2.png differ diff --git a/src/lay/lay/doc/images/drc_interacting3.png b/src/lay/lay/doc/images/drc_interacting3.png index 1ca5f6703..91daa8762 100644 Binary files a/src/lay/lay/doc/images/drc_interacting3.png and b/src/lay/lay/doc/images/drc_interacting3.png differ diff --git a/src/lay/lay/doc/images/drc_interacting4.png b/src/lay/lay/doc/images/drc_interacting4.png index 4eff34e8d..38a4fd033 100644 Binary files a/src/lay/lay/doc/images/drc_interacting4.png and b/src/lay/lay/doc/images/drc_interacting4.png differ diff --git a/src/lay/lay/doc/images/drc_interacting5.png b/src/lay/lay/doc/images/drc_interacting5.png index 63aa03f67..72b1316f7 100644 Binary files a/src/lay/lay/doc/images/drc_interacting5.png and b/src/lay/lay/doc/images/drc_interacting5.png differ diff --git a/src/lay/lay/doc/images/drc_join1.png b/src/lay/lay/doc/images/drc_join1.png index b5acb1b0a..d76202b20 100644 Binary files a/src/lay/lay/doc/images/drc_join1.png and b/src/lay/lay/doc/images/drc_join1.png differ diff --git a/src/lay/lay/doc/images/drc_join2.png b/src/lay/lay/doc/images/drc_join2.png index b3d66c286..f0e5afc18 100644 Binary files a/src/lay/lay/doc/images/drc_join2.png and b/src/lay/lay/doc/images/drc_join2.png differ diff --git a/src/lay/lay/doc/images/drc_merged1.png b/src/lay/lay/doc/images/drc_merged1.png index ff025981e..f8902eb65 100644 Binary files a/src/lay/lay/doc/images/drc_merged1.png and b/src/lay/lay/doc/images/drc_merged1.png differ diff --git a/src/lay/lay/doc/images/drc_merged2.png b/src/lay/lay/doc/images/drc_merged2.png index c66432764..6e8aee84f 100644 Binary files a/src/lay/lay/doc/images/drc_merged2.png and b/src/lay/lay/doc/images/drc_merged2.png differ diff --git a/src/lay/lay/doc/images/drc_merged3.png b/src/lay/lay/doc/images/drc_merged3.png index 24d14f99c..a6cc97752 100644 Binary files a/src/lay/lay/doc/images/drc_merged3.png and b/src/lay/lay/doc/images/drc_merged3.png differ diff --git a/src/lay/lay/doc/images/drc_merged4.png b/src/lay/lay/doc/images/drc_merged4.png index f66a7a02c..fcdd01725 100644 Binary files a/src/lay/lay/doc/images/drc_merged4.png and b/src/lay/lay/doc/images/drc_merged4.png differ diff --git a/src/lay/lay/doc/images/drc_middle1.png b/src/lay/lay/doc/images/drc_middle1.png index 109ee09ad..ba9dca0d2 100644 Binary files a/src/lay/lay/doc/images/drc_middle1.png and b/src/lay/lay/doc/images/drc_middle1.png differ diff --git a/src/lay/lay/doc/images/drc_moved1.png b/src/lay/lay/doc/images/drc_moved1.png index 9fbd96ea1..f7f0d3235 100644 Binary files a/src/lay/lay/doc/images/drc_moved1.png and b/src/lay/lay/doc/images/drc_moved1.png differ diff --git a/src/lay/lay/doc/images/drc_not1.png b/src/lay/lay/doc/images/drc_not1.png index c44c4d55e..b222eed5d 100644 Binary files a/src/lay/lay/doc/images/drc_not1.png and b/src/lay/lay/doc/images/drc_not1.png differ diff --git a/src/lay/lay/doc/images/drc_not2.png b/src/lay/lay/doc/images/drc_not2.png index 2e4c3784f..17e258276 100644 Binary files a/src/lay/lay/doc/images/drc_not2.png and b/src/lay/lay/doc/images/drc_not2.png differ diff --git a/src/lay/lay/doc/images/drc_not3.png b/src/lay/lay/doc/images/drc_not3.png index 3a51db056..a558b73eb 100644 Binary files a/src/lay/lay/doc/images/drc_not3.png and b/src/lay/lay/doc/images/drc_not3.png differ diff --git a/src/lay/lay/doc/images/drc_not_covering.png b/src/lay/lay/doc/images/drc_not_covering.png index a192aecd3..4a89f993a 100644 Binary files a/src/lay/lay/doc/images/drc_not_covering.png and b/src/lay/lay/doc/images/drc_not_covering.png differ diff --git a/src/lay/lay/doc/images/drc_not_in.png b/src/lay/lay/doc/images/drc_not_in.png index 784aab798..588a5ddec 100644 Binary files a/src/lay/lay/doc/images/drc_not_in.png and b/src/lay/lay/doc/images/drc_not_in.png differ diff --git a/src/lay/lay/doc/images/drc_not_inside.png b/src/lay/lay/doc/images/drc_not_inside.png index 16146f7aa..069afb6b3 100644 Binary files a/src/lay/lay/doc/images/drc_not_inside.png and b/src/lay/lay/doc/images/drc_not_inside.png differ diff --git a/src/lay/lay/doc/images/drc_not_interacting.png b/src/lay/lay/doc/images/drc_not_interacting.png index 66f1d8478..e1124a818 100644 Binary files a/src/lay/lay/doc/images/drc_not_interacting.png and b/src/lay/lay/doc/images/drc_not_interacting.png differ diff --git a/src/lay/lay/doc/images/drc_not_interacting2.png b/src/lay/lay/doc/images/drc_not_interacting2.png index cb6ec6d38..d6105f972 100644 Binary files a/src/lay/lay/doc/images/drc_not_interacting2.png and b/src/lay/lay/doc/images/drc_not_interacting2.png differ diff --git a/src/lay/lay/doc/images/drc_not_interacting3.png b/src/lay/lay/doc/images/drc_not_interacting3.png index 069e09508..32604950c 100644 Binary files a/src/lay/lay/doc/images/drc_not_interacting3.png and b/src/lay/lay/doc/images/drc_not_interacting3.png differ diff --git a/src/lay/lay/doc/images/drc_not_interacting4.png b/src/lay/lay/doc/images/drc_not_interacting4.png index d78b0219e..6a02f22cc 100644 Binary files a/src/lay/lay/doc/images/drc_not_interacting4.png and b/src/lay/lay/doc/images/drc_not_interacting4.png differ diff --git a/src/lay/lay/doc/images/drc_not_interacting5.png b/src/lay/lay/doc/images/drc_not_interacting5.png index ee77c5bdd..a7a81e180 100644 Binary files a/src/lay/lay/doc/images/drc_not_interacting5.png and b/src/lay/lay/doc/images/drc_not_interacting5.png differ diff --git a/src/lay/lay/doc/images/drc_not_outside.png b/src/lay/lay/doc/images/drc_not_outside.png index f2519219a..00e0104f5 100644 Binary files a/src/lay/lay/doc/images/drc_not_outside.png and b/src/lay/lay/doc/images/drc_not_outside.png differ diff --git a/src/lay/lay/doc/images/drc_not_overlapping.png b/src/lay/lay/doc/images/drc_not_overlapping.png index 9909a7f36..40661ce0e 100644 Binary files a/src/lay/lay/doc/images/drc_not_overlapping.png and b/src/lay/lay/doc/images/drc_not_overlapping.png differ diff --git a/src/lay/lay/doc/images/drc_or1.png b/src/lay/lay/doc/images/drc_or1.png index 7357a705c..0763b79d2 100644 Binary files a/src/lay/lay/doc/images/drc_or1.png and b/src/lay/lay/doc/images/drc_or1.png differ diff --git a/src/lay/lay/doc/images/drc_or2.png b/src/lay/lay/doc/images/drc_or2.png index 0aa51b9fa..fdd7cab47 100644 Binary files a/src/lay/lay/doc/images/drc_or2.png and b/src/lay/lay/doc/images/drc_or2.png differ diff --git a/src/lay/lay/doc/images/drc_outside.png b/src/lay/lay/doc/images/drc_outside.png index 0345e4258..a3913d379 100644 Binary files a/src/lay/lay/doc/images/drc_outside.png and b/src/lay/lay/doc/images/drc_outside.png differ diff --git a/src/lay/lay/doc/images/drc_outside_part.png b/src/lay/lay/doc/images/drc_outside_part.png index 34cc504d2..213f7a15e 100644 Binary files a/src/lay/lay/doc/images/drc_outside_part.png and b/src/lay/lay/doc/images/drc_outside_part.png differ diff --git a/src/lay/lay/doc/images/drc_overlap1.png b/src/lay/lay/doc/images/drc_overlap1.png index f58070e79..e4bd2d325 100644 Binary files a/src/lay/lay/doc/images/drc_overlap1.png and b/src/lay/lay/doc/images/drc_overlap1.png differ diff --git a/src/lay/lay/doc/images/drc_overlap1u.png b/src/lay/lay/doc/images/drc_overlap1u.png index 72401d229..4fa168ee3 100644 Binary files a/src/lay/lay/doc/images/drc_overlap1u.png and b/src/lay/lay/doc/images/drc_overlap1u.png differ diff --git a/src/lay/lay/doc/images/drc_overlap2.png b/src/lay/lay/doc/images/drc_overlap2.png index 4da4a00ab..108b48822 100644 Binary files a/src/lay/lay/doc/images/drc_overlap2.png and b/src/lay/lay/doc/images/drc_overlap2.png differ diff --git a/src/lay/lay/doc/images/drc_overlap2u.png b/src/lay/lay/doc/images/drc_overlap2u.png index 6b4666f18..9c246f0e8 100644 Binary files a/src/lay/lay/doc/images/drc_overlap2u.png and b/src/lay/lay/doc/images/drc_overlap2u.png differ diff --git a/src/lay/lay/doc/images/drc_overlapping.png b/src/lay/lay/doc/images/drc_overlapping.png index d3f803281..c066614e0 100644 Binary files a/src/lay/lay/doc/images/drc_overlapping.png and b/src/lay/lay/doc/images/drc_overlapping.png differ diff --git a/src/lay/lay/doc/images/drc_raw1.png b/src/lay/lay/doc/images/drc_raw1.png index 81d56369b..38490f5c1 100644 Binary files a/src/lay/lay/doc/images/drc_raw1.png and b/src/lay/lay/doc/images/drc_raw1.png differ diff --git a/src/lay/lay/doc/images/drc_raw2.png b/src/lay/lay/doc/images/drc_raw2.png index 2803f371f..e788362dc 100644 Binary files a/src/lay/lay/doc/images/drc_raw2.png and b/src/lay/lay/doc/images/drc_raw2.png differ diff --git a/src/lay/lay/doc/images/drc_raw3.png b/src/lay/lay/doc/images/drc_raw3.png index f335740ad..dffd596e6 100644 Binary files a/src/lay/lay/doc/images/drc_raw3.png and b/src/lay/lay/doc/images/drc_raw3.png differ diff --git a/src/lay/lay/doc/images/drc_rotated1.png b/src/lay/lay/doc/images/drc_rotated1.png index 10f561f25..f16aaf3d3 100644 Binary files a/src/lay/lay/doc/images/drc_rotated1.png and b/src/lay/lay/doc/images/drc_rotated1.png differ diff --git a/src/lay/lay/doc/images/drc_rounded_corners.png b/src/lay/lay/doc/images/drc_rounded_corners.png index 49dfb4495..984f71ae2 100644 Binary files a/src/lay/lay/doc/images/drc_rounded_corners.png and b/src/lay/lay/doc/images/drc_rounded_corners.png differ diff --git a/src/lay/lay/doc/images/drc_scaled1.png b/src/lay/lay/doc/images/drc_scaled1.png index 10595dfee..a0ae3fdbc 100644 Binary files a/src/lay/lay/doc/images/drc_scaled1.png and b/src/lay/lay/doc/images/drc_scaled1.png differ diff --git a/src/lay/lay/doc/images/drc_separation1.png b/src/lay/lay/doc/images/drc_separation1.png index 1dfa0e9f3..e982d2871 100644 Binary files a/src/lay/lay/doc/images/drc_separation1.png and b/src/lay/lay/doc/images/drc_separation1.png differ diff --git a/src/lay/lay/doc/images/drc_separation10.png b/src/lay/lay/doc/images/drc_separation10.png index 041e66910..af8fdeac7 100644 Binary files a/src/lay/lay/doc/images/drc_separation10.png and b/src/lay/lay/doc/images/drc_separation10.png differ diff --git a/src/lay/lay/doc/images/drc_separation11.png b/src/lay/lay/doc/images/drc_separation11.png index bfa3d688f..de975994c 100644 Binary files a/src/lay/lay/doc/images/drc_separation11.png and b/src/lay/lay/doc/images/drc_separation11.png differ diff --git a/src/lay/lay/doc/images/drc_separation1u.png b/src/lay/lay/doc/images/drc_separation1u.png index c3bbe1416..1f0db1ee8 100644 Binary files a/src/lay/lay/doc/images/drc_separation1u.png and b/src/lay/lay/doc/images/drc_separation1u.png differ diff --git a/src/lay/lay/doc/images/drc_separation2.png b/src/lay/lay/doc/images/drc_separation2.png index 9859e8e4b..9878580aa 100644 Binary files a/src/lay/lay/doc/images/drc_separation2.png and b/src/lay/lay/doc/images/drc_separation2.png differ diff --git a/src/lay/lay/doc/images/drc_separation3.png b/src/lay/lay/doc/images/drc_separation3.png index cfdd7f26b..54425378d 100644 Binary files a/src/lay/lay/doc/images/drc_separation3.png and b/src/lay/lay/doc/images/drc_separation3.png differ diff --git a/src/lay/lay/doc/images/drc_separation4.png b/src/lay/lay/doc/images/drc_separation4.png index 7c3d58d68..818d2ef7d 100644 Binary files a/src/lay/lay/doc/images/drc_separation4.png and b/src/lay/lay/doc/images/drc_separation4.png differ diff --git a/src/lay/lay/doc/images/drc_separation5.png b/src/lay/lay/doc/images/drc_separation5.png index 7087dfe60..dea235507 100644 Binary files a/src/lay/lay/doc/images/drc_separation5.png and b/src/lay/lay/doc/images/drc_separation5.png differ diff --git a/src/lay/lay/doc/images/drc_separation6.png b/src/lay/lay/doc/images/drc_separation6.png index dfa38c475..f21d778a8 100644 Binary files a/src/lay/lay/doc/images/drc_separation6.png and b/src/lay/lay/doc/images/drc_separation6.png differ diff --git a/src/lay/lay/doc/images/drc_separation7.png b/src/lay/lay/doc/images/drc_separation7.png index 95006d6af..0a76ec4de 100644 Binary files a/src/lay/lay/doc/images/drc_separation7.png and b/src/lay/lay/doc/images/drc_separation7.png differ diff --git a/src/lay/lay/doc/images/drc_separation8.png b/src/lay/lay/doc/images/drc_separation8.png index 1dc539958..638722f9b 100644 Binary files a/src/lay/lay/doc/images/drc_separation8.png and b/src/lay/lay/doc/images/drc_separation8.png differ diff --git a/src/lay/lay/doc/images/drc_separation9.png b/src/lay/lay/doc/images/drc_separation9.png index a6da75eaa..c6a675e18 100644 Binary files a/src/lay/lay/doc/images/drc_separation9.png and b/src/lay/lay/doc/images/drc_separation9.png differ diff --git a/src/lay/lay/doc/images/drc_shielded1.png b/src/lay/lay/doc/images/drc_shielded1.png index 22b98c231..aa788f104 100644 Binary files a/src/lay/lay/doc/images/drc_shielded1.png and b/src/lay/lay/doc/images/drc_shielded1.png differ diff --git a/src/lay/lay/doc/images/drc_shielded2.png b/src/lay/lay/doc/images/drc_shielded2.png index 0116e6229..1ee78bb0e 100644 Binary files a/src/lay/lay/doc/images/drc_shielded2.png and b/src/lay/lay/doc/images/drc_shielded2.png differ diff --git a/src/lay/lay/doc/images/drc_shielded3.png b/src/lay/lay/doc/images/drc_shielded3.png index d7c3abf0b..ba1ab8312 100644 Binary files a/src/lay/lay/doc/images/drc_shielded3.png and b/src/lay/lay/doc/images/drc_shielded3.png differ diff --git a/src/lay/lay/doc/images/drc_shielded4.png b/src/lay/lay/doc/images/drc_shielded4.png index f7fbc75fc..c1644a2ec 100644 Binary files a/src/lay/lay/doc/images/drc_shielded4.png and b/src/lay/lay/doc/images/drc_shielded4.png differ diff --git a/src/lay/lay/doc/images/drc_sized1.png b/src/lay/lay/doc/images/drc_sized1.png index 445a60538..daae1b5ec 100644 Binary files a/src/lay/lay/doc/images/drc_sized1.png and b/src/lay/lay/doc/images/drc_sized1.png differ diff --git a/src/lay/lay/doc/images/drc_sized2.png b/src/lay/lay/doc/images/drc_sized2.png index db23995c6..1e5f2514d 100644 Binary files a/src/lay/lay/doc/images/drc_sized2.png and b/src/lay/lay/doc/images/drc_sized2.png differ diff --git a/src/lay/lay/doc/images/drc_sized3.png b/src/lay/lay/doc/images/drc_sized3.png index 247bda8b2..63946cc16 100644 Binary files a/src/lay/lay/doc/images/drc_sized3.png and b/src/lay/lay/doc/images/drc_sized3.png differ diff --git a/src/lay/lay/doc/images/drc_sized4.png b/src/lay/lay/doc/images/drc_sized4.png index 5e180f7d2..c4d470f98 100644 Binary files a/src/lay/lay/doc/images/drc_sized4.png and b/src/lay/lay/doc/images/drc_sized4.png differ diff --git a/src/lay/lay/doc/images/drc_sized5.png b/src/lay/lay/doc/images/drc_sized5.png index 7caace4de..4426443b4 100644 Binary files a/src/lay/lay/doc/images/drc_sized5.png and b/src/lay/lay/doc/images/drc_sized5.png differ diff --git a/src/lay/lay/doc/images/drc_sized6.png b/src/lay/lay/doc/images/drc_sized6.png index 83677eef9..0849455da 100644 Binary files a/src/lay/lay/doc/images/drc_sized6.png and b/src/lay/lay/doc/images/drc_sized6.png differ diff --git a/src/lay/lay/doc/images/drc_space1.png b/src/lay/lay/doc/images/drc_space1.png index 96caf65c2..a4d6a8877 100644 Binary files a/src/lay/lay/doc/images/drc_space1.png and b/src/lay/lay/doc/images/drc_space1.png differ diff --git a/src/lay/lay/doc/images/drc_space1u.png b/src/lay/lay/doc/images/drc_space1u.png index c3fc2f8a1..617e6af62 100644 Binary files a/src/lay/lay/doc/images/drc_space1u.png and b/src/lay/lay/doc/images/drc_space1u.png differ diff --git a/src/lay/lay/doc/images/drc_space2.png b/src/lay/lay/doc/images/drc_space2.png index 5b7b015c6..713378517 100644 Binary files a/src/lay/lay/doc/images/drc_space2.png and b/src/lay/lay/doc/images/drc_space2.png differ diff --git a/src/lay/lay/doc/images/drc_space2u.png b/src/lay/lay/doc/images/drc_space2u.png index 0f3303314..d223d9663 100644 Binary files a/src/lay/lay/doc/images/drc_space2u.png and b/src/lay/lay/doc/images/drc_space2u.png differ diff --git a/src/lay/lay/doc/images/drc_space3.png b/src/lay/lay/doc/images/drc_space3.png index 9273739f0..a9ddcd213 100644 Binary files a/src/lay/lay/doc/images/drc_space3.png and b/src/lay/lay/doc/images/drc_space3.png differ diff --git a/src/lay/lay/doc/images/drc_space3u.png b/src/lay/lay/doc/images/drc_space3u.png index 2d304de7c..41b7853de 100644 Binary files a/src/lay/lay/doc/images/drc_space3u.png and b/src/lay/lay/doc/images/drc_space3u.png differ diff --git a/src/lay/lay/doc/images/drc_start_segments1.png b/src/lay/lay/doc/images/drc_start_segments1.png index 377a6ac57..bdd7c7051 100644 Binary files a/src/lay/lay/doc/images/drc_start_segments1.png and b/src/lay/lay/doc/images/drc_start_segments1.png differ diff --git a/src/lay/lay/doc/images/drc_start_segments2.png b/src/lay/lay/doc/images/drc_start_segments2.png index ad269e32d..8c23e1c0b 100644 Binary files a/src/lay/lay/doc/images/drc_start_segments2.png and b/src/lay/lay/doc/images/drc_start_segments2.png differ diff --git a/src/lay/lay/doc/images/drc_textpoly1.png b/src/lay/lay/doc/images/drc_textpoly1.png index 487cfcc9c..d43240264 100644 Binary files a/src/lay/lay/doc/images/drc_textpoly1.png and b/src/lay/lay/doc/images/drc_textpoly1.png differ diff --git a/src/lay/lay/doc/images/drc_textpoly2.png b/src/lay/lay/doc/images/drc_textpoly2.png index e6eec02b4..ff84fb7b0 100644 Binary files a/src/lay/lay/doc/images/drc_textpoly2.png and b/src/lay/lay/doc/images/drc_textpoly2.png differ diff --git a/src/lay/lay/doc/images/drc_texts1.png b/src/lay/lay/doc/images/drc_texts1.png index a3c5eabf2..44e30c5bb 100644 Binary files a/src/lay/lay/doc/images/drc_texts1.png and b/src/lay/lay/doc/images/drc_texts1.png differ diff --git a/src/lay/lay/doc/images/drc_texts2.png b/src/lay/lay/doc/images/drc_texts2.png index 2e672d4ce..010c0abca 100644 Binary files a/src/lay/lay/doc/images/drc_texts2.png and b/src/lay/lay/doc/images/drc_texts2.png differ diff --git a/src/lay/lay/doc/images/drc_transformed1.png b/src/lay/lay/doc/images/drc_transformed1.png index 1c8f240f0..3fbbc5af2 100644 Binary files a/src/lay/lay/doc/images/drc_transformed1.png and b/src/lay/lay/doc/images/drc_transformed1.png differ diff --git a/src/lay/lay/doc/images/drc_width1.png b/src/lay/lay/doc/images/drc_width1.png index e603ea2ec..afc906e51 100644 Binary files a/src/lay/lay/doc/images/drc_width1.png and b/src/lay/lay/doc/images/drc_width1.png differ diff --git a/src/lay/lay/doc/images/drc_width1u.png b/src/lay/lay/doc/images/drc_width1u.png index 0620c9f52..dfdc2267f 100644 Binary files a/src/lay/lay/doc/images/drc_width1u.png and b/src/lay/lay/doc/images/drc_width1u.png differ diff --git a/src/lay/lay/doc/images/drc_width2.png b/src/lay/lay/doc/images/drc_width2.png index adbd23e3e..e27d018ef 100644 Binary files a/src/lay/lay/doc/images/drc_width2.png and b/src/lay/lay/doc/images/drc_width2.png differ diff --git a/src/lay/lay/doc/images/drc_width2u.png b/src/lay/lay/doc/images/drc_width2u.png index 72059ed49..da04841dd 100644 Binary files a/src/lay/lay/doc/images/drc_width2u.png and b/src/lay/lay/doc/images/drc_width2u.png differ diff --git a/src/lay/lay/doc/images/drc_width3.png b/src/lay/lay/doc/images/drc_width3.png index b6e4f245d..47a5c108f 100644 Binary files a/src/lay/lay/doc/images/drc_width3.png and b/src/lay/lay/doc/images/drc_width3.png differ diff --git a/src/lay/lay/doc/images/drc_width3u.png b/src/lay/lay/doc/images/drc_width3u.png index d8b9975fa..3766720b1 100644 Binary files a/src/lay/lay/doc/images/drc_width3u.png and b/src/lay/lay/doc/images/drc_width3u.png differ diff --git a/src/lay/lay/doc/images/drc_width4.png b/src/lay/lay/doc/images/drc_width4.png index 10024dbfd..afef4849c 100644 Binary files a/src/lay/lay/doc/images/drc_width4.png and b/src/lay/lay/doc/images/drc_width4.png differ diff --git a/src/lay/lay/doc/images/drc_width4u.png b/src/lay/lay/doc/images/drc_width4u.png index 481c252f2..6434c0e14 100644 Binary files a/src/lay/lay/doc/images/drc_width4u.png and b/src/lay/lay/doc/images/drc_width4u.png differ diff --git a/src/lay/lay/doc/images/drc_width5u.png b/src/lay/lay/doc/images/drc_width5u.png index df054f8b5..9bcd5eadf 100644 Binary files a/src/lay/lay/doc/images/drc_width5u.png and b/src/lay/lay/doc/images/drc_width5u.png differ diff --git a/src/lay/lay/doc/images/drc_width6u.png b/src/lay/lay/doc/images/drc_width6u.png index 5c25d49a4..664e44a3e 100644 Binary files a/src/lay/lay/doc/images/drc_width6u.png and b/src/lay/lay/doc/images/drc_width6u.png differ diff --git a/src/lay/lay/doc/images/drc_with_angle1.png b/src/lay/lay/doc/images/drc_with_angle1.png index 77e234653..ec941dbbb 100644 Binary files a/src/lay/lay/doc/images/drc_with_angle1.png and b/src/lay/lay/doc/images/drc_with_angle1.png differ diff --git a/src/lay/lay/doc/images/drc_with_angle2.png b/src/lay/lay/doc/images/drc_with_angle2.png index c122a281b..7deb564f0 100644 Binary files a/src/lay/lay/doc/images/drc_with_angle2.png and b/src/lay/lay/doc/images/drc_with_angle2.png differ diff --git a/src/lay/lay/doc/images/drc_with_angle3.png b/src/lay/lay/doc/images/drc_with_angle3.png index 1e04a839b..98df2c5f8 100644 Binary files a/src/lay/lay/doc/images/drc_with_angle3.png and b/src/lay/lay/doc/images/drc_with_angle3.png differ diff --git a/src/lay/lay/doc/images/drc_with_angle4.png b/src/lay/lay/doc/images/drc_with_angle4.png index 2fc74b3c7..605b45d14 100644 Binary files a/src/lay/lay/doc/images/drc_with_angle4.png and b/src/lay/lay/doc/images/drc_with_angle4.png differ diff --git a/src/lay/lay/doc/images/drc_xor1.png b/src/lay/lay/doc/images/drc_xor1.png index d33f65b84..9e7b24970 100644 Binary files a/src/lay/lay/doc/images/drc_xor1.png and b/src/lay/lay/doc/images/drc_xor1.png differ diff --git a/src/lay/lay/doc/images/drc_xor2.png b/src/lay/lay/doc/images/drc_xor2.png index ec9da5c2b..246364a18 100644 Binary files a/src/lay/lay/doc/images/drc_xor2.png and b/src/lay/lay/doc/images/drc_xor2.png differ diff --git a/src/lay/lay/layLogViewerDialog.cc b/src/lay/lay/layLogViewerDialog.cc index e0ca83912..b3604b652 100644 --- a/src/lay/lay/layLogViewerDialog.cc +++ b/src/lay/lay/layLogViewerDialog.cc @@ -101,7 +101,7 @@ LogReceiver::begin () LogFile::LogFile (size_t max_entries, bool register_global) : m_error_receiver (this, 0, &LogFile::add_error), m_warn_receiver (this, 0, &LogFile::add_warn), - m_log_receiver (this, 10, &LogFile::add_info), + m_log_receiver (this, 0, &LogFile::add_info), m_info_receiver (this, 0, &LogFile::add_info), m_max_entries (max_entries), m_generation_id (0), diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 4b01a130a..d40814b05 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2525,21 +2525,30 @@ MainWindow::cm_new_layout () std::string technology = m_initial_technology; static std::string s_new_cell_cell_name ("TOP"); static double s_new_cell_window_size = 2.0; + static std::vector s_layers; double dbu = 0.0; lay::NewLayoutPropertiesDialog dialog (this); - if (dialog.exec_dialog (technology, s_new_cell_cell_name, dbu, s_new_cell_window_size, m_new_layout_current_panel)) { + if (dialog.exec_dialog (technology, s_new_cell_cell_name, dbu, s_new_cell_window_size, s_layers, m_new_layout_current_panel)) { - lay::CellViewRef cellview = create_or_load_layout (0, 0, technology, m_new_layout_current_panel ? 2 : 1 /*= new view*/); + std::unique_ptr handle (new lay::LayoutHandle (new db::Layout (& manager ()), std::string ())); + handle->rename ("new"); if (dbu > 1e-10) { - cellview->layout ().dbu (dbu); + handle->layout ().dbu (dbu); } - db::cell_index_type new_ci = cellview->layout ().add_cell (s_new_cell_cell_name.empty () ? 0 : s_new_cell_cell_name.c_str ()); - cellview.set_cell (new_ci); + db::cell_index_type new_ci = handle->layout ().add_cell (s_new_cell_cell_name.empty () ? 0 : s_new_cell_cell_name.c_str ()); - current_view ()->zoom_box_and_set_hier_levels (db::DBox (-0.5 * s_new_cell_window_size, -0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size), std::make_pair (0, 1)); + for (std::vector::const_iterator l = s_layers.begin (); l != s_layers.end (); ++l) { + handle->layout ().insert_layer (*l); + } + + lay::LayoutView *mp_view = (m_new_layout_current_panel && current_view ()) ? current_view () : view (create_view ()); + + unsigned int ci = mp_view->add_layout (handle.release (), true); + mp_view->cellview_ref (ci).set_cell (new_ci); + mp_view->zoom_box_and_set_hier_levels (db::DBox (-0.5 * s_new_cell_window_size, -0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size, 0.5 * s_new_cell_window_size), std::make_pair (0, 1)); } } diff --git a/src/lay/lay/laySearchReplaceDialog.cc b/src/lay/lay/laySearchReplaceDialog.cc index 0c5f5b321..4f8196e64 100644 --- a/src/lay/lay/laySearchReplaceDialog.cc +++ b/src/lay/lay/laySearchReplaceDialog.cc @@ -1040,7 +1040,7 @@ BEGIN_PROTECTED query_to_model (model, lq, iq, std::numeric_limits::max (), true); model.end_changes (); - std::unique_ptr handle (new lay::LayoutHandle (new db::Layout (), std::string ())); + std::unique_ptr handle (new lay::LayoutHandle (new db::Layout (mp_view->manager ()), std::string ())); handle->rename ("query_results"); model.export_layout (handle->layout ()); mp_view->add_layout (handle.release (), true); diff --git a/src/laybasic/laybasic/NewLayoutPropertiesDialog.ui b/src/laybasic/laybasic/NewLayoutPropertiesDialog.ui index 200666491..588a93c4f 100644 --- a/src/laybasic/laybasic/NewLayoutPropertiesDialog.ui +++ b/src/laybasic/laybasic/NewLayoutPropertiesDialog.ui @@ -6,8 +6,8 @@ 0 0 - 563 - 234 + 594 + 401 @@ -50,7 +50,7 @@ 6 - + @@ -60,13 +60,6 @@ - - - - Database unit - - - @@ -80,13 +73,80 @@ - + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + Qt::Horizontal + + + + 141 + 20 + + + + + µm + + + + µm + + + + + + + Top cell + + + + + + + Database unit + + + + + + + Technology + + + @@ -100,74 +160,34 @@ - - - - - 0 - 0 - - - - - - - - - + + - Top cell + (empty for default) - - - - - 0 - 0 - - - - - - - - Technology - - - - + Initial window size - - + + - µm + Initial layer(s) - - - - Qt::Horizontal - - - - 141 - 20 - - - - - - + + - (empty for default) + <html><head/><body>Specify a comma or blank separated list of layers to create in the usual layer notation, e.g. "1/0 2/0 3/0", "metal1 via1 metal2" or "metal1 (1/0) via1 (2/0) metal2 (3/0)"</body></html> + + + true @@ -214,10 +234,12 @@ + tech_cbx topcell_le dbu_le window_le - buttonBox + layers_le + current_panel_cb diff --git a/src/laybasic/laybasic/layDialogs.cc b/src/laybasic/laybasic/layDialogs.cc index 3eb6e7156..886684442 100644 --- a/src/laybasic/laybasic/layDialogs.cc +++ b/src/laybasic/laybasic/layDialogs.cc @@ -129,7 +129,7 @@ NewLayoutPropertiesDialog::tech_changed () } bool -NewLayoutPropertiesDialog::exec_dialog (std::string &technology, std::string &cell_name, double &dbu, double &size, bool ¤t_panel) +NewLayoutPropertiesDialog::exec_dialog (std::string &technology, std::string &cell_name, double &dbu, double &size, std::vector &layers, bool ¤t_panel) { mp_ui->tech_cbx->clear (); unsigned int technology_index = 0; @@ -151,6 +151,15 @@ NewLayoutPropertiesDialog::exec_dialog (std::string &technology, std::string &ce mp_ui->topcell_le->setText (tl::to_qstring (cell_name)); mp_ui->current_panel_cb->setChecked (current_panel); + std::string layer_string; + for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { + if (l != layers.begin ()) { + layer_string += ", "; + } + layer_string += l->to_string (); + } + mp_ui->layers_le->setText (tl::to_qstring (layer_string)); + if (QDialog::exec ()) { // get the selected technology name @@ -167,8 +176,24 @@ NewLayoutPropertiesDialog::exec_dialog (std::string &technology, std::string &ce } else { dbu = 0.0; } + cell_name = tl::to_string (mp_ui->topcell_le->text ()); current_panel = mp_ui->current_panel_cb->isChecked (); + + layers.clear (); + layer_string = tl::to_string (mp_ui->layers_le->text ()); + tl::Extractor ex (layer_string.c_str ()); + while (! ex.at_end ()) { + db::LayerProperties lp; + try { + lp.read (ex); + } catch (...) { + break; + } + layers.push_back (lp); + ex.test (","); + } + return true; } else { diff --git a/src/laybasic/laybasic/layDialogs.h b/src/laybasic/laybasic/layDialogs.h index 8a12966ea..cb926c3c8 100644 --- a/src/laybasic/laybasic/layDialogs.h +++ b/src/laybasic/laybasic/layDialogs.h @@ -328,7 +328,7 @@ public: NewLayoutPropertiesDialog (QWidget *parent); virtual ~NewLayoutPropertiesDialog (); - bool exec_dialog (std::string &tech_name, std::string &cell_name, double &dbu, double &window_size, bool ¤t_panel); + bool exec_dialog (std::string &tech_name, std::string &cell_name, double &dbu, double &window_size, std::vector &layers, bool ¤t_panel); private slots: void tech_changed (); diff --git a/src/laybasic/laybasic/layLayoutView.cc b/src/laybasic/laybasic/layLayoutView.cc index 1a4531ac1..c3bd6fc2a 100644 --- a/src/laybasic/laybasic/layLayoutView.cc +++ b/src/laybasic/laybasic/layLayoutView.cc @@ -2859,6 +2859,8 @@ LayoutView::add_new_layers (const std::vector &layer_ids, int cv_ // create the layers and do a basic recoloring .. lay::LayerPropertiesList new_props (get_properties ()); + bool was_empty = new_props.begin_const_recursive ().at_end (); + // don't create new layers for those, for which there are layers already: compute a // set of layers already present std::set present_layers; @@ -2890,6 +2892,10 @@ LayoutView::add_new_layers (const std::vector &layer_ids, int cv_ set_properties (new_props); + if (was_empty) { + set_current_layer (new_props.begin_const_recursive ()); + } + } } @@ -3291,6 +3297,18 @@ LayoutView::add_layout (lay::LayoutHandle *layout_handle, bool add_cellview, boo } + // select the first layer if nothing else is selected + if (cv_index == 0 && ! mp_control_panel->has_selection ()) { + const lay::LayerPropertiesList &lp = get_properties (); + lay::LayerPropertiesConstIterator li = lp.begin_const_recursive (); + while (! li.at_end () && li->has_children ()) { + ++li; + } + if (! li.at_end ()) { + mp_control_panel->set_current_layer (li); + } + } + // signal to any observers file_open_event (); @@ -3456,6 +3474,18 @@ LayoutView::load_layout (const std::string &filename, const db::LoadLayoutOption // create the initial layer properties create_initial_layer_props (cv_index, lyp_file, add_other_layers); + // select the first layer if nothing else is selected + if (cv_index == 0 && ! mp_control_panel->has_selection ()) { + const lay::LayerPropertiesList &lp = get_properties (); + lay::LayerPropertiesConstIterator li = lp.begin_const_recursive (); + while (! li.at_end () && li->has_children ()) { + ++li; + } + if (! li.at_end ()) { + mp_control_panel->set_current_layer (li); + } + } + // signal to any observers file_open_event (); diff --git a/testdata/algo/deep_region_au11.gds b/testdata/algo/deep_region_au11.gds index 764182714..cb37c402b 100644 Binary files a/testdata/algo/deep_region_au11.gds and b/testdata/algo/deep_region_au11.gds differ diff --git a/testdata/drc/drcSimpleTests_20.drc b/testdata/drc/drcSimpleTests_20.drc index 5468d4f58..36eb31718 100644 --- a/testdata/drc/drcSimpleTests_20.drc +++ b/testdata/drc/drcSimpleTests_20.drc @@ -12,6 +12,18 @@ l2 = input(2, 0) l1.output(1, 0) l2.output(2, 0) +def split_vs_normal(r, f1, f2, *args) + d1 = r.send(f1, *args)[0].data + d2 = r.send(f2, *args).data + d1.to_s == d2.to_s || raise("#{f1.to_s} vs. #{f2.to_s} check failed: #{d1.to_s} != #{d2.to_s}") +end + +def splitn_vs_normal(r, f1, f2, *args) + d1 = r.send(f1, *args)[1].data + d2 = r.send(f2, *args).data + d1.to_s == d2.to_s || raise("#{f1.to_s} vs. #{f2.to_s} check failed: #{d1.to_s} != #{d2.to_s}") +end + l1.interacting(l2, 1).output(100, 0) l1.interacting(l2, 2).output(101, 0) l1.interacting(l2, 1..2).output(102, 0) @@ -22,6 +34,11 @@ else end l1.interacting(l2, 1, 2).output(104, 0) +split_vs_normal(l1, :split_interacting, :interacting, l2, 1) +split_vs_normal(l1, :split_interacting, :interacting, l2, 2) +split_vs_normal(l1, :split_interacting, :interacting, l2, 1..2) +split_vs_normal(l1, :split_interacting, :interacting, l2, 1, 2) + l1.overlapping(l2, 1).output(110, 0) l1.overlapping(l2, 2).output(111, 0) l1.overlapping(l2, 1..2).output(112, 0) @@ -32,6 +49,11 @@ else end l1.overlapping(l2, 1, 2).output(114, 0) +split_vs_normal(l1, :split_overlapping, :overlapping, l2, 1) +split_vs_normal(l1, :split_overlapping, :overlapping, l2, 2) +split_vs_normal(l1, :split_overlapping, :overlapping, l2, 1..2) +split_vs_normal(l1, :split_overlapping, :overlapping, l2, 1, 2) + l = l1.dup l.select_interacting(l2, 1) l.output(200, 0) @@ -82,6 +104,11 @@ else end l1.not_interacting(l2, 1, 2).output(304, 0) +splitn_vs_normal(l1, :split_interacting, :not_interacting, l2, 1) +splitn_vs_normal(l1, :split_interacting, :not_interacting, l2, 2) +splitn_vs_normal(l1, :split_interacting, :not_interacting, l2, 1..2) +splitn_vs_normal(l1, :split_interacting, :not_interacting, l2, 1, 2) + l1.not_overlapping(l2, 1).output(310, 0) l1.not_overlapping(l2, 2).output(311, 0) l1.not_overlapping(l2, 1..2).output(312, 0) @@ -92,6 +119,11 @@ else end l1.not_overlapping(l2, 1, 2).output(314, 0) +splitn_vs_normal(l1, :split_overlapping, :not_overlapping, l2, 1) +splitn_vs_normal(l1, :split_overlapping, :not_overlapping, l2, 2) +splitn_vs_normal(l1, :split_overlapping, :not_overlapping, l2, 1..2) +splitn_vs_normal(l1, :split_overlapping, :not_overlapping, l2, 1, 2) + l = l1.dup l.select_not_interacting(l2, 1) l.output(400, 0) diff --git a/testdata/drc/drcSimpleTests_24.drc b/testdata/drc/drcSimpleTests_24.drc index 3b594e534..3c69ec3bc 100644 --- a/testdata/drc/drcSimpleTests_24.drc +++ b/testdata/drc/drcSimpleTests_24.drc @@ -10,11 +10,33 @@ b = input(2, 0) a.output(1, 0) b.output(2, 0) +def split_vs_normal(r, f1, f2, *args) + d1 = r.send(f1, *args)[0].data + d2 = r.send(f2, *args).data + d1.to_s == d2.to_s || raise("#{f1.to_s} vs. #{f2.to_s} check failed: #{d1.to_s} != #{d2.to_s}") +end + +def splitn_vs_normal(r, f1, f2, *args) + d1 = r.send(f1, *args)[1].data + d2 = r.send(f2, *args).data + d1.to_s == d2.to_s || raise("#{f1.to_s} vs. #{f2.to_s} check failed: #{d1.to_s} != #{d2.to_s}") +end + a.covering(b).output(100, 0) a.covering(b, 1..1).output(101, 0) a.covering(b, 2..2).output(102, 0) a.covering(b, 3..3).output(103, 0) b.inside(a).output(110, 0) +a.not_covering(b).output(120, 0) +b.not_inside(a).output(130, 0) + +split_vs_normal(a, :split_covering, :covering, b) +split_vs_normal(a, :split_covering, :covering, b, 1..1) +split_vs_normal(a, :split_covering, :covering, b, 2..2) +split_vs_normal(a, :split_covering, :covering, b, 3..3) +split_vs_normal(b, :split_inside, :inside, a) +splitn_vs_normal(a, :split_covering, :not_covering, b) +splitn_vs_normal(b, :split_inside, :not_inside, a) deep @@ -26,4 +48,14 @@ a.covering(b, 1..1).output(201, 0) a.covering(b, 2..2).output(202, 0) a.covering(b, 3..3).output(203, 0) b.inside(a).output(210, 0) +a.not_covering(b).output(220, 0) +b.not_inside(a).output(230, 0) + +split_vs_normal(a, :split_covering, :covering, b) +split_vs_normal(a, :split_covering, :covering, b, 1..1) +split_vs_normal(a, :split_covering, :covering, b, 2..2) +split_vs_normal(a, :split_covering, :covering, b, 3..3) +split_vs_normal(b, :split_inside, :inside, a) +splitn_vs_normal(a, :split_covering, :not_covering, b) +splitn_vs_normal(b, :split_inside, :not_inside, a) diff --git a/testdata/drc/drcSimpleTests_30.drc b/testdata/drc/drcSimpleTests_30.drc new file mode 100644 index 000000000..de3b78fee --- /dev/null +++ b/testdata/drc/drcSimpleTests_30.drc @@ -0,0 +1,18 @@ + +source $drc_test_source +target $drc_test_target + +b = input(0, 0) +a = input(1, 0) + +b.output(0, 0) +a.output(1, 0) + +a.with_density(0..0.1, tile_size(10.um), tile_boundary(b)).output(100, 0) +a.without_density(0..0.1, tile_size(10.um)).output(101, 0) +a.with_density(0.1, nil, tile_size(10.um), tile_origin(25.um, 10.um)).output(102, 0) +a.with_density(0.1, nil, tile_size(10.um, 20.um)).output(103, 0) +a.with_density(0.1, 1.0, tile_size(10.um), tile_step(10.um, 20.um)).output(104, 0) +a.with_density(0.1, nil, tile_size(10.um), tile_origin(25.um, 10.um), tile_count(10, 15)).output(105, 0) +a.with_density(0..0.1, tile_size(100.um), tile_step(10.um)).output(110, 0) + diff --git a/testdata/drc/drcSimpleTests_30.gds b/testdata/drc/drcSimpleTests_30.gds new file mode 100644 index 000000000..14b2f86b8 Binary files /dev/null and b/testdata/drc/drcSimpleTests_30.gds differ diff --git a/testdata/drc/drcSimpleTests_au24.gds b/testdata/drc/drcSimpleTests_au24.gds index 8ca7815d2..e650d083b 100644 Binary files a/testdata/drc/drcSimpleTests_au24.gds and b/testdata/drc/drcSimpleTests_au24.gds differ diff --git a/testdata/drc/drcSimpleTests_au30.gds b/testdata/drc/drcSimpleTests_au30.gds new file mode 100644 index 000000000..f09ab94b3 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au30.gds differ diff --git a/testdata/drc/drcSuiteTests.drc b/testdata/drc/drcSuiteTests.drc index 9574e8e96..35615d564 100644 --- a/testdata/drc/drcSuiteTests.drc +++ b/testdata/drc/drcSuiteTests.drc @@ -148,6 +148,7 @@ def run_testsuite(dm, ic, tiled = false, hier = false) b.not_interacting(a).output(lb, dm + 1) b.interacting(empty).output(lb, dm + 2) b.not_interacting(empty).output(lb, dm + 3) + b.interacting(a).in(b).output(lb + 1, dm) (b|a).not_in(b).output(lb + 2, dm) x.in(b).output(lb + 3, dm) @@ -160,18 +161,42 @@ def run_testsuite(dm, ic, tiled = false, hier = false) b.not_inside(c).output(lb, dm + 1) b.inside(empty).output(lb, dm + 2) b.not_inside(empty).output(lb, dm + 3) + (p, m) = b.split_inside(c) + p.output(lb, dm + 10) + m.output(lb, dm + 11) + + b.covering(c).output(lb, dm + 100) + b.not_covering(c).output(lb, dm + 101) + b.covering(empty).output(lb, dm + 102) + b.not_covering(empty).output(lb, dm + 103) + (p, m) = b.split_covering(c) + p.output(lb, dm + 110) + m.output(lb, dm + 111) + b.outside(c).output(lb + 1, dm) b.not_outside(c).output(lb + 1, dm + 1) b.outside(empty).output(lb + 1, dm + 2) b.not_outside(empty).output(lb + 1, dm + 3) + (p, m) = b.split_outside(c) + p.output(lb + 1, dm + 10) + m.output(lb + 1, dm + 11) + b.overlapping(c).output(lb + 2, dm) b.not_overlapping(c).output(lb + 2, dm + 1) b.overlapping(empty).output(lb + 2, dm + 2) b.not_overlapping(empty).output(lb + 2, dm + 3) + (p, m) = b.split_overlapping(c) + p.output(lb + 2, dm + 10) + m.output(lb + 2, dm + 11) + b.interacting(c).output(lb + 3, dm) b.not_interacting(c).output(lb + 3, dm + 1) b.interacting(empty).output(lb + 3, dm + 2) b.not_interacting(empty).output(lb + 3, dm + 3) + (p, m) = b.split_interacting(c) + p.output(lb + 3, dm + 10) + m.output(lb + 3, dm + 11) + bdup = b.dup bdup.select_inside(c) bdup.xor(b.inside(c)).output(lb + 4, dm) diff --git a/testdata/drc/drcSuiteTests_au1.oas b/testdata/drc/drcSuiteTests_au1.oas index ef395210f..0dd5c6851 100644 Binary files a/testdata/drc/drcSuiteTests_au1.oas and b/testdata/drc/drcSuiteTests_au1.oas differ diff --git a/testdata/drc/drcSuiteTests_au2.oas b/testdata/drc/drcSuiteTests_au2.oas index 8a5528975..6ccbca614 100644 Binary files a/testdata/drc/drcSuiteTests_au2.oas and b/testdata/drc/drcSuiteTests_au2.oas differ diff --git a/testdata/drc/drcSuiteTests_au3.oas b/testdata/drc/drcSuiteTests_au3.oas index 4f5221a28..c42f0b098 100644 Binary files a/testdata/drc/drcSuiteTests_au3.oas and b/testdata/drc/drcSuiteTests_au3.oas differ diff --git a/testdata/drc/drcSuiteTests_au4.oas b/testdata/drc/drcSuiteTests_au4.oas index bff2c5694..1b2dc47b6 100644 Binary files a/testdata/drc/drcSuiteTests_au4.oas and b/testdata/drc/drcSuiteTests_au4.oas differ diff --git a/testdata/drc/drcSuiteTests_au5.oas b/testdata/drc/drcSuiteTests_au5.oas index c5ea03d11..ccb803594 100644 Binary files a/testdata/drc/drcSuiteTests_au5.oas and b/testdata/drc/drcSuiteTests_au5.oas differ diff --git a/testdata/drc/drcSuiteTests_au6.oas b/testdata/drc/drcSuiteTests_au6.oas index e1017d058..e9a693a4d 100644 Binary files a/testdata/drc/drcSuiteTests_au6.oas and b/testdata/drc/drcSuiteTests_au6.oas differ diff --git a/testdata/python/dbPolygonTest.py b/testdata/python/dbPolygonTest.py index 1b653d102..ce679554f 100644 --- a/testdata/python/dbPolygonTest.py +++ b/testdata/python/dbPolygonTest.py @@ -289,6 +289,9 @@ class DBPolygonTests(unittest.TestCase): p = pya.Polygon( [ pya.Point.new(0, 0), pya.Point.new(10, 50), pya.Point.new(0, 100), pya.Point.new(200, 100), pya.Point.new(200, 0) ]) self.assertEqual(str(p.smooth(5)), "(0,0;10,50;0,100;200,100;200,0)") self.assertEqual(str(p.smooth(15)), "(0,0;0,100;200,100;200,0)") + p = pya.Polygon( [ pya.Point.new(0, 0), pya.Point.new(10, 50), pya.Point.new(10, 100), pya.Point.new(200, 100), pya.Point.new(200, 0) ]) + self.assertEqual(str(p.smooth(15, False)), "(0,0;10,100;200,100;200,0)") + self.assertEqual(str(p.smooth(15, True)), "(0,0;10,50;10,100;200,100;200,0)") # Ellipse constructor p = pya.Polygon.ellipse( pya.Box(-10000, -20000, 30000, 40000), 200 ) diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index 468864b35..8f94efafb 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -304,6 +304,9 @@ class DBPolygon_TestClass < TestBase p = RBA::Polygon::new( [ RBA::Point.new(0, 0), RBA::Point.new(10, 50), RBA::Point.new(0, 100), RBA::Point.new(200, 100), RBA::Point.new(200, 0) ]) assert_equal(p.smooth(5).to_s, "(0,0;10,50;0,100;200,100;200,0)") assert_equal(p.smooth(15).to_s, "(0,0;0,100;200,100;200,0)") + p = RBA::Polygon::new( [ RBA::Point.new(0, 0), RBA::Point.new(10, 50), RBA::Point.new(10, 100), RBA::Point.new(200, 100), RBA::Point.new(200, 0) ]) + assert_equal(p.smooth(15, false).to_s, "(0,0;10,100;200,100;200,0)") + assert_equal(p.smooth(15, true).to_s, "(0,0;10,50;10,100;200,100;200,0)") # Ellipse constructor p = RBA::Polygon::ellipse( RBA::Box::new(-10000, -20000, 30000, 40000), 200 ) diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index 27cd9b257..79985b676 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -525,34 +525,49 @@ class DBRegion_TestClass < TestBase r1 = RBA::Region::new r1.insert(RBA::Box::new(10, 20, 100, 200)) + r11 = r1.dup r1.insert(RBA::Box::new(50, 70, 150, 270)) r1.insert(RBA::Box::new(100, 70, 250, 270)) r2 = RBA::Region::new(RBA::Box::new(-10, -20, 100, 200)) r3 = RBA::Region::new(RBA::Box::new(150, 270, 160, 280)) r3 += r2 + r21 = r2.dup + r21 += RBA::Region::new(RBA::Box::new(110, -20, 200, 200)) assert_equal(r1.merged_semantics?, true) r1.merged_semantics = false assert_equal(r1.merged_semantics?, false) assert_equal(r1.inside(r2).to_s, "(10,20;10,200;100,200;100,20)") + assert_equal(r1.split_inside(r2)[0].to_s, "(10,20;10,200;100,200;100,20)") assert_equal(csort(r1.not_inside(r2).to_s), csort("(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) + assert_equal(csort(r1.split_inside(r2)[1].to_s), csort("(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) + assert_equal(r21.covering(r11).to_s, "(-10,-20;-10,200;100,200;100,-20)") + assert_equal(r21.split_covering(r11)[0].to_s, "(-10,-20;-10,200;100,200;100,-20)") + assert_equal(csort(r21.not_covering(r11).to_s), csort("(110,-20;110,200;200,200;200,-20)")) + assert_equal(csort(r21.split_covering(r11)[1].to_s), csort("(110,-20;110,200;200,200;200,-20)")) assert_equal(csort(r1.interacting(r2).to_s), csort("(10,20;10,200;100,200;100,20);(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) assert_equal(csort(r1.interacting(r3, 1).to_s), csort("(10,20;10,200;100,200;100,20);(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) assert_equal(csort(r1.interacting(r3, 2).to_s), csort("(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) + assert_equal(csort(r1.split_interacting(r3, 2)[0].to_s), csort("(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) assert_equal(r1.interacting(r3, 3).to_s, "") assert_equal(r1.interacting(r3, 1, 1).to_s, "(10,20;10,200;100,200;100,20)") assert_equal(csort(r1.interacting(r3, 2, 2).to_s), csort("(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) assert_equal(r1.not_interacting(r2).to_s, "") assert_equal(r1.not_interacting(r3, 1).to_s, "") assert_equal(r1.not_interacting(r3, 2).to_s, "(10,20;10,200;100,200;100,20)") + assert_equal(r1.split_interacting(r3, 2)[1].to_s, "(10,20;10,200;100,200;100,20)") assert_equal(csort(r1.not_interacting(r3, 3).to_s), csort("(10,20;10,200;100,200;100,20);(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) assert_equal(csort(r1.not_interacting(r3, 1, 1).to_s), csort("(50,70;50,270;150,270;150,70);(100,70;100,270;250,270;250,70)")) assert_equal(r1.not_interacting(r3, 2, 2).to_s, "(10,20;10,200;100,200;100,20)") assert_equal(csort(r1.overlapping(r2).to_s), csort("(10,20;10,200;100,200;100,20);(50,70;50,270;150,270;150,70)")) + assert_equal(csort(r1.split_overlapping(r2)[0].to_s), csort("(10,20;10,200;100,200;100,20);(50,70;50,270;150,270;150,70)")) assert_equal(r1.not_overlapping(r2).to_s, "(100,70;100,270;250,270;250,70)") + assert_equal(r1.split_overlapping(r2)[1].to_s, "(100,70;100,270;250,270;250,70)") assert_equal(r1.outside(r2).to_s, "(100,70;100,270;250,270;250,70)") + assert_equal(r1.split_outside(r2)[0].to_s, "(100,70;100,270;250,270;250,70)") assert_equal(csort(r1.not_outside(r2).to_s), csort("(10,20;10,200;100,200;100,20);(50,70;50,270;150,270;150,70)")) + assert_equal(csort(r1.split_outside(r2)[1].to_s), csort("(10,20;10,200;100,200;100,20);(50,70;50,270;150,270;150,70)")) e2 = RBA::Edges::new(RBA::Edge::new(-10, -20, 100, 200)) e3 = RBA::Edges::new(RBA::Edge::new(150, 270, 160, 280)) @@ -561,12 +576,14 @@ class DBRegion_TestClass < TestBase assert_equal(csort(r1.interacting(e2).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70);(10,20;10,200;100,200;100,20)")) assert_equal(csort(r1.interacting(e3, 1).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70);(10,20;10,200;100,200;100,20)")) assert_equal(csort(r1.interacting(e3, 2).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70)")) + assert_equal(csort(r1.split_interacting(e3, 2)[0].to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70)")) assert_equal(r1.interacting(e3, 3).to_s, "") assert_equal(r1.interacting(e3, 1, 1).to_s, "(10,20;10,200;100,200;100,20)") assert_equal(csort(r1.interacting(e3, 2, 2).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70)")) assert_equal(r1.not_interacting(e2).to_s, "") assert_equal(r1.not_interacting(e3, 1).to_s, "") assert_equal(r1.not_interacting(e3, 2).to_s, "(10,20;10,200;100,200;100,20)") + assert_equal(r1.split_interacting(e3, 2)[1].to_s, "(10,20;10,200;100,200;100,20)") assert_equal(csort(r1.not_interacting(e3, 3).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70);(10,20;10,200;100,200;100,20)")) assert_equal(csort(r1.not_interacting(e3, 1, 1).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70)")) assert_equal(r1.not_interacting(e3, 2, 2).to_s, "(10,20;10,200;100,200;100,20)") @@ -577,6 +594,7 @@ class DBRegion_TestClass < TestBase assert_equal(csort(r1.interacting(t2).to_s), csort("(50,70;50,270;150,270;150,70);(10,20;10,200;100,200;100,20)")) assert_equal(csort(r1.interacting(t3, 1).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70);(10,20;10,200;100,200;100,20)")) + assert_equal(csort(r1.split_interacting(t3, 1)[0].to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70);(10,20;10,200;100,200;100,20)")) assert_equal(r1.interacting(t3, 2).to_s, "(50,70;50,270;150,270;150,70)") assert_equal(r1.interacting(t3, 3).to_s, "") assert_equal(csort(r1.interacting(t3, 1, 1).to_s), csort("(100,70;100,270;250,270;250,70);(10,20;10,200;100,200;100,20)")) @@ -584,6 +602,7 @@ class DBRegion_TestClass < TestBase assert_equal(r1.not_interacting(t2).to_s, "(100,70;100,270;250,270;250,70)") assert_equal(r1.not_interacting(t3, 1).to_s, "") assert_equal(csort(r1.not_interacting(t3, 2).to_s), csort("(100,70;100,270;250,270;250,70);(10,20;10,200;100,200;100,20)")) + assert_equal(csort(r1.split_interacting(t3, 2)[1].to_s), csort("(100,70;100,270;250,270;250,70);(10,20;10,200;100,200;100,20)")) assert_equal(csort(r1.not_interacting(t3, 3).to_s), csort("(100,70;100,270;250,270;250,70);(50,70;50,270;150,270;150,70);(10,20;10,200;100,200;100,20)")) assert_equal(r1.not_interacting(t3, 1, 1).to_s, "(50,70;50,270;150,270;150,70)") assert_equal(csort(r1.not_interacting(t3, 2, 2).to_s), csort("(100,70;100,270;250,270;250,70);(10,20;10,200;100,200;100,20)"))