refactor plotting. made cli display in gui.
This commit is contained in:
parent
0998cd8aeb
commit
9ba3aa0ab4
|
|
@ -1,5 +1,5 @@
|
||||||
use std::{iter, ops::Add};
|
|
||||||
use crate::message::{self, Message};
|
use crate::message::{self, Message};
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
pub fn encrypt_message(message: &mut Message, circle_length: &usize) -> Vec<Circle> {
|
pub fn encrypt_message(message: &mut Message, circle_length: &usize) -> Vec<Circle> {
|
||||||
encode_circles(
|
encode_circles(
|
||||||
|
|
@ -8,13 +8,13 @@ pub fn encrypt_message(message: &mut Message, circle_length: &usize) -> Vec<Circ
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn caesar_shift(char: char, shift: u8) -> char {
|
fn caesar_shift(char: &char, shift: &u8) -> char {
|
||||||
shift.wrapping_add(char as u8) as char
|
shift.wrapping_add(*char as u8) as char
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Circle = Vec<message::Triple>;
|
pub type Circle = Vec<message::Triple>;
|
||||||
|
|
||||||
pub fn circle_to_points(circle: Circle) -> Vec<f64> {
|
pub fn circle_to_points(circle: &Circle) -> Vec<f64> {
|
||||||
circle.iter().flat_map(|triple| {
|
circle.iter().flat_map(|triple| {
|
||||||
vec![
|
vec![
|
||||||
triple.first as u8 as f64,
|
triple.first as u8 as f64,
|
||||||
|
|
@ -44,11 +44,11 @@ fn encode_circles(circles: &mut Vec<Circle>, shift: &mut u8) -> Vec<Circle> {
|
||||||
0 => circle_iter.skip(1),
|
0 => circle_iter.skip(1),
|
||||||
_ => circle_iter.skip(0),
|
_ => circle_iter.skip(0),
|
||||||
}.map(|triple| {
|
}.map(|triple| {
|
||||||
triple.first = caesar_shift(triple.first, *shift);
|
triple.first = caesar_shift(&triple.first, shift);
|
||||||
*shift = shift.wrapping_add_signed(shift_delta);
|
*shift = shift.wrapping_add_signed(shift_delta);
|
||||||
triple.second = caesar_shift(triple.second, *shift);
|
triple.second = caesar_shift(&triple.second, shift);
|
||||||
*shift = shift.wrapping_add_signed(shift_delta);
|
*shift = shift.wrapping_add_signed(shift_delta);
|
||||||
triple.second = caesar_shift(triple.third, *shift);
|
triple.second = caesar_shift(&triple.third, shift);
|
||||||
*shift = shift.wrapping_add_signed(shift_delta);
|
*shift = shift.wrapping_add_signed(shift_delta);
|
||||||
|
|
||||||
triple.clone()
|
triple.clone()
|
||||||
|
|
|
||||||
29
src/gui.rs
29
src/gui.rs
|
|
@ -0,0 +1,29 @@
|
||||||
|
struct PlotDisplay {
|
||||||
|
circles: Vec<crate::Circle>,
|
||||||
|
circle_length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlotDisplay {
|
||||||
|
fn new(circles: Vec<crate::Circle>, circle_length: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
circles,
|
||||||
|
circle_length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl eframe::App for PlotDisplay { //TODO: Define axis ranges
|
||||||
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
crate::plot(ui, &mut self.circles, &self.circle_length);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn display_plot(circles: Vec<crate::Circle>) -> Result<(), eframe::Error> {
|
||||||
|
let options = eframe::NativeOptions::default();
|
||||||
|
eframe::run_native("Encoded Message", options, Box::new(|_cc| Ok(Box::<PlotDisplay>::new(
|
||||||
|
PlotDisplay::new(circles, 1000)
|
||||||
|
))))
|
||||||
|
}
|
||||||
28
src/lib.rs
28
src/lib.rs
|
|
@ -1,14 +1,11 @@
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
mod cli;
|
||||||
mod encoding;
|
mod encoding;
|
||||||
|
mod gui;
|
||||||
mod message;
|
mod message;
|
||||||
pub mod plotting;
|
mod plotting;
|
||||||
|
|
||||||
pub use message::Message;
|
|
||||||
pub use encoding::encrypt_message;
|
|
||||||
pub use encoding::circle_to_points;
|
|
||||||
pub use encoding::Circle;
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
|
|
@ -26,9 +23,26 @@ pub struct Args {
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Gui,
|
Gui,
|
||||||
|
Encode {
|
||||||
|
#[command(subcommand)]
|
||||||
|
output: OutputMode,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum OutputMode {
|
||||||
Display,
|
Display,
|
||||||
Save {
|
Save {
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
path: PathBuf
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub use encoding::encrypt_message;
|
||||||
|
pub use encoding::circle_to_points;
|
||||||
|
pub use encoding::Circle;
|
||||||
|
pub use gui::display_plot;
|
||||||
|
pub use message::Message;
|
||||||
|
pub use plotting::plot;
|
||||||
|
|
||||||
|
|
|
||||||
52
src/main.rs
52
src/main.rs
|
|
@ -1,52 +0,0 @@
|
||||||
use circle_cipher::{encrypt_message, plotting};
|
|
||||||
use eframe::egui;
|
|
||||||
use egui_plot::{Plot, PlotPoints};
|
|
||||||
|
|
||||||
struct MyApp {
|
|
||||||
circles: Vec<circle_cipher::Circle>,
|
|
||||||
cicrle_length: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MyApp {
|
|
||||||
fn new(circles: Vec<circle_cipher::Circle>, cicrle_length: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
circles,
|
|
||||||
cicrle_length,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl eframe::App for MyApp { //TODO: Define axis ranges
|
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
|
||||||
Plot::new("Polar Plot")
|
|
||||||
.height(500.0)
|
|
||||||
.width(500.0)
|
|
||||||
.data_aspect(1.0)
|
|
||||||
.view_aspect(1.0)
|
|
||||||
.show(ui, |plot_ui| {
|
|
||||||
self.circles.iter().enumerate().for_each(|(count, circle)| {
|
|
||||||
plot_ui.line(egui_plot::Line::new(
|
|
||||||
plotting::plot(ctx, _frame,
|
|
||||||
self.cicrle_length,
|
|
||||||
circle_cipher::circle_to_points(circle.clone()),
|
|
||||||
count
|
|
||||||
)
|
|
||||||
));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn main() -> Result<(), eframe::Error> {
|
|
||||||
let mut message = circle_cipher::Message::new("Hello".to_string(), 12);
|
|
||||||
let circles = encrypt_message(&mut message, &127);
|
|
||||||
println!("{:?}", circles.len());
|
|
||||||
|
|
||||||
let options = eframe::NativeOptions::default();
|
|
||||||
eframe::run_native("Polar Plot Example", options, Box::new(|_cc| Ok(Box::<MyApp>::new(
|
|
||||||
MyApp::new(circles, 1000)
|
|
||||||
))))
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
|
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
pub parts: Parts,
|
pub parts: Parts,
|
||||||
pub combined: String,
|
pub combined: String,
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,78 @@
|
||||||
use std::f64::{self, consts::PI, INFINITY, NEG_INFINITY};
|
use egui::Ui;
|
||||||
|
|
||||||
use egui_plot::{Plot, PlotPoints};
|
use egui_plot::{Plot, PlotPoints};
|
||||||
|
use std::f64::{self, consts::PI};
|
||||||
|
|
||||||
pub fn plot(ctx: &egui::Context, _frame: &mut eframe::Frame, num_points: usize, peak_values: Vec<f64>, offset: usize) -> PlotPoints {
|
pub fn plot(ui: &mut Ui, circles: &mut Vec<crate::Circle>, num_points: &usize) {
|
||||||
let baseline_r = 1.0;
|
Plot::new("Encoded Message")
|
||||||
|
.height(500.0)
|
||||||
|
.width(500.0)
|
||||||
|
.data_aspect(1.0)
|
||||||
|
.view_aspect(1.0)
|
||||||
|
.show(ui, |plot_ui| {
|
||||||
|
circles.iter_mut().enumerate().for_each(|(count, circle)| {
|
||||||
|
let points = match count {
|
||||||
|
count if count % 2 == 0 => crate::circle_to_points(circle),
|
||||||
|
_ => {
|
||||||
|
circle.reverse();
|
||||||
|
crate::circle_to_points(circle)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
plot_ui.line(egui_plot::Line::new(
|
||||||
|
gaussian_distribution(num_points, &points, count)
|
||||||
|
));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gaussian_distribution(num_points: &usize, peak_values: &Vec<f64>, offset: &f64) -> PlotPoints {
|
||||||
|
let mut radii: Vec<f64> = vec![1.0; *num_points];
|
||||||
let num_peaks = peak_values.len();
|
let num_peaks = peak_values.len();
|
||||||
|
let peak_angles = generate_peak_angles(&num_peaks);
|
||||||
|
let theta = generate_theta(&num_points);
|
||||||
|
|
||||||
let peak_angles: Vec<f64> = (0..num_peaks)
|
|
||||||
.map(|i| {
|
|
||||||
let angle = 2.0 * PI * (i as f64) / (num_peaks as f64);
|
|
||||||
angle + (PI / 2.0)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
|
|
||||||
let theta: Vec<f64> = (0..num_points)
|
|
||||||
.map(|i| 2.0 * PI * (i as f64) / (num_points as f64))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut r: Vec<f64> = vec![baseline_r; num_points];
|
|
||||||
for (peak_value, peak_angle) in peak_values.iter().zip(peak_angles.iter()) {
|
for (peak_value, peak_angle) in peak_values.iter().zip(peak_angles.iter()) {
|
||||||
let peak_width: f64 = 1.0 / num_points as f64;
|
let peak_width: f64 = 1.0 / *num_points as f64;
|
||||||
for (j, theta_value) in theta.iter().enumerate() {
|
for (j, theta_value) in theta.iter().enumerate() {
|
||||||
let delta = (theta_value - peak_angle + PI).rem_euclid(2.0 * PI) - PI;
|
let delta = (theta_value - peak_angle + PI).rem_euclid(2.0 * PI) - PI;
|
||||||
r[j] += peak_value * (-((delta.powf(2.0)) / (2.0 * peak_width.powf(2.0)))).exp();
|
radii[j] += peak_value * (-((delta.powf(2.0)) / (2.0 * peak_width.powf(2.0)))).exp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let min_r = r.iter().cloned().fold(INFINITY, f64::min);
|
normalize(&mut radii, &offset);
|
||||||
let max_r = r.iter().cloned().fold(NEG_INFINITY, f64::max);
|
|
||||||
|
|
||||||
|
cartesian_to_polar(&radii, &theta)
|
||||||
|
}
|
||||||
|
|
||||||
let r: Vec<f64> = r.iter_mut().map(|value| {
|
fn normalize(radii: &mut Vec<f64>, offset: &f64) -> Vec<f64> {
|
||||||
1.0 + (offset as f64) + (*value - min_r) / (max_r - min_r)
|
let min_r = radii.iter().cloned().fold(f64::INFINITY, f64::min);
|
||||||
}).collect();
|
let max_r = radii.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
|
||||||
|
|
||||||
|
radii.iter_mut().map(|value| {
|
||||||
|
1.0 + offset + (*value - min_r) / (max_r - min_r)
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cartesian_to_polar(radii: &Vec<f64>, theta: &Vec<f64>) -> PlotPoints {
|
||||||
theta.iter()
|
theta.iter()
|
||||||
.zip(r.iter())
|
.zip(radii.iter())
|
||||||
.map(|(&theta, &radius)| {
|
.map(|(&theta, &radius)| {
|
||||||
let x = radius * theta.cos();
|
let x = radius * theta.cos();
|
||||||
let y = radius * theta.sin();
|
let y = radius * theta.sin();
|
||||||
[x, y]
|
[x, y]
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_peak_angles(num_peaks: &usize) -> Vec<f64> {
|
||||||
|
(0..*num_peaks)
|
||||||
|
.map(|i| {
|
||||||
|
let angle = 2.0 * PI * (i as f64) / (*num_peaks as f64);
|
||||||
|
angle + (PI / 2.0)
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_theta(num_points: &usize) -> Vec<f64> {
|
||||||
|
(0..*num_points)
|
||||||
|
.map(|i| 2.0 * PI * (i as f64) / (*num_points as f64))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue