Fill cell box introduced as a concept, added tests, overlapping fill cells supported.

This commit is contained in:
Matthias Koefferlein 2021-03-29 22:12:47 +02:00
parent 74d3251ff7
commit 3f37b0e5a4
11 changed files with 140 additions and 66 deletions

View File

@ -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 <db::Polygon> *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 <db::Polygon> 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 <db::Polygon> fpa;
std::vector <db::Polygon> 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 <db::Polygon> *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;

View File

@ -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 <db::Polygon> *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 <db::Polygon> *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 ());
}

View File

@ -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<db::Cell> 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<db::Cell> 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<db::Cell> 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 ()),

View File

@ -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;

View File

@ -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");
}

View File

@ -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<bool, db::cell_index_type> 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;

View File

@ -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

BIN
testdata/algo/fill_tool_au4b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/fill_tool_au4c.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au42.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au43.gds vendored Normal file

Binary file not shown.