Resample path vertices for arc-length parameterization.
Uses piecewise linear arc length estimation. Output vertices have constant spacing along curve.
455{
456 if (path_vertices.size() < 2 || num_samples < 2) {
457 return path_vertices;
458 }
459
460 std::vector<float> arc_lengths;
461 arc_lengths.reserve(path_vertices.size());
462 arc_lengths.push_back(0.0F);
463
464 float total_length = 0.0F;
465 for (size_t i = 1; i < path_vertices.size(); ++i) {
466 float segment_length = glm::distance(
469 total_length += segment_length;
470 arc_lengths.push_back(total_length);
471 }
472
473 if (total_length < 1e-6F) {
474 return path_vertices;
475 }
476
477 std::vector<Kakshya::LineVertex> resampled;
478 resampled.reserve(num_samples);
479
480 for (size_t i = 0; i < num_samples; ++i) {
481 float target_length = (static_cast<float>(i) / static_cast<float>(num_samples - 1)) * total_length;
482
483 auto it = std::ranges::lower_bound(arc_lengths, target_length);
484 size_t idx = std::distance(arc_lengths.begin(), it);
485
486 if (idx == 0) {
487 resampled.push_back(path_vertices[0]);
488 } else if (idx >= path_vertices.size()) {
489 resampled.push_back(path_vertices.back());
490 } else {
491 float s0 = arc_lengths[idx - 1];
492 float s1 = arc_lengths[idx];
493 float t = (target_length - s0) / (s1 - s0);
494
495 glm::vec3 p0 = path_vertices[idx - 1].position;
496 glm::vec3 p1 = path_vertices[idx].position;
497 glm::vec3
position = glm::mix(p0, p1, t);
498
499 glm::vec3 c0 = path_vertices[idx - 1].color;
500 glm::vec3 c1 = path_vertices[idx].color;
501 glm::vec3
color = glm::mix(c0, c1, t);
502
503 resampled.push_back({ .position =
position,
505 .thickness = 1.0F });
506 }
507 }
508
509 return resampled;
510}
std::optional< glm::vec3 > position