BLI: Add utility to find true/false mix in boolean array
This is useful for #108014, when determining whether there are any sharp faces and edges in a mesh.
This commit is contained in:
parent
ba3f26fac5
commit
c9dac7e77c
|
@ -141,4 +141,16 @@ inline void gather(const VArray<T> &src,
|
|||
|
||||
void invert_booleans(MutableSpan<bool> span);
|
||||
|
||||
enum class BooleanMix {
|
||||
None,
|
||||
AllFalse,
|
||||
AllTrue,
|
||||
Mixed,
|
||||
};
|
||||
BooleanMix booleans_mix_calc(const VArray<bool> &varray, IndexRange range_to_check);
|
||||
inline BooleanMix booleans_mix_calc(const VArray<bool> &varray)
|
||||
{
|
||||
return booleans_mix_calc(varray, varray.index_range());
|
||||
}
|
||||
|
||||
} // namespace blender::array_utils
|
||||
|
|
|
@ -52,4 +52,55 @@ void invert_booleans(MutableSpan<bool> span)
|
|||
});
|
||||
}
|
||||
|
||||
BooleanMix booleans_mix_calc(const VArray<bool> &varray, const IndexRange range_to_check)
|
||||
{
|
||||
if (varray.is_empty()) {
|
||||
return BooleanMix::None;
|
||||
}
|
||||
const CommonVArrayInfo info = varray.common_info();
|
||||
if (info.type == CommonVArrayInfo::Type::Single) {
|
||||
return *static_cast<const bool *>(info.data) ? BooleanMix::AllTrue : BooleanMix::AllFalse;
|
||||
}
|
||||
if (info.type == CommonVArrayInfo::Type::Span) {
|
||||
const Span<bool> span(static_cast<const bool *>(info.data), varray.size());
|
||||
return threading::parallel_reduce(
|
||||
range_to_check,
|
||||
4096,
|
||||
BooleanMix::None,
|
||||
[&](const IndexRange range, const BooleanMix init) {
|
||||
if (init == BooleanMix::Mixed) {
|
||||
return init;
|
||||
}
|
||||
|
||||
const Span<bool> slice = span.slice(range);
|
||||
const bool first = slice.first();
|
||||
for (const bool value : slice.drop_front(1)) {
|
||||
if (value != first) {
|
||||
return BooleanMix::Mixed;
|
||||
}
|
||||
}
|
||||
return first ? BooleanMix::AllTrue : BooleanMix::AllFalse;
|
||||
},
|
||||
[&](BooleanMix a, BooleanMix b) { return (a == b) ? a : BooleanMix::Mixed; });
|
||||
}
|
||||
return threading::parallel_reduce(
|
||||
range_to_check,
|
||||
2048,
|
||||
BooleanMix::None,
|
||||
[&](const IndexRange range, const BooleanMix init) {
|
||||
if (init == BooleanMix::Mixed) {
|
||||
return init;
|
||||
}
|
||||
/* Alternatively, this could use #materialize to retrieve many values at once. */
|
||||
const bool first = varray[range.first()];
|
||||
for (const int64_t i : range.drop_front(1)) {
|
||||
if (varray[i] != first) {
|
||||
return BooleanMix::Mixed;
|
||||
}
|
||||
}
|
||||
return first ? BooleanMix::AllTrue : BooleanMix::AllFalse;
|
||||
},
|
||||
[&](BooleanMix a, BooleanMix b) { return (a == b) ? a : BooleanMix::Mixed; });
|
||||
}
|
||||
|
||||
} // namespace blender::array_utils
|
||||
|
|
Loading…
Reference in New Issue