MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ evaluate_planar()

void MayaFlux::Kinesis::CurveEvaluator::evaluate_planar ( std::span< const double >  control_points,
size_t  dim,
Eigen::Index  num_samples,
std::vector< double > &  out,
std::vector< double > &  tangents 
)

Evaluate a curve into coordinate-major position and tangent buffers.

Parameters
control_pointsPoint-major, dim * control_count doubles.
dimCoordinate count per point, at least 1.
num_samplesOutput sample count, at least 2.
outResized to dim * num_samples, coordinate-major.
tangentsResized to dim * num_samples, coordinate-major.

A sample's state is its position and its direction, so both are produced together: the basis fold already yields the polynomial coefficients, and differentiating them is a scale by power feeding the same Horner kernel one degree lower. Callers that ignore tangents pay one extra pass over the parameter buffer already in cache.

tangents holds the derivative with respect to the segment parameter, so it is a direction and not a rate: its magnitude is not comparable across segments and changes under arc length reparameterization. At a cusp or a repeated control point the derivative is zero, and consumers must fall back to a difference of neighbouring positions there.

control_points must not alias out or tangents.

Definition at line 734 of file MotionCurves.cpp.

740{
741 if (num_samples < 2) {
742 error<std::invalid_argument>(
745 std::source_location::current(),
746 "num_samples must be at least 2, but got {}",
747 num_samples);
748 }
749
750 if (dim == 0) {
751 error<std::invalid_argument>(
754 std::source_location::current(),
755 "dim must be at least 1");
756 }
757
758 const auto control_count = static_cast<Eigen::Index>(control_points.size() / dim);
759
760 if (control_count < 2) {
761 error<std::invalid_argument>(
764 std::source_location::current(),
765 "Need at least 2 control points, but got {}",
766 control_count);
767 }
768
769 if (m_points_per_segment == 0) {
770 error<std::invalid_argument>(
773 std::source_location::current(),
774 "Unsupported interpolation mode: {}",
775 static_cast<int>(m_mode));
776 }
777
778 if (!m_supports_multi && control_count != m_points_per_segment) {
779 error<std::invalid_argument>(
782 std::source_location::current(),
783 "{} interpolation requires exactly {} control points, but got {}",
784 static_cast<int>(m_mode), m_points_per_segment, control_count);
785 }
786
787 Eigen::Index active_count = 0;
788 const double* active = extend(control_points, dim, active_count);
789
790 const Eigen::Index num_segments = compute_num_segments(
791 active_count, m_points_per_segment, m_overlap);
792
793 if (num_segments < 1) {
794 error<std::invalid_argument>(
797 std::source_location::current(),
798 "Need sufficient control points for multi-segment {} interpolation, but got {}",
799 static_cast<int>(m_mode), control_count);
800 }
801
802 const auto stride = static_cast<size_t>(num_samples);
803 out.resize(dim * stride);
804 tangents.resize(dim * stride);
805
806 build_chunks(num_samples, num_segments, active_count);
807
808 const Eigen::Index pps = m_points_per_segment;
809 const bool trig = m_trigonometric;
810 const double* basis = m_basis.data();
811 double* out_base = out.data();
812 double* tan_base = tangents.data();
813
814 if (m_chunks.size() > 1 && num_samples >= k_parallel_min_samples) {
815 std::for_each(std::execution::par_unseq, m_chunks.begin(), m_chunks.end(),
816 [&](const CurveChunk& chunk) {
817 const auto count = static_cast<size_t>(chunk.sample_count);
818 std::vector<double> params(count);
819 fill_parameters(params.data(), chunk, num_samples, num_segments);
820
821 const auto offset = static_cast<size_t>(chunk.sample_begin);
822 double* dst = out_base + offset;
823 double* tan = tan_base + offset;
824
825 if (trig) {
826 evaluate_chunk_cosine(active, chunk.start_col, params.data(),
827 dim, count, dst, stride);
828 evaluate_chunk_cosine_derivative(active, chunk.start_col, params.data(),
829 dim, count, tan, stride);
830 return;
831 }
832
833 std::vector<double> folded(dim * static_cast<size_t>(pps));
834 fold_controls(active, chunk.start_col, dim, pps, basis, folded.data());
835
836 evaluate_chunk_polynomial(folded.data(), params.data(),
837 dim, pps, count, dst, stride);
838
839 std::vector<double> dfolded(dim * static_cast<size_t>(pps - 1));
840 fold_derivative(folded.data(), dim, pps, dfolded.data());
841
842 evaluate_chunk_polynomial(dfolded.data(), params.data(),
843 dim, pps - 1, count, tan, stride);
844 });
845
846 return;
847 }
848
849 for (const CurveChunk& chunk : m_chunks) {
850 const auto count = static_cast<size_t>(chunk.sample_count);
851
852 m_tbuf.resize(count);
853 fill_parameters(m_tbuf.data(), chunk, num_samples, num_segments);
854
855 const auto offset = static_cast<size_t>(chunk.sample_begin);
856 double* dst = out_base + offset;
857 double* tan = tan_base + offset;
858
859 if (trig) {
860 evaluate_chunk_cosine(active, chunk.start_col, m_tbuf.data(),
861 dim, count, dst, stride);
862 evaluate_chunk_cosine_derivative(active, chunk.start_col, m_tbuf.data(),
863 dim, count, tan, stride);
864 continue;
865 }
866
867 m_folded.resize(dim * static_cast<size_t>(pps));
868 fold_controls(active, chunk.start_col, dim, pps, basis, m_folded.data());
869
870 evaluate_chunk_polynomial(m_folded.data(), m_tbuf.data(),
871 dim, pps, count, dst, stride);
872
873 m_dfolded.resize(dim * static_cast<size_t>(pps - 1));
874 fold_derivative(m_folded.data(), dim, pps, m_dfolded.data());
875
876 evaluate_chunk_polynomial(m_dfolded.data(), m_tbuf.data(),
877 dim, pps - 1, count, tan, stride);
878 }
879}
uint64_t offset
Definition Composite.cpp:10
uint32_t * dst
std::vector< float > * out
size_t count
const double * extend(std::span< const double > control_points, size_t dim, Eigen::Index &count)
void build_chunks(Eigen::Index num_samples, Eigen::Index num_segments, Eigen::Index active_count)
std::vector< CurveChunk > m_chunks
@ Runtime
General runtime operations (default fallback)
@ Kinesis
General mathematical and physics algorithns.

References build_chunks(), count, dst, extend(), MayaFlux::Journal::Kinesis, m_basis, m_chunks, m_mode, m_overlap, m_points_per_segment, m_supports_multi, m_trigonometric, out, MayaFlux::Journal::Runtime, and MayaFlux::Kinesis::CurveChunk::start_col.

Referenced by MayaFlux::Nodes::GpuSync::TopologyGeneratorNode::build_interpolated_path(), and MayaFlux::Nodes::GpuSync::PathGeneratorNode::write_curve_segment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: