From 9008464268cec47959c5b2edede9226702a96a96 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 10:26:01 +0100 Subject: [PATCH 01/12] WIP: hierarchical mode for Region#in and Region#not_in --- src/db/db/dbDeepRegion.cc | 44 +++++++++++--- src/db/db/dbDeepRegion.h | 1 + src/db/db/dbRegionLocalOperations.cc | 77 +++++++++++++++++++++++++ src/db/db/dbRegionLocalOperations.h | 18 ++++++ src/db/unit_tests/dbDeepRegionTests.cc | 49 ++++++++++++++++ testdata/algo/deep_region_au31.gds | Bin 0 -> 9666 bytes testdata/algo/deep_region_l31.gds | Bin 0 -> 2274 bytes 7 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 testdata/algo/deep_region_au31.gds create mode 100644 testdata/algo/deep_region_l31.gds diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index f38d94228..8d1abf149 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1550,13 +1550,6 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const return res.release (); } -RegionDelegate * -DeepRegion::in (const Region &other, bool invert) const -{ - // TODO: this can be optimized maybe ... - return db::AsIfFlatRegion::in (other, invert); -} - template static Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &node) @@ -1796,6 +1789,43 @@ private: } +RegionDelegate * +DeepRegion::in (const Region &other, bool invert) const +{ + // TODO: we could offer in_and_not_it (both at once) + InteractingOutputMode output_mode = invert ? Negative : Positive; + return in_and_out (other, output_mode).first; +} + +std::pair +DeepRegion::in_and_out (const Region &other, InteractingOutputMode output_mode) const +{ + std::unique_ptr dr_holder; + const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); + if (! other_deep) { + // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization + dr_holder.reset (new db::DeepRegion (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + const db::DeepLayer &polygons = merged_deep_layer (); + const db::DeepLayer &other_polygons = other_deep->merged_deep_layer (); + + db::ContainedLocalOperation op (output_mode); + + 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 ()); + proc.set_report_progress (report_progress ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (polygons.store ()->threads ()); + + InteractingResultHolder orh (output_mode, merged_semantics (), polygons); + + proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ()); + + return orh.result_pair (); +} + 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 { diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 75ea1961d..aec863284 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -155,6 +155,7 @@ protected: 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 std::pair in_and_out (const Region &other, InteractingOutputMode output_mode) 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/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index d6aa19b9e..9f42af6c6 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -915,6 +915,83 @@ template class DB_PUBLIC interacting_local_operation +contained_local_operation::contained_local_operation (InteractingOutputMode output_mode) + : m_output_mode (output_mode) +{ + // .. nothing yet .. +} + +template +db::Coord contained_local_operation::dist () const +{ + return 0; +} + +template +void contained_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); + } + + db::EdgeProcessor ep; + ep.set_base_verbosity (50); + + std::set others; + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j).second); + } + } + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const TS &subject = interactions.subject_shape (i->first); + if (others.find (subject) != others.end ()) { + if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) { + results [0].insert (subject); + } + } else { + if (m_output_mode == Negative) { + results [0].insert (subject); + } else if (m_output_mode == PositiveAndNegative) { + results [1].insert (subject); + } + } + } +} + +template +OnEmptyIntruderHint +contained_local_operation::on_empty_intruder_hint () const +{ + 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::Ignore; + } +} + +template +std::string contained_local_operation::description () const +{ + return tl::to_string (tr ("Select polygons contained in other region")); +} + +// explicit instantiations +template class DB_PUBLIC contained_local_operation; +template class DB_PUBLIC contained_local_operation; + +// --------------------------------------------------------------------------------------------------------------- + template pull_local_operation::pull_local_operation (int mode, bool touching) : m_mode (mode), m_touching (touching) diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 6d81c2b0d..7a457e413 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -351,6 +351,24 @@ public: typedef pull_with_text_local_operation PullWithTextLocalOperation; +template +class contained_local_operation + : public local_operation +{ +public: + contained_local_operation (InteractingOutputMode output_mode); + + 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; + virtual OnEmptyIntruderHint on_empty_intruder_hint () const; + virtual std::string description () const; + +private: + InteractingOutputMode m_output_mode; +}; + +typedef contained_local_operation ContainedLocalOperation; + } // namespace db #endif diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index fb1dfffbc..052a2ccea 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2018,6 +2018,55 @@ TEST(30c_interact_with_count_text) EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)"); } +TEST(31_in) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l31.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + + db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r1r = r1; + r1r.set_merged_semantics (false); + db::Region r2r = r2; + r2r.set_merged_semantics (false); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.in (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in (r1, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in (r1, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.in (r1r)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.in (r1r, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2r.in (r1r)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2r.in (r1r, true)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds"); +} + TEST(100_Integration) { db::Layout ly; diff --git a/testdata/algo/deep_region_au31.gds b/testdata/algo/deep_region_au31.gds new file mode 100644 index 0000000000000000000000000000000000000000..f079981bf337bb0c5fb0767823e7d9126e85b843 GIT binary patch literal 9666 zcmb`MKWtT19LIlseZ75@f)84x(psvNv?b3{Q;nEZ)7Cl|n*d3NrW3}6ffxr96C_T= zKqQ8k4n)NeH35?j4h#$q4#YS(I50RkFc2pP1_uWQf8TS?xA*>D?+Q#{FWozN z>+7`@8R?1ZvMf_oy&;nAt4U3={WTGpYj%r_{UP$=eb1@7$iZJk$ksn1$45j+j#JhT zMB-&Xh#b{laQc!+-{YLe^zY$S5t8GSW${{AU-4()icY#LLKga>`d-~1en9B@bw4EA zl~H|bT+ip6o`G_5PUPiNIoYms`d)e3Q&`APtt&i*SFp=xG%{8N9)95eeqMKaf|E-k&)yLs*{+Q053H+pQUu)pkshzEgJiohsz3h7>p|#d`g1}b`lI^pF~5Eg z>&AXatUvTe^{sI~ABeSMeiG{m{ZT#QAJcV$6FMH}N3vZR)#Kct1@Y`KH_3KoQP1ko zX4~{pY-2f$jPDN=Z+4q)SlDdKTA|_;FEYuZwhDFGg8Z zF~`2ueCUSyu@^O$UcFqpXID#5`H^ejOLw&{Y3`D!D^urveE~U6S$2jl9^M_)9&onh zYaNMN1vel$PFWVupd2Q};o#eLMa9pWY2XJx5tN zmlG}#`lIuse?osjoGbJs+m%uM%!jIPYE4nXp|J*%?aHYBy(RC);PjBl`}#~txOC`` z>d))h!9zee`Um<;vc1h)`ieJ?3i8Xut02D^FEzi6J|Vx1KID(fj~(Wh(c|vWGwAOS zjVJzAN3va6e7@AX+CTiWz7xNz=V*Q$()G?b!1f6gL*-- zT^ZFc%=vYIqkoCKt+7bVANtGmZXe5f4$u820%G2?^O~pEL{>L)vR_#i$L-_vvab=~ z;9Ze5T@Q)c5&EP0Px}2nK&<~$tS1or2>oSxw~x>6`+b1e$LCGI{x2`(#6H5fvN&!Z zS4aFlK&*dV*F$0-p}$P;>iEqIUJpX|{YFmQJ8!T1`zMHaVSF^+SIe5CEfH|~p~#Q= ze903Uqd_|E#7Mod5SY9+1~cP8$I45csaOl!@p-F+m+GtNB&|Q2p#g9 zWczmdn+<=b0QaaTfA=US?i!)LIR9Y9zGmW8;A@QM@-yMyWb_HXX7mZZMt!Hg#5nF8 z5`2mJPJM-O+&Y49xO}IdkP%;@zEfXd9Jh{8_uYF#KOiH%Kz&udVB%Ha3ykOXm*5Lq z^sN8%1Cs4+zHq2RUoiRvUoiRvUoiRvUoiUi`{)Z#v`*_U7`cxcJ;zapZz+rS+0b9C z%SNBzOGb}-=HUnazRCM1$#!LQ{^C6r<8hBABllP{e}XR>J?@v759Ga*WVre3I(V{O`;G>M^>PdnR8h!iw(4Nnszj&V1cj|+T zYrYR;B(JIO)JGY|?IXcQjlP)Qd@smIepBD64>OM2M}iMi?|ird-()!HzUN^)x1NOitI;RiKey=l{T$9=2jANneS(i0eS(i0eS(i0eS(h~eS(h} zeS(irU)4R8@iyNNey^~@?;DIh!Ph2>?^gxB#&~W&3BE>sr@q8EZXF4}M17~e!Z>an z3BE#or@p{AZXF4}Kz&udz<6#w3BE8@%-aflf$`jW5`4kv6MSKdewV&r^a;LT^a;LT z^a;LT^zHXqeoo`(wvzj-(Q_Pi?f2o(U%U?+eS$9;eZuFvEqdN}@wsRRpYM!5!557_ r;q%=VJ@2{vTt~8989o05U*`N(`7+~e)~8+iveECxm-YYr>vj1b2Yh2s literal 0 HcmV?d00001 diff --git a/testdata/algo/deep_region_l31.gds b/testdata/algo/deep_region_l31.gds new file mode 100644 index 0000000000000000000000000000000000000000..1c6661453820cac7cd0489128ead06045abd5c0f GIT binary patch literal 2274 zcmbuAF-#Oe6o&uXJN8aE;Q*rqFcLWenDfA(5fe0kG)59Ft{_wx8wz7AOiYX=1tu00 z7A9Iym}qHXL1|&EEi5c8jFkn2g{A+$dp~=U9Vy&o^KIVD|K`n`w{H+5iq)5|wMz1hFAvNyB)a=nGouCOkSW2#COAU+-;Lfjhx zSf~|&vCqKSk13~1z`zHn9pcCndr+n>J*l;tQFd) za8bMLqi01Wp8Ar0pXN@7e*vb)$&>&AuoZ4lyuQJwKz+??DJ&(-umt?=V z#S?r6h(q*MzL(K=NgL>sn zT2W`GwN2Z}PQAOs|JJ4b9Mn+~3)eqfN4ArBaUAGfZ{CY(`=L7gYkkdSZ_Ukv?PPF$ z>0NKGKht*C;SpV+634Aux7i1}*(3*Ic7%Ai05ztr<#kd|RXt&D2Po{MF&)fJMy~Er zw3s*YX#4QUa)79&xUb_BvC&O1FXOd1Riyq$YF|l-}_rhvtFGi;T9DLA`DQ%@d`saUZ7b|I#mh zO>YB{c|>a?qi%`zcyN7|VlZtdgZeuw>1`}Fhk(00 eQ&YEedpxM$WbSl_h`Q15^EGYv-NJvORKg!eQR&M7 literal 0 HcmV?d00001 From 25e61205d2fb2f672a7a6f8d534274b06579eb64 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 10:37:43 +0100 Subject: [PATCH 02/12] Deep implementation of in/not_in --- src/db/db/dbRegionLocalOperations.cc | 3 --- testdata/algo/deep_region_au31.gds | Bin 9666 -> 7298 bytes 2 files changed, 3 deletions(-) diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 9f42af6c6..33fe39dd6 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -939,9 +939,6 @@ void contained_local_operation::do_compute_local (db::Layout * /*lay tl_assert (results.size () == 2); } - db::EdgeProcessor ep; - ep.set_base_verbosity (50); - std::set others; for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { diff --git a/testdata/algo/deep_region_au31.gds b/testdata/algo/deep_region_au31.gds index f079981bf337bb0c5fb0767823e7d9126e85b843..4ff450d2f99e19b09ad2494ce62b2b1be6cdc473 100644 GIT binary patch delta 499 zcmX@)-DIi6z{bGD6u}_F$i)7Pftx{^fr~+rffJcMQAu48LvUkM2IJ%@JR%dzoF|{= z;+-tUXgql~5AVcd5N;TdyPHpN@+?M;$y@lrs-guTs&?~(Re`u5Rl%YVRVGp*AkEnl z5aH8Oyda~crJ+X4Kvb#7fmKz@fmJbTPR#OW)SS%4Xg}Fl8KlA#)1{jqFuq`(?7++p zcBc$0&*TM6>XW^>c_;s2v<8dKVbuZ4@8;#59K&inSy~Vx2XZ1*j!|^-1r~cCDZmOM z16b|BE`^!)8t7_}X&~3bOanO`WZG_^TS0OlH^WTR1e>M_Hcb;~nuQ!Y1A`1J&M4UY zj5U^J@orwm&Aa&%7#Cj_W}Iv-#XC7cym|6zso2RG(hid~q+KSjk$yi}TW-SS#|p8N a8x$QTJ1DwLKEta&`Lp6qHlPJ8EDQh~C5GJq literal 9666 zcmb`MKWtT19LIlseZ75@f)84x(psvNv?b3{Q;nEZ)7Cl|n*d3NrW3}6ffxr96C_T= zKqQ8k4n)NeH35?j4h#$q4#YS(I50RkFc2pP1_uWQf8TS?xA*>D?+Q#{FWozN z>+7`@8R?1ZvMf_oy&;nAt4U3={WTGpYj%r_{UP$=eb1@7$iZJk$ksn1$45j+j#JhT zMB-&Xh#b{laQc!+-{YLe^zY$S5t8GSW${{AU-4()icY#LLKga>`d-~1en9B@bw4EA zl~H|bT+ip6o`G_5PUPiNIoYms`d)e3Q&`APtt&i*SFp=xG%{8N9)95eeqMKaf|E-k&)yLs*{+Q053H+pQUu)pkshzEgJiohsz3h7>p|#d`g1}b`lI^pF~5Eg z>&AXatUvTe^{sI~ABeSMeiG{m{ZT#QAJcV$6FMH}N3vZR)#Kct1@Y`KH_3KoQP1ko zX4~{pY-2f$jPDN=Z+4q)SlDdKTA|_;FEYuZwhDFGg8Z zF~`2ueCUSyu@^O$UcFqpXID#5`H^ejOLw&{Y3`D!D^urveE~U6S$2jl9^M_)9&onh zYaNMN1vel$PFWVupd2Q};o#eLMa9pWY2XJx5tN zmlG}#`lIuse?osjoGbJs+m%uM%!jIPYE4nXp|J*%?aHYBy(RC);PjBl`}#~txOC`` z>d))h!9zee`Um<;vc1h)`ieJ?3i8Xut02D^FEzi6J|Vx1KID(fj~(Wh(c|vWGwAOS zjVJzAN3va6e7@AX+CTiWz7xNz=V*Q$()G?b!1f6gL*-- zT^ZFc%=vYIqkoCKt+7bVANtGmZXe5f4$u820%G2?^O~pEL{>L)vR_#i$L-_vvab=~ z;9Ze5T@Q)c5&EP0Px}2nK&<~$tS1or2>oSxw~x>6`+b1e$LCGI{x2`(#6H5fvN&!Z zS4aFlK&*dV*F$0-p}$P;>iEqIUJpX|{YFmQJ8!T1`zMHaVSF^+SIe5CEfH|~p~#Q= ze903Uqd_|E#7Mod5SY9+1~cP8$I45csaOl!@p-F+m+GtNB&|Q2p#g9 zWczmdn+<=b0QaaTfA=US?i!)LIR9Y9zGmW8;A@QM@-yMyWb_HXX7mZZMt!Hg#5nF8 z5`2mJPJM-O+&Y49xO}IdkP%;@zEfXd9Jh{8_uYF#KOiH%Kz&udVB%Ha3ykOXm*5Lq z^sN8%1Cs4+zHq2RUoiRvUoiRvUoiRvUoiUi`{)Z#v`*_U7`cxcJ;zapZz+rS+0b9C z%SNBzOGb}-=HUnazRCM1$#!LQ{^C6r<8hBABllP{e}XR>J?@v759Ga*WVre3I(V{O`;G>M^>PdnR8h!iw(4Nnszj&V1cj|+T zYrYR;B(JIO)JGY|?IXcQjlP)Qd@smIepBD64>OM2M}iMi?|ird-()!HzUN^)x1NOitI;RiKey=l{T$9=2jANneS(i0eS(i0eS(i0eS(h~eS(h} zeS(irU)4R8@iyNNey^~@?;DIh!Ph2>?^gxB#&~W&3BE>sr@q8EZXF4}M17~e!Z>an z3BE#or@p{AZXF4}Kz&udz<6#w3BE8@%-aflf$`jW5`4kv6MSKdewV&r^a;LT^a;LT z^a;LT^zHXqeoo`(wvzj-(Q_Pi?f2o(U%U?+eS$9;eZuFvEqdN}@wsRRpYM!5!557_ r;q%=VJ@2{vTt~8989o05U*`N(`7+~e)~8+iveECxm-YYr>vj1b2Yh2s From 0304930136abd3d3679d19cac18cc1a8ef931d89 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 14:53:30 +0100 Subject: [PATCH 03/12] WIP: introducing Region#in_and_out and Edges#in_and_out, support for hierachical Edges#in, Tests updated --- src/db/db/dbAsIfFlatEdges.cc | 22 ++++++++ src/db/db/dbAsIfFlatEdges.h | 1 + src/db/db/dbAsIfFlatRegion.cc | 69 ++++++++++++++++++------- src/db/db/dbAsIfFlatRegion.h | 11 +++- src/db/db/dbDeepEdges.cc | 59 ++++++++++++++++++++- src/db/db/dbDeepEdges.h | 1 + src/db/db/dbDeepRegion.cc | 10 +--- src/db/db/dbDeepRegion.h | 4 +- src/db/db/dbEdges.h | 13 +++++ src/db/db/dbEdgesDelegate.h | 1 + src/db/db/dbEmptyEdges.h | 1 + src/db/db/dbEmptyRegion.h | 1 + src/db/db/dbRegion.h | 13 +++++ src/db/db/dbRegionDelegate.h | 1 + src/db/db/dbRegionLocalOperations.cc | 1 + src/db/db/dbRegionLocalOperations.h | 2 + src/db/unit_tests/dbDeepRegionTests.cc | 62 +++++++++++++++++++++- src/db/unit_tests/dbRegionTests.cc | 10 ++++ testdata/algo/deep_region_au31.gds | Bin 7298 -> 8522 bytes 19 files changed, 247 insertions(+), 35 deletions(-) diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index e42d5c29b..fc505a457 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -530,6 +530,28 @@ AsIfFlatEdges::in (const Edges &other, bool invert) const return new_region.release (); } +std::pair +AsIfFlatEdges::in_and_out (const Edges &other) const +{ + std::set op; + for (EdgesIterator o (other.begin_merged ()); ! o.at_end (); ++o) { + op.insert (*o); + } + + std::unique_ptr in (new FlatEdges (false)); + std::unique_ptr out (new FlatEdges (false)); + + for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { + if (op.find (*o) != op.end ()) { + in->insert (*o); + } else { + out->insert (*o); + } + } + + return std::make_pair (in.release (), out.release ()); +} + size_t AsIfFlatEdges::count () const { diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index 785b0a677..4a15a91a4 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -204,6 +204,7 @@ public: virtual std::pair selected_inside_pair (const Region &other) const; virtual EdgesDelegate *in (const Edges &, bool) const; + virtual std::pair in_and_out (const Edges &) const; virtual bool equals (const Edges &other) const; virtual bool less (const Edges &other) const; diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index e0bb9dd4e..c0a2896bc 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -148,25 +148,6 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter) const return result.release (); } -RegionDelegate * -AsIfFlatRegion::in (const Region &other, bool invert) const -{ - std::set op; - for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) { - op.insert (*o); - } - - std::unique_ptr new_region (new FlatRegion (false)); - - for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) { - if ((op.find (*o) == op.end ()) == invert) { - new_region->insert (*o); - } - } - - return new_region.release (); -} - bool AsIfFlatRegion::is_box () const { @@ -400,6 +381,56 @@ private: } +std::pair +AsIfFlatRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const +{ + OutputPairHolder oph (output_mode, merged_semantics ()); + + if (output_mode == None) { + return oph.region_pair (); + } + + // 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 (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 ()); + } + } + + std::set op; + for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) { + op.insert (*o); + } + + std::unique_ptr new_region (new FlatRegion (false)); + + for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) { + if (op.find (*o) != op.end ()) { + if (output_mode == Positive || output_mode == PositiveAndNegative) { + oph.results () [0]->insert (*o); + } + } else { + if (output_mode == Negative) { + oph.results () [0]->insert (*o); + } else if (output_mode == PositiveAndNegative) { + oph.results () [1]->insert (*o); + } + } + } + + return oph.region_pair (); +} + std::pair AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index d6ec3366c..699431ce3 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -265,7 +265,15 @@ public: return pull_generic (other, 0, false); } - virtual RegionDelegate *in (const Region &other, bool invert) const; + virtual RegionDelegate *in (const Region &other, bool invert) const + { + return in_and_out_generic (other, invert ? Negative : Positive).first; + } + + virtual std::pair in_and_out (const Region &other) const + { + return in_and_out_generic (other, PositiveAndNegative); + } virtual bool equals (const Region &other) const; virtual bool less (const Region &other) const; @@ -284,6 +292,7 @@ protected: 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; + virtual std::pair in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const; template static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes); diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 93dd301d1..e3b40b063 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -34,6 +34,7 @@ #include "dbLayoutUtils.h" #include "dbLocalOperation.h" #include "dbLocalOperationUtils.h" +#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation #include "dbHierProcessor.h" #include "dbEmptyEdges.h" @@ -1741,8 +1742,62 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const { - // TODO: is there a cheaper way? - return AsIfFlatEdges::in (other, invert); + std::unique_ptr dr_holder; + const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); + if (! other_deep) { + // if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchization + dr_holder.reset (new db::DeepEdges (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + const db::DeepLayer &edges = merged_deep_layer (); + + DeepLayer dl_out (edges.derived ()); + + std::vector output_layers; + output_layers.reserve (1); + output_layers.push_back (dl_out.layer ()); + + db::ContainedEdgesLocalOperation op (invert ? Negative : Positive); + + db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edges.store ()->threads ()); + + proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers); + + return new db::DeepEdges (dl_out); +} + +std::pair DeepEdges::in_and_out (const Edges &other) const +{ + std::unique_ptr dr_holder; + const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); + if (! other_deep) { + // if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchization + dr_holder.reset (new db::DeepEdges (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + const db::DeepLayer &edges = merged_deep_layer (); + + DeepLayer dl_out (edges.derived ()); + DeepLayer dl_out2 (edges.derived ()); + + std::vector output_layers; + output_layers.reserve (2); + output_layers.push_back (dl_out.layer ()); + output_layers.push_back (dl_out2.layer ()); + + db::ContainedEdgesLocalOperation op (PositiveAndNegative); + + db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edges.store ()->threads ()); + + proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers); + + return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2)); } namespace diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index 1bd84c16f..7fd8730aa 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -156,6 +156,7 @@ public: virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const; virtual EdgesDelegate *in (const Edges &, bool) const; + virtual std::pair in_and_out (const Edges &) const; virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 8d1abf149..3aae6b595 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1789,16 +1789,8 @@ private: } -RegionDelegate * -DeepRegion::in (const Region &other, bool invert) const -{ - // TODO: we could offer in_and_not_it (both at once) - InteractingOutputMode output_mode = invert ? Negative : Positive; - return in_and_out (other, output_mode).first; -} - std::pair -DeepRegion::in_and_out (const Region &other, InteractingOutputMode output_mode) const +DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const { std::unique_ptr dr_holder; const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index aec863284..e47cfae95 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -133,8 +133,6 @@ public: virtual RegionDelegate *sized (coord_type d, unsigned int mode) const; virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const; - virtual RegionDelegate *in (const Region &other, bool invert) const; - virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; virtual DeepShapeCollectionDelegateBase *deep () @@ -155,10 +153,10 @@ protected: 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 std::pair in_and_out (const Region &other, InteractingOutputMode output_mode) 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; + virtual std::pair in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const; private: friend class DeepEdges; diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 6f2114d41..1524581c8 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -1390,6 +1390,19 @@ public: return Edges (mp_delegate->in (other, invert)); } + /** + * @brief Returns all edges which are in the other edge set and which are not. + * + * This method is equivalent to calling in with invert = false and true, but more efficient. + * + * Merged semantics applies. + */ + std::pair in_and_out (const Edges &other) const + { + std::pair p = mp_delegate->in_and_out (other); + return std::pair (Edges (p.first), Edges (p.second)); + } + /** * @brief Returns the nth edge * diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 59a595f4b..db17aeda4 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -333,6 +333,7 @@ public: virtual std::pair selected_inside_pair (const Edges &other) const = 0; virtual EdgesDelegate *in (const Edges &other, bool invert) const = 0; + virtual std::pair in_and_out (const Edges &) const = 0; virtual const db::Edge *nth (size_t n) const = 0; virtual bool has_valid_edges () const = 0; diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index 569eada56..4cefa2693 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -115,6 +115,7 @@ public: virtual std::pair selected_inside_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual EdgesDelegate *in (const Edges &, bool) const { return new EmptyEdges (); } + virtual std::pair in_and_out (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual const db::Edge *nth (size_t) const { tl_assert (false); } virtual bool has_valid_edges () const { return true; } diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h index e5537792d..60c5332d9 100644 --- a/src/db/db/dbEmptyRegion.h +++ b/src/db/db/dbEmptyRegion.h @@ -133,6 +133,7 @@ public: virtual TextsDelegate *pull_interacting (const Texts &) const { return new EmptyTexts (); } virtual RegionDelegate *pull_overlapping (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); } + virtual std::pair in_and_out (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual bool has_valid_polygons () const { return true; } virtual bool has_valid_merged_polygons () const { return true; } diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index af8671d46..3030911e2 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -1602,6 +1602,19 @@ public: return Region (mp_delegate->in (other, invert)); } + /** + * @brief Returns all polygons which are in the other region plus the ones which are not + * + * This method is similar to calling in with inverse = false and true, but more efficient. + * + * Merged semantics applies. + */ + std::pair in_and_out (const Region &other) const + { + std::pair p = mp_delegate->in_and_out (other); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Round corners (in-place) * diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index 985ba48e1..e94737cad 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -308,6 +308,7 @@ public: virtual RegionDelegate *pull_overlapping (const Region &other) const = 0; virtual TextsDelegate *pull_interacting (const Texts &other) const = 0; virtual RegionDelegate *in (const Region &other, bool invert) const = 0; + virtual std::pair in_and_out (const Region &other) const = 0; virtual const db::Polygon *nth (size_t n) const = 0; virtual bool has_valid_polygons () const = 0; diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 33fe39dd6..501d534f5 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -986,6 +986,7 @@ std::string contained_local_operation::description () const // explicit instantiations template class DB_PUBLIC contained_local_operation; template class DB_PUBLIC contained_local_operation; +template class DB_PUBLIC contained_local_operation; // --------------------------------------------------------------------------------------------------------------- diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 7a457e413..102076b79 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -368,6 +368,8 @@ private: }; typedef contained_local_operation ContainedLocalOperation; +// the implementation is type-agnostic and can be used for edges too +typedef contained_local_operation ContainedEdgesLocalOperation; } // namespace db diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 052a2ccea..dfff18bf6 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2036,10 +2036,11 @@ TEST(31_in) unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); - unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); db::Region r1r = r1; r1r.set_merged_semantics (false); db::Region r2r = r2; @@ -2053,6 +2054,10 @@ TEST(31_in) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.in (r1)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in (r1, true)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in (r3, false)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in (r3, true)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in (r1, false)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in (r1, true)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in (r1)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in (r1, true)); @@ -2067,6 +2072,61 @@ TEST(31_in) db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds"); } +TEST(31_in_and_out) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l31.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty + + db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + + db::Region r1r = r1; + r1r.set_merged_semantics (false); + db::Region r2r = r2; + r2r.set_merged_semantics (false); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.in_and_out (r1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in_and_out (r1).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in_and_out (r3).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in_and_out (r3).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in_and_out (r1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in_and_out (r1).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in_and_out (r1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in_and_out (r1).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.in_and_out (r1r).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.in_and_out (r1r).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2r.in_and_out (r1r).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2r.in_and_out (r1r).second); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds"); +} + TEST(100_Integration) { db::Layout ly; diff --git a/src/db/unit_tests/dbRegionTests.cc b/src/db/unit_tests/dbRegionTests.cc index adb905dc1..c29654f1c 100644 --- a/src/db/unit_tests/dbRegionTests.cc +++ b/src/db/unit_tests/dbRegionTests.cc @@ -1095,15 +1095,25 @@ TEST(19) r2.insert (db::Box (db::Point (0, 0), db::Point (20, 30))); EXPECT_EQ (r1.in (r2, false).to_string (), "(0,0;0,30;20,30;20,0)"); + EXPECT_EQ (r1.in_and_out (r2).first.to_string (), "(0,0;0,30;20,30;20,0)"); EXPECT_EQ (r1.in (r2, true).to_string (), ""); + EXPECT_EQ (r1.in (r1, false).to_string (), "(0,0;0,30;20,30;20,0)"); + EXPECT_EQ (r1.in (r1, true).to_string (), ""); + EXPECT_EQ (r1.in_and_out (r2).second.to_string (), ""); EXPECT_EQ (r2.in (r1, true).to_string (), ""); r1.set_merged_semantics (false); r2.set_merged_semantics (false); EXPECT_EQ (db::compare (r1.in (r2, false), "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true); + EXPECT_EQ (db::compare (r1.in_and_out (r2).first, "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true); EXPECT_EQ (r1.in (r2, true).to_string (), "(0,0;0,20;10,20;10,0)"); + EXPECT_EQ (r1.in_and_out (r2).second.to_string (), "(0,0;0,20;10,20;10,0)"); EXPECT_EQ (r2.in (r1, true).to_string (), "(0,0;0,10;20,10;20,0)"); + EXPECT_EQ (r1.in (db::Region (), false).to_string (), ""); + EXPECT_EQ (db::compare (r1.in (db::Region (), true), "(0,0;0,20;10,20;10,0);(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true); + EXPECT_EQ (db::Region ().in (r1, false).to_string (), ""); + EXPECT_EQ (db::Region ().in (r1, true).to_string (), ""); } TEST(20) diff --git a/testdata/algo/deep_region_au31.gds b/testdata/algo/deep_region_au31.gds index 4ff450d2f99e19b09ad2494ce62b2b1be6cdc473..786700549f5b3184698a2217c14080913edb63ff 100644 GIT binary patch delta 223 zcmZp&JmsXsz{bGD6u}_F$i)7Pftx{^fsetMK>(ROQAu48LvUl%c_v2QiCO-Pypy>Y z?Saf)Af^|Hx%m}SDhsBT%?a$^S%7K+xPfXW7qGhn$qQT{wg9*N=5U^Q%vkiW3BE?qp Date: Sun, 27 Nov 2022 15:31:25 +0100 Subject: [PATCH 04/12] Edges#in/in_and_out: tests added --- src/db/db/dbAsIfFlatEdges.cc | 12 +++ src/db/db/dbRegionLocalOperations.cc | 2 +- src/db/unit_tests/dbDeepEdgesTests.cc | 110 ++++++++++++++++++++++++++ src/db/unit_tests/dbEdgesTests.cc | 36 +++++++++ testdata/algo/deep_edges_au20.gds | Bin 0 -> 29050 bytes 5 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 testdata/algo/deep_edges_au20.gds diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index fc505a457..fc8cab428 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -514,6 +514,12 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c EdgesDelegate * AsIfFlatEdges::in (const Edges &other, bool invert) const { + if (other.empty ()) { + return invert ? clone () : new EmptyEdges (); + } else if (empty ()) { + return new EmptyEdges (); + } + std::set op; for (EdgesIterator o (other.begin_merged ()); ! o.at_end (); ++o) { op.insert (*o); @@ -533,6 +539,12 @@ AsIfFlatEdges::in (const Edges &other, bool invert) const std::pair AsIfFlatEdges::in_and_out (const Edges &other) const { + if (other.empty ()) { + return std::make_pair (new EmptyEdges (), clone ()); + } else if (empty ()) { + return std::make_pair (new EmptyEdges (), new EmptyEdges ()); + } + std::set op; for (EdgesIterator o (other.begin_merged ()); ! o.at_end (); ++o) { op.insert (*o); diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 501d534f5..f1d543a62 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -925,7 +925,7 @@ contained_local_operation::contained_local_operation (InteractingOut template db::Coord contained_local_operation::dist () const { - return 0; + return 1; // touching included for degenerated polygons and edges } template diff --git a/src/db/unit_tests/dbDeepEdgesTests.cc b/src/db/unit_tests/dbDeepEdgesTests.cc index 05695fb03..5149ce316 100644 --- a/src/db/unit_tests/dbDeepEdgesTests.cc +++ b/src/db/unit_tests/dbDeepEdgesTests.cc @@ -1182,3 +1182,113 @@ TEST(19_AndNotWithEdges) EXPECT_EQ (db::compare (eflat.andnot (ee).second, "(1500,2000;1500,2100);(1100,0;1100,1000);(0,0;0,1000);(100,0;100,3000);(1800,2500;1800,3500);(-1500,0;-1500,1000);(1700,1500;1600,2500)"), true); } +TEST(20_in) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l31.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty + + db::Edges e1 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l1), dss)).edges ()); + db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ()); + db::Edges e3 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l3), dss)).edges ()); + + db::Edges e1r = e1; + e1r.set_merged_semantics (false); + db::Edges e2r = e2; + e2r.set_merged_semantics (false); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), e1); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), e2); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e2.in (e1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e2.in (e1, true)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), e2.in (e3)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), e2.in (e3, true)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), e3.in (e1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), e3.in (e1, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e2r.in (e1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), e2r.in (e1, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e2.in (e1r)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e2.in (e1r, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), e2r.in (e1r)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e2r.in (e1r, true)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au20.gds"); +} + +TEST(20_in_and_out) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l31.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty + + db::Edges e1 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l1), dss)).edges ()); + db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ()); + db::Edges e3 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l3), dss)).edges ()); + + db::Edges e1r = e1; + e1r.set_merged_semantics (false); + db::Edges e2r = e2; + e2r.set_merged_semantics (false); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), e1); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), e2); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e2.in_and_out (e1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e2.in_and_out (e1).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), e2.in_and_out (e3).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), e2.in_and_out (e3).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), e3.in_and_out (e1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), e3.in_and_out (e1).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e2r.in_and_out (e1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), e2r.in_and_out (e1).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e2.in_and_out (e1r).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e2.in_and_out (e1r).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), e2r.in_and_out (e1r).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e2r.in_and_out (e1r).second); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au20.gds"); +} + diff --git a/src/db/unit_tests/dbEdgesTests.cc b/src/db/unit_tests/dbEdgesTests.cc index 96d2d4068..7f7fac46b 100644 --- a/src/db/unit_tests/dbEdgesTests.cc +++ b/src/db/unit_tests/dbEdgesTests.cc @@ -1121,6 +1121,42 @@ TEST(27) EXPECT_EQ (db::compare (e.selected_outside_differential (ee).second, "(1100,-1000;1100,2000);(1200,-1000;1200,0);(1300,-800;1300,-200);(1400,1000;1400,1100);(1500,1000;1500,2100);(1600,-800;1600,-200);(1900,1000;1900,2000)"), true); } +// Edges::in and Edges:in_and_out +TEST(28) +{ + db::Edges e; + e.insert (db::Edge (0, 0, 0, 1000)); + e.insert (db::Edge (0, 1000, 0, 2000)); + e.insert (db::Edge (100, 0, 100, 1000)); + + db::Edges ee; + ee.insert (db::Edge (0, 0, 0, 2000)); + ee.insert (db::Edge (100, 1000, 0, 2000)); + ee.insert (db::Edge (100, 0, 100, 1000)); + + EXPECT_EQ (db::compare (e.in (db::Edges ()), ""), true); + EXPECT_EQ (db::compare (e.in (db::Edges (), true), "(0,0;0,1000);(0,1000;0,2000);(100,0;100,1000)"), true); + EXPECT_EQ (db::compare (e.in_and_out (db::Edges ()).first, ""), true); + EXPECT_EQ (db::compare (e.in_and_out (db::Edges ()).second, "(0,0;0,1000);(0,1000;0,2000);(100,0;100,1000)"), true); + EXPECT_EQ (db::compare (db::Edges ().in (ee), ""), true); + EXPECT_EQ (db::compare (db::Edges ().in (ee, true), ""), true); + EXPECT_EQ (db::compare (db::Edges ().in_and_out (ee).first, ""), true); + EXPECT_EQ (db::compare (db::Edges ().in_and_out (ee).second, ""), true); + EXPECT_EQ (db::compare (e.in (ee), "(0,0;0,2000);(100,0;100,1000)"), true); + EXPECT_EQ (db::compare (e.in (ee, true), ""), true); + EXPECT_EQ (db::compare (e.in_and_out (ee).first, "(0,0;0,2000);(100,0;100,1000)"), true); + EXPECT_EQ (db::compare (e.in_and_out (ee).second, ""), true); + EXPECT_EQ (db::compare (ee.in (e, true), "(100,1000;0,2000)"), true); + EXPECT_EQ (db::compare (ee.in_and_out (e).second, "(100,1000;0,2000)"), true); + + e.set_merged_semantics (false); + ee.set_merged_semantics (false); + + EXPECT_EQ (db::compare (e.in (ee), "(100,0;100,1000)"), true); + EXPECT_EQ (db::compare (e.in (ee, true), "(0,0;0,1000);(0,1000;0,2000)"), true); + EXPECT_EQ (db::compare (ee.in (e, true), "(0,0;0,2000);(100,1000;0,2000)"), true); +} + // GitHub issue #72 (Edges/Region NOT issue) TEST(100) { diff --git a/testdata/algo/deep_edges_au20.gds b/testdata/algo/deep_edges_au20.gds new file mode 100644 index 0000000000000000000000000000000000000000..45fee953f694f1a2748ef8fb0729e3bfd3234b35 GIT binary patch literal 29050 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 literal 0 HcmV?d00001 From d76eef10afe1c8ed662e309f587f03542a9dcfcc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 15:59:18 +0100 Subject: [PATCH 05/12] GSI enabling of Edges#in_and_out, Region#in_and_out and corresponding DRC feature --- src/db/db/gsiDeclDbEdges.cc | 37 ++++++---- src/db/db/gsiDeclDbRegion.cc | 35 ++++++--- src/doc/doc/about/drc_ref_layer.xml | 82 ++++++++++------------ src/drc/drc/built-in-macros/_drc_layer.rb | 25 +++++++ src/drc/unit_tests/drcSimpleTests.cc | 10 +++ testdata/drc/drcSimpleTests_58.drc | 27 +++++++ testdata/drc/drcSimpleTests_58.gds | Bin 0 -> 2274 bytes testdata/drc/drcSimpleTests_au58.gds | Bin 0 -> 19966 bytes testdata/drc/drcSimpleTests_au58d.gds | Bin 0 -> 13470 bytes 9 files changed, 149 insertions(+), 67 deletions(-) create mode 100644 testdata/drc/drcSimpleTests_58.drc create mode 100644 testdata/drc/drcSimpleTests_58.gds create mode 100644 testdata/drc/drcSimpleTests_au58.gds create mode 100644 testdata/drc/drcSimpleTests_au58d.gds diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index e2977296f..f1ce6d959 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -35,7 +35,16 @@ namespace gsi { -static db::Edges *new_v () +static inline std::vector as_2edges_vector (const std::pair &rp) +{ + std::vector res; + res.reserve (2); + res.push_back (db::Edges (const_cast (rp.first).take_delegate ())); + res.push_back (db::Edges (const_cast (rp.second).take_delegate ())); + return res; +} + +static db::Edges *new_v () { return new db::Edges (); } @@ -166,6 +175,11 @@ static db::Edges not_in (const db::Edges *r, const db::Edges &other) return r->in (other, true); } +static std::vector in_and_out (const db::Edges *r, const db::Edges &other) +{ + return as_2edges_vector (r->in_and_out (other)); +} + static db::Edges &move_p (db::Edges *r, const db::Vector &p) { r->transform (db::Disp (p)); @@ -377,15 +391,6 @@ static size_t id (const db::Edges *e) return tl::id_of (e->delegate ()); } -static inline std::vector as_2edges_vector (const std::pair &rp) -{ - std::vector res; - res.reserve (2); - res.push_back (db::Edges (const_cast (rp.first).take_delegate ())); - res.push_back (db::Edges (const_cast (rp.second).take_delegate ())); - return res; -} - static std::vector andnot_with_edges (const db::Edges *r, const db::Edges &other) { return as_2edges_vector (r->andnot (other)); @@ -1633,16 +1638,24 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" ) + - method_ext ("members_of|#in", &in, gsi::arg ("other"), + method_ext ("members_of|in", &in, gsi::arg ("other"), "@brief Returns all edges which are members of the other edge collection\n" "This method returns all edges in self which can be found in the other edge collection as well with exactly the same " "geometry." ) + - method_ext ("not_members_of|#not_in", ¬_in, gsi::arg ("other"), + method_ext ("not_members_of|not_in", ¬_in, gsi::arg ("other"), "@brief Returns all edges which are not members of the other edge collection\n" "This method returns all edges in self which can not be found in the other edge collection with exactly the same " "geometry." ) + + method_ext ("in_and_out", &in_and_out, gsi::arg ("other"), + "@brief Returns all polygons which are members and not members of the other region\n" + "This method is equivalent to calling \\members_of and \\not_members_of, but delivers both results at the same time and " + "is more efficient than two separate calls. " + "The first element returned is the \\members_of part, the second is the \\not_members_of part.\n" + "\n" + "This method has been introduced in version 0.28.\n" + ) + method_ext ("is_deep?", &is_deep, "@brief Returns true if the edge collection is a deep (hierarchical) one\n" "\n" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index f7874686b..d3dafb24d 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -44,6 +44,15 @@ namespace gsi { +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 db::Region *new_v () { return new db::Region (); @@ -430,6 +439,11 @@ static db::Region not_in (const db::Region *r, const db::Region &other) return r->in (other, true); } +static std::vector in_and_out (const db::Region *r, const db::Region &other) +{ + return as_2region_vector (r->in_and_out (other)); +} + static db::Region rectangles (const db::Region *r) { db::RectangleFilter f (false, false); @@ -605,15 +619,6 @@ 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) { return as_2region_vector (r->andnot (other)); @@ -2186,16 +2191,24 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "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" ) + - method_ext ("members_of|#in", &in, gsi::arg ("other"), + method_ext ("members_of|in", &in, gsi::arg ("other"), "@brief Returns all polygons which are members of the other region\n" "This method returns all polygons in self which can be found in the other region as well with exactly the same " "geometry." ) + - method_ext ("not_members_of|#not_in", ¬_in, gsi::arg ("other"), + method_ext ("not_members_of|not_in", ¬_in, gsi::arg ("other"), "@brief Returns all polygons which are not members of the other region\n" "This method returns all polygons in self which can not be found in the other region with exactly the same " "geometry." ) + + method_ext ("in_and_out", &in_and_out, gsi::arg ("other"), + "@brief Returns all polygons which are members and not members of the other region\n" + "This method is equivalent to calling \\members_of and \\not_members_of, but delivers both results at the same time and " + "is more efficient than two separate calls. " + "The first element returned is the \\members_of part, the second is the \\not_members_of part.\n" + "\n" + "This method has been introduced in version 0.28.\n" + ) + method_ext ("rectangles", &rectangles, "@brief Returns all polygons which are rectangles\n" "This method returns all polygons in self which are rectangles." diff --git a/src/doc/doc/about/drc_ref_layer.xml b/src/doc/doc/about/drc_ref_layer.xml index 323b77638..10321b4c6 100644 --- a/src/doc/doc/about/drc_ref_layer.xml +++ b/src/doc/doc/about/drc_ref_layer.xml @@ -1342,6 +1342,44 @@ The following image shows the effect of the "in" method (input1: red, input2: bl

