54 std::atomic<bool> success =
false;
56 const IndexRange points = src_points_by_curve[curve_i];
58 const bool is_cyclic = src_cyclic[curve_i];
59 const float epsilon = thresholds[curve_i];
63 const bool use_first_as_corner = !
is_cyclic && !corners[points.
first()];
64 const bool use_last_as_corner = !
is_cyclic && !corners[points.
last()];
66 if (use_first_as_corner) {
69 if (points.
size() > 2) {
70 for (const int i : IndexRange::from_begin_end(1, points.size() - 1)) {
71 if (corners[points[i]]) {
72 src_corners.append(i);
76 if (use_last_as_corner) {
77 src_corners.append(points.last());
79 const uint *src_corners_ptr = src_corners.is_empty() ?
81 reinterpret_cast<uint *
>(src_corners.data());
85 float *cubic_array =
nullptr;
88 uint32_t *corner_index_array =
nullptr;
89 uint32_t corner_index_array_size = 0;
92 error = curve_fit_cubic_to_points_fl(curve_positions.cast<
float>().data(),
93 curve_positions.size(),
103 &corner_index_array_size);
106 error = curve_fit_cubic_to_points_refit_fl(curve_positions.cast<
float>().data(),
107 curve_positions.size(),
119 &corner_index_array_size);
124 dst_curve_sizes[curve_i] = points.
size();
129 success.store(
true, std::memory_order_relaxed);
131 const int dst_points_num = cubic_array_size;
134 dst_curve_sizes[curve_i] = dst_points_num;
139 corner_indices_per_curve[
pos] =
MutableSpan<int>(
reinterpret_cast<int *
>(corner_index_array),
140 corner_index_array_size);
141 original_indices_per_curve[
pos] =
MutableSpan<int>(
reinterpret_cast<int *
>(orig_index_map),
152 dst_curves.resize(dst_curves.offsets().last(), dst_curves.curves_num());
154 const Span<float3> src_handles_left = src_curves.handle_positions_left();
155 const Span<float3> src_handles_right = src_curves.handle_positions_right();
156 const VArraySpan<int8_t> src_handle_types_left = src_curves.handle_types_left();
157 const VArraySpan<int8_t> src_handle_types_right = src_curves.handle_types_right();
159 MutableSpan<float3> dst_positions = dst_curves.positions_for_write();
160 MutableSpan<float3> dst_handles_left = dst_curves.handle_positions_left_for_write();
161 MutableSpan<float3> dst_handles_right = dst_curves.handle_positions_right_for_write();
162 MutableSpan<int8_t> dst_handle_types_left = dst_curves.handle_types_left_for_write();
163 MutableSpan<int8_t> dst_handle_types_right = dst_curves.handle_types_right_for_write();
166 if (!src_handles_left.is_empty()) {
174 src_points_by_curve, dst_points_by_curve, unselected_curves, src_positions, dst_positions);
175 if (!src_handles_right.is_empty()) {
182 if (!src_handle_types_left.is_empty()) {
186 src_handle_types_left,
187 dst_handle_types_left);
189 if (!src_handle_types_right.is_empty()) {
193 src_handle_types_right,
194 dst_handle_types_right);
197 Array<int> old_by_new_map(dst_curves.points_num());
198 unselected_curves.foreach_index(GrainSize(1024), [&](
const int64_t curve_i) {
199 const IndexRange src_points = src_points_by_curve[curve_i];
200 const IndexRange dst_points = dst_points_by_curve[curve_i];
206 curve_selection.foreach_index(GrainSize(1024), [&](
const int64_t curve_i,
const int64_t pos) {
207 const IndexRange src_points = src_points_by_curve[curve_i];
208 const IndexRange dst_points = dst_points_by_curve[curve_i];
209 MutableSpan<float3> positions = dst_positions.slice(dst_points);
210 MutableSpan<int> old_by_new = old_by_new_map.as_mutable_span().slice(dst_points);
214 BLI_assert(src_points.size() == dst_points.size());
215 positions.copy_from(src_positions.slice(src_points));
216 dst_handles_left.slice(dst_points).copy_from(src_positions.slice(src_points));
217 dst_handles_right.slice(dst_points).copy_from(src_positions.slice(src_points));
224 const Span<float3> cubic_array = cubic_array_per_curve[
pos];
225 BLI_assert(dst_points.size() * 3 == cubic_array.size());
226 MutableSpan<float3> left_handles = dst_handles_left.slice(dst_points);
227 MutableSpan<float3> right_handles = dst_handles_right.slice(dst_points);
229 for (const int i : range) {
230 const int index = i * 3;
231 positions[i] = cubic_array[index + 1];
232 left_handles[i] = cubic_array[index];
233 right_handles[i] = cubic_array[index + 2];
237 const Span<int> corner_indices = corner_indices_per_curve[
pos];
240 dst_handle_types_left.slice(dst_points).fill_indices(corner_indices,
BEZIER_HANDLE_FREE);
241 dst_handle_types_right.slice(dst_points).fill_indices(corner_indices,
BEZIER_HANDLE_FREE);
243 const Span<int> original_indices = original_indices_per_curve[
pos];
245 for (const int i : range) {
246 old_by_new[i] = src_points[original_indices[i]];
251 dst_curves.update_curve_types();
253 bke::gather_attributes(
254 src_curves.attributes(),
255 bke::AttrDomain::Point,
256 bke::AttrDomain::Point,
257 bke::attribute_filter_with_skip_ref(
259 {
"position",
"handle_left",
"handle_right",
"handle_type_left",
"handle_type_right"}),
261 dst_curves.attributes_for_write());
264 for (MutableSpan<float3> cubic_array : cubic_array_per_curve) {
265 free(cubic_array.data());
267 for (MutableSpan<int> corner_indices : corner_indices_per_curve) {
268 free(corner_indices.data());
270 for (MutableSpan<int> original_indices : original_indices_per_curve) {
271 free(original_indices.data());