ratatui/widgets/canvas/
map.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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
211
212
use strum::{Display, EnumString};

use crate::{
    style::Color,
    widgets::canvas::{
        world::{WORLD_HIGH_RESOLUTION, WORLD_LOW_RESOLUTION},
        Painter, Shape,
    },
};

/// Defines how many points are going to be used to draw a [`Map`].
///
/// You generally want a [high](MapResolution::High) resolution map.
#[derive(Debug, Default, Display, EnumString, Clone, Copy, Eq, PartialEq, Hash)]
pub enum MapResolution {
    /// A lesser resolution for the [`Map`] [`Shape`].
    ///
    /// Contains about 1000 points.
    #[default]
    Low,
    /// A higher resolution for the [`Map`] [`Shape`].
    ///
    /// Contains about 5000 points, you likely want to use [`Marker::Braille`] with this.
    ///
    /// [`Marker::Braille`]: (crate::symbols::Marker::Braille)
    High,
}

impl MapResolution {
    const fn data(self) -> &'static [(f64, f64)] {
        match self {
            Self::Low => &WORLD_LOW_RESOLUTION,
            Self::High => &WORLD_HIGH_RESOLUTION,
        }
    }
}

/// A world map
///
/// A world map can be rendered with different [resolutions](MapResolution) and [colors](Color).
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct Map {
    /// The resolution of the map.
    ///
    /// This is the number of points used to draw the map.
    pub resolution: MapResolution,
    /// Map color
    ///
    /// This is the color of the points of the map.
    pub color: Color,
}