+

"in_and_out" - Selects shapes or regions of self which are and which are not contained in the other layer

+ +

Usage:

+
    +
  • (in, not_in) = layer.in_and_out(other)
  • +
+

+This method is equivalent to calling in and not_in, but more +efficient as it delivers both results in a single call. +

+This method is available for polygon, text and edge layers. Edges can be selected +with respect to other edges or polygons. Texts can be selected with respect to +polygons. Polygons can be selected with respect to edges, texts and other polygons. +

+The following image shows the effect of the "interacting" method (input1: red, input2: blue): +

+ + + + +
+

+If a single count is given, shapes from self are selected only if they do interact at least with the given +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 min_count or more, but a maximum of max_count different shapes +from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions. +

+ + + + + + + + + +
+

"insert" - Inserts one or many objects into the layer

Usage:

@@ -1448,50 +1486,6 @@ method computing both inside and outside part in a single call.

-

"interacting" - Selects shapes or regions of self which touch or overlap shapes from the other region

- -

Usage:

-
    -
  • layer.interacting(other)
  • -
  • layer.interacting(other, min_count)
  • -
  • layer.interacting(other, min_count, max_count)
  • -
  • layer.interacting(other, min_count .. max_count)
  • -
-

-This method selects all shapes or regions from self which touch or overlap shapes from the other -region. Unless self is in raw mode (see raw), coherent regions are selected from self, -otherwise individual shapes are selected. -It returns a new layer containing the selected shapes. A version which modifies self -is select_interacting. -

-This method is available for polygon, text and edge layers. Edges can be selected -with respect to other edges or polygons. Texts can be selected with respect to -polygons. Polygons can be selected with respect to edges, texts and other polygons. -

-The following image shows the effect of the "interacting" method (input1: red, input2: blue): -

- - - - -
-

-If a single count is given, shapes from self are selected only if they do interact at least with the given -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 min_count or more, but a maximum of max_count different shapes -from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions. -

- - - - - - - - - -
-

"intersections" - Returns the intersection points of intersecting edge segments for two edge collections

Usage:

diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index abea2dd64..aef166151 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -2442,6 +2442,13 @@ CODE # @/tr # @/table + # %DRC% + # @name in_and_out + # @brief Selects shapes or regions of self which are and which are not contained in the other layer + # @synopsis (in, not_in) = layer.in_and_out(other) + # This method is equivalent to calling \in and \not_in, but more + # efficient as it delivers both results in a single call. + # %DRC% # @name interacting # @brief Selects shapes or regions of self which touch or overlap shapes from the other region @@ -2844,6 +2851,24 @@ CODE CODE end + %w(in_and_out).each do |f| + eval <<"CODE" + def #{f}(other, *args) + + @engine._context("#{f}") do + + requires_same_type(other) + requires_edges_or_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(split_interacting).each do |f| eval <<"CODE" def #{f}(other, *args) diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 7ba20d07b..ab37a7f8a 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1376,3 +1376,13 @@ TEST(57d_issue_1190) { run_test (_this, "57", true); } + +TEST(58_in_and_out) +{ + run_test (_this, "58", false); +} + +TEST(58d_in_and_out) +{ + run_test (_this, "58", true); +} diff --git a/testdata/drc/drcSimpleTests_58.drc b/testdata/drc/drcSimpleTests_58.drc new file mode 100644 index 000000000..611071b3c --- /dev/null +++ b/testdata/drc/drcSimpleTests_58.drc @@ -0,0 +1,27 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) +l2 = input(2, 0) + +l1.output(1, 0) +l2.output(2, 0) + +l1e = l1.edges +l2e = l2.edges + +l2.in(l1).output(10, 0) +l2.not_in(l1).output(11, 0) +l2.in_and_out(l1).first.output(12, 0) +l2.in_and_out(l1).last.output(13, 0) + +l2e.in(l1e).output(20, 0) +l2e.not_in(l1e).output(21, 0) +l2e.in_and_out(l1e).first.output(22, 0) +l2e.in_and_out(l1e).last.output(23, 0) + diff --git a/testdata/drc/drcSimpleTests_58.gds b/testdata/drc/drcSimpleTests_58.gds new file mode 100644 index 0000000000000000000000000000000000000000..1c6661453820cac7cd0489128ead06045abd5c0f GIT binary patch literal 2274 zcmbuAF-#Oe6o&uXJN8aE;Q*rqFcLWenDfA(5fe0kG)59Ft{_wx8wz7AOiYX=1tu00 z7A9Iym}qHXL1|&EEi5c8jFkn2g{A+$dp~=U9Vy&o^KIVD|K`n`w{H+5iq)5|wMz1hFAvNyB)a=nGouCOkSW2#COAU+-;Lfjhx zSf~|&vCqKSk13~1z`zHn9pcCndr+n>J*l;tQFd) za8bMLqi01Wp8Ar0pXN@7e*vb)$&>&AuoZ4lyuQJwKz+??DJ&(-umt?=V z#S?r6h(q*MzL(K=NgL>sn zT2W`GwN2Z}PQAOs|JJ4b9Mn+~3)eqfN4ArBaUAGfZ{CY(`=L7gYkkdSZ_Ukv?PPF$ z>0NKGKht*C;SpV+634Aux7i1}*(3*Ic7%Ai05ztr<#kd|RXt&D2Po{MF&)fJMy~Er zw3s*YX#4QUa)79&xUb_BvC&O1FXOd1Riyq$YF|l-}_rhvtFGi;T9DLA`DQ%@d`saUZ7b|I#mh zO>YB{c|>a?qi%`zcyN7|VlZtdgZeuw>1`}Fhk(00 eQ&YEedpxM$WbSl_h`Q15^EGYv-NJvORKg!eQR&M7 literal 0 HcmV?d00001 diff --git a/testdata/drc/drcSimpleTests_au58.gds b/testdata/drc/drcSimpleTests_au58.gds new file mode 100644 index 0000000000000000000000000000000000000000..41d44f9a9202b06c217fb9ac0744326bff55aa5d GIT binary patch literal 19966 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 SgHWX2AXHnup}$!Shw>jq+V^Gv literal 0 HcmV?d00001 From 5db45d7aeef8988260d48026aa84a5c2146fe8bf Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 19:43:53 +0100 Subject: [PATCH 06/12] Proper setting of merged status after interacting/inside etc. --- src/db/db/dbAsIfFlatRegion.cc | 10 +++++----- src/db/db/dbDeepRegion.cc | 15 ++++++--------- src/db/unit_tests/dbDeepRegionTests.cc | 21 ++++++++++----------- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index c0a2896bc..842e55eba 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -434,7 +434,7 @@ AsIfFlatRegion::in_and_out_generic (const Region &other, InteractingOutputMode o 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 ()); + OutputPairHolder oph (output_mode, merged_semantics () || is_merged ()); if (output_mode == None) { return oph.region_pair (); @@ -485,7 +485,7 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOut std::pair AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { - OutputPairHolder oph (output_mode, merged_semantics ()); + OutputPairHolder oph (output_mode, merged_semantics () || is_merged ()); if (output_mode == None) { return oph.region_pair (); @@ -531,7 +531,7 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOut 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 ()); + OutputPairHolder oph (output_mode, merged_semantics () || is_merged ()); if (output_mode == None) { return oph.region_pair (); @@ -611,7 +611,7 @@ AsIfFlatRegion::pull_generic (const Edges &other) const std::vector > others; others.push_back (other.begin_merged ()); - std::unique_ptr output (new FlatEdges (merged_semantics ())); + std::unique_ptr output (new FlatEdges (other.merged_semantics () || other.is_merged ())); std::vector results; results.push_back (&output->raw_edges ()); @@ -720,7 +720,7 @@ AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) cons std::vector > others; others.push_back (other.begin_merged ()); - std::unique_ptr output (new FlatRegion (merged_semantics ())); + std::unique_ptr output (new FlatRegion (other.merged_semantics () || other.is_merged ())); std::vector results; results.push_back (&output->raw_polygons ()); diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 3aae6b595..5a46e4e8d 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1840,7 +1840,8 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to const db::DeepLayer &polygons = merged_deep_layer (); // 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 (); + bool other_needs_merged = (mode < 0 || counting); + const db::DeepLayer &other_polygons = other_needs_merged ? other_deep->merged_deep_layer () : other_deep->deep_layer (); db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true); @@ -1854,7 +1855,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); } - bool result_is_merged = (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())); + bool result_is_merged = (! split_after && (merged_semantics () || is_merged ())); InteractingResultHolder orh (output_mode, result_is_merged, polygons); proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ()); @@ -1892,7 +1893,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputM proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); } - bool result_is_merged = (! split_after && other.is_merged () && (merged_semantics () || is_merged ())); + bool result_is_merged = (! split_after && (merged_semantics () || is_merged ())); InteractingResultHolder orh (output_mode, result_is_merged, polygons); proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), orh.layers ()); @@ -1935,9 +1936,7 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ()); db::DeepRegion *res = new db::DeepRegion (dl_out); - if (! split_after && ((mode < 0 && merged_semantics ()) || is_merged ()) && (other.merged_semantics () || other.is_merged ())) { - res->set_is_merged (true); - } + res->set_is_merged (! split_after && (other.merged_semantics () || other.is_merged ())); return res; } @@ -1998,9 +1997,7 @@ DeepRegion::pull_generic (const Texts &other) const proc.set_threads (polygons.store ()->threads ()); proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ()); - db::DeepTexts *res = new db::DeepTexts (dl_out); - res->set_is_merged (is_merged ()); - return res; + return new db::DeepTexts (dl_out); } diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index dfff18bf6..74590d2d0 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -880,8 +880,6 @@ TEST(14_Interacting) db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss); db::Region r1f (db::RecursiveShapeIterator (ly, top_cell, l1)); - db::Region r2f (db::RecursiveShapeIterator (ly, top_cell, l2)); - db::Region r6f (db::RecursiveShapeIterator (ly, top_cell, l6)); db::Region r1r = r1; r1r.set_merged_semantics (false); db::Region r2r = r2; @@ -947,12 +945,13 @@ TEST(14_Interacting) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (66, 0)), r6r.selected_overlapping (r1r)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (67, 0)), r6r.selected_not_overlapping (r1r)); - EXPECT_EQ (r2.selected_interacting (r1).is_merged (), false); - EXPECT_EQ (r2.selected_interacting (r1.merged ()).is_merged (), true); - EXPECT_EQ (r2.selected_inside (r1).is_merged (), true); + EXPECT_EQ (r2.selected_interacting (r1).is_merged (), true); EXPECT_EQ (r2r.selected_interacting (r1).is_merged (), false); - EXPECT_EQ (r2.selected_interacting (r1r).is_merged (), false); - EXPECT_EQ (r2r.selected_interacting (r1r).is_merged (), false); + EXPECT_EQ (r2r.selected_interacting (r1.merged ()).is_merged (), false); + EXPECT_EQ (r2.selected_interacting (r1r).is_merged (), true); + EXPECT_EQ (r2.selected_inside (r1).is_merged (), true); + EXPECT_EQ (r2r.selected_inside (r1).is_merged (), false); + EXPECT_EQ (r2.selected_inside (r1).is_merged (), true); CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au14a.gds"); @@ -976,8 +975,8 @@ TEST(14_Interacting) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), r6r.selected_interacting (r1er)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (33, 0)), r6r.selected_not_interacting (r1er)); - EXPECT_EQ (r6.selected_interacting (r1e).is_merged (), false); - EXPECT_EQ (r6.selected_interacting (r1er).is_merged (), false); + EXPECT_EQ (r6.selected_interacting (r1e).is_merged (), true); + EXPECT_EQ (r6.selected_interacting (r1er).is_merged (), true); EXPECT_EQ (r6r.selected_interacting (r1e).is_merged (), false); EXPECT_EQ (r6r.selected_interacting (r1er).is_merged (), false); @@ -1499,8 +1498,8 @@ TEST(25_Pull) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (62, 0)), r2r.pull_overlapping (r6r)); EXPECT_EQ (r2.pull_inside (r6).is_merged (), true); - EXPECT_EQ (r2.pull_interacting (r6).is_merged (), false); - EXPECT_EQ (r2r.pull_interacting (r6).is_merged (), false); + EXPECT_EQ (r2.pull_interacting (r6).is_merged (), true); + EXPECT_EQ (r2r.pull_interacting (r6).is_merged (), true); EXPECT_EQ (r2.pull_interacting (r6r).is_merged (), false); EXPECT_EQ (r2r.pull_interacting (r6r).is_merged (), false); From 5597ee8960a8ad3f92fe9839cc822f483c1f5344 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 21:59:06 +0100 Subject: [PATCH 07/12] DeepRegion performance: take fast path for DeepRegion::edges if merged polygons are available. --- src/db/db/dbDeepRegion.cc | 8 ++++++- src/db/db/dbDeepRegion.h | 1 + src/db/unit_tests/dbDeepRegionTests.cc | 30 +++++++++++++------------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 5a46e4e8d..e7e29ea12 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -555,6 +555,12 @@ DeepRegion::merged_deep_layer () const } } +bool +DeepRegion::merged_polygons_available () const +{ + return m_is_merged || m_merged_polygons_valid; +} + void DeepRegion::ensure_merged_polygons_valid () const { @@ -1169,7 +1175,7 @@ public: EdgesDelegate * DeepRegion::edges (const EdgeFilterBase *filter) const { - if (! filter && merged_semantics ()) { + if (! filter && merged_semantics () && ! merged_polygons_available ()) { // Hierarchical edge detector - no pre-merge required diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index e47cfae95..a45895bfd 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -142,6 +142,7 @@ public: void set_is_merged (bool f); + bool merged_polygons_available () const; const DeepLayer &merged_deep_layer () const; protected: diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 74590d2d0..972b06614 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -887,6 +887,11 @@ TEST(14_Interacting) db::Region r6r = r6; r6r.set_merged_semantics (false); + db::Edges r1e = r1.edges (); + db::Edges r1ef = r1f.edges (); + db::Edges r1er = r1r.edges (); + r1er.set_merged_semantics (false); + { db::Layout target; unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); @@ -957,11 +962,6 @@ TEST(14_Interacting) db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au14a.gds"); } - db::Edges r1e = r1.edges (); - db::Edges r1ef = r1f.edges (); - db::Edges r1er = r1r.edges (); - r1er.set_merged_semantics (false); - { db::Layout target; unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); @@ -1469,6 +1469,16 @@ TEST(25_Pull) db::Region r6r = r6; r6r.set_merged_semantics (false); + db::Edges r1e = r1.edges (); + db::Edges r1ef = r1f.edges (); + db::Edges r1er = r1r.edges (); + r1er.set_merged_semantics (false); + + db::Edges r6e = r6.edges (); + db::Edges r6ef = r6f.edges (); + db::Edges r6er = r6r.edges (); + r6er.set_merged_semantics (false); + { db::Layout target; unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); @@ -1507,16 +1517,6 @@ TEST(25_Pull) db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au25a.gds"); } - db::Edges r1e = r1.edges (); - db::Edges r1ef = r1f.edges (); - db::Edges r1er = r1r.edges (); - r1er.set_merged_semantics (false); - - db::Edges r6e = r6.edges (); - db::Edges r6ef = r6f.edges (); - db::Edges r6er = r6r.edges (); - r6er.set_merged_semantics (false); - { db::Layout target; unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); From a752257f526b15e6109fa60b237619f1803ce29e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 28 Nov 2022 01:35:49 +0100 Subject: [PATCH 08/12] Multiple empty-input shortcuts for DeepRegion - tests need update --- src/db/db/dbDeepRegion.cc | 165 +++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 2 deletions(-) diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index e7e29ea12..3af4d04c6 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -856,6 +856,10 @@ DeepRegion::is_box () const size_t DeepRegion::count () const { + if (empty ()) { + return 0; + } + size_t n = 0; const db::Layout &layout = deep_layer ().layout (); @@ -870,6 +874,10 @@ DeepRegion::count () const size_t DeepRegion::hier_count () const { + if (empty ()) { + return 0; + } + size_t n = 0; const db::Layout &layout = deep_layer ().layout (); @@ -883,6 +891,10 @@ DeepRegion::hier_count () const DeepRegion::area_type DeepRegion::area (const db::Box &box) const { + if (empty ()) { + return 0; + } + if (box.empty ()) { const db::DeepLayer &polygons = merged_deep_layer (); @@ -916,6 +928,10 @@ DeepRegion::area (const db::Box &box) const DeepRegion::perimeter_type DeepRegion::perimeter (const db::Box &box) const { + if (empty ()) { + return 0; + } + if (box.empty ()) { const db::DeepLayer &polygons = merged_deep_layer (); @@ -961,6 +977,10 @@ DeepRegion::to_string (size_t nmax) const EdgePairsDelegate * DeepRegion::grid_check (db::Coord gx, db::Coord gy) const { + if (empty ()) { + return new EmptyEdgePairs (); + } + if (gx < 0 || gy < 0) { throw tl::Exception (tl::to_string (tr ("Grid check requires a positive grid value"))); } @@ -1019,6 +1039,10 @@ DeepRegion::grid_check (db::Coord gx, db::Coord gy) const EdgePairsDelegate * DeepRegion::angle_check (double min, double max, bool inverse) const { + if (empty ()) { + return new DeepEdgePairs (deep_layer ().derived ()); + } + const db::DeepLayer &polygons = merged_deep_layer (); db::Layout &layout = const_cast (polygons.layout ()); @@ -1043,6 +1067,10 @@ DeepRegion::angle_check (double min, double max, bool inverse) const RegionDelegate * DeepRegion::snapped (db::Coord gx, db::Coord gy) { + if (empty ()) { + return clone (); + } + if (gx < 0 || gy < 0) { throw tl::Exception (tl::to_string (tr ("Snapping requires a positive grid value"))); } @@ -1053,7 +1081,7 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy) } if (! gx) { - return this; + return clone (); } const db::DeepLayer &polygons = merged_deep_layer (); @@ -1175,6 +1203,10 @@ public: EdgesDelegate * DeepRegion::edges (const EdgeFilterBase *filter) const { + if (empty ()) { + return new db::DeepEdges (deep_layer ().derived ()); + } + if (! filter && merged_semantics () && ! merged_polygons_available ()) { // Hierarchical edge detector - no pre-merge required @@ -1257,6 +1289,10 @@ DeepRegion::edges (const EdgeFilterBase *filter) const RegionDelegate * DeepRegion::process_in_place (const PolygonProcessorBase &filter) { + if (empty ()) { + return this; + } + // TODO: implement to be really in-place return processed (filter); } @@ -1264,24 +1300,40 @@ DeepRegion::process_in_place (const PolygonProcessorBase &filter) EdgesDelegate * DeepRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const { + if (empty ()) { + return new db::DeepEdges (deep_layer ().derived ()); + } + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } EdgePairsDelegate * DeepRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const { + if (empty ()) { + return new db::DeepEdgePairs (deep_layer ().derived ()); + } + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } RegionDelegate * DeepRegion::processed (const PolygonProcessorBase &filter) const { + if (empty ()) { + return clone (); + } + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } RegionDelegate * DeepRegion::filter_in_place (const PolygonFilterBase &filter) { + if (empty ()) { + return this; + } + // TODO: implement to be really in-place *this = *apply_filter (filter); return this; @@ -1290,6 +1342,10 @@ DeepRegion::filter_in_place (const PolygonFilterBase &filter) RegionDelegate * DeepRegion::filtered (const PolygonFilterBase &filter) const { + if (empty ()) { + return clone (); + } + return apply_filter (filter); } @@ -1372,6 +1428,10 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const RegionDelegate * DeepRegion::merged_in_place () { + if (empty ()) { + return this; + } + ensure_merged_polygons_valid (); // NOTE: this makes both layers share the same resource @@ -1384,12 +1444,17 @@ DeepRegion::merged_in_place () RegionDelegate * DeepRegion::merged_in_place (bool min_coherence, unsigned int min_wc) { + // TODO: implement to be really in-place return merged (min_coherence, min_wc); } RegionDelegate * DeepRegion::merged () const { + if (empty ()) { + return clone (); + } + ensure_merged_polygons_valid (); db::Layout &layout = const_cast (m_merged_polygons.layout ()); @@ -1408,6 +1473,10 @@ DeepRegion::merged () const RegionDelegate * DeepRegion::merged (bool min_coherence, unsigned int min_wc) const { + if (empty ()) { + return clone (); + } + tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons"); db::Layout &layout = const_cast (deep_layer ().layout ()); @@ -1642,6 +1711,12 @@ DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node) EdgePairsDelegate * DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const { + if (empty ()) { + return new db::DeepEdgePairs (deep_layer ().derived ()); + } else if (other && ! is_subject_regionptr (other) && other->empty () && ! options.negative) { + return new db::DeepEdgePairs (deep_layer ().derived ()); + } + const db::DeepRegion *other_deep = 0; unsigned int other_layer = 0; bool other_is_merged = true; @@ -1705,6 +1780,10 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons EdgePairsDelegate * DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const { + if (empty ()) { + return new db::DeepEdgePairs (deep_layer ().derived ()); + } + const db::DeepLayer &polygons = merged_deep_layer (); EdgeRelationFilter check (rel, d, options.metrics); @@ -1798,6 +1877,24 @@ private: std::pair DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const { + if (output_mode == None) { + return std::pair ((RegionDelegate *) 0, (RegionDelegate *) 0); + } else if (empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (clone (), clone ()); + } else { + return std::make_pair (clone (), (RegionDelegate *) 0); + } + } else if (other.empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ()); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } + } + std::unique_ptr dr_holder; const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); if (! other_deep) { @@ -1828,7 +1925,21 @@ 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); + return std::pair ((RegionDelegate *) 0, (RegionDelegate *) 0); + } else if (empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (clone (), clone ()); + } else { + return std::make_pair (clone (), (RegionDelegate *) 0); + } + } else if (other.empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ()); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } } bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); @@ -1872,6 +1983,24 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to std::pair DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { + if (output_mode == None) { + return std::pair ((RegionDelegate *) 0, (RegionDelegate *) 0); + } else if (empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (clone (), clone ()); + } else { + return std::make_pair (clone (), (RegionDelegate *) 0); + } + } else if (other.empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ()); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } + } + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); // with these flag set to true, the resulting polygons are broken again. @@ -1910,6 +2039,12 @@ DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputM RegionDelegate * DeepRegion::pull_generic (const Region &other, int mode, bool touching) const { + if (empty ()) { + return clone (); + } else if (other.empty ()) { + return new DeepRegion (deep_layer ().derived ()); + } + // with these flag set to true, the resulting polygons are broken again. bool split_after = false; @@ -1949,6 +2084,10 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const EdgesDelegate * DeepRegion::pull_generic (const Edges &other) const { + if (empty () || other.empty ()) { + return new DeepEdges (deep_layer ().derived ()); + } + std::unique_ptr dr_holder; const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); if (! other_deep) { @@ -1980,6 +2119,10 @@ DeepRegion::pull_generic (const Edges &other) const TextsDelegate * DeepRegion::pull_generic (const Texts &other) const { + if (empty () || other.empty ()) { + return new DeepTexts (deep_layer ().derived ()); + } + std::unique_ptr dr_holder; const db::DeepTexts *other_deep = dynamic_cast (other.delegate ()); if (! other_deep) { @@ -2010,6 +2153,24 @@ DeepRegion::pull_generic (const Texts &other) const std::pair DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { + if (output_mode == None) { + return std::pair ((RegionDelegate *) 0, (RegionDelegate *) 0); + } else if (empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (clone (), clone ()); + } else { + return std::make_pair (clone (), (RegionDelegate *) 0); + } + } else if (other.empty ()) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ()); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } + } + // with these flag set to true, the resulting polygons are broken again. bool split_after = false; From 13874986b21e2b4b5ec92cf7df2bc37079c942da Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 28 Nov 2022 23:40:04 +0100 Subject: [PATCH 09/12] Bugfix, tests updated --- src/db/db/dbDeepRegion.cc | 20 +++++++++++++++----- src/db/unit_tests/dbDeepRegionTests.cc | 6 +++--- testdata/algo/deep_region_au31.gds | Bin 8522 -> 8586 bytes 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 3af4d04c6..0f7ea7fd7 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1933,12 +1933,22 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to return std::make_pair (clone (), (RegionDelegate *) 0); } } else if (other.empty ()) { - if (output_mode == PositiveAndNegative) { - return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ()); - } else if (output_mode == Negative) { - return std::make_pair (clone (), (RegionDelegate *) 0); + if (mode > 0 /*outside*/) { + if (output_mode == PositiveAndNegative) { + return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ())); + } else if (output_mode == Negative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } else { + return std::make_pair (clone (), (RegionDelegate *) 0); + } } else { - return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + if (output_mode == PositiveAndNegative) { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ()); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0); + } } } diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 972b06614..d749a8ddf 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -1799,7 +1799,7 @@ TEST(30a_interact_with_count_region) EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), ""); - EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"); 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)"); @@ -1890,7 +1890,7 @@ TEST(30b_interact_with_count_edge) EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), ""); - EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"); 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)"); @@ -1980,7 +1980,7 @@ TEST(30c_interact_with_count_text) EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), ""); - EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); + EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"); 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)"); diff --git a/testdata/algo/deep_region_au31.gds b/testdata/algo/deep_region_au31.gds index 786700549f5b3184698a2217c14080913edb63ff..49e69259cfef2078b283e5bba99b3f4b64b54933 100644 GIT binary patch delta 180 zcmX@*)a9(iz{bGD6u}_F$i)7Pftx{wL7YL6K@gceQAt$-i!cKl8=KQ)Mq%-dW!%h@ z4>E^NZezBdyq}kKvlz>C7GW$pHXq>l&ocQxukYkN+{Tl$C3q+QfzX?M`1rBw$P?mX SoBTt(ROQAt$-i!cKl8=KQ)M`7`eW!%h@ zFETq!Ze$MKEXFdOMHq|f%?CLCvrOL3V==j&k7M$FUf<0 Date: Thu, 1 Dec 2022 08:23:17 +0100 Subject: [PATCH 10/12] Updated build script --- build.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/build.sh b/build.sh index c2a7bd11a..e49c132e5 100755 --- a/build.sh +++ b/build.sh @@ -560,6 +560,25 @@ else fi echo " Installation target: $BIN" echo " Build directory: $BUILD" +echo "" +echo " Build flags:" +echo " HAVE_RUBY=$HAVE_RUBY" +echo " HAVE_PYTHON=$HAVE_PYTHON" +echo " HAVE_QTBINDINGS=$HAVE_QTBINDINGS" +echo " HAVE_QT=$HAVE_QT" +echo " HAVE_QT_UITOOLS=$HAVE_QT_UITOOLS" +echo " HAVE_QT_NETWORK=$HAVE_QT_NETWORK" +echo " HAVE_QT_SQL=$HAVE_QT_SQL" +echo " HAVE_QT_SVG=$HAVE_QT_SVG" +echo " HAVE_QT_PRINTSUPPORT=$HAVE_QT_PRINTSUPPORT" +echo " HAVE_QT_MULTIMEDIA=$HAVE_QT_MULTIMEDIA" +echo " HAVE_QT_DESIGNER=$HAVE_QT_DESIGNER" +echo " HAVE_QT_XML=$HAVE_QT_XML" +echo " HAVE_64BIT_COORD=$HAVE_64BIT_COORD" +echo " HAVE_CURL=$HAVE_CURL" +echo " HAVE_PNG=$HAVE_PNG" +echo " HAVE_EXPAT=$HAVE_EXPAT" +echo " RPATH=$RPATH" mkdir -p $BUILD @@ -674,6 +693,7 @@ if [ $BUILD_EXPERT = 1 ]; then QMAKE_CXXFLAGS="$CXXFLAGS" QMAKE_CXXFLAGS_RELEASE= QMAKE_CXXFLAGS_DEBUG= + QMAKE_LIBS="$LIBS" QMAKE_LFLAGS="$LDFLAGS" QMAKE_LFLAGS_RELEASE= QMAKE_LFLAGS_DEBUG= From 512662f3e49fd6eb979955efdf75b9fde909abae Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 1 Dec 2022 21:24:00 +0100 Subject: [PATCH 11/12] Updated golden test data --- testdata/drc/drcSuiteTests_au6.oas | Bin 33448 -> 7804 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/testdata/drc/drcSuiteTests_au6.oas b/testdata/drc/drcSuiteTests_au6.oas index 411786177ae63b2ad81ec30d329b0b03c342cfbe..b29bc12cdf2577ff0fc422a43f8771a35758cebb 100644 GIT binary patch literal 7804 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 bL=qS{*h3N6Kv-H>PgodOn2`T7!NB|v6{s~7 literal 33448 zcmeHQ3wRYpmhS4lxk+wr2!ZYk*NMiU84!>UqOQ3S8FhTII^qmEGLGLm-%i|d_uJ3M z&g>3RaT8Qb9MnXRg&7=fzzAUw6XOFEF$oF@A||{{WeM->&N+2XbyX#I@+Ci+c;=)FCr_N59$?zIF=LgEWX1VkmT}VL8-H@) zlp7~cyzHt=F1~T%Ro7f{*(E=_@w$l@UvqhiFDpGufUmtOUWF_pF!{!7CS85wk1x6M z%Ag-5{L?i0Wj-XS7hZ^;kxA^LbVa|jP+6vKNNHl75nW}*c{eG{UmtAE=nm`})DVpN zYlk&VF!EVS)ZgZ7^R@fRHTr4EsMdR~#e3h}%r;+Va!qQ~-x)FTeZI!qO7n`ZSi6vw zgjbG51%J~?HL2}rI1d#ow1x@#ZBhTKq-tGnTa|?Olk_PYQpzsC`>C@7g{{|DT%}L# zNRIlOuk0G5=a*|0=Tv6v+sn1q>wB(E^A*;x8urTp^xKI1OFw!u3Rr(?o%I_J+liU> zB1{oX3Q5$amJQ&HPU%Q?Qm^PYgG1tPL&~Zo!Lr5aR3Q|I!4!)Tx%o&3q9&CFf=1Fa z5F}H#ERT#DeQKNU@pR(Kh}`1S?&wIl`}xqj+4^09!YZvKFHH@!BroQPd$niSZfzl(r4<^HThXXAeD}&Bou}$k1C83F;m=0vQx9r^2aVUq;>`m|wW&{y z(#LP|S7{%eo2KmX4b<;irUq^TDi(O!;7D!*k|m?>-aPc4VQ6v?NUG0tH_12g+y%@} zs$Mc~2ZrvHyGz2g!vyUOL}{Jx8CK<=Nt6=#Z9d*`7U*wgCjI{*=;sXu{VPE>dYPAL z(O>mLK@4yzflt^{#yMzWoP|5Lsho%33LZ>E!~+mgQZgmB-jjR_D`+iwcc5B;Is4&QgWe%B`d9L9T5@{%q!BGY`@()5x+(^HqHuOoPt zq~KEO^KMUj0T*rm+ov5$Da|{aBGjkNS4c#qvBHJwsDKeJW(S76d>T=T;b4W+@lxM0 zoyBooN8||fsrA9_X(f5&AuS`$-vAj^ ztrK<;%{G^KEoKa|f{eUL)3(0B!^+L}>v1ppboP`&~{ zwcdPIXsp7b{>p56vujXEUfFP}+L}>24AZpI#FB%AvnS9srui&*sa=Sq=tXycRDwDg zNEm8UOTzTJT&va{T{HwclhJp9!B`WcSd9p3X4RKAUrD8TnYF2)8Kt?I6owEDOZ3+3 z3910vH3p4Qnwwd60VqYi&gAYu>jS3UvyI+ zq%e^PrRMFE(vlnjVop8*qJADZ`Z-{~`aI*oV`@GjfLmYQ6eW!B=hS z5`E=ZqK$9>xik6(J!pvzi2%@& z(R^j?ur!3-s8}$>0-=&UVDZG^MQW2x14hDiGG&fdZ$bb}NHa|>`~wRKZLrjZ6<+2$ zUniudEI^_;AZREQ5e(kStH_~DG!{}|DhaG!gPsAKsk7+8)*Vxy(1T0!EwzCd%mHzZ z_JtwG=y55N{XoO-XQR)D&b!S8kFN0o0j5HaAe9yBY%8&;x**AE5Cx|QQxirI$@&U#6+PItr-ou@Tmo79LLtGz*4*aD;wlRDx1}vlbB79iXM>{%0(}E;F|{dEErV6IhFYG)>u%g1mIBi0mD) zK07yy5urg^Y zpFoE)uMHi?v&)Gfq4yvG$(U`6cEV$?Q^Z=OYjQY#EYwm#Xf$P@WIE;|N^I7OXV)r& zW!weXmJy+~ss32j5jm=5&}i>mL&9TR+r|67EY@CXpd|_0_+p}Pn6ONb6J__Hx0h9o z0_0+H&A>8SG%;6Kydne4^d{(A>VjC`63ZpFrZfb5#tR41+nSNR5@PyXNGJYs1OV|? zaX^QuiJ(o$m4?_{SAmZz*W`*DFt}DJ@a!CK2v<0BxH`U|0=OK&CN@0Fv*;nEFV<|( zJmIRDXHjSZGGDO*m!=%l()og;T*kBX$>E{x1s$S^7QD#9#DWg7YmV^EQ5Xb%U~mso?#&t>$xW^@;kK10;Iwo%YtnjftA8tk{yQNRJ#LM z{>C#c!y4x;L+TLs8&ceyU?6=(>SZSbzK*#AbyPMtBe*jW*Nl9uzI6@4myoz@_QImf z4UB@cezK|*aIq{}Z*mHviYk(Zefhdr;LWQIh126e_O0NLS%OnaH_r+HNdF;*C12N}SSAPR~7c*cn{ zLnMSD_#l3*`9010Y({WXwven>Ot+ig;!t1K|XgX)jVbEgF=VL9J!7h?T|Xb(xhoS0T)B6O{>S zr#+N^d6Ut}BWq}sqzwyad_*Q&C#`k<=QXs-iF@da)g#>E~fm(>UCpO=5Z6rV~ zGv5@Svu$S!h?$46!pR}*(*PCD{SY)SxPxwwM+UVrtxcGwN*C+MB71Ym1t-3weSaM> zQni@O8yX@F*IFv^7^MtL$b{`2UYe!TBYI*cw6H@lbMB(l<%Frm>@zz0rfQtGoW=dJ z6K8K;Yz*G_&b;FxSqqI!BaeRc_n{#ccKh1D%e`mm_N?Z#{doBTT!M4y5z>+IkY&nH zU^}(37lacorrOiniM?lHGv$%&Jwx^`rWiNW2l^#EwtCOBv4M`% zqGNBz@x}<(yd1)oZr7reBeD4&exDB>$4<{)ptC;_p4cpHogSc#BC(nN(fojTV(Z5D zH7hmFt3jIL{z4?vk>l|D(0R2UYTZ;Gvm;CAJq^k{GZSVjmu&GI_tW0j-eig6VRiVF zbu2oLJOhSXGFmgD+0ktJ-8BYB2b-T|9XO_>-%jWM=+v?iX^uSwu7}q%ew;b{nmDN* z*~ENWQ*QlrYl1jpNC%zsaR4>9_==6W_$D%fo*K8Xjk#;fM7x~Lj{1Gnjch?(H?F4K z;=;`tW>2Tuxb>}D*)p|>r77KkK{}2|R%kdPdB!&0S@9e;E34htCvEIaX5_RbrZ3X& zfW_f8^4C7#+W~h;1JbF(0n6#(+SE!ME^Pk?l1MMojO_Tv7~YD-04YkTQtx%C9m$Qk zwKx-Btyku|M@SFv#3Oh@GR;LVZAWA72ScssV&BP049G=DhQ#A+s1`kUFxiS3h!t;H#AzVd>qly)DT z(4#kv!Q#9JgUv`#o3A7}Jcu^Md5h5IW!{3GYbHL78u#bR7B&A&&va&vFl?GypS$+D z+SGlM^&84H>WTJ-4%Bg+cU2OdS~DW=9t&dbD%X~&M2_MlrGvy;#stX}>-)4d#PStR zF_BOjq)_!L^A%sw0AE9b*5lElPwT{IV_bF;3Zi4QH1few!}MV+Tm7<;{#jl^JL2Nuiosw>4pY+S?Z;kl zT&hyi#q^So@pAw_2l4YMem=vcDThGs`dkcRQ!ZWBV6e}b!M4youJhIeD>U415vhPRP+fiM zs-z}J1;j)iF%h+7tliQVqG^k=36T+*)i=fCW}}XaPxh#4L>8#HE2hq0`led^kbmt1 zsSVfl+@epN`{TE-XuYsxnh{xuR{c|jqv(X&mZ@At@`d-ceGfNTBWIC|D3bKIJS!w5 z2={$FPO|^b-Em@y^mD3IxMbmwTS$`nH8iOScjxrL`qU;wavm>j zyb9PSzPY61MtGSj!;%;~gI{V4N(W10V23GkM0yK*VkiPOj(-TXf%D_stLjj?nZ$^!K)uEZbmPz33AMxcrD)ppFeUgVN?uQA zD^(rgbnP&N;qY%wSPtmA%!s^z*3%0s{oR2Xh2l6Pp2Nk{4j3^6>Fhma517Yz@n+NE5PZF0IuF1c4&eBiP)`8HIF2 zlAsTSr{`7T#wd$mheqgAW(W9vh3r)*z}jzFs77Snx7>q1ZM|w<8z%1G%fC07-%dAn zHmf|t`y#&^2^a~?nn;cMmg*1FY^Y!@aqD6c}KDhRrFtM zR6COS6?A3;MW6OYue7wNK9%m7q|V^DRl0Q&SIxC=!7M==G4-OYK-u>p1G(sFM7F7M zS1{u)mBucq%Kho_PC*#s-t=Hjv;^zHiz5eL=hjAJT-(?0bBeroxYkW?9w zecz-9+cIK4zSuTsMBe`(XAm=*zF6@rONJ9BqyN>YMZs zM^dKaw8q4U6vw|GvVXIfsqrORB8{J+nX~JT`%x!G<4eCu*KwHZr^c5Zoo379q3(rEf#qUNI z@tp_+6E#17wkE^C1XYaiqXOZMKWged;TOlIA;G#jHD#<3nXmbL(+eqxn=yxSF5L9m z<}2klXB*>|d*o}~y_xwGK1n2!ww^-ky;jsDPZY}V!<=D_aWx+N2{B$yi{19DB7Lol z`9hIe&AFG&-b`*;>>qHCR z_=O$3_E9I-87Sw5ef#XBI5BC2pT@F&f-P|7IbhR!#K=Arse_#29UhPpbM|ZQ4TPvj zL?L-ifK9Y(v$4&sdxw#IY{3#_WQC@%t}zO28OMp3>`H7Ipi>Pk8MJkPA5qFy#H-Ha zN`UEAG`nE}Zi~S7+?rIp0aeh6+)!jCaM^p9%<)Ej`^Zg#t<=tAqV|qF$6b~2ZJ)`u6>#&XZnpf2nnS3MeqI^u!3#=IK!61&m-ThF;tSLL-j* zav>NxyoZsFyx98)1EbxGxg8s%J4e9oG=^;e;%yZ4h(g)`sET*Hg-7oF9ae^mX&18~ z>9;*D?h%ugf}?n3AGURXm3W#BRHmuKj34To8ZGYO6@S6u!qDK899D=n33U}Pq4{)e z?r?rUu$!Tt&(W6RmFU<^hzCzS=(@rR|s&};jH40r)j^oi6j7<+NVxhe0 zEOh=$Rx4V3PB(AG7jw#G1I2~L)jA&Bmu4w^zY}pZB!#*)otrI3 z;E{)I3xCb;S#`=Aw-H#UFNIx+BkT6%y76v^b{=zVpqp1gcG-Z233S=BrAyB1f9rk3 z02Da`61r_CQ%PhA)d|>22k=X2P^&Y!HkAwZoUyl}S$x&Tf%r;4J~TM{#0Arkf_aP{ zrCv_P1KRI<*TmKi;@I>k1?u0wmLN8eXLL_!Nq=tVi`A0BcdCsVyi#TM;G0>`X@hT5 zx{Sd^>Kb?r*Q?vvD|jWqx3gDeIrO8o@I?%bdQMAI%C&)d`#MeCobmZ-K++_TAA3zZV0@0Mg_-`rIU6+Isb2ItGQEsa9jCL*ZYBEDT^F;gtn#Z$hZ{et#O_pU3v9>Fx&w-F{zB)5&}jY=T`|Tp&!6!r zzbfii^c}0=;PxABK1IJ_#gO{ko&esxj6J3`*y@5_N{7EPSifO=+T6@`RM}B)LQva$ zXPn=FT{rL5uz8~&3e6k+aOj1FDO(;Kn4&0q-c5gc+pi4$xvx?cLw|aE8h$TdnXVXF z8~3L_u|9;tM?GrIY?z0#`j*wV7+DR^rA}|9%1eLGRP$Z+t4Tno;mOEa|9S@6S=FOY z>MzXA5}+qLv=68IIH>MEzmc_Xn{Qc{PgD3q$N#eWmjfInfBvE_`H?RMqW_sY2fV#v zh*=B7;H}E2C!lM2FH@9DR}DlZQU2=j05GX4)mi#`dd-XIVBzASq738*_nsokFU?9j z{A5}{t$p#LRqqWvbilu~YqT+*i>srCeOSYu9rNksfj_H&?0Pr-rPtKxxpjMz|9q}| z!2bp4vpGqtZ^0A({q69e)wh%{pgQ=sc}2+agcq-U9OgBx8hE#6*~y-Fv(_6?69;Ob z_E(=}^Nz(6ev5y9xHs&mw|~YZvI7AY-N+8aJ5)kp@$6A<$}EZ&Y#if;hz4lmfmm$- ztc#v5Wq>EE4az%ro+)W`Hb9k+_We*Yg?dilyHz9OwGmY~9Wf0=hw&g5S`YaaksgTE z2E8O^%nfn2aj;yX6I8mXBk;#p)J}rKz1)*0jn$uqr`91n927Y zu3IQDx=|iFA!=FjIYPS6fMM<^*9C#=f^+XwPX=UPttO~&5o}d$- z1LAH1`OWRp(13dgfd+I5(*80(4L~A(!RVQxC1ol(?rpEIkE_(cm~L4MGC(asI>+Ln zYhTj{Co!A?R1!_Nf>;a*{t^J)q$j}YU_=N3gxb#ZvC$8P7Hkjf`ZRzUQA{VVFYrC| zf=@Am-R}-y3LG_g?WX0-Q75?mal-;(_@4Mn3R5uGbOCkn-u*)?Tz}k`?7$NI>l;}X zsI5I^{_Y=GSl(YepmY{ZZo5B7U06!gV9ueQAFkD2*+b~@+_O?Mf=}0FiYJ1uep?3? zn)QqI#|QjXJ;C=j z41MzD)cLd3!w3A!yGG-;Df+o(Dv7>&C?>M&Q3V=fDUj3$4A)y#%(4or;Ls;o6bb?j zKm$>Z)o}3^dd2k%Px$B7AK9(P#spftmQ4h%uipcd+C!(%cn1xOYk`V$)@k6g>Z%k^Yh(#2+s6>&}>rZg2&@Z&@K4n{G z;O9bdEDs3x&V2&JhktnD&8;UCgwqi~@m`eWtY%FRqTrd*#B0kRIS~Qm!2-CLVLT9l z$V-l+-x%aPd=g**`Fu-`@U>Pil6lnPL7@PwFUvO0#$WTRVW#rDpAr}W$yLu!LwlDW z7wT`#P;yv2R$=*WSpz+J)Z9YjhR89&Tfu>4380B+6)IA7(d-=ZBk#^&q$LLC9;gQT zkzER+#A^?MR&96RXf7Z^aU3c|T~&R;-rJcJI32YB7ga1K+}%1ngwQ?@1)NRs*23W- zMxqe_fl2g>-!y2X@FFol+GC|aNIF){4ngO#$g7HxMAQX_j?0Phe0+O928~t{E z^TZbQ&;#jqGK73GzqKu9ocup5(5JzqKL<17{*PklN=x_N`IlMgd^O7JqaSS z=)uE~JsWuF!OJU_*`ddpWjxyO!8>hQZ6yg-3??vAB zc-T`47AnZqU@Ujm(+UBP_IL!fZW2;;%VzZGi)p68Y&`74T7YFR`ZHyjCgiQ^Akuyt zMfWMR%s{IdJd&FEL6TTzsQoek+#;TP^AN2)i1Pfo>9mA^`bJjGJA+Zsv@Bd&K{u@$JsjG66IOi!XINlhvSyq(T>~uou%=VlwFTkx zFP`vEw$#{fnI-5Y7DKI7PPD*?qRuf;-7)>B}6b-Xr zKjgqjo$2M;k|DAJnG$fqPJl$HJ4^y@OO!v{Lh+?2|8>RyD?LIl2!F*a1>}?-alf)| z5^st@z!KwOiiTB%KcEASh(9zw8sHFaMElz`j+Q?>8%-qyjHg4B>9`^2434wUH zcX29wUw~mKxBgAvYdduj=E5mc1Tz#WCxQ>5m2Pbl5KAj15LGRRR3xjCfC#lDoiu|5 z3T2Sg9>=C``dl*gb(4^2S_%ghZL2|QE;K{Om`N=mwL@}i)r8u8QT+qx3Wf#iyqZXd zF)UbbF`Y5Ag3@bJ7w*q7=*X2h2L24~MurR&&{>{Dlftf>#It59qJH-bQgL)WbL%jn zQfRb(&1s^H4zT(xf*O#DrDy0YMh63BWI=bxi78?pGtPeuJAi28cJUQ!7cyFdH&^Uw zThim{eC<8- Date: Thu, 1 Dec 2022 23:54:43 +0100 Subject: [PATCH 12/12] Fixed #1198 - 0.28 ignores link to script folder --- src/lym/lym/lymMacroCollection.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lym/lym/lymMacroCollection.cc b/src/lym/lym/lymMacroCollection.cc index 3316ef036..e6ac4ee9b 100644 --- a/src/lym/lym/lymMacroCollection.cc +++ b/src/lym/lym/lymMacroCollection.cc @@ -422,7 +422,8 @@ void MacroCollection::scan () } } - std::vector dirs = tl::dir_entries (p, false /*with_files*/, true /*with_dirs*/, true /*without_dotfiles*/); + // NOTE: we add files to capture symlinks to directories + std::vector dirs = tl::dir_entries (p, true /*with_files*/, true /*with_dirs*/, true /*without_dotfiles*/); for (auto f = dirs.begin (); f != dirs.end (); ++f) { std::string fp = tl::combine_path (p, *f);