diff options
-rw-r--r-- | source/blender/blenkernel/BKE_curves.hh | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curves_geometry.cc | 34 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curves_geometry_test.cc | 22 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_curves_types.h | 1 |
4 files changed, 59 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index 0f2ae8a02a6..96963dcbd8d 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -146,6 +146,8 @@ class CurvesGeometry : public ::CurvesGeometry { MutableSpan<int8_t> curve_types(); bool has_curve_with_type(const CurveType type) const; + /** Return the number of curves with each type. */ + std::array<int, CURVE_TYPES_NUM> count_curve_types() const; MutableSpan<float3> positions(); Span<float3> positions() const; diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 5bb6a97fa49..207d0d173ac 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -277,6 +277,40 @@ bool CurvesGeometry::has_curve_with_type(const CurveType type) const return false; } +std::array<int, CURVE_TYPES_NUM> CurvesGeometry::count_curve_types() const +{ + using CountsType = std::array<int, CURVE_TYPES_NUM>; + + CountsType identity; + identity.fill(0); + + const VArray<int8_t> types = this->curve_types(); + if (types.is_single()) { + identity[types.get_internal_single()] = this->curves_num(); + return identity; + } + + Span<int8_t> types_span = types.get_internal_span(); + return threading::parallel_reduce( + this->curves_range(), + 2048, + identity, + [&](const IndexRange curves_range, const CountsType &init) { + CountsType result = init; + for (const int curve_index : curves_range) { + result[types_span[curve_index]]++; + } + return result; + }, + [](const CountsType &a, const CountsType &b) { + CountsType result = a; + for (const int i : IndexRange(CURVE_TYPES_NUM)) { + result[i] += b[i]; + } + return result; + }); +} + MutableSpan<float3> CurvesGeometry::positions() { this->position = (float(*)[3])CustomData_duplicate_referenced_layer_named( diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc index bc99785de1c..574f90f2e51 100644 --- a/source/blender/blenkernel/intern/curves_geometry_test.cc +++ b/source/blender/blenkernel/intern/curves_geometry_test.cc @@ -63,6 +63,28 @@ TEST(curves_geometry, Move) EXPECT_EQ(second_other.offsets().data(), offsets_data); } +TEST(curves_geometry, TypeCount) +{ + CurvesGeometry curves = create_basic_curves(100, 10); + curves.curve_types().copy_from({ + CURVE_TYPE_BEZIER, + CURVE_TYPE_NURBS, + CURVE_TYPE_NURBS, + CURVE_TYPE_NURBS, + CURVE_TYPE_CATMULL_ROM, + CURVE_TYPE_CATMULL_ROM, + CURVE_TYPE_CATMULL_ROM, + CURVE_TYPE_POLY, + CURVE_TYPE_POLY, + CURVE_TYPE_POLY, + }); + std::array<int, CURVE_TYPES_NUM> counts = curves.count_curve_types(); + EXPECT_EQ(counts[CURVE_TYPE_CATMULL_ROM], 3); + EXPECT_EQ(counts[CURVE_TYPE_POLY], 3); + EXPECT_EQ(counts[CURVE_TYPE_BEZIER], 1); + EXPECT_EQ(counts[CURVE_TYPE_NURBS], 3); +} + TEST(curves_geometry, CatmullRomEvaluation) { CurvesGeometry curves(4, 1); diff --git a/source/blender/makesdna/DNA_curves_types.h b/source/blender/makesdna/DNA_curves_types.h index f1626781fc6..97cc588e639 100644 --- a/source/blender/makesdna/DNA_curves_types.h +++ b/source/blender/makesdna/DNA_curves_types.h @@ -28,6 +28,7 @@ typedef enum CurveType { CURVE_TYPE_BEZIER = 2, CURVE_TYPE_NURBS = 3, } CurveType; +#define CURVE_TYPES_NUM 4 typedef enum HandleType { /** The handle can be moved anywhere, and doesn't influence the point's other handle. */ |