From a6adb7ecaef38e419d9268074193942669be6e7f Mon Sep 17 00:00:00 2001 From: Johnny Matthews Date: Wed, 15 Sep 2021 11:13:10 -0500 Subject: 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 --- source/blender/blenlib/BLI_span.hh | 10 +++++ source/blender/blenlib/tests/BLI_span_test.cc | 23 +++++++++++ .../nodes/geometry/nodes/node_geo_curve_reverse.cc | 46 ++++++---------------- 3 files changed, 46 insertions(+), 33 deletions(-) (limited to 'source') diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh index e04295b0e51..5adb47ba0b0 100644 --- a/source/blender/blenlib/BLI_span.hh +++ b/source/blender/blenlib/BLI_span.hh @@ -643,6 +643,16 @@ template 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. diff --git a/source/blender/blenlib/tests/BLI_span_test.cc b/source/blender/blenlib/tests/BLI_span_test.cc index 4d23a53c08a..fb88fb63e53 100644 --- a/source/blender/blenlib/tests/BLI_span_test.cc +++ b/source/blender/blenlib/tests/BLI_span_test.cc @@ -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 src0 = {}; + MutableSpan span0 = src0; + span0.reverse(); + EXPECT_EQ_ARRAY(span0.data(), Span({}).data(), 0); + + std::array src1 = {4}; + MutableSpan span1 = src1; + span1.reverse(); + EXPECT_EQ_ARRAY(span1.data(), Span({4}).data(), 1); + + std::array src2 = {4, 5}; + MutableSpan span2 = src2; + span2.reverse(); + EXPECT_EQ_ARRAY(span2.data(), Span({5, 4}).data(), 2); + + std::array src5 = {4, 5, 6, 7, 8}; + MutableSpan span5 = src5; + span5.reverse(); + EXPECT_EQ_ARRAY(span5.data(), Span({8, 7, 6, 5, 4}).data(), 5); +} + TEST(span, MutableReverseIterator) { std::array src = {4, 5, 6, 7}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc index 2cb75eda202..70bb9bd28f4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc @@ -29,31 +29,6 @@ static void geo_node_curve_reverse_declare(NodeDeclarationBuilder &b) b.add_output("Curve"); } -/** - * Reverse the data in a MutableSpan object. - */ -template static void reverse_data(MutableSpan 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 static void reverse_data(MutableSpan left, MutableSpan 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("Curve"); @@ -78,9 +53,9 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params) continue; } - reverse_data(splines[i]->positions()); - reverse_data(splines[i]->radii()); - reverse_data(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()); + output_attribute->typed().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(splines[i].get())) { - reverse_data(spline->handle_types_left()); - reverse_data(spline->handle_types_right()); - reverse_data(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(splines[i].get())) { - reverse_data(spline->weights()); + spline->weights().reverse(); } /* Nothing to do for poly splines. */ -- cgit v1.2.3