コンテンツにスキップ

group

src

振動子毎に, どのパターンの emission を出力するかを選ぶ. 振動子の振り分けは TransducerGroups でキー (enum など) を割り当てて決める. どのキーも割り当てられていない振動子は無出力になる.

合成には 2 つの API がある.

  • group_compute — キー毎にキーと TransducerMask を受け取って計算し, 合成する.
  • group — 計算済みのバッファをキーから選んで合成する. 計算結果を使い回したい場合やグループ毎に並列に計算したい場合に使う.
#[derive(Clone, Copy, PartialEq, Eq)]
enum Side {
Left,
Right,
}
group_compute(
&geometry,
&groups,
|side, mask, buffer| match side {
Side::Left => gspat(
&NalgebraBackend,
&geometry,
&foci,
wavelength,
&GspatOption {
mask,
..Default::default()
},
buffer,
),
Side::Right => {
focus(&geometry, target, wavelength, buffer);
Ok(())
}
},
&mut dst,
)?;
引数 型 説明
geometry &Geometry ジオメトリ
groups &TransducerGroups<K> 振動子毎のキー
compute FnMut(K, TransducerMask, &mut [Vec<Emission>]) -> Result<(), E> キーとマスクを受け取り, 作業バッファへ計算する
dst &mut [Vec<Emission>] 出力バッファ

compute はキー毎に 1 回 (キーの初出順) 呼ばれ, 計算結果のうちそのキーの振動子分だけが dst に書き込まれる. どのキーにも割り当てられていない振動子は無出力 (Emission::NULL) になる.

#[derive(Clone, Copy, PartialEq, Eq)]
enum Side {
Left,
Right,
}
let groups = TransducerGroups::new(&geometry, |device, tr| {
Some(if device.position(tr).x < center.x {
Side::Left
} else {
Side::Right
})
});
group(
&geometry,
&groups,
|side| match side {
Side::Left => &left,
Side::Right => &right,
},
&mut dst,
);
引数 型 説明
geometry &Geometry ジオメトリ
groups &TransducerGroups<K> 振動子毎のキー
source FnMut(K) -> impl AsRef<[Vec<Emission>]> キーから出力元バッファを返す
dst &mut [Vec<Emission>] 出力バッファ

TransducerGroups::new(&geometry, |device, tr| ...) がデバイスと振動子インデックスからキー (None = どのグループにも属さない) を返し, 振動子毎のキーを保持する. キーは Rust では Copy + Eq な型, C# では値型 (struct), Python ではハッシュ可能な値. mask(key) でキー key の振動子だけを有効にした Holo 用の TransducerMaskを取得できる.

use anyhow::Result;
use autd3_rs::geometry::{Autd3, Geometry, TransducerGroups, offset};
use autd3_rs::units::{m, mm, s};
use autd3_rs_pattern::{focus, group_compute, wavelength};
use autd3_rs_pattern_holo::{AmplitudeTarget, GspatOption, NalgebraBackend, Pa, gspat};
#[derive(Clone, Copy, PartialEq, Eq)]
enum Side {
Left,
Right,
}
let geometry = Geometry::new(vec![Autd3::default()]);
let wavelength = wavelength(340.0 * m / s);
let center = geometry.center();
let groups = TransducerGroups::new(&geometry, |device, tr| {
Some(if device.position(tr).x < center.x {
Side::Left
} else {
Side::Right
})
});
let foci = [
AmplitudeTarget {
point: center + offset(-50.0 * mm, 0.0 * mm, 150.0 * mm),
amplitude: 5e3 * Pa,
},
AmplitudeTarget {
point: center + offset(-20.0 * mm, 0.0 * mm, 150.0 * mm),
amplitude: 5e3 * Pa,
},
];
let mut dst = geometry.pattern_buffer();
group_compute(
&geometry,
&groups,
|side, mask, buffer| match side {
Side::Left => gspat(
&NalgebraBackend,
&geometry,
&foci,
wavelength,
&GspatOption {
mask,
..Default::default()
},
buffer,
),
Side::Right => {
focus(
&geometry,
center + offset(40.0 * mm, 0.0 * mm, 150.0 * mm),
wavelength,
buffer,
);
Ok(())
}
},
&mut dst,
)?;