This commit is contained in:
Matthias Koefferlein 2021-03-08 20:45:52 +01:00
parent d76fc02244
commit 7bd4a692d8
3 changed files with 111 additions and 13 deletions

View File

@ -323,11 +323,69 @@ rasterize_extended (const db::Polygon &fp, const db::Box &fc_bbox, db::AreaMap &
return false;
}
am.reinitialize (fp_bbox.p1 (), db::Vector (dx, dy), size_t (nx), size_t (ny));
// @@@
// try to create a point for which the fill box is inside the polygon
size_t nhull = fp.hull ().size ();
if (nhull < 3) {
return false;
}
db::Point p0 = fp.hull ()[0];
db::Point p1 = fp.hull ()[1];
db::Point pm1 = fp.hull ()[nhull - 1];
db::Coord hx = (dx + 1) / 2;
db::Coord hy = (dy + 1) / 2;
db::Edge e1 (p0, p1);
if (e1.dx () < 0) {
e1.move (db::Vector (hx, hy));
} else {
e1.move (db::Vector (hx, -hy));
}
db::Edge em1 (p0, pm1);
if (em1.dy () < 0) {
em1.move (db::Vector (hx, hy));
} else {
em1.move (db::Vector (-hx, hy));
}
std::pair<bool, db::Point> cp = e1.cut_point (em1);
db::Point o = fp_bbox.p1 ();
if (cp.first) {
db::Point po = cp.second - db::Vector (hx, hy);
o = po - db::Vector (dx * ((po.x () - fp_bbox.p1 ().x ()) / dx), dy * ((po.y () - fp_bbox.p1 ().y ()) / dy));
}
printf("@@@ fp=%s\n", fp.to_string().c_str()); fflush(stdout); // @@@
printf("@@@ -> o=%s\n", o.to_string().c_str()); fflush(stdout); // @@@
// @@@
am.reinitialize (o, db::Vector (dx, dy), size_t (nx), size_t (ny));
// Rasterize to determine fill regions
db::rasterize (fp, am);
// @@@
{
db::Coord nx = db::Coord (am.nx ());
db::Coord ny = db::Coord (am.ny ());
db::AreaMap::area_type amax = am.pixel_area ();
double n = 0;
for (size_t i = 0; i < size_t (nx); ++i) {
for (size_t j = 0; j < size_t (ny); ++j) {
if (am.get (i, j) >= amax) {
n += 1;
}
}
}
printf("@@@ -> n=%d\n", int(n)); fflush(stdout); // @@@
}
// @@@
return true; // @@@
if (tl::verbosity () >= 50) {
db::Coord nx = db::Coord (am.nx ());
@ -356,7 +414,6 @@ rasterize_extended (const db::Polygon &fp, const db::Box &fc_bbox, db::AreaMap &
am.move (d);
am.clear ();
db::rasterize (fp, am);
if (tl::verbosity () >= 50) {
@ -501,7 +558,7 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
std::vector <db::Polygon> fpa;
std::vector <db::Polygon> fpb;
fpa.push_back (fp0.transformed (shear));
fpa.push_back (fp0);
ep.size (fpa, -dx, 0, fpb, 3 /*mode*/, false /*=don't resolve holes*/);
fpa.swap (fpb);
@ -524,7 +581,9 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
filled_regions.clear ();
bool any_fill = false;
for (std::vector <db::Polygon>::const_iterator fp = fpb.begin (); fp != fpb.end (); ++fp) {
for (std::vector <db::Polygon>::const_iterator fpr = fpb.begin (); fpr != fpb.end (); ++fpr) {
db::Polygon fp = fpr->transformed (shear);
size_t ninsts = 0;
@ -534,7 +593,7 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
// Rasterize to determine fill regions
// NOTE: rasterization happens post-shear transformation (e.g. with a rectangular kernel)
if ((enhanced_fill && rasterize_extended (*fp, raster_box, am)) || (!enhanced_fill && rasterize_simple (*fp, raster_box, origin, am))) {
if ((enhanced_fill && rasterize_extended (fp, raster_box, am)) || (!enhanced_fill && rasterize_simple (fp, raster_box, origin, am))) {
size_t nx = am.nx ();
size_t ny = am.ny ();
@ -585,7 +644,7 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
}
if (tl::verbosity () >= 30 && ninsts > 0) {
tl::info << "Part " << fp->to_string ();
tl::info << "Part " << fpr->to_string ();
tl::info << "Created " << ninsts << " instances";
}
@ -630,7 +689,7 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell
static void
fill_region_impl (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, int iteration)
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, int iteration)
{
if (row_step.x () <= 0 || column_step.y () <= 0) {
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row step must have a positive x component while column step must have a positive y component")));
@ -708,6 +767,7 @@ fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fi
++iteration;
remaining.clear ();
fill_region_impl (cell, *fill_region, fill_cell_index, kernel_origin, row_step, column_step, db::Point (), true, &remaining, fill_margin, remaining_polygons, iteration);
new_fill_region.swap (remaining);

View File

@ -213,3 +213,35 @@ TEST(3c)
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/fill_tool_au3c.gds");
}
TEST(4)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/fill_tool4.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type fill_cell = ly.cell_by_name ("FILL_CELL").second;
db::cell_index_type top_cell = ly.cell_by_name ("TOP").second;
unsigned int fill_layer = ly.get_layer (db::LayerProperties (1, 0));
db::Region fill_region (db::RecursiveShapeIterator (ly, ly.cell (top_cell), fill_layer));
db::Region remaining_polygons;
db::Vector ko (-100, -130);
db::Vector rs (230, 0);
db::Vector cs (0, 230);
db::fill_region_repeat (&ly.cell (top_cell), fill_region, fill_cell, ko, rs, cs, db::Vector (50, 100), &remaining_polygons);
unsigned int l100 = ly.insert_layer (db::LayerProperties (100, 0));
unsigned int l101 = ly.insert_layer (db::LayerProperties (101, 0));
remaining_polygons.insert_into (&ly, top_cell, l101);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/fill_tool_au4.gds");
}

View File

@ -176,13 +176,15 @@ FillDialog::generate_fill (const FillParameters &fp)
const db::Cell *fill_cell = &ly.cell (fc.second);
std::pair<bool, db::cell_index_type> fc2 = cv->layout ().cell_by_name (fp.fill_cell_name2.c_str ());
if (! fc.first) {
throw tl::Exception (tl::to_string (QObject::tr ("Secondary fill cell not found: ")) + fp.fill_cell_name2);
const db::Cell *fill_cell2 = 0;
if (! fp.fill_cell_name2.empty ()) {
std::pair<bool, db::cell_index_type> fc2 = cv->layout ().cell_by_name (fp.fill_cell_name2.c_str ());
if (! fc2.first) {
throw tl::Exception (tl::to_string (QObject::tr ("Secondary fill cell not found: ")) + fp.fill_cell_name2);
}
fill_cell2 = &ly.cell (fc2.second);
}
const db::Cell *fill_cell2 = &ly.cell (fc2.second);
db::Vector row_step = db::CplxTrans (ly.dbu ()).inverted () * fp.row_step;
db::Vector column_step = db::CplxTrans (ly.dbu ()).inverted () * fp.column_step;
db::Vector kernel_origin = db::CplxTrans (ly.dbu ()).inverted () * fp.kernel_origin;
@ -472,7 +474,11 @@ FillDialog::get_fill_parameters ()
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 ()) {
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected to get fill cell's bounding box from - layer is empty for the fill cell")));
if (fc_bbox_layer >= 0) {
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected to get fill cell's bounding box from - layer is empty for the fill cell")));
} else {
throw tl::Exception (tl::to_string (QObject::tr ("Fill cell is empty")));
}
}
s = tl::to_string (row_le->text ());