250 GMutableSpan sampled_values =
params.uninitialized_single_output_if_required(5,
"Value");
252 auto return_default = [&]() {
253 if (!sampled_positions.
is_empty()) {
256 if (!sampled_tangents.is_empty()) {
259 if (!sampled_normals.is_empty()) {
279 if (!sampled_tangents.is_empty()) {
282 if (!sampled_normals.is_empty()) {
288 const VArray<int> curve_indices =
params.readonly_single_input<
int>(0,
"Curve Index");
298 if (!sampled_positions.
is_empty()) {
301 if (!sampled_tangents.is_empty()) {
304 if (!sampled_normals.is_empty()) {
307 if (!sampled_values.is_empty()) {
309 using T = decltype(dummy);
310 index_mask::masked_fill<T>(sampled_values.typed<T>(), {},
mask);
315 auto sample_curve = [&](
const int curve_i,
const IndexMask &
mask) {
316 const IndexRange evaluated_points = evaluated_points_by_curve[curve_i];
317 if (evaluated_points.
size() == 1) {
318 if (!sampled_positions.is_empty()) {
320 sampled_positions, evaluated_positions[evaluated_points.
first()],
mask);
322 if (!sampled_tangents.is_empty()) {
324 sampled_tangents, evaluated_tangents[evaluated_points.
first()],
mask);
326 if (!sampled_normals.is_empty()) {
328 sampled_normals, evaluated_normals[evaluated_points.
first()],
mask);
330 if (!sampled_values.is_empty()) {
332 using T = decltype(dummy);
333 const T &value = source_data_->typed<T>()[points_by_curve[curve_i].first()];
334 index_mask::masked_fill<T>(sampled_values.typed<T>(), value, mask);
340 const Span<float> accumulated_lengths = curves.evaluated_lengths_for_curve(curve_i,
342 if (accumulated_lengths.is_empty()) {
351 factors.reinitialize(
mask.size());
353 accumulated_lengths, lengths, length_mode_,
mask,
indices, factors);
355 if (!sampled_positions.is_empty()) {
357 evaluated_positions.slice(evaluated_points),
363 if (!sampled_tangents.is_empty()) {
365 evaluated_tangents.slice(evaluated_points),
indices, factors,
mask, sampled_tangents);
367 [&](
const int i) { sampled_tangents[i] =
math::normalize(sampled_tangents[i]); });
369 if (!sampled_normals.is_empty()) {
371 evaluated_normals.slice(evaluated_points),
indices, factors,
mask, sampled_normals);
373 [&](
const int i) { sampled_normals[i] =
math::normalize(sampled_normals[i]); });
375 if (!sampled_values.is_empty()) {
376 const IndexRange points = points_by_curve[curve_i];
377 src_original_values.reinitialize(points.size());
379 src_evaluated_values.reinitialize(evaluated_points.
size());
380 curves.interpolate_to_evaluated(curve_i, src_original_values, src_evaluated_values);
382 using T = decltype(dummy);
383 const Span<T> src_evaluated_values_typed = src_evaluated_values.as_span().typed<T>();
384 MutableSpan<T> sampled_values_typed = sampled_values.typed<T>();
385 length_parameterize::interpolate_to_masked<T>(
386 src_evaluated_values_typed, indices, factors, mask, sampled_values_typed);
391 if (
const std::optional<int> curve_i = curve_indices.get_if_single()) {
392 if (curves.curves_range().contains(*curve_i)) {
393 sample_curve(*curve_i,
mask);
402 VectorSet<int> used_curves;
404 mask.foreach_index([&](
const int i) {
405 const int curve_i = curve_indices[i];
406 if (curves.curves_range().contains(curve_i)) {
407 used_curves.add(curve_i);
408 valid_indices.append(i);
411 invalid_indices.append(i);
416 IndexMaskMemory memory;
417 const IndexMask valid_indices_mask = valid_indices.size() ==
mask.size() ?
421 Array<IndexMask> mask_by_curve(used_curves.size());
425 [&](
const int i) {
return used_curves.index_of(curve_indices[i]); },
428 for (
const int i : mask_by_curve.index_range()) {
429 sample_curve(used_curves[i], mask_by_curve[i]);