use std::borrow::Borrow;
use std::marker::PhantomData;
use num_traits::{float::FloatConst, Float, ToPrimitive};
use crate::{Continuous, Discrete, TransferFunction};
use super::{FrequencyCharacteristics, FrequencyTransferFunction, FrequencyUnit, Hz};
pub struct BodeDiagramPlotter<T, U = Hz> {
freq_from: T,
dfreq: T,
data_len: usize,
log_scale: bool,
_unit: PhantomData<U>,
}
impl <T, U> BodeDiagramPlotter<T, U>
where
T: Float + FloatConst + ToPrimitive + 'static,
U: FrequencyUnit,
{
pub fn new(freq_from: T, freq_to: T, dfreq: T, log_scale: bool) -> Self {
Self {
freq_from,
dfreq,
data_len: ((freq_to - freq_from) / dfreq).ceil().to_usize().unwrap_or(0),
log_scale,
_unit: PhantomData,
}
}
pub fn plot<G: Into<FrequencyTransferFunction<T>>>(&self, g: G) -> Vec<FrequencyCharacteristics<T, U>> {
let g = g.into();
(0..self.data_len)
.map(|i| g.characteristics(self.freq_from + T::from(i).unwrap() * self.dfreq, self.log_scale))
.collect()
}
pub fn frequency_response_s<S: Borrow<TransferFunction<T, Continuous>>>(&self, tf: S) -> Vec<FrequencyCharacteristics<T, U>> {
self.plot(tf.borrow().frequency_transfer_function())
}
pub fn frequency_response_z<S: Borrow<TransferFunction<T, Discrete>>>(&self, tf: S, ts: T) -> Vec<FrequencyCharacteristics<T, U>> {
self.plot(tf.borrow().frequency_transfer_function(ts))
}
}