diff --git a/Changelog b/Changelog index 32ad2a392..c6b319e1b 100644 --- a/Changelog +++ b/Changelog @@ -47,6 +47,10 @@ * Bugfix: https://github.com/klayoutmatthias/klayout/issues/114 Custom line styles not loaded from tech's layer properties file. +* Enhancement: https://github.com/klayoutmatthias/klayout/issues/113 + The XOR tool has an option now to heal result shapes which + cross tile boundaries. The result shape count of tiled + and non-tiled mode should basically be the same then. * Bugfix: https://github.com/klayoutmatthias/klayout/issues/112 Salt package repository relative paths have not been working. * Bugfix: https://github.com/klayoutmatthias/klayout/issues/109 diff --git a/src/ext/ext/XORToolDialog.ui b/src/ext/ext/XORToolDialog.ui index ff1d90e6b..e9cf1d978 100644 --- a/src/ext/ext/XORToolDialog.ui +++ b/src/ext/ext/XORToolDialog.ui @@ -1,7 +1,8 @@ - + + XORToolDialog - - + + 0 0 @@ -9,87 +10,103 @@ 649 - + XOR Tool - - - 9 - - + + 6 + + 9 + + + 9 + + + 9 + + + 9 + - - + + Input - - + + 9 - + + 9 + + + 9 + + + 9 + + 6 - - - + + + From region - - - + + + Layout A - - - + + + Use for input - - - + + + Layout B - - - - - 5 - 0 + + + + 1 0 - + All Layers (different layouts) - + Visible layers (different layouts) - + - + Qt::Vertical - + QSizePolicy::Fixed - + 0 10 @@ -97,72 +114,66 @@ - - - - - 5 - 0 + + + + 0 0 - + All - + Visible region - + Clipped to ruler - - - - - 5 - 0 + + + + 1 0 - + QComboBox::AdjustToContentsOnFirstShow - - - - - 5 - 0 + + + + 1 0 - + QComboBox::AdjustToContentsOnFirstShow - + - + Qt::Vertical - + QSizePolicy::Fixed - + 0 10 @@ -170,17 +181,15 @@ - - - - - 7 - 5 + + + + 1 0 - + @@ -189,59 +198,64 @@ - - + + Options - - + + 9 - + + 9 + + + 9 + + + 9 + + 6 - - - - - 5 - 0 + + + + 0 0 - + A NOT B (In A but not in B) - - - - - 5 - 0 + + + + 0 0 - + A XOR B (differences) - + true - + - + Qt::Vertical - + QSizePolicy::Fixed - + 0 10 @@ -249,72 +263,79 @@ - - - + + + Summarize missing layers - + true - - - + + + Tolerances - - - + + + Compare modes - - - + + + Tolerances (t1,t2,..) in micron - - - + + + Threads - - - + + + Tiling - - - + + + QFrame::NoFrame - + QFrame::Raised - - - 0 - - + + 6 + + 0 + + + 0 + + + 0 + + + 0 + - - - - 5 - 0 + + + 0 0 @@ -322,56 +343,68 @@ - - - - 5 - 5 + + + 1 0 - + Tile size in micron + + + + Heal result shapes + + + - - - + + + QFrame::NoFrame - + QFrame::Raised - - - 0 - - + + 6 + + 0 + + + 0 + + + 0 + + + 0 + - - + + 1 - - - - 5 - 5 + + + 1 0 - + Used for tiles and layers @@ -379,27 +412,23 @@ - - - - - 5 - 0 + + + + 0 0 - + B NOT A (in B but not in A) - - - - - 5 - 0 + + + + 1 0 @@ -410,74 +439,79 @@ - - + + Output - - - 9 - - + + 6 + + 9 + + + 9 + + + 9 + + + 9 + - - + + Send output to - - - - 7 - 0 + + + 0 0 - + Marker database - + Other layout - + New layers in layout A ... - + New layers in layout B ... - - + + with offset - - - - 5 - 0 + + + 0 0 - + 1000/0 @@ -487,10 +521,10 @@ - + Qt::Vertical - + 0 16 @@ -499,12 +533,12 @@ - - + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -541,11 +575,11 @@ XORToolDialog accept() - + 248 254 - + 157 274 @@ -557,11 +591,11 @@ XORToolDialog reject() - + 316 260 - + 286 274 diff --git a/src/ext/ext/ext.pro b/src/ext/ext/ext.pro index 093a3ff5f..0900927a9 100644 --- a/src/ext/ext/ext.pro +++ b/src/ext/ext/ext.pro @@ -41,6 +41,7 @@ FORMS += \ SizingOptionsDialog.ui \ StreamImportDialog.ui \ MergeOptionsDialog.ui \ + XORToolDialog.ui SOURCES += \ extBooleanOperationsDialogs.cc \ diff --git a/src/ext/ext/extXORToolDialog.cc b/src/ext/ext/extXORToolDialog.cc index 47cfd30e0..4bd5ae6a9 100644 --- a/src/ext/ext/extXORToolDialog.cc +++ b/src/ext/ext/extXORToolDialog.cc @@ -29,6 +29,7 @@ #include "dbRecursiveShapeIterator.h" #include "dbClip.h" #include "dbLayoutUtils.h" +#include "dbRegion.h" #include "tlTimer.h" #include "tlProgress.h" #include "tlThreadedWorkers.h" @@ -58,6 +59,7 @@ std::string cfg_xor_bnota ("xor-bnota"); std::string cfg_xor_summarize ("xor-summarize"); std::string cfg_xor_tolerances ("xor-tolerances"); std::string cfg_xor_tiling ("xor-tiling"); +std::string cfg_xor_tiling_heal ("xor-tiling-heal"); std::string cfg_xor_region_mode ("xor-region-mode"); // Note: this enum must match with the order of the combo box entries in the @@ -254,6 +256,11 @@ XORToolDialog::exec_dialog (lay::LayoutView *view) mp_ui->tiling->setText (tl::to_qstring (tiling)); } + bool heal = false; + if (config_root->config_get (cfg_xor_tiling_heal, heal)) { + mp_ui->heal_cb->setChecked (heal); + } + int ret = QDialog::exec (); if (ret) { @@ -329,6 +336,7 @@ BEGIN_PROTECTED config_root->config_set (cfg_xor_summarize, mp_ui->summarize_cb->isChecked ()); config_root->config_set (cfg_xor_tolerances, tl::to_string (mp_ui->tolerances->text ())); config_root->config_set (cfg_xor_tiling, tl::to_string (mp_ui->tiling->text ())); + config_root->config_set (cfg_xor_tiling_heal, mp_ui->heal_cb->isChecked ()); config_root->config_end (); QDialog::accept (); @@ -380,6 +388,7 @@ public: m_op (op), m_el_handling (el_handling), m_has_tiles (false), + m_tile_heal (false), m_dbu (dbu), m_cva (cva), m_cvb (cvb), @@ -415,11 +424,12 @@ public: return m_has_tiles; } - void has_tiles (bool ht, int nx, int ny) + void set_tiles (bool ht, int nx, int ny, bool heal) { m_has_tiles = ht; m_nx = ht ? nx : 0; m_ny = ht ? ny : 0; + m_tile_heal = heal; } double dbu () const @@ -500,11 +510,17 @@ public: } } - void issue_polygon (unsigned int tol_index, unsigned int layer_index, const db::Polygon &polygon, const db::CplxTrans &trans) + void issue_polygon (unsigned int tol_index, unsigned int layer_index, const db::Polygon &polygon, bool touches_border = false) { QMutexLocker locker (&m_mutex); + db::CplxTrans trans (dbu ()); - if (m_output_mode == OMMarkerDatabase) { + if (m_tile_heal && touches_border) { + + // save for merging later + m_polygons_to_heal [std::make_pair (tol_index, layer_index)].insert (polygon); + + } else if (m_output_mode == OMMarkerDatabase) { rdb::Category *layercat = m_layer_categories[tol_index][layer_index]; @@ -532,6 +548,16 @@ public: } } + void finish () + { + // merge the polygons to heal and re-issue (this time without healing) + for (std::map, db::Region>::iterator p = m_polygons_to_heal.begin (); p != m_polygons_to_heal.end (); ++p) { + for (db::Region::const_iterator mp = p->second.begin_merged (); !mp.at_end (); ++mp) { + issue_polygon (p->first.first, p->first.second, *mp, false); + } + } + } + virtual tl::Worker *create_worker (); private: @@ -539,6 +565,7 @@ private: db::BooleanOp::BoolOp m_op; EmptyLayerHandling m_el_handling; bool m_has_tiles; + bool m_tile_heal; double m_dbu; lay::CellView m_cva; lay::CellView m_cvb; @@ -554,6 +581,7 @@ private: std::string m_result_string; size_t m_nx, m_ny; std::map, std::vector > > m_results; + std::map, db::Region> m_polygons_to_heal; }; class XORTask @@ -826,8 +854,6 @@ XORWorker::do_perform (const XORTask *xor_task) sp.size (xor_results, xor_results_cell, 0, xor_results_cell.shapes (0), ((*t + 1) / 2), (unsigned int)2, false); } - db::CplxTrans trans = db::CplxTrans (mp_job->dbu ()); - size_t n = 0; for (db::Shapes::shape_iterator s = xor_results_cell.shapes (0).begin (db::ShapeIterator::All); ! s.at_end (); ++s) { @@ -836,14 +862,16 @@ XORWorker::do_perform (const XORTask *xor_task) std::vector clipped_poly; clip_poly (s->polygon (), xor_task->clip_box (), clipped_poly, false /*don't resolve holes*/); + db::Box inner = xor_task->clip_box ().enlarged (db::Vector (-1, -1)); for (std::vector ::const_iterator cp = clipped_poly.begin (); cp != clipped_poly.end (); ++cp) { - mp_job->issue_polygon (tol_index, xor_task->layer_index (), *cp, trans); + + mp_job->issue_polygon (tol_index, xor_task->layer_index (), *cp, !cp->box ().inside (inner)); ++n; } } else { - mp_job->issue_polygon (tol_index, xor_task->layer_index (), s->polygon (), trans); + mp_job->issue_polygon (tol_index, xor_task->layer_index (), s->polygon ()); ++n; } @@ -988,6 +1016,7 @@ XORToolDialog::run_xor () } double tile_size = 0; // in micron units + bool tile_heal = mp_ui->heal_cb->isChecked (); { std::string text (tl::to_string (mp_ui->tiling->text ())); @@ -1298,7 +1327,7 @@ XORToolDialog::run_xor () db::Coord tile_enlargement_b = db::coord_traits::rounded_up (tile_enlargement * dbu / cvb->layout ().dbu ()); if (ntiles_w > 1 || ntiles_h > 1 || region_mode != RMAll /*enforces clip*/) { - job.has_tiles (true, ntiles_w, ntiles_h); + job.set_tiles (true, ntiles_w, ntiles_h, tile_heal); } // create the XOR tasks @@ -1378,6 +1407,9 @@ XORToolDialog::run_xor () throw tl::Exception (tl::to_string (QObject::tr ("Errors occured during processing. First error message says:\n")) + job.error_messages ().front ()); } + // apply healing if required + job.finish (); + } if (was_cancelled && output_mode == OMMarkerDatabase) { diff --git a/src/lay/lay/lay.pro b/src/lay/lay/lay.pro index b17a5fe2b..bc8e16865 100644 --- a/src/lay/lay/lay.pro +++ b/src/lay/lay/lay.pro @@ -97,7 +97,6 @@ FORMS = \ TechLayerMappingEditorPage.ui \ TechMacrosPage.ui \ TechSetupDialog.ui \ - XORToolDialog.ui \ TechLoadOptionsEditorPage.ui \ TechSaveOptionsEditorPage.ui \ MainConfigPage7.ui \