more helper functions for the Cluster functionality in HexoSynth
This commit is contained in:
parent
b7f544f102
commit
37b57a4472
3 changed files with 144 additions and 1 deletions
|
@ -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) {
|
pub fn as_offs(&self, x: usize) -> (i32, i32) {
|
||||||
let even = x % 2 == 0;
|
let even = x % 2 == 0;
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -36,7 +36,7 @@ use std::collections::{HashMap, HashSet};
|
||||||
///
|
///
|
||||||
/// matrix.sync().unwrap();
|
/// matrix.sync().unwrap();
|
||||||
///```
|
///```
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub struct Cell {
|
pub struct Cell {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
x: u8,
|
x: u8,
|
||||||
|
@ -178,6 +178,20 @@ impl Cell {
|
||||||
(self.x as usize, self.y as usize)
|
(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 {
|
pub fn has_dir_set(&self, dir: CellDir) -> bool {
|
||||||
match dir {
|
match dir {
|
||||||
CellDir::TR => self.out1.is_some(),
|
CellDir::TR => self.out1.is_some(),
|
||||||
|
@ -258,6 +272,8 @@ pub enum MatrixError {
|
||||||
output1: (NodeId, u8),
|
output1: (NodeId, u8),
|
||||||
output2: (NodeId, u8),
|
output2: (NodeId, u8),
|
||||||
},
|
},
|
||||||
|
NonEmptyCell { cell: Cell },
|
||||||
|
PosOutOfRange
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An intermediate data structure to store a single edge in the [Matrix].
|
/// 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.
|
/// Inserts a cell into the hexagonal grid of the matrix.
|
||||||
/// You have to make sure that the resulting DSP graph topology
|
/// You have to make sure that the resulting DSP graph topology
|
||||||
/// does not have cycles, otherwise an upload to the DSP thread via
|
/// does not have cycles, otherwise an upload to the DSP thread via
|
||||||
|
|
|
@ -17,6 +17,12 @@ use crate::log;
|
||||||
use ringbuf::{Producer, Consumer};
|
use ringbuf::{Producer, Consumer};
|
||||||
use std::sync::Arc;
|
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
|
/// Holds the complete allocation of nodes and
|
||||||
/// the program. New Nodes or the program is
|
/// the program. New Nodes or the program is
|
||||||
/// not newly allocated in the audio backend, but it is
|
/// not newly allocated in the audio backend, but it is
|
||||||
|
@ -256,6 +262,8 @@ impl NodeExecutor {
|
||||||
GraphMessage::NewProg { prog, copy_old_out } => {
|
GraphMessage::NewProg { prog, copy_old_out } => {
|
||||||
let mut prev_prog = std::mem::replace(&mut self.prog, prog);
|
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 =
|
self.monitor_signal_cur_inp_indices =
|
||||||
[UNUSED_MONITOR_IDX; MON_SIG_CNT];
|
[UNUSED_MONITOR_IDX; MON_SIG_CNT];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue