diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index a7882ca18..222cd8ee6 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -871,18 +871,27 @@ std::string CompoundRegionLogicalCaseSelectOperationNode::generated_description return r + CompoundRegionMultiInputOperationNode::description (); } -template -void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const +CompoundRegionLogicalCaseSelectOperationNode::ResultType +CompoundRegionLogicalCaseSelectOperationNode::result_type () const +{ + ResultType result = Region; + for (size_t i = 1; i < children (); i += 2) { + if (i == 1) { + result = child (i)->result_type (); + } else { + tl_assert (result == child (i)->result_type ()); + } + } + return result; +} + +template +void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const { bool ok = false; for (unsigned int ci = 0; ci < children (); ++ci) { - if (! ok && ci % 2 == 1) { - // skip false branches - continue; - } - shape_interactions computed; const shape_interactions &child_interactions = interactions_for_child (interactions, ci, computed); @@ -890,14 +899,24 @@ void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local (db:: if (ci % 2 == 0) { - ok = node->compute_local_bool (layout, child_interactions, max_vertex_count, area_ratio); + if (ci + 1 < children ()) { - } else { + ok = node->compute_local_bool (layout, child_interactions, max_vertex_count, area_ratio); + continue; + + } else { + // executes the following statement as default branch + ok = true; + } + + } + + if (ok) { if (m_multi_layer && results.size () > size_t (ci / 2)) { - std::vector > one; - one.push_back (std::unordered_set ()); + std::vector > one; + one.push_back (std::unordered_set ()); node->compute_local (layout, child_interactions, one, max_vertex_count, area_ratio); results[ci / 2].swap (one.front ()); diff --git a/src/db/db/dbCompoundOperation.h b/src/db/db/dbCompoundOperation.h index 323093085..f5f4109eb 100644 --- a/src/db/db/dbCompoundOperation.h +++ b/src/db/db/dbCompoundOperation.h @@ -130,20 +130,23 @@ public: if (result_type () == Region) { std::vector > res; + res.push_back (std::unordered_set ()); compute_local (layout, interactions, res, max_vertex_count, area_ratio); - return ! res.empty (); + return ! res.front ().empty (); } else if (result_type () == Edges) { std::vector > res; + res.push_back (std::unordered_set ()); compute_local (layout, interactions, res, max_vertex_count, area_ratio); - return ! res.empty (); + return ! res.front ().empty (); } else if (result_type () == EdgePairs) { std::vector > res; + res.push_back (std::unordered_set ()); compute_local (layout, interactions, res, max_vertex_count, area_ratio); - return ! res.empty (); + return ! res.front ().empty (); } else { return false; @@ -664,7 +667,7 @@ public: virtual std::string generated_description () const; // specifies the result type - virtual ResultType result_type () const { return Region; } + virtual ResultType result_type () const; // the different computation slots virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const @@ -677,9 +680,29 @@ public: implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); } + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + + virtual void do_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + implement_compute_local (layout, interactions, results, max_vertex_count, area_ratio); + } + private: - template - void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; + template + void implement_compute_local (db::Layout *layout, const shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const; bool m_multi_layer; }; diff --git a/src/db/db/dbRegionProcessors.cc b/src/db/db/dbRegionProcessors.cc index 2186312c1..72f608ecb 100644 --- a/src/db/db/dbRegionProcessors.cc +++ b/src/db/db/dbRegionProcessors.cc @@ -87,6 +87,17 @@ void CornerDetectorCore::detect_corners (const db::Polygon &poly, const CornerPo } } +// ----------------------------------------------------------------------------------- +// Extents implementation + +void Extents::process (const db::Polygon &poly, std::vector &result) const +{ + db::Box b = poly.box (); + if (! b.empty ()) { + result.push_back (db::Polygon (b)); + } +} + // ----------------------------------------------------------------------------------- // RelativeExtents implementation @@ -105,7 +116,7 @@ void RelativeExtents::process (const db::Polygon &poly, std::vector const TransformationReducer *RelativeExtents::vars () const { - if (m_dx == 0 && m_dy == 0 && fabs (m_fx1) < db::epsilon && fabs (m_fy1) < db::epsilon && fabs (m_fx2) < db::epsilon && fabs (m_fy2) < db::epsilon) { + if (m_dx == 0 && m_dy == 0 && fabs (m_fx1) < db::epsilon && fabs (m_fy1) < db::epsilon && fabs (1.0 - m_fx2) < db::epsilon && fabs (1.0 - m_fy2) < db::epsilon) { return 0; } else if (m_dx == m_dy && fabs (m_fx1 - m_fy1) < db::epsilon && fabs (1.0 - (m_fx1 + m_fx2)) < db::epsilon && fabs (m_fx2 - m_fy2) < db::epsilon && fabs (1.0 - (m_fy1 + m_fy2)) < db::epsilon) { return & m_isotropic_reducer; diff --git a/src/db/db/dbRegionProcessors.h b/src/db/db/dbRegionProcessors.h index b56438971..d6413e41f 100644 --- a/src/db/db/dbRegionProcessors.h +++ b/src/db/db/dbRegionProcessors.h @@ -158,6 +158,27 @@ public: // ----------------------------------------------------------------------------------- // Extents +/** + * @brief A processor delivering the extents (bounding box) of the merged polygons + */ +class DB_PUBLIC Extents + : public db::PolygonProcessorBase +{ +public: + Extents () + { + // .. nothing yet .. + } + + void process (const db::Polygon &poly, std::vector &result) const; + + virtual const TransformationReducer *vars () const { return 0; } + virtual bool result_is_merged () const { return false; } + virtual bool result_must_not_be_merged () const { return false; } + virtual bool requires_raw_input () const { return false; } + virtual bool wants_variants () const { return false; } // variants are too common, so don't do this +}; + /** * @brief A processor delivering the relative extents (bounding box) of the merged polygons * This processor allows over- or undersizing of the resulting box by a given amount and delivery diff --git a/src/db/unit_tests/dbCompoundOperationTests.cc b/src/db/unit_tests/dbCompoundOperationTests.cc index ef4029804..fb767d044 100644 --- a/src/db/unit_tests/dbCompoundOperationTests.cc +++ b/src/db/unit_tests/dbCompoundOperationTests.cc @@ -29,6 +29,7 @@ #include "dbCompoundOperation.h" #include "dbReader.h" #include "dbRecursiveShapeIterator.h" +#include "dbRegionUtils.h" #include "dbTestSupport.h" #include "tlStream.h" @@ -337,3 +338,59 @@ TEST(8_PullWithEdgeOperation) db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au8.gds"); } +TEST(9_LogicalSelectOperation) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/drc/compound_9.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::RegionCheckOptions check_options; + check_options.metrics = db::Projection; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + db::Region r (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l1)); + + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + db::Region r2 (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l2)); + + // the if/then ladder is: + // + // if (area > 10um2) return sized(+50nm) + // else if (is_rectangle) return sized(-50nm) + // else return bbox + + db::CompoundRegionOperationPrimaryNode *primary = new db::CompoundRegionOperationPrimaryNode (); + + std::vector inputs; + + db::CompoundRegionFilterOperationNode *condition1 = new db::CompoundRegionFilterOperationNode (new db::RegionAreaFilter (0, 10000000, true), primary, true); + inputs.push_back (condition1); + + db::CompoundRegionSizeOperationNode *result1 = new db::CompoundRegionSizeOperationNode (50, 50, 2, primary); + inputs.push_back (result1); + + db::CompoundRegionFilterOperationNode *condition2 = new db::CompoundRegionFilterOperationNode (new db::RectangleFilter (false), primary, true); + inputs.push_back (condition2); + + db::CompoundRegionSizeOperationNode *result2 = new db::CompoundRegionSizeOperationNode (-50, -50, 2, primary); + inputs.push_back (result2); + + db::CompoundRegionProcessingOperationNode *result_default = new db::CompoundRegionProcessingOperationNode (new db::Extents (), primary, true); + inputs.push_back (result_default); + + db::CompoundRegionLogicalCaseSelectOperationNode select_node (false, inputs); + + db::Region res = r.cop_to_region (select_node); + + unsigned int l1000 = ly.get_layer (db::LayerProperties (1000, 0)); + res.insert_into (&ly, *ly.begin_top_down (), l1000); + + CHECKPOINT(); + db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au9.gds"); +} + diff --git a/testdata/drc/compound_9.gds b/testdata/drc/compound_9.gds new file mode 100644 index 000000000..534f8b356 Binary files /dev/null and b/testdata/drc/compound_9.gds differ diff --git a/testdata/drc/compound_au9.gds b/testdata/drc/compound_au9.gds new file mode 100644 index 000000000..b7d3dd391 Binary files /dev/null and b/testdata/drc/compound_au9.gds differ