Some fill tool enhancements

* It's possible to specify the fill cell origin now
  (this is the point where the first cell's lower left is placed)
* margin is taken into account when no step vectors are specified
* "No exclude" is default
This commit is contained in:
Matthias Koefferlein 2026-02-14 22:03:17 +01:00
parent 88efda71e6
commit c1b4f97f33
3 changed files with 254 additions and 152 deletions

View File

@ -86,87 +86,6 @@
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QFrame" name="frame_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="_14">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="fill_area_cbx">
<property name="toolTip">
<string>Select how the region to fill is specified.</string>
</property>
<item>
<property name="text">
<string>All (whole cell)</string>
</property>
</item>
<item>
<property name="text">
<string>Shapes on layer ...</string>
</property>
</item>
<item>
<property name="text">
<string>Selected shapes</string>
</property>
</item>
<item>
<property name="text">
<string>Single box with ...</string>
</property>
</item>
<item>
<property name="text">
<string>Ruler bounding boxes</string>
</property>
</item>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QFrame" name="frame_6">
<property name="frameShape">
@ -277,22 +196,6 @@
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="0" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>241</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<spacer>
<property name="orientation">
@ -316,6 +219,22 @@
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>241</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_6">
@ -436,6 +355,87 @@
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QFrame" name="frame_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="_14">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="fill_area_cbx">
<property name="toolTip">
<string>Select how the region to fill is specified.</string>
</property>
<item>
<property name="text">
<string>All (whole cell)</string>
</property>
</item>
<item>
<property name="text">
<string>Shapes on layer ...</string>
</property>
</item>
<item>
<property name="text">
<string>Selected shapes</string>
</property>
</item>
<item>
<property name="text">
<string>Single box with ...</string>
</property>
</item>
<item>
<property name="text">
<string>Ruler bounding boxes</string>
</property>
</item>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
@ -491,6 +491,9 @@
<property name="toolTip">
<string>The fill will not be generated over the areas specified by these layers</string>
</property>
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>All layers</string>
@ -810,6 +813,83 @@
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Raster origin</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="origin_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>(x, y of lower-left corner of fill cell in µm)</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>135</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="second_order_fill_cb">
<property name="title">
@ -837,13 +917,6 @@
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="2">
<widget class="QLabel" name="label_60">
<property name="text">
<string>µm (keep distance between fill cells unless stitched)</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLineEdit" name="fill_cell_2nd_le">
<property name="toolTip">
@ -851,16 +924,17 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="fill2_margin_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="1" column="2">
<widget class="QLabel" name="label_60">
<property name="text">
<string>µm (keep distance between fill cells unless stitched)</string>
</property>
<property name="toolTip">
<string>Leave empty for no distance. Otherwise enter a distance in micron (can be anisotropic in the form &quot;dx,dy&quot;)</string>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_57">
<property name="text">
<string>Fill cell margin </string>
</property>
</widget>
</item>
@ -871,26 +945,6 @@
</property>
</widget>
</item>
<item row="1" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>141</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_57">
<property name="text">
<string>Fill cell margin </string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_59">
<property name="sizePolicy">
@ -904,16 +958,6 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="5">
<widget class="QLabel" name="label_58">
<property name="text">
<string>The second order fill cell is used to fill space remaining from the first fill step. Thus, the second order fill cell must be smaller than the first order fill cell. The boundary layer must be the same for the second order fill cell.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_56">
<property name="text">
@ -980,6 +1024,42 @@
</layout>
</widget>
</item>
<item row="1" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>141</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="5">
<widget class="QLabel" name="label_58">
<property name="text">
<string>The second order fill cell is used to fill space remaining from the first fill step. Thus, the second order fill cell must be smaller than the first order fill cell. The boundary layer must be the same for the second order fill cell.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="fill2_margin_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Leave empty for no distance. Otherwise enter a distance in micron (can be anisotropic in the form &quot;dx,dy&quot;)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -1030,6 +1110,7 @@
<tabstop>row_le</tabstop>
<tabstop>column_le</tabstop>
<tabstop>enhanced_cb</tabstop>
<tabstop>origin_le</tabstop>
<tabstop>second_order_fill_cb</tabstop>
<tabstop>fill_cell_2nd_le</tabstop>
<tabstop>choose_fc_2nd_pb</tabstop>

View File

@ -92,6 +92,7 @@ FillDialog::FillDialog (QWidget *parent, LayoutViewBase *view)
fill_area_stack->setCurrentIndex (0);
connect (fill_area_cbx, SIGNAL (currentIndexChanged (int)), this, SLOT (fill_area_changed (int)));
connect (enhanced_cb, SIGNAL (stateChanged (int)), this, SLOT (enhanced_fill_changed (int)));
connect (button_box, SIGNAL (accepted ()), this, SLOT (ok_pressed ()));
connect (choose_fc_pb, SIGNAL (clicked ()), this, SLOT (choose_fc ()));
connect (choose_fc_2nd_pb, SIGNAL (clicked ()), this, SLOT (choose_fc_2nd ()));
@ -167,6 +168,8 @@ FillDialog::generate_fill (const FillParameters &fp)
bool enhanced_fill = enhanced_cb->isChecked ();
db::Point fill_origin = db::CplxTrans (ly.dbu ()).inverted () * fp.fill_origin;
db::Coord exclude_x = db::coord_traits<db::Coord>::rounded (fp.exclude_distance.x () / ly.dbu ());
db::Coord exclude_y = db::coord_traits<db::Coord>::rounded (fp.exclude_distance.y () / ly.dbu ());
@ -232,8 +235,6 @@ FillDialog::generate_fill (const FillParameters &fp)
fill_region.merge ();
}
db::Box fr_bbox = fill_region.bbox ();
if (tl::verbosity () >= 20) {
tl::info << "Collecting exclude areas";
}
@ -263,8 +264,6 @@ FillDialog::generate_fill (const FillParameters &fp)
// Perform the NOT operation to create the fill region
fill_region -= es;
db::Region new_fill_area;
int step = 0;
do {
@ -276,7 +275,7 @@ FillDialog::generate_fill (const FillParameters &fp)
}
if (! enhanced_fill) {
db::fill_region (cv.cell (), fill_region, fill_cell->cell_index (), fc_bbox, row_step, column_step, fr_bbox.p1 (), false, fill_cell2 ? &fill_region : 0, fill_margin, fill_cell2 ? &fill_region : 0);
db::fill_region (cv.cell (), fill_region, fill_cell->cell_index (), fc_bbox, row_step, column_step, fill_origin, false, fill_cell2 ? &fill_region : 0, fill_margin, fill_cell2 ? &fill_region : 0);
} else {
db::fill_region_repeat (cv.cell (), fill_region, fill_cell->cell_index (), fc_bbox, row_step, column_step, fill_margin, fill_cell2 ? &fill_region : 0);
}
@ -478,6 +477,20 @@ FillDialog::get_fill_parameters ()
fp.enhanced_fill = enhanced_cb->isChecked ();
// read origin
x = 0.0, y = 0.0;
s = tl::to_string (origin_le->text ());
ex = tl::Extractor (s.c_str ());
if (ex.try_read (x)) {
if (ex.test (",") && ex.try_read (y)) {
// take x, y
} else {
y = x;
}
}
fp.fill_origin = db::DPoint (x, y);
db::DBox fc_bbox = db::CplxTrans (cv->layout ().dbu ()) * (fc_bbox_layer < 0 ? fill_cell->bbox () : fill_cell->bbox (fc_bbox_layer));
if (fc_bbox.empty ()) {
if (fc_bbox_layer >= 0) {
@ -492,7 +505,7 @@ FillDialog::get_fill_parameters ()
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
fp.row_step = db::DVector (x, y);
} else {
fp.row_step = db::DVector (fc_bbox.width (), 0.0);
fp.row_step = db::DVector (fc_bbox.width () + fp.fill_cell_margin.x (), 0.0);
}
s = tl::to_string (column_le->text ());
@ -500,7 +513,7 @@ FillDialog::get_fill_parameters ()
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
fp.column_step = db::DVector (x, y);
} else {
fp.column_step = db::DVector (0.0, fc_bbox.height ());
fp.column_step = db::DVector (0.0, fc_bbox.height () + fp.fill_cell_margin.y ());
}
fp.fc_bbox = fc_bbox;
@ -528,7 +541,7 @@ FillDialog::get_fill_parameters ()
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
fp.row_step2 = db::DVector (x, y);
} else {
fp.row_step2 = db::DVector (fc_bbox2.width (), 0.0);
fp.row_step2 = db::DVector (fc_bbox2.width () + fp.fill_cell_margin2.x (), 0.0);
}
s = tl::to_string (column_2nd_le->text ());
@ -536,7 +549,7 @@ FillDialog::get_fill_parameters ()
if (ex.try_read (x) && ex.test (",") && ex.try_read (y)) {
fp.column_step2 = db::DVector (x, y);
} else {
fp.column_step2 = db::DVector (0.0, fc_bbox2.height ());
fp.column_step2 = db::DVector (0.0, fc_bbox2.height () + fp.fill_cell_margin2.y ());
}
fp.fc_bbox2 = fc_bbox2;
@ -575,6 +588,12 @@ BEGIN_PROTECTED
END_PROTECTED
}
void
FillDialog::enhanced_fill_changed (int ef)
{
origin_le->setEnabled (ef != Qt::Checked);
}
void
FillDialog::fill_area_changed (int fa)
{

View File

@ -53,6 +53,7 @@ struct LAY_PUBLIC FillParameters
bool exclude_all_layers;
std::vector<db::LayerProperties> exclude_layers;
FillRegionMode fill_region_mode;
db::DPoint fill_origin;
db::Region fill_region;
db::LayerProperties fill_region_layer;
db::DVector exclude_distance;
@ -81,6 +82,7 @@ public:
public slots:
void fill_area_changed (int);
void enhanced_fill_changed (int);
void ok_pressed ();
void choose_fc ();
void choose_fc_2nd ();