mirror of https://github.com/KLayout/klayout.git
GSI binding of Region#binned_area - experimental!
This commit is contained in:
parent
8fa308b74c
commit
a2e449989e
|
|
@ -21,10 +21,107 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dbBinnedAreaCollector.h"
|
#include "dbBinnedAreaCollector.h"
|
||||||
|
#include "dbTypes.h"
|
||||||
|
#include "dbRegion.h"
|
||||||
|
|
||||||
|
#include "gsiDecl.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
||||||
// .. nothing yet ..
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
class AreaReceiver
|
||||||
|
: public db::binned_area_receiver<unsigned int>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef db::coord_traits<db::Coord>::area_type area_type;
|
||||||
|
|
||||||
|
AreaReceiver (unsigned int count)
|
||||||
|
{
|
||||||
|
m_areas.resize (count, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void add_area (area_type area, const unsigned int &index)
|
||||||
|
{
|
||||||
|
m_areas [index] += area;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<area_type> &get () const
|
||||||
|
{
|
||||||
|
return m_areas;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<area_type> m_areas;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this does not belong here. It is an experimental feature
|
||||||
|
|
||||||
|
static std::vector<AreaReceiver::area_type>
|
||||||
|
binned_area (const std::vector<const db::Region *> &inputs, const std::vector<std::string> &vectors)
|
||||||
|
{
|
||||||
|
db::EdgeProcessor ep;
|
||||||
|
|
||||||
|
unsigned int index = 0;
|
||||||
|
for (auto r = inputs.begin (); r != inputs.end (); ++r, ++index) {
|
||||||
|
for (auto p = (*r)->begin (); ! p.at_end (); ++p) {
|
||||||
|
ep.insert (*p, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tl::bit_set_map<unsigned int> bsm;
|
||||||
|
index = 0;
|
||||||
|
for (auto i = vectors.begin (); i != vectors.end (); ++i, ++index) {
|
||||||
|
bsm.insert (tl::BitSetMask (*i), index);
|
||||||
|
}
|
||||||
|
bsm.sort ();
|
||||||
|
|
||||||
|
AreaReceiver rec (index);
|
||||||
|
db::binned_area_collector<unsigned int> coll (bsm, rec);
|
||||||
|
ep.process (coll, coll);
|
||||||
|
|
||||||
|
return rec.get ();
|
||||||
|
}
|
||||||
|
|
||||||
|
gsi::ClassExt<db::Region> extend_region_by_binned_area (
|
||||||
|
gsi::method ("binned_area", &binned_area, gsi::arg ("inputs"), gsi::arg ("masks"),
|
||||||
|
"@brief Computes the areas of a binned decomposition of the overall region.\n"
|
||||||
|
"In this function, the overall region is decomposed into subregions with different overlap situations. "
|
||||||
|
"Each overlap case is assigned a bin using a bit mask from the 'masks' argument. "
|
||||||
|
"Each bit corresponds to one input from 'inputs' - bit 0 is the first one etc.\n"
|
||||||
|
"The masks are strings of characters 0, 1 or 'X', representing 'inside', 'outside' and "
|
||||||
|
"'any' for the respective input. The first character represents the first input, the second the second input etc.\n"
|
||||||
|
"Missing characters are treated as 'any', so the empty string matches every situation.\n"
|
||||||
|
"\n"
|
||||||
|
"The result is a vector of accumulated areas for each bin identified by one mask. "
|
||||||
|
"Bins may overlay if multiple masks match, so the total sum of areas is not necessarily "
|
||||||
|
"identical to the total area. A bin with an empty string mask will deliver the total area.\n"
|
||||||
|
"\n"
|
||||||
|
"Merge semantics always applies - i.e. all shapes inside the regions are conceptually "
|
||||||
|
"merged in 'positive wrap count' mode before computing the area. Hence overlapping shapes ""
|
||||||
|
"per input region just count once.\n"
|
||||||
|
"\n"
|
||||||
|
"Example:\n"
|
||||||
|
"\n"
|
||||||
|
"@code\n"
|
||||||
|
"r1 = RBA::Region::new\n"
|
||||||
|
"r1.insert(RBA::Box::new(0, 0, 1000, 2000))\n"
|
||||||
|
"\n"
|
||||||
|
"r2 = RBA::Region::new\n"
|
||||||
|
"r2.insert(RBA::Box::new(500, 1000, 1500, 3000))\n"
|
||||||
|
"\n"
|
||||||
|
"areas = RBA::Region::binned_area([ r1, r2 ], [ \"10\", \"01\", \"\" ])\n"
|
||||||
|
"r1_not_r2, r2_not_r1, all = areas\n"
|
||||||
|
"@/code\n"
|
||||||
|
"\n"
|
||||||
|
"This feature is highly experimental."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,11 @@ public:
|
||||||
mp_receiver->finish ();
|
mp_receiver->finish ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void put (const db::Edge &, int)
|
||||||
|
{
|
||||||
|
// not used.
|
||||||
|
}
|
||||||
|
|
||||||
virtual void put (const db::Edge &edge)
|
virtual void put (const db::Edge &edge)
|
||||||
{
|
{
|
||||||
area_type partial_area = area_type (edge.p1 ().x () + edge.p2 ().x ()) * area_type (edge.dy ()) * 0.5;
|
area_type partial_area = area_type (edge.p1 ().x () + edge.p2 ().x ()) * area_type (edge.dy ()) * 0.5;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue