use openigtlink_rust::error::Result;
use openigtlink_rust::io::{ClientBuilder, SyncIgtlClient};
use openigtlink_rust::protocol::message::IgtlMessage;
use openigtlink_rust::protocol::types::{NdArrayMessage, ScalarType};
use std::thread;
use std::time::Duration;
fn main() {
if let Err(e) = run() {
eprintln!("[ERROR] {}", e);
std::process::exit(1);
}
}
fn run() -> Result<()> {
println!("=== NDARRAY Message: Multi-Dimensional Array Transfer ===\n");
let mut client = ClientBuilder::new().tcp("127.0.0.1:18944").sync().build()?;
println!("[INFO] Connected to OpenIGTLink server\n");
println!("[SCENARIO 1] 1D Array - ECG Waveform");
println!(" Transferring cardiac signal data...\n");
send_1d_waveform(&mut client)?;
thread::sleep(Duration::from_secs(1));
println!("\n[SCENARIO 2] 2D Array - Transformation Matrix");
println!(" Transferring 4x4 homogeneous transform...\n");
send_2d_matrix(&mut client)?;
thread::sleep(Duration::from_secs(1));
println!("\n[SCENARIO 3] 3D Array - Lookup Table Volume");
println!(" Transferring color mapping table...\n");
send_3d_lut(&mut client)?;
println!("\n[INFO] All arrays transferred successfully");
Ok(())
}
fn send_1d_waveform(client: &mut SyncIgtlClient) -> Result<()> {
let sample_count = 100;
let mut data = Vec::new();
for i in 0..sample_count {
let t = i as f32 / sample_count as f32;
let value = if t < 0.2 {
0.3 * (t * 5.0 * std::f32::consts::PI).sin() } else if t < 0.4 {
-0.2 } else if t < 0.5 {
5.0 * ((t - 0.4) * 10.0 * std::f32::consts::PI).sin() } else if t < 0.7 {
0.0 } else if t < 0.9 {
0.5 * ((t - 0.7) * 5.0 * std::f32::consts::PI).sin() } else {
0.0 };
data.extend_from_slice(&value.to_be_bytes());
}
let array = NdArrayMessage::new_1d(ScalarType::Float32, data)?;
println!(" Array Properties:");
println!(" Dimensions: 1D");
println!(" Size: [{}]", sample_count);
println!(" Data Type: Float32");
println!(" Total Elements: {}", array.element_count());
println!(" Data Size: {} bytes", array.data_size());
let msg = IgtlMessage::new(array, "ECG_Waveform")?;
client.send(&msg)?;
println!(" ✓ Sent");
Ok(())
}
fn send_2d_matrix(client: &mut SyncIgtlClient) -> Result<()> {
#[rustfmt::skip]
let matrix: [f64; 16] = [
1.0, 0.0, 0.0, 10.0, 0.0, 1.0, 0.0, 20.0, 0.0, 0.0, 1.0, 30.0, 0.0, 0.0, 0.0, 1.0, ];
let mut data = Vec::new();
for &value in &matrix {
data.extend_from_slice(&value.to_be_bytes());
}
let array = NdArrayMessage::new_2d(ScalarType::Float64, 4, 4, data)?;
println!(" Array Properties:");
println!(" Dimensions: 2D");
println!(" Size: [4, 4]");
println!(" Data Type: Float64");
println!(" Total Elements: {}", array.element_count());
println!(" Data Size: {} bytes", array.data_size());
println!(" Represents: Translation (10, 20, 30) mm");
let msg = IgtlMessage::new(array, "TransformMatrix")?;
client.send(&msg)?;
println!(" ✓ Sent");
Ok(())
}
fn send_3d_lut(client: &mut SyncIgtlClient) -> Result<()> {
let lut_size = 16;
let mut data = Vec::new();
for r in 0..lut_size {
for g in 0..lut_size {
let red = ((lut_size - r - 1) * 255 / (lut_size - 1)) as u8;
let green = (g * 255 / (lut_size - 1)) as u8;
let blue = ((r + g) * 255 / (2 * (lut_size - 1))) as u8;
data.push(red);
data.push(green);
data.push(blue);
}
}
let array =
NdArrayMessage::new_3d(ScalarType::Uint8, lut_size as u16, lut_size as u16, 3, data)?;
println!(" Array Properties:");
println!(" Dimensions: 3D");
println!(
" Size: [{}, {}, 3] (height, width, RGB)",
lut_size, lut_size
);
println!(" Data Type: Uint8");
println!(" Total Elements: {}", array.element_count());
println!(" Data Size: {} bytes", array.data_size());
println!(" Represents: RGB color lookup table");
let msg = IgtlMessage::new(array, "ColorLUT")?;
client.send(&msg)?;
println!(" ✓ Sent");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1d_array_creation() {
let data: Vec<u8> = vec![1, 2, 3, 4];
let array = NdArrayMessage::new_1d(ScalarType::Uint8, data).unwrap();
assert_eq!(array.ndim(), 1);
assert_eq!(array.element_count(), 4);
}
#[test]
fn test_2d_array_creation() {
let data = vec![0u8; 16];
let array = NdArrayMessage::new_2d(ScalarType::Uint8, 4, 4, data).unwrap();
assert_eq!(array.ndim(), 2);
assert_eq!(array.size, vec![4, 4]);
assert_eq!(array.element_count(), 16);
}
#[test]
fn test_3d_array_creation() {
let data = vec![0u8; 768];
let array = NdArrayMessage::new_3d(ScalarType::Uint8, 16, 16, 3, data).unwrap();
assert_eq!(array.ndim(), 3);
assert_eq!(array.size, vec![16, 16, 3]);
assert_eq!(array.element_count(), 768);
}
#[test]
fn test_float32_encoding() {
let value = 3.14159f32;
let mut data = Vec::new();
data.extend_from_slice(&value.to_be_bytes());
let array = NdArrayMessage::new_1d(ScalarType::Float32, data.clone()).unwrap();
assert_eq!(array.data, data);
}
#[test]
fn test_scalar_type_sizes() {
assert_eq!(ScalarType::Uint8.size(), 1);
assert_eq!(ScalarType::Float32.size(), 4);
assert_eq!(ScalarType::Float64.size(), 8);
}
}