From a2e449989eaa2c00dbb9ec9d521f558db91fd2d2 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 29 Aug 2024 22:53:19 +0200 Subject: [PATCH] GSI binding of Region#binned_area - experimental! --- src/db/db/dbBinnedAreaCollector.cc | 99 +++++++++++++++++++++++++++++- src/db/db/dbBinnedAreaCollector.h | 5 ++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/db/db/dbBinnedAreaCollector.cc b/src/db/db/dbBinnedAreaCollector.cc index abf9a8a7e..96599ef1b 100644 --- a/src/db/db/dbBinnedAreaCollector.cc +++ b/src/db/db/dbBinnedAreaCollector.cc @@ -21,10 +21,107 @@ */ #include "dbBinnedAreaCollector.h" +#include "dbTypes.h" +#include "dbRegion.h" + +#include "gsiDecl.h" + +#include namespace db { - // .. nothing yet .. +namespace +{ + +class AreaReceiver + : public db::binned_area_receiver +{ +public: + typedef db::coord_traits::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 &get () const + { + return m_areas; + } + +private: + std::vector m_areas; +}; + +} + +// NOTE: this does not belong here. It is an experimental feature + +static std::vector +binned_area (const std::vector &inputs, const std::vector &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 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 coll (bsm, rec); + ep.process (coll, coll); + + return rec.get (); +} + +gsi::ClassExt 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." + ) +); } diff --git a/src/db/db/dbBinnedAreaCollector.h b/src/db/db/dbBinnedAreaCollector.h index 2de1f2c16..2d3756ccc 100644 --- a/src/db/db/dbBinnedAreaCollector.h +++ b/src/db/db/dbBinnedAreaCollector.h @@ -206,6 +206,11 @@ public: mp_receiver->finish (); } + virtual void put (const db::Edge &, int) + { + // not used. + } + 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;