mirror of https://github.com/KLayout/klayout.git
WIP.
This commit is contained in:
parent
7bd4a692d8
commit
d4f641bff8
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbRegion.h"
|
||||
#include "dbCell.h"
|
||||
#include "tlIntervalMap.h"
|
||||
#include "tlMath.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -268,9 +269,107 @@ optimize_offset (const db::Polygon &fp, const db::AreaMap &am)
|
|||
return db::Vector (xshift, yshift);
|
||||
}
|
||||
|
||||
class GenericRasterizer
|
||||
{
|
||||
public:
|
||||
GenericRasterizer ()
|
||||
: m_row_step (), m_column_step (), m_row_steps (0), m_column_steps (0), m_origin ()
|
||||
{
|
||||
// .. 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)
|
||||
{
|
||||
db::Coord dx = row_step.x ();
|
||||
db::Coord dy = column_step.y ();
|
||||
|
||||
if (row_step.y () == 0) {
|
||||
m_row_steps = 1;
|
||||
} else {
|
||||
m_row_steps = tl::lcm (dy, std::abs (row_step.y ())) / std::abs (row_step.y ());
|
||||
}
|
||||
|
||||
if (column_step.x () == 0) {
|
||||
m_column_steps = 1;
|
||||
} else {
|
||||
m_column_steps = tl::lcm (dx, std::abs (column_step.x ())) / std::abs (column_step.x ());
|
||||
}
|
||||
|
||||
db::Box fp_bbox = fp.box ();
|
||||
|
||||
db::Coord ddx = dx * db::Coord (m_row_steps) - column_step.x () * ((db::Coord (m_row_steps) * row_step.y ()) / dy);
|
||||
db::Coord ddy = dy * db::Coord (m_column_steps) - row_step.y () * ((db::Coord (m_column_steps) * column_step.x ()) / dx);
|
||||
|
||||
// round polygon bbox
|
||||
db::Coord fp_left = db::Coord (tl::round_down (fp_bbox.left () - origin.x (), ddx)) + origin.x ();
|
||||
db::Coord fp_bottom = db::Coord (tl::round_down (fp_bbox.bottom () - origin.y (), ddy)) + origin.y ();
|
||||
db::Coord fp_right = db::Coord (tl::round_up (fp_bbox.right () - origin.x (), ddx)) + origin.x ();
|
||||
db::Coord fp_top = db::Coord (tl::round_up (fp_bbox.top () - origin.y (), ddy)) + 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.resize (m_row_steps * m_column_steps);
|
||||
|
||||
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);
|
||||
|
||||
long ir_add = dc.x () / dx;
|
||||
dr -= m_row_step * ir_add;
|
||||
|
||||
long ic_add = dr.y () / dy;
|
||||
dc -= m_column_step * ic_add;
|
||||
|
||||
db::AreaMap &am = m_area_maps [ic * m_row_steps + ir];
|
||||
am.reinitialize (db::Point (fp_left, fp_bottom) + dr + dc, db::Vector (ddx, ddy), db::Vector (dx, dy), nx, ny);
|
||||
|
||||
db::rasterize (fp, am);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const db::Point &p0 () const { return m_origin; }
|
||||
|
||||
unsigned int row_steps () const { return m_row_steps; }
|
||||
unsigned int column_steps () const { return m_column_steps; }
|
||||
|
||||
const db::AreaMap &area_map (unsigned int ir, unsigned int ic) const
|
||||
{
|
||||
return m_area_maps [ic * m_row_steps + ir];
|
||||
}
|
||||
|
||||
db::Vector area_map_offset (unsigned int ir, unsigned int ic) const
|
||||
{
|
||||
return m_row_step * long (ir) + m_column_step * long (ic);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<db::AreaMap> m_area_maps;
|
||||
db::Vector m_row_step, m_column_step;
|
||||
unsigned int m_row_steps, m_column_steps;
|
||||
db::Point m_origin;
|
||||
};
|
||||
|
||||
|
||||
static bool
|
||||
rasterize_simple (const db::Polygon &fp, const db::Box &fc_bbox, const db::Point &p0, db::AreaMap &am)
|
||||
{
|
||||
|
||||
db::Coord dx = fc_bbox.width ();
|
||||
db::Coord dy = fc_bbox.height ();
|
||||
|
||||
|
|
@ -439,19 +538,6 @@ printf("@@@ -> n=%d\n", int(n)); fflush(stdout); // @@@
|
|||
return true;
|
||||
}
|
||||
|
||||
static db::IMatrix2d
|
||||
compute_shear_matrix (const db::Vector &r, const db::Vector &c)
|
||||
{
|
||||
double det = r.x () * c.y () - r.y () * c.x ();
|
||||
|
||||
double m11 = c.y () * r.x () / det;
|
||||
double m22 = m11;
|
||||
double m12 = -c.x () * r.x () / det;
|
||||
double m21 = -c.y () * r.y () / det;
|
||||
|
||||
return IMatrix2d (m11, m12, m21, m22);
|
||||
}
|
||||
|
||||
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,
|
||||
std::vector <db::Polygon> *remaining_parts, const db::Vector &fill_margin)
|
||||
|
|
@ -463,73 +549,6 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
|
|||
return fill_region (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);
|
||||
}
|
||||
|
||||
static db::Polygon
|
||||
produce_fill_stripe (const db::Vector &row_step, const db::Vector &column_step, long n)
|
||||
{
|
||||
if (column_step.x () == 0) {
|
||||
|
||||
db::Coord ymin = std::min (0, row_step.y ());
|
||||
db::Coord ymax = std::max (0, row_step.y ()) + n * column_step.y ();
|
||||
|
||||
return db::Polygon (db::Box (0, ymin, row_step.x (), ymax));
|
||||
|
||||
} else {
|
||||
|
||||
db::Coord xmin = 0;
|
||||
db::Coord xmax = row_step.x ();
|
||||
|
||||
db::Coord ymin = 0;
|
||||
db::Coord ymax = n * column_step.y ();
|
||||
|
||||
std::vector<db::Point> pts;
|
||||
pts.reserve (n * 2);
|
||||
|
||||
for (long i = 0; i < n; ++i) {
|
||||
|
||||
db::Coord x = xmin + i * column_step.x ();
|
||||
db::Coord y = i * column_step.y ();
|
||||
|
||||
if (i == 0) {
|
||||
pts.push_back (db::Point (x, ymin));
|
||||
} else {
|
||||
pts.push_back (db::Point (x, y));
|
||||
}
|
||||
if (i == n - 1) {
|
||||
pts.push_back (db::Point (x, ymax));
|
||||
} else {
|
||||
pts.push_back (db::Point (x, y + column_step.y ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (long i = n; i > 0; ) {
|
||||
|
||||
--i;
|
||||
|
||||
db::Coord x = xmax + i * column_step.x ();
|
||||
db::Coord y = i * column_step.y ();
|
||||
|
||||
if (i == n - 1) {
|
||||
pts.push_back (db::Point (x, ymax));
|
||||
} else {
|
||||
pts.push_back (db::Point (x, y + column_step.y ()));
|
||||
}
|
||||
if (i == 0) {
|
||||
pts.push_back (db::Point (x, ymin));
|
||||
} else {
|
||||
pts.push_back (db::Point (x, y));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Polygon p;
|
||||
p.assign_hull (pts.begin (), pts.end ());
|
||||
return p;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
std::vector <db::Polygon> *remaining_parts, const db::Vector &fill_margin)
|
||||
|
|
@ -542,14 +561,6 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
|
|||
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::IMatrix2d shear = compute_shear_matrix (row_step, column_step);
|
||||
db::IMatrix2d inverse_shear = shear.inverted ();
|
||||
|
||||
tl_assert (shear.trans (row_step).y () == 0);
|
||||
tl_assert (shear.trans (row_step).x () == row_step.x ());
|
||||
tl_assert (shear.trans (column_step).x () == 0);
|
||||
tl_assert (shear.trans (column_step).y () == column_step.y ());
|
||||
|
||||
std::vector <db::Polygon> filled_regions;
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
|
|
@ -581,62 +592,68 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
|
|||
filled_regions.clear ();
|
||||
bool any_fill = false;
|
||||
|
||||
for (std::vector <db::Polygon>::const_iterator fpr = fpb.begin (); fpr != fpb.end (); ++fpr) {
|
||||
|
||||
db::Polygon fp = fpr->transformed (shear);
|
||||
for (std::vector <db::Polygon>::const_iterator fp = fpb.begin (); fp != fpb.end (); ++fp) {
|
||||
|
||||
size_t ninsts = 0;
|
||||
|
||||
db::AreaMap am;
|
||||
GenericRasterizer am (*fp, row_step, column_step, origin);
|
||||
|
||||
db::Box raster_box (0, 0, row_step.x (), column_step.y ());
|
||||
// @@@ optimize fill offset ...
|
||||
|
||||
// Rasterize to determine fill regions
|
||||
// NOTE: rasterization happens post-shear transformation (e.g. with a rectangular kernel)
|
||||
if ((enhanced_fill && rasterize_extended (fp, raster_box, am)) || (!enhanced_fill && rasterize_simple (fp, raster_box, origin, am))) {
|
||||
for (unsigned int ir = 0; ir < am.row_steps (); ++ir) {
|
||||
|
||||
size_t nx = am.nx ();
|
||||
size_t ny = am.ny ();
|
||||
for (unsigned int ic = 0; ic < am.column_steps (); ++ic) {
|
||||
|
||||
db::AreaMap::area_type amax = am.pixel_area ();
|
||||
const db::AreaMap &am1 = am.area_map (ir, ic);
|
||||
|
||||
// Create the fill cell instances
|
||||
for (size_t i = 0; i < nx; ++i) {
|
||||
size_t nx = am1.nx ();
|
||||
size_t ny = am1.ny ();
|
||||
|
||||
for (size_t j = 0; j < ny; ) {
|
||||
// Create the fill cell instances
|
||||
for (size_t i = 0; i < nx; ++i) {
|
||||
|
||||
size_t jj = j + 1;
|
||||
if (am.get (i, j) >= amax) {
|
||||
for (size_t j = 0; j < ny; ) {
|
||||
|
||||
size_t jj = j + 1;
|
||||
if (am1.get (i, j) == am1.pixel_area ()) {
|
||||
|
||||
while (jj != ny && am1.get (i, jj) == am1.pixel_area ()) {
|
||||
++jj;
|
||||
}
|
||||
|
||||
ninsts += (jj - j);
|
||||
|
||||
db::Vector p0 = (am1.p0 () - db::Point ()) - kernel_origin;
|
||||
p0 += db::Vector (i * am1.d ().x (), j * am1.d ().y ());
|
||||
|
||||
db::CellInstArray array;
|
||||
|
||||
if (jj > j + 1) {
|
||||
array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), db::Vector (0, am1.d ().y ()), db::Vector (), (unsigned long) (jj - j), 1);
|
||||
} else {
|
||||
array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0));
|
||||
}
|
||||
|
||||
cell->insert (array);
|
||||
|
||||
if (remaining_parts) {
|
||||
if (am1.d ().y () == am1.p ().y ()) {
|
||||
filled_regions.push_back (db::Polygon (db::Box (db::Point (), db::Point (am1.p ().x (), am1.p ().y () * (jj - j))).moved (kernel_origin + p0)));
|
||||
} else {
|
||||
for (size_t k = 0; k < jj - j; ++k) {
|
||||
filled_regions.push_back (db::Polygon (db::Box (db::Point (), db::Point () + am1.p ()).moved (kernel_origin + p0 + db::Vector (0, am1.d ().y () * db::Coord (k)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
any_fill = true;
|
||||
|
||||
while (jj != ny && am.get (i, jj) >= amax) {
|
||||
++jj;
|
||||
}
|
||||
|
||||
ninsts += (jj - j);
|
||||
|
||||
db::Vector p0 (inverse_shear.trans (am.p0 ()) - kernel_origin);
|
||||
p0 += row_step * long (i) + column_step * long (j);
|
||||
|
||||
db::CellInstArray array;
|
||||
|
||||
if (jj > j + 1) {
|
||||
array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), column_step, db::Vector (), (unsigned long) (jj - j), 1);
|
||||
} else {
|
||||
array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0));
|
||||
}
|
||||
|
||||
cell->insert (array);
|
||||
|
||||
if (remaining_parts) {
|
||||
filled_regions.push_back (produce_fill_stripe (row_step, column_step, long (jj - j)).moved (p0 + kernel_origin));
|
||||
}
|
||||
|
||||
any_fill = true;
|
||||
j = jj;
|
||||
|
||||
}
|
||||
|
||||
j = jj;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -644,7 +661,7 @@ fill_region (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type fill_ce
|
|||
}
|
||||
|
||||
if (tl::verbosity () >= 30 && ninsts > 0) {
|
||||
tl::info << "Part " << fpr->to_string ();
|
||||
tl::info << "Part " << fp->to_string ();
|
||||
tl::info << "Created " << ninsts << " instances";
|
||||
}
|
||||
|
||||
|
|
@ -773,6 +790,8 @@ fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fi
|
|||
new_fill_region.swap (remaining);
|
||||
fill_region = &new_fill_region;
|
||||
|
||||
break; // @@@
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1563,8 +1563,35 @@ AreaMap::AreaMap ()
|
|||
mp_av = 0;
|
||||
}
|
||||
|
||||
AreaMap::AreaMap (const AreaMap &other)
|
||||
: m_nx (0), m_ny (0)
|
||||
{
|
||||
mp_av = 0;
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
AreaMap &
|
||||
AreaMap::operator= (const AreaMap &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
// TODO: this could be copy on write
|
||||
reinitialize (other.p0 (), other.d (), other.p (), other.nx (), other.ny ());
|
||||
if (other.mp_av) {
|
||||
memcpy (mp_av, other.mp_av, m_nx * m_ny * sizeof (*mp_av));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
AreaMap::AreaMap (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny)
|
||||
: m_p0 (p0), m_d (d), m_nx (nx), m_ny (ny)
|
||||
: m_p0 (p0), m_d (d), m_p (d), m_nx (nx), m_ny (ny)
|
||||
{
|
||||
mp_av = new area_type [nx * ny];
|
||||
clear ();
|
||||
}
|
||||
|
||||
AreaMap::AreaMap (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny)
|
||||
: m_p0 (p0), m_d (d), m_p (std::min (d.x (), p.x ()), std::min (d.y (), p.y ())), m_nx (nx), m_ny (ny)
|
||||
{
|
||||
mp_av = new area_type [nx * ny];
|
||||
clear ();
|
||||
|
|
@ -1580,9 +1607,16 @@ AreaMap::~AreaMap ()
|
|||
|
||||
void
|
||||
AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny)
|
||||
{
|
||||
reinitialize (p0, d, d, nx, ny);
|
||||
}
|
||||
|
||||
void
|
||||
AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny)
|
||||
{
|
||||
m_p0 = p0;
|
||||
m_d = d;
|
||||
m_p = db::Vector (std::min (d.x (), p.x ()), std::min (d.y (), p.y ()));
|
||||
m_nx = nx;
|
||||
m_ny = ny;
|
||||
|
||||
|
|
@ -1629,6 +1663,16 @@ AreaMap::total_area () const
|
|||
return asum;
|
||||
}
|
||||
|
||||
db::Box
|
||||
AreaMap::bbox () const
|
||||
{
|
||||
if (m_nx == 0 || m_ny == 0) {
|
||||
return db::Box ();
|
||||
} else {
|
||||
return db::Box (m_p0, m_p0 + db::Vector (db::Coord (m_nx - 1) * m_d.x () + m_p.x (), db::Coord (m_ny - 1) * m_d.y () + m_p.y ()));
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Implementation of rasterize
|
||||
|
||||
|
|
@ -1646,6 +1690,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
db::Coord ymin = box.bottom (), ymax = box.top ();
|
||||
db::Coord dy = am.d ().y (), dx = am.d ().x ();
|
||||
db::Coord py = am.p ().y (), px = am.p ().x ();
|
||||
db::Coord y0 = am.p0 ().y (), x0 = am.p0 ().x ();
|
||||
size_t ny = am.ny (), nx = am.nx ();
|
||||
|
||||
|
|
@ -1695,7 +1740,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
for (size_t iy = iy0; iy < iy1; ++iy) {
|
||||
|
||||
db::Coord yy = y + dy;
|
||||
db::Coord yy = y + py;
|
||||
while (f != edges.end () && db::edge_ymin (*f) < yy) {
|
||||
++f;
|
||||
}
|
||||
|
|
@ -1711,7 +1756,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
while (cc != edges.end () && cc != f && db::edge_xmax (*cc) <= x) {
|
||||
db::Coord y1 = std::max (y, std::min (yy, cc->p1 ().y ()));
|
||||
db::Coord y2 = std::max (y, std::min (yy, cc->p2 ().y ()));
|
||||
a += area_type (dx) * area_type (y2 - y1);
|
||||
a += area_type (px) * area_type (y2 - y1);
|
||||
++cc;
|
||||
}
|
||||
|
||||
|
|
@ -1719,7 +1764,8 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
for (size_t ix = ix0; ix < ix1; ++ix) {
|
||||
|
||||
db::Coord xx = x + dx;
|
||||
db::Coord xx = x + px;
|
||||
db::Coord xxx = x + dx;
|
||||
|
||||
// TODO: edge_xmin_at_interval(y, yy) and edge_xmax.. would be more efficient in the
|
||||
// all-angle case. However, it is crucial that the edge clipping produces
|
||||
|
|
@ -1730,6 +1776,14 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
++ff;
|
||||
}
|
||||
|
||||
std::vector <db::Edge>::iterator fff = ff;
|
||||
|
||||
if (xx < xxx) {
|
||||
while (fff != f && db::edge_xmin (*fff) < xxx) {
|
||||
++fff;
|
||||
}
|
||||
}
|
||||
|
||||
if (xl < x) {
|
||||
|
||||
// consider all edges or parts of those left of the first cell
|
||||
|
|
@ -1739,24 +1793,50 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
std::pair<bool, db::Edge> ec = e->clipped (left);
|
||||
if (ec.first && db::edge_xmin (ec.second) < x) {
|
||||
a += area_type (ec.second.dy ()) * area_type (dx);
|
||||
a += area_type (ec.second.dy ()) * area_type (px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Box cell (x, y, xx, yy);
|
||||
|
||||
area_type aa = a;
|
||||
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != ff; ++e) {
|
||||
if (dx == py) {
|
||||
|
||||
std::pair<bool, db::Edge> ec = e->clipped (cell);
|
||||
if (ec.first && db::edge_xmin (ec.second) < xx) {
|
||||
db::Box cell (x, y, xx, yy);
|
||||
|
||||
aa += area_type (ec.second.dy ()) * area_type (2 * xx - (ec.second.p2 ().x () + ec.second.p1 ().x ())) / 2;
|
||||
a += area_type (ec.second.dy ()) * area_type (dx);
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != ff; ++e) {
|
||||
|
||||
std::pair<bool, db::Edge> ec = e->clipped (cell);
|
||||
if (ec.first && db::edge_xmin (ec.second) < xx) {
|
||||
aa += (area_type (ec.second.dy ()) * area_type (2 * xx - (ec.second.p2 ().x () + ec.second.p1 ().x ()))) / 2;
|
||||
a += area_type (ec.second.dy ()) * area_type (px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::Box cell (x, y, xx, yy);
|
||||
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != ff; ++e) {
|
||||
|
||||
std::pair<bool, db::Edge> ec = e->clipped (cell);
|
||||
if (ec.first && db::edge_xmin (ec.second) < xx) {
|
||||
aa += (area_type (ec.second.dy ()) * area_type (2 * xx - (ec.second.p2 ().x () + ec.second.p1 ().x ()))) / 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Box wide_cell (x, y, x + dx, yy);
|
||||
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != fff; ++e) {
|
||||
|
||||
std::pair<bool, db::Edge> wide_ec = e->clipped (wide_cell);
|
||||
if (wide_ec.first && db::edge_xmin (wide_ec.second) < x + dx) {
|
||||
a += area_type (wide_ec.second.dy ()) * area_type (px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1764,8 +1844,10 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
am.get (ix, iy) += aa;
|
||||
|
||||
x = xx;
|
||||
xl = xx;
|
||||
x += dx;
|
||||
xl = x;
|
||||
|
||||
ff = fff;
|
||||
|
||||
for (std::vector <db::Edge>::iterator ccx = cc; ccx != ff; ++ccx) {
|
||||
if (db::edge_xmax (*ccx) <= x) {
|
||||
|
|
@ -1776,6 +1858,13 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
}
|
||||
|
||||
if (yy < y + dy) {
|
||||
yy = y + dy;
|
||||
while (f != edges.end () && db::edge_ymin (*f) < yy) {
|
||||
++f;
|
||||
}
|
||||
}
|
||||
|
||||
y = yy;
|
||||
|
||||
for (std::vector <db::Edge>::iterator cx = c; cx != f; ++cx) {
|
||||
|
|
|
|||
|
|
@ -500,21 +500,41 @@ public:
|
|||
*/
|
||||
AreaMap ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
AreaMap (const AreaMap &);
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
AreaMap (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Constructor with pixel size
|
||||
*/
|
||||
AreaMap (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~AreaMap ();
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
AreaMap &operator= (const AreaMap &);
|
||||
|
||||
/**
|
||||
* @brief Reinitialize
|
||||
*/
|
||||
void reinitialize (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Reinitialize with pixel size
|
||||
*/
|
||||
void reinitialize (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Swap of two maps
|
||||
*/
|
||||
|
|
@ -576,13 +596,18 @@ public:
|
|||
return m_d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The pixel size (must be less than d)
|
||||
*/
|
||||
const db::Vector &p () const
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute the bounding box of the area map
|
||||
*/
|
||||
db::Box bbox () const
|
||||
{
|
||||
return db::Box (m_p0, m_p0 + db::Vector (db::Coord (m_nx) * m_d.x (), db::Coord (m_ny) * m_d.y ()));
|
||||
}
|
||||
db::Box bbox () const;
|
||||
|
||||
/**
|
||||
* @brief Compute the total area
|
||||
|
|
@ -594,7 +619,7 @@ public:
|
|||
*/
|
||||
area_type pixel_area () const
|
||||
{
|
||||
return area_type (m_d.x ()) * area_type (m_d.y ());
|
||||
return area_type (m_p.x ()) * area_type (m_p.y ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -606,11 +631,8 @@ private:
|
|||
area_type *mp_av;
|
||||
db::Point m_p0;
|
||||
db::Vector m_d;
|
||||
db::Vector m_p;
|
||||
size_t m_nx, m_ny;
|
||||
|
||||
// no copying
|
||||
AreaMap (const AreaMap &);
|
||||
AreaMap &operator= (const AreaMap &);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -918,6 +918,37 @@ TEST(25)
|
|||
|
||||
EXPECT_EQ (am_to_string (am), "(1650,5000,8350,3000,0),(3350,9175,10000,8660,330),(0,825,6650,10000,5000),(0,0,0,3350,8845),(0,0,0,0,825)");
|
||||
EXPECT_EQ (am.total_area (), 85010);
|
||||
|
||||
am.reinitialize (db::Point (0, 0), db::Vector (100, 100), db::Vector (50, 50), 5, 5);
|
||||
db::rasterize (in, am);
|
||||
|
||||
EXPECT_EQ (am_to_string (am), "(0,0,1250,750,0),(825,2500,2500,2500,0),(0,0,2287,2500,1750),(0,0,0,825,2500),(0,0,0,0,0)");
|
||||
EXPECT_EQ (am.total_area (), 20187);
|
||||
|
||||
am.reinitialize (db::Point (200, 0), db::Vector (100, 100), db::Vector (50, 50), 1, 1);
|
||||
db::rasterize (in, am);
|
||||
|
||||
EXPECT_EQ (am_to_string (am), "(1250)");
|
||||
|
||||
am.reinitialize (db::Point (300, 0), db::Vector (100, 100), db::Vector (50, 50), 1, 1);
|
||||
db::rasterize (in, am);
|
||||
|
||||
EXPECT_EQ (am_to_string (am), "(750)");
|
||||
|
||||
am.reinitialize (db::Point (400, 0), db::Vector (100, 100), db::Vector (50, 50), 1, 1);
|
||||
db::rasterize (in, am);
|
||||
|
||||
EXPECT_EQ (am_to_string (am), "(0)");
|
||||
|
||||
am.reinitialize (db::Point (400, 100), db::Vector (100, 100), db::Vector (50, 50), 1, 1);
|
||||
db::rasterize (in, am);
|
||||
|
||||
EXPECT_EQ (am_to_string (am), "(0)");
|
||||
|
||||
am.reinitialize (db::Point (400, 200), db::Vector (100, 100), db::Vector (50, 50), 1, 1);
|
||||
db::rasterize (in, am);
|
||||
|
||||
EXPECT_EQ (am_to_string (am), "(1750)");
|
||||
}
|
||||
|
||||
TEST(26)
|
||||
|
|
@ -1047,7 +1078,7 @@ TEST(30)
|
|||
EXPECT_EQ (am_to_string (am), "(5418,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(6642,6267,1967,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(6642,6642,6582,3119,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(6642,6642,6642,6642,4317,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(1701,1701,1701,4995,6642,5303,735,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,4428,6642,6642,5952,1127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,4428,6642,6642,6642,6178,1484,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,2430,3645,3645,4644,6642,6355,1859,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,2214,6642,6642,6489,2275,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,2214,6642,6642,6642,6582,2698,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,1863,5589,5589,5589,6642,6632,2994,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,6642,6642,6624,2698,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,6642,6642,6642,6587,2379,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,6642,6642,6642,6642,6537,2111,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,891,891,891,4725,6642,6471,1859,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,4428,6642,6642,6378,1570,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,4428,6642,6642,6642,6166,960,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,1890,2835,2835,4104,6642,5617,432,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2214,6642,6642,4860,104,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2214,6642,6642,6642,3854,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1593,4779,4779,4779,6642,2788,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6642,6538,1777,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6642,6642,6110,704),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6642,6642,6642,4539),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,81,81,55)");
|
||||
}
|
||||
|
||||
TEST(31)
|
||||
TEST(41)
|
||||
{
|
||||
db::Point pattern [] = {
|
||||
db::Point (0, -100),
|
||||
|
|
@ -1131,7 +1162,7 @@ TEST(31)
|
|||
EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)");
|
||||
}
|
||||
|
||||
TEST(32)
|
||||
TEST(42)
|
||||
{
|
||||
db::Point pattern [] = {
|
||||
db::Point (0, -100),
|
||||
|
|
|
|||
Loading…
Reference in New Issue