ranim_items/vitem/geometry/
anchor.rs1use ranim_core::{
2 core_item::vitem::Basis2d,
3 glam::{DVec2, DVec3},
4 traits::Locate,
5};
6
7use crate::vitem::geometry::{Arc, ArcBetweenPoints, Circle, Ellipse, EllipticArc};
8
9#[derive(Debug, Clone, Copy)]
11pub struct Origin;
12
13#[derive(Debug, Clone, Copy)]
15pub struct Focus {
16 pos: bool,
17}
18
19impl Focus {
20 pub const POS: Self = Focus { pos: true };
22 pub const NEG: Self = Focus { pos: false };
24}
25
26impl Locate<Arc> for Origin {
27 fn locate(&self, target: &Arc) -> DVec3 {
28 target.center
29 }
30}
31
32impl Locate<Arc> for Focus {
33 fn locate(&self, target: &Arc) -> DVec3 {
34 target.center
35 }
36}
37
38impl Locate<ArcBetweenPoints> for Origin {
39 fn locate(&self, target: &ArcBetweenPoints) -> DVec3 {
40 Arc::from(target.clone()).center
42 }
43}
44
45impl Locate<ArcBetweenPoints> for Focus {
46 fn locate(&self, target: &ArcBetweenPoints) -> DVec3 {
47 Arc::from(target.clone()).center
49 }
50}
51
52impl Locate<Circle> for Origin {
53 fn locate(&self, target: &Circle) -> DVec3 {
54 target.center
55 }
56}
57
58impl Locate<Circle> for Focus {
59 fn locate(&self, target: &Circle) -> DVec3 {
60 target.center
61 }
62}
63
64fn ellipse_focus(basis: Basis2d, radius: DVec2) -> DVec3 {
65 let DVec2 { x: rx, y: ry } = radius;
66 let c = (rx * rx - ry * ry).abs().sqrt();
67 (if rx > ry { basis.u() } else { basis.v() }) * c
68}
69
70impl Locate<EllipticArc> for Origin {
71 fn locate(&self, target: &EllipticArc) -> DVec3 {
72 target.center
73 }
74}
75
76impl Locate<EllipticArc> for Focus {
77 fn locate(&self, target: &EllipticArc) -> DVec3 {
78 let &EllipticArc {
79 basis,
80 center,
81 radius,
82 ..
83 } = target;
84 let focus = ellipse_focus(basis, radius);
85 if self.pos {
86 center + focus
87 } else {
88 center - focus
89 }
90 }
91}
92
93impl Locate<Ellipse> for Origin {
94 fn locate(&self, target: &Ellipse) -> DVec3 {
95 target.center
96 }
97}
98
99impl Locate<Ellipse> for Focus {
100 fn locate(&self, target: &Ellipse) -> DVec3 {
101 let &Ellipse {
102 basis,
103 center,
104 radius,
105 ..
106 } = target;
107 let focus = ellipse_focus(basis, radius);
108 if self.pos {
109 center + focus
110 } else {
111 center - focus
112 }
113 }
114}