ratatui/widgets/canvas/
map.rs

1use strum::{Display, EnumString};
2
3use crate::{
4    style::Color,
5    widgets::canvas::{
6        world::{WORLD_HIGH_RESOLUTION, WORLD_LOW_RESOLUTION},
7        Painter, Shape,
8    },
9};
10
11/// Defines how many points are going to be used to draw a [`Map`].
12///
13/// You generally want a [high](MapResolution::High) resolution map.
14#[derive(Debug, Default, Display, EnumString, Clone, Copy, Eq, PartialEq, Hash)]
15pub enum MapResolution {
16    /// A lesser resolution for the [`Map`] [`Shape`].
17    ///
18    /// Contains about 1000 points.
19    #[default]
20    Low,
21    /// A higher resolution for the [`Map`] [`Shape`].
22    ///
23    /// Contains about 5000 points, you likely want to use [`Marker::Braille`] with this.
24    ///
25    /// [`Marker::Braille`]: (crate::symbols::Marker::Braille)
26    High,
27}
28
29impl MapResolution {
30    const fn data(self) -> &'static [(f64, f64)] {
31        match self {
32            Self::Low => &WORLD_LOW_RESOLUTION,
33            Self::High => &WORLD_HIGH_RESOLUTION,
34        }
35    }
36}
37
38/// A world map
39///
40/// A world map can be rendered with different [resolutions](MapResolution) and [colors](Color).
41#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
42pub struct Map {
43    /// The resolution of the map.
44    ///
45    /// This is the number of points used to draw the map.
46    pub resolution: MapResolution,
47    /// Map color
48    ///
49    /// This is the color of the points of the map.
50    pub color: Color,
51}
52
53impl Shape for Map {
54    fn draw(&self, painter: &mut Painter) {
55        for (x, y) in self.resolution.data() {
56            if let Some((x, y)) = painter.get_point(*x, *y) {
57                painter.paint(x, y, self.color);
58            }
59        }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use strum::ParseError;
66
67    use super::*;
68    use crate::{
69        buffer::Buffer,
70        layout::Rect,
71        symbols::Marker,
72        widgets::{canvas::Canvas, Widget},
73    };
74
75    #[test]
76    fn map_resolution_to_string() {
77        assert_eq!(MapResolution::Low.to_string(), "Low");
78        assert_eq!(MapResolution::High.to_string(), "High");
79    }
80
81    #[test]
82    fn map_resolution_from_str() {
83        assert_eq!("Low".parse(), Ok(MapResolution::Low));
84        assert_eq!("High".parse(), Ok(MapResolution::High));
85        assert_eq!(
86            "".parse::<MapResolution>(),
87            Err(ParseError::VariantNotFound)
88        );
89    }
90
91    #[test]
92    fn default() {
93        let map = Map::default();
94        assert_eq!(map.resolution, MapResolution::Low);
95        assert_eq!(map.color, Color::Reset);
96    }
97
98    #[test]
99    fn draw_low() {
100        let mut buffer = Buffer::empty(Rect::new(0, 0, 80, 40));
101        let canvas = Canvas::default()
102            .marker(Marker::Dot)
103            .x_bounds([-180.0, 180.0])
104            .y_bounds([-90.0, 90.0])
105            .paint(|context| {
106                context.draw(&Map::default());
107            });
108        canvas.render(buffer.area, &mut buffer);
109        let expected = Buffer::with_lines([
110            "                                                                                ",
111            "                   ••••••• •• •• •• •                                           ",
112            "            ••••••••••••••       •••      ••••  •••  ••    ••••                 ",
113            "            ••••••••••••••••     ••                ••• ••••••• •• •• •••        ",
114            "• • •• •••••• •••••••••••• ••   •••  •    •••••  •••••••••          ••  • • • • ",
115            "•••••       ••••  •••••••• •• ••  •••    •••• ••••    •• •                    • ",
116            "   ••••••••  ••••••• •••••  •••       ••••••••                        • •••••   ",
117            "  •• ••   ••    •••••••  ••          ••• ••••                        ••    •    ",
118            "•••       •••    •••••• ••••         ••••                             •• •   •• ",
119            "            •      •••••••••          ••  •   ••• • •• ••            ••         ",
120            "            • •     ••••             •• ••••••••• •••   •         • • ••        ",
121            "            •         •               ••••• ••••  ••             ••••••         ",
122            "             •      ••               •   • •• •                  •••••          ",
123            "              ••  •• •              •         ••  ••              •             ",
124            "    ••        •••   •••            •           •  •••••    •   •••              ",
125            "     •           •••• •••                       •   •  •    •  • ••             ",
126            "                  •••• •           •            •• •     •  ••   ••             ",
127            "                     ••• ••         •           • •     ••   ••• •••            ",
128            "                      •    •        • •• •              •   •   •  •            ",
129            "                   •  •     •            •    • •            ••• •  •           ",
130            "                     •        •           •   •              •• •   • •         ",
131            "                               •                •              ••   ••• •       ",
132            " •                    •       •           •     • •                • •          ",
133            "                        •                 •    • ••               •  • •   •  • ",
134            "                              •                •                •       •       ",
135            "                       •    •                 •  •              •        •      ",
136            "                       •   ••              • •                  • • ••       •  ",
137            "                       •  •                •                         ••••    •• ",
138            "                       • •                                             ••   ••• ",
139            "                       ••                                                   •   ",
140            "                       •• •                                                     ",
141            "                       ••                                                       ",
142            "                                                                                ",
143            "                        •••                        •      •••• • • •• •         ",
144            "                       ••••           •••••• •••••• ••••••             • •••    ",
145            "         •• •••••• ••••• ••      • ••• •                                   ••   ",
146            "•  •••••             ••  •• ••••••                                         • •• ",
147            "•    •                 •   •  •                                             • • ",
148            "       •                                                                        ",
149            "                                                                                ",
150        ]);
151        assert_eq!(buffer, expected);
152    }
153
154    #[test]
155    fn draw_high() {
156        let mut buffer = Buffer::empty(Rect::new(0, 0, 80, 40));
157        let canvas = Canvas::default()
158            .marker(Marker::Braille)
159            .x_bounds([-180.0, 180.0])
160            .y_bounds([-90.0, 90.0])
161            .paint(|context| {
162                context.draw(&Map {
163                    resolution: MapResolution::High,
164                    ..Default::default()
165                });
166            });
167        canvas.render(buffer.area, &mut buffer);
168        let expected = Buffer::with_lines([
169            "                                                                                ",
170            "                  ⢀⣠⠤⠤⠤⠔⢤⣤⡄⠤⡠⣄⠢⠂⢢⠰⣠⡄⣀⡀                      ⣀                   ",
171            "            ⢀⣀⡤⣦⠲⢶⣿⣮⣿⡉⣰⢶⢏⡂        ⢀⣟⠁     ⢺⣻⢿⠏   ⠈⠉⠁ ⢀⣀    ⠈⠓⢳⣢⣂⡀               ",
172            "            ⡞⣳⣿⣻⡧⣷⣿⣿⢿⢿⣧⡀⠉⠉⠙⢆      ⣰⠇               ⣠⠞⠃⢉⣄⣀⣠⠴⠊⠉⠁ ⠐⠾⠤⢤⠤⡄⠐⣻⠜⢓⠂      ",
173            "⢍ ⢀⡴⠊⠙⠓⠒⠒⠤⠖⠺⠿⠽⣷⣬⢬⣾⣷⢻⣷⢲⢲⣍⠱⡀ ⠹⡗   ⢀⢐⠟        ⡔⠒⠉⠲⠤⢀⢄⡀⢩⣣⠦⢷⢼⡏⠈          ⠉⠉⠉ ⠈⠈⠉⠖⠤⠆⠒⠭",
174            "⠶⢽⡲⣽⡆             ⠈⣠⣽⣯⡼⢯⣘⡯⠃⠘⡆ ⢰⠒⠁ ⢾⣚⠟    ⢀⠆ ⣔⠆ ⢷⠾⠋⠁    ⠙⠁                     ⠠⡤",
175            "  ⠠⢧⣄⣀⡶⠦⠤⡀        ⢰⡁ ⠉⡻⠙⣎⡥  ⠘⠲⠇       ⢀⡀⠨⣁⡄⣸⢫⡤⠄                        ⣀⢠⣤⠊⣼⠅⠖⠋⠁",
176            "   ⣠⠾⠛⠁  ⠈⣱        ⠋⠦⢤⡼ ⠈⠈⠦⡀         ⢀⣿⣇ ⢹⣷⣂⡞⠃                       ⢀⣂⡀  ⠏⣜    ",
177            "          ⠙⣷⡄        ⠘⠆ ⢀⣀⡠⣗         ⠘⣻⣽⡟⠉⠈                           ⢹⡇  ⠟⠁    ",
178            "           ⠈⡟           ⢎⣻⡿⠾⠇         ⠘⠇  ⣀⡀  ⣤⣤⡆ ⡠⡦                 ⢀⠎⡏        ",
179            "            ⡇          ⣀⠏⠋           ⢸⠒⢃⡖⢻⢟⣷⣄⣰⣡⠥⣱ ⢏⣧              ⣀ ⡴⠚⢰⠟        ",
180            "            ⢳         ⢸⠃             ⠸⣄⣼⣠⢼⡴⡟⢿⢿⣀⣄  ⠸⡹             ⠘⡯⢿⡇⡠⢼⠁        ",
181            "             ⢳⣀      ⢀⠞⠁             ⢠⠋⠁ ⠐⠧⡄⣬⣉⣈⡽                  ⢧⠘⢽⠟⠉         ",
182            "              ⣿⣄  ⡴⠚⠛⣿⣀             ⢠⠖     ⠈⠁ ⠹⣧  ⢾⣄⡀             ⡼ ⠈           ",
183            "    ⣀         ⠘⣿⡄ ⡇  ⣘⣻             ⡏          ⢻⡄ ⠘⠿⢿⠒⠲⡀   ⢀⡀   ⢀⡰⣗             ",
184            "    ⠉⠷          ⢫⡀⢧⡼⡟⠉⣛⣳⣦⡀         ⠈⡇          ⠸⣱  ⢀⡼  ⢺  ⡸⠉⢇  ⣾⡏ ⣁             ",
185            "                 ⠉⠒⢆⡓⡆             ⠠⡃           ⢳⣇⡠⠏   ⠐⡄⡞  ⠘⣇⡀⢱  ⣾⡀            ",
186            "                    ⢹⣇⣀⣾⡷⠤⡆         ⢣            ⠯⢺⠇    ⢣⣅   ⣽⢱⡔ ⢠⢿⣗            ",
187            "                     ⠙⢱   ⠘⠦⡄       ⠈⢦⡠⣠⢶⣀        ⡜     ⠈⠿  ⢠⣽⢆ ⢀⣼⡜⠿            ",
188            "                     ⢀⡞     ⢱⡀           ⢸       ⡔⠁          ⢻⢿⢰⠏⢸⣤⣴⣆           ",
189            "                     ⢘⠆      ⠙⠢⢄         ⠸⡀     ⡸⠁           ⠈⣞⡎⠥⡟⣿⠠⠿⣷⠒⢤⢀⣆      ",
190            "                     ⠘⠆        ⢈⠂         ⢳     ⡇             ⠈⠳⠶⣤⣭⣠ ⠋⢧⡬⣟⠉⠷⡄    ",
191            "                      ⢨        ⡜          ⢸     ⠸ ⣠               ⠁⢁⣰⢶ ⡇⠉⠁ ⠛    ",
192            "⠆                     ⠈⢱⡀      ⡆          ⡇    ⢀⡜⡴⢹               ⢰⠏⠁⠘⢶⠹⡀   ⠸ ⢠⡶",
193            "                        ⠅     ⣸           ⢸    ⢫ ⡞⡊             ⢠⠔⠋     ⢳⡀ ⠐⣦   ",
194            "                        ⡅    ⡏            ⠈⡆  ⢠⠎ ⠳⠃             ⢸        ⢳      ",
195            "                       ⠨    ⡸⠁             ⢱  ⡸                 ⠈⡇ ⢀⣀⡀   ⢸      ",
196            "                       ⠸  ⠐⡶⠁              ⠘⠖⠚                   ⠣⠒⠋ ⠱⣇ ⢀⠇   ⠰⡄ ",
197            "                       ⠽ ⣰⡖⠁                                          ⠘⢚⡊    ⢀⣿⠇",
198            "                       ⡯⢀⡟                                             ⠘⠏   ⢠⢾⠃ ",
199            "                       ⠇⢨⠆                            ⢠⡄                    ⠈⠁  ",
200            "                       ⢧⣷⡀⠚                                                     ",
201            "                        ⠉⠁                                                      ",
202            "                          ⢀⡀                                                    ",
203            "                        ⢠⡾⠋                      ⣀⡠⠖⢦⣀⣀  ⣀⠤⠦⢤⠤⠶⠤⠖⠦⠤⠤⠤⠴⠤⢤⣄       ",
204            "                ⢀⣤⣀ ⡀  ⣼⣻⠙⡆         ⢀⡤⠤⠤⠴⠒⠖⠒⠒⠒⠚⠉⠋⠁    ⢰⡳⠊⠁              ⠈⠉⠉⠒⠤⣤  ",
205            "    ⢀⣀⣀⡴⠖⠒⠒⠚⠛⠛⠛⠒⠚⠳⠉⠉⠉⠉⢉⣉⡥⠔⠃     ⢀⣠⠤⠴⠃                                      ⢠⠞⠁  ",
206            "   ⠘⠛⣓⣒⠆              ⠸⠥⣀⣤⡦⠠⣞⣭⣇⣘⠿⠆                                         ⣖⠛   ",
207            "⠶⠔⠲⠤⠠⠜⢗⠤⠄                 ⠘⠉  ⠁                                            ⠈⠉⠒⠔⠤",
208            "                                                                                ",
209        ]);
210        assert_eq!(buffer, expected);
211    }
212}