Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenlib/tests/BLI_length_parameterize_test.cc
| /* SPDX-License-Identifier: Apache-2.0 */ | /* SPDX-License-Identifier: Apache-2.0 */ | ||||
| #include "BLI_array.hh" | #include "BLI_array.hh" | ||||
| #include "BLI_length_parameterize.hh" | #include "BLI_length_parameterize.hh" | ||||
| #include "BLI_vector.hh" | #include "BLI_vector.hh" | ||||
| #include "testing/testing.h" | #include "testing/testing.h" | ||||
| namespace blender::length_parameterize::tests { | namespace blender::length_parameterize::tests { | ||||
| template<typename T> Array<float> calculate_lengths(const Span<T> values, const bool cyclic) | template<typename T> Array<float> calculate_lengths(const Span<T> values, const bool cyclic) | ||||
| { | { | ||||
| Array<float> lengths(lengths_num(values.size(), cyclic)); | Array<float> lengths(segments_num(values.size(), cyclic)); | ||||
| accumulate_lengths<T>(values, cyclic, lengths); | accumulate_lengths<T>(values, cyclic, lengths); | ||||
| return lengths; | return lengths; | ||||
| } | } | ||||
| template<typename T> void test_uniform_lengths(const Span<T> values) | template<typename T> void test_uniform_lengths(const Span<T> values) | ||||
| { | { | ||||
| const float segment_length = math::distance(values.first(), values.last()) / (values.size() - 1); | const float segment_length = math::distance(values.first(), values.last()) / (values.size() - 1); | ||||
| for (const int i : values.index_range().drop_back(1)) { | for (const int i : values.index_range().drop_back(1)) { | ||||
| EXPECT_NEAR(math::distance(values[i], values[i + 1]), segment_length, 1e-5); | EXPECT_NEAR(math::distance(values[i], values[i + 1]), segment_length, 1e-5); | ||||
| } | } | ||||
| } | } | ||||
| TEST(length_parameterize, FloatSimple) | TEST(length_parameterize, FloatSimple) | ||||
| { | { | ||||
| Array<float> values{{0, 1, 4}}; | Array<float> values{{0, 1, 4}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), false); | Array<float> lengths = calculate_lengths(values.as_span(), false); | ||||
| Array<int> indices(4); | Array<int> indices(4); | ||||
| Array<float> factors(4); | Array<float> factors(4); | ||||
| create_uniform_samples(lengths, false, indices, factors); | sample_uniform(lengths, true, indices, factors); | ||||
| Array<float> results(4); | Array<float> results(4); | ||||
| linear_interpolation<float>(values, indices, factors, results); | linear_interpolation<float>(values, indices, factors, results); | ||||
| Array<float> expected({ | Array<float> expected({ | ||||
| 0.0f, | 0.0f, | ||||
| 1.33333f, | 1.33333f, | ||||
| 2.66667f, | 2.66667f, | ||||
| 4.0f, | 4.0f, | ||||
| }); | }); | ||||
| for (const int i : results.index_range()) { | for (const int i : results.index_range()) { | ||||
| EXPECT_NEAR(results[i], expected[i], 1e-5); | EXPECT_NEAR(results[i], expected[i], 1e-5); | ||||
| } | } | ||||
| test_uniform_lengths(results.as_span()); | test_uniform_lengths(results.as_span()); | ||||
| } | } | ||||
| TEST(length_parameterize, Float) | TEST(length_parameterize, Float) | ||||
| { | { | ||||
| Array<float> values{{1, 2, 3, 5, 10}}; | Array<float> values{{1, 2, 3, 5, 10}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), false); | Array<float> lengths = calculate_lengths(values.as_span(), false); | ||||
| Array<int> indices(20); | Array<int> indices(20); | ||||
| Array<float> factors(20); | Array<float> factors(20); | ||||
| create_uniform_samples(lengths, false, indices, factors); | sample_uniform(lengths, true, indices, factors); | ||||
| Array<float> results(20); | Array<float> results(20); | ||||
| linear_interpolation<float>(values, indices, factors, results); | linear_interpolation<float>(values, indices, factors, results); | ||||
| Array<float> expected({ | Array<float> expected({ | ||||
| 1.0f, 1.47368f, 1.94737f, 2.42105f, 2.89474f, 3.36842f, 3.84211f, | 1.0f, 1.47368f, 1.94737f, 2.42105f, 2.89474f, 3.36842f, 3.84211f, | ||||
| 4.31579f, 4.78947f, 5.26316f, 5.73684f, 6.21053f, 6.68421f, 7.1579f, | 4.31579f, 4.78947f, 5.26316f, 5.73684f, 6.21053f, 6.68421f, 7.1579f, | ||||
| 7.63158f, 8.10526f, 8.57895f, 9.05263f, 9.52632f, 10.0f, | 7.63158f, 8.10526f, 8.57895f, 9.05263f, 9.52632f, 10.0f, | ||||
| }); | }); | ||||
| for (const int i : results.index_range()) { | for (const int i : results.index_range()) { | ||||
| EXPECT_NEAR(results[i], expected[i], 1e-5); | EXPECT_NEAR(results[i], expected[i], 1e-5); | ||||
| } | } | ||||
| test_uniform_lengths(results.as_span()); | test_uniform_lengths(results.as_span()); | ||||
| } | } | ||||
| TEST(length_parameterize, Float2) | TEST(length_parameterize, Float2) | ||||
| { | { | ||||
| Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), false); | Array<float> lengths = calculate_lengths(values.as_span(), false); | ||||
| Array<int> indices(12); | Array<int> indices(12); | ||||
| Array<float> factors(12); | Array<float> factors(12); | ||||
| create_uniform_samples(lengths, false, indices, factors); | sample_uniform(lengths, true, indices, factors); | ||||
| Array<float2> results(12); | Array<float2> results(12); | ||||
| linear_interpolation<float2>(values, indices, factors, results); | linear_interpolation<float2>(values, indices, factors, results); | ||||
| Array<float2> expected({ | Array<float2> expected({ | ||||
| {0.0f, 0.0f}, | {0.0f, 0.0f}, | ||||
| {0.272727f, 0.0f}, | {0.272727f, 0.0f}, | ||||
| {0.545455f, 0.0f}, | {0.545455f, 0.0f}, | ||||
| {0.818182f, 0.0f}, | {0.818182f, 0.0f}, | ||||
| {1.0f, 0.0909091f}, | {1.0f, 0.0909091f}, | ||||
| Show All 13 Lines | |||||
| TEST(length_parameterize, Float2Cyclic) | TEST(length_parameterize, Float2Cyclic) | ||||
| { | { | ||||
| Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), true); | Array<float> lengths = calculate_lengths(values.as_span(), true); | ||||
| Array<int> indices(12); | Array<int> indices(12); | ||||
| Array<float> factors(12); | Array<float> factors(12); | ||||
| create_uniform_samples(lengths, true, indices, factors); | sample_uniform(lengths, false, indices, factors); | ||||
| Array<float2> results(12); | Array<float2> results(12); | ||||
| linear_interpolation<float2>(values, indices, factors, results); | linear_interpolation<float2>(values, indices, factors, results); | ||||
| Array<float2> expected({ | Array<float2> expected({ | ||||
| {0.0f, 0.0f}, | {0.0f, 0.0f}, | ||||
| {0.333333f, 0.0f}, | {0.333333f, 0.0f}, | ||||
| {0.666667f, 0.0f}, | {0.666667f, 0.0f}, | ||||
| {1.0f, 0.0f}, | {1.0f, 0.0f}, | ||||
| {1.0f, 0.333333f}, | {1.0f, 0.333333f}, | ||||
| Show All 13 Lines | |||||
| TEST(length_parameterize, LineMany) | TEST(length_parameterize, LineMany) | ||||
| { | { | ||||
| Array<float> values{{1, 2}}; | Array<float> values{{1, 2}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), false); | Array<float> lengths = calculate_lengths(values.as_span(), false); | ||||
| Array<int> indices(5007); | Array<int> indices(5007); | ||||
| Array<float> factors(5007); | Array<float> factors(5007); | ||||
| create_uniform_samples(lengths, false, indices, factors); | sample_uniform(lengths, true, indices, factors); | ||||
| Array<float> results(5007); | Array<float> results(5007); | ||||
| linear_interpolation<float>(values, indices, factors, results); | linear_interpolation<float>(values, indices, factors, results); | ||||
| Array<float> expected({ | Array<float> expected({ | ||||
| 1.9962f, 1.9964f, 1.9966f, 1.9968f, 1.997f, 1.9972f, 1.9974f, 1.9976f, 1.9978f, 1.998f, | 1.9962f, 1.9964f, 1.9966f, 1.9968f, 1.997f, 1.9972f, 1.9974f, 1.9976f, 1.9978f, 1.998f, | ||||
| 1.9982f, 1.9984f, 1.9986f, 1.9988f, 1.999f, 1.9992f, 1.9994f, 1.9996f, 1.9998f, 2.0f, | 1.9982f, 1.9984f, 1.9986f, 1.9988f, 1.999f, 1.9992f, 1.9994f, 1.9996f, 1.9998f, 2.0f, | ||||
| }); | }); | ||||
| for (const int i : expected.index_range()) { | for (const int i : expected.index_range()) { | ||||
| EXPECT_NEAR(results.as_span().take_back(20)[i], expected[i], 1e-5); | EXPECT_NEAR(results.as_span().take_back(20)[i], expected[i], 1e-5); | ||||
| } | } | ||||
| } | } | ||||
| TEST(length_parameterize, CyclicMany) | TEST(length_parameterize, CyclicMany) | ||||
| { | { | ||||
| Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), true); | Array<float> lengths = calculate_lengths(values.as_span(), true); | ||||
| Array<int> indices(5007); | Array<int> indices(5007); | ||||
| Array<float> factors(5007); | Array<float> factors(5007); | ||||
| create_uniform_samples(lengths, true, indices, factors); | sample_uniform(lengths, false, indices, factors); | ||||
| Array<float2> results(5007); | Array<float2> results(5007); | ||||
| linear_interpolation<float2>(values, indices, factors, results); | linear_interpolation<float2>(values, indices, factors, results); | ||||
| Array<float2> expected({ | Array<float2> expected({ | ||||
| {0, 0.0159776}, {0, 0.0151787}, {0, 0.0143797}, {0, 0.013581}, {0, 0.0127821}, | {0, 0.0159776}, {0, 0.0151787}, {0, 0.0143797}, {0, 0.013581}, {0, 0.0127821}, | ||||
| {0, 0.0119832}, {0, 0.0111842}, {0, 0.0103855}, {0, 0.00958657}, {0, 0.00878763}, | {0, 0.0119832}, {0, 0.0111842}, {0, 0.0103855}, {0, 0.00958657}, {0, 0.00878763}, | ||||
| {0, 0.00798869}, {0, 0.00718999}, {0, 0.00639105}, {0, 0.00559211}, {0, 0.00479317}, | {0, 0.00798869}, {0, 0.00718999}, {0, 0.00639105}, {0, 0.00559211}, {0, 0.00479317}, | ||||
| {0, 0.00399446}, {0, 0.00319552}, {0, 0.00239658}, {0, 0.00159764}, {0, 0.000798941}, | {0, 0.00399446}, {0, 0.00319552}, {0, 0.00239658}, {0, 0.00159764}, {0, 0.000798941}, | ||||
| }); | }); | ||||
| for (const int i : expected.index_range()) { | for (const int i : expected.index_range()) { | ||||
| EXPECT_NEAR(results.as_span().take_back(20)[i].x, expected[i].x, 1e-5); | EXPECT_NEAR(results.as_span().take_back(20)[i].x, expected[i].x, 1e-5); | ||||
| EXPECT_NEAR(results.as_span().take_back(20)[i].y, expected[i].y, 1e-5); | EXPECT_NEAR(results.as_span().take_back(20)[i].y, expected[i].y, 1e-5); | ||||
| } | } | ||||
| } | } | ||||
| TEST(length_parameterize, InterpolateColor) | TEST(length_parameterize, InterpolateColor) | ||||
| { | { | ||||
| Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), true); | Array<float> lengths = calculate_lengths(values.as_span(), true); | ||||
| Array<ColorGeometry4f> colors{{{0, 0, 0, 1}, {1, 0, 0, 1}, {1, 1, 0, 1}, {0, 1, 0, 1}}}; | Array<ColorGeometry4f> colors{{{0, 0, 0, 1}, {1, 0, 0, 1}, {1, 1, 0, 1}, {0, 1, 0, 1}}}; | ||||
| Array<int> indices(10); | Array<int> indices(10); | ||||
| Array<float> factors(10); | Array<float> factors(10); | ||||
| create_uniform_samples(lengths, true, indices, factors); | sample_uniform(lengths, false, indices, factors); | ||||
| Array<ColorGeometry4f> results(10); | Array<ColorGeometry4f> results(10); | ||||
| linear_interpolation<ColorGeometry4f>(colors, indices, factors, results); | linear_interpolation<ColorGeometry4f>(colors, indices, factors, results); | ||||
| Array<ColorGeometry4f> expected({ | Array<ColorGeometry4f> expected({ | ||||
| {0, 0, 0, 1}, | {0, 0, 0, 1}, | ||||
| {0.4, 0, 0, 1}, | {0.4, 0, 0, 1}, | ||||
| {0.8, 0, 0, 1}, | {0.8, 0, 0, 1}, | ||||
| {1, 0.2, 0, 1}, | {1, 0.2, 0, 1}, | ||||
| {1, 0.6, 0, 1}, | {1, 0.6, 0, 1}, | ||||
| Show All 14 Lines | |||||
| TEST(length_parameterize, ArbitraryFloatSimple) | TEST(length_parameterize, ArbitraryFloatSimple) | ||||
| { | { | ||||
| Array<float> values{{0, 1, 4}}; | Array<float> values{{0, 1, 4}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), false); | Array<float> lengths = calculate_lengths(values.as_span(), false); | ||||
| Array<float> sample_lengths{{0.5f, 1.5f, 2.0f, 4.0f}}; | Array<float> sample_lengths{{0.5f, 1.5f, 2.0f, 4.0f}}; | ||||
| Array<int> indices(4); | Array<int> indices(4); | ||||
| Array<float> factors(4); | Array<float> factors(4); | ||||
| create_samples_from_sorted_lengths(lengths, sample_lengths, false, indices, factors); | sample_at_lengths(lengths, sample_lengths, indices, factors); | ||||
| Array<float> results(4); | Array<float> results(4); | ||||
| linear_interpolation<float>(values, indices, factors, results); | linear_interpolation<float>(values, indices, factors, results); | ||||
| results.as_span().print_as_lines("results"); | results.as_span().print_as_lines("results"); | ||||
| Array<float> expected({ | Array<float> expected({ | ||||
| 0.5f, | 0.5f, | ||||
| 1.5f, | 1.5f, | ||||
| 2.0f, | 2.0f, | ||||
| 4.0f, | 4.0f, | ||||
| }); | }); | ||||
| for (const int i : results.index_range()) { | for (const int i : results.index_range()) { | ||||
| EXPECT_NEAR(results[i], expected[i], 1e-5); | EXPECT_NEAR(results[i], expected[i], 1e-5); | ||||
| } | } | ||||
| } | } | ||||
| TEST(length_parameterize, ArbitraryFloat2) | TEST(length_parameterize, ArbitraryFloat2) | ||||
| { | { | ||||
| Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | ||||
| Array<float> lengths = calculate_lengths(values.as_span(), true); | Array<float> lengths = calculate_lengths(values.as_span(), true); | ||||
| Array<float> sample_lengths{ | Array<float> sample_lengths{ | ||||
| {0.5f, 1.5f, 2.0f, 2.0f, 2.1f, 2.5f, 3.5f, 3.6f, 3.8f, 3.85f, 3.90f, 4.0f}}; | {0.5f, 1.5f, 2.0f, 2.0f, 2.1f, 2.5f, 3.5f, 3.6f, 3.8f, 3.85f, 3.90f, 4.0f}}; | ||||
| Array<int> indices(12); | Array<int> indices(12); | ||||
| Array<float> factors(12); | Array<float> factors(12); | ||||
| create_samples_from_sorted_lengths(lengths, sample_lengths, true, indices, factors); | sample_at_lengths(lengths, sample_lengths, indices, factors); | ||||
| Array<float2> results(12); | Array<float2> results(12); | ||||
| linear_interpolation<float2>(values, indices, factors, results); | linear_interpolation<float2>(values, indices, factors, results); | ||||
| results.as_span().print_as_lines("results"); | results.as_span().print_as_lines("results"); | ||||
| Array<float2> expected({ | Array<float2> expected({ | ||||
| {0.5f, 0.0f}, | {0.5f, 0.0f}, | ||||
| {1.0f, 0.5f}, | {1.0f, 0.5f}, | ||||
| {1.0f, 1.0f}, | {1.0f, 1.0f}, | ||||
| {1.0f, 1.0f}, | {1.0f, 1.0f}, | ||||
| Show All 16 Lines | |||||