diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index e795c0f1b..d6d216d2b 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -37,13 +37,13 @@ class GenericRasterizer { public: GenericRasterizer () - : m_row_step (), m_column_step (), m_row_steps (0), m_column_steps (0), m_origin () + : m_row_step (), m_column_step (), m_row_steps (0), m_column_steps (0), m_origin (), m_dim () { // .. nothing yet .. } - GenericRasterizer (const db::Polygon &fp, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin) - : m_row_step (row_step), m_column_step (column_step), m_row_steps (0), m_column_steps (0), m_origin (origin) + GenericRasterizer (const db::Polygon &fp, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, const db::Vector &dim) + : m_row_step (row_step), m_column_step (column_step), m_row_steps (0), m_column_steps (0), m_origin (origin), m_dim (dim) { rasterize (fp); } @@ -76,6 +76,11 @@ public: m_column_steps = tl::lcm (dx, std::abs (m_column_step.x ())) / std::abs (m_column_step.x ()); } + // because the rasterizer can't handle overlapping cells we need to multiply the row and columns steps + // with an integer until the effective rasterizer pitch get big enough. + m_row_steps *= (m_dim.x () - 1) / (m_row_steps * m_row_step.x ()) + 1; + m_column_steps *= (m_dim.y () - 1) / (m_column_steps * m_column_step.y ()) + 1; + db::Box fp_bbox = fp.box (); // compensate for distortion by sheared kernel @@ -115,7 +120,7 @@ public: db::Vector dr = m_row_step * long (ir); db::Vector dc = m_column_step * long (ic); - am.reinitialize (db::Point (fp_left, fp_bottom) + dr + dc, db::Vector (ddx, ddy), db::Vector (dx, dy), nx, ny); + am.reinitialize (db::Point (fp_left, fp_bottom) + dr + dc, db::Vector (ddx, ddy), m_dim, nx, ny); if (db::rasterize (fp, am)) { m_area_maps.push_back (db::AreaMap ()); @@ -191,11 +196,12 @@ private: db::Vector m_row_step, m_column_step; unsigned int m_row_steps, m_column_steps; db::Point m_origin; + db::Vector m_dim; }; static bool -fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, 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, +fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill, std::vector *remaining_parts, const db::Vector &fill_margin, const db::Box &glue_box) { if (row_step.x () <= 0 || column_step.y () <= 0) { @@ -211,11 +217,13 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f enhanced_fill = false; } + db::Vector kernel_origin (fc_bbox.left (), fc_bbox.bottom ()); + std::vector filled_regions; db::EdgeProcessor ep; // under- and oversize the polygon to remove slivers that cannot be filled. - db::Coord dx = row_step.x () / 2 - 1, dy = column_step.y () / 2 - 1; + db::Coord dx = fc_bbox.width () / 2 - 1, dy = fc_bbox.height () / 2 - 1; std::vector fpa; std::vector fpb; @@ -255,7 +263,7 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f o = fp->hull () [0]; } - GenericRasterizer am (*fp, row_step, column_step, o); + GenericRasterizer am (*fp, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ()); for (unsigned int i = 0; i < am.area_maps (); ++i) { @@ -350,10 +358,10 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f } DB_PUBLIC bool -fill_region (db::Cell *cell, const db::Polygon &fp0, 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, +fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_cell_index, const Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill, std::vector *remaining_parts, const db::Vector &fill_margin, const db::Box &glue_box) { - return fill_polygon_impl (cell, fp0, fill_cell_index, kernel_origin, row_step, column_step, origin, enhanced_fill, remaining_parts, fill_margin, glue_box); + return fill_polygon_impl (cell, fp0, fill_cell_index, fc_box, row_step, column_step, origin, enhanced_fill, remaining_parts, fill_margin, glue_box); } DB_PUBLIC bool @@ -364,11 +372,11 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)"))); } - return fill_polygon_impl (cell, fp0, fill_cell_index, fc_bbox.p1 () - db::Point (), db::Vector (fc_bbox.width (), 0), db::Vector (0, fc_bbox.height ()), origin, enhanced_fill, remaining_parts, fill_margin, glue_box); + return fill_polygon_impl (cell, fp0, fill_cell_index, fc_bbox, db::Vector (fc_bbox.width (), 0), db::Vector (0, fc_bbox.height ()), origin, enhanced_fill, remaining_parts, fill_margin, glue_box); } 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, +fill_region_impl (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, 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, const db::Box &glue_box) { if (row_step.x () <= 0 || column_step.y () <= 0) { @@ -396,7 +404,7 @@ fill_region_impl (db::Cell *cell, const db::Region &fr, db::cell_index_type fill tl::RelativeProgress progress (progress_title, n); for (db::Region::const_iterator p = fr.begin_merged (); !p.at_end (); ++p) { - if (! fill_polygon_impl (cell, *p, fill_cell_index, kernel_origin, row_step, column_step, origin, enhanced_fill, remaining_parts ? &rem_pp : 0, fill_margin, glue_box)) { + if (! fill_polygon_impl (cell, *p, fill_cell_index, fc_bbox, row_step, column_step, origin, enhanced_fill, remaining_parts ? &rem_pp : 0, fill_margin, glue_box)) { if (remaining_polygons) { rem_poly.push_back (*p); } @@ -425,10 +433,10 @@ fill_region_impl (db::Cell *cell, const db::Region &fr, db::cell_index_type fill } DB_PUBLIC void -fill_region (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, +fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, 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, const db::Box &glue_box) { - fill_region_impl (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin, enhanced_fill, remaining_parts, fill_margin, remaining_polygons, 0, glue_box); + fill_region_impl (cell, fr, fill_cell_index, fc_bbox, row_step, column_step, origin, enhanced_fill, remaining_parts, fill_margin, remaining_polygons, 0, glue_box); } DB_PUBLIC void @@ -439,13 +447,13 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)"))); } - fill_region_impl (cell, fr, fill_cell_index, fc_bbox.p1 () - db::Point (), db::Vector (fc_bbox.width (), 0), db::Vector (0, fc_bbox.height ()), + fill_region_impl (cell, fr, fill_cell_index, fc_bbox, db::Vector (fc_bbox.width (), 0), db::Vector (0, fc_bbox.height ()), origin, enhanced_fill, remaining_parts, fill_margin, remaining_polygons, 0, glue_box); } DB_PUBLIC void fill_region_repeat (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::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box) { const db::Region *fill_region = &fr; @@ -460,7 +468,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, origin, true, &remaining, fill_margin, remaining_polygons, iteration, glue_box); + fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, origin, true, &remaining, fill_margin, remaining_polygons, iteration, glue_box); new_fill_region.swap (remaining); fill_region = &new_fill_region; diff --git a/src/db/db/dbFillTool.h b/src/db/db/dbFillTool.h index 2e1bef33d..a6b5c905c 100644 --- a/src/db/db/dbFillTool.h +++ b/src/db/db/dbFillTool.h @@ -50,33 +50,24 @@ class Region; * * Return value: true, if the polygon could be filled, false if no fill tile at all could be applied (remaining_parts will not be fed in that case) * - * Explanation for the fill kernel_origin, row step and column step vectors: + * Explanation for the fill fc_box, row step and column step vectors: * - * The "kernel" is a rectangular or diamond-shaped area which is repeated along it's primary - * axes. In case of a box, the kernel is a rectangle and the primary axes are the x and y axes. - * The step vectors describe the repetition: in case of the box, the row step vector is (w,0) and - * the column step vector is (h,0) (w and h are the box width and heigth respectively). Hence - * the kernel will be repeated seamlessly. + * The "fc_box" is a rectangular area which is repeated along the primary fill axes given by row_step + * and column_step vectors. The fill box is placed with the lower-left corner. * - * The kernel's boundary in case of the diamond kernel is: - * - * (o,o+c,o+c+r,o+r) - * - * (o = kernel_origin, r = row_step, c = column_step) - * - * Formally, the kernel will be placed a positions + * Formally, the fill box will be placed a positions * * p(i,j) = p0 + i * row_step + j * column_step * * p0 is a position chosen by the fill alogorithm or the "origin", if enhanced_fill is false. * - * This pattern is overlaid with the polygon to fill and all instances where the kernel moved by p(i,j) is entirely inside + * This pattern is overlaid with the polygon to fill and all instances where the fill box moved by p(i,j) is entirely inside * the polygon generate a fill cell instance with a displacement of p. * - * Afterwards, the residual parts are computed by subtracting all moved kernels from the polygon to fill. + * Afterwards, the residual parts are computed by subtracting all moved fill boxes from the polygon to fill. * This implies that ideally the fc_boxes should overlap while they are repeated with row_step and column_step. * - * As a practical consequence, if all fill cell geometries are within the kernel's boundary, they will also + * As a practical consequence, if all fill cell geometries are within the fill boxes boundary, they will also * be within the polygon to fill. * * If the glue box is non-empty, fill cells are guaranteed to use the global origin even in enhanced mode if @@ -92,7 +83,7 @@ fill_region (db::Cell *cell, const db::Polygon &fp, db::cell_index_type fill_cel std::vector *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), const db::Box &glue_box = db::Box ()); DB_PUBLIC bool -fill_region (db::Cell *cell, const db::Polygon &fp, 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, +fill_region (db::Cell *cell, const db::Polygon &fp, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill, std::vector *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), const db::Box &glue_box = db::Box ()); @@ -111,7 +102,7 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell db::Region *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), db::Region *remaining_polygons = 0, const db::Box &glue_box = db::Box ()); DB_PUBLIC void -fill_region (db::Cell *cell, const db::Region &fp, 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, +fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, bool enhanced_fill, db::Region *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), db::Region *remaining_polygons = 0, const db::Box &glue_box = db::Box ()); /** @@ -126,7 +117,7 @@ fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell */ DB_PUBLIC void fill_region_repeat (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::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Vector &fill_margin, db::Region *remaining_polygons = 0, const db::Point &origin = db::Point (), const db::Box &glue_box = db::Box ()); } diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index 5fc4c6dc9..6681da3f8 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1304,17 +1304,17 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell } static void -fill_region_skew (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, +fill_region_skew (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin, db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) { - db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); + db::fill_region (cell, fr, fill_cell_index, fc_box, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); } static void -fill_region_multi (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, +fill_region_multi (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box) { - db::fill_region_repeat (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); + db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); } static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t) @@ -1846,7 +1846,7 @@ Class decl_Cell ("db", "Cell", ) + gsi::method_ext ("fill_region", &fill_region_skew, gsi::arg ("region"), gsi::arg ("fill_cell_index"), - gsi::arg ("fc_origin"), + gsi::arg ("fc_bbox"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("origin", &default_origin, "(0, 0)"), @@ -1857,7 +1857,7 @@ Class decl_Cell ("db", "Cell", "@brief Fills the given region with cells of the given type (skew step version)\n" "@param region The region to fill\n" "@param fill_cell_index The fill cell to place\n" - "@param fc_origin The location of the reference point of the fill cell\n" + "@param fc_bbox The fill cell's box to place\n" "@param row_step The 'rows' step vector\n" "@param column_step The 'columns' step vector\n" "@param origin The global origin of the fill pattern or nil to allow local (per-polygon) optimization\n" @@ -1865,14 +1865,18 @@ Class decl_Cell ("db", "Cell", "@param fill_margin See explanation in other version\n" "@param remaining_polygons See explanation in other version\n" "\n" - "This version is similar to the version providing a rectangular fill kernel, but it offers more generic stepping of the fill cell.\n" + "This version is similar to the version providing an orthogonal fill, but it offers more generic stepping of the fill cell.\n" "The step pattern is defined by an origin and two vectors (row_step and column_step) which span the axes of the fill cell pattern.\n" "\n" + "The fill box and the step vectors are decoupled which means the fill box can be larger or smaller than the step pitch - it can " + "be overlapping and there can be space between the fill box instances. Fill boxes are placed where they fit entirely into a polygon of the region. " + "The fill boxes lower left corner is the reference for the fill pattern and aligns with the origin if given.\n" + "\n" "This variant has been introduced in version 0.27.\n" ) + gsi::method_ext ("fill_region_multi", &fill_region_multi, gsi::arg ("region"), gsi::arg ("fill_cell_index"), - gsi::arg ("fc_origin"), + gsi::arg ("fc_bbox"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("fill_margin", db::Vector ()), diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 4d01ac07f..898e01120 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -722,17 +722,17 @@ fill_region (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell } static void -fill_region_skew (const db::Region *fr, db::Cell *cell, 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, +fill_region_skew (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin, db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) { - db::fill_region (cell, *fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); + db::fill_region (cell, *fr, fill_cell_index, fc_box, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); } static void -fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, +fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box) { - db::fill_region_repeat (cell, *fr, fill_cell_index, kernel_origin, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); + db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); } static db::Point default_origin; diff --git a/src/db/unit_tests/dbFillToolTests.cc b/src/db/unit_tests/dbFillToolTests.cc index 87078732a..b7857ccd5 100644 --- a/src/db/unit_tests/dbFillToolTests.cc +++ b/src/db/unit_tests/dbFillToolTests.cc @@ -104,7 +104,8 @@ TEST(3) db::Vector ko (-100, -130); db::Vector rs (230, 40); db::Vector cs (40, 230); - db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, ko, rs, cs, db::Point (), true, &remaining_parts, db::Vector (50, 100), &remaining_polygons); + db::Box fc_box (db::Point () + ko, db::Point (rs.x (), cs.y ()) + ko); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), true, &remaining_parts, 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)); @@ -137,7 +138,8 @@ TEST(3a) db::Vector ko (-100, -130); db::Vector rs (230, 40); db::Vector cs (-40, 230); - db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, ko, rs, cs, db::Point (), true, &remaining_parts, db::Vector (50, 100), &remaining_polygons); + db::Box fc_box (db::Point () + ko, db::Point (rs.x (), cs.y ()) + ko); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), true, &remaining_parts, 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)); @@ -170,7 +172,8 @@ TEST(3b) db::Vector ko (-100, -130); db::Vector rs (230, -40); db::Vector cs (40, 230); - db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, ko, rs, cs, db::Point (), true, &remaining_parts, db::Vector (50, 100), &remaining_polygons); + db::Box fc_box (db::Point () + ko, db::Point (rs.x (), cs.y ()) + ko); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), true, &remaining_parts, 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)); @@ -203,7 +206,8 @@ TEST(3c) db::Vector ko (-100, -130); db::Vector rs (230, -40); db::Vector cs (-40, 230); - db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, ko, rs, cs, db::Point (), true, &remaining_parts, db::Vector (50, 100), &remaining_polygons); + db::Box fc_box (db::Point () + ko, db::Point (rs.x (), cs.y ()) + ko); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), true, &remaining_parts, 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)); @@ -236,12 +240,76 @@ TEST(4) 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); + db::Box fc_box (db::Point () + ko, db::Point (rs.x (), cs.y ()) + ko); + db::fill_region_repeat (&ly.cell (top_cell), fill_region, fill_cell, fc_box, 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"); } + +TEST(4b) +{ + 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::Box fc_box (db::Point () + ko, db::Point ()); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), true, &remaining_polygons); + + 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_au4b.gds"); +} + +TEST(4c) +{ + 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::Box fc_box (db::Point () + ko, db::Point (rs.x (), cs.y ()) + ko); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box.enlarged (db::Vector (100, 100)), rs, cs, db::Point (), true, &remaining_polygons); + + 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_au4c.gds"); +} diff --git a/src/lay/lay/layFillDialog.cc b/src/lay/lay/layFillDialog.cc index acf29211e..4d59325ca 100644 --- a/src/lay/lay/layFillDialog.cc +++ b/src/lay/lay/layFillDialog.cc @@ -187,11 +187,11 @@ FillDialog::generate_fill (const FillParameters &fp) 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; + db::Box fc_bbox = db::CplxTrans (ly.dbu ()).inverted () * fp.fc_bbox; db::Vector row_step2 = db::CplxTrans (ly.dbu ()).inverted () * fp.row_step2; db::Vector column_step2 = db::CplxTrans (ly.dbu ()).inverted () * fp.column_step2; - db::Vector kernel_origin2 = db::CplxTrans (ly.dbu ()).inverted () * fp.kernel_origin2; + db::Box fc_bbox2 = db::CplxTrans (ly.dbu ()).inverted () * fp.fc_bbox2; if (tl::verbosity () >= 20) { @@ -271,15 +271,15 @@ FillDialog::generate_fill (const FillParameters &fp) } if (! enhanced_fill) { - db::fill_region (cv.cell (), fill_region, fill_cell->cell_index (), kernel_origin, 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, fr_bbox.p1 (), 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 (), kernel_origin, row_step, column_step, fill_margin, fill_cell2 ? &fill_region : 0); + 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); } fill_cell = fill_cell2; row_step = row_step2; column_step = column_step2; - kernel_origin = kernel_origin2; + fc_bbox = fc_bbox2; fill_margin = fill_margin2; fill_cell2 = 0; @@ -497,13 +497,12 @@ FillDialog::get_fill_parameters () fp.column_step = db::DVector (0.0, fc_bbox.height ()); } - fp.kernel_origin = fc_bbox.p1 () - db::DPoint (); - - const db::Cell *fill_cell2 = 0; - db::DBox fc_bbox2; + fp.fc_bbox = fc_bbox; if (second_order_fill_cb->isChecked ()) { + db::DBox fc_bbox2; + fp.fill_cell_name2 = tl::to_string (fill_cell_2nd_le->text ()); std::pair fc = cv->layout ().cell_by_name (fp.fill_cell_name2.c_str ()); @@ -511,7 +510,7 @@ FillDialog::get_fill_parameters () throw tl::Exception (tl::to_string (QObject::tr ("Second order fill cell not found: ")) + tl::to_string (fill_cell_2nd_le->text ())); } - fill_cell2 = &cv->layout ().cell (fc.second); + const db::Cell *fill_cell2 = &cv->layout ().cell (fc.second); fc_bbox2 = db::CplxTrans (cv->layout ().dbu ()) * (fc_bbox_layer < 0 ? fill_cell2->bbox () : fill_cell2->bbox (fc_bbox_layer)); if (fc_bbox2.empty ()) { @@ -534,6 +533,8 @@ FillDialog::get_fill_parameters () fp.column_step2 = db::DVector (0.0, fc_bbox2.height ()); } + fp.fc_bbox2 = fc_bbox2; + } return fp; diff --git a/src/lay/lay/layFillDialog.h b/src/lay/lay/layFillDialog.h index e8a894d0c..620aeb9e9 100644 --- a/src/lay/lay/layFillDialog.h +++ b/src/lay/lay/layFillDialog.h @@ -60,10 +60,12 @@ struct LAY_PUBLIC FillParameters bool enhanced_fill; std::string fill_cell_name; db::DVector fill_cell_margin; - db::DVector kernel_origin, row_step, column_step; + db::DVector row_step, column_step; + db::DBox fc_bbox; std::string fill_cell_name2; db::DVector fill_cell_margin2; - db::DVector kernel_origin2, row_step2, column_step2; + db::DVector row_step2, column_step2; + db::DBox fc_bbox2; }; class LAY_PUBLIC FillDialog diff --git a/testdata/algo/fill_tool_au4b.gds b/testdata/algo/fill_tool_au4b.gds new file mode 100644 index 000000000..9bb6c2c82 Binary files /dev/null and b/testdata/algo/fill_tool_au4b.gds differ diff --git a/testdata/algo/fill_tool_au4c.gds b/testdata/algo/fill_tool_au4c.gds new file mode 100644 index 000000000..5fab766ce Binary files /dev/null and b/testdata/algo/fill_tool_au4c.gds differ diff --git a/testdata/drc/drcSimpleTests_au42.gds b/testdata/drc/drcSimpleTests_au42.gds new file mode 100644 index 000000000..01f2a2f5a Binary files /dev/null and b/testdata/drc/drcSimpleTests_au42.gds differ diff --git a/testdata/drc/drcSimpleTests_au43.gds b/testdata/drc/drcSimpleTests_au43.gds new file mode 100644 index 000000000..9684dc210 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au43.gds differ