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