impl Shape for Map {
    fn draw(&self, painter: &mut Painter) {
        for (x, y) in self.resolution.data() {
            if let Some((x, y)) = painter.get_point(*x, *y) {
                painter.paint(x, y, self.color);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use strum::ParseError;

    use super::*;
    use crate::{
        buffer::Buffer,
        layout::Rect,
        symbols::Marker,
        widgets::{canvas::Canvas, Widget},
    };

    #[test]
    fn map_resolution_to_string() {
        assert_eq!(MapResolution::Low.to_string(), "Low");
        assert_eq!(MapResolution::High.to_string(), "High");
    }

    #[test]
    fn map_resolution_from_str() {
        assert_eq!("Low".parse(), Ok(MapResolution::Low));
        assert_eq!("High".parse(), Ok(MapResolution::High));
        assert_eq!(
            "".parse::<MapResolution>(),
            Err(ParseError::VariantNotFound)
        );
    }

    #[test]
    fn default() {
        let map = Map::default();
        assert_eq!(map.resolution, MapResolution::Low);
        assert_eq!(map.color, Color::Reset);
    }

    #[test]
    fn draw_low() {
        let mut buffer = Buffer::empty(Rect::new(0, 0, 80, 40));
        let canvas = Canvas::default()
            .marker(Marker::Dot)
            .x_bounds([-180.0, 180.0])
            .y_bounds([-90.0, 90.0])
            .paint(|context| {
                context.draw(&Map::default());
            });
        canvas.render(buffer.area, &mut buffer);
        let expected = Buffer::with_lines([
            "                                                                                ",
            "                   ••••••• •• •• •• •                                           ",
            "            ••••••••••••••       •••      ••••  •••  ••    ••••                 ",
            "            ••••••••••••••••     ••                ••• ••••••• •• •• •••        ",
            "• • •• •••••• •••••••••••• ••   •••  •    •••••  •••••••••          ••  • • • • ",
            "•••••       ••••  •••••••• •• ••  •••    •••• ••••    •• •                    • ",
            "   ••••••••  ••••••• •••••  •••       ••••••••                        • •••••   ",
            "  •• ••   ••    •••••••  ••          ••• ••••                        ••    •    ",
            "•••       •••    •••••• ••••         ••••                             •• •   •• ",
            "            •      •••••••••          ••  •   ••• • •• ••            ••         ",
            "            • •     ••••             •• ••••••••• •••   •         • • ••        ",
            "            •         •               ••••• ••••  ••             ••••••         ",
            "             •      ••               •   • •• •                  •••••          ",
            "              ••  •• •              •         ••  ••              •             ",
            "    ••        •••   •••            •           •  •••••    •   •••              ",
            "     •           •••• •••                       •   •  •    •  • ••             ",
            "                  •••• •           •            •• •     •  ••   ••             ",
            "                     ••• ••         •           • •     ••   ••• •••            ",
            "                      •    •        • •• •              •   •   •  •            ",
            "                   •  •     •            •    • •            ••• •  •           ",
            "                     •        •           •   •              •• •   • •         ",
            "                               •                •              ••   ••• •       ",
            " •                    •       •           •     • •                • •          ",
            "                        •                 •    • ••               •  • •   •  • ",
            "                              •                •                •       •       ",
            "                       •    •                 •  •              •        •      ",
            "                       •   ••              • •                  • • ••       •  ",
            "                       •  •                •                         ••••    •• ",
            "                       • •                                             ••   ••• ",
            "                       ••                                                   •   ",
            "                       •• •                                                     ",
            "                       ••                                                       ",
            "                                                                                ",
            "                        •••                        •      •••• • • •• •         ",
            "                       ••••           •••••• •••••• ••••••             • •••    ",
            "         •• •••••• ••••• ••      • ••• •                                   ••   ",
            "•  •••••             ••  •• ••••••                                         • •• ",
            "•    •                 •   •  •                                             • • ",
            "       •                                                                        ",
            "                                                                                ",
        ]);
        assert_eq!(buffer, expected);
    }

    #[test]
    fn draw_high() {
        let mut buffer = Buffer::empty(Rect::new(0, 0, 80, 40));
        let canvas = Canvas::default()
            .marker(Marker::Braille)
            .x_bounds([-180.0, 180.0])
            .y_bounds([-90.0, 90.0])
            .paint(|context| {
                context.draw(&Map {
                    resolution: MapResolution::High,
                    ..Default::default()
                });
            });
        canvas.render(buffer.area, &mut buffer);
        let expected = Buffer::with_lines([
            "                                                                                ",
            "                  ⢀⣠⠤⠤⠤⠔⢤⣤⡄⠤⡠⣄⠢⠂⢢⠰⣠⡄⣀⡀                      ⣀                   ",
            "            ⢀⣀⡤⣦⠲⢶⣿⣮⣿⡉⣰⢶⢏⡂        ⢀⣟⠁     ⢺⣻⢿⠏   ⠈⠉⠁ ⢀⣀    ⠈⠓⢳⣢⣂⡀               ",
            "            ⡞⣳⣿⣻⡧⣷⣿⣿⢿⢿⣧⡀⠉⠉⠙⢆      ⣰⠇               ⣠⠞⠃⢉⣄⣀⣠⠴⠊⠉⠁ ⠐⠾⠤⢤⠤⡄⠐⣻⠜⢓⠂      ",
            "⢍ ⢀⡴⠊⠙⠓⠒⠒⠤⠖⠺⠿⠽⣷⣬⢬⣾⣷⢻⣷⢲⢲⣍⠱⡀ ⠹⡗   ⢀⢐⠟        ⡔⠒⠉⠲⠤⢀⢄⡀⢩⣣⠦⢷⢼⡏⠈          ⠉⠉⠉ ⠈⠈⠉⠖⠤⠆⠒⠭",
            "⠶⢽⡲⣽⡆             ⠈⣠⣽⣯⡼⢯⣘⡯⠃⠘⡆ ⢰⠒⠁ ⢾⣚⠟    ⢀⠆ ⣔⠆ ⢷⠾⠋⠁    ⠙⠁                     ⠠⡤",
            "  ⠠⢧⣄⣀⡶⠦⠤⡀        ⢰⡁ ⠉⡻⠙⣎⡥  ⠘⠲⠇       ⢀⡀⠨⣁⡄⣸⢫⡤⠄                        ⣀⢠⣤⠊⣼⠅⠖⠋⠁",
            "   ⣠⠾⠛⠁  ⠈⣱        ⠋⠦⢤⡼ ⠈⠈⠦⡀         ⢀⣿⣇ ⢹⣷⣂⡞⠃                       ⢀⣂⡀  ⠏⣜    ",
            "          ⠙⣷⡄        ⠘⠆ ⢀⣀⡠⣗         ⠘⣻⣽⡟⠉⠈                           ⢹⡇  ⠟⠁    ",
            "           ⠈⡟           ⢎⣻⡿⠾⠇         ⠘⠇  ⣀⡀  ⣤⣤⡆ ⡠⡦                 ⢀⠎⡏        ",
            "            ⡇          ⣀⠏⠋           ⢸⠒⢃⡖⢻⢟⣷⣄⣰⣡⠥⣱ ⢏⣧              ⣀ ⡴⠚⢰⠟        ",
            "            ⢳         ⢸⠃             ⠸⣄⣼⣠⢼⡴⡟⢿⢿⣀⣄  ⠸⡹             ⠘⡯⢿⡇⡠⢼⠁        ",
            "             ⢳⣀      ⢀⠞⠁             ⢠⠋⠁ ⠐⠧⡄⣬⣉⣈⡽                  ⢧⠘⢽⠟⠉         ",
            "              ⣿⣄  ⡴⠚⠛⣿⣀             ⢠⠖     ⠈⠁ ⠹⣧  ⢾⣄⡀             ⡼ ⠈           ",
            "    ⣀         ⠘⣿⡄ ⡇  ⣘⣻             ⡏          ⢻⡄ ⠘⠿⢿⠒⠲⡀   ⢀⡀   ⢀⡰⣗             ",
            "    ⠉⠷          ⢫⡀⢧⡼⡟⠉⣛⣳⣦⡀         ⠈⡇          ⠸⣱  ⢀⡼  ⢺  ⡸⠉⢇  ⣾⡏ ⣁             ",
            "                 ⠉⠒⢆⡓⡆             ⠠⡃           ⢳⣇⡠⠏   ⠐⡄⡞  ⠘⣇⡀⢱  ⣾⡀            ",
            "                    ⢹⣇⣀⣾⡷⠤⡆         ⢣            ⠯⢺⠇    ⢣⣅   ⣽⢱⡔ ⢠⢿⣗            ",
            "                     ⠙⢱   ⠘⠦⡄       ⠈⢦⡠⣠⢶⣀        ⡜     ⠈⠿  ⢠⣽⢆ ⢀⣼⡜⠿            ",
            "                     ⢀⡞     ⢱⡀           ⢸       ⡔⠁          ⢻⢿⢰⠏⢸⣤⣴⣆           ",
            "                     ⢘⠆      ⠙⠢⢄         ⠸⡀     ⡸⠁           ⠈⣞⡎⠥⡟⣿⠠⠿⣷⠒⢤⢀⣆      ",
            "                     ⠘⠆        ⢈⠂         ⢳     ⡇             ⠈⠳⠶⣤⣭⣠ ⠋⢧⡬⣟⠉⠷⡄    ",
            "                      ⢨        ⡜          ⢸     ⠸ ⣠               ⠁⢁⣰⢶ ⡇⠉⠁ ⠛    ",
            "⠆                     ⠈⢱⡀      ⡆          ⡇    ⢀⡜⡴⢹               ⢰⠏⠁⠘⢶⠹⡀   ⠸ ⢠⡶",
            "                        ⠅     ⣸           ⢸    ⢫ ⡞⡊             ⢠⠔⠋     ⢳⡀ ⠐⣦   ",
            "                        ⡅    ⡏            ⠈⡆  ⢠⠎ ⠳⠃             ⢸        ⢳      ",
            "                       ⠨    ⡸⠁             ⢱  ⡸                 ⠈⡇ ⢀⣀⡀   ⢸      ",
            "                       ⠸  ⠐⡶⠁              ⠘⠖⠚                   ⠣⠒⠋ ⠱⣇ ⢀⠇   ⠰⡄ ",
            "                       ⠽ ⣰⡖⠁                                          ⠘⢚⡊    ⢀⣿⠇",
            "                       ⡯⢀⡟                                             ⠘⠏   ⢠⢾⠃ ",
            "                       ⠇⢨⠆                            ⢠⡄                    ⠈⠁  ",
            "                       ⢧⣷⡀⠚                                                     ",
            "                        ⠉⠁                                                      ",
            "                          ⢀⡀                                                    ",
            "                        ⢠⡾⠋                      ⣀⡠⠖⢦⣀⣀  ⣀⠤⠦⢤⠤⠶⠤⠖⠦⠤⠤⠤⠴⠤⢤⣄       ",
            "                ⢀⣤⣀ ⡀  ⣼⣻⠙⡆         ⢀⡤⠤⠤⠴⠒⠖⠒⠒⠒⠚⠉⠋⠁    ⢰⡳⠊⠁              ⠈⠉⠉⠒⠤⣤  ",
            "    ⢀⣀⣀⡴⠖⠒⠒⠚⠛⠛⠛⠒⠚⠳⠉⠉⠉⠉⢉⣉⡥⠔⠃     ⢀⣠⠤⠴⠃                                      ⢠⠞⠁  ",
            "   ⠘⠛⣓⣒⠆              ⠸⠥⣀⣤⡦⠠⣞⣭⣇⣘⠿⠆                                         ⣖⠛   ",
            "⠶⠔⠲⠤⠠⠜⢗⠤⠄                 ⠘⠉  ⠁                                            ⠈⠉⠒⠔⠤",
            "                                                                                ",
        ]);
        assert_eq!(buffer, expected);
    }
}