The logic can be much simpler when curves are selected rather than points, because then we just copy all of the points in each curve. Like some other operators, implement both cases.
85 lines
2.7 KiB
C++
85 lines
2.7 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "BLI_array_utils.hh"
|
|
#include "BLI_offset_indices.hh"
|
|
#include "BLI_task.hh"
|
|
|
|
namespace blender::offset_indices {
|
|
|
|
OffsetIndices<int> accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets,
|
|
const int start_offset)
|
|
{
|
|
int offset = start_offset;
|
|
for (const int i : counts_to_offsets.index_range().drop_back(1)) {
|
|
const int count = counts_to_offsets[i];
|
|
BLI_assert(count >= 0);
|
|
counts_to_offsets[i] = offset;
|
|
offset += count;
|
|
}
|
|
counts_to_offsets.last() = offset;
|
|
return OffsetIndices<int>(counts_to_offsets);
|
|
}
|
|
|
|
void fill_constant_group_size(const int size, const int start_offset, MutableSpan<int> offsets)
|
|
{
|
|
threading::parallel_for(offsets.index_range(), 1024, [&](const IndexRange range) {
|
|
for (const int64_t i : range) {
|
|
offsets[i] = size * i + start_offset;
|
|
}
|
|
});
|
|
}
|
|
|
|
void copy_group_sizes(const OffsetIndices<int> offsets,
|
|
const IndexMask &mask,
|
|
MutableSpan<int> sizes)
|
|
{
|
|
mask.foreach_index_optimized<int64_t>(GrainSize(4096),
|
|
[&](const int64_t i) { sizes[i] = offsets[i].size(); });
|
|
}
|
|
|
|
void gather_group_sizes(const OffsetIndices<int> offsets,
|
|
const IndexMask &mask,
|
|
MutableSpan<int> sizes)
|
|
{
|
|
mask.foreach_index_optimized<int64_t>(GrainSize(4096), [&](const int64_t i, const int64_t pos) {
|
|
sizes[pos] = offsets[i].size();
|
|
});
|
|
}
|
|
|
|
OffsetIndices<int> gather_selected_offsets(const OffsetIndices<int> src_offsets,
|
|
const IndexMask &selection,
|
|
const int start_offset,
|
|
MutableSpan<int> dst_offsets)
|
|
{
|
|
if (selection.is_empty()) {
|
|
return {};
|
|
}
|
|
int offset = start_offset;
|
|
selection.foreach_index_optimized<int>([&](const int i, const int pos) {
|
|
dst_offsets[pos] = offset;
|
|
offset += src_offsets[i].size();
|
|
});
|
|
dst_offsets.last() = offset;
|
|
return OffsetIndices<int>(dst_offsets);
|
|
}
|
|
|
|
void build_reverse_map(OffsetIndices<int> offsets, MutableSpan<int> r_map)
|
|
{
|
|
threading::parallel_for(offsets.index_range(), 1024, [&](const IndexRange range) {
|
|
for (const int64_t i : range) {
|
|
r_map.slice(offsets[i]).fill(i);
|
|
}
|
|
});
|
|
}
|
|
|
|
void build_reverse_offsets(const Span<int> indices, MutableSpan<int> offsets)
|
|
{
|
|
BLI_assert(std::all_of(offsets.begin(), offsets.end(), [](int value) { return value == 0; }));
|
|
array_utils::count_indices(indices, offsets);
|
|
offset_indices::accumulate_counts_to_offsets(offsets);
|
|
}
|
|
|
|
} // namespace blender::offset_indices
|