/*
Copyright 2021, 2023-2024 Gabriel Bjørnager Jen-
sen.
This file is part of benoit-cli.
benoit-cli is free software: you can redistrib-
ute it and/or modify it under the terms of the
GNU General Public License as published by the
Free Software Foundation, either version 3 of
the License, or (at your option) any later ver-
sion.
benoit-cli is distributed in the hope that it
will be useful, but WITHOUT ANY WARRANTY; with-
out even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Gene-
ral Public License along with benoit-cli. If
not, see .
*/
use crate::keyframe::Keyframe;
use benoit::complex::Complex;
use rug::Float;
/// Interpolater between keyframes.
///
/// This is done as an iterator over the interpolated values.
#[derive(Clone, Debug)]
pub struct KeyframeInterpolater {
pub(in super) frame: Option,
pub(in super) last_frame: u32,
pub(in super) max_iter_count: u64,
pub(in super) centre: Complex,
pub(in super) seed: Complex,
pub(in super) zoom: Float,
pub(in super) colour_range: f64,
pub(in super) max_iter_count_step: i64,
pub(in super) centre_step: Complex,
pub(in super) seed_step: Complex,
pub(in super) zoom_factor: Float,
pub(in super) colour_range_step: f64,
}
impl KeyframeInterpolater {
/// Advances the contained values to the next step.
///
/// # Panics
///
/// Panics if overflow occurs when calculating the new maximum iteration count.
/// This is guaranteed to not happen as long as the iterator hasn't been completed.
pub(in super) fn advance_values(&mut self) {
self.max_iter_count = self.max_iter_count
.checked_add_signed(self.max_iter_count_step)
.unwrap();
self.centre.real += &self.centre_step.real;
self.centre.imag += &self.centre_step.imag;
self.seed.real += &self.seed_step.real;
self.seed.imag += &self.seed_step.imag;
self.zoom *= &self.zoom_factor;
self.colour_range += self.colour_range_step;
}
}
impl Iterator for KeyframeInterpolater {
type Item = Keyframe;
fn next(&mut self) -> Option {
let frame = self.frame?;
assert!(frame <= self.last_frame);
let keyframe = Keyframe {
frame,
max_iter_count: self.max_iter_count,
centre: self.centre.clone(),
seed: self.seed.clone(),
zoom: self.zoom.clone(),
colour_range: self.colour_range,
};
self.frame = (frame != self.last_frame).then(|| {
self.advance_values();
frame + 0x1
});
Some(keyframe)
}
}