mirror of https://github.com/KLayout/klayout.git
Grayscale rasterizer for Region
This commit is contained in:
parent
1dbb3917c8
commit
596c6c0aac
|
|
@ -780,6 +780,39 @@ size_dvm (db::Region *region, const db::Vector &dv, unsigned int mode)
|
|||
return *region;
|
||||
}
|
||||
|
||||
static std::vector<std::vector<double> >
|
||||
rasterize2 (const db::Region *region, const db::Point &origin, const db::Vector &pixel_distance, const db::Vector &pixel_size, unsigned int nx, unsigned int ny)
|
||||
{
|
||||
db::AreaMap am (origin, pixel_distance, pixel_size, nx, ny);
|
||||
|
||||
auto si = region->begin ();
|
||||
si = si.confined (am.bbox (), false /*not overlapping*/);
|
||||
|
||||
while (! si.at_end ()) {
|
||||
db::rasterize (*si, am);
|
||||
++si;
|
||||
}
|
||||
|
||||
std::vector<std::vector<double> > result;
|
||||
result.reserve (ny);
|
||||
for (unsigned int y = 0; y < ny; ++y) {
|
||||
result.push_back (std::vector<double> ());
|
||||
std::vector<double> &row = result.back ();
|
||||
row.reserve (nx);
|
||||
for (unsigned int x = 0; x < nx; ++x) {
|
||||
row.push_back (am.get (x, y));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<std::vector<double> >
|
||||
rasterize1 (const db::Region *region, const db::Point &origin, const db::Vector &pixel_size, unsigned int nx, unsigned int ny)
|
||||
{
|
||||
return rasterize2 (region, origin, pixel_size, pixel_size, nx, ny);
|
||||
}
|
||||
|
||||
static db::Point default_origin;
|
||||
|
||||
// provided by gsiDeclDbPolygon.cc:
|
||||
|
|
@ -3071,6 +3104,38 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@brief Converts the region to a string\n"
|
||||
"This version allows specification of the maximum number of polygons contained in the string."
|
||||
) +
|
||||
method_ext ("rasterize", &rasterize1, gsi::arg ("origin"), gsi::arg ("pixel_size"), gsi::arg ("nx"), gsi::arg ("ny"),
|
||||
"@brief A grayscale rasterizer delivering the area covered per pixel\n"
|
||||
"@param origin The lower-left corner of the lowest-left pixel\n"
|
||||
"@param pixel_size The dimension of each pixel (the x component gives the width, the y component the height)\n"
|
||||
"@param nx The number of pixels in horizontal direction\n"
|
||||
"@param ny The number of pixels in vertical direction\n"
|
||||
"The method will create a grayscale, high-resolution density map of a rectangular region.\n"
|
||||
"The scan region is defined by the origin, the pixel size and the number of pixels in horizontal (nx) and\n"
|
||||
"vertical (ny) direction. The resulting array will contain the area covered by polygons from the region\n"
|
||||
"in square database units.\n"
|
||||
"\n"
|
||||
"For non-overlapping polygons, the maximum density value is px*py. Overlapping polygons are counted multiple\n"
|
||||
"times, so the actual values may be larger. If you want overlaps removed, you have to\n"
|
||||
"merge the region before. Merge semantics does not apply for the 'rasterize' method.\n"
|
||||
"\n"
|
||||
"Although the resulting area values are floating-point, internal computation is done with integer precision currently.\n"
|
||||
"This implies a certain area error when skew angle edges are involved. The pixel area is precise for Manhattan and\n""
|
||||
"half-Manhattan (45 degree multiples) input geometries.\n"
|
||||
"\n"
|
||||
"A second version exists that allows specifying an active pixel size which is smaller than the\n"
|
||||
"pixel distance hence allowing pixels samples that do not cover the full area, but leave gaps between the pixels.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.29.\n"
|
||||
) +
|
||||
method_ext ("rasterize", &rasterize2, gsi::arg ("origin"), gsi::arg ("pixel_distance"), gsi::arg ("pixel_size"), gsi::arg ("nx"), gsi::arg ("ny"),
|
||||
"@brief A version of 'rasterize' that allows a pixel step distance which is larger than the pixel size\n"
|
||||
"This version behaves like the first variant of 'rasterize', but the pixel distance (pixel-to-pixel step raster)\n"
|
||||
"can be specified separately from the pixel size. Currently, the pixel size must be equal or smaller than the\n"
|
||||
"pixel distance - i.e. the pixels must not overlap.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.29.\n"
|
||||
) +
|
||||
method ("enable_progress", &db::Region::enable_progress, gsi::arg ("label"),
|
||||
"@brief Enable progress reporting\n"
|
||||
"After calling this method, the region will report the progress through a progress bar while "
|
||||
|
|
|
|||
|
|
@ -1188,6 +1188,36 @@ class DBRegion_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# rasterize
|
||||
def test_rasterize
|
||||
|
||||
r = RBA::Region::new()
|
||||
r.insert(RBA::Polygon::new([[0, 0], [100, 100], [200, 0]]))
|
||||
r.insert(RBA::Polygon::new(RBA::Box::new([0, 200], [100, 300])))
|
||||
|
||||
pd = RBA::Vector::new(50, 50)
|
||||
ps = RBA::Vector::new(25, 25)
|
||||
|
||||
sum = 0
|
||||
2.times do |ix|
|
||||
2.times do |iy|
|
||||
am = r.rasterize(RBA::Point::new(-50 + ix * ps.x, -20 + iy * ps.y), pd, ps, 7, 7)
|
||||
sum += am.collect { |r| r.sum }.sum
|
||||
end
|
||||
end
|
||||
|
||||
assert_equal(sum, 8.0 * pd.x * pd.y)
|
||||
|
||||
tot = 0.0
|
||||
pd = RBA::Vector::new(50, 50)
|
||||
|
||||
am = r.rasterize(RBA::Point::new(-50, -20), pd, 7, 7)
|
||||
sum = am.collect { |r| r.sum }.sum
|
||||
|
||||
assert_equal(sum, 8.0 * pd.x * pd.y)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue