1
use easygpu_lyon::lyon_tessellation::{FillTessellator, StrokeTessellator};
2
use figures::{Displayable, Points, Vectorlike};
3

            
4
use super::lyon_point;
5
use crate::math::{Figure, Pixels, Point, Scale, Scaled};
6
use crate::scene::Target;
7
use crate::shape::{Fill, Stroke};
8
use crate::Error;
9
3
#[derive(Clone, Debug)]
10
pub struct Circle<S> {
11
    pub center: Point<f32, S>,
12
    pub radius: Figure<f32, S>,
13
}
14

            
15
impl<U> Circle<U> {
16
    pub fn cast_unit<V>(self) -> Circle<V> {
17
        Circle {
18
            center: self.center.cast_unit(),
19
            radius: self.radius.cast_unit(),
20
        }
21
    }
22
}
23

            
24
impl Circle<Pixels> {
25
3
    pub(crate) fn translate_and_convert_to_device(
26
3
        &self,
27
3
        location: Point<f32, Pixels>,
28
3
        scene: &Target,
29
3
    ) -> Self {
30
3
        let effective_scale = scene.scale();
31
3
        let center = location + self.center.to_vector();
32
3
        let radius = self.radius.to_pixels(effective_scale);
33
3
        Self { center, radius }
34
3
    }
35
}
36

            
37
impl Circle<Pixels> {
38
    pub fn build(
39
        &self,
40
        builder: &mut easygpu_lyon::ShapeBuilder,
41
        stroke: &Option<Stroke>,
42
        fill: &Option<Fill>,
43
    ) -> crate::Result<()> {
44
3
        if let Some(fill) = fill {
45
3
            builder.default_color = fill.color.rgba();
46
3
            let mut tessellator = FillTessellator::new();
47
3
            tessellator
48
3
                .tessellate_circle(
49
3
                    lyon_point(self.center),
50
3
                    self.radius.get(),
51
3
                    &fill.options,
52
3
                    builder,
53
3
                )
54
3
                .map_err(Error::Tessellation)?;
55
        }
56

            
57
3
        if let Some(stroke) = stroke {
58
            builder.default_color = stroke.color.rgba();
59
            let mut tessellator = StrokeTessellator::new();
60
            tessellator
61
                .tessellate_circle(
62
                    lyon_point(self.center),
63
                    self.radius.get(),
64
                    &stroke.options,
65
                    builder,
66
                )
67
                .map_err(Error::Tessellation)?;
68
3
        }
69

            
70
3
        Ok(())
71
3
    }
72
}
73

            
74
impl<Src, Dst> std::ops::Mul<Scale<f32, Src, Dst>> for Circle<Src> {
75
    type Output = Circle<Dst>;
76

            
77
    fn mul(self, scale: Scale<f32, Src, Dst>) -> Self::Output {
78
        Self::Output {
79
            center: self.center * scale,
80
            radius: self.radius * scale,
81
        }
82
    }
83
}
84

            
85
impl Displayable<f32> for Circle<Pixels> {
86
    type Pixels = Self;
87
    type Points = Circle<Points>;
88
    type Scaled = Circle<Scaled>;
89

            
90
    fn to_pixels(&self, _scale: &figures::DisplayScale<f32>) -> Self::Pixels {
91
        self.clone()
92
    }
93

            
94
    fn to_points(&self, scale: &figures::DisplayScale<f32>) -> Self::Points {
95
        Circle {
96
            center: self.center.to_points(scale),
97
            radius: self.radius.to_points(scale),
98
        }
99
    }
100

            
101
    fn to_scaled(&self, scale: &figures::DisplayScale<f32>) -> Self::Scaled {
102
        Circle {
103
            center: self.center.to_scaled(scale),
104
            radius: self.radius.to_scaled(scale),
105
        }
106
    }
107
}
108

            
109
impl Displayable<f32> for Circle<Points> {
110
    type Pixels = Circle<Pixels>;
111
    type Points = Self;
112
    type Scaled = Circle<Scaled>;
113

            
114
    fn to_pixels(&self, scale: &figures::DisplayScale<f32>) -> Self::Pixels {
115
        Circle {
116
            center: self.center.to_pixels(scale),
117
            radius: self.radius.to_pixels(scale),
118
        }
119
    }
120

            
121
    fn to_points(&self, _scale: &figures::DisplayScale<f32>) -> Self::Points {
122
        self.clone()
123
    }
124

            
125
    fn to_scaled(&self, scale: &figures::DisplayScale<f32>) -> Self::Scaled {
126
        Circle {
127
            center: self.center.to_scaled(scale),
128
            radius: self.radius.to_scaled(scale),
129
        }
130
    }
131
}
132

            
133
impl Displayable<f32> for Circle<Scaled> {
134
    type Pixels = Circle<Pixels>;
135
    type Points = Circle<Points>;
136
    type Scaled = Self;
137

            
138
3
    fn to_pixels(&self, scale: &figures::DisplayScale<f32>) -> Self::Pixels {
139
3
        Circle {
140
3
            center: self.center.to_pixels(scale),
141
3
            radius: self.radius.to_pixels(scale),
142
3
        }
143
3
    }
144

            
145
    fn to_points(&self, scale: &figures::DisplayScale<f32>) -> Self::Points {
146
        Circle {
147
            center: self.center.to_points(scale),
148
            radius: self.radius.to_points(scale),
149
        }
150
    }
151

            
152
    fn to_scaled(&self, _scale: &figures::DisplayScale<f32>) -> Self::Scaled {
153
        self.clone()
154
    }
155
}