Skip to content

Commit a0e1ca9

Browse files
Curve Fit - Performance Improvement
The Animation Curve "Simplify" tool's performance has been improved by using a stateful interpolator design, so that that expensive results are pre-computed, and then reused for each point interpolation. The internal memory of the interpolator is also reused to avoid memory fragmentation.
1 parent 0ecf67c commit a0e1ca9

4 files changed

Lines changed: 305 additions & 146 deletions

File tree

lib/rust/mmscenegraph/src/math/curve_fit.rs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -401,36 +401,27 @@ impl CurveFitLinearNPointsProblem {
401401
let reference_values: Vec<(f64, f64)> = reference_curve.to_vec();
402402
debug!("reference_values.len()={}", reference_values.len());
403403

404+
let interpolator = Interpolator::from_method(interpolation_method);
405+
interpolator.set_control_points_x(&control_points_x);
406+
404407
Ok(Self {
405408
reference_values,
406409
control_points_x,
407-
interpolator: Interpolator::from_method(interpolation_method),
410+
interpolator,
408411
})
409412
}
410413

411414
fn parameter_count(&self) -> usize {
412415
self.control_points_x.len()
413416
}
414417

415-
fn interpolate_y_value_at_x(
416-
&self,
417-
value_x: f64,
418-
control_points_y: &[f64],
419-
) -> f64 {
420-
self.interpolator.interpolate(
421-
value_x,
422-
&self.control_points_x,
423-
control_points_y,
424-
)
425-
}
426-
427418
fn residuals(&self, control_points_y: &[f64]) -> Vec<f64> {
419+
self.interpolator.set_control_points_y(control_points_y);
428420
self.reference_values
429421
.iter()
430422
.map(|&(value_x, data_y)| {
431-
let curve_y =
432-
self.interpolate_y_value_at_x(value_x, control_points_y);
433-
(curve_y - data_y).abs()
423+
let value_y = self.interpolator.interpolate(value_x);
424+
(value_y - data_y).abs()
434425
})
435426
.collect()
436427
}
@@ -571,10 +562,17 @@ pub fn nonlinear_line_n_points_with_initial(
571562
y_values.len(),
572563
"X and Y values must match length."
573564
);
574-
assert!(
575-
x_initial_control_points.len() >= 3,
576-
"Must have at least 3 control points."
577-
);
565+
if interpolation_method == InterpolationMethod::CubicNUBS {
566+
assert!(
567+
x_initial_control_points.len() >= 4,
568+
"Must have at least 4 control points for InterpolationMethod::CubicNUBS."
569+
);
570+
} else {
571+
assert!(
572+
x_initial_control_points.len() >= 3,
573+
"Must have at least 3 control points for InterpolationMethod::Linear or InterpolationMethod::CubicSpline."
574+
);
575+
}
578576
assert_eq!(
579577
x_initial_control_points.len(),
580578
y_initial_control_points.len(),
@@ -645,10 +643,18 @@ pub fn nonlinear_line_n_points(
645643
assert_eq!(x_values.len(), y_values.len());
646644
let value_count = x_values.len();
647645
assert!(value_count > 2);
648-
assert!(
649-
control_point_count >= 3,
650-
"Must have at least 3 control points"
651-
);
646+
647+
if interpolation == InterpolationMethod::CubicNUBS {
648+
assert!(
649+
control_point_count >= 4,
650+
"Must have at least 4 control points for InterpolationMethod::CubicNUBS."
651+
);
652+
} else {
653+
assert!(
654+
control_point_count >= 3,
655+
"Must have at least 3 control points for InterpolationMethod::Linear or InterpolationMethod::CubicSpline."
656+
);
657+
}
652658

653659
let mut point_x = 0.0;
654660
let mut point_y = 0.0;

0 commit comments

Comments
 (0)