more helper functions for the Cluster functionality in HexoSynth

This commit is contained in:
Weird Constructor 2021-07-31 13:26:10 +02:00
parent b7f544f102
commit 37b57a4472
3 changed files with 144 additions and 1 deletions

View file

@ -73,6 +73,73 @@ impl CellDir {
}
}
pub fn path_from_to(mut a: (usize, usize), b: (usize, usize))
-> Vec<CellDir>
{
let mut path = vec![];
let mut defensive_max : i32 = 1024;
while (a.0 != b.0 || a.1 != b.1) && defensive_max > 0 {
//d// println!("ITER START: A={:?} B={:?}", a, b);
defensive_max -= 1;
let mut min_distance = 99999.0;
let mut min_dir = CellDir::C;
let mut min_new_a = a;
for e in 0..6 {
let dir = Self::from(e);
if let Some(new_pos) = dir.offs_pos(a) {
let dist =
(b.0 as f32 - new_pos.0 as f32).powf(2.0)
+ (b.1 as f32 - new_pos.1 as f32).powf(2.0);
//d// println!("DIST={:5.3} FOR {:?} (B={:?})", dist, new_pos, b);
if dist < min_distance {
min_distance = dist;
min_dir = dir;
min_new_a = new_pos;
}
} else {
//d// println!("NOPOS {:?} {:?}", dir, a);
}
}
if min_distance < 99999.0 {
//d// println!("A={:?} => {:?} DIR={:?} B={:?}", a, min_new_a, min_dir, b);
a = min_new_a;
path.push(min_dir);
} else {
//d// println!("ITER BREAK");
break;
}
//d// println!("ITER END: A={:?} B={:?} MAX={}", a, b, defensive_max);
}
//d// println!("PATH: {:?}", path);
path
}
pub fn offs_pos(&self, pos: (usize, usize)) -> Option<(usize, usize)> {
let offs = self.as_offs(pos.0);
let new_pos = (
pos.0 as i32 + offs.0,
pos.1 as i32 + offs.1
);
if new_pos.0 >= 0 && new_pos.1 >= 0 {
Some((new_pos.0 as usize, new_pos.1 as usize))
} else {
None
}
}
pub fn as_offs(&self, x: usize) -> (i32, i32) {
let even = x % 2 == 0;
match self {

View file

@ -36,7 +36,7 @@ use std::collections::{HashMap, HashSet};
///
/// matrix.sync().unwrap();
///```
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub struct Cell {
node_id: NodeId,
x: u8,
@ -178,6 +178,20 @@ impl Cell {
(self.x as usize, self.y as usize)
}
pub fn offs_dir(&mut self, dir: CellDir) -> bool {
if let Some(new_pos) =
dir.offs_pos((self.x as usize, self.y as usize))
{
self.x = new_pos.0 as u8;
self.y = new_pos.1 as u8;
true
}
else
{
false
}
}
pub fn has_dir_set(&self, dir: CellDir) -> bool {
match dir {
CellDir::TR => self.out1.is_some(),
@ -258,6 +272,8 @@ pub enum MatrixError {
output1: (NodeId, u8),
output2: (NodeId, u8),
},
NonEmptyCell { cell: Cell },
PosOutOfRange
}
/// An intermediate data structure to store a single edge in the [Matrix].
@ -443,6 +459,58 @@ impl Matrix {
}
}
/// Like [Matrix::change_matrix] but the function passed to this
/// needs to return a `Result<(), MatrixError>`.
pub fn change_matrix_err<F>(&mut self, mut f: F)
-> Result<(), MatrixError>
where F: FnMut(&mut Self) -> Result<(), MatrixError>
{
self.save_matrix();
if let Err(e) = f(self) {
self.restore_matrix();
return Err(e);
}
if let Err(e) = self.check() {
self.restore_matrix();
Err(e)
} else {
Ok(())
}
}
/// Tries to place all `cells` at once, if they are placed in empty
/// cells only! Returns an error of the destination cell is not empty
/// or out of range, or if the placement of the cluster results in any
/// other inconsistencies.
///
/// This action must be wrapped with [Matrix::change_matrix_err]!
///
/// Restores the matrix to the previous state if placing fails.
pub fn place_multiple(&mut self, cells: &[Cell]) -> Result<(), MatrixError> {
for cell in cells {
let x = cell.pos().0;
let y = cell.pos().1;
if let Some(existing) = self.get(x, y) {
if !existing.is_empty() {
return Err(MatrixError::NonEmptyCell { cell: *existing });
}
self.place(x, y, *cell);
} else {
return Err(MatrixError::PosOutOfRange);
}
}
if let Err(e) = self.check() {
Err(e)
} else {
Ok(())
}
}
/// Inserts a cell into the hexagonal grid of the matrix.
/// You have to make sure that the resulting DSP graph topology
/// does not have cycles, otherwise an upload to the DSP thread via

View file

@ -17,6 +17,12 @@ use crate::log;
use ringbuf::{Producer, Consumer};
use std::sync::Arc;
use core::arch::x86_64::{
_MM_FLUSH_ZERO_ON,
_MM_SET_FLUSH_ZERO_MODE,
// _MM_GET_FLUSH_ZERO_MODE
};
/// Holds the complete allocation of nodes and
/// the program. New Nodes or the program is
/// not newly allocated in the audio backend, but it is
@ -256,6 +262,8 @@ impl NodeExecutor {
GraphMessage::NewProg { prog, copy_old_out } => {
let mut prev_prog = std::mem::replace(&mut self.prog, prog);
unsafe { _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); }
self.monitor_signal_cur_inp_indices =
[UNUSED_MONITOR_IDX; MON_SIG_CNT];