1use crate::geometric::GA3;
25use crate::projection::Projection;
26use crate::transforms::{Rotor, Transform, Translation, Versor};
27use amari_core::{Bivector, Vector};
28use std::sync::{Arc, Mutex};
29
30type SubscriberList = Arc<Mutex<Vec<Box<dyn Fn(&GA3) + Send + Sync>>>>;
32
33#[derive(Clone)]
42pub struct GeometricState {
43 inner: Arc<Mutex<GA3>>,
45 subscribers: SubscriberList,
47}
48
49impl GeometricState {
50 pub fn new(mv: GA3) -> Self {
52 Self {
53 inner: Arc::new(Mutex::new(mv)),
54 subscribers: Arc::new(Mutex::new(Vec::new())),
55 }
56 }
57
58 pub fn from_scalar(value: f64) -> Self {
60 Self::new(GA3::scalar(value))
61 }
62
63 pub fn from_vector(x: f64, y: f64, z: f64) -> Self {
65 let v = Vector::<3, 0, 0>::from_components(x, y, z);
66 Self::new(GA3::from_vector(&v))
67 }
68
69 pub fn from_bivector(xy: f64, xz: f64, yz: f64) -> Self {
71 let b = Bivector::<3, 0, 0>::from_components(xy, xz, yz);
72 Self::new(GA3::from_bivector(&b))
73 }
74
75 pub fn from_coefficients(coeffs: Vec<f64>) -> Self {
77 Self::new(GA3::from_coefficients(coeffs))
78 }
79
80 pub fn zero() -> Self {
82 Self::new(GA3::zero())
83 }
84
85 pub fn identity() -> Self {
87 Self::new(GA3::scalar(1.0))
88 }
89
90 pub fn multivector(&self) -> GA3 {
92 self.inner.lock().unwrap().clone()
93 }
94
95 pub fn get(&self, index: usize) -> f64 {
97 self.inner.lock().unwrap().get(index)
98 }
99
100 pub fn scalar(&self) -> f64 {
102 self.get(0)
103 }
104
105 pub fn as_vector(&self) -> (f64, f64, f64) {
107 let mv = self.inner.lock().unwrap();
108 (mv.get(1), mv.get(2), mv.get(4))
109 }
110
111 pub fn as_typed_vector(&self) -> Vector<3, 0, 0> {
113 let mv = self.inner.lock().unwrap();
114 Vector::from_components(mv.get(1), mv.get(2), mv.get(4))
115 }
116
117 pub fn as_bivector(&self) -> (f64, f64, f64) {
119 let mv = self.inner.lock().unwrap();
120 (mv.get(3), mv.get(5), mv.get(6))
121 }
122
123 pub fn as_typed_bivector(&self) -> Bivector<3, 0, 0> {
125 let mv = self.inner.lock().unwrap();
126 Bivector::from_components(mv.get(3), mv.get(5), mv.get(6))
127 }
128
129 pub fn magnitude(&self) -> f64 {
131 self.inner.lock().unwrap().magnitude()
132 }
133
134 pub fn project<P: Projection>(&self, projection: &P) -> P::Output {
136 let mv = self.inner.lock().unwrap();
137 projection.project(&mv)
138 }
139
140 pub fn set(&self, mv: GA3) {
142 {
143 let mut inner = self.inner.lock().unwrap();
144 *inner = mv;
145 }
146 self.notify_subscribers();
147 }
148
149 pub fn set_scalar(&self, value: f64) {
151 self.set(GA3::scalar(value));
152 }
153
154 pub fn set_vector(&self, x: f64, y: f64, z: f64) {
156 let v = Vector::<3, 0, 0>::from_components(x, y, z);
157 self.set(GA3::from_vector(&v));
158 }
159
160 pub fn set_typed_vector(&self, v: &Vector<3, 0, 0>) {
162 self.set(GA3::from_vector(v));
163 }
164
165 pub fn set_typed_bivector(&self, b: &Bivector<3, 0, 0>) {
167 self.set(GA3::from_bivector(b));
168 }
169
170 pub fn update<F>(&self, f: F)
172 where
173 F: FnOnce(&GA3) -> GA3,
174 {
175 {
176 let mut inner = self.inner.lock().unwrap();
177 *inner = f(&inner);
178 }
179 self.notify_subscribers();
180 }
181
182 pub fn apply_rotor(&self, rotor: &Rotor) -> GeometricState {
186 let mv = self.inner.lock().unwrap();
187 let transformed = rotor.transform(&mv);
188 GeometricState::new(transformed)
189 }
190
191 pub fn apply_rotor_mut(&self, rotor: &Rotor) {
193 self.update(|mv| rotor.transform(mv));
194 }
195
196 pub fn apply_translation(&self, translation: &Translation) -> GeometricState {
200 let mv = self.inner.lock().unwrap();
201 let transformed = translation.transform(&mv);
202 GeometricState::new(transformed)
203 }
204
205 pub fn apply_translation_mut(&self, translation: &Translation) {
207 self.update(|mv| translation.transform(mv));
208 }
209
210 pub fn apply_versor(&self, versor: &Versor) -> GeometricState {
214 let mv = self.inner.lock().unwrap();
215 let transformed = versor.transform(&mv);
216 GeometricState::new(transformed)
217 }
218
219 pub fn apply_versor_mut(&self, versor: &Versor) {
221 self.update(|mv| versor.transform(mv));
222 }
223
224 pub fn apply_transform(&self, transform: &Transform) -> GeometricState {
228 let mv = self.inner.lock().unwrap();
229 let transformed = transform.transform(&mv);
230 GeometricState::new(transformed)
231 }
232
233 pub fn apply_transform_mut(&self, transform: &Transform) {
235 self.update(|mv| transform.transform(mv));
236 }
237
238 pub fn add(&self, other: &GeometricState) -> GeometricState {
240 let a = self.inner.lock().unwrap();
241 let b = other.inner.lock().unwrap();
242 GeometricState::new(&*a + &*b)
243 }
244
245 pub fn sub(&self, other: &GeometricState) -> GeometricState {
247 let a = self.inner.lock().unwrap();
248 let b = other.inner.lock().unwrap();
249 GeometricState::new(&*a - &*b)
250 }
251
252 pub fn scale(&self, factor: f64) -> GeometricState {
254 let mv = self.inner.lock().unwrap();
255 GeometricState::new(&*mv * factor)
256 }
257
258 pub fn geometric_product(&self, other: &GeometricState) -> GeometricState {
260 let a = self.inner.lock().unwrap();
261 let b = other.inner.lock().unwrap();
262 GeometricState::new(a.geometric_product(&b))
263 }
264
265 pub fn normalize(&self) -> Option<GeometricState> {
267 let mv = self.inner.lock().unwrap();
268 mv.normalize().map(GeometricState::new)
269 }
270
271 pub fn normalize_mut(&self) -> bool {
273 let mut inner = self.inner.lock().unwrap();
274 match inner.normalize() {
275 Some(normalized) => {
276 *inner = normalized;
277 drop(inner);
278 self.notify_subscribers();
279 true
280 }
281 None => false,
282 }
283 }
284
285 pub fn reverse(&self) -> GeometricState {
287 let mv = self.inner.lock().unwrap();
288 GeometricState::new(mv.reverse())
289 }
290
291 pub fn lerp(&self, other: &GeometricState, t: f64) -> GeometricState {
293 let a = self.inner.lock().unwrap();
294 let b = other.inner.lock().unwrap();
295
296 let diff = &*b - &*a;
298 let interpolated = &*a + &(&diff * t);
299 GeometricState::new(interpolated)
300 }
301
302 pub fn slerp(&self, other: &GeometricState, t: f64) -> GeometricState {
306 let a_mv = self.inner.lock().unwrap();
308 let b_mv = other.inner.lock().unwrap();
309
310 let rotor_a = Rotor::from_multivector(a_mv.clone());
311 let rotor_b = Rotor::from_multivector(b_mv.clone());
312
313 let interpolated = rotor_a.slerp_to(&rotor_b, t);
314 GeometricState::new(interpolated.as_multivector().clone())
315 }
316
317 pub fn subscribe<F>(&self, callback: F) -> GeometricSubscription
319 where
320 F: Fn(&GA3) + Send + Sync + 'static,
321 {
322 let mut subs = self.subscribers.lock().unwrap();
323 let id = subs.len();
324 subs.push(Box::new(callback));
325
326 GeometricSubscription {
327 id,
328 subscribers: self.subscribers.clone(),
329 }
330 }
331
332 fn notify_subscribers(&self) {
334 let mv = self.inner.lock().unwrap();
335 let subs = self.subscribers.lock().unwrap();
336 for callback in subs.iter() {
337 callback(&mv);
338 }
339 }
340}
341
342impl std::fmt::Debug for GeometricState {
343 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
344 let mv = self.inner.lock().unwrap();
345 write!(f, "GeometricState({:?})", mv)
346 }
347}
348
349pub struct GeometricSubscription {
351 id: usize,
352 subscribers: SubscriberList,
353}
354
355impl GeometricSubscription {
356 pub fn unsubscribe(self) {
362 let _ = (self.id, self.subscribers);
365 }
366}
367
368#[cfg(test)]
369mod tests {
370 use super::*;
371 use crate::projection::{IntProjection, ScalarProjection, VectorProjection};
372 use std::f64::consts::PI;
373 use std::sync::atomic::{AtomicUsize, Ordering};
374
375 #[test]
376 fn test_from_scalar() {
377 let state = GeometricState::from_scalar(42.0);
378 assert!((state.scalar() - 42.0).abs() < 1e-10);
379 }
380
381 #[test]
382 fn test_from_vector() {
383 let state = GeometricState::from_vector(1.0, 2.0, 3.0);
384 let (x, y, z) = state.as_vector();
385 assert!((x - 1.0).abs() < 1e-10);
386 assert!((y - 2.0).abs() < 1e-10);
387 assert!((z - 3.0).abs() < 1e-10);
388 }
389
390 #[test]
391 fn test_apply_rotor() {
392 let state = GeometricState::from_vector(1.0, 0.0, 0.0);
393 let rotor = Rotor::xy(PI / 2.0);
394 let rotated = state.apply_rotor(&rotor);
395
396 let (x, y, z) = rotated.as_vector();
397 assert!(x.abs() < 1e-10, "x should be ~0, got {}", x);
398 assert!((y - 1.0).abs() < 1e-10, "y should be ~1, got {}", y);
399 assert!(z.abs() < 1e-10, "z should be ~0, got {}", z);
400 }
401
402 #[test]
403 fn test_apply_translation() {
404 let state = GeometricState::from_vector(0.0, 0.0, 0.0);
405 let trans = Translation::new(1.0, 2.0, 3.0);
406 let translated = state.apply_translation(&trans);
407
408 let (x, y, z) = translated.as_vector();
409 assert!((x - 1.0).abs() < 1e-10);
410 assert!((y - 2.0).abs() < 1e-10);
411 assert!((z - 3.0).abs() < 1e-10);
412 }
413
414 #[test]
415 fn test_apply_transform() {
416 let state = GeometricState::from_vector(1.0, 0.0, 0.0);
417 let transform = Transform::new(Rotor::xy(PI / 2.0), Translation::new(1.0, 0.0, 0.0));
418
419 let result = state.apply_transform(&transform);
420 let (x, y, z) = result.as_vector();
421
422 assert!((x - 1.0).abs() < 1e-10, "x should be ~1, got {}", x);
424 assert!((y - 1.0).abs() < 1e-10, "y should be ~1, got {}", y);
425 assert!(z.abs() < 1e-10);
426 }
427
428 #[test]
429 fn test_lerp() {
430 let a = GeometricState::from_scalar(0.0);
431 let b = GeometricState::from_scalar(10.0);
432
433 let half = a.lerp(&b, 0.5);
434 assert!((half.scalar() - 5.0).abs() < 1e-10);
435
436 let quarter = a.lerp(&b, 0.25);
437 assert!((quarter.scalar() - 2.5).abs() < 1e-10);
438 }
439
440 #[test]
441 fn test_projection() {
442 let state = GeometricState::from_scalar(42.7);
443
444 let scalar = state.project(&ScalarProjection);
445 assert!((scalar - 42.7).abs() < 1e-10);
446
447 let int = state.project(&IntProjection);
448 assert_eq!(int, 42);
449 }
450
451 #[test]
452 fn test_vector_projection() {
453 let state = GeometricState::from_vector(1.0, 2.0, 3.0);
454 let (x, y, z) = state.project(&VectorProjection);
455 assert!((x - 1.0).abs() < 1e-10);
456 assert!((y - 2.0).abs() < 1e-10);
457 assert!((z - 3.0).abs() < 1e-10);
458 }
459
460 #[test]
461 fn test_subscribe() {
462 let state = GeometricState::from_scalar(0.0);
463 let call_count = Arc::new(AtomicUsize::new(0));
464 let call_count_clone = call_count.clone();
465
466 let _sub = state.subscribe(move |_mv| {
467 call_count_clone.fetch_add(1, Ordering::SeqCst);
468 });
469
470 state.set_scalar(1.0);
471 state.set_scalar(2.0);
472
473 assert_eq!(call_count.load(Ordering::SeqCst), 2);
474 }
475
476 #[test]
477 fn test_typed_vector_accessors() {
478 let state = GeometricState::from_vector(1.0, 2.0, 3.0);
479 let v = state.as_typed_vector();
480 assert!((v.mv.get(1) - 1.0).abs() < 1e-10);
482 assert!((v.mv.get(2) - 2.0).abs() < 1e-10);
483 assert!((v.mv.get(4) - 3.0).abs() < 1e-10);
484 }
485
486 #[test]
487 fn test_typed_bivector_accessors() {
488 let state = GeometricState::from_bivector(0.5, 0.3, 0.1);
489 let b = state.as_typed_bivector();
490 assert!((b.get(0) - 0.5).abs() < 1e-10);
491 assert!((b.get(1) - 0.3).abs() < 1e-10);
492 assert!((b.get(2) - 0.1).abs() < 1e-10);
493 }
494
495 #[test]
496 fn test_set_typed_vector() {
497 let state = GeometricState::zero();
498 let v = Vector::<3, 0, 0>::from_components(4.0, 5.0, 6.0);
499 state.set_typed_vector(&v);
500 let result = state.as_typed_vector();
501 assert!((result.mv.get(1) - 4.0).abs() < 1e-10);
503 assert!((result.mv.get(2) - 5.0).abs() < 1e-10);
504 assert!((result.mv.get(4) - 6.0).abs() < 1e-10);
505 }
506
507 #[test]
508 fn test_scale() {
509 let state = GeometricState::from_vector(1.0, 2.0, 3.0);
510 let scaled = state.scale(2.0);
511
512 let (x, y, z) = scaled.as_vector();
513 assert!((x - 2.0).abs() < 1e-10);
514 assert!((y - 4.0).abs() < 1e-10);
515 assert!((z - 6.0).abs() < 1e-10);
516 }
517
518 #[test]
519 fn test_normalize() {
520 let state = GeometricState::from_vector(3.0, 4.0, 0.0);
521 let normalized = state.normalize().unwrap();
522
523 let mag = normalized.magnitude();
524 assert!((mag - 1.0).abs() < 1e-10);
525
526 let (x, y, _) = normalized.as_vector();
527 assert!((x - 0.6).abs() < 1e-10);
528 assert!((y - 0.8).abs() < 1e-10);
529 }
530}