mirror of https://github.com/KLayout/klayout.git
WIP: exclude area for fill functions
This commit is contained in:
parent
6ada4cb6f9
commit
ff6ab4267b
|
|
@ -42,10 +42,18 @@ public:
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericRasterizer (const db::Polygon &fp, const db::Vector &row_step, const db::Vector &column_step, const db::Point &origin, const db::Vector &dim)
|
GenericRasterizer (const std::vector<db::Polygon> &fr, const db::Box &rasterized_area, 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)
|
: 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);
|
rasterize (rasterized_area, fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericRasterizer (const db::Polygon &fp, const db::Box &rasterized_area, 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)
|
||||||
|
{
|
||||||
|
std::vector<db::Polygon> fr;
|
||||||
|
fr.push_back (fp);
|
||||||
|
rasterize (rasterized_area, fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void move (const db::Vector &d)
|
void move (const db::Vector &d)
|
||||||
|
|
@ -59,101 +67,6 @@ public:
|
||||||
m_area_maps.clear ();
|
m_area_maps.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rasterize (const db::Polygon &fp)
|
|
||||||
{
|
|
||||||
db::Coord dx = m_row_step.x ();
|
|
||||||
db::Coord dy = m_column_step.y ();
|
|
||||||
|
|
||||||
if (m_row_step.y () == 0) {
|
|
||||||
m_row_steps = 1;
|
|
||||||
} else {
|
|
||||||
m_row_steps = tl::lcm (dy, std::abs (m_row_step.y ())) / std::abs (m_row_step.y ());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_column_step.x () == 0) {
|
|
||||||
m_column_steps = 1;
|
|
||||||
} else {
|
|
||||||
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 gets 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
|
|
||||||
db::Coord ex = std::max (std::abs (db::Coord (m_column_step.x () * m_column_steps)), std::abs (db::Coord (m_row_step.x () * m_row_steps)));
|
|
||||||
db::Coord ey = std::max (std::abs (db::Coord (m_column_step.y () * m_column_steps)), std::abs (db::Coord (m_row_step.y () * m_row_steps)));
|
|
||||||
fp_bbox.enlarge (db::Vector (ex, ey));
|
|
||||||
|
|
||||||
int columns_per_rows = (int (m_row_steps) * m_row_step.y ()) / dy;
|
|
||||||
int rows_per_columns = (int (m_column_steps) * m_column_step.x ()) / dx;
|
|
||||||
|
|
||||||
db::Coord ddx = dx * db::Coord (m_row_steps) - m_column_step.x () * columns_per_rows;
|
|
||||||
db::Coord ddy = dy * db::Coord (m_column_steps) - m_row_step.y () * rows_per_columns;
|
|
||||||
|
|
||||||
// round polygon bbox
|
|
||||||
db::Coord fp_left = db::Coord (tl::round_down (fp_bbox.left () - m_origin.x (), ddx)) + m_origin.x ();
|
|
||||||
db::Coord fp_bottom = db::Coord (tl::round_down (fp_bbox.bottom () - m_origin.y (), ddy)) + m_origin.y ();
|
|
||||||
db::Coord fp_right = db::Coord (tl::round_up (fp_bbox.right () - m_origin.x (), ddx)) + m_origin.x ();
|
|
||||||
db::Coord fp_top = db::Coord (tl::round_up (fp_bbox.top () - m_origin.y (), ddy)) + m_origin.y ();
|
|
||||||
fp_bbox = db::Box (fp_left, fp_bottom, fp_right, fp_top);
|
|
||||||
|
|
||||||
size_t nx = fp_bbox.width () / ddx;
|
|
||||||
size_t ny = fp_bbox.height () / ddy;
|
|
||||||
|
|
||||||
tl_assert (fp.box ().inside (fp_bbox));
|
|
||||||
|
|
||||||
if (nx == 0 || ny == 0) {
|
|
||||||
// nothing to rasterize:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_area_maps.reserve (m_row_steps * m_column_steps + std::abs (columns_per_rows) * std::abs (rows_per_columns));
|
|
||||||
|
|
||||||
db::AreaMap am;
|
|
||||||
|
|
||||||
for (unsigned int ic = 0; ic < m_column_steps; ++ic) {
|
|
||||||
|
|
||||||
for (unsigned int ir = 0; ir < m_row_steps; ++ir) {
|
|
||||||
|
|
||||||
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), m_dim, nx, ny);
|
|
||||||
|
|
||||||
if (db::rasterize (fp, am)) {
|
|
||||||
m_area_maps.push_back (db::AreaMap ());
|
|
||||||
m_area_maps.back ().swap (am);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// adds the "dead corner" piece
|
|
||||||
|
|
||||||
for (unsigned int ic = 0; ic < (unsigned int) std::abs (columns_per_rows); ++ic) {
|
|
||||||
|
|
||||||
for (unsigned int ir = 0; ir < (unsigned int) std::abs (rows_per_columns); ++ir) {
|
|
||||||
|
|
||||||
db::Vector dr = m_row_step * long ((rows_per_columns > 0 ? -int (ir + 1) : ir) + m_row_steps);
|
|
||||||
db::Vector dc = m_column_step * long ((columns_per_rows > 0 ? -int (ic + 1) : ic) + m_column_steps);
|
|
||||||
|
|
||||||
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 ());
|
|
||||||
m_area_maps.back ().swap (am);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const db::Point &p0 () const { return m_origin; }
|
const db::Point &p0 () const { return m_origin; }
|
||||||
|
|
||||||
unsigned int row_steps () const { return m_row_steps; }
|
unsigned int row_steps () const { return m_row_steps; }
|
||||||
|
|
@ -180,80 +93,128 @@ private:
|
||||||
unsigned int m_row_steps, m_column_steps;
|
unsigned int m_row_steps, m_column_steps;
|
||||||
db::Point m_origin;
|
db::Point m_origin;
|
||||||
db::Vector m_dim;
|
db::Vector m_dim;
|
||||||
|
|
||||||
|
void rasterize (const db::Box &rasterized_area, const std::vector<db::Polygon> &fr)
|
||||||
|
{
|
||||||
|
db::Coord dx = m_row_step.x ();
|
||||||
|
db::Coord dy = m_column_step.y ();
|
||||||
|
|
||||||
|
if (m_row_step.y () == 0) {
|
||||||
|
m_row_steps = 1;
|
||||||
|
} else {
|
||||||
|
m_row_steps = tl::lcm (dy, std::abs (m_row_step.y ())) / std::abs (m_row_step.y ());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_column_step.x () == 0) {
|
||||||
|
m_column_steps = 1;
|
||||||
|
} else {
|
||||||
|
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 gets 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 ra_org = rasterized_area;
|
||||||
|
|
||||||
|
// compensate for distortion by sheared kernel
|
||||||
|
db::Coord ex = std::max (std::abs (db::Coord (m_column_step.x () * m_column_steps)), std::abs (db::Coord (m_row_step.x () * m_row_steps)));
|
||||||
|
db::Coord ey = std::max (std::abs (db::Coord (m_column_step.y () * m_column_steps)), std::abs (db::Coord (m_row_step.y () * m_row_steps)));
|
||||||
|
ra_org.enlarge (db::Vector (ex, ey));
|
||||||
|
|
||||||
|
int columns_per_rows = (int (m_row_steps) * m_row_step.y ()) / dy;
|
||||||
|
int rows_per_columns = (int (m_column_steps) * m_column_step.x ()) / dx;
|
||||||
|
|
||||||
|
db::Coord ddx = dx * db::Coord (m_row_steps) - m_column_step.x () * columns_per_rows;
|
||||||
|
db::Coord ddy = dy * db::Coord (m_column_steps) - m_row_step.y () * rows_per_columns;
|
||||||
|
|
||||||
|
// round polygon bbox
|
||||||
|
db::Coord ra_left = db::Coord (tl::round_down (ra_org.left () - m_origin.x (), ddx)) + m_origin.x ();
|
||||||
|
db::Coord ra_bottom = db::Coord (tl::round_down (ra_org.bottom () - m_origin.y (), ddy)) + m_origin.y ();
|
||||||
|
db::Coord ra_right = db::Coord (tl::round_up (ra_org.right () - m_origin.x (), ddx)) + m_origin.x ();
|
||||||
|
db::Coord ra_top = db::Coord (tl::round_up (ra_org.top () - m_origin.y (), ddy)) + m_origin.y ();
|
||||||
|
db::Box ra = db::Box (ra_left, ra_bottom, ra_right, ra_top);
|
||||||
|
|
||||||
|
size_t nx = ra.width () / ddx;
|
||||||
|
size_t ny = ra.height () / ddy;
|
||||||
|
|
||||||
|
tl_assert (ra_org.inside (ra));
|
||||||
|
|
||||||
|
if (nx == 0 || ny == 0) {
|
||||||
|
// nothing to rasterize:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_area_maps.reserve (m_row_steps * m_column_steps + std::abs (columns_per_rows) * std::abs (rows_per_columns));
|
||||||
|
|
||||||
|
db::AreaMap am;
|
||||||
|
|
||||||
|
for (unsigned int ic = 0; ic < m_column_steps; ++ic) {
|
||||||
|
|
||||||
|
for (unsigned int ir = 0; ir < m_row_steps; ++ir) {
|
||||||
|
|
||||||
|
db::Vector dr = m_row_step * long (ir);
|
||||||
|
db::Vector dc = m_column_step * long (ic);
|
||||||
|
|
||||||
|
am.reinitialize (db::Point (ra_left, ra_bottom) + dr + dc, db::Vector (ddx, ddy), m_dim, nx, ny);
|
||||||
|
|
||||||
|
bool any = false;
|
||||||
|
for (auto i = fr.begin (); i != fr.end (); ++i) {
|
||||||
|
if (db::rasterize (*i, am)) {
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (any) {
|
||||||
|
m_area_maps.push_back (db::AreaMap ());
|
||||||
|
m_area_maps.back ().swap (am);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds the "dead corner" piece
|
||||||
|
|
||||||
|
for (unsigned int ic = 0; ic < (unsigned int) std::abs (columns_per_rows); ++ic) {
|
||||||
|
|
||||||
|
for (unsigned int ir = 0; ir < (unsigned int) std::abs (rows_per_columns); ++ir) {
|
||||||
|
|
||||||
|
db::Vector dr = m_row_step * long ((rows_per_columns > 0 ? -int (ir + 1) : ir) + m_row_steps);
|
||||||
|
db::Vector dc = m_column_step * long ((columns_per_rows > 0 ? -int (ic + 1) : ic) + m_column_steps);
|
||||||
|
|
||||||
|
am.reinitialize (db::Point (ra_left, ra_bottom) + dr + dc, db::Vector (ddx, ddy), m_dim, nx, ny);
|
||||||
|
|
||||||
|
bool any = false;
|
||||||
|
for (auto i = fr.begin (); i != fr.end (); ++i) {
|
||||||
|
if (db::rasterize (*i, am)) {
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (any) {
|
||||||
|
m_area_maps.push_back (db::AreaMap ());
|
||||||
|
m_area_maps.back ().swap (am);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static size_t
|
||||||
static bool
|
create_instances (GenericRasterizer &am, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &fill_margin, const GenericRasterizer *exclude_rasterized, std::vector<db::Polygon> *filled_regions)
|
||||||
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) {
|
|
||||||
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")));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db::vprod_sign (row_step, column_step) <= 0) {
|
|
||||||
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row_step x column_step vector vector product must be > 0")));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = fc_bbox.width () / 2 - 1, dy = fc_bbox.height () / 2 - 1;
|
|
||||||
|
|
||||||
std::vector <db::Polygon> fpa;
|
|
||||||
std::vector <db::Polygon> fpb;
|
|
||||||
fpa.push_back (fp0);
|
|
||||||
|
|
||||||
ep.size (fpa, -dx, 0, fpb, 3 /*mode*/, false /*=don't resolve holes*/);
|
|
||||||
fpa.swap (fpb);
|
|
||||||
fpb.clear ();
|
|
||||||
|
|
||||||
ep.size (fpa, dx, 0, fpb, 3 /*mode*/, false /*=don't resolve holes*/);
|
|
||||||
fpa.swap (fpb);
|
|
||||||
fpb.clear ();
|
|
||||||
|
|
||||||
ep.size (fpa, 0, -dy, fpb, 3 /*mode*/, false /*=don't resolve holes*/);
|
|
||||||
fpa.swap (fpb);
|
|
||||||
fpb.clear ();
|
|
||||||
|
|
||||||
ep.size (fpa, 0, dy, fpb, 3 /*mode*/, false /*=don't resolve holes*/);
|
|
||||||
fpa.swap (fpb);
|
|
||||||
fpb.clear ();
|
|
||||||
|
|
||||||
ep.simple_merge (fpa, fpb, false /*=don't resolve holes*/);
|
|
||||||
|
|
||||||
filled_regions.clear ();
|
|
||||||
bool any_fill = false;
|
|
||||||
|
|
||||||
for (std::vector <db::Polygon>::const_iterator fp = fpb.begin (); fp != fpb.end (); ++fp) {
|
|
||||||
|
|
||||||
if (fp->hull ().size () == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box
|
|
||||||
bool ef = enhanced_fill;
|
|
||||||
if (ef && ! glue_box.empty () && ! fp->box ().enlarged (db::Vector (1, 1)).inside (glue_box)) {
|
|
||||||
ef = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pick a heuristic "good" starting point in enhanced mode
|
|
||||||
// TODO: this is a pretty weak optimization.
|
|
||||||
db::Point o = origin;
|
|
||||||
if (ef) {
|
|
||||||
o = fp->hull () [0];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ninsts = 0;
|
size_t ninsts = 0;
|
||||||
|
|
||||||
GenericRasterizer am (*fp, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ());
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < am.area_maps (); ++i) {
|
for (unsigned int i = 0; i < am.area_maps (); ++i) {
|
||||||
|
|
||||||
db::AreaMap &am1 = am.area_map (i);
|
db::AreaMap &am1 = am.area_map (i);
|
||||||
|
const db::AreaMap *am1_excl = 0;
|
||||||
|
if (exclude_rasterized) {
|
||||||
|
tl_assert (i < exclude_rasterized->area_maps ());
|
||||||
|
am1_excl = &exclude_rasterized->area_map (i);
|
||||||
|
}
|
||||||
|
|
||||||
size_t nx = am1.nx ();
|
size_t nx = am1.nx ();
|
||||||
size_t ny = am1.ny ();
|
size_t ny = am1.ny ();
|
||||||
|
|
@ -264,9 +225,9 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
||||||
for (size_t j = 0; j < ny; ) {
|
for (size_t j = 0; j < ny; ) {
|
||||||
|
|
||||||
size_t jj = j + 1;
|
size_t jj = j + 1;
|
||||||
if (am1.get (i, j) == am1.pixel_area ()) {
|
if (am1.get (i, j) == am1.pixel_area () && (!am1_excl || am1_excl->get (i, j) == 0)) {
|
||||||
|
|
||||||
while (jj != ny && am1.get (i, jj) == am1.pixel_area ()) {
|
while (jj != ny && am1.get (i, jj) == am1.pixel_area () && (!am1_excl || am1_excl->get (i, jj) == 0)) {
|
||||||
++jj;
|
++jj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,7 +241,7 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
||||||
for ( ; ii < nx; ++ii) {
|
for ( ; ii < nx; ++ii) {
|
||||||
bool all = true;
|
bool all = true;
|
||||||
for (size_t k = j; k < jj && all; ++k) {
|
for (size_t k = j; k < jj && all; ++k) {
|
||||||
all = am1.get (ii, k) == am1.pixel_area ();
|
all = (am1.get (ii, k) == am1.pixel_area () && (!am1_excl || am1_excl->get (ii, k) == 0));
|
||||||
}
|
}
|
||||||
if (all) {
|
if (all) {
|
||||||
for (size_t k = j; k < jj; ++k) {
|
for (size_t k = j; k < jj; ++k) {
|
||||||
|
|
@ -307,23 +268,21 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
||||||
cell->insert (array);
|
cell->insert (array);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remaining_parts) {
|
if (filled_regions) {
|
||||||
if (am1.d ().y () == am1.p ().y () && am1.d ().x () == am1.p ().x ()) {
|
if (am1.d ().y () == am1.p ().y () && am1.d ().x () == am1.p ().x ()) {
|
||||||
db::Box fill_box (db::Point (), db::Point (am1.p ().x () * db::Coord (ii - i), am1.p ().y () * db::Coord (jj - j)));
|
db::Box fill_box (db::Point (), db::Point (am1.p ().x () * db::Coord (ii - i), am1.p ().y () * db::Coord (jj - j)));
|
||||||
filled_regions.push_back (db::Polygon (fill_box.enlarged (fill_margin).moved (kernel_origin + p0)));
|
filled_regions->push_back (db::Polygon (fill_box.enlarged (fill_margin).moved (kernel_origin + p0)));
|
||||||
} else {
|
} else {
|
||||||
db::Box fill_box (db::Point (), db::Point () + am1.p ());
|
db::Box fill_box (db::Point (), db::Point () + am1.p ());
|
||||||
fill_box.enlarge (fill_margin);
|
fill_box.enlarge (fill_margin);
|
||||||
for (size_t k = 0; k < jj - j; ++k) {
|
for (size_t k = 0; k < jj - j; ++k) {
|
||||||
for (size_t l = 0; l < ii - i; ++l) {
|
for (size_t l = 0; l < ii - i; ++l) {
|
||||||
filled_regions.push_back (db::Polygon (fill_box.moved (kernel_origin + p0 + db::Vector (am1.d ().x () * db::Coord (l), am1.d ().y () * db::Coord (k)))));
|
filled_regions->push_back (db::Polygon (fill_box.moved (kernel_origin + p0 + db::Vector (am1.d ().x () * db::Coord (l), am1.d ().y () * db::Coord (k)))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
any_fill = true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
j = jj;
|
j = jj;
|
||||||
|
|
@ -334,6 +293,137 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ninsts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
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, const db::Region &exclude_area)
|
||||||
|
{
|
||||||
|
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")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (db::vprod_sign (row_step, column_step) <= 0) {
|
||||||
|
throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row_step x column_step vector vector product must be > 0")));
|
||||||
|
}
|
||||||
|
|
||||||
|
db::Vector kernel_origin (fc_bbox.left (), fc_bbox.bottom ());
|
||||||
|
|
||||||
|
db::Coord dx = fc_bbox.width () / 2 - 1, dy = fc_bbox.height () / 2 - 1;
|
||||||
|
|
||||||
|
db::Region fr (fp0);
|
||||||
|
db::Box rasterized_area = fp0.box ();
|
||||||
|
|
||||||
|
std::unique_ptr<GenericRasterizer> exclude_rasterized;
|
||||||
|
|
||||||
|
if (! exclude_area.empty ()) {
|
||||||
|
|
||||||
|
auto iter = exclude_area.iter ();
|
||||||
|
iter.confine_region (fp0.box ());
|
||||||
|
|
||||||
|
// over- and undersize the polygons to fill gaps that cannot be filled.
|
||||||
|
db::Region excluded (iter);
|
||||||
|
excluded.size (dx, 0);
|
||||||
|
excluded.size (-dx, 0);
|
||||||
|
excluded.size (dy, 0);
|
||||||
|
excluded.size (-dy, 0);
|
||||||
|
excluded.merge ();
|
||||||
|
|
||||||
|
if (enhanced_fill || remaining_parts != 0) {
|
||||||
|
|
||||||
|
tl::warn << "@@@ using booleans for exclude";
|
||||||
|
|
||||||
|
// In enhanced fill or if the remaining parts are requested, it is better to implement the
|
||||||
|
// exclude area by a boolean NOT
|
||||||
|
fr -= excluded;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
tl::warn << "@@@ using exclude area rasterizer";
|
||||||
|
|
||||||
|
// Otherwise use a second rasterizer for the exclude polygons that must have a zero pixel coverage for the
|
||||||
|
// pixel to be filled.
|
||||||
|
|
||||||
|
std::vector<db::Polygon> excluded_poly;
|
||||||
|
excluded_poly.reserve (excluded.count ());
|
||||||
|
for (auto i = excluded.begin (); ! i.at_end (); ++i) {
|
||||||
|
excluded_poly.push_back (*i);
|
||||||
|
}
|
||||||
|
excluded.clear ();
|
||||||
|
|
||||||
|
exclude_rasterized.reset (new GenericRasterizer (excluded_poly, rasterized_area, row_step, column_step, origin, fc_bbox.p2 () - fc_bbox.p1 ()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector <db::Polygon> filled_poly;
|
||||||
|
|
||||||
|
// under- and oversize the polygon to remove slivers that cannot be filled.
|
||||||
|
fr.size (-dx, 0);
|
||||||
|
fr.size (dx, 0);
|
||||||
|
fr.size (0, -dy);
|
||||||
|
fr.size (0, dy);
|
||||||
|
fr.merge ();
|
||||||
|
|
||||||
|
filled_poly.reserve (fr.count ());
|
||||||
|
for (auto i = fr.begin (); ! i.at_end (); ++i) {
|
||||||
|
filled_poly.push_back (*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
fr.clear ();
|
||||||
|
|
||||||
|
if (filled_poly.empty ()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector <db::Polygon> filled_regions;
|
||||||
|
bool any_fill = false;
|
||||||
|
|
||||||
|
if (exclude_rasterized.get ()) {
|
||||||
|
|
||||||
|
tl_assert (remaining_parts == 0);
|
||||||
|
GenericRasterizer am (filled_poly, rasterized_area, row_step, column_step, origin, fc_bbox.p2 () - fc_bbox.p1 ());
|
||||||
|
|
||||||
|
size_t ninsts = create_instances (am, cell, fill_cell_index, kernel_origin, fill_margin, exclude_rasterized.get (), 0);
|
||||||
|
if (ninsts > 0) {
|
||||||
|
any_fill = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tl::verbosity () >= 30 && ninsts > 0) {
|
||||||
|
tl::info << "Part " << fp0.to_string ();
|
||||||
|
tl::info << "Created " << ninsts << " instances";
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (auto fp = filled_poly.begin (); fp != filled_poly.end (); ++fp) {
|
||||||
|
|
||||||
|
if (fp->is_empty ()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box
|
||||||
|
bool ef = enhanced_fill;
|
||||||
|
if (ef && ! glue_box.empty () && ! fp->box ().enlarged (db::Vector (1, 1)).inside (glue_box)) {
|
||||||
|
ef = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick a heuristic "good" starting point in enhanced mode
|
||||||
|
// TODO: this is a pretty weak optimization.
|
||||||
|
db::Point o = origin;
|
||||||
|
if (ef) {
|
||||||
|
o = fp->hull () [0];
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericRasterizer am (*fp, rasterized_area, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ());
|
||||||
|
|
||||||
|
size_t ninsts = create_instances (am, cell, fill_cell_index, kernel_origin, fill_margin, 0, remaining_parts ? &filled_regions : 0);
|
||||||
|
if (ninsts > 0) {
|
||||||
|
any_fill = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (tl::verbosity () >= 30 && ninsts > 0) {
|
if (tl::verbosity () >= 30 && ninsts > 0) {
|
||||||
tl::info << "Part " << fp->to_string ();
|
tl::info << "Part " << fp->to_string ();
|
||||||
tl::info << "Created " << ninsts << " instances";
|
tl::info << "Created " << ninsts << " instances";
|
||||||
|
|
@ -341,9 +431,12 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (any_fill) {
|
if (any_fill) {
|
||||||
|
|
||||||
if (remaining_parts) {
|
if (remaining_parts) {
|
||||||
|
db::EdgeProcessor ep;
|
||||||
std::vector <db::Polygon> fp1;
|
std::vector <db::Polygon> fp1;
|
||||||
fp1.push_back (fp0);
|
fp1.push_back (fp0);
|
||||||
ep.boolean (fp1, filled_regions, *remaining_parts, db::BooleanOp::ANotB, false /*=don't resolve holes*/);
|
ep.boolean (fp1, filled_regions, *remaining_parts, db::BooleanOp::ANotB, false /*=don't resolve holes*/);
|
||||||
|
|
@ -358,25 +451,25 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
|
||||||
|
|
||||||
DB_PUBLIC bool
|
DB_PUBLIC bool
|
||||||
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,
|
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)
|
std::vector <db::Polygon> *remaining_parts, const db::Vector &fill_margin, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
return fill_polygon_impl (cell, fp0, fill_cell_index, fc_box, 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, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
DB_PUBLIC bool
|
DB_PUBLIC bool
|
||||||
fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, const db::Point &origin, bool enhanced_fill,
|
fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, const db::Point &origin, bool enhanced_fill,
|
||||||
std::vector <db::Polygon> *remaining_parts, const db::Vector &fill_margin, const db::Box &glue_box)
|
std::vector <db::Polygon> *remaining_parts, const db::Vector &fill_margin, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
if (fc_bbox.empty () || fc_bbox.width () == 0 || fc_bbox.height () == 0) {
|
if (fc_bbox.empty () || fc_bbox.width () == 0 || fc_bbox.height () == 0) {
|
||||||
throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)")));
|
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, 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, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
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,
|
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)
|
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, int iteration, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
if (row_step.x () <= 0 || column_step.y () <= 0) {
|
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")));
|
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")));
|
||||||
|
|
@ -403,7 +496,7 @@ fill_region_impl (db::Cell *cell, const db::Region &fr, db::cell_index_type fill
|
||||||
tl::RelativeProgress progress (progress_title, n);
|
tl::RelativeProgress progress (progress_title, n);
|
||||||
|
|
||||||
for (db::Region::const_iterator p = fr.begin_merged (); !p.at_end (); ++p) {
|
for (db::Region::const_iterator p = fr.begin_merged (); !p.at_end (); ++p) {
|
||||||
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 (! 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, exclude_area)) {
|
||||||
if (remaining_polygons) {
|
if (remaining_polygons) {
|
||||||
rem_poly.push_back (*p);
|
rem_poly.push_back (*p);
|
||||||
}
|
}
|
||||||
|
|
@ -433,27 +526,27 @@ fill_region_impl (db::Cell *cell, const db::Region &fr, db::cell_index_type fill
|
||||||
|
|
||||||
DB_PUBLIC void
|
DB_PUBLIC void
|
||||||
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,
|
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)
|
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
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);
|
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, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
DB_PUBLIC void
|
DB_PUBLIC void
|
||||||
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_bbox, 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::Point &origin, bool enhanced_fill,
|
||||||
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
|
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
if (fc_bbox.empty () || fc_bbox.width () == 0 || fc_bbox.height () == 0) {
|
if (fc_bbox.empty () || fc_bbox.width () == 0 || fc_bbox.height () == 0) {
|
||||||
throw tl::Exception (tl::to_string (tr ("Invalid fill cell footprint (empty or zero width/height)")));
|
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, 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);
|
origin, enhanced_fill, remaining_parts, fill_margin, remaining_polygons, 0, glue_box, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
DB_PUBLIC void
|
DB_PUBLIC void
|
||||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
fill_region_repeat (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::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step,
|
||||||
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
|
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
const db::Region *fill_region = &fr;
|
const db::Region *fill_region = &fr;
|
||||||
|
|
||||||
|
|
@ -467,7 +560,7 @@ fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fi
|
||||||
++iteration;
|
++iteration;
|
||||||
|
|
||||||
remaining.clear ();
|
remaining.clear ();
|
||||||
fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, db::Point (), true, &remaining, fill_margin, remaining_polygons, iteration, glue_box);
|
fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, db::Point (), true, &remaining, fill_margin, remaining_polygons, iteration, glue_box, exclude_area);
|
||||||
|
|
||||||
new_fill_region.swap (remaining);
|
new_fill_region.swap (remaining);
|
||||||
fill_region = &new_fill_region;
|
fill_region = &new_fill_region;
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,12 @@
|
||||||
|
|
||||||
#include "dbTypes.h"
|
#include "dbTypes.h"
|
||||||
#include "dbPolygon.h"
|
#include "dbPolygon.h"
|
||||||
|
#include "dbRegion.h"
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
||||||
class Cell;
|
class Cell;
|
||||||
class Region;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a tiling pattern for a single polygon using a fill cell which is repeated periodically
|
* @brief Creates a tiling pattern for a single polygon using a fill cell which is repeated periodically
|
||||||
|
|
@ -41,6 +41,7 @@ class Region;
|
||||||
* @param column_step (some_versions) The column advance vector of the fill cell. By default this is (0, fc_bbox.height())
|
* @param column_step (some_versions) The column advance vector of the fill cell. By default this is (0, fc_bbox.height())
|
||||||
* @param origin Specifies the origin of the fill raster if enhanced_fill is false
|
* @param origin Specifies the origin of the fill raster if enhanced_fill is false
|
||||||
* @param enhanced_fill If set, the tiling offset will be optimized such that as much tiling cells fit into each polygon
|
* @param enhanced_fill If set, the tiling offset will be optimized such that as much tiling cells fit into each polygon
|
||||||
|
* @param exclude_area The region which fill cells must not overlap
|
||||||
*
|
*
|
||||||
* Optional parameters:
|
* Optional parameters:
|
||||||
*
|
*
|
||||||
|
|
@ -79,12 +80,16 @@ class Region;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DB_PUBLIC bool
|
DB_PUBLIC bool
|
||||||
fill_region (db::Cell *cell, const db::Polygon &fp, db::cell_index_type fill_cell_index, const db::Box &fc_box, 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,
|
||||||
std::vector <db::Polygon> *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), const db::Box &glue_box = db::Box ());
|
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 ());
|
||||||
|
|
||||||
DB_PUBLIC bool
|
DB_PUBLIC bool
|
||||||
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,
|
fill_region (db::Cell *cell, const db::Polygon &fp, db::cell_index_type fill_cell_index, const db::Box &fc_box,
|
||||||
std::vector <db::Polygon> *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), const db::Box &glue_box = db::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 (), const db::Region &exclude_area = db::Region ());
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -98,12 +103,16 @@ fill_region (db::Cell *cell, const db::Polygon &fp, db::cell_index_type fill_cel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DB_PUBLIC void
|
DB_PUBLIC void
|
||||||
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, 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_box,
|
||||||
db::Region *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), db::Region *remaining_polygons = 0, const db::Box &glue_box = db::Box ());
|
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 (), const db::Region &exclude_area = db::Region ());
|
||||||
|
|
||||||
DB_PUBLIC void
|
DB_PUBLIC void
|
||||||
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,
|
fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell_index, const db::Box &fc_box,
|
||||||
db::Region *remaining_parts = 0, const db::Vector &fill_margin = db::Vector (), db::Region *remaining_polygons = 0, const db::Box &glue_box = db::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 (), const db::Region &exclude_area = db::Region ());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An iterative version for enhanced fill
|
* @brief An iterative version for enhanced fill
|
||||||
|
|
@ -118,6 +127,7 @@ fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell
|
||||||
DB_PUBLIC void
|
DB_PUBLIC void
|
||||||
fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index,
|
fill_region_repeat (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::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::Box &glue_box = db::Box ());
|
const db::Vector &fill_margin, db::Region *remaining_polygons = 0,
|
||||||
|
const db::Box &glue_box = db::Box (), const db::Region &exclude_area = db::Region ());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1510,23 +1510,23 @@ static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db::
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
|
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
|
||||||
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
|
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box);
|
db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
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,
|
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::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
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);
|
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, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
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,
|
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::Box &glue_box)
|
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box);
|
db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t)
|
static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t)
|
||||||
|
|
@ -2215,6 +2215,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
|
gsi::arg ("exclude_area", db::Region (), "empty"),
|
||||||
"@brief Fills the given region with cells of the given type (extended version)\n"
|
"@brief Fills the given region with cells of the given type (extended version)\n"
|
||||||
"@param region The region to fill\n"
|
"@param region The region to fill\n"
|
||||||
"@param fill_cell_index The fill cell to place\n"
|
"@param fill_cell_index The fill cell to place\n"
|
||||||
|
|
@ -2224,6 +2225,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
"@param fill_margin See explanation below\n"
|
"@param fill_margin See explanation below\n"
|
||||||
"@param remaining_polygons See explanation below\n"
|
"@param remaining_polygons See explanation below\n"
|
||||||
"@param glue_box Guarantees fill cell compatibility to neighbor regions in enhanced mode\n"
|
"@param glue_box Guarantees fill cell compatibility to neighbor regions in enhanced mode\n"
|
||||||
|
"@param exclude_area A region that defines the areas which are not be filled\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method creates a regular pattern of fill cells to cover the interior of the given region as far as possible. "
|
"This method creates a regular pattern of fill cells to cover the interior of the given region as far as possible. "
|
||||||
"This process is also known as tiling. This implementation supports rectangular (not necessarily square) tile cells. "
|
"This process is also known as tiling. This implementation supports rectangular (not necessarily square) tile cells. "
|
||||||
|
|
@ -2236,6 +2238,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
"\n"
|
"\n"
|
||||||
"The implementation will basically try to find a repetition pattern of the tile cell's footprint "
|
"The implementation will basically try to find a repetition pattern of the tile cell's footprint "
|
||||||
"and produce instances which fit entirely into the fill region.\n"
|
"and produce instances which fit entirely into the fill region.\n"
|
||||||
|
"If an exclude area is given, the fill cells also must not overlap that region.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"There is also a version available which offers skew step vectors as a generalization of the orthogonal ones.\n"
|
"There is also a version available which offers skew step vectors as a generalization of the orthogonal ones.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -2275,7 +2278,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
"at the raster implied by origin at the glue box border and beyond. To ensure fill cell compatibility inside the tiling processor, it is sufficient to use the tile "
|
"at the raster implied by origin at the glue box border and beyond. To ensure fill cell compatibility inside the tiling processor, it is sufficient to use the tile "
|
||||||
"box as the glue box.\n"
|
"box as the glue box.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.23 and enhanced in version 0.27.\n"
|
"This method has been introduced in version 0.23 and enhanced in version 0.27. The 'exclude_area' argument has been added in version 0.30.4.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("fill_region", &fill_region_skew, gsi::arg ("region"),
|
gsi::method_ext ("fill_region", &fill_region_skew, gsi::arg ("region"),
|
||||||
gsi::arg ("fill_cell_index"),
|
gsi::arg ("fill_cell_index"),
|
||||||
|
|
@ -2287,16 +2290,18 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
|
gsi::arg ("exclude_area", db::Region (), "empty"),
|
||||||
"@brief Fills the given region with cells of the given type (skew step version)\n"
|
"@brief Fills the given region with cells of the given type (skew step version)\n"
|
||||||
"@param region The region to fill\n"
|
"@param region The region to fill\n"
|
||||||
"@param fill_cell_index The fill cell to place\n"
|
"@param fill_cell_index The fill cell to place\n"
|
||||||
"@param fc_bbox The fill cell's box to place\n"
|
"@param fc_bbox The fill cell's box, defining the box that needs to be inside the fill region\n"
|
||||||
"@param row_step The 'rows' step vector\n"
|
"@param row_step The 'rows' step vector\n"
|
||||||
"@param column_step The 'columns' 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"
|
"@param origin The global origin of the fill pattern or nil to allow local (per-polygon) optimization\n"
|
||||||
"@param remaining_parts See explanation in other version\n"
|
"@param remaining_parts See explanation in other version\n"
|
||||||
"@param fill_margin See explanation in other version\n"
|
"@param fill_margin See explanation in other version\n"
|
||||||
"@param remaining_polygons See explanation in other version\n"
|
"@param remaining_polygons See explanation in other version\n"
|
||||||
|
"@param exclude_area A region that defines the areas which are not be filled\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This version is similar to the version providing an orthogonal fill, 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"
|
"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"
|
||||||
|
|
@ -2305,7 +2310,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
"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. "
|
"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"
|
"The fill boxes lower left corner is the reference for the fill pattern and aligns with the origin if given.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This variant has been introduced in version 0.27.\n"
|
"This variant has been introduced in version 0.27. The 'exclude_area' argument has been added in version 0.30.4.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("fill_region_multi", &fill_region_multi, gsi::arg ("region"),
|
gsi::method_ext ("fill_region_multi", &fill_region_multi, gsi::arg ("region"),
|
||||||
gsi::arg ("fill_cell_index"),
|
gsi::arg ("fill_cell_index"),
|
||||||
|
|
@ -2315,6 +2320,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
|
gsi::arg ("exclude_area", db::Region (), "empty"),
|
||||||
"@brief Fills the given region with cells of the given type in enhanced mode with iterations\n"
|
"@brief Fills the given region with cells of the given type in enhanced mode with iterations\n"
|
||||||
"This version operates like \\fill_region, but repeats the fill generation until no further fill cells can be placed. "
|
"This version operates like \\fill_region, but repeats the fill generation until no further fill cells can be placed. "
|
||||||
"As the fill pattern origin changes between the iterations, narrow regions can be filled which cannot with a fixed fill pattern origin. "
|
"As the fill pattern origin changes between the iterations, narrow regions can be filled which cannot with a fixed fill pattern origin. "
|
||||||
|
|
@ -2323,7 +2329,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
||||||
"\n"
|
"\n"
|
||||||
"The origin is ignored unless a glue box is given. See \\fill_region for a description of this concept.\n"
|
"The origin is ignored unless a glue box is given. See \\fill_region for a description of this concept.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.27.\n"
|
"This method has been introduced in version 0.27. The 'exclude_area' argument has been added in version 0.30.4.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("begin_shapes_rec", &begin_shapes_rec, gsi::arg ("layer"),
|
gsi::method_ext ("begin_shapes_rec", &begin_shapes_rec, gsi::arg ("layer"),
|
||||||
"@brief Delivers a recursive shape iterator for the shapes below the cell on the given layer\n"
|
"@brief Delivers a recursive shape iterator for the shapes below the cell on the given layer\n"
|
||||||
|
|
|
||||||
|
|
@ -1309,23 +1309,23 @@ tl::Variant complex_op (db::Region *region, db::CompoundRegionOperationNode *nod
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_region (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
|
fill_region (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
|
||||||
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
|
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
db::fill_region (cell, *fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box);
|
db::fill_region (cell, *fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
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,
|
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::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
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);
|
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, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
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,
|
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::Box &glue_box)
|
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box, const db::Region &exclude_area)
|
||||||
{
|
{
|
||||||
db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box);
|
db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box, exclude_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::Region
|
static db::Region
|
||||||
|
|
@ -4340,6 +4340,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
|
gsi::arg ("exclude_area", db::Region (), "empty"),
|
||||||
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
|
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
|
||||||
|
|
@ -4348,7 +4349,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("fill", &fill_region_skew, gsi::arg ("in_cell"),
|
gsi::method_ext ("fill", &fill_region_skew, gsi::arg ("in_cell"),
|
||||||
gsi::arg ("fill_cell_index"),
|
gsi::arg ("fill_cell_index"),
|
||||||
gsi::arg ("fc_origin"),
|
gsi::arg ("fc_bbox"),
|
||||||
gsi::arg ("row_step"),
|
gsi::arg ("row_step"),
|
||||||
gsi::arg ("column_step"),
|
gsi::arg ("column_step"),
|
||||||
gsi::arg ("origin", &default_origin, "(0, 0)"),
|
gsi::arg ("origin", &default_origin, "(0, 0)"),
|
||||||
|
|
@ -4356,6 +4357,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
|
gsi::arg ("exclude_area", db::Region (), "empty"),
|
||||||
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
|
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
|
||||||
|
|
@ -4364,12 +4366,13 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("fill_multi", &fill_region_multi, gsi::arg ("in_cell"),
|
gsi::method_ext ("fill_multi", &fill_region_multi, gsi::arg ("in_cell"),
|
||||||
gsi::arg ("fill_cell_index"),
|
gsi::arg ("fill_cell_index"),
|
||||||
gsi::arg ("fc_origin"),
|
gsi::arg ("fc_bbox"),
|
||||||
gsi::arg ("row_step"),
|
gsi::arg ("row_step"),
|
||||||
gsi::arg ("column_step"),
|
gsi::arg ("column_step"),
|
||||||
gsi::arg ("fill_margin", db::Vector ()),
|
gsi::arg ("fill_margin", db::Vector ()),
|
||||||
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
|
||||||
gsi::arg ("glue_box", db::Box ()),
|
gsi::arg ("glue_box", db::Box ()),
|
||||||
|
gsi::arg ("exclude_area", db::Region (), "empty"),
|
||||||
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
"@brief A mapping of \\Cell#fill_region to the Region class\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
|
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
|
||||||
|
|
|
||||||
|
|
@ -644,6 +644,10 @@ module DRC
|
||||||
DRCFillStep::new(false, x, y)
|
DRCFillStep::new(false, x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fill_exclude(excl)
|
||||||
|
DRCFillExclude::new(excl)
|
||||||
|
end
|
||||||
|
|
||||||
def auto_origin
|
def auto_origin
|
||||||
DRCFillOrigin::new
|
DRCFillOrigin::new
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -5755,6 +5755,8 @@ CODE
|
||||||
# @li @b multi_origin @/b: lets the algorithm choose the origin and repeats the fill with different origins
|
# @li @b multi_origin @/b: lets the algorithm choose the origin and repeats the fill with different origins
|
||||||
# until no further fill cell can be fitted. @/li
|
# until no further fill cell can be fitted. @/li
|
||||||
# @li @b fill_pattern(..) @/b: specifies the fill pattern. @/li
|
# @li @b fill_pattern(..) @/b: specifies the fill pattern. @/li
|
||||||
|
# @li @b fill_exclude(excl) @/b: specifies a fill exclude region ('excl' is a polygon layer). This is conceptually
|
||||||
|
# equivalent to subtracting that layer from the fill region, but usually more efficient. @/li
|
||||||
# @/ul
|
# @/ul
|
||||||
#
|
#
|
||||||
# "fill_pattern" generates a fill pattern object. This object is used for configuring the fill pattern
|
# "fill_pattern" generates a fill pattern object. This object is used for configuring the fill pattern
|
||||||
|
|
@ -5895,6 +5897,7 @@ CODE
|
||||||
pattern = nil
|
pattern = nil
|
||||||
origin = RBA::DPoint::new
|
origin = RBA::DPoint::new
|
||||||
repeat = false
|
repeat = false
|
||||||
|
excl = RBA::Region::new
|
||||||
|
|
||||||
args.each_with_index do |a,ai|
|
args.each_with_index do |a,ai|
|
||||||
if a.is_a?(DRCSource)
|
if a.is_a?(DRCSource)
|
||||||
|
|
@ -5907,6 +5910,11 @@ CODE
|
||||||
raise("Duplicate fill pattern specification for '#{m}' at argument ##{ai+1}")
|
raise("Duplicate fill pattern specification for '#{m}' at argument ##{ai+1}")
|
||||||
end
|
end
|
||||||
pattern = a
|
pattern = a
|
||||||
|
elsif a.is_a?(DRCFillExclude)
|
||||||
|
if excl
|
||||||
|
raise("Duplicate exclude region specification for '#{m}' at argument ##{ai+1}")
|
||||||
|
end
|
||||||
|
excl = a.excl
|
||||||
elsif a.is_a?(DRCFillStep)
|
elsif a.is_a?(DRCFillStep)
|
||||||
if a.for_row
|
if a.for_row
|
||||||
if row_step
|
if row_step
|
||||||
|
|
@ -5988,6 +5996,7 @@ CODE
|
||||||
tp.var("fc_index", fc_index)
|
tp.var("fc_index", fc_index)
|
||||||
tp.var("repeat", repeat)
|
tp.var("repeat", repeat)
|
||||||
tp.var("with_left", with_left)
|
tp.var("with_left", with_left)
|
||||||
|
tp.var("excl", excl)
|
||||||
|
|
||||||
tp.queue(<<"END")
|
tp.queue(<<"END")
|
||||||
var tc_box = _frame.bbox;
|
var tc_box = _frame.bbox;
|
||||||
|
|
@ -5997,8 +6006,8 @@ CODE
|
||||||
tile_box = tile_box & tc_box;
|
tile_box = tile_box & tc_box;
|
||||||
var left = with_left ? Region.new : nil;
|
var left = with_left ? Region.new : nil;
|
||||||
repeat ?
|
repeat ?
|
||||||
(region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, left, _tile.bbox) :
|
(region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, left, _tile.bbox, excl) :
|
||||||
(region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, fill_margin, left, _tile.bbox);
|
(region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, fill_margin, left, _tile.bbox, excl);
|
||||||
with_left && _output(#{result_arg}, left)
|
with_left && _output(#{result_arg}, left)
|
||||||
)
|
)
|
||||||
END
|
END
|
||||||
|
|
@ -6020,9 +6029,9 @@ END
|
||||||
|
|
||||||
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
|
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
|
||||||
if repeat
|
if repeat
|
||||||
self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, result)
|
self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, result, RBA::Box::new, excl)
|
||||||
else
|
else
|
||||||
self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, fill_margin, result)
|
self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, fill_margin, result, RBA::Box::new, excl)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -475,6 +475,18 @@ module DRC
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# A wrapper for the fill step definition
|
||||||
|
class DRCFillExclude
|
||||||
|
def initialize(excl)
|
||||||
|
excl.is_a?(DRCLayer) || raise("Exclude layer argument needs to be a DRC layer")
|
||||||
|
excl.requires_region("Exclude layer")
|
||||||
|
@excl = excl.data
|
||||||
|
end
|
||||||
|
def excl
|
||||||
|
@excl
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# A wrapper for the fill step definition
|
# A wrapper for the fill step definition
|
||||||
class DRCFillStep
|
class DRCFillStep
|
||||||
def initialize(for_row, x, y = nil)
|
def initialize(for_row, x, y = nil)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue