BLI: Add a reverse method to MutableSpan
Add a method that allows a MutableSpan to reverse itself. This reverses the data in the original span object. This is a first step in extracting some functionality from nodes and making it more general. Differential Revision: https://developer.blender.org/D12485
This commit is contained in:
@@ -643,6 +643,16 @@ template<typename T> class MutableSpan {
|
||||
return MutableSpan(data_ + size_ - new_size, new_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the data in the MutableSpan.
|
||||
*/
|
||||
constexpr void reverse()
|
||||
{
|
||||
for (const int i : IndexRange(size_ / 2)) {
|
||||
std::swap(data_[size_ - 1 - i], data_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an (immutable) Span that references the same array. This is usually not needed,
|
||||
* due to implicit conversions. However, sometimes automatic type deduction needs some help.
|
||||
|
@@ -362,6 +362,29 @@ TEST(span, ReverseIterator)
|
||||
EXPECT_EQ_ARRAY(reversed_vec.data(), Span({7, 6, 5, 4}).data(), 4);
|
||||
}
|
||||
|
||||
TEST(span, ReverseMutableSpan)
|
||||
{
|
||||
std::array<int, 0> src0 = {};
|
||||
MutableSpan<int> span0 = src0;
|
||||
span0.reverse();
|
||||
EXPECT_EQ_ARRAY(span0.data(), Span<int>({}).data(), 0);
|
||||
|
||||
std::array<int, 1> src1 = {4};
|
||||
MutableSpan<int> span1 = src1;
|
||||
span1.reverse();
|
||||
EXPECT_EQ_ARRAY(span1.data(), Span<int>({4}).data(), 1);
|
||||
|
||||
std::array<int, 2> src2 = {4, 5};
|
||||
MutableSpan<int> span2 = src2;
|
||||
span2.reverse();
|
||||
EXPECT_EQ_ARRAY(span2.data(), Span<int>({5, 4}).data(), 2);
|
||||
|
||||
std::array<int, 5> src5 = {4, 5, 6, 7, 8};
|
||||
MutableSpan<int> span5 = src5;
|
||||
span5.reverse();
|
||||
EXPECT_EQ_ARRAY(span5.data(), Span<int>({8, 7, 6, 5, 4}).data(), 5);
|
||||
}
|
||||
|
||||
TEST(span, MutableReverseIterator)
|
||||
{
|
||||
std::array<int, 4> src = {4, 5, 6, 7};
|
||||
|
@@ -29,31 +29,6 @@ static void geo_node_curve_reverse_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::Geometry>("Curve");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the data in a MutableSpan object.
|
||||
*/
|
||||
template<typename T> static void reverse_data(MutableSpan<T> r_data)
|
||||
{
|
||||
const int size = r_data.size();
|
||||
for (const int i : IndexRange(size / 2)) {
|
||||
std::swap(r_data[size - 1 - i], r_data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse and Swap the data between 2 MutableSpans.
|
||||
*/
|
||||
template<typename T> static void reverse_data(MutableSpan<T> left, MutableSpan<T> right)
|
||||
{
|
||||
BLI_assert(left.size() == right.size());
|
||||
const int size = left.size();
|
||||
|
||||
for (const int i : IndexRange(size / 2 + size % 2)) {
|
||||
std::swap(left[i], right[size - 1 - i]);
|
||||
std::swap(right[i], left[size - 1 - i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
|
||||
{
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
|
||||
@@ -78,9 +53,9 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
|
||||
continue;
|
||||
}
|
||||
|
||||
reverse_data<float3>(splines[i]->positions());
|
||||
reverse_data<float>(splines[i]->radii());
|
||||
reverse_data<float>(splines[i]->tilts());
|
||||
splines[i]->positions().reverse();
|
||||
splines[i]->radii().reverse();
|
||||
splines[i]->tilts().reverse();
|
||||
|
||||
splines[i]->attributes.foreach_attribute(
|
||||
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
|
||||
@@ -92,7 +67,7 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
|
||||
}
|
||||
attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
reverse_data(output_attribute->typed<T>());
|
||||
output_attribute->typed<T>().reverse();
|
||||
});
|
||||
return true;
|
||||
},
|
||||
@@ -100,12 +75,17 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
|
||||
|
||||
/* Deal with extra info on derived types. */
|
||||
if (BezierSpline *spline = dynamic_cast<BezierSpline *>(splines[i].get())) {
|
||||
reverse_data<BezierSpline::HandleType>(spline->handle_types_left());
|
||||
reverse_data<BezierSpline::HandleType>(spline->handle_types_right());
|
||||
reverse_data<float3>(spline->handle_positions_left(), spline->handle_positions_right());
|
||||
spline->handle_types_left().reverse();
|
||||
spline->handle_types_right().reverse();
|
||||
|
||||
spline->handle_positions_left().reverse();
|
||||
spline->handle_positions_right().reverse();
|
||||
for (int i : spline->handle_positions_left().index_range()) {
|
||||
std::swap(spline->handle_positions_left()[i], spline->handle_positions_right()[i]);
|
||||
}
|
||||
}
|
||||
else if (NURBSpline *spline = dynamic_cast<NURBSpline *>(splines[i].get())) {
|
||||
reverse_data<float>(spline->weights());
|
||||
spline->weights().reverse();
|
||||
}
|
||||
/* Nothing to do for poly splines. */
|
||||
|
||||
|
Reference in New Issue
Block a user