From 7bd4a692d8f32177ab24114d722cf15d0d255ed0 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 8 Mar 2021 20:45:52 +0100 Subject: [PATCH] WIP --- src/db/db/dbFillTool.cc | 74 +++++++++++++++++++++++++--- src/db/unit_tests/dbFillToolTests.cc | 32 ++++++++++++ src/lay/lay/layFillDialog.cc | 18 ++++--- 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index 809049824..73f7e434d 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -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 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 fpa; std::vector 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 ::const_iterator fp = fpb.begin (); fp != fpb.end (); ++fp) { + for (std::vector ::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); diff --git a/src/db/unit_tests/dbFillToolTests.cc b/src/db/unit_tests/dbFillToolTests.cc index 9bade38cf..87078732a 100644 --- a/src/db/unit_tests/dbFillToolTests.cc +++ b/src/db/unit_tests/dbFillToolTests.cc @@ -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"); +} diff --git a/src/lay/lay/layFillDialog.cc b/src/lay/lay/layFillDialog.cc index 2d4abf1ae..acf29211e 100644 --- a/src/lay/lay/layFillDialog.cc +++ b/src/lay/lay/layFillDialog.cc @@ -176,13 +176,15 @@ FillDialog::generate_fill (const FillParameters &fp) const db::Cell *fill_cell = &ly.cell (fc.second); - std::pair 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 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 ());