Array Utils: Add find_all_ranges function
This functions returns a vector of all the index ranges for which the span contains consecutive values that equal to the value given. Pull Request: https://projects.blender.org/blender/blender/pulls/110265
This commit is contained in:
@@ -169,4 +169,29 @@ inline BooleanMix booleans_mix_calc(const VArray<bool> &varray)
|
||||
return booleans_mix_calc(varray, varray.index_range());
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all the index ranges for which consecutive values in \a span equal \a value.
|
||||
*/
|
||||
template<typename T> inline Vector<IndexRange> find_all_ranges(const Span<T> span, const T &value)
|
||||
{
|
||||
if (span.is_empty()) {
|
||||
return Vector<IndexRange>();
|
||||
}
|
||||
Vector<IndexRange> ranges;
|
||||
int64_t length = (span.first() == value) ? 1 : 0;
|
||||
for (const int64_t i : span.index_range().drop_front(1)) {
|
||||
if (span[i - 1] == value && span[i] != value) {
|
||||
ranges.append(IndexRange(i - length, length));
|
||||
length = 0;
|
||||
}
|
||||
else if (span[i] == value) {
|
||||
length++;
|
||||
}
|
||||
}
|
||||
if (length > 0) {
|
||||
ranges.append(IndexRange(span.size() - length, length));
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
} // namespace blender::array_utils
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "testing/testing.h"
|
||||
|
||||
#include "BLI_array_utils.h"
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_utildefines_stack.h"
|
||||
|
||||
@@ -241,3 +242,52 @@ TEST(array_utils, DeduplicateOrdered3)
|
||||
}
|
||||
|
||||
#undef DEDUPLICATE_ORDERED_TEST
|
||||
|
||||
static void find_all_ranges_test(const blender::Span<bool> data,
|
||||
const blender::Span<blender::IndexRange> data_cmp)
|
||||
{
|
||||
using namespace blender;
|
||||
Vector<IndexRange> ranges = array_utils::find_all_ranges(data, true);
|
||||
EXPECT_EQ(ranges.size(), data_cmp.size());
|
||||
EXPECT_EQ_ARRAY(data_cmp.data(), ranges.as_span().data(), data_cmp.size());
|
||||
}
|
||||
|
||||
TEST(array_utils, FindAllRanges1)
|
||||
{
|
||||
using namespace blender;
|
||||
const std::array data = {false};
|
||||
Vector<IndexRange> ranges = array_utils::find_all_ranges(Span(data.data(), data.size()), true);
|
||||
EXPECT_EQ(ranges.size(), 0);
|
||||
}
|
||||
|
||||
TEST(array_utils, FindAllRanges2)
|
||||
{
|
||||
using namespace blender;
|
||||
const std::array data = {true, true, true};
|
||||
const std::array data_cmp = {IndexRange(0, 3)};
|
||||
find_all_ranges_test(data, data_cmp);
|
||||
}
|
||||
|
||||
TEST(array_utils, FindAllRanges3)
|
||||
{
|
||||
using namespace blender;
|
||||
const std::array data = {true, false};
|
||||
const std::array data_cmp = {IndexRange(0, 1)};
|
||||
find_all_ranges_test(data, data_cmp);
|
||||
}
|
||||
|
||||
TEST(array_utils, FindAllRanges4)
|
||||
{
|
||||
using namespace blender;
|
||||
const std::array data = {false, true};
|
||||
const std::array data_cmp = {IndexRange(1, 1)};
|
||||
find_all_ranges_test(data, data_cmp);
|
||||
}
|
||||
|
||||
TEST(array_utils, FindAllRanges5)
|
||||
{
|
||||
using namespace blender;
|
||||
const std::array data = {true, false, false, true, true, false, true};
|
||||
const std::array data_cmp = {IndexRange(0, 1), IndexRange(3, 2), IndexRange(6, 1)};
|
||||
find_all_ranges_test(data, data_cmp);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user