33 const float3 ray_dir = positions[last_index] - positions[first_index];
36 lambda =
math::dot(ray_dir, positions[index] - positions[first_index]) /
39 const T &from = attribute_data[first_index];
40 const T &to = attribute_data[last_index];
41 const T &value = attribute_data[index];
57 points_to_delete.
slice(range).
fill(
false);
64 if (sub_range.
size() < 3) {
69 float max_dist = -1.0f;
71 for (
const int64_t index : inside_range) {
73 positions, attribute_data, sub_range.
first(), sub_range.
last(), index);
74 if (dist > max_dist) {
76 max_index = index - sub_range.
first();
80 if (max_dist > epsilon) {
83 stack.
push(sub_range.
slice(0, max_index + 1));
84 stack.
push(sub_range.
slice(max_index, sub_range.
size() - max_index));
88 points_to_delete.
slice(inside_range).
fill(
true);
101 points_to_delete.
as_span(),
true);
104 for (const IndexRange range : selection_ranges.as_span().slice(range_of_ranges)) {
105 ramer_douglas_peucker(range, positions, epsilon, attribute_data, points_to_delete);
110 const int points_num = positions.size();
111 if (cyclic && points_num > 2) {
113 positions, attribute_data, points_num - 2, 0, points_num - 1);
114 if (dist <= epsilon) {
115 points_to_delete[points_num - 1] =
true;
123 const GSpan attribute_data,
127 bke::attribute_math::convert_to_static_type(attribute_data.
type(), [&](
auto dummy) {
128 using T = decltype(dummy);
129 if constexpr (std::is_same_v<T, float> || std::is_same_v<T, float2> ||
130 std::is_same_v<T, float3>)
132 curve_simplify(positions, cyclic, epsilon, attribute_data.typed<T>(), points_to_delete);
142 const GSpan attribute_data,
145 Array<bool> points_to_delete(positions.size(),
false);
146 if (epsilon <= 0.0f) {
147 return IndexMask::from_bools(points_to_delete, memory);
149 bke::curves::fill_points(
150 points_by_curve, curves_selection,
true, points_to_delete.
as_mutable_span());
152 const IndexRange points = points_by_curve[curve_i];
153 bke::attribute_math::convert_to_static_type(attribute_data.
type(), [&](
auto dummy) {
154 using T = decltype(dummy);
155 if constexpr (std::is_same_v<T, float> || std::is_same_v<T, float2> ||
156 std::is_same_v<T, float3>)
158 curve_simplify(positions.slice(points),
161 attribute_data.typed<T>().slice(points),
162 points_to_delete.as_mutable_span().slice(points));
166 return IndexMask::from_bools(points_to_delete, memory);
Low-level operations for curves.
MutableSpan< T > as_mutable_span()
const CPPType & type() const
constexpr int64_t first() const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr IndexRange slice(int64_t start, int64_t size) const
constexpr IndexRange drop_front(int64_t n) const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr void fill(const T &value) const
constexpr Span< T > as_span() const
void push(const T &value)
IndexRange index_range() const
void foreach_index(Fn &&fn) const
Vector< IndexRange > find_all_ranges(const Span< T > span, const T &value)
float perpendicular_distance(const Span< float3 > positions, const Span< T > attribute_data, const int64_t first_index, const int64_t last_index, const int64_t index)
static void ramer_douglas_peucker(const IndexRange range, const Span< float3 > positions, const float epsilon, const Span< T > attribute_data, MutableSpan< bool > points_to_delete)
IndexMask simplify_curve_attribute(const Span< float3 > positions, const IndexMask &curves_selection, const OffsetIndices< int > points_by_curve, const VArray< bool > &cyclic, float epsilon, GSpan attribute_data, IndexMaskMemory &memory)
void curve_simplify(const Span< float3 > positions, const bool cyclic, const float epsilon, const GSpan attribute_data, MutableSpan< bool > points_to_delete)
T distance(const T &a, const T &b)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T interpolate(const T &a, const T &b, const FactorT &t)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))