From c05d2850420a2c163b8f62c33a6cef7c0ae1ad8d Mon Sep 17 00:00:00 2001 From: Vladislav Stepanov <8uk.8ak@gmail.com> Date: Fri, 14 Apr 2023 23:18:58 +0400 Subject: Workspace reorder (#868) * Try different workspace structure Move main crate (atuin) to be on the same level with other crates in this workspace * extract common dependencies to the workspace definition * fix base64 v0.21 deprecation warning * questionable: update deps & fix chrono deprecations possible panic sites are unchanged, they're just more visible now * Revert "questionable: update deps & fix chrono deprecations" This reverts commit 993e60f8dea81a1625a04285a617959ad09a0866. --- src/ratatui/widgets/barchart.rs | 219 -- src/ratatui/widgets/block.rs | 573 --- src/ratatui/widgets/canvas/line.rs | 95 - src/ratatui/widgets/canvas/map.rs | 48 - src/ratatui/widgets/canvas/mod.rs | 510 --- src/ratatui/widgets/canvas/points.rs | 30 - src/ratatui/widgets/canvas/rectangle.rs | 52 - src/ratatui/widgets/canvas/world.rs | 6299 ------------------------------- src/ratatui/widgets/chart.rs | 660 ---- src/ratatui/widgets/clear.rs | 37 - src/ratatui/widgets/gauge.rs | 313 -- src/ratatui/widgets/list.rs | 268 -- src/ratatui/widgets/mod.rs | 184 - src/ratatui/widgets/paragraph.rs | 214 -- src/ratatui/widgets/reflow.rs | 534 --- src/ratatui/widgets/sparkline.rs | 155 - src/ratatui/widgets/table.rs | 504 --- src/ratatui/widgets/tabs.rs | 129 - 18 files changed, 10824 deletions(-) delete mode 100644 src/ratatui/widgets/barchart.rs delete mode 100644 src/ratatui/widgets/block.rs delete mode 100644 src/ratatui/widgets/canvas/line.rs delete mode 100644 src/ratatui/widgets/canvas/map.rs delete mode 100644 src/ratatui/widgets/canvas/mod.rs delete mode 100644 src/ratatui/widgets/canvas/points.rs delete mode 100644 src/ratatui/widgets/canvas/rectangle.rs delete mode 100644 src/ratatui/widgets/canvas/world.rs delete mode 100644 src/ratatui/widgets/chart.rs delete mode 100644 src/ratatui/widgets/clear.rs delete mode 100644 src/ratatui/widgets/gauge.rs delete mode 100644 src/ratatui/widgets/list.rs delete mode 100644 src/ratatui/widgets/mod.rs delete mode 100644 src/ratatui/widgets/paragraph.rs delete mode 100644 src/ratatui/widgets/reflow.rs delete mode 100644 src/ratatui/widgets/sparkline.rs delete mode 100644 src/ratatui/widgets/table.rs delete mode 100644 src/ratatui/widgets/tabs.rs (limited to 'src/ratatui/widgets') diff --git a/src/ratatui/widgets/barchart.rs b/src/ratatui/widgets/barchart.rs deleted file mode 100644 index 13f386a4..00000000 --- a/src/ratatui/widgets/barchart.rs +++ /dev/null @@ -1,219 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::Rect, - style::Style, - symbols, - widgets::{Block, Widget}, -}; -use std::cmp::min; -use unicode_width::UnicodeWidthStr; - -/// Display multiple bars in a single widgets -/// -/// # Examples -/// -/// ``` -/// # use ratatui::widgets::{Block, Borders, BarChart}; -/// # use ratatui::style::{Style, Color, Modifier}; -/// BarChart::default() -/// .block(Block::default().title("BarChart").borders(Borders::ALL)) -/// .bar_width(3) -/// .bar_gap(1) -/// .bar_style(Style::default().fg(Color::Yellow).bg(Color::Red)) -/// .value_style(Style::default().fg(Color::Red).add_modifier(Modifier::BOLD)) -/// .label_style(Style::default().fg(Color::White)) -/// .data(&[("B0", 0), ("B1", 2), ("B2", 4), ("B3", 3)]) -/// .max(4); -/// ``` -#[derive(Debug, Clone)] -pub struct BarChart<'a> { - /// Block to wrap the widget in - block: Option>, - /// The width of each bar - bar_width: u16, - /// The gap between each bar - bar_gap: u16, - /// Set of symbols used to display the data - bar_set: symbols::bar::Set, - /// Style of the bars - bar_style: Style, - /// Style of the values printed at the bottom of each bar - value_style: Style, - /// Style of the labels printed under each bar - label_style: Style, - /// Style for the widget - style: Style, - /// Slice of (label, value) pair to plot on the chart - data: &'a [(&'a str, u64)], - /// Value necessary for a bar to reach the maximum height (if no value is specified, - /// the maximum value in the data is taken as reference) - max: Option, - /// Values to display on the bar (computed when the data is passed to the widget) - values: Vec, -} - -impl<'a> Default for BarChart<'a> { - fn default() -> BarChart<'a> { - BarChart { - block: None, - max: None, - data: &[], - values: Vec::new(), - bar_style: Style::default(), - bar_width: 1, - bar_gap: 1, - bar_set: symbols::bar::NINE_LEVELS, - value_style: Default::default(), - label_style: Default::default(), - style: Default::default(), - } - } -} - -impl<'a> BarChart<'a> { - pub fn data(mut self, data: &'a [(&'a str, u64)]) -> BarChart<'a> { - self.data = data; - self.values = Vec::with_capacity(self.data.len()); - for &(_, v) in self.data { - self.values.push(format!("{}", v)); - } - self - } - - pub fn block(mut self, block: Block<'a>) -> BarChart<'a> { - self.block = Some(block); - self - } - - pub fn max(mut self, max: u64) -> BarChart<'a> { - self.max = Some(max); - self - } - - pub fn bar_style(mut self, style: Style) -> BarChart<'a> { - self.bar_style = style; - self - } - - pub fn bar_width(mut self, width: u16) -> BarChart<'a> { - self.bar_width = width; - self - } - - pub fn bar_gap(mut self, gap: u16) -> BarChart<'a> { - self.bar_gap = gap; - self - } - - pub fn bar_set(mut self, bar_set: symbols::bar::Set) -> BarChart<'a> { - self.bar_set = bar_set; - self - } - - pub fn value_style(mut self, style: Style) -> BarChart<'a> { - self.value_style = style; - self - } - - pub fn label_style(mut self, style: Style) -> BarChart<'a> { - self.label_style = style; - self - } - - pub fn style(mut self, style: Style) -> BarChart<'a> { - self.style = style; - self - } -} - -impl<'a> Widget for BarChart<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - buf.set_style(area, self.style); - - let chart_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - if chart_area.height < 2 { - return; - } - - let max = self - .max - .unwrap_or_else(|| self.data.iter().map(|t| t.1).max().unwrap_or_default()); - let max_index = min( - (chart_area.width / (self.bar_width + self.bar_gap)) as usize, - self.data.len(), - ); - let mut data = self - .data - .iter() - .take(max_index) - .map(|&(l, v)| { - ( - l, - v * u64::from(chart_area.height - 1) * 8 / std::cmp::max(max, 1), - ) - }) - .collect::>(); - for j in (0..chart_area.height - 1).rev() { - for (i, d) in data.iter_mut().enumerate() { - let symbol = match d.1 { - 0 => self.bar_set.empty, - 1 => self.bar_set.one_eighth, - 2 => self.bar_set.one_quarter, - 3 => self.bar_set.three_eighths, - 4 => self.bar_set.half, - 5 => self.bar_set.five_eighths, - 6 => self.bar_set.three_quarters, - 7 => self.bar_set.seven_eighths, - _ => self.bar_set.full, - }; - - for x in 0..self.bar_width { - buf.get_mut( - chart_area.left() + i as u16 * (self.bar_width + self.bar_gap) + x, - chart_area.top() + j, - ) - .set_symbol(symbol) - .set_style(self.bar_style); - } - - if d.1 > 8 { - d.1 -= 8; - } else { - d.1 = 0; - } - } - } - - for (i, &(label, value)) in self.data.iter().take(max_index).enumerate() { - if value != 0 { - let value_label = &self.values[i]; - let width = value_label.width() as u16; - if width < self.bar_width { - buf.set_string( - chart_area.left() - + i as u16 * (self.bar_width + self.bar_gap) - + (self.bar_width - width) / 2, - chart_area.bottom() - 2, - value_label, - self.value_style, - ); - } - } - buf.set_stringn( - chart_area.left() + i as u16 * (self.bar_width + self.bar_gap), - chart_area.bottom() - 1, - label, - self.bar_width as usize, - self.label_style, - ); - } - } -} diff --git a/src/ratatui/widgets/block.rs b/src/ratatui/widgets/block.rs deleted file mode 100644 index 20b43614..00000000 --- a/src/ratatui/widgets/block.rs +++ /dev/null @@ -1,573 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::{Alignment, Rect}, - style::Style, - symbols::line, - text::{Span, Spans}, - widgets::{Borders, Widget}, -}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum BorderType { - Plain, - Rounded, - Double, - Thick, -} - -impl BorderType { - pub fn line_symbols(border_type: BorderType) -> line::Set { - match border_type { - BorderType::Plain => line::NORMAL, - BorderType::Rounded => line::ROUNDED, - BorderType::Double => line::DOUBLE, - BorderType::Thick => line::THICK, - } - } -} - -/// Base widget to be used with all upper level ones. It may be used to display a box border around -/// the widget and/or add a title. -/// -/// # Examples -/// -/// ``` -/// # use ratatui::widgets::{Block, BorderType, Borders}; -/// # use ratatui::style::{Style, Color}; -/// Block::default() -/// .title("Block") -/// .borders(Borders::LEFT | Borders::RIGHT) -/// .border_style(Style::default().fg(Color::White)) -/// .border_type(BorderType::Rounded) -/// .style(Style::default().bg(Color::Black)); -/// ``` -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Block<'a> { - /// Optional title place on the upper left of the block - title: Option>, - /// Title alignment. The default is top left of the block, but one can choose to place - /// title in the top middle, or top right of the block - title_alignment: Alignment, - /// Visible borders - borders: Borders, - /// Border style - border_style: Style, - /// Type of the border. The default is plain lines but one can choose to have rounded corners - /// or doubled lines instead. - border_type: BorderType, - /// Widget style - style: Style, -} - -impl<'a> Default for Block<'a> { - fn default() -> Block<'a> { - Block { - title: None, - title_alignment: Alignment::Left, - borders: Borders::NONE, - border_style: Default::default(), - border_type: BorderType::Plain, - style: Default::default(), - } - } -} - -impl<'a> Block<'a> { - pub fn title(mut self, title: T) -> Block<'a> - where - T: Into>, - { - self.title = Some(title.into()); - self - } - - #[deprecated( - since = "0.10.0", - note = "You should use styling capabilities of `text::Spans` given as argument of the `title` method to apply styling to the title." - )] - pub fn title_style(mut self, style: Style) -> Block<'a> { - if let Some(t) = self.title { - let title = String::from(t); - self.title = Some(Spans::from(Span::styled(title, style))); - } - self - } - - pub fn title_alignment(mut self, alignment: Alignment) -> Block<'a> { - self.title_alignment = alignment; - self - } - - pub fn border_style(mut self, style: Style) -> Block<'a> { - self.border_style = style; - self - } - - pub fn style(mut self, style: Style) -> Block<'a> { - self.style = style; - self - } - - pub fn borders(mut self, flag: Borders) -> Block<'a> { - self.borders = flag; - self - } - - pub fn border_type(mut self, border_type: BorderType) -> Block<'a> { - self.border_type = border_type; - self - } - - /// Compute the inner area of a block based on its border visibility rules. - pub fn inner(&self, area: Rect) -> Rect { - let mut inner = area; - if self.borders.intersects(Borders::LEFT) { - inner.x = inner.x.saturating_add(1).min(inner.right()); - inner.width = inner.width.saturating_sub(1); - } - if self.borders.intersects(Borders::TOP) || self.title.is_some() { - inner.y = inner.y.saturating_add(1).min(inner.bottom()); - inner.height = inner.height.saturating_sub(1); - } - if self.borders.intersects(Borders::RIGHT) { - inner.width = inner.width.saturating_sub(1); - } - if self.borders.intersects(Borders::BOTTOM) { - inner.height = inner.height.saturating_sub(1); - } - inner - } -} - -impl<'a> Widget for Block<'a> { - fn render(self, area: Rect, buf: &mut Buffer) { - if area.area() == 0 { - return; - } - buf.set_style(area, self.style); - let symbols = BorderType::line_symbols(self.border_type); - - // Sides - if self.borders.intersects(Borders::LEFT) { - for y in area.top()..area.bottom() { - buf.get_mut(area.left(), y) - .set_symbol(symbols.vertical) - .set_style(self.border_style); - } - } - if self.borders.intersects(Borders::TOP) { - for x in area.left()..area.right() { - buf.get_mut(x, area.top()) - .set_symbol(symbols.horizontal) - .set_style(self.border_style); - } - } - if self.borders.intersects(Borders::RIGHT) { - let x = area.right() - 1; - for y in area.top()..area.bottom() { - buf.get_mut(x, y) - .set_symbol(symbols.vertical) - .set_style(self.border_style); - } - } - if self.borders.intersects(Borders::BOTTOM) { - let y = area.bottom() - 1; - for x in area.left()..area.right() { - buf.get_mut(x, y) - .set_symbol(symbols.horizontal) - .set_style(self.border_style); - } - } - - // Corners - if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) { - buf.get_mut(area.right() - 1, area.bottom() - 1) - .set_symbol(symbols.bottom_right) - .set_style(self.border_style); - } - if self.borders.contains(Borders::RIGHT | Borders::TOP) { - buf.get_mut(area.right() - 1, area.top()) - .set_symbol(symbols.top_right) - .set_style(self.border_style); - } - if self.borders.contains(Borders::LEFT | Borders::BOTTOM) { - buf.get_mut(area.left(), area.bottom() - 1) - .set_symbol(symbols.bottom_left) - .set_style(self.border_style); - } - if self.borders.contains(Borders::LEFT | Borders::TOP) { - buf.get_mut(area.left(), area.top()) - .set_symbol(symbols.top_left) - .set_style(self.border_style); - } - - // Title - if let Some(title) = self.title { - let left_border_dx = if self.borders.intersects(Borders::LEFT) { - 1 - } else { - 0 - }; - - let right_border_dx = if self.borders.intersects(Borders::RIGHT) { - 1 - } else { - 0 - }; - - let title_area_width = area - .width - .saturating_sub(left_border_dx) - .saturating_sub(right_border_dx); - - let title_dx = match self.title_alignment { - Alignment::Left => left_border_dx, - Alignment::Center => area.width.saturating_sub(title.width() as u16) / 2, - Alignment::Right => area - .width - .saturating_sub(title.width() as u16) - .saturating_sub(right_border_dx), - }; - - let title_x = area.left() + title_dx; - let title_y = area.top(); - - buf.set_spans(title_x, title_y, &title, title_area_width); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::ratatui::layout::Rect; - - #[test] - fn inner_takes_into_account_the_borders() { - // No borders - assert_eq!( - Block::default().inner(Rect::default()), - Rect { - x: 0, - y: 0, - width: 0, - height: 0 - }, - "no borders, width=0, height=0" - ); - assert_eq!( - Block::default().inner(Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }), - Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }, - "no borders, width=1, height=1" - ); - - // Left border - assert_eq!( - Block::default().borders(Borders::LEFT).inner(Rect { - x: 0, - y: 0, - width: 0, - height: 1 - }), - Rect { - x: 0, - y: 0, - width: 0, - height: 1 - }, - "left, width=0" - ); - assert_eq!( - Block::default().borders(Borders::LEFT).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }), - Rect { - x: 1, - y: 0, - width: 0, - height: 1 - }, - "left, width=1" - ); - assert_eq!( - Block::default().borders(Borders::LEFT).inner(Rect { - x: 0, - y: 0, - width: 2, - height: 1 - }), - Rect { - x: 1, - y: 0, - width: 1, - height: 1 - }, - "left, width=2" - ); - - // Top border - assert_eq!( - Block::default().borders(Borders::TOP).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 0 - }), - Rect { - x: 0, - y: 0, - width: 1, - height: 0 - }, - "top, height=0" - ); - assert_eq!( - Block::default().borders(Borders::TOP).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }), - Rect { - x: 0, - y: 1, - width: 1, - height: 0 - }, - "top, height=1" - ); - assert_eq!( - Block::default().borders(Borders::TOP).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 2 - }), - Rect { - x: 0, - y: 1, - width: 1, - height: 1 - }, - "top, height=2" - ); - - // Right border - assert_eq!( - Block::default().borders(Borders::RIGHT).inner(Rect { - x: 0, - y: 0, - width: 0, - height: 1 - }), - Rect { - x: 0, - y: 0, - width: 0, - height: 1 - }, - "right, width=0" - ); - assert_eq!( - Block::default().borders(Borders::RIGHT).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }), - Rect { - x: 0, - y: 0, - width: 0, - height: 1 - }, - "right, width=1" - ); - assert_eq!( - Block::default().borders(Borders::RIGHT).inner(Rect { - x: 0, - y: 0, - width: 2, - height: 1 - }), - Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }, - "right, width=2" - ); - - // Bottom border - assert_eq!( - Block::default().borders(Borders::BOTTOM).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 0 - }), - Rect { - x: 0, - y: 0, - width: 1, - height: 0 - }, - "bottom, height=0" - ); - assert_eq!( - Block::default().borders(Borders::BOTTOM).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }), - Rect { - x: 0, - y: 0, - width: 1, - height: 0 - }, - "bottom, height=1" - ); - assert_eq!( - Block::default().borders(Borders::BOTTOM).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 2 - }), - Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }, - "bottom, height=2" - ); - - // All borders - assert_eq!( - Block::default() - .borders(Borders::ALL) - .inner(Rect::default()), - Rect { - x: 0, - y: 0, - width: 0, - height: 0 - }, - "all borders, width=0, height=0" - ); - assert_eq!( - Block::default().borders(Borders::ALL).inner(Rect { - x: 0, - y: 0, - width: 1, - height: 1 - }), - Rect { - x: 1, - y: 1, - width: 0, - height: 0, - }, - "all borders, width=1, height=1" - ); - assert_eq!( - Block::default().borders(Borders::ALL).inner(Rect { - x: 0, - y: 0, - width: 2, - height: 2, - }), - Rect { - x: 1, - y: 1, - width: 0, - height: 0, - }, - "all borders, width=2, height=2" - ); - assert_eq!( - Block::default().borders(Borders::ALL).inner(Rect { - x: 0, - y: 0, - width: 3, - height: 3, - }), - Rect { - x: 1, - y: 1, - width: 1, - height: 1, - }, - "all borders, width=3, height=3" - ); - } - - #[test] - fn inner_takes_into_account_the_title() { - assert_eq!( - Block::default().title("Test").inner(Rect { - x: 0, - y: 0, - width: 0, - height: 1, - }), - Rect { - x: 0, - y: 1, - width: 0, - height: 0, - }, - ); - assert_eq!( - Block::default() - .title("Test") - .title_alignment(Alignment::Center) - .inner(Rect { - x: 0, - y: 0, - width: 0, - height: 1, - }), - Rect { - x: 0, - y: 1, - width: 0, - height: 0, - }, - ); - assert_eq!( - Block::default() - .title("Test") - .title_alignment(Alignment::Right) - .inner(Rect { - x: 0, - y: 0, - width: 0, - height: 1, - }), - Rect { - x: 0, - y: 1, - width: 0, - height: 0, - }, - ); - } -} diff --git a/src/ratatui/widgets/canvas/line.rs b/src/ratatui/widgets/canvas/line.rs deleted file mode 100644 index 84d121ce..00000000 --- a/src/ratatui/widgets/canvas/line.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::ratatui::{ - style::Color, - widgets::canvas::{Painter, Shape}, -}; - -/// Shape to draw a line from (x1, y1) to (x2, y2) with the given color -#[derive(Debug, Clone)] -pub struct Line { - pub x1: f64, - pub y1: f64, - pub x2: f64, - pub y2: f64, - pub color: Color, -} - -impl Shape for Line { - fn draw(&self, painter: &mut Painter) { - let (x1, y1) = match painter.get_point(self.x1, self.y1) { - Some(c) => c, - None => return, - }; - let (x2, y2) = match painter.get_point(self.x2, self.y2) { - Some(c) => c, - None => return, - }; - let (dx, x_range) = if x2 >= x1 { - (x2 - x1, x1..=x2) - } else { - (x1 - x2, x2..=x1) - }; - let (dy, y_range) = if y2 >= y1 { - (y2 - y1, y1..=y2) - } else { - (y1 - y2, y2..=y1) - }; - - if dx == 0 { - for y in y_range { - painter.paint(x1, y, self.color); - } - } else if dy == 0 { - for x in x_range { - painter.paint(x, y1, self.color); - } - } else if dy < dx { - if x1 > x2 { - draw_line_low(painter, x2, y2, x1, y1, self.color); - } else { - draw_line_low(painter, x1, y1, x2, y2, self.color); - } - } else if y1 > y2 { - draw_line_high(painter, x2, y2, x1, y1, self.color); - } else { - draw_line_high(painter, x1, y1, x2, y2, self.color); - } - } -} - -fn draw_line_low(painter: &mut Painter, x1: usize, y1: usize, x2: usize, y2: usize, color: Color) { - let dx = (x2 - x1) as isize; - let dy = (y2 as isize - y1 as isize).abs(); - let mut d = 2 * dy - dx; - let mut y = y1; - for x in x1..=x2 { - painter.paint(x, y, color); - if d > 0 { - y = if y1 > y2 { - y.saturating_sub(1) - } else { - y.saturating_add(1) - }; - d -= 2 * dx; - } - d += 2 * dy; - } -} - -fn draw_line_high(painter: &mut Painter, x1: usize, y1: usize, x2: usize, y2: usize, color: Color) { - let dx = (x2 as isize - x1 as isize).abs(); - let dy = (y2 - y1) as isize; - let mut d = 2 * dx - dy; - let mut x = x1; - for y in y1..=y2 { - painter.paint(x, y, color); - if d > 0 { - x = if x1 > x2 { - x.saturating_sub(1) - } else { - x.saturating_add(1) - }; - d -= 2 * dy; - } - d += 2 * dx; - } -} diff --git a/src/ratatui/widgets/canvas/map.rs b/src/ratatui/widgets/canvas/map.rs deleted file mode 100644 index d835dd31..00000000 --- a/src/ratatui/widgets/canvas/map.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::ratatui::{ - style::Color, - widgets::canvas::{ - world::{WORLD_HIGH_RESOLUTION, WORLD_LOW_RESOLUTION}, - Painter, Shape, - }, -}; - -#[derive(Debug, Clone, Copy)] -pub enum MapResolution { - Low, - High, -} - -impl MapResolution { - fn data(self) -> &'static [(f64, f64)] { - match self { - MapResolution::Low => &WORLD_LOW_RESOLUTION, - MapResolution::High => &WORLD_HIGH_RESOLUTION, - } - } -} - -/// Shape to draw a world map with the given resolution and color -#[derive(Debug, Clone)] -pub struct Map { - pub resolution: MapResolution, - pub color: Color, -} - -impl Default for Map { - fn default() -> Map { - Map { - resolution: MapResolution::Low, - color: Color::Reset, - } - } -} - -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); - } - } - } -} diff --git a/src/ratatui/widgets/canvas/mod.rs b/src/ratatui/widgets/canvas/mod.rs deleted file mode 100644 index 7b174596..00000000 --- a/src/ratatui/widgets/canvas/mod.rs +++ /dev/null @@ -1,510 +0,0 @@ -mod line; -mod map; -mod points; -mod rectangle; -mod world; - -pub use self::line::Line; -pub use self::map::{Map, MapResolution}; -pub use self::points::Points; -pub use self::rectangle::Rectangle; - -use crate::ratatui::{ - buffer::Buffer, - layout::Rect, - style::{Color, Style}, - symbols, - text::Spans, - widgets::{Block, Widget}, -}; -use std::fmt::Debug; - -/// Interface for all shapes that may be drawn on a Canvas widget. -pub trait Shape { - fn draw(&self, painter: &mut Painter); -} - -/// Label to draw some text on the canvas -#[derive(Debug, Clone)] -pub struct Label<'a> { - x: f64, - y: f64, - spans: Spans<'a>, -} - -#[derive(Debug, Clone)] -struct Layer { - string: String, - colors: Vec, -} - -trait Grid: Debug { - fn width(&self) -> u16; - fn height(&self) -> u16; - fn resolution(&self) -> (f64, f64); - fn paint(&mut self, x: usize, y: usize, color: Color); - fn save(&self) -> Layer; - fn reset(&mut self); -} - -#[derive(Debug, Clone)] -struct BrailleGrid { - width: u16, - height: u16, - cells: Vec, - colors: Vec, -} - -impl BrailleGrid { - fn new(width: u16, height: u16) -> BrailleGrid { - let length = usize::from(width * height); - BrailleGrid { - width, - height, - cells: vec![symbols::braille::BLANK; length], - colors: vec![Color::Reset; length], - } - } -} - -impl Grid for BrailleGrid { - fn width(&self) -> u16 { - self.width - } - - fn height(&self) -> u16 { - self.height - } - - fn resolution(&self) -> (f64, f64) { - ( - f64::from(self.width) * 2.0 - 1.0, - f64::from(self.height) * 4.0 - 1.0, - ) - } - - fn save(&self) -> Layer { - Layer { - string: String::from_utf16(&self.cells).unwrap(), - colors: self.colors.clone(), - } - } - - fn reset(&mut self) { - for c in &mut self.cells { - *c = symbols::braille::BLANK; - } - for c in &mut self.colors { - *c = Color::Reset; - } - } - - fn paint(&mut self, x: usize, y: usize, color: Color) { - let index = y / 4 * self.width as usize + x / 2; - if let Some(c) = self.cells.get_mut(index) { - *c |= symbols::braille::DOTS[y % 4][x % 2]; - } - if let Some(c) = self.colors.get_mut(index) { - *c = color; - } - } -} - -#[derive(Debug, Clone)] -struct CharGrid { - width: u16, - height: u16, - cells: Vec, - colors: Vec, - cell_char: char, -} - -impl CharGrid { - fn new(width: u16, height: u16, cell_char: char) -> CharGrid { - let length = usize::from(width * height); - CharGrid { - width, - height, - cells: vec![' '; length], - colors: vec![Color::Reset; length], - cell_char, - } - } -} - -impl Grid for CharGrid { - fn width(&self) -> u16 { - self.width - } - - fn height(&self) -> u16 { - self.height - } - - fn resolution(&self) -> (f64, f64) { - (f64::from(self.width) - 1.0, f64::from(self.height) - 1.0) - } - - fn save(&self) -> Layer { - Layer { - string: self.cells.iter().collect(), - colors: self.colors.clone(), - } - } - - fn reset(&mut self) { - for c in &mut self.cells { - *c = ' '; - } - for c in &mut self.colors { - *c = Color::Reset; - } - } - - fn paint(&mut self, x: usize, y: usize, color: Color) { - let index = y * self.width as usize + x; - if let Some(c) = self.cells.get_mut(index) { - *c = self.cell_char; - } - if let Some(c) = self.colors.get_mut(index) { - *c = color; - } - } -} - -#[derive(Debug)] -pub struct Painter<'a, 'b> { - context: &'a mut Context<'b>, - resolution: (f64, f64), -} - -impl<'a, 'b> Painter<'a, 'b> { - /// Convert the (x, y) coordinates to location of a point on the grid - /// - /// # Examples: - /// ``` - /// use ratatui::{symbols, widgets::canvas::{Painter, Context}}; - /// - /// let mut ctx = Context::new(2, 2, [1.0, 2.0], [0.0, 2.0], symbols::Marker::Braille); - /// let mut painter = Painter::from(&mut ctx); - /// let point = painter.get_point(1.0, 0.0); - /// assert_eq!(point, Some((0, 7))); - /// let point = painter.get_point(1.5, 1.0); - /// assert_eq!(point, Some((1, 3))); - /// let point = painter.get_point(0.0, 0.0); - /// assert_eq!(point, None); - /// let point = painter.get_point(2.0, 2.0); - /// assert_eq!(point, Some((3, 0))); - /// let point = painter.get_point(1.0, 2.0); - /// assert_eq!(point, Some((0, 0))); - /// ``` - pub fn get_point(&self, x: f64, y: f64) -> Option<(usize, usize)> { - let left = self.context.x_bounds[0]; - let right = self.context.x_bounds[1]; - let top = self.context.y_bounds[1]; - let bottom = self.context.y_bounds[0]; - if x < left || x > right || y < bottom || y > top { - return None; - } - let width = (self.context.x_bounds[1] - self.context.x_bounds[0]).abs(); - let height = (self.context.y_bounds[1] - self.context.y_bounds[0]).abs(); - if width == 0.0 || height == 0.0 { - return None; - } - let x = ((x - left) * self.resolution.0 / width) as usize; - let y = ((top - y) * self.resolution.1 / height) as usize; - Some((x, y)) - } - - /// Paint a point of the grid - /// - /// # Examples: - /// ``` - /// use ratatui::{style::Color, symbols, widgets::canvas::{Painter, Context}}; - /// - /// let mut ctx = Context::new(1, 1, [0.0, 2.0], [0.0, 2.0], symbols::Marker::Braille); - /// let mut painter = Painter::from(&mut ctx); - /// let cell = painter.paint(1, 3, Color::Red); - /// ``` - pub fn paint(&mut self, x: usize, y: usize, color: Color) { - self.context.grid.paint(x, y, color); - } -} - -impl<'a, 'b> From<&'a mut Context<'b>> for Painter<'a, 'b> { - fn from(context: &'a mut Context<'b>) -> Painter<'a, 'b> { - let resolution = context.grid.resolution(); - Painter { - context, - resolution, - } - } -} - -/// Holds the state of the Canvas when painting to it. -#[derive(Debug)] -pub struct Context<'a> { - x_bounds: [f64; 2], - y_bounds: [f64; 2], - grid: Box, - dirty: bool, - layers: Vec, - labels: Vec>, -} - -impl<'a> Context<'a> { - pub fn new( - width: u16, - height: u16, - x_bounds: [f64; 2], - y_bounds: [f64; 2], - marker: symbols::Marker, - ) -> Context<'a> { - let grid: Box = match marker { - symbols::Marker::Dot => Box::new(CharGrid::new(width, height, '•')), - symbols::Marker::Block => Box::new(CharGrid::new(width, height, '▄')), - symbols::Marker::Braille => Box::new(BrailleGrid::new(width, height)), - }; - Context { - x_bounds, - y_bounds, - grid, - dirty: false, - layers: Vec::new(), - labels: Vec::new(), - } - } - - /// Draw any object that may implement the Shape trait - pub fn draw(&mut self, shape: &S) - where - S: Shape, - { - self.dirty = true; - let mut painter = Painter::from(self); - shape.draw(&mut painter); - } - - /// Go one layer above in the canvas. - pub fn layer(&mut self) { - self.layers.push(self.grid.save()); - self.grid.reset(); - self.dirty = false; - } - - /// Print a string on the canvas at the given position - pub fn print(&mut self, x: f64, y: f64, spans: T) - where - T: Into>, - { - self.labels.push(Label { - x, - y, - spans: spans.into(), - }); - } - - /// Push the last layer if necessary - fn finish(&mut self) { - if self.dirty { - self.layer() - } - } -} - -/// The Canvas widget may be used to draw more detailed figures using braille patterns (each -/// cell can have a braille character in 8 different positions). -/// # Examples -/// -/// ``` -/// # use ratatui::widgets::{Block, Borders}; -/// # use ratatui::layout::Rect; -/// # use ratatui::widgets::canvas::{Canvas, Shape, Line, Rectangle, Map, MapResolution}; -/// # use ratatui::style::Color; -/// Canvas::default() -/// .block(Block::default().title("Canvas").borders(Borders::ALL)) -/// .x_bounds([-180.0, 180.0]) -/// .y_bounds([-90.0, 90.0]) -/// .paint(|ctx| { -/// ctx.draw(&Map { -/// resolution: MapResolution::High, -/// color: Color::White -/// }); -/// ctx.layer(); -/// ctx.draw(&Line { -/// x1: 0.0, -/// y1: 10.0, -/// x2: 10.0, -/// y2: 10.0, -/// color: Color::White, -/// }); -/// ctx.draw(&Rectangle { -/// x: 10.0, -/// y: 20.0, -/// width: 10.0, -/// height: 10.0, -/// color: Color::Red -/// }); -/// }); -/// ``` -pub struct Canvas<'a, F> -where - F: Fn(&mut Context), -{ - block: Option>, - x_bounds: [f64; 2], - y_bounds: [f64; 2], - painter: Option, - background_color: Color, - marker: symbols::Marker, -} - -impl<'a, F> Default for Canvas<'a, F> -where - F: Fn(&mut Context), -{ - fn default() -> Canvas<'a, F> { - Canvas { - block: None, - x_bounds: [0.0, 0.0], - y_bounds: [0.0, 0.0], - painter: None, - background_color: Color::Reset, - marker: symbols::Marker::Braille, - } - } -} - -impl<'a, F> Canvas<'a, F> -where - F: Fn(&mut Context), -{ - pub fn block(mut self, block: Block<'a>) -> Canvas<'a, F> { - self.block = Some(block); - self - } - - /// Define the viewport of the canvas. - /// If you were to "zoom" to a certain part of the world you may want to choose different - /// bounds. - pub fn x_bounds(mut self, bounds: [f64; 2]) -> Canvas<'a, F> { - self.x_bounds = bounds; - self - } - - /// Define the viewport of the canvas. - /// - /// If you were to "zoom" to a certain part of the world you may want to choose different - /// bounds. - pub fn y_bounds(mut self, bounds: [f64; 2]) -> Canvas<'a, F> { - self.y_bounds = bounds; - self - } - - /// Store the closure that will be used to draw to the Canvas - pub fn paint(mut self, f: F) -> Canvas<'a, F> { - self.painter = Some(f); - self - } - - pub fn background_color(mut self, color: Color) -> Canvas<'a, F> { - self.background_color = color; - self - } - - /// Change the type of points used to draw the shapes. By default the braille patterns are used - /// as they provide a more fine grained result but you might want to use the simple dot or - /// block instead if the targeted terminal does not support those symbols. - /// - /// # Examples - /// - /// ``` - /// # use ratatui::widgets::canvas::Canvas; - /// # use ratatui::symbols; - /// Canvas::default().marker(symbols::Marker::Braille).paint(|ctx| {}); - /// - /// Canvas::default().marker(symbols::Marker::Dot).paint(|ctx| {}); - /// - /// Canvas::default().marker(symbols::Marker::Block).paint(|ctx| {}); - /// ``` - pub fn marker(mut self, marker: symbols::Marker) -> Canvas<'a, F> { - self.marker = marker; - self - } -} - -impl<'a, F> Widget for Canvas<'a, F> -where - F: Fn(&mut Context), -{ - fn render(mut self, area: Rect, buf: &mut Buffer) { - let canvas_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - buf.set_style(canvas_area, Style::default().bg(self.background_color)); - - let width = canvas_area.width as usize; - - let painter = match self.painter { - Some(ref p) => p, - None => return, - }; - - // Create a blank context that match the size of the canvas - let mut ctx = Context::new( - canvas_area.width, - canvas_area.height, - self.x_bounds, - self.y_bounds, - self.marker, - ); - // Paint to this context - painter(&mut ctx); - ctx.finish(); - - // Retrieve painted points for each layer - for layer in ctx.layers { - for (i, (ch, color)) in layer - .string - .chars() - .zip(layer.colors.into_iter()) - .enumerate() - { - if ch != ' ' && ch != '\u{2800}' { - let (x, y) = (i % width, i / width); - buf.get_mut(x as u16 + canvas_area.left(), y as u16 + canvas_area.top()) - .set_char(ch) - .set_fg(color); - } - } - } - - // Finally draw the labels - let left = self.x_bounds[0]; - let right = self.x_bounds[1]; - let top = self.y_bounds[1]; - let bottom = self.y_bounds[0]; - let width = (self.x_bounds[1] - self.x_bounds[0]).abs(); - let height = (self.y_bounds[1] - self.y_bounds[0]).abs(); - let resolution = { - let width = f64::from(canvas_area.width - 1); - let height = f64::from(canvas_area.height - 1); - (width, height) - }; - for label in ctx - .labels - .iter() - .filter(|l| l.x >= left && l.x <= right && l.y <= top && l.y >= bottom) - { - let x = ((label.x - left) * resolution.0 / width) as u16 + canvas_area.left(); - let y = ((top - label.y) * resolution.1 / height) as u16 + canvas_area.top(); - buf.set_spans(x, y, &label.spans, canvas_area.right() - x); - } - } -} diff --git a/src/ratatui/widgets/canvas/points.rs b/src/ratatui/widgets/canvas/points.rs deleted file mode 100644 index d9f97522..00000000 --- a/src/ratatui/widgets/canvas/points.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::ratatui::{ - style::Color, - widgets::canvas::{Painter, Shape}, -}; - -/// A shape to draw a group of points with the given color -#[derive(Debug, Clone)] -pub struct Points<'a> { - pub coords: &'a [(f64, f64)], - pub color: Color, -} - -impl<'a> Shape for Points<'a> { - fn draw(&self, painter: &mut Painter) { - for (x, y) in self.coords { - if let Some((x, y)) = painter.get_point(*x, *y) { - painter.paint(x, y, self.color); - } - } - } -} - -impl<'a> Default for Points<'a> { - fn default() -> Points<'a> { - Points { - coords: &[], - color: Color::Reset, - } - } -} diff --git a/src/ratatui/widgets/canvas/rectangle.rs b/src/ratatui/widgets/canvas/rectangle.rs deleted file mode 100644 index 07ac9137..00000000 --- a/src/ratatui/widgets/canvas/rectangle.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::ratatui::{ - style::Color, - widgets::canvas::{Line, Painter, Shape}, -}; - -/// Shape to draw a rectangle from a `Rect` with the given color -#[derive(Debug, Clone)] -pub struct Rectangle { - pub x: f64, - pub y: f64, - pub width: f64, - pub height: f64, - pub color: Color, -} - -impl Shape for Rectangle { - fn draw(&self, painter: &mut Painter) { - let lines: [Line; 4] = [ - Line { - x1: self.x, - y1: self.y, - x2: self.x, - y2: self.y + self.height, - color: self.color, - }, - Line { - x1: self.x, - y1: self.y + self.height, - x2: self.x + self.width, - y2: self.y + self.height, - color: self.color, - }, - Line { - x1: self.x + self.width, - y1: self.y, - x2: self.x + self.width, - y2: self.y + self.height, - color: self.color, - }, - Line { - x1: self.x, - y1: self.y, - x2: self.x + self.width, - y2: self.y, - color: self.color, - }, - ]; - for line in &lines { - line.draw(painter); - } - } -} diff --git a/src/ratatui/widgets/canvas/world.rs b/src/ratatui/widgets/canvas/world.rs deleted file mode 100644 index b15b7c32..00000000 --- a/src/ratatui/widgets/canvas/world.rs +++ /dev/null @@ -1,6299 +0,0 @@ -/// [Source data](http://www.gnuplotting.org/plotting-the-world-revisited) - -pub static WORLD_HIGH_RESOLUTION: [(f64, f64); 5125] = [ - (-163.7128, -78.5956), - (-163.1058, -78.2233), - (-161.2451, -78.3801), - (-160.2462, -78.6936), - (-159.4824, -79.0463), - (-159.2081, -79.4970), - (-161.1276, -79.6342), - (-162.4398, -79.2814), - (-163.0274, -78.9287), - (-163.0666, -78.8699), - (-163.7128, -78.5956), - (-6.1978, 53.8675), - (-6.0329, 53.1531), - (-6.7888, 52.2601), - (-8.5616, 51.6693), - (-9.9770, 51.8204), - (-9.1662, 52.8646), - (-9.6885, 53.8813), - (-8.3279, 54.6645), - (-7.5721, 55.1316), - (-6.7338, 55.1728), - (-5.6619, 54.5546), - (-6.1978, 53.8675), - (141.0002, -2.6001), - (142.7352, -3.2891), - (144.5839, -3.8614), - (145.2731, -4.3737), - (145.8297, -4.8764), - (145.9819, -5.4656), - (147.6480, -6.0836), - (147.8911, -6.6140), - (146.9709, -6.7216), - (147.1918, -7.3880), - (148.0846, -8.0441), - (148.7341, -9.1046), - (149.3068, -9.0714), - (149.2666, -9.5144), - (150.0387, -9.6843), - (149.7387, -9.8729), - (150.8016, -10.2936), - (150.6905, -10.5827), - (150.0283, -10.6524), - (149.7823, -10.3932), - (148.9231, -10.2809), - (147.9130, -10.1304), - (147.1354, -9.4924), - (146.5678, -8.9425), - (146.0484, -8.0674), - (144.7441, -7.6301), - (143.8970, -7.9153), - (143.2863, -8.2454), - (143.4139, -8.9830), - (142.6284, -9.3268), - (142.0682, -9.1595), - (141.0338, -9.1178), - (140.1434, -8.2971), - (139.1277, -8.0960), - (138.8814, -8.3809), - (137.6144, -8.4116), - (138.0390, -7.5978), - (138.6686, -7.3202), - (138.4079, -6.2328), - (137.9278, -5.3933), - (135.9892, -4.5465), - (135.1645, -4.4629), - (133.6628, -3.5388), - (133.3677, -4.0248), - (132.9839, -4.1129), - (132.7569, -3.7462), - (132.7537, -3.3117), - (131.9898, -2.8205), - (133.0668, -2.4604), - (133.7800, -2.4798), - (133.6962, -2.2145), - (132.2323, -2.2125), - (131.8362, -1.6171), - (130.9428, -1.4325), - (130.5195, -0.9377), - (131.8675, -0.6954), - (132.3801, -0.3695), - (133.9855, -0.7802), - (134.1433, -1.1518), - (134.4226, -2.7691), - (135.4576, -3.3677), - (136.2933, -2.3070), - (137.4407, -1.7035), - (138.3297, -1.7026), - (139.1849, -2.0512), - (139.9266, -2.4089), - (141.0002, -2.6001), - (114.2040, 4.5258), - (114.5999, 4.9000), - (115.4507, 5.4477), - (116.2207, 6.1431), - (116.7251, 6.9247), - (117.1296, 6.9280), - (117.6433, 6.4221), - (117.6890, 5.9874), - (118.3476, 5.7086), - (119.1819, 5.4078), - (119.1106, 5.0161), - (118.4397, 4.9665), - (118.6183, 4.4782), - (117.8820, 4.1375), - (117.3132, 3.2344), - (118.0483, 2.2876), - (117.8756, 1.8276), - (118.9967, 0.9022), - (117.8118, 0.7842), - (117.4783, 0.1024), - (117.5216, -0.8037), - (116.5600, -1.4876), - (116.5337, -2.4835), - (116.1480, -4.0127), - (116.0008, -3.6570), - (114.8648, -4.1069), - (114.4686, -3.4957), - (113.7556, -3.4391), - (113.2569, -3.1187), - (112.0681, -3.4783), - (111.7032, -2.9944), - (111.0482, -3.0494), - (110.2238, -2.9340), - (110.0709, -1.5928), - (109.5719, -1.3149), - (109.0918, -0.4595), - (108.9526, 0.4153), - (109.0691, 1.3419), - (109.6632, 2.0064), - (110.3961, 1.6637), - (111.1688, 1.8506), - (111.3700, 2.6973), - (111.7969, 2.8858), - (112.9956, 3.1023), - (113.7129, 3.8935), - (114.2040, 4.5258), - (-93.6127, 74.9799), - (-94.1569, 74.5923), - (-95.6086, 74.6668), - (-96.8209, 74.9276), - (-96.2885, 75.3778), - (-94.8508, 75.6472), - (-93.9777, 75.2964), - (-93.6127, 74.9799), - (-93.8400, 77.5199), - (-94.2956, 77.4913), - (-96.1696, 77.5551), - (-96.4363, 77.8346), - (-94.4225, 77.8200), - (-93.7206, 77.6343), - (-93.8400, 77.5199), - (-96.7543, 78.7658), - (-95.5592, 78.4183), - (-95.8302, 78.0569), - (-97.3098, 77.8505), - (-98.1242, 78.0828), - (-98.5528, 78.4581), - (-98.6319, 78.8719), - (-97.3372, 78.8319), - (-96.7543, 78.7658), - (-88.1503, 74.3923), - (-89.7647, 74.5155), - (-92.4224, 74.8377), - (-92.7682, 75.3868), - (-92.8899, 75.8826), - (-93.8938, 76.3192), - (-95.9624, 76.4413), - (-97.1213, 76.7510), - (-96.7451, 77.1613), - (-94.6840, 77.0978), - (-93.5739, 76.7762), - (-91.6050, 76.7785), - (-90.7418, 76.4495), - (-90.9696, 76.0740), - (-89.8222, 75.8477), - (-89.1870, 75.6101), - (-87.8382, 75.5661), - (-86.3791, 75.4824), - (-84.7896, 75.6992), - (-82.7534, 75.7843), - (-81.1285, 75.7139), - (-80.0575, 75.3368), - (-79.8339, 74.9231), - (-80.4577, 74.6573), - (-81.9488, 74.4424), - (-83.2288, 74.5640), - (-86.0974, 74.4100), - (-88.1503, 74.3923), - (-111.2644, 78.1529), - (-109.8544, 77.9963), - (-110.1869, 77.6970), - (-112.0511, 77.4092), - (-113.5342, 77.7322), - (-112.7245, 78.0510), - (-111.2644, 78.1529), - (-110.9636, 78.8044), - (-109.6631, 78.6019), - (-110.8813, 78.4069), - (-112.5420, 78.4079), - (-112.5258, 78.5505), - (-111.5000, 78.8499), - (-110.9636, 78.8044), - (-66.2824, 18.5147), - (-65.7713, 18.4266), - (-65.5910, 18.2280), - (-65.8471, 17.9759), - (-66.5999, 17.9818), - (-67.1841, 17.9465), - (-67.2424, 18.3744), - (-67.1006, 18.5206), - (-66.2824, 18.5147), - (-77.5696, 18.4905), - (-76.8966, 18.4008), - (-76.3653, 18.1607), - (-76.1996, 17.8868), - (-76.9025, 17.8682), - (-77.2063, 17.7011), - (-77.7660, 17.8615), - (-78.3377, 18.2259), - (-78.2177, 18.4545), - (-77.7973, 18.5242), - (-77.5696, 18.4905), - (-82.2681, 23.1886), - (-81.4044, 23.1172), - (-80.6187, 23.1060), - (-79.6795, 22.7653), - (-79.2814, 22.3992), - (-78.3474, 22.5121), - (-77.9932, 22.2771), - (-77.1464, 21.6578), - (-76.5238, 21.2068), - (-76.1946, 21.2205), - (-75.5982, 21.0166), - (-75.6710, 20.7350), - (-74.9338, 20.6939), - (-74.1780, 20.2846), - (-74.2966, 20.0503), - (-74.9615, 19.9234), - (-75.6346, 19.8737), - (-76.3236, 19.9528), - (-77.7554, 19.8554), - (-77.0851, 20.4133), - (-77.4926, 20.6731), - (-78.1372, 20.7399), - (-78.4828, 21.0286), - (-78.7198, 21.5981), - (-79.2849, 21.5591), - (-80.2174, 21.8273), - (-80.5175, 22.0370), - (-81.8209, 22.1920), - (-82.1699, 22.3871), - (-81.7950, 22.6369), - (-82.7758, 22.6881), - (-83.4944, 22.1685), - (-83.9088, 22.1545), - (-84.0521, 21.9105), - (-84.5470, 21.8012), - (-84.9749, 21.8960), - (-84.4470, 22.2049), - (-84.2303, 22.5657), - (-83.7782, 22.7881), - (-83.2675, 22.9830), - (-82.5104, 23.0787), - (-82.2681, 23.1886), - (-55.6002, 51.3170), - (-56.1340, 50.6870), - (-56.7958, 49.8123), - (-56.1431, 50.1501), - (-55.4714, 49.9358), - (-55.8224, 49.5871), - (-54.9351, 49.3130), - (-54.4737, 49.5566), - (-53.4765, 49.2491), - (-53.7860, 48.5167), - (-53.0861, 48.6878), - (-52.9586, 48.1571), - (-52.6480, 47.5355), - (-53.0691, 46.6554), - (-53.5214, 46.6182), - (-54.1789, 46.8070), - (-53.9618, 47.6252), - (-54.2404, 47.7522), - (-55.4007, 46.8849), - (-55.9974, 46.9197), - (-55.2912, 47.3895), - (-56.2507, 47.6325), - (-57.3252, 47.5728), - (-59.2660, 47.6033), - (-59.4194, 47.8994), - (-58.7965, 48.2515), - (-59.2316, 48.5231), - (-58.3918, 49.1255), - (-57.3586, 50.7182), - (-56.7386, 51.2874), - (-55.8709, 51.6320), - (-55.4069, 51.5882), - (-55.6002, 51.3170), - (-83.8826, 65.1096), - (-82.7875, 64.7666), - (-81.6420, 64.4551), - (-81.5534, 63.9796), - (-80.8173, 64.0574), - (-80.1034, 63.7259), - (-80.9910, 63.4112), - (-82.5471, 63.6517), - (-83.1087, 64.1018), - (-84.1004, 63.5697), - (-85.5234, 63.0523), - (-85.8667, 63.6372), - (-87.2219, 63.5412), - (-86.3527, 64.0358), - (-86.2248, 64.8229), - (-85.8838, 65.7387), - (-85.1613, 65.6572), - (-84.9757, 65.2175), - (-84.4640, 65.3717), - (-83.8826, 65.1096), - (-78.7706, 72.3521), - (-77.8246, 72.7496), - (-75.6058, 72.2436), - (-74.2286, 71.7671), - (-74.0991, 71.3308), - (-72.2422, 71.5569), - (-71.2000, 70.9200), - (-68.7860, 70.5250), - (-67.9149, 70.1219), - (-66.9690, 69.1860), - (-68.8051, 68.7201), - (-66.4498, 68.0671), - (-64.8623, 67.8475), - (-63.4249, 66.9284), - (-61.8519, 66.8621), - (-62.1631, 66.1602), - (-63.9184, 64.9986), - (-65.1488, 65.4260), - (-66.7212, 66.3880), - (-68.0150, 66.2627), - (-68.1412, 65.6897), - (-67.0896, 65.1084), - (-65.7320, 64.6484), - (-65.3201, 64.3827), - (-64.6694, 63.3929), - (-65.0138, 62.6741), - (-66.2750, 62.9450), - (-68.7831, 63.7456), - (-67.3696, 62.8839), - (-66.3282, 62.2800), - (-66.1655, 61.9308), - (-68.8773, 62.3301), - (-71.0234, 62.9107), - (-72.2353, 63.3978), - (-71.8862, 63.6799), - (-73.3783, 64.1939), - (-74.8344, 64.6791), - (-74.8185, 64.3890), - (-77.7099, 64.2295), - (-78.5559, 64.5729), - (-77.8972, 65.3091), - (-76.0182, 65.3269), - (-73.9597, 65.4547), - (-74.2938, 65.8117), - (-73.9449, 66.3105), - (-72.6511, 67.2845), - (-72.9260, 67.7269), - (-73.3116, 68.0694), - (-74.8433, 68.5546), - (-76.8691, 68.8947), - (-76.2286, 69.1477), - (-77.2873, 69.7695), - (-78.1686, 69.8264), - (-78.9572, 70.1668), - (-79.4924, 69.8718), - (-81.3054, 69.7431), - (-84.9447, 69.9666), - (-87.0600, 70.2600), - (-88.6817, 70.4107), - (-89.5134, 70.7620), - (-88.4677, 71.2181), - (-89.8881, 71.2225), - (-90.2051, 72.2350), - (-89.4365, 73.1294), - (-88.4082, 73.5378), - (-85.8261, 73.8038), - (-86.5621, 73.1574), - (-85.7743, 72.5341), - (-84.8501, 73.3402), - (-82.3155, 73.7509), - (-80.6000, 72.7165), - (-80.7489, 72.0619), - (-78.7706, 72.3521), - (-94.5036, 74.1349), - (-92.4200, 74.1000), - (-90.5097, 73.8567), - (-92.0039, 72.9662), - (-93.1962, 72.7719), - (-94.2690, 72.0245), - (-95.4098, 72.0618), - (-96.0337, 72.9402), - (-96.0182, 73.4374), - (-95.4957, 73.8624), - (-94.5036, 74.1349), - (-100.4383, 72.7058), - (-101.54, 73.36), - (-100.3564, 73.8438), - (-99.1638, 73.6333), - (-97.38, 73.76), - (-97.12, 73.47), - (-98.0535, 72.9905), - (-96.54, 72.56), - (-96.72, 71.66), - (-98.3596, 71.2728), - (-99.3228, 71.3563), - (-100.0148, 71.7382), - (-102.48, 72.4829), - (-102.48, 72.83), - (-100.4383, 72.7058), - (-107.8194, 75.8455), - (-106.9289, 76.0128), - (-105.8809, 75.9693), - (-105.7049, 75.4795), - (-106.3134, 75.0052), - (-109.6999, 74.8500), - (-112.2230, 74.4169), - (-113.7438, 74.3942), - (-113.8713, 74.7202), - (-111.7942, 75.1624), - (-116.3121, 75.0434), - (-117.7104, 75.2222), - (-116.3460, 76.1990), - (-115.4048, 76.4788), - (-112.5905, 76.1413), - (-110.8142, 75.5491), - (-109.0671, 75.4732), - (-110.4972, 76.4298), - (-109.5811, 76.7941), - (-108.5485, 76.6783), - (-108.2114, 76.2016), - (-107.8194, 75.8455), - (-122.8549, 76.1165), - (-121.1575, 76.8645), - (-119.1039, 77.5122), - (-117.5701, 77.4983), - (-116.1985, 77.6452), - (-116.3358, 76.8769), - (-117.1060, 76.5300), - (-118.0404, 76.4811), - (-119.8993, 76.0532), - (-121.4999, 75.9000), - (-122.8549, 76.1165), - (-121.5378, 74.4489), - (-120.1097, 74.2413), - (-117.5556, 74.1857), - (-116.5844, 73.8960), - (-115.5107, 73.4752), - (-116.7679, 73.2229), - (-119.22, 72.52), - (-120.46, 71.82), - (-120.46, 71.3836), - (-123.0921, 70.9016), - (-123.62, 71.34), - (-125.9289, 71.8686), - (-125.5, 72.2922), - (-124.8072, 73.0225), - (-123.94, 73.68), - (-124.9177, 74.2927), - (-121.5378, 74.4489), - (-166.4677, 60.3841), - (-165.6744, 60.2936), - (-165.5791, 59.9099), - (-166.1927, 59.7544), - (-166.8483, 59.9414), - (-167.4552, 60.2130), - (-166.4677, 60.3841), - (-153.2287, 57.9690), - (-152.5647, 57.9014), - (-152.1411, 57.5910), - (-153.0063, 57.1158), - (-154.0050, 56.7346), - (-154.5164, 56.9927), - (-154.6709, 57.4611), - (-153.7627, 57.8165), - (-153.2287, 57.9690), - (-132.7100, 54.0400), - (-131.7499, 54.1200), - (-132.0494, 52.9846), - (-131.1790, 52.1804), - (-131.5778, 52.1823), - (-132.1804, 52.6397), - (-132.5499, 53.1000), - (-133.0546, 53.4114), - (-133.2396, 53.8510), - (-133.1800, 54.1699), - (-132.7100, 54.0400), - (-125.4150, 49.9500), - (-124.9207, 49.4752), - (-123.9225, 49.0624), - (-123.5100, 48.5100), - (-124.0128, 48.3708), - (-125.6550, 48.8250), - (-125.9549, 49.1799), - (-126.8500, 49.5300), - (-127.0299, 49.8149), - (-128.0593, 49.9949), - (-128.4445, 50.5391), - (-128.3584, 50.7706), - (-127.3085, 50.5525), - (-126.6950, 50.4009), - (-125.7550, 50.2950), - (-125.4150, 49.9500), - (-171.7316, 63.7825), - (-171.1144, 63.5921), - (-170.4911, 63.6949), - (-169.6825, 63.4311), - (-168.6894, 63.2975), - (-168.7719, 63.1885), - (-169.5294, 62.9769), - (-170.2905, 63.1944), - (-170.6713, 63.3758), - (-171.5530, 63.3177), - (-171.7911, 63.4058), - (-171.7316, 63.7825), - (-105.4922, 79.3015), - (-103.5292, 79.1653), - (-100.8251, 78.8004), - (-100.0601, 78.3247), - (-99.6709, 77.9075), - (-101.3039, 78.0189), - (-102.9498, 78.3432), - (-105.1761, 78.3803), - (-104.2104, 78.6774), - (-105.4195, 78.9183), - (-105.4922, 79.3015), - (32.9469, 35.3867), - (33.6672, 35.3732), - (34.5764, 35.6715), - (33.9008, 35.2457), - (34.0048, 34.9780), - (32.9798, 34.5718), - (32.4902, 34.7016), - (32.2566, 35.1032), - (32.8024, 35.1455), - (32.9469, 35.3867), - (26.2900, 35.2999), - (26.1649, 35.0049), - (24.7249, 34.9199), - (24.7350, 35.0849), - (23.5149, 35.2799), - (23.6999, 35.7050), - (24.2466, 35.3680), - (25.0250, 35.4249), - (25.7692, 35.3540), - (25.7450, 35.1799), - (26.2900, 35.2999), - (49.5435, -12.4698), - (49.8089, -12.8952), - (50.0565, -13.5557), - (50.2174, -14.7587), - (50.4765, -15.2265), - (50.3771, -15.7060), - (50.2002, -16.0002), - (49.8606, -15.4142), - (49.6726, -15.7101), - (49.8633, -16.4510), - (49.7745, -16.8750), - (49.4986, -17.1060), - (49.4356, -17.9530), - (49.0417, -19.1187), - (48.5485, -20.4968), - (47.9307, -22.3915), - (47.5477, -23.7819), - (47.0957, -24.9416), - (46.2824, -25.1784), - (45.4095, -25.6014), - (44.8335, -25.3461), - (44.0397, -24.9883), - (43.7637, -24.4606), - (43.6977, -23.5741), - (43.3456, -22.7769), - (43.2541, -22.0574), - (43.4332, -21.3364), - (43.8936, -21.1633), - (43.8963, -20.8304), - (44.3743, -20.0723), - (44.4643, -19.4354), - (44.2324, -18.9619), - (44.0429, -18.3313), - (43.9630, -17.4099), - (44.3124, -16.8504), - (44.4465, -16.2162), - (44.9449, -16.1793), - (45.5027, -15.9743), - (45.8729, -15.7934), - (46.3122, -15.7800), - (46.8821, -15.2101), - (47.7051, -14.5943), - (48.0052, -14.0912), - (47.8689, -13.6638), - (48.2938, -13.7840), - (48.8450, -13.0891), - (48.8635, -12.4878), - (49.1946, -12.0405), - (49.5435, -12.4698), - (167.2168, -15.8918), - (167.8448, -16.4663), - (167.5151, -16.5978), - (167.1800, -16.1599), - (167.2168, -15.8918), - (166.7931, -15.6688), - (166.6498, -15.3927), - (166.6291, -14.6264), - (167.1077, -14.9339), - (167.2700, -15.7400), - (167.0012, -15.6146), - (166.7931, -15.6688), - (134.2101, -6.8952), - (134.1127, -6.1424), - (134.2903, -5.7830), - (134.4996, -5.4450), - (134.7270, -5.7375), - (134.7246, -6.2144), - (134.2101, -6.8952), - (-48.6606, -78.0470), - (-48.1513, -78.0470), - (-46.6628, -77.8314), - (-45.1547, -78.0470), - (-43.9208, -78.4781), - (-43.4899, -79.0855), - (-43.3724, -79.5166), - (-43.3332, -80.0261), - (-44.8805, -80.3396), - (-46.5061, -80.5943), - (-48.3864, -80.8294), - (-50.4821, -81.0254), - (-52.8519, -80.9666), - (-54.1642, -80.6335), - (-53.9879, -80.2220), - (-51.8531, -79.9477), - (-50.9913, -79.6146), - (-50.3645, -79.1834), - (-49.9141, -78.8112), - (-49.3069, -78.4585), - (-48.6606, -78.0470), - (-66.2900, -80.2557), - (-64.0376, -80.2948), - (-61.8832, -80.3928), - (-61.1389, -79.9813), - (-60.6101, -79.6286), - (-59.5720, -80.0401), - (-59.8658, -80.5496), - (-60.1596, -81.0003), - (-62.2553, -80.8631), - (-64.4881, -80.9219), - (-65.7416, -80.5888), - (-65.7416, -80.5496), - (-66.2900, -80.2557), - (-73.9158, -71.2693), - (-73.2303, -71.1517), - (-72.0747, -71.1909), - (-71.7809, -70.6814), - (-71.7221, -70.3091), - (-71.7417, -69.5057), - (-71.1738, -69.0354), - (-70.2532, -68.8787), - (-69.7244, -69.2510), - (-69.4894, -69.6233), - (-69.0585, -70.0740), - (-68.7255, -70.5051), - (-68.4513, -70.9558), - (-68.3338, -71.4064), - (-68.5101, -71.7984), - (-68.7842, -72.1706), - (-69.9594, -72.3078), - (-71.0758, -72.5038), - (-72.3881, -72.4842), - (-71.8984, -72.0923), - (-73.0736, -72.2294), - (-74.1900, -72.3666), - (-74.9538, -72.0727), - (-75.0126, -71.6612), - (-73.9158, -71.2693), - (-102.3307, -71.8941), - (-101.7039, -71.7177), - (-100.4309, -71.8549), - (-98.9815, -71.9333), - (-97.8847, -72.0705), - (-96.7879, -71.9529), - (-96.2003, -72.5212), - (-96.9837, -72.4428), - (-98.1980, -72.4820), - (-99.4320, -72.4428), - (-100.7834, -72.5016), - (-101.8018, -72.3056), - (-102.3307, -71.8941), - (-122.6217, -73.6577), - (-122.4062, -73.3246), - (-121.2115, -73.5009), - (-119.9188, -73.6577), - (-118.7241, -73.4813), - (-119.2921, -73.8340), - (-120.2322, -74.0888), - (-121.6228, -74.0104), - (-122.6217, -73.6577), - (-127.2831, -73.4617), - (-126.5584, -73.2462), - (-125.5595, -73.4813), - (-124.0318, -73.8732), - (-124.6194, -73.8340), - (-125.9121, -73.7361), - (-127.2831, -73.4617), - (165.7799, -21.0800), - (166.5999, -21.7000), - (167.1200, -22.1599), - (166.7400, -22.3999), - (166.1897, -22.1297), - (165.4743, -21.6796), - (164.8298, -21.1498), - (164.1679, -20.4447), - (164.0296, -20.1056), - (164.4599, -20.1200), - (165.0200, -20.4599), - (165.4600, -20.8000), - (165.7799, -21.0800), - (152.6400, -3.6599), - (153.0199, -3.9800), - (153.1400, -4.4999), - (152.8272, -4.7664), - (152.6386, -4.1761), - (152.4060, -3.7897), - (151.9532, -3.4620), - (151.3842, -3.0354), - (150.6620, -2.7414), - (150.9399, -2.5000), - (151.4799, -2.7799), - (151.8200, -2.9999), - (152.2399, -3.2400), - (152.6400, -3.6599), - (151.3013, -5.8407), - (150.7544, -6.0837), - (150.2411, -6.3177), - (149.7099, -6.3165), - (148.8900, -6.0260), - (148.3189, -5.7471), - (148.4018, -5.4377), - (149.2984, -5.5837), - (149.8455, -5.5055), - (149.9962, -5.0261), - (150.1397, -5.0013), - (150.2369, -5.5322), - (150.8074, -5.4558), - (151.0896, -5.1136), - (151.6478, -4.7570), - (151.5378, -4.1678), - (152.1367, -4.1487), - (152.3387, -4.3129), - (152.3186, -4.8676), - (151.9827, -5.4780), - (151.4591, -5.5602), - (151.3013, -5.8407), - (162.1190, -10.4827), - (162.3986, -10.8263), - (161.7000, -10.8200), - (161.3197, -10.2047), - (161.9173, -10.4466), - (162.1190, -10.4827), - (161.6799, -9.5999), - (161.5293, -9.7843), - (160.7882, -8.9175), - (160.5799, -8.3200), - (160.9200, -8.3200), - (161.2800, -9.1200), - (161.6799, -9.5999), - (160.8522, -9.8729), - (160.4625, -9.8952), - (159.8494, -9.7940), - (159.6400, -9.6399), - (159.7029, -9.2429), - (160.3629, -9.4003), - (160.6885, -9.6101), - (160.8522, -9.8729), - (159.6400, -8.0200), - (159.8750, -8.3373), - (159.9174, -8.5382), - (159.1336, -8.1141), - (158.5861, -7.7548), - (158.2111, -7.4218), - (158.3599, -7.3200), - (158.8200, -7.5600), - (159.6400, -8.0200), - (157.1400, -7.0216), - (157.5384, -7.3478), - (157.3394, -7.4047), - (156.9020, -7.1768), - (156.4913, -6.7659), - (156.5428, -6.5993), - (157.1400, -7.0216), - (154.7599, -5.3399), - (155.0629, -5.5667), - (155.5477, -6.2006), - (156.0199, -6.5400), - (155.8800, -6.8199), - (155.5999, -6.9199), - (155.1669, -6.5359), - (154.7291, -5.9007), - (154.5141, -5.1391), - (154.6525, -5.0423), - (154.7599, -5.3399), - (176.8858, -40.0659), - (176.5080, -40.6047), - (176.0124, -41.2896), - (175.2395, -41.6883), - (175.0678, -41.4258), - (174.6509, -41.2818), - (175.2276, -40.4592), - (174.9001, -39.9088), - (173.8240, -39.5088), - (173.8522, -39.1466), - (174.5748, -38.7976), - (174.7434, -38.0278), - (174.6969, -37.3811), - (174.2920, -36.7110), - (174.3190, -36.5348), - (173.8409, -36.1219), - (173.0541, -35.2371), - (172.6360, -34.5291), - (173.0070, -34.4506), - (173.5512, -35.0061), - (174.3293, -35.2654), - (174.6120, -36.1563), - (175.3366, -37.2090), - (175.3575, -36.5261), - (175.8088, -36.7989), - (175.9584, -37.5553), - (176.7631, -37.8812), - (177.4388, -37.9612), - (178.0103, -37.5798), - (178.5170, -37.6953), - (178.2747, -38.5828), - (177.9704, -39.1663), - (177.2069, -39.1457), - (176.9399, -39.4497), - (177.0329, -39.8799), - (176.8858, -40.0659), - (169.6678, -43.5553), - (170.5249, -43.0316), - (171.1250, -42.5127), - (171.5697, -41.7674), - (171.9487, -41.5144), - (172.0972, -40.9561), - (172.7985, -40.4939), - (173.0203, -40.9190), - (173.2472, -41.3319), - (173.9584, -40.9267), - (174.2475, -41.3491), - (174.2485, -41.7700), - (173.8764, -42.2331), - (173.2227, -42.9700), - (172.7112, -43.3722), - (173.0801, -43.8533), - (172.3085, -43.8656), - (171.4529, -44.2424), - (171.1851, -44.8971), - (170.6166, -45.9089), - (169.8314, -46.3557), - (169.3323, -46.6412), - (168.4113, -46.6199), - (167.7637, -46.2901), - (166.6768, -46.2199), - (166.5091, -45.8527), - (167.0463, -45.1109), - (168.3037, -44.1239), - (168.9494, -43.9358), - (169.6678, -43.5553), - (147.6892, -40.8082), - (148.2890, -40.8754), - (148.3598, -42.0623), - (148.0173, -42.4070), - (147.9140, -43.2115), - (147.5645, -42.9376), - (146.8703, -43.6345), - (146.6633, -43.5808), - (146.0483, -43.5497), - (145.4319, -42.6937), - (145.2950, -42.0336), - (144.7180, -41.1625), - (144.7437, -40.7039), - (145.3979, -40.7925), - (146.3641, -41.1376), - (146.9085, -41.0005), - (147.6892, -40.8082), - (126.1487, -32.2159), - (125.0886, -32.7287), - (124.2216, -32.9594), - (124.0289, -33.4838), - (123.6596, -33.8901), - (122.8110, -33.9144), - (122.1830, -34.0034), - (121.2991, -33.8210), - (120.5802, -33.9301), - (119.8936, -33.9760), - (119.2988, -34.5093), - (119.0073, -34.4641), - (118.5057, -34.7468), - (118.0249, -35.0647), - (117.2955, -35.0254), - (116.6251, -35.0250), - (115.5643, -34.3864), - (115.0268, -34.1965), - (115.0486, -33.6234), - (115.5451, -33.4872), - (115.7146, -33.2595), - (115.6793, -32.9003), - (115.8016, -32.2050), - (115.6896, -31.6124), - (115.1609, -30.6015), - (114.9970, -30.0307), - (115.0400, -29.4610), - (114.6419, -28.8102), - (114.6164, -28.5163), - (114.1735, -28.1180), - (114.0488, -27.3347), - (113.4774, -26.5431), - (113.3389, -26.1165), - (113.7783, -26.5490), - (113.4409, -25.6212), - (113.9369, -25.9112), - (114.2328, -26.2984), - (114.2161, -25.7862), - (113.7212, -24.9989), - (113.6253, -24.6839), - (113.3935, -24.3847), - (113.5020, -23.8063), - (113.7069, -23.5602), - (113.8434, -23.0599), - (113.7365, -22.4754), - (114.1497, -21.7558), - (114.2253, -22.5174), - (114.6477, -21.8295), - (115.4601, -21.4951), - (115.9473, -21.0686), - (116.7116, -20.7016), - (117.1663, -20.6235), - (117.4415, -20.7468), - (118.2295, -20.3742), - (118.8360, -20.2633), - (118.9878, -20.0442), - (119.2524, -19.9529), - (119.8052, -19.9765), - (120.8562, -19.6837), - (121.3998, -19.2397), - (121.6550, -18.7053), - (122.2416, -18.1976), - (122.2866, -17.7986), - (122.3127, -17.2549), - (123.0125, -16.4051), - (123.4337, -17.2685), - (123.8593, -17.0690), - (123.5032, -16.5965), - (123.8170, -16.1113), - (124.2582, -16.3279), - (124.3797, -15.5670), - (124.9261, -15.0751), - (125.1672, -14.6803), - (125.6700, -14.5100), - (125.6857, -14.2306), - (126.1251, -14.3473), - (126.1428, -14.0959), - (126.5825, -13.9527), - (127.0658, -13.8179), - (127.8046, -14.2769), - (128.3596, -14.8691), - (128.9855, -14.8759), - (129.6214, -14.9697), - (129.4096, -14.4206), - (129.8886, -13.6187), - (130.3394, -13.3573), - (130.1835, -13.1075), - (130.6177, -12.5363), - (131.2234, -12.1836), - (131.7350, -12.3024), - (132.5752, -12.1140), - (132.5572, -11.6030), - (131.8246, -11.2737), - (132.3572, -11.1285), - (133.0195, -11.3764), - (133.5508, -11.7865), - (134.3930, -12.0423), - (134.6786, -11.9411), - (135.2984, -12.2486), - (135.8826, -11.9622), - (136.2583, -12.0493), - (136.4924, -11.8572), - (136.9516, -12.3519), - (136.6851, -12.8872), - (136.3054, -13.2912), - (135.9617, -13.3245), - (136.0776, -13.7242), - (135.7838, -14.2239), - (135.4286, -14.7154), - (135.5001, -14.9977), - (136.2951, -15.5502), - (137.0653, -15.8707), - (137.5804, -16.2150), - (138.3032, -16.8076), - (138.5851, -16.8066), - (139.1085, -17.0626), - (139.2605, -17.3716), - (140.2151, -17.7108), - (140.8754, -17.3690), - (141.0711, -16.8320), - (141.2740, -16.3888), - (141.3982, -15.8405), - (141.7021, -15.0449), - (141.5633, -14.5613), - (141.6355, -14.2703), - (141.5198, -13.6980), - (141.6509, -12.9446), - (141.8426, -12.7415), - (141.6869, -12.4076), - (141.9286, -11.8774), - (142.1184, -11.3280), - (142.1437, -11.0427), - (142.5152, -10.6681), - (142.7973, -11.1573), - (142.8667, -11.7847), - (143.1159, -11.9056), - (143.1586, -12.3256), - (143.5221, -12.8343), - (143.5971, -13.4004), - (143.5618, -13.7636), - (143.9220, -14.5483), - (144.5637, -14.1711), - (144.8948, -14.5944), - (145.3747, -14.9849), - (145.2719, -15.4282), - (145.4852, -16.2856), - (145.6369, -16.7849), - (145.8888, -16.9069), - (146.1603, -17.7616), - (146.0636, -18.2800), - (146.3874, -18.9582), - (147.4710, -19.4807), - (148.1776, -19.9559), - (148.8484, -20.3912), - (148.7174, -20.6334), - (149.2894, -21.2605), - (149.6783, -22.3425), - (150.0773, -22.1227), - (150.4829, -22.5561), - (150.7272, -22.4023), - (150.8995, -23.4622), - (151.6091, -24.0762), - (152.0735, -24.4578), - (152.8551, -25.2675), - (153.1361, -26.0711), - (153.1619, -26.6413), - (153.0929, -27.2602), - (153.5694, -28.1100), - (153.5121, -28.9950), - (153.3390, -29.4582), - (153.0692, -30.3502), - (153.0895, -30.9236), - (152.8915, -31.6404), - (152.4500, -32.5500), - (151.7091, -33.0413), - (151.3439, -33.8160), - (151.0105, -34.3103), - (150.7141, -35.1734), - (150.3282, -35.6718), - (150.0752, -36.4202), - (149.9461, -37.1090), - (149.9972, -37.4252), - (149.4238, -37.7726), - (148.3046, -37.8090), - (147.3817, -38.2192), - (146.9221, -38.6065), - (146.3179, -39.0357), - (145.4896, -38.5937), - (144.8769, -38.4174), - (145.0322, -37.8961), - (144.4856, -38.0853), - (143.6099, -38.8094), - (142.7454, -38.5382), - (142.1783, -38.3800), - (141.6065, -38.3085), - (140.6385, -38.0193), - (139.9921, -37.4029), - (139.8065, -36.6436), - (139.5741, -36.1383), - (139.0828, -35.7327), - (138.1207, -35.6122), - (138.4494, -35.1272), - (138.2075, -34.3847), - (137.7191, -35.0768), - (136.8294, -35.2605), - (137.3523, -34.7073), - (137.5038, -34.1302), - (137.8901, -33.6404), - (137.8103, -32.9000), - (136.9968, -33.7527), - (136.3720, -34.0947), - (135.9890, -34.8901), - (135.2082, -34.4786), - (135.2392, -33.9479), - (134.6134, -33.2227), - (134.0859, -32.8480), - (134.2739, -32.6172), - (132.9907, -32.0112), - (132.2880, -31.9826), - (131.3263, -31.4958), - (129.5357, -31.5904), - (128.2409, -31.9484), - (127.1028, -32.2822), - (126.1487, -32.2159), - (81.7879, 7.5230), - (81.6373, 6.4817), - (81.2180, 6.1971), - (80.3483, 5.9683), - (79.8724, 6.7634), - (79.6951, 8.2008), - (80.1478, 9.8240), - (80.8388, 9.2684), - (81.3043, 8.5642), - (81.7879, 7.5230), - (129.3709, -2.8021), - (130.4713, -3.0937), - (130.8348, -3.8584), - (129.9905, -3.4463), - (129.1552, -3.3626), - (128.5906, -3.4286), - (127.8988, -3.3934), - (128.1358, -2.8436), - (129.3709, -2.8021), - (126.8749, -3.7909), - (126.1838, -3.6073), - (125.9890, -3.1772), - (127.0006, -3.1293), - (127.2492, -3.4590), - (126.8749, -3.7909), - (127.9323, 2.1745), - (128.0041, 1.6285), - (128.5945, 1.5408), - (128.6882, 1.1323), - (128.6359, 0.2584), - (128.1201, 0.3564), - (127.9680, -0.2520), - (128.3799, -0.7800), - (128.1000, -0.8999), - (127.6964, -0.2665), - (127.3994, 1.0117), - (127.6005, 1.8106), - (127.9323, 2.1745), - (122.9275, 0.8751), - (124.0775, 0.9171), - (125.0659, 1.6432), - (125.2405, 1.4198), - (124.4370, 0.4278), - (123.6855, 0.2355), - (122.7230, 0.4311), - (121.0567, 0.3812), - (120.1830, 0.2372), - (120.0408, -0.5196), - (120.9359, -1.4089), - (121.4758, -0.9559), - (123.3405, -0.6156), - (123.2583, -1.0762), - (122.8226, -0.9309), - (122.3885, -1.5168), - (121.5082, -1.9044), - (122.4545, -3.1860), - (122.2718, -3.5295), - (123.1709, -4.6836), - (123.1623, -5.3406), - (122.6285, -5.6345), - (122.2363, -5.2829), - (122.7195, -4.4641), - (121.7382, -4.8513), - (121.4894, -4.5745), - (121.6191, -4.1884), - (120.8981, -3.6021), - (120.9723, -2.6276), - (120.3054, -2.9316), - (120.3900, -4.0975), - (120.4307, -5.5282), - (119.7965, -5.6734), - (119.3669, -5.3798), - (119.6536, -4.4594), - (119.4988, -3.4944), - (119.0783, -3.4870), - (118.7677, -2.8019), - (119.1809, -2.1471), - (119.3233, -1.3531), - (119.8259, 0.1542), - (120.0357, 0.5664), - (120.8857, 1.3092), - (121.6668, 1.0139), - (122.9275, 0.8751), - (120.2950, -10.2586), - (118.9678, -9.5579), - (119.9003, -9.3613), - (120.4257, -9.6659), - (120.7755, -9.9696), - (120.7156, -10.2395), - (120.2950, -10.2586), - (121.3416, -8.5367), - (122.0073, -8.4606), - (122.9035, -8.0942), - (122.7569, -8.6498), - (121.2544, -8.9336), - (119.9243, -8.8104), - (119.9209, -8.4448), - (120.7150, -8.2369), - (121.3416, -8.5367), - (118.2606, -8.3623), - (118.8784, -8.2806), - (119.1265, -8.7058), - (117.9704, -8.9066), - (117.2777, -9.0408), - (116.7401, -9.0328), - (117.0837, -8.4571), - (117.6320, -8.4493), - (117.9000, -8.0956), - (118.2606, -8.3623), - (108.4868, -6.4219), - (108.6234, -6.7776), - (110.5392, -6.8773), - (110.7595, -6.4651), - (112.6148, -6.9460), - (112.9787, -7.5942), - (114.4789, -7.7765), - (115.7055, -8.3708), - (114.5645, -8.7518), - (113.4647, -8.3489), - (112.5596, -8.3761), - (111.5220, -8.3021), - (110.5861, -8.1226), - (109.4276, -7.7406), - (108.6936, -7.6416), - (108.2777, -7.7666), - (106.4541, -7.3548), - (106.2806, -6.9248), - (105.3654, -6.8514), - (106.0516, -5.8959), - (107.2650, -5.9549), - (108.0720, -6.3457), - (108.4868, -6.4219), - (104.3699, -1.0848), - (104.5394, -1.7823), - (104.8878, -2.3404), - (105.6221, -2.4288), - (106.1085, -3.0617), - (105.8574, -4.3055), - (105.8176, -5.8523), - (104.7103, -5.8732), - (103.8682, -5.0373), - (102.5842, -4.2202), - (102.1561, -3.6141), - (101.3991, -2.7997), - (100.9025, -2.0502), - (100.1419, -0.6503), - (99.2637, 0.1831), - (98.9700, 1.0428), - (98.6013, 1.8235), - (97.6995, 2.4531), - (97.1769, 3.3087), - (96.4240, 3.8688), - (95.3808, 4.9707), - (95.2930, 5.4798), - (95.9368, 5.4395), - (97.4848, 5.2463), - (98.3691, 4.2683), - (99.1425, 3.5903), - (99.6939, 3.1743), - (100.6414, 2.0993), - (101.6580, 2.0836), - (102.4982, 1.3987), - (103.0768, 0.5613), - (103.8383, 0.1045), - (103.4376, -0.7119), - (104.0107, -1.0592), - (104.3699, -1.0848), - (120.8338, 12.7044), - (120.3234, 13.4664), - (121.1801, 13.4296), - (121.5273, 13.0695), - (121.2621, 12.2055), - (120.8338, 12.7044), - (122.5860, 9.9810), - (122.8370, 10.2611), - (122.9474, 10.8818), - (123.4988, 10.9406), - (123.3377, 10.2673), - (124.0779, 11.2327), - (123.9824, 10.2787), - (123.6230, 9.9500), - (123.3099, 9.3182), - (122.9958, 9.0221), - (122.3800, 9.7133), - (122.5860, 9.9810), - (126.3768, 8.4147), - (126.4785, 7.7503), - (126.5374, 7.1894), - (126.1967, 6.2742), - (125.8314, 7.2937), - (125.3638, 6.7864), - (125.6831, 6.0496), - (125.3965, 5.5810), - (124.2197, 6.1613), - (123.9387, 6.8851), - (124.2436, 7.3606), - (123.6101, 7.8335), - (123.2960, 7.4188), - (122.8255, 7.4573), - (122.0854, 6.8994), - (121.9199, 7.1921), - (122.3123, 8.0349), - (122.9423, 8.3162), - (123.4876, 8.6930), - (123.8411, 8.2403), - (124.6014, 8.5141), - (124.7646, 8.9604), - (125.4713, 8.9869), - (125.4121, 9.7603), - (126.2227, 9.2860), - (126.3066, 8.7824), - (126.3768, 8.4147), - (109.4752, 18.1977), - (108.6552, 18.5076), - (108.6262, 19.3678), - (109.1190, 19.8210), - (110.2115, 20.1012), - (110.7865, 20.0775), - (111.0100, 19.6959), - (110.5706, 19.2558), - (110.3391, 18.6783), - (109.4752, 18.1977), - (121.7778, 24.3942), - (121.1756, 22.7908), - (120.7470, 21.9705), - (120.2200, 22.8148), - (120.1061, 23.5562), - (120.6946, 24.5384), - (121.4950, 25.2954), - (121.9512, 24.9975), - (121.7778, 24.3942), - (141.8846, 39.1808), - (140.9594, 38.1740), - (140.9763, 37.1420), - (140.5997, 36.3439), - (140.7740, 35.8428), - (140.2532, 35.1381), - (138.9755, 34.6676), - (137.2175, 34.6062), - (135.7929, 33.4648), - (135.1209, 33.8490), - (135.0794, 34.5965), - (133.3403, 34.3759), - (132.1567, 33.9049), - (130.9861, 33.8857), - (132.0000, 33.1499), - (131.3327, 31.4503), - (130.6863, 31.0295), - (130.2024, 31.4182), - (130.4476, 32.3194), - (129.8146, 32.6103), - (129.4084, 33.2960), - (130.3539, 33.6041), - (130.8784, 34.2327), - (131.8842, 34.7497), - (132.6176, 35.4333), - (134.6083, 35.7316), - (135.6775, 35.5271), - (136.7238, 37.3049), - (137.3906, 36.8273), - (138.8576, 37.8274), - (139.4264, 38.2159), - (140.0547, 39.4388), - (139.8833, 40.5633), - (140.3057, 41.1950), - (141.3689, 41.3785), - (141.9142, 39.9916), - (141.8846, 39.1808), - (144.6134, 43.9609), - (145.3208, 44.3847), - (145.5431, 43.2621), - (144.0596, 42.9883), - (143.1838, 41.9952), - (141.6114, 42.6787), - (141.0672, 41.5845), - (139.9551, 41.5695), - (139.8175, 42.5637), - (140.3120, 43.3332), - (141.3805, 43.3888), - (141.6719, 44.7721), - (141.9676, 45.5514), - (143.1428, 44.5103), - (143.9101, 44.1740), - (144.6134, 43.9609), - (8.7099, 40.8999), - (9.2100, 41.2099), - (9.8099, 40.5000), - (9.6695, 39.1773), - (9.2148, 39.2404), - (8.8069, 38.9066), - (8.4283, 39.1718), - (8.3882, 40.3783), - (8.1599, 40.9500), - (8.7099, 40.8999), - (8.7460, 42.6281), - (9.3900, 43.0099), - (9.5600, 42.1525), - (9.2297, 41.3800), - (8.7757, 41.5836), - (8.5442, 42.2565), - (8.7460, 42.6281), - (12.3709, 56.1114), - (12.6900, 55.6099), - (12.0899, 54.8000), - (11.0435, 55.3648), - (10.9039, 55.7799), - (12.3709, 56.1114), - (-4.2114, 58.5508), - (-3.0050, 58.6350), - (-4.0738, 57.5530), - (-3.0550, 57.6900), - (-1.9592, 57.6847), - (-2.2199, 56.8700), - (-3.1190, 55.9737), - (-2.0850, 55.9099), - (-1.1149, 54.6249), - (-0.4304, 54.4643), - (0.1849, 53.3250), - (0.4699, 52.9299), - (1.6815, 52.7395), - (1.5599, 52.0999), - (1.0505, 51.8067), - (1.4498, 51.2894), - (0.5503, 50.7657), - (-0.7875, 50.7749), - (-2.4899, 50.5000), - (-2.9562, 50.6968), - (-3.6174, 50.2283), - (-4.5425, 50.3418), - (-5.2450, 49.9599), - (-5.7765, 50.1596), - (-4.3099, 51.2100), - (-3.4148, 51.4260), - (-4.9843, 51.5934), - (-5.2672, 51.9914), - (-4.2223, 52.3013), - (-4.7700, 52.8400), - (-4.5799, 53.4950), - (-3.0920, 53.4044), - (-2.9450, 53.9849), - (-3.6300, 54.6150), - (-4.8441, 54.7909), - (-5.0825, 55.0616), - (-4.7191, 55.5084), - (-5.0479, 55.7839), - (-5.5863, 55.3111), - (-5.6449, 56.2750), - (-6.1499, 56.7850), - (-5.7868, 57.8188), - (-5.0099, 58.6300), - (-4.2114, 58.5508), - (-14.5086, 66.4558), - (-14.7396, 65.8087), - (-13.6097, 65.1266), - (-14.9098, 64.3640), - (-17.7944, 63.6787), - (-18.6562, 63.4963), - (-19.9727, 63.6436), - (-22.7629, 63.9601), - (-21.7784, 64.4021), - (-23.9550, 64.8911), - (-22.1844, 65.0849), - (-22.2274, 65.3785), - (-24.3261, 65.6111), - (-23.6505, 66.2625), - (-22.1349, 66.4104), - (-20.5762, 65.7321), - (-19.0568, 66.2766), - (-17.7986, 65.9938), - (-16.1678, 66.5268), - (-14.5086, 66.4558), - (142.9146, 53.7045), - (143.2608, 52.7407), - (143.2352, 51.7566), - (143.6480, 50.7476), - (144.6541, 48.9763), - (143.1739, 49.3065), - (142.5586, 47.8615), - (143.5334, 46.8367), - (143.5052, 46.1379), - (142.7477, 46.7407), - (142.0920, 45.9667), - (141.9069, 46.8059), - (142.0184, 47.7801), - (141.9044, 48.8591), - (142.1358, 49.6151), - (142.1799, 50.9523), - (141.5940, 51.9354), - (141.6825, 53.3019), - (142.6069, 53.7621), - (142.2097, 54.2254), - (142.6547, 54.3658), - (142.9146, 53.7045), - (118.5045, 9.3163), - (117.1742, 8.3674), - (117.6644, 9.0668), - (118.3869, 9.6844), - (118.9873, 10.3762), - (119.5114, 11.3696), - (119.6896, 10.5542), - (119.0294, 10.0036), - (118.5045, 9.3163), - (122.3369, 18.2248), - (122.1742, 17.8102), - (122.5156, 17.0935), - (122.2523, 16.2624), - (121.6627, 15.9310), - (121.5050, 15.1248), - (121.7288, 14.3283), - (122.2589, 14.2182), - (122.7012, 14.3365), - (123.9502, 13.7821), - (123.8551, 13.2377), - (124.1812, 12.9975), - (124.0774, 12.5366), - (123.2980, 13.0275), - (122.9286, 13.5529), - (122.6713, 13.1858), - (122.0346, 13.7844), - (121.1263, 13.6366), - (120.6286, 13.8576), - (120.6793, 14.2710), - (120.9918, 14.5253), - (120.6933, 14.7566), - (120.5641, 14.3962), - (120.0704, 14.9708), - (119.9209, 15.4063), - (119.8837, 16.3637), - (120.2864, 16.0346), - (120.3900, 17.5990), - (120.7158, 18.5052), - (121.3213, 18.5040), - (121.9376, 18.2185), - (122.2460, 18.4789), - (122.3369, 18.2248), - (122.0383, 11.4158), - (121.8835, 11.8917), - (122.4838, 11.5822), - (123.1202, 11.5836), - (123.1008, 11.1659), - (122.6377, 10.7413), - (122.0026, 10.4410), - (121.9673, 10.9056), - (122.0383, 11.4158), - (125.5025, 12.1626), - (125.7834, 11.0461), - (125.0118, 11.3114), - (125.0327, 10.9758), - (125.2774, 10.3587), - (124.8018, 10.1346), - (124.7601, 10.8379), - (124.4591, 10.8899), - (124.3025, 11.4953), - (124.8910, 11.4155), - (124.8779, 11.7941), - (124.2667, 12.5577), - (125.2271, 12.5357), - (125.5025, 12.1626), - (-77.3533, 8.6705), - (-76.8366, 8.6387), - (-76.0863, 9.3368), - (-75.6746, 9.4432), - (-75.6647, 9.7740), - (-75.4804, 10.6189), - (-74.9068, 11.0830), - (-74.2767, 11.1020), - (-74.1972, 11.3104), - (-73.4147, 11.2270), - (-72.6278, 11.7319), - (-72.2381, 11.9555), - (-71.7540, 12.4373), - (-71.3998, 12.3760), - (-71.1374, 12.1129), - (-71.3315, 11.7762), - (-71.3600, 11.5399), - (-71.9470, 11.4232), - (-71.6208, 10.9694), - (-71.6330, 10.4464), - (-72.0741, 9.8656), - (-71.6956, 9.0722), - (-71.2645, 9.1372), - (-71.0399, 9.8599), - (-71.3500, 10.2119), - (-71.4006, 10.9689), - (-70.1552, 11.3754), - (-70.2938, 11.8468), - (-69.9432, 12.1623), - (-69.5843, 11.4596), - (-68.8829, 11.4433), - (-68.2332, 10.8857), - (-68.1941, 10.5546), - (-67.2962, 10.5458), - (-66.2278, 10.6486), - (-65.6552, 10.2007), - (-64.8904, 10.0772), - (-64.3294, 10.3895), - (-64.3180, 10.6414), - (-63.0793, 10.7017), - (-61.8809, 10.7156), - (-62.7301, 10.4202), - (-62.3885, 9.9482), - (-61.5887, 9.8730), - (-60.8305, 9.3813), - (-60.6712, 8.5801), - (-60.1500, 8.6027), - (-59.7582, 8.3670), - (-59.1016, 7.9992), - (-58.4829, 7.3476), - (-58.4548, 6.8327), - (-58.0781, 6.8090), - (-57.5422, 6.3212), - (-57.1474, 5.9731), - (-55.9493, 5.7728), - (-55.8417, 5.9531), - (-55.0332, 6.0252), - (-53.9580, 5.7565), - (-53.6184, 5.6465), - (-52.8821, 5.4098), - (-51.8233, 4.5657), - (-51.6577, 4.1562), - (-51.2999, 4.1200), - (-51.0697, 3.6503), - (-50.5088, 1.9015), - (-49.9740, 1.7364), - (-49.9471, 1.0461), - (-50.6992, 0.2229), - (-50.3882, -0.0784), - (-48.6205, -0.2354), - (-48.5844, -1.2378), - (-47.8249, -0.5816), - (-46.5665, -0.9410), - (-44.9057, -1.5517), - (-44.4176, -2.1377), - (-44.5815, -2.6913), - (-43.4187, -2.3831), - (-41.4726, -2.9120), - (-39.9786, -2.8730), - (-38.5003, -3.7006), - (-37.2232, -4.8209), - (-36.4529, -5.1094), - (-35.5977, -5.1495), - (-35.2353, -5.4649), - (-34.8960, -6.7381), - (-34.7299, -7.3432), - (-35.1282, -8.9964), - (-35.6369, -9.6492), - (-37.0465, -11.0407), - (-37.6836, -12.1711), - (-38.4238, -13.0381), - (-38.6738, -13.0576), - (-38.9532, -13.7933), - (-38.8822, -15.6670), - (-39.1610, -17.2084), - (-39.2673, -17.8677), - (-39.5835, -18.2622), - (-39.7608, -19.5991), - (-40.7747, -20.9045), - (-40.9447, -21.9373), - (-41.7541, -22.3706), - (-41.9882, -22.9700), - (-43.0747, -22.9676), - (-44.6478, -23.3519), - (-45.3521, -23.7968), - (-46.4720, -24.0889), - (-47.6489, -24.8851), - (-48.4954, -25.8770), - (-48.6410, -26.6236), - (-48.4747, -27.1759), - (-48.6615, -28.1861), - (-48.8884, -28.6741), - (-49.5873, -29.2244), - (-50.6968, -30.9844), - (-51.5762, -31.7776), - (-52.2560, -32.2453), - (-52.7120, -33.1965), - (-53.3736, -33.7683), - (-53.8064, -34.3968), - (-54.9358, -34.9526), - (-55.6740, -34.7526), - (-56.2152, -34.8598), - (-57.1396, -34.4304), - (-57.8178, -34.4625), - (-58.4270, -33.9094), - (-58.4954, -34.4314), - (-57.2258, -35.2880), - (-57.3623, -35.9773), - (-56.7374, -36.4131), - (-56.7882, -36.9015), - (-57.7491, -38.1838), - (-59.2318, -38.7201), - (-61.2374, -38.9284), - (-62.3359, -38.8277), - (-62.1257, -39.4241), - (-62.3305, -40.1725), - (-62.1459, -40.6768), - (-62.7458, -41.0287), - (-63.7704, -41.1667), - (-64.7320, -40.8026), - (-65.1180, -41.0643), - (-64.9785, -42.0580), - (-64.3034, -42.3590), - (-63.7559, -42.0436), - (-63.4580, -42.5631), - (-64.3788, -42.8735), - (-65.1818, -43.4953), - (-65.3288, -44.5013), - (-65.5652, -45.0367), - (-66.5099, -45.0396), - (-67.2937, -45.5518), - (-67.5805, -46.3017), - (-66.5970, -47.0338), - (-65.6410, -47.2361), - (-65.9850, -48.1332), - (-67.1661, -48.6973), - (-67.8160, -49.8696), - (-68.7287, -50.2641), - (-69.1385, -50.7325), - (-68.8155, -51.7711), - (-68.1499, -52.3499), - (-68.5715, -52.2994), - (-69.4612, -52.2919), - (-69.9427, -52.5379), - (-70.8451, -52.8991), - (-71.0063, -53.8332), - (-71.4297, -53.8564), - (-72.5579, -53.5314), - (-73.7027, -52.8350), - (-74.9467, -52.2627), - (-75.2600, -51.6293), - (-74.9766, -51.0433), - (-75.4797, -50.3783), - (-75.6080, -48.6737), - (-75.1827, -47.7119), - (-74.1265, -46.9392), - (-75.6443, -46.6476), - (-74.6921, -45.7639), - (-74.3517, -44.1030), - (-73.2403, -44.4549), - (-72.7178, -42.3833), - (-73.3888, -42.1175), - (-73.7013, -43.3657), - (-74.3319, -43.2249), - (-74.0179, -41.7948), - (-73.6770, -39.9422), - (-73.2175, -39.2586), - (-73.5055, -38.2828), - (-73.5880, -37.1562), - (-73.1667, -37.1237), - (-72.5531, -35.5088), - (-71.8617, -33.9090), - (-71.4384, -32.4188), - (-71.6687, -30.9206), - (-71.3700, -30.0956), - (-71.4898, -28.8614), - (-70.9051, -27.6403), - (-70.7249, -25.7059), - (-70.4039, -23.6289), - (-70.0912, -21.3933), - (-70.1644, -19.7564), - (-70.3725, -18.3479), - (-71.3752, -17.7737), - (-71.4620, -17.3634), - (-73.4445, -16.3593), - (-75.2378, -15.2656), - (-76.0092, -14.6492), - (-76.4234, -13.8231), - (-76.2592, -13.5350), - (-77.1061, -12.2227), - (-78.0921, -10.3777), - (-79.0369, -8.3865), - (-79.4459, -7.9308), - (-79.7605, -7.1943), - (-80.5374, -6.5416), - (-81.2499, -6.1368), - (-80.9263, -5.6905), - (-81.4109, -4.7367), - (-81.0996, -4.0363), - (-80.3025, -3.4048), - (-79.7702, -2.6575), - (-79.9865, -2.2207), - (-80.3687, -2.6851), - (-80.9677, -2.2469), - (-80.7648, -1.9650), - (-80.9336, -1.0574), - (-80.5833, -0.9066), - (-80.3993, -0.2837), - (-80.0208, 0.3603), - (-80.0906, 0.7684), - (-79.5427, 0.9829), - (-78.8552, 1.3809), - (-78.9909, 1.6913), - (-78.6178, 1.7664), - (-78.6621, 2.2673), - (-78.4276, 2.6295), - (-77.9315, 2.6966), - (-77.5104, 3.3250), - (-77.1276, 3.8496), - (-77.4962, 4.0876), - (-77.3076, 4.6679), - (-77.5332, 5.5828), - (-77.3188, 5.8453), - (-77.4766, 6.6911), - (-77.8815, 7.2237), - (-74.6625, -52.8374), - (-73.8380, -53.0474), - (-72.4341, -53.7153), - (-71.1077, -54.0743), - (-70.5917, -53.6158), - (-70.2674, -52.9312), - (-69.3456, -52.5182), - (-68.6341, -52.6362), - (-68.2500, -53.1000), - (-67.7499, -53.8499), - (-66.4499, -54.4500), - (-65.0500, -54.7000), - (-65.5000, -55.1999), - (-66.4499, -55.2500), - (-66.9599, -54.8968), - (-67.2910, -55.3012), - (-68.1486, -55.6118), - (-68.6399, -55.5800), - (-69.2320, -55.4990), - (-69.9580, -55.1984), - (-71.0056, -55.0538), - (-72.2639, -54.4951), - (-73.2852, -53.9575), - (-74.6625, -52.8374), - (44.8469, 80.5898), - (46.7991, 80.7719), - (48.3184, 80.7840), - (48.5228, 80.5145), - (49.0971, 80.7539), - (50.0397, 80.9188), - (51.5229, 80.6997), - (51.1361, 80.5472), - (49.7936, 80.4154), - (48.8944, 80.3395), - (48.7549, 80.1754), - (47.5861, 80.0101), - (46.5028, 80.2472), - (47.0724, 80.5594), - (44.8469, 80.5898), - (53.5082, 73.7498), - (55.9024, 74.6274), - (55.6319, 75.0814), - (57.8686, 75.6093), - (61.1700, 76.2518), - (64.4983, 76.4390), - (66.2109, 76.8097), - (68.1570, 76.9396), - (68.8522, 76.5448), - (68.1805, 76.2336), - (64.6373, 75.7377), - (61.5835, 75.2608), - (58.4770, 74.3090), - (56.9867, 73.3330), - (55.4193, 72.3712), - (55.6228, 71.5405), - (57.5356, 70.7204), - (56.9449, 70.6327), - (53.6773, 70.7626), - (53.4120, 71.2066), - (51.6018, 71.4747), - (51.4557, 72.0148), - (52.4782, 72.2294), - (52.4441, 72.7747), - (54.4276, 73.6275), - (53.5082, 73.7498), - (27.4075, 80.0564), - (25.9246, 79.5178), - (23.0244, 79.4000), - (20.0751, 79.5668), - (19.8972, 79.8423), - (18.4622, 79.8598), - (17.3680, 80.3188), - (20.4559, 80.5981), - (21.9079, 80.3576), - (22.9192, 80.6571), - (25.4476, 80.4073), - (27.4075, 80.0564), - (24.7241, 77.8538), - (22.4903, 77.4449), - (20.7260, 77.6770), - (21.4160, 77.9350), - (20.8118, 78.2546), - (22.8842, 78.4549), - (23.2813, 78.0795), - (24.7241, 77.8538), - (15.1428, 79.6743), - (15.5225, 80.0160), - (16.9908, 80.0508), - (18.2518, 79.7017), - (21.5438, 78.9561), - (19.0273, 78.5625), - (18.4717, 77.8266), - (17.5944, 77.6379), - (17.1182, 76.8094), - (15.9131, 76.7704), - (13.7626, 77.3803), - (14.6695, 77.7356), - (13.1705, 78.0249), - (11.2222, 78.8692), - (10.4445, 79.6523), - (13.1707, 80.0104), - (13.7185, 79.6604), - (15.1428, 79.6743), - (-77.8815, 7.2237), - (-78.2149, 7.5122), - (-78.4291, 8.0520), - (-78.1820, 8.3191), - (-78.4354, 8.3877), - (-78.6221, 8.7181), - (-79.1203, 8.9960), - (-79.5578, 8.9323), - (-79.7605, 8.5845), - (-80.1644, 8.3333), - (-80.3826, 8.2984), - (-80.4806, 8.0903), - (-80.0036, 7.5475), - (-80.2766, 7.4197), - (-80.4211, 7.2715), - (-80.8864, 7.2205), - (-81.0595, 7.8179), - (-81.1897, 7.6479), - (-81.5195, 7.7066), - (-81.7213, 8.1089), - (-82.1314, 8.1753), - (-82.3909, 8.2923), - (-82.6054, 8.2916), - (-82.8200, 8.2908), - (-82.8509, 8.0738), - (-82.9657, 8.2250), - (-83.5084, 8.4469), - (-83.7114, 8.6568), - (-83.5963, 8.8304), - (-83.6326, 9.0513), - (-83.9098, 9.2908), - (-84.3034, 9.4873), - (-84.6476, 9.6155), - (-84.7133, 9.9080), - (-84.9756, 10.0867), - (-84.9113, 9.7959), - (-85.1109, 9.5570), - (-85.3394, 9.8345), - (-85.6607, 9.9333), - (-85.7974, 10.1348), - (-85.7917, 10.4393), - (-85.6593, 10.7543), - (-85.8005, 10.8247), - (-85.9417, 10.8952), - (-85.7125, 11.0884), - (-86.0584, 11.4034), - (-86.5258, 11.8068), - (-86.7459, 12.1439), - (-87.1675, 12.4582), - (-87.6684, 12.9099), - (-87.5574, 13.0645), - (-87.3923, 12.9140), - (-87.3166, 12.9846), - (-87.4894, 13.2975), - (-87.6412, 13.3410), - (-87.7931, 13.3844), - (-87.9041, 13.1490), - (-88.4833, 13.1639), - (-88.8432, 13.2597), - (-89.2567, 13.4585), - (-89.8123, 13.5206), - (-90.0955, 13.7353), - (-90.6086, 13.9097), - (-91.2324, 13.9278), - (-91.6897, 14.1262), - (-92.2277, 14.5388), - (-93.3594, 15.6154), - (-93.8751, 15.9401), - (-94.6916, 16.2009), - (-95.2502, 16.1283), - (-96.0533, 15.7520), - (-96.5574, 15.6535), - (-97.2635, 15.9170), - (-98.0130, 16.1073), - (-98.9476, 16.5660), - (-99.6973, 16.7061), - (-100.8294, 17.1710), - (-101.6660, 17.6490), - (-101.9185, 17.9160), - (-102.4781, 17.9757), - (-103.5009, 18.2922), - (-103.9175, 18.7485), - (-104.9920, 19.3161), - (-105.4930, 19.9467), - (-105.7313, 20.4341), - (-105.3977, 20.5317), - (-105.5006, 20.8168), - (-105.2707, 21.0762), - (-105.2658, 21.4221), - (-105.6031, 21.8711), - (-105.6934, 22.2690), - (-106.0287, 22.7737), - (-106.9099, 23.7678), - (-107.9154, 24.5489), - (-108.4019, 25.1723), - (-109.2601, 25.5806), - (-109.4440, 25.8248), - (-109.2916, 26.4429), - (-109.8014, 26.6761), - (-110.3917, 27.1621), - (-110.6410, 27.8598), - (-111.1789, 27.9412), - (-111.7596, 28.4679), - (-112.2282, 28.9544), - (-112.2718, 29.2668), - (-112.8095, 30.0211), - (-113.1638, 30.7868), - (-113.1486, 31.1709), - (-113.8718, 31.5676), - (-114.2057, 31.5240), - (-114.7764, 31.7995), - (-114.9366, 31.3934), - (-114.7712, 30.9136), - (-114.6738, 30.1626), - (-114.3309, 29.7504), - (-113.5888, 29.0616), - (-113.4240, 28.8261), - (-113.2719, 28.7547), - (-113.1400, 28.4112), - (-112.9622, 28.4251), - (-112.7615, 27.7802), - (-112.4579, 27.5258), - (-112.2449, 27.1717), - (-111.6164, 26.6628), - (-111.2846, 25.7325), - (-110.9878, 25.2946), - (-110.7100, 24.8260), - (-110.6550, 24.2985), - (-110.1728, 24.2655), - (-109.7718, 23.8111), - (-109.4091, 23.3646), - (-109.4333, 23.1855), - (-109.8542, 22.8182), - (-110.0313, 22.8230), - (-110.2950, 23.4309), - (-110.9495, 24.0009), - (-111.6705, 24.4844), - (-112.1820, 24.7384), - (-112.1489, 25.4701), - (-112.3007, 26.0120), - (-112.7772, 26.3219), - (-113.4646, 26.7681), - (-113.5967, 26.6394), - (-113.8489, 26.9000), - (-114.4657, 27.1420), - (-115.0551, 27.7227), - (-114.9822, 27.7982), - (-114.5703, 27.7414), - (-114.1993, 28.1150), - (-114.1620, 28.5661), - (-114.9318, 29.2794), - (-115.5186, 29.5563), - (-115.8873, 30.1807), - (-116.2583, 30.8364), - (-116.7215, 31.6357), - (-117.1277, 32.5353), - (-117.2959, 33.0462), - (-117.944, 33.6212), - (-118.4106, 33.7409), - (-118.5198, 34.0277), - (-119.081, 34.078), - (-119.4388, 34.3484), - (-120.3677, 34.4470), - (-120.6228, 34.6085), - (-120.7443, 35.1568), - (-121.7145, 36.1615), - (-122.5474, 37.5517), - (-122.5119, 37.7833), - (-122.9531, 38.1136), - (-123.7271, 38.9516), - (-123.8651, 39.7669), - (-124.3980, 40.3131), - (-124.1788, 41.1420), - (-124.2137, 41.9996), - (-124.5328, 42.7659), - (-124.1421, 43.7083), - (-124.0205, 44.6158), - (-123.8989, 45.5234), - (-124.0796, 46.8647), - (-124.3956, 47.7201), - (-124.6872, 48.1844), - (-124.5661, 48.3797), - (-123.12, 48.04), - (-122.5873, 47.0959), - (-122.3399, 47.3600), - (-122.5000, 48.1800), - (-122.84, 49.0), - (-122.9742, 49.0025), - (-124.9102, 49.9845), - (-125.6246, 50.4165), - (-127.4356, 50.8305), - (-127.9927, 51.7158), - (-127.8503, 52.3296), - (-129.1297, 52.7553), - (-129.3052, 53.5615), - (-130.5149, 54.2875), - (-130.5361, 54.8027), - (-131.0858, 55.1789), - (-131.9672, 55.4977), - (-132.2500, 56.3699), - (-133.5391, 57.1788), - (-134.0780, 58.1230), - (-135.0382, 58.1877), - (-136.6280, 58.2122), - (-137.8000, 58.4999), - (-139.8677, 59.5377), - (-140.8252, 59.7275), - (-142.5744, 60.0844), - (-143.9588, 59.9991), - (-145.9255, 60.4586), - (-147.1143, 60.8846), - (-148.2243, 60.6729), - (-148.0180, 59.9783), - (-148.5708, 59.9141), - (-149.7278, 59.7056), - (-150.6082, 59.3682), - (-151.7163, 59.1558), - (-151.8594, 59.7449), - (-151.4097, 60.7258), - (-150.3469, 61.0335), - (-150.6211, 61.2844), - (-151.8958, 60.7271), - (-152.5783, 60.0616), - (-154.0191, 59.3502), - (-153.2875, 58.8647), - (-154.2324, 58.1463), - (-155.3074, 57.7277), - (-156.3083, 57.4227), - (-156.5560, 56.9799), - (-158.1172, 56.4636), - (-158.4333, 55.9941), - (-159.6033, 55.5666), - (-160.2897, 55.6435), - (-161.2230, 55.3647), - (-162.2377, 55.0241), - (-163.0694, 54.6897), - (-164.7855, 54.4041), - (-164.9422, 54.5722), - (-163.8483, 55.0394), - (-162.8700, 55.3480), - (-161.8041, 55.8949), - (-160.5636, 56.0080), - (-160.0705, 56.4180), - (-158.6844, 57.0166), - (-158.4610, 57.2169), - (-157.7227, 57.5700), - (-157.5502, 58.3283), - (-157.0416, 58.9188), - (-158.1947, 58.6158), - (-158.5172, 58.7877), - (-159.0586, 58.4241), - (-159.7116, 58.9313), - (-159.9812, 58.5725), - (-160.3552, 59.0711), - (-161.3550, 58.6708), - (-161.9688, 58.6716), - (-162.0549, 59.2669), - (-161.8741, 59.6336), - (-162.5180, 59.9897), - (-163.8183, 59.7980), - (-164.6622, 60.2674), - (-165.3463, 60.5074), - (-165.3508, 61.0738), - (-166.1213, 61.5000), - (-165.7344, 62.0749), - (-164.9191, 62.6330), - (-164.5625, 63.1463), - (-163.7533, 63.2194), - (-163.0672, 63.0594), - (-162.2605, 63.5419), - (-161.5344, 63.4558), - (-160.7725, 63.7661), - (-160.9583, 64.2227), - (-161.5180, 64.4027), - (-160.7777, 64.7886), - (-161.3919, 64.7772), - (-162.4530, 64.5594), - (-162.7577, 64.3386), - (-163.5463, 64.5591), - (-164.9608, 64.4469), - (-166.4252, 64.6866), - (-166.8450, 65.0888), - (-168.1105, 65.6699), - (-166.7052, 66.0883), - (-164.4747, 66.5766), - (-163.6525, 66.5766), - (-163.7886, 66.0772), - (-161.6777, 66.1161), - (-162.4897, 66.7355), - (-163.7197, 67.1163), - (-164.4309, 67.6163), - (-165.3902, 68.0427), - (-166.7644, 68.3588), - (-166.2047, 68.8830), - (-164.4308, 68.9155), - (-163.1686, 69.3711), - (-162.9305, 69.8580), - (-161.9088, 70.3333), - (-160.9347, 70.4476), - (-159.0391, 70.8916), - (-158.1197, 70.8247), - (-156.5808, 71.3577), - (-155.0677, 71.1477), - (-154.3441, 70.6964), - (-153.9000, 70.8899), - (-152.2100, 70.8299), - (-152.2700, 70.6000), - (-150.7399, 70.4300), - (-149.7200, 70.5300), - (-147.6133, 70.2140), - (-145.6899, 70.1200), - (-144.9200, 69.9899), - (-143.5894, 70.1525), - (-142.0725, 69.8519), - (-140.9859, 69.7119), - (-139.1205, 69.4710), - (-137.5463, 68.9900), - (-136.5035, 68.8980), - (-135.6257, 69.3151), - (-134.4146, 69.6274), - (-132.9292, 69.5053), - (-131.4313, 69.9445), - (-129.7947, 70.1937), - (-129.1077, 69.7792), - (-128.3615, 70.0128), - (-128.1381, 70.4838), - (-127.4471, 70.3772), - (-125.7563, 69.4805), - (-124.4248, 70.1584), - (-124.2896, 69.3996), - (-123.0610, 69.5637), - (-122.6834, 69.8555), - (-121.4722, 69.7977), - (-119.9428, 69.3778), - (-117.6026, 69.0112), - (-116.2264, 68.8414), - (-115.2468, 68.9059), - (-113.8979, 68.3989), - (-115.3048, 67.9026), - (-113.4972, 67.6881), - (-110.7980, 67.8060), - (-109.9461, 67.9810), - (-108.8801, 67.3814), - (-107.7923, 67.8873), - (-108.8129, 68.3116), - (-108.1672, 68.6539), - (-106.9500, 68.6999), - (-106.1500, 68.7999), - (-105.3428, 68.5612), - (-104.3379, 68.0180), - (-103.2211, 68.0977), - (-101.4543, 67.6468), - (-99.9019, 67.8056), - (-98.4432, 67.7816), - (-98.5586, 68.4039), - (-97.6694, 68.5786), - (-96.1199, 68.2394), - (-96.1258, 67.2933), - (-95.4894, 68.0907), - (-94.6849, 68.0638), - (-94.2328, 69.0690), - (-95.3040, 69.6857), - (-96.4713, 70.0897), - (-96.3911, 71.1948), - (-95.2088, 71.9205), - (-93.8899, 71.7601), - (-92.8781, 71.3186), - (-91.5196, 70.1912), - (-92.4069, 69.6999), - (-90.5471, 69.4976), - (-90.5514, 68.4749), - (-89.2151, 69.2587), - (-88.0196, 68.6150), - (-88.3174, 67.8733), - (-87.3501, 67.1987), - (-86.3060, 67.9214), - (-85.5766, 68.7845), - (-85.5219, 69.8820), - (-84.1008, 69.8054), - (-82.6225, 69.6582), - (-81.2804, 69.1620), - (-81.2202, 68.6656), - (-81.9643, 68.1325), - (-81.2592, 67.5971), - (-81.3865, 67.1107), - (-83.3445, 66.4115), - (-84.7354, 66.2572), - (-85.7694, 66.5583), - (-86.0676, 66.0562), - (-87.0314, 65.2129), - (-87.3232, 64.7756), - (-88.4829, 64.0989), - (-89.9144, 64.0327), - (-90.7039, 63.6101), - (-90.7700, 62.9602), - (-91.9334, 62.8350), - (-93.1569, 62.0246), - (-94.2415, 60.8986), - (-94.6293, 60.1102), - (-94.6846, 58.9488), - (-93.2150, 58.7821), - (-92.7646, 57.8457), - (-92.2970, 57.0870), - (-90.8976, 57.2846), - (-89.0395, 56.8517), - (-88.0397, 56.4716), - (-87.3241, 55.9991), - (-86.0712, 55.7238), - (-85.0118, 55.3026), - (-83.3605, 55.2448), - (-82.2728, 55.1483), - (-82.4362, 54.2822), - (-82.1250, 53.2770), - (-81.4007, 52.1578), - (-79.9128, 51.2083), - (-79.1430, 51.5339), - (-78.6019, 52.5620), - (-79.1242, 54.1414), - (-79.8295, 54.6677), - (-78.2287, 55.1364), - (-77.0955, 55.8374), - (-76.5413, 56.5342), - (-76.6231, 57.2026), - (-77.3022, 58.0520), - (-78.5168, 58.8045), - (-77.3367, 59.8526), - (-77.7727, 60.7578), - (-78.1068, 62.3196), - (-77.4106, 62.5505), - (-75.6962, 62.2783), - (-74.6682, 62.1811), - (-73.8398, 62.4437), - (-72.9085, 62.1050), - (-71.6770, 61.5253), - (-71.3736, 61.1371), - (-69.5904, 61.0614), - (-69.6203, 60.2212), - (-69.2878, 58.9573), - (-68.3745, 58.8010), - (-67.6497, 58.2120), - (-66.2017, 58.7673), - (-65.2451, 59.8707), - (-64.5835, 60.3355), - (-63.8047, 59.4425), - (-62.5023, 58.1670), - (-61.3965, 56.9674), - (-61.7986, 56.3394), - (-60.4685, 55.7754), - (-59.5696, 55.2040), - (-57.9750, 54.9454), - (-57.3332, 54.6264), - (-56.9368, 53.7803), - (-56.1581, 53.6474), - (-55.7563, 53.2703), - (-55.6833, 52.1466), - (-56.4091, 51.7706), - (-57.1269, 51.4197), - (-58.7748, 51.0642), - (-60.0331, 50.2427), - (-61.7236, 50.0804), - (-63.8625, 50.2909), - (-65.3633, 50.2981), - (-66.3990, 50.2289), - (-67.2363, 49.5115), - (-68.5111, 49.0683), - (-69.9536, 47.7448), - (-71.1045, 46.8217), - (-70.2552, 46.9860), - (-68.6499, 48.2999), - (-66.5524, 49.1330), - (-65.0562, 49.2327), - (-64.1709, 48.7425), - (-65.1154, 48.0708), - (-64.7985, 46.9929), - (-64.4721, 46.2384), - (-63.1732, 45.7390), - (-61.5207, 45.8837), - (-60.5181, 47.0079), - (-60.4486, 46.2826), - (-59.8028, 45.9204), - (-61.0398, 45.2652), - (-63.2547, 44.6701), - (-64.2465, 44.2655), - (-65.3640, 43.5452), - (-66.1234, 43.6186), - (-66.1617, 44.4651), - (-64.4254, 45.2920), - (-66.0260, 45.2593), - (-67.1374, 45.1375), - (-66.9646, 44.8097), - (-68.0325, 44.3252), - (-69.06, 43.98), - (-70.1161, 43.6840), - (-70.6454, 43.0902), - (-70.8148, 42.8652), - (-70.8249, 42.3349), - (-70.4949, 41.8049), - (-70.0800, 41.7800), - (-70.1849, 42.1449), - (-69.8849, 41.9228), - (-69.9650, 41.6371), - (-70.6399, 41.4749), - (-71.1203, 41.4944), - (-71.8538, 41.3199), - (-72.2949, 41.2699), - (-72.8764, 41.2206), - (-73.71, 40.9311), - (-72.2412, 41.1194), - (-71.9450, 40.9300), - (-73.3450, 40.6300), - (-73.9819, 40.6280), - (-73.9523, 40.7507), - (-74.2567, 40.4734), - (-73.9624, 40.4276), - (-74.1783, 39.7092), - (-74.9060, 38.9395), - (-74.9804, 39.1963), - (-75.2000, 39.2484), - (-75.5280, 39.4984), - (-75.3199, 38.9599), - (-75.0718, 38.7820), - (-75.0567, 38.4041), - (-75.3774, 38.0155), - (-75.9402, 37.2169), - (-76.0312, 37.2565), - (-75.7220, 37.9370), - (-76.2328, 38.3192), - (-76.35, 39.15), - (-76.5427, 38.7176), - (-76.3293, 38.0832), - (-76.9899, 38.2399), - (-76.3016, 37.9179), - (-76.2587, 36.9664), - (-75.9718, 36.8972), - (-75.8680, 36.5512), - (-75.7274, 35.5507), - (-76.3631, 34.8085), - (-77.3976, 34.5120), - (-78.0549, 33.9254), - (-78.5543, 33.8613), - (-79.0606, 33.4939), - (-79.2035, 33.1583), - (-80.3013, 32.5093), - (-80.8649, 32.0333), - (-81.3362, 31.4404), - (-81.4904, 30.7299), - (-81.3137, 30.0355), - (-80.9799, 29.1800), - (-80.5355, 28.4721), - (-80.5299, 28.0399), - (-80.0565, 26.88), - (-80.0880, 26.2057), - (-80.1315, 25.8167), - (-80.3810, 25.2061), - (-80.6800, 25.0799), - (-81.1721, 25.2012), - (-81.3299, 25.6399), - (-81.7099, 25.8699), - (-82.2400, 26.7299), - (-82.7051, 27.4950), - (-82.8552, 27.8862), - (-82.6500, 28.5499), - (-82.93, 29.1), - (-83.7095, 29.9365), - (-84.1, 30.09), - (-85.1088, 29.6361), - (-85.2878, 29.6861), - (-85.7731, 30.1526), - (-86.3999, 30.4000), - (-87.5303, 30.2743), - (-88.4178, 30.3849), - (-89.1804, 30.3159), - (-89.5938, 30.1599), - (-89.4137, 29.8941), - (-89.43, 29.48864), - (-89.2176, 29.2910), - (-89.4082, 29.1596), - (-89.7792, 29.3071), - (-90.1546, 29.1174), - (-90.8802, 29.1485), - (-91.6267, 29.677), - (-92.4990, 29.5523), - (-93.2263, 29.7837), - (-93.8484, 29.7136), - (-94.6900, 29.4800), - (-95.6002, 28.7386), - (-96.5940, 28.3074), - (-97.1400, 27.8300), - (-97.3699, 27.3800), - (-97.3799, 26.6899), - (-97.3299, 26.2100), - (-97.1400, 25.8699), - (-97.5280, 24.9921), - (-97.7029, 24.2723), - (-97.7760, 22.9325), - (-97.8723, 22.4442), - (-97.6990, 21.8986), - (-97.3889, 21.4110), - (-97.1893, 20.6354), - (-96.5255, 19.8909), - (-96.2921, 19.3203), - (-95.9008, 18.8280), - (-94.8390, 18.5627), - (-94.4257, 18.1443), - (-93.5486, 18.4238), - (-92.7861, 18.5248), - (-92.0373, 18.7045), - (-91.4079, 18.8760), - (-90.7718, 19.2841), - (-90.5335, 19.8674), - (-90.4514, 20.7075), - (-90.2786, 20.9998), - (-89.6013, 21.2617), - (-88.5438, 21.4936), - (-87.6584, 21.4588), - (-87.0518, 21.5435), - (-86.8119, 21.3315), - (-86.8459, 20.8498), - (-87.3832, 20.2554), - (-87.6210, 19.6465), - (-87.4367, 19.4724), - (-87.5865, 19.0401), - (-87.8371, 18.2598), - (-88.0906, 18.5166), - (-88.3000, 18.4999), - (-88.2963, 18.3532), - (-88.1068, 18.3486), - (-88.1234, 18.0766), - (-88.2853, 17.6441), - (-88.1978, 17.4894), - (-88.3026, 17.1316), - (-88.2395, 17.0360), - (-88.3554, 16.5307), - (-88.5518, 16.2654), - (-88.7324, 16.2336), - (-88.9306, 15.8872), - (-88.6045, 15.7063), - (-88.5183, 15.8553), - (-88.1899, 15.7199), - (-88.1211, 15.6886), - (-87.9018, 15.8644), - (-87.6156, 15.8787), - (-87.5229, 15.7972), - (-87.3677, 15.8469), - (-86.9031, 15.7567), - (-86.4409, 15.7828), - (-86.1192, 15.8934), - (-86.0019, 16.0054), - (-85.6833, 15.9536), - (-85.4440, 15.8857), - (-85.1824, 15.9091), - (-84.9837, 15.9959), - (-84.5269, 15.8572), - (-84.3682, 15.8351), - (-84.0630, 15.6482), - (-83.7739, 15.4240), - (-83.4103, 15.2709), - (-83.1472, 14.9958), - (-83.2332, 14.8998), - (-83.2841, 14.6766), - (-83.1821, 14.3107), - (-83.4124, 13.9700), - (-83.5198, 13.5676), - (-83.5522, 13.1270), - (-83.4985, 12.8692), - (-83.4733, 12.4190), - (-83.6261, 12.3208), - (-83.7196, 11.8931), - (-83.6508, 11.6290), - (-83.8554, 11.3733), - (-83.8089, 11.1030), - (-83.6556, 10.9387), - (-83.5900, 10.7850), - (-83.4023, 10.3954), - (-83.0156, 9.9929), - (-82.5461, 9.5661), - (-82.1871, 9.2074), - (-82.2075, 8.9955), - (-81.8085, 8.9506), - (-81.7141, 9.0319), - (-81.4392, 8.7862), - (-80.9473, 8.8585), - (-80.5219, 9.1110), - (-79.9145, 9.3127), - (-79.5733, 9.6116), - (-79.0211, 9.5529), - (-79.0584, 9.4545), - (-78.5008, 9.4204), - (-78.0559, 9.2477), - (-77.7295, 8.9468), - (-77.3533, 8.6705), - (-71.7123, 19.7144), - (-71.5873, 19.8849), - (-71.3800, 19.9049), - (-70.8067, 19.8802), - (-70.2143, 19.6228), - (-69.9508, 19.6479), - (-69.7692, 19.2932), - (-69.2221, 19.3132), - (-69.2543, 19.0151), - (-68.8094, 18.9791), - (-68.3179, 18.6121), - (-68.6893, 18.2051), - (-69.1649, 18.4226), - (-69.6239, 18.3807), - (-69.9529, 18.4283), - (-70.1332, 18.2459), - (-70.5171, 18.1842), - (-70.6692, 18.4268), - (-70.9999, 18.2833), - (-71.4002, 17.5985), - (-71.6576, 17.7575), - (-71.7083, 18.0449), - (-72.3724, 18.2149), - (-72.8444, 18.1456), - (-73.4545, 18.2179), - (-73.9224, 18.0309), - (-74.4580, 18.3425), - (-74.3699, 18.6649), - (-73.4495, 18.5260), - (-72.6949, 18.4457), - (-72.3348, 18.6684), - (-72.7916, 19.1016), - (-72.7841, 19.4835), - (-73.4150, 19.6395), - (-73.1897, 19.9156), - (-72.5796, 19.8715), - (-71.7123, 19.7144), - (14.7612, 38.1438), - (15.5203, 38.2311), - (15.1602, 37.4440), - (15.3098, 37.1342), - (15.0999, 36.6199), - (14.3352, 36.9966), - (13.8267, 37.1045), - (12.4310, 37.6129), - (12.5709, 38.1263), - (13.7411, 38.0349), - (14.7612, 38.1438), - (37.5391, 44.6572), - (38.6799, 44.2799), - (39.9550, 43.4349), - (132.3711, 33.4636), - (132.9243, 34.0602), - (133.4929, 33.9446), - (133.9041, 34.3649), - (134.6384, 34.1492), - (134.7663, 33.8063), - (134.2034, 33.2011), - (133.7929, 33.5219), - (133.2802, 33.2895), - (133.0148, 32.7045), - (132.3631, 32.9893), - (132.3711, 33.4636), - (180.0000, 68.9636), - (178.5999, 69.4000), - (175.7240, 69.8772), - (173.6439, 69.8174), - (170.4534, 70.0970), - (170.0082, 69.6527), - (170.8168, 69.0136), - (169.5776, 68.6938), - (167.8629, 69.5687), - (165.9403, 69.4719), - (164.0524, 69.6682), - (162.2790, 69.6420), - (160.9405, 69.4372), - (159.7086, 69.7219), - (159.8303, 70.4532), - (158.9977, 70.8667), - (157.0068, 71.0314), - (152.9688, 70.8422), - (150.3511, 71.6064), - (149.5000, 72.1999), - (140.4681, 72.8494), - (139.1479, 72.4161), - (139.8698, 71.4878), - (138.2340, 71.6280), - (137.4975, 71.3476), - (135.5619, 71.6552), - (133.8576, 71.3864), - (132.2535, 71.8363), - (131.2885, 70.7869), - (129.7159, 71.1930), - (128.46, 71.98), - (129.0515, 72.3987), - (128.5912, 73.0387), - (126.9764, 73.5654), - (125.38, 73.56), - (123.2577, 73.7350), - (123.2006, 72.9712), - (119.02, 73.12), - (118.7763, 73.5877), - (115.5678, 73.7528), - (113.9688, 73.5948), - (113.5295, 73.3350), - (113.0195, 73.9769), - (112.1191, 73.7877), - (110.64, 74.04), - (109.4, 74.18), - (110.1512, 74.4767), - (112.7791, 75.0318), - (113.8853, 75.3277), - (114.1341, 75.8476), - (113.3315, 76.2222), - (111.07726, 76.71), - (108.1537, 76.7233), - (107.2399, 76.4799), - (106.9701, 76.9741), - (104.7050, 77.1273), - (106.0666, 77.3738), - (104.3515, 77.6979), - (101.9908, 77.2875), - (101.0353, 76.8618), - (100.7596, 76.4302), - (98.9225, 76.4468), - (96.6782, 75.9154), - (95.8600, 76.1400), - (93.2342, 76.0471), - (92.9006, 75.7733), - (90.2599, 75.6399), - (88.3156, 75.1439), - (87.1668, 75.1164), - (86.0095, 74.4596), - (86.8223, 73.9368), - (84.6552, 73.8059), - (82.2499, 73.8500), - (80.5110, 73.6482), - (80.6107, 72.5828), - (81.5000, 71.7499), - (79.6520, 72.3201), - (77.5766, 72.2671), - (75.9031, 71.8740), - (76.3591, 71.1528), - (75.2889, 71.3355), - (75.6835, 72.3005), - (75.1580, 72.8549), - (74.6592, 72.8322), - (74.8908, 72.1211), - (73.1011, 71.4471), - (74.3998, 70.6317), - (73.6018, 69.6276), - (73.8423, 69.0714), - (74.9358, 68.9891), - (74.4692, 68.3289), - (75.052, 67.76047), - (74.1865, 67.2842), - (73.9209, 66.7894), - (72.8207, 66.5326), - (72.4230, 66.1726), - (71.28, 66.32), - (73.2387, 67.7404), - (73.6678, 68.4079), - (72.5646, 69.0208), - (72.7918, 70.3911), - (72.4701, 71.0901), - (71.8481, 71.4089), - (72.7960, 72.2200), - (72.5875, 72.7762), - (69.94, 73.04), - (69.1963, 72.8433), - (68.5400, 71.9345), - (66.6946, 71.0289), - (66.7249, 70.7088), - (67.2597, 69.9287), - (66.9300, 69.4546), - (68.1352, 69.3564), - (68.1644, 69.1443), - (69.1806, 68.6156), - (68.5121, 68.0923), - (64.8881, 69.2348), - (63.5040, 69.5473), - (60.5500, 69.8500), - (60.03, 69.52), - (61.0778, 68.9406), - (59.9414, 68.2784), - (58.802, 68.88082), - (57.3170, 68.4662), - (55.4426, 68.4386), - (54.7530, 68.0868), - (53.4858, 68.2013), - (54.4717, 68.8081), - (53.7174, 68.8573), - (48.1387, 67.5223), - (47.8941, 66.8845), - (46.3491, 66.6676), - (45.5620, 67.0100), - (45.5551, 67.5665), - (46.8213, 67.6899), - (46.2500, 68.2499), - (43.4528, 68.5708), - (44.1747, 67.9616), - (43.6983, 67.3524), - (44.5322, 66.7563), - (43.9497, 66.0690), - (43.0160, 66.4185), - (42.0930, 66.4762), - (39.7626, 65.4968), - (40.4356, 64.7644), - (39.5934, 64.5207), - (37.1760, 65.1432), - (36.5395, 64.7644), - (37.1419, 64.3347), - (37.0127, 63.8498), - (36.2312, 64.1094), - (34.9439, 64.4143), - (34.8785, 65.4362), - (34.8147, 65.9001), - (33.1844, 66.6325), - (33.9186, 66.7595), - (38.3829, 65.9995), - (40.0158, 66.2661), - (41.1259, 66.7915), - (41.0598, 67.4571), - (40.2923, 67.9323), - (36.5139, 69.0634), - (33.7754, 69.3014), - (32.1327, 69.9059), - (31.1010, 69.5580), - (30.0054, 70.1862), - (31.2934, 70.4537), - (28.1655, 71.1854), - (26.3700, 70.9862), - (24.5465, 71.0304), - (23.0237, 70.2020), - (21.3784, 70.2551), - (19.1840, 69.8174), - (16.4359, 68.5632), - (14.7611, 67.8106), - (12.3583, 65.8797), - (10.5277, 64.4860), - (8.5534, 63.4540), - (5.9129, 62.6144), - (4.9920, 61.9709), - (5.3082, 59.6632), - (5.6658, 58.5881), - (7.0487, 58.0788), - (8.3820, 58.3132), - (10.3565, 59.4698), - (11.0273, 58.8561), - (11.7879, 57.4418), - (12.6251, 56.3070), - (12.9429, 55.3617), - (14.1007, 55.4077), - (14.6666, 56.2008), - (15.8797, 56.1043), - (16.4477, 57.0411), - (16.8291, 58.7198), - (17.8692, 58.9537), - (18.7877, 60.0819), - (17.8313, 60.6365), - (17.1195, 61.3411), - (17.8477, 62.7494), - (19.7788, 63.6095), - (21.3696, 64.4135), - (21.2135, 65.0260), - (22.1831, 65.7237), - (23.9033, 66.0069), - (25.2940, 65.5343), - (25.3980, 65.1114), - (24.7305, 64.9023), - (22.4427, 63.8178), - (21.5360, 63.1897), - (21.0592, 62.6073), - (21.5448, 61.7053), - (21.3222, 60.7201), - (22.2907, 60.3919), - (22.8696, 59.8463), - (24.4966, 60.0573), - (26.2551, 60.4239), - (28.0699, 60.5035), - (29.1176, 60.0280), - (27.9811, 59.4753), - (26.9491, 59.4458), - (25.8641, 59.6110), - (24.6042, 59.4658), - (23.3397, 59.1872), - (23.4265, 58.6127), - (24.0611, 58.2573), - (24.4289, 58.3834), - (24.3128, 57.7934), - (24.1207, 57.0256), - (23.3184, 57.0062), - (22.5243, 57.7533), - (21.5818, 57.4118), - (21.0904, 56.7838), - (21.0558, 56.0310), - (21.2684, 55.1904), - (19.8884, 54.8661), - (19.6606, 54.4260), - (18.6962, 54.4387), - (18.6208, 54.6826), - (17.6228, 54.8515), - (16.3634, 54.5131), - (14.8029, 54.0507), - (14.1196, 53.7570), - (13.6474, 54.0755), - (12.5184, 54.4703), - (11.9562, 54.1964), - (10.9394, 54.0086), - (10.9501, 54.3636), - (9.9395, 54.5966), - (9.9219, 54.9831), - (9.6499, 55.4699), - (10.3699, 56.1900), - (10.6678, 56.0813), - (10.9121, 56.4586), - (10.3699, 56.6099), - (10.2500, 56.8900), - (10.5461, 57.2157), - (10.5800, 57.7300), - (9.7755, 57.4479), - (9.4244, 57.1720), - (8.5434, 57.1100), - (8.2565, 56.8099), - (8.0899, 56.5400), - (8.1203, 55.5177), - (8.5262, 54.9627), - (8.5721, 54.3956), - (8.8007, 54.0207), - (8.1217, 53.5277), - (7.9362, 53.7482), - (7.1004, 53.6939), - (6.9051, 53.4821), - (6.0741, 53.5104), - (4.7059, 53.0917), - (3.8302, 51.6205), - (3.3149, 51.3457), - (2.5135, 51.1485), - (1.6390, 50.9466), - (1.3387, 50.1271), - (-0.9894, 49.3473), - (-1.9334, 49.7763), - (-1.6165, 48.6444), - (-3.2958, 48.9016), - (-4.5923, 48.6841), - (-4.4915, 47.9549), - (-2.9632, 47.5703), - (-2.2257, 47.0643), - (-1.1937, 46.0149), - (-1.3842, 44.0226), - (-1.9013, 43.4228), - (-3.5175, 43.4559), - (-4.3478, 43.4034), - (-5.4118, 43.5742), - (-6.7544, 43.5679), - (-7.9781, 43.7483), - (-9.3928, 43.0266), - (-8.9844, 42.5927), - (-9.0348, 41.8805), - (-8.9907, 41.5434), - (-8.7908, 41.1843), - (-8.7686, 40.7606), - (-8.9773, 40.1593), - (-9.0483, 39.7550), - (-9.4469, 39.3920), - (-9.5265, 38.7374), - (-9.2874, 38.3584), - (-8.8399, 38.2662), - (-8.7461, 37.6513), - (-8.8988, 36.8688), - (-8.3828, 36.9788), - (-7.8556, 36.8382), - (-7.4537, 37.0977), - (-6.5201, 36.9429), - (-6.2366, 36.3676), - (-5.8664, 36.0298), - (-5.3771, 35.9468), - (-4.9952, 36.3247), - (-4.3689, 36.6778), - (-3.4157, 36.6588), - (-2.1464, 36.6741), - (-1.4383, 37.4430), - (-0.6833, 37.6423), - (-0.4671, 38.2923), - (0.1112, 38.7385), - (-0.2787, 39.3099), - (0.1066, 40.1239), - (0.7213, 40.6783), - (0.8105, 41.0147), - (2.0918, 41.2260), - (3.0394, 41.8921), - (2.9859, 42.4730), - (3.1004, 43.0752), - (4.5569, 43.3996), - (6.5292, 43.1288), - (7.4351, 43.6938), - (7.8507, 43.7671), - (8.4285, 44.2312), - (8.8889, 44.3663), - (9.7024, 44.0362), - (10.2000, 43.9200), - (10.5119, 42.9314), - (11.1919, 42.3554), - (12.1066, 41.7045), - (12.8880, 41.2530), - (13.6279, 41.1882), - (14.0606, 40.7863), - (14.7032, 40.6045), - (14.9984, 40.1729), - (15.4136, 40.0483), - (15.7188, 39.5440), - (16.1093, 38.9645), - (15.8919, 38.7509), - (15.6879, 38.2145), - (15.6840, 37.9088), - (16.1009, 37.9858), - (16.6350, 38.8435), - (17.0528, 38.9028), - (17.1714, 39.4246), - (16.4487, 39.7954), - (16.8695, 40.4422), - (17.7383, 40.2776), - (18.2933, 39.8107), - (18.4802, 40.1688), - (18.3766, 40.3556), - (17.5191, 40.8771), - (16.7850, 41.1796), - (15.8893, 41.5410), - (16.1698, 41.7402), - (15.9261, 41.9613), - (15.1425, 41.9551), - (14.0298, 42.7610), - (13.5269, 43.5877), - (12.5892, 44.0913), - (12.2614, 44.6004), - (12.3838, 44.8853), - (12.3285, 45.3817), - (13.1416, 45.7366), - (13.9376, 45.5910), - (13.7150, 45.5003), - (13.6794, 45.4841), - (13.6569, 45.1369), - (13.9522, 44.8021), - (14.2587, 45.2337), - (14.9016, 45.0760), - (14.9203, 44.7384), - (15.3762, 44.3179), - (15.1744, 44.2431), - (16.0153, 43.5072), - (16.9300, 43.2099), - (17.5099, 42.8499), - (18.4500, 42.4799), - (18.8821, 42.2815), - (19.1624, 41.9550), - (19.3717, 41.8775), - (19.5400, 41.7199), - (19.4035, 41.4095), - (19.3190, 40.7272), - (19.4060, 40.2507), - (19.9600, 39.9150), - (19.9800, 39.6949), - (20.1500, 39.6249), - (20.2177, 39.3402), - (20.7300, 38.7699), - (21.1200, 38.3103), - (21.2950, 37.6449), - (21.6700, 36.8449), - (22.4900, 36.4100), - (23.1542, 36.4225), - (22.7749, 37.3050), - (23.4099, 37.4099), - (23.1150, 37.9200), - (24.0400, 37.6550), - (24.0250, 38.2199), - (23.5300, 38.5100), - (22.9730, 38.9709), - (23.3500, 39.1900), - (22.8497, 39.6593), - (22.6262, 40.2565), - (22.8139, 40.4760), - (23.3429, 39.9609), - (23.8999, 39.9620), - (24.4079, 40.1249), - (23.7148, 40.6871), - (24.9258, 40.9470), - (25.4476, 40.8525), - (26.0569, 40.8241), - (26.0433, 40.6177), - (26.3580, 40.1519), - (27.1923, 40.6905), - (27.6190, 40.9998), - (28.8064, 41.0549), - (28.9884, 41.2999), - (28.1155, 41.6228), - (27.9967, 42.0073), - (27.6738, 42.5778), - (28.0390, 43.2931), - (28.5580, 43.7074), - (28.8378, 44.9138), - (29.1416, 44.8202), - (29.6265, 45.0353), - (29.6032, 45.2933), - (30.3776, 46.0324), - (30.7487, 46.5831), - (31.6753, 46.7062), - (31.7441, 46.3333), - (33.2985, 46.0805), - (33.5881, 45.8515), - (32.6308, 45.5191), - (32.4541, 45.3274), - (33.5469, 45.0347), - (33.3264, 44.5648), - (33.8825, 44.3614), - (35.2399, 44.9399), - (36.3347, 45.1132), - (36.5299, 45.4699), - (35.5100, 45.4099), - (35.0207, 45.6512), - (34.9623, 46.2731), - (35.8236, 46.6459), - (36.7598, 46.6987), - (37.4251, 47.0222), - (38.2235, 47.1021), - (39.1212, 47.2633), - (39.1476, 47.0447), - (37.6737, 46.6365), - (38.2329, 46.2408), - (37.4031, 45.4045), - (36.6754, 45.2446), - (37.5391, 44.6572), - (38.6799, 44.2799), - (39.9550, 43.4349), - (40.3213, 43.1286), - (40.8754, 43.0136), - (41.4534, 42.6451), - (41.7031, 41.9629), - (41.5540, 41.5356), - (40.3734, 41.0136), - (39.5126, 41.1027), - (38.3476, 40.9485), - (36.9131, 41.3353), - (35.1677, 42.0402), - (33.5132, 42.0189), - (32.3479, 41.7362), - (31.1459, 41.0876), - (29.2400, 41.2199), - (28.8199, 40.4600), - (27.2800, 40.4200), - (26.1707, 39.4636), - (26.8047, 38.9857), - (26.3182, 38.2081), - (27.0487, 37.6533), - (27.6411, 36.6588), - (28.7329, 36.6768), - (29.6999, 36.1443), - (30.3910, 36.2629), - (30.6216, 36.6778), - (31.6995, 36.6442), - (32.5091, 36.1075), - (34.0268, 36.2199), - (34.7145, 36.7955), - (35.5509, 36.5654), - (36.1608, 36.6506), - (35.7820, 36.2749), - (36.1497, 35.8215), - (35.9050, 35.4100), - (35.9984, 34.6449), - (35.9795, 34.6100), - (35.4822, 33.9054), - (35.1260, 33.0909), - (35.0984, 33.0805), - (34.9554, 32.8273), - (34.7525, 32.0729), - (34.4881, 31.6055), - (34.5563, 31.5488), - (34.2654, 31.2193), - (33.7733, 30.9674), - (32.9939, 31.0240), - (32.1924, 31.2603), - (31.9604, 30.9336), - (31.6879, 31.4296), - (30.9769, 31.5558), - (30.0950, 31.4734), - (29.6834, 31.1868), - (28.9135, 30.8700), - (28.4504, 31.0257), - (27.4576, 31.3212), - (26.4953, 31.5856), - (25.1648, 31.5691), - (24.9211, 31.8993), - (23.9275, 32.0166), - (23.6091, 32.1872), - (23.2368, 32.1914), - (22.8957, 32.6385), - (21.5430, 32.8432), - (20.8545, 32.7067), - (20.1339, 32.2381), - (19.8203, 31.7517), - (20.0533, 30.9857), - (19.5740, 30.5258), - (19.0864, 30.2663), - (18.0211, 30.7635), - (16.6116, 31.1821), - (15.7139, 31.3762), - (15.2456, 32.2650), - (13.9186, 32.7119), - (13.0832, 32.8788), - (12.6633, 32.7927), - (11.4887, 33.1369), - (11.1085, 33.2933), - (10.8568, 33.7687), - (10.3396, 33.7857), - (10.1495, 34.3307), - (10.8078, 34.8335), - (10.9395, 35.6989), - (10.5932, 35.9474), - (10.6000, 36.4100), - (11.1000, 36.8999), - (11.0288, 37.0921), - (10.1806, 36.7240), - (10.2100, 37.2300), - (9.5099, 37.3499), - (8.4209, 36.9464), - (7.7370, 36.8857), - (7.3303, 37.1183), - (6.2618, 37.1106), - (5.3201, 36.7165), - (4.8157, 36.8650), - (3.1616, 36.7839), - (1.4669, 36.6056), - (0.5038, 36.3012), - (-0.1274, 35.8886), - (-1.2086, 35.7148), - (-2.1699, 35.1683), - (-2.6043, 35.1790), - (-3.6400, 35.3998), - (-4.5910, 35.3307), - (-5.1938, 35.7551), - (-5.9299, 35.7599), - (-6.2443, 35.1458), - (-6.9125, 34.1104), - (-7.6541, 33.6970), - (-8.6574, 33.2402), - (-9.3006, 32.5646), - (-9.4347, 32.0380), - (-9.8147, 31.1777), - (-9.5648, 29.9335), - (-10.3995, 29.0985), - (-10.9009, 28.8321), - (-11.6889, 28.1486), - (-12.6188, 28.0381), - (-13.1399, 27.6401), - (-13.7738, 26.6188), - (-14.4399, 26.2544), - (-14.8009, 25.6362), - (-14.8246, 25.1035), - (-15.0893, 24.5202), - (-15.4260, 24.3591), - (-15.9826, 23.7233), - (-16.3264, 23.0177), - (-16.2619, 22.6793), - (-16.5891, 22.1582), - (-16.9732, 21.8857), - (-17.0204, 21.4223), - (-17.0634, 20.9997), - (-16.5363, 20.5678), - (-16.2778, 20.0925), - (-16.3776, 19.5938), - (-16.2568, 19.0967), - (-16.1463, 18.1084), - (-16.2705, 17.1669), - (-16.5497, 16.6738), - (-16.4630, 16.1350), - (-16.7007, 15.6215), - (-17.1851, 14.9194), - (-17.6250, 14.7295), - (-17.1261, 14.3735), - (-16.7137, 13.5949), - (-16.8415, 13.1513), - (-16.6774, 12.3848), - (-16.6138, 12.1709), - (-16.3089, 11.9587), - (-16.3147, 11.8065), - (-16.0852, 11.5245), - (-15.6641, 11.4584), - (-15.1303, 11.0404), - (-14.8395, 10.8765), - (-14.6932, 10.6563), - (-14.5796, 10.2144), - (-14.3300, 10.0157), - (-14.0740, 9.8861), - (-13.6851, 9.4947), - (-13.2465, 8.9030), - (-13.1240, 8.1639), - (-12.9490, 7.7986), - (-12.4280, 7.2629), - (-11.7081, 6.8600), - (-11.4387, 6.7859), - (-10.7653, 6.1407), - (-9.9134, 5.5935), - (-9.0047, 4.8324), - (-7.9741, 4.3557), - (-7.7121, 4.3645), - (-7.5189, 4.3382), - (-6.5287, 4.7050), - (-5.8344, 4.9937), - (-4.6499, 5.1682), - (-4.0088, 5.1798), - (-3.3110, 4.9842), - (-2.8561, 4.9944), - (-1.9647, 4.7104), - (-1.0636, 5.0005), - (-0.5076, 5.3434), - (1.0601, 5.9288), - (1.8652, 6.1421), - (2.6917, 6.2588), - (3.5741, 6.2583), - (4.3256, 6.2706), - (5.0335, 5.6118), - (5.3628, 4.8879), - (5.8981, 4.2624), - (6.6980, 4.2405), - (7.0825, 4.4646), - (7.4621, 4.4121), - (8.5002, 4.7719), - (8.4888, 4.4956), - (8.7449, 4.3522), - (8.9481, 3.9041), - (9.4043, 3.7345), - (9.7951, 3.0734), - (9.6491, 2.2838), - (9.3056, 1.1609), - (9.4928, 1.0101), - (9.2913, 0.2686), - (9.0484, -0.4593), - (8.8300, -0.7790), - (8.7979, -1.1113), - (9.4052, -2.1443), - (10.0661, -2.9694), - (11.0937, -3.9788), - (11.9149, -5.0379), - (12.1823, -5.7899), - (12.3224, -6.1000), - (12.2273, -6.2944), - (12.7282, -6.9271), - (12.9330, -7.5965), - (13.2364, -8.5626), - (12.9290, -8.9590), - (12.8753, -9.1669), - (13.1209, -9.7668), - (13.3873, -10.3735), - (13.6863, -10.7310), - (13.7387, -11.2978), - (13.6337, -12.0386), - (13.3129, -12.4836), - (12.7384, -13.1379), - (12.5000, -13.5476), - (12.1756, -14.4491), - (12.1235, -14.8783), - (11.7785, -15.7938), - (11.6400, -16.6731), - (11.7341, -17.3018), - (11.7949, -18.0691), - (12.6085, -19.0453), - (12.8268, -19.6731), - (13.3524, -20.8728), - (13.8686, -21.6990), - (14.2577, -22.1112), - (14.3857, -22.6566), - (14.4081, -23.8530), - (14.7432, -25.3929), - (14.9897, -26.1173), - (15.2104, -27.0909), - (15.6018, -27.8212), - (16.3449, -28.5767), - (17.0629, -29.8759), - (17.0644, -29.8786), - (17.5669, -30.7257), - (18.2217, -31.6616), - (18.2479, -32.4291), - (17.9251, -32.6112), - (18.2500, -33.2814), - (18.2444, -33.8677), - (18.3774, -34.1365), - (18.4246, -33.9978), - (18.8553, -34.4443), - (19.1932, -34.4625), - (19.6164, -34.8191), - (20.0712, -34.7951), - (20.6890, -34.4171), - (21.5427, -34.2588), - (22.5741, -33.8640), - (22.9881, -33.9164), - (23.5940, -33.7944), - (24.6778, -33.9871), - (25.1728, -33.7968), - (25.7806, -33.9446), - (25.9096, -33.6670), - (26.4194, -33.6149), - (27.4646, -33.2269), - (28.2197, -32.7719), - (28.9255, -32.1720), - (30.0557, -31.1402), - (30.6228, -30.4237), - (30.9017, -29.9099), - (31.3255, -29.4019), - (31.5210, -29.2573), - (32.2033, -28.7524), - (32.4621, -28.3010), - (32.5802, -27.4701), - (32.8301, -26.7421), - (32.9159, -26.2158), - (32.6603, -26.1485), - (32.5746, -25.7273), - (33.0132, -25.3575), - (34.2158, -24.8163), - (35.0407, -24.4783), - (35.4587, -24.1226), - (35.6074, -23.7065), - (35.3717, -23.5353), - (35.5339, -23.0707), - (35.5625, -22.09), - (35.3858, -22.14), - (35.3734, -21.8408), - (35.1761, -21.2543), - (34.7018, -20.4970), - (34.7863, -19.7840), - (35.1983, -19.5528), - (35.8964, -18.8422), - (36.2812, -18.6596), - (37.4111, -17.5863), - (38.5383, -17.1010), - (39.4525, -16.7208), - (40.0892, -16.1007), - (40.4772, -15.4062), - (40.7754, -14.6917), - (40.5996, -14.2019), - (40.5608, -12.6391), - (40.4372, -11.7617), - (40.4783, -10.7654), - (40.3165, -10.3170), - (39.9495, -10.0984), - (39.5357, -9.1123), - (39.1865, -8.4855), - (39.2520, -8.0078), - (39.1946, -7.7039), - (39.4699, -7.0999), - (39.4400, -6.8399), - (38.7997, -6.4756), - (38.7405, -5.9089), - (39.2022, -4.6767), - (39.6049, -4.3465), - (39.8000, -3.6811), - (40.1211, -3.2776), - (40.2630, -2.5730), - (40.6378, -2.4997), - (40.8847, -2.0825), - (41.5851, -1.6832), - (41.8109, -1.4464), - (42.0415, -0.9191), - (43.1359, 0.2921), - (44.0681, 1.0528), - (45.5639, 2.0457), - (46.5647, 2.8552), - (47.7407, 4.2194), - (48.5945, 5.3391), - (49.4527, 6.8046), - (50.0709, 8.0817), - (50.5523, 9.1987), - (50.8341, 10.2797), - (51.0452, 10.6409), - (51.0415, 11.1665), - (51.1338, 11.7481), - (51.1112, 12.0246), - (50.7320, 12.0219), - (50.2587, 11.6795), - (49.7286, 11.5789), - (49.2677, 11.4303), - (48.9482, 11.4106), - (48.3787, 11.3754), - (48.0215, 11.1930), - (47.5256, 11.1272), - (46.6454, 10.8165), - (45.5569, 10.6980), - (44.6142, 10.4422), - (44.1178, 10.4455), - (43.6666, 10.8641), - (43.4706, 11.2777), - (43.1453, 11.4620), - (42.7158, 11.7356), - (43.2863, 11.9749), - (43.3178, 12.3901), - (43.0812, 12.6996), - (42.5895, 13.0004), - (42.2768, 13.3439), - (41.7349, 13.9210), - (41.1792, 14.4910), - (39.8142, 15.4356), - (39.2661, 15.9227), - (38.9906, 16.8406), - (38.4100, 17.9983), - (37.8627, 18.3678), - (37.4817, 18.6140), - (37.1147, 19.8079), - (36.9694, 20.8374), - (37.1887, 21.0188), - (36.86623, 22.0), - (36.6907, 22.2048), - (35.5259, 23.1024), - (35.4937, 23.7523), - (35.6924, 23.9267), - (34.7950, 25.0337), - (34.4738, 25.5985), - (34.1045, 26.1422), - (33.3487, 27.6998), - (32.7348, 28.7052), - (32.3204, 29.7604), - (32.4232, 29.8510), - (33.1367, 28.4176), - (33.5881, 27.9713), - (33.9213, 27.6487), - (34.1545, 27.8233), - (34.4265, 28.3439), - (34.6417, 29.0994), - (34.9226, 29.5013), - (34.9560, 29.3565), - (34.8322, 28.9574), - (34.7877, 28.6074), - (34.6323, 28.0585), - (35.1301, 28.0633), - (35.6401, 27.3765), - (36.2491, 26.5701), - (36.6396, 25.8262), - (36.9316, 25.6029), - (37.2094, 25.0845), - (37.1548, 24.8584), - (37.4836, 24.2854), - (38.0238, 24.0786), - (38.4927, 23.6884), - (39.0663, 22.5796), - (39.0236, 21.9868), - (39.1393, 21.2919), - (39.8016, 20.3388), - (40.2476, 20.1746), - (40.9393, 19.4864), - (41.2213, 18.6715), - (41.7543, 17.8330), - (42.2708, 17.4747), - (42.3479, 17.0758), - (42.6495, 16.7746), - (42.7793, 16.3478), - (42.8236, 15.9117), - (42.7024, 15.7188), - (42.8050, 15.2619), - (42.6048, 15.2133), - (42.8922, 14.8022), - (43.0879, 14.0626), - (43.2514, 13.7675), - (43.2228, 13.2209), - (43.4829, 12.6368), - (44.1751, 12.5859), - (44.4945, 12.7216), - (44.9895, 12.6995), - (45.1443, 12.9539), - (45.4064, 13.0269), - (45.6250, 13.2909), - (45.8775, 13.3477), - (46.7170, 13.3996), - (47.3544, 13.5922), - (47.9389, 14.0072), - (48.2389, 13.9480), - (48.6792, 14.0032), - (49.5745, 14.7087), - (51.1725, 15.1752), - (52.1681, 15.5974), - (52.1917, 15.9384), - (52.3852, 16.3824), - (53.1085, 16.6510), - (53.5705, 16.7076), - (54.2392, 17.0449), - (54.7910, 16.9506), - (55.2749, 17.2283), - (55.2699, 17.6323), - (55.6614, 17.8841), - (56.2835, 17.8760), - (56.5121, 18.0871), - (56.6096, 18.5742), - (57.2342, 18.9479), - (57.6943, 18.9447), - (57.7887, 19.0675), - (57.6657, 19.7360), - (57.8263, 20.2430), - (58.0343, 20.4814), - (58.4879, 20.4289), - (58.8611, 21.1140), - (59.2824, 21.4338), - (59.4421, 21.7145), - (59.8061, 22.3105), - (59.8080, 22.5336), - (59.4500, 22.6602), - (59.1805, 22.9923), - (58.7292, 23.5656), - (58.1369, 23.7479), - (57.4034, 23.8785), - (56.8451, 24.2416), - (56.3968, 24.9247), - (56.2610, 25.7146), - (56.3914, 25.8959), - (56.4856, 26.3091), - (56.3620, 26.3959), - (56.0708, 26.0554), - (55.4390, 25.4391), - (54.6930, 24.7978), - (54.0080, 24.1217), - (53.4040, 24.1513), - (52.5770, 24.1774), - (51.7943, 24.0198), - (51.7574, 24.2940), - (51.5795, 24.2454), - (51.3896, 24.6273), - (51.6067, 25.2156), - (51.5890, 25.8011), - (51.2864, 26.1145), - (51.0133, 26.0069), - (50.7439, 25.4824), - (50.8101, 24.7547), - (50.6605, 24.9998), - (50.5273, 25.3278), - (50.2398, 25.6080), - (50.1133, 25.9439), - (50.2129, 26.2770), - (50.1524, 26.6896), - (49.4709, 27.1099), - (49.2995, 27.4612), - (48.8075, 27.6896), - (48.4160, 28.5520), - (48.0939, 29.3062), - (48.1831, 29.5344), - (47.9745, 29.9758), - (48.5679, 29.9267), - (48.9413, 30.3170), - (49.5768, 29.9857), - (50.1150, 30.1477), - (50.8529, 28.8145), - (51.5207, 27.8656), - (52.4835, 27.5808), - (53.4930, 26.8123), - (54.7150, 26.4806), - (55.7237, 26.9646), - (56.4921, 27.1433), - (56.9707, 26.9661), - (57.3972, 25.7399), - (58.5257, 25.6099), - (59.6161, 25.3801), - (61.4973, 25.0782), - (62.9057, 25.2184), - (64.5304, 25.2370), - (66.3728, 25.4251), - (67.1454, 24.6636), - (67.4436, 23.9448), - (68.1766, 23.6919), - (69.3495, 22.8431), - (69.6449, 22.4507), - (69.1641, 22.0892), - (70.4704, 20.8773), - (71.1752, 20.7574), - (72.6305, 21.3560), - (72.8244, 20.4195), - (72.8209, 19.2082), - (73.1199, 17.9285), - (73.5341, 15.9906), - (74.4438, 14.6172), - (74.6167, 13.9925), - (74.8648, 12.7419), - (75.3961, 11.7812), - (75.7464, 11.3082), - (76.1300, 10.2996), - (76.5929, 8.8992), - (77.5398, 7.9655), - (77.9411, 8.2529), - (78.2779, 8.9330), - (79.1897, 9.2165), - (78.8853, 9.5461), - (79.3405, 10.3088), - (79.8579, 10.3572), - (79.8625, 12.0562), - (80.2862, 13.0062), - (80.2332, 13.8357), - (80.0250, 15.1364), - (80.3248, 15.8991), - (80.7919, 15.9519), - (81.6927, 16.3102), - (82.1912, 16.5566), - (82.1927, 17.0166), - (83.1892, 17.6712), - (83.9410, 18.3020), - (85.0602, 19.4785), - (86.4993, 20.1516), - (87.0331, 20.7433), - (86.9757, 21.4955), - (88.2084, 21.7031), - (88.8887, 21.6905), - (89.0319, 22.0557), - (89.4188, 21.9661), - (89.7020, 21.8571), - (89.8474, 22.0391), - (90.2729, 21.8363), - (90.5869, 22.3927), - (90.4960, 22.8050), - (91.4170, 22.7650), - (91.8348, 22.1829), - (92.0252, 21.7015), - (92.0828, 21.1921), - (92.3685, 20.6708), - (93.0782, 19.8551), - (93.6632, 19.7269), - (93.5409, 19.3664), - (94.3248, 18.2135), - (94.5334, 17.2772), - (94.1888, 16.0379), - (94.8084, 15.8034), - (95.3693, 15.7143), - (96.5057, 16.4272), - (97.1645, 16.9287), - (97.5970, 16.1005), - (97.7777, 14.8372), - (98.1036, 13.6404), - (98.5095, 13.1223), - (98.4283, 12.0329), - (98.7645, 11.4412), - (98.4571, 10.6752), - (98.5535, 9.9329), - (98.2591, 8.9739), - (98.1500, 8.3500), - (98.3396, 7.7945), - (98.5037, 8.3823), - (98.9882, 7.9079), - (99.5196, 7.3434), - (99.6906, 6.8482), - (100.0857, 6.4644), - (100.3062, 6.0405), - (100.1967, 5.3124), - (100.5574, 4.7672), - (100.6954, 3.9391), - (101.2735, 3.2702), - (101.3906, 2.7608), - (102.5736, 1.9671), - (103.5197, 1.2263), - (104.2288, 1.2930), - (104.2479, 1.6311), - (103.8546, 2.5154), - (103.5024, 2.7910), - (103.4294, 3.3828), - (103.3321, 3.7266), - (103.4385, 4.1816), - (103.3812, 4.8550), - (102.9617, 5.5244), - (102.3711, 6.1282), - (102.1411, 6.2216), - (101.6230, 6.7406), - (101.0173, 6.8568), - (100.4592, 7.4295), - (100.2796, 8.2951), - (99.8738, 9.2078), - (99.2223, 9.2392), - (99.1537, 9.9630), - (99.4789, 10.8463), - (100.0187, 12.3070), - (100.0977, 13.4068), - (100.9784, 13.4127), - (100.8318, 12.6270), - (101.6871, 12.6457), - (102.5849, 12.1865), - (103.0906, 11.1536), - (103.4972, 10.6325), - (104.3343, 10.4865), - (105.0762, 9.9184), - (104.7951, 9.2410), - (105.1582, 8.5997), - (106.4051, 9.5308), - (107.2209, 10.3644), - (108.3661, 11.0083), - (109.2001, 11.6668), - (109.3352, 13.4260), - (108.8771, 15.2766), - (108.2694, 16.0797), - (107.3619, 16.6974), - (106.4268, 18.0041), - (105.6620, 19.0581), - (105.8816, 19.7520), - (106.7150, 20.6968), - (108.0501, 21.5523), - (108.5228, 21.7152), - (109.8644, 21.3950), - (109.6276, 21.0082), - (109.8898, 20.2824), - (110.4440, 20.3410), - (110.5093, 20.5654), - (110.7854, 21.3971), - (111.8435, 21.5504), - (113.2410, 22.0513), - (113.8067, 22.5483), - (114.1525, 22.2237), - (114.7638, 22.6680), - (115.8907, 22.7828), - (117.2816, 23.6245), - (118.6568, 24.5473), - (119.5854, 25.7407), - (120.3954, 27.0532), - (121.1256, 28.1356), - (121.6844, 28.2255), - (121.9384, 29.0180), - (122.0921, 29.8325), - (121.5035, 30.1429), - (121.2642, 30.6762), - (121.8919, 30.9493), - (121.9081, 31.6921), - (121.2290, 32.4603), - (120.6203, 33.3767), - (120.2275, 34.3603), - (119.1512, 34.9098), - (119.6645, 35.6097), - (120.6370, 36.1114), - (121.1041, 36.6513), - (122.5199, 36.9306), - (122.3579, 37.4544), - (121.7112, 37.4811), - (120.8234, 37.8704), - (119.7028, 37.1563), - (118.9116, 37.4484), - (118.8781, 37.8973), - (118.0596, 38.0614), - (117.5327, 38.7376), - (118.0427, 39.2042), - (119.0234, 39.2523), - (119.6396, 39.8980), - (120.7686, 40.5933), - (121.6403, 40.9463), - (122.1685, 40.4224), - (121.3767, 39.7502), - (121.5859, 39.3608), - (121.0545, 38.8974), - (122.1313, 39.1704), - (122.8675, 39.6377), - (124.2656, 39.9284), - (124.7374, 39.6603), - (125.3211, 39.5513), - (125.3865, 39.3879), - (125.1328, 38.8485), - (125.2219, 38.6658), - (124.9859, 38.5484), - (124.7121, 38.1083), - (124.9810, 37.9488), - (125.2400, 37.8572), - (125.2753, 37.6690), - (125.5684, 37.7520), - (125.6891, 37.9400), - (126.1747, 37.7496), - (126.8601, 36.8939), - (126.1173, 36.7254), - (126.5592, 35.6845), - (126.3739, 34.9345), - (126.4857, 34.3900), - (127.3865, 34.4756), - (128.1858, 34.8903), - (129.0913, 35.0824), - (129.4683, 35.6321), - (129.4604, 36.7841), - (129.2129, 37.4323), - (128.3497, 38.6122), - (127.7833, 39.0508), - (127.3854, 39.2134), - (127.5021, 39.3239), - (127.5334, 39.7568), - (127.9674, 40.0254), - (128.6333, 40.1898), - (129.0103, 40.4854), - (129.1881, 40.6618), - (129.7051, 40.8828), - (129.6673, 41.6011), - (129.9659, 41.9413), - (130.4000, 42.2800), - (130.7800, 42.2200), - (130.9358, 42.5527), - (132.2780, 43.2845), - (132.9062, 42.7984), - (133.5368, 42.8114), - (134.8694, 43.3982), - (135.5153, 43.9889), - (136.8623, 45.1434), - (138.2197, 46.3079), - (138.5547, 46.9996), - (140.0619, 48.4467), - (140.5130, 50.0455), - (140.5974, 51.2396), - (141.3792, 52.2387), - (141.3453, 53.0895), - (139.9015, 54.1896), - (138.8046, 54.2545), - (138.1647, 53.7550), - (137.1934, 53.9773), - (136.7017, 54.6035), - (135.1261, 54.7295), - (138.9584, 57.0880), - (142.1978, 59.0399), - (145.4872, 59.3363), - (148.5448, 59.1644), - (149.7837, 59.6557), - (151.3381, 59.5039), - (151.2657, 58.7808), - (152.8118, 58.8838), - (155.0437, 59.1449), - (154.2180, 59.7581), - (156.7206, 61.4344), - (159.3023, 61.7739), - (160.1214, 60.5442), - (162.6579, 61.6424), - (163.2583, 62.4662), - (164.4735, 62.5506), - (163.6696, 61.1408), - (161.87204, 60.343), - (160.1506, 59.3147), - (158.3643, 58.0557), - (156.8103, 57.8320), - (156.7581, 57.3647), - (155.9144, 56.7679), - (155.4336, 55.3810), - (155.9918, 53.1589), - (156.42, 51.7), - (156.7897, 51.0110), - (158.2311, 51.9426), - (158.5309, 52.9586), - (160.0217, 53.2025), - (160.3687, 54.3443), - (162.1174, 54.8551), - (161.7014, 55.2856), - (162.1263, 56.1158), - (163.0579, 56.1592), - (163.1919, 57.6150), - (162.0529, 57.8391), - (162.0173, 58.2432), - (163.2171, 59.2110), - (163.5392, 59.8686), - (164.8767, 59.7316), - (165.84, 60.16), - (166.2949, 59.7885), - (168.9004, 60.5735), - (170.3308, 59.8817), - (170.6985, 60.3361), - (172.15, 60.95), - (173.6801, 61.6526), - (174.5692, 61.7691), - (177.3643, 62.5219), - (179.2282, 62.3041), - (179.4863, 62.5689), - (179.3703, 62.9826), - (178.9082, 63.2519), - (178.313, 64.07593), - (177.4112, 64.6082), - (178.7072, 64.5349), - (180.0, 64.9797), - (-177.5500, 68.1999), - (-179.9999, 68.9636), - (-179.9999, -16.0671), - (-179.7933, -16.0208), - (-179.9173, -16.5017), - (-179.9999, -16.5552), - (125.9470, -8.4320), - (126.6447, -8.3982), - (126.9572, -8.2733), - (127.3359, -8.3973), - (126.9679, -8.6682), - (125.9258, -9.1060), - (125.0885, -9.3931), - (124.4359, -10.1400), - (123.5799, -10.3599), - (123.4599, -10.2399), - (123.5500, -9.9000), - (123.9800, -9.2900), - (124.9686, -8.8927), - (125.0862, -8.6568), - (125.9470, -8.4320), - (-180.0, 68.9636), - (-177.5500, 68.1999), - (-174.9282, 67.2058), - (-175.0142, 66.5843), - (-174.3398, 66.3355), - (-174.5718, 67.0621), - (-171.8573, 66.9130), - (-169.8995, 65.9772), - (-170.8910, 65.5413), - (-172.5302, 65.4379), - (-172.555, 64.46079), - (-172.9553, 64.2526), - (-173.8918, 64.2826), - (-174.6539, 64.6312), - (-175.9835, 64.9228), - (-176.2071, 65.3566), - (-177.2226, 65.5202), - (-178.3599, 65.3905), - (-178.9033, 65.7404), - (-178.6861, 66.1121), - (-179.8837, 65.8745), - (-179.4326, 65.4041), - (-180.0, 64.9797), - (-180.0, 71.5157), - (-179.8718, 71.5576), - (-179.0243, 71.5555), - (-177.5779, 71.2694), - (-177.6635, 71.1327), - (-178.6937, 70.8930), - (-180.0, 70.8321), - (180.0, 70.8321), - (178.9034, 70.7811), - (178.7253, 71.0988), - (180.0, 71.5157), - (180.0, -16.5552), - (179.3641, -16.8013), - (178.7250, -17.0120), - (178.5968, -16.6391), - (179.0966, -16.4339), - (179.4135, -16.3790), - (180.0, -16.0671), - (-61.2, -51.85), - (-60.0, -51.25), - (-59.15, -51.5), - (-58.55, -51.1), - (-57.75, -51.55), - (-58.05, -51.9), - (-59.4, -52.2), - (-59.85, -51.85), - (-60.7, -52.3), - (-61.2, -51.85), - (68.935, -48.625), - (69.58, -48.94), - (70.525, -49.065), - (70.56, -49.255), - (70.28, -49.71), - (68.745, -49.775), - (68.72, -49.2425), - (68.8675, -48.83), - (68.935, -48.625), - (178.1255, -17.5048), - (178.3736, -17.3399), - (178.7180, -17.6284), - (178.5527, -18.1505), - (177.9326, -18.2879), - (177.3814, -18.1643), - (177.2850, -17.7246), - (177.6708, -17.3811), - (178.1255, -17.5048), - (-61.68, 10.76), - (-61.105, 10.89), - (-60.895, 10.855), - (-60.935, 10.11), - (-61.77, 10.0), - (-61.95, 10.09), - (-61.66, 10.365), - (-61.68, 10.76), - (-155.4021, 20.0797), - (-155.2245, 19.9930), - (-155.0622, 19.8591), - (-154.8074, 19.5087), - (-154.8314, 19.4532), - (-155.2221, 19.2397), - (-155.5421, 19.0834), - (-155.6881, 18.9161), - (-155.9366, 19.0593), - (-155.9080, 19.3388), - (-156.0734, 19.7029), - (-156.0236, 19.8142), - (-155.8500, 19.9772), - (-155.9190, 20.1739), - (-155.8610, 20.2672), - (-155.7850, 20.2487), - (-155.4021, 20.0797), - (-155.9956, 20.7640), - (-156.0792, 20.6439), - (-156.4144, 20.5724), - (-156.58673, 20.783), - (-156.7016, 20.8643), - (-156.7105, 20.9267), - (-156.6125, 21.0124), - (-156.2571, 20.9174), - (-155.9956, 20.7640), - (-156.7582, 21.1768), - (-156.7893, 21.0687), - (-157.3252, 21.0977), - (-157.2502, 21.2195), - (-156.7582, 21.1768), - (-158.0252, 21.7169), - (-157.9416, 21.6527), - (-157.6528, 21.3221), - (-157.7070, 21.2644), - (-157.7786, 21.2772), - (-158.1266, 21.3124), - (-158.2538, 21.5391), - (-158.2926, 21.5791), - (-158.0252, 21.7169), - (-159.3656, 22.2149), - (-159.34512, 21.982), - (-159.4637, 21.8829), - (-159.8005, 22.0653), - (-159.7487, 22.1382), - (-159.5962, 22.2361), - (-159.3656, 22.2149), - (-78.1908, 25.2103), - (-77.89, 25.17), - (-77.54, 24.34), - (-77.5346, 23.7597), - (-77.78, 23.71), - (-78.0340, 24.2861), - (-78.4084, 24.5756), - (-78.1908, 25.2103), - (-78.98, 26.79), - (-78.51, 26.87), - (-77.85, 26.84), - (-77.82, 26.58), - (-78.91, 26.42), - (-78.98, 26.79), - (-77.79, 27.04), - (-77.0, 26.59), - (-77.1725, 25.8791), - (-77.3564, 26.0073), - (-77.34, 26.53), - (-77.7880, 26.9251), - (-77.79, 27.04), - (-64.0148, 47.0360), - (-63.6645, 46.5500), - (-62.9393, 46.4158), - (-62.0120, 46.4431), - (-62.5039, 46.0333), - (-62.8743, 45.9681), - (-64.1428, 46.3926), - (-64.3926, 46.7274), - (-64.0148, 47.0360), - (46.6820, 44.6092), - (47.6759, 45.6414), - (48.6454, 45.8062), - (49.1011, 46.3993), - (50.0340, 46.6089), - (51.1919, 47.0487), - (52.0420, 46.8046), - (53.0427, 46.8530), - (53.2208, 46.2346), - (53.0408, 45.2590), - (52.1673, 45.4083), - (51.3168, 45.2459), - (51.2785, 44.5148), - (50.3056, 44.6098), - (50.3391, 44.2840), - (50.8912, 44.0310), - (51.3424, 43.1329), - (52.5014, 42.7922), - (52.6921, 42.4438), - (52.4463, 42.0271), - (52.5024, 41.7833), - (52.8146, 41.1353), - (52.9167, 41.8681), - (53.7217, 42.1231), - (54.0083, 41.5512), - (54.7368, 40.9510), - (53.8581, 40.6310), - (52.9152, 40.8765), - (52.6939, 40.0336), - (53.3578, 39.9752), - (53.1010, 39.2905), - (53.8809, 38.9520), - (53.7355, 37.9061), - (53.9215, 37.1989), - (53.8257, 36.9650), - (52.2640, 36.7004), - (50.8423, 36.8728), - (50.1477, 37.3745), - (49.1996, 37.5828), - (48.8832, 38.3202), - (48.8565, 38.8154), - (49.2232, 39.0492), - (49.3952, 39.3994), - (49.5692, 40.1761), - (50.3928, 40.2565), - (50.0848, 40.5261), - (49.6189, 40.5729), - (49.1102, 41.2822), - (48.5843, 41.8088), - (47.4925, 42.9865), - (47.5909, 43.6601), - (46.6820, 44.6092), - (-64.5191, 49.8730), - (-64.1732, 49.9571), - (-62.8582, 49.7064), - (-61.8355, 49.2885), - (-61.8063, 49.1050), - (-62.2931, 49.0871), - (-63.5892, 49.4006), - (-64.5191, 49.8730), - (-80.3153, 62.0855), - (-79.9293, 62.3856), - (-79.5200, 62.3637), - (-79.2658, 62.1586), - (-79.6575, 61.6330), - (-80.0995, 61.7181), - (-80.3621, 62.0164), - (-80.3153, 62.0855), - (-83.9936, 62.4528), - (-83.2504, 62.9140), - (-81.8769, 62.9045), - (-81.8982, 62.7108), - (-83.0685, 62.1592), - (-83.7746, 62.1823), - (-83.9936, 62.4528), - (-75.2159, 67.4442), - (-75.8658, 67.1488), - (-76.9868, 67.0987), - (-77.2364, 67.5880), - (-76.8116, 68.1485), - (-75.8952, 68.2872), - (-75.1145, 68.0103), - (-75.1033, 67.5820), - (-75.2159, 67.4442), - (-96.5574, 69.6800), - (-95.6476, 69.1076), - (-96.2695, 68.7570), - (-97.6174, 69.0600), - (-98.4318, 68.9507), - (-99.7974, 69.4000), - (-98.9174, 69.7100), - (-98.2182, 70.1435), - (-97.1574, 69.8600), - (-96.5574, 69.6800), - (-106.5225, 73.0760), - (-105.4024, 72.6725), - (-104.7748, 71.6984), - (-104.4647, 70.9929), - (-102.7853, 70.4977), - (-100.9807, 70.0243), - (-101.0893, 69.5844), - (-102.7311, 69.5040), - (-102.0932, 69.1196), - (-102.4302, 68.7528), - (-104.24, 68.91), - (-105.96, 69.18), - (-107.1225, 69.1192), - (-109.0, 68.78), - (-111.5341, 68.6300), - (-113.3132, 68.5355), - (-113.8549, 69.0074), - (-115.22, 69.28), - (-116.1079, 69.1682), - (-117.34, 69.96), - (-116.6747, 70.0665), - (-115.1311, 70.2373), - (-113.7213, 70.1923), - (-112.4161, 70.3663), - (-114.3499, 70.6000), - (-116.4868, 70.5204), - (-117.9048, 70.5405), - (-118.4323, 70.9092), - (-116.1131, 71.3091), - (-117.6556, 71.2951), - (-119.4019, 71.5585), - (-118.5626, 72.3078), - (-117.8664, 72.7059), - (-115.1890, 73.3145), - (-114.1671, 73.1214), - (-114.6663, 72.6527), - (-112.4410, 72.9553), - (-111.0503, 72.4504), - (-109.9203, 72.9611), - (-109.0065, 72.6333), - (-108.1883, 71.6508), - (-107.6859, 72.0654), - (-108.3964, 73.0895), - (-107.5164, 73.2359), - (-106.5225, 73.0760), - (-79.7758, 72.8029), - (-80.8760, 73.3331), - (-80.8338, 73.6931), - (-80.3530, 73.7597), - (-78.0644, 73.6519), - (-76.34, 73.1026), - (-76.2514, 72.8263), - (-77.3144, 72.8555), - (-78.3916, 72.8766), - (-79.4862, 72.7422), - (-79.7758, 72.8029), - (139.8631, 73.3698), - (140.8117, 73.7650), - (142.0620, 73.8575), - (143.4828, 73.4752), - (143.6038, 73.2124), - (142.0876, 73.2054), - (140.0381, 73.3169), - (139.8631, 73.3698), - (148.2222, 75.3458), - (150.7316, 75.0840), - (149.5759, 74.6889), - (147.9774, 74.7783), - (146.1191, 75.1729), - (146.3584, 75.4968), - (148.2222, 75.3458), - (138.8310, 76.1367), - (141.4716, 76.0928), - (145.0862, 75.5626), - (144.3, 74.82), - (140.6138, 74.8476), - (138.9554, 74.6114), - (136.9743, 75.2616), - (137.5117, 75.9491), - (138.8310, 76.1367), - (-98.5770, 76.5886), - (-98.5, 76.72), - (-97.7355, 76.2565), - (-97.7044, 75.7434), - (-98.16, 75.0), - (-99.8087, 74.8974), - (-100.8836, 75.0573), - (-100.8629, 75.6407), - (-102.5020, 75.5638), - (-102.5655, 76.3365), - (-101.4897, 76.3053), - (-99.9834, 76.6463), - (-98.5770, 76.5886), - (102.8378, 79.2812), - (105.3724, 78.7133), - (105.0754, 78.3068), - (99.43814, 77.921), - (101.2649, 79.2339), - (102.0863, 79.3464), - (102.8378, 79.2812), - (93.7776, 81.0246), - (95.9408, 81.2504), - (97.8838, 80.7469), - (100.1866, 79.7801), - (99.9397, 78.8809), - (97.7579, 78.7562), - (94.9725, 79.0447), - (93.3128, 79.4265), - (92.5454, 80.1437), - (91.1810, 80.3414), - (93.7776, 81.0246), - (-96.0164, 80.6023), - (-95.3234, 80.9072), - (-94.2984, 80.9772), - (-94.7354, 81.2064), - (-92.4098, 81.2573), - (-91.1328, 80.7234), - (-87.81, 80.32), - (-87.02, 79.66), - (-85.8143, 79.3369), - (-87.1875, 79.0393), - (-89.0353, 78.2872), - (-90.8043, 78.2153), - (-92.8766, 78.3433), - (-93.9511, 78.7510), - (-93.9357, 79.1137), - (-93.1452, 79.3801), - (-94.9739, 79.3724), - (-96.0761, 79.7050), - (-96.7097, 80.1577), - (-96.0164, 80.6023), - (-91.5870, 81.8942), - (-90.1, 82.085), - (-88.9322, 82.1175), - (-86.9702, 82.2796), - (-85.5, 82.6522), - (-84.2600, 82.6), - (-83.18, 82.32), - (-82.42, 82.86), - (-81.1, 83.02), - (-79.3066, 83.1305), - (-76.25, 83.1720), - (-75.7187, 83.0640), - (-72.8315, 83.2332), - (-70.6657, 83.1697), - (-68.5, 83.1063), - (-65.8273, 83.0280), - (-63.68, 82.9), - (-61.85, 82.6286), - (-61.8938, 82.3616), - (-64.334, 81.92775), - (-66.7534, 81.7252), - (-67.6575, 81.5014), - (-65.4803, 81.5065), - (-67.84, 80.9), - (-69.4697, 80.6168), - (-71.18, 79.8), - (-73.2428, 79.6341), - (-73.88, 79.4301), - (-76.9077, 79.3230), - (-75.5292, 79.1976), - (-76.2204, 79.0190), - (-75.3934, 78.5258), - (-76.3435, 78.1829), - (-77.8885, 77.8999), - (-78.3626, 77.5085), - (-79.7595, 77.2096), - (-79.6196, 76.9833), - (-77.9108, 77.0220), - (-77.8891, 76.7779), - (-80.5612, 76.1781), - (-83.1743, 76.4540), - (-86.1118, 76.2990), - (-87.6, 76.42), - (-89.4906, 76.4723), - (-89.6161, 76.9521), - (-87.7673, 77.1783), - (-88.26, 77.9), - (-87.65, 77.9702), - (-84.9763, 77.5387), - (-86.34, 78.18), - (-87.9619, 78.3718), - (-87.1519, 78.7586), - (-85.3786, 78.9969), - (-85.0949, 79.3454), - (-86.5073, 79.7362), - (-86.9317, 80.2514), - (-84.1984, 80.2083), - (-83.4086, 80.1), - (-81.8482, 80.4644), - (-84.1, 80.58), - (-87.5989, 80.5162), - (-89.3666, 80.8556), - (-90.2, 81.26), - (-91.3678, 81.5531), - (-91.5870, 81.8942), - (-46.7637, 82.6279), - (-43.4064, 83.2251), - (-39.8975, 83.1801), - (-38.6221, 83.5490), - (-35.0878, 83.6451), - (-27.1004, 83.5196), - (-20.8453, 82.7266), - (-22.6918, 82.3416), - (-26.5175, 82.2976), - (-31.9, 82.2), - (-31.3964, 82.0215), - (-27.8566, 82.1317), - (-24.8444, 81.7869), - (-22.9032, 82.0931), - (-22.0717, 81.7344), - (-23.1696, 81.1527), - (-20.6236, 81.5246), - (-15.7681, 81.9124), - (-12.7701, 81.7188), - (-12.2085, 81.2915), - (-16.2853, 80.5800), - (-16.85, 80.35), - (-20.0462, 80.1770), - (-17.7303, 80.1291), - (-18.9, 79.4), - (-19.7049, 78.7512), - (-19.6735, 77.6385), - (-18.4728, 76.9856), - (-20.0350, 76.9443), - (-21.6794, 76.6279), - (-19.8340, 76.0980), - (-19.5989, 75.2483), - (-20.6681, 75.1558), - (-19.3728, 74.2956), - (-21.5942, 74.2238), - (-20.4345, 73.8171), - (-20.7623, 73.4643), - (-22.1722, 73.3095), - (-23.5659, 73.3066), - (-22.3131, 72.6292), - (-22.2995, 72.1840), - (-24.2783, 72.5978), - (-24.7929, 72.3302), - (-23.4429, 72.0801), - (-22.1328, 71.4689), - (-21.7535, 70.6636), - (-23.53603, 70.471), - (-24.3070, 70.8564), - (-25.5434, 71.4309), - (-25.2013, 70.7522), - (-26.3627, 70.2264), - (-23.7274, 70.1840), - (-22.3490, 70.1294), - (-25.0292, 69.2588), - (-27.7473, 68.4704), - (-30.6737, 68.1250), - (-31.7766, 68.1207), - (-32.8110, 67.7354), - (-34.2019, 66.6797), - (-36.3528, 65.9789), - (-37.0437, 65.9376), - (-38.3750, 65.6921), - (-39.8122, 65.4584), - (-40.6689, 64.8399), - (-40.6828, 64.1390), - (-41.1887, 63.4824), - (-42.8193, 62.6823), - (-42.4166, 61.9009), - (-42.8661, 61.0740), - (-43.3784, 60.0977), - (-44.7875, 60.0367), - (-46.2636, 60.8532), - (-48.2629, 60.8584), - (-49.2330, 61.4068), - (-49.9003, 62.3833), - (-51.6332, 63.6269), - (-52.1401, 64.2784), - (-52.2765, 65.1767), - (-53.6616, 66.0995), - (-53.3016, 66.8365), - (-53.9691, 67.1889), - (-52.9804, 68.3575), - (-51.4753, 68.7295), - (-51.0804, 69.1478), - (-50.8712, 69.9291), - (-52.0135, 69.5749), - (-52.5579, 69.4261), - (-53.4562, 69.2836), - (-54.6833, 69.6100), - (-54.7500, 70.2893), - (-54.3588, 70.8213), - (-53.4313, 70.8357), - (-51.3901, 70.5697), - (-53.1093, 71.2048), - (-54.0042, 71.5471), - (-55.0, 71.4065), - (-55.8346, 71.6544), - (-54.7181, 72.5862), - (-55.3263, 72.9586), - (-56.1200, 73.6497), - (-57.3236, 74.7102), - (-58.5967, 75.0986), - (-58.5851, 75.5172), - (-61.2686, 76.1023), - (-63.3916, 76.1752), - (-66.0642, 76.1348), - (-68.5043, 76.0614), - (-69.6648, 76.3797), - (-71.4025, 77.0085), - (-68.7767, 77.3231), - (-66.7639, 77.3759), - (-71.0429, 77.6359), - (-73.297, 78.04419), - (-73.1593, 78.4327), - (-69.3734, 78.9138), - (-65.7107, 79.3943), - (-65.3239, 79.7581), - (-68.0229, 80.1172), - (-67.1512, 80.5158), - (-63.6892, 81.2139), - (-62.2344, 81.3211), - (-62.6511, 81.7704), - (-60.2824, 82.0336), - (-57.2074, 82.1907), - (-54.1344, 82.1996), - (-53.0432, 81.8883), - (-50.3906, 82.4388), - (-48.0038, 82.0648), - (-46.5998, 81.9859), - (-44.523, 81.6607), - (-46.9007, 82.1997), - (-46.7637, 82.6279), - (-106.6, 73.6), - (-105.26, 73.64), - (-104.5, 73.42), - (-105.38, 72.76), - (-106.94, 73.46), - (-106.6, 73.6), - (-180.0, -84.71338), - (-179.9424, -84.7214), - (-179.0586, -84.1394), - (-177.2567, -84.4529), - (-176.0846, -84.0992), - (-175.8298, -84.1179), - (-174.3825, -84.5343), - (-173.1165, -84.1179), - (-172.8891, -84.0610), - (-169.9512, -83.8846), - (-168.9999, -84.1179), - (-168.5301, -84.2373), - (-167.0220, -84.5704), - (-164.1821, -84.8252), - (-161.9297, -85.1387), - (-158.0713, -85.3739), - (-155.1922, -85.0995), - (-150.9420, -85.2955), - (-148.5330, -85.6090), - (-145.8889, -85.3151), - (-143.1077, -85.0407), - (-142.8922, -84.5704), - (-146.8290, -84.5312), - (-150.0607, -84.2961), - (-150.9029, -83.9042), - (-153.5862, -83.6886), - (-153.4099, -83.2380), - (-153.0377, -82.8265), - (-152.6656, -82.4541), - (-152.8615, -82.0426), - (-154.5262, -81.7683), - (-155.2901, -81.4156), - (-156.8374, -81.1021), - (-154.4087, -81.1609), - (-152.0976, -81.0041), - (-150.6482, -81.3373), - (-148.8659, -81.0433), - (-147.2207, -80.6710), - (-146.4177, -80.3379), - (-146.7702, -79.9264), - (-148.0629, -79.6520), - (-149.5319, -79.3582), - (-151.5884, -79.2993), - (-153.3903, -79.1622), - (-155.3293, -79.0642), - (-155.9756, -78.6919), - (-157.2683, -78.3784), - (-158.0517, -78.0256), - (-158.3651, -76.8892), - (-157.8754, -76.9872), - (-156.9745, -77.3007), - (-155.3293, -77.2027), - (-153.7428, -77.0655), - (-152.9202, -77.4966), - (-151.3337, -77.3987), - (-150.0019, -77.1831), - (-148.7484, -76.9088), - (-147.6124, -76.5757), - (-146.1044, -76.4777), - (-146.1435, -76.1054), - (-146.4960, -75.7331), - (-146.2023, -75.3804), - (-144.9096, -75.2040), - (-144.3220, -75.5371), - (-142.7943, -75.3412), - (-141.6387, -75.0864), - (-140.2090, -75.0668), - (-138.8575, -74.9689), - (-137.5062, -74.7337), - (-136.4289, -74.5182), - (-135.2145, -74.3026), - (-134.4311, -74.3614), - (-133.7456, -74.4398), - (-132.2571, -74.3026), - (-130.9253, -74.4790), - (-129.5542, -74.4594), - (-128.2420, -74.3222), - (-126.8906, -74.4202), - (-125.4020, -74.5182), - (-124.0114, -74.4790), - (-122.5621, -74.4986), - (-121.0736, -74.5182), - (-119.7025, -74.4790), - (-118.6841, -74.1850), - (-117.4698, -74.0283), - (-116.2163, -74.2438), - (-115.0215, -74.0675), - (-113.9443, -73.7148), - (-113.2979, -74.0283), - (-112.9454, -74.3810), - (-112.2990, -74.7141), - (-111.2610, -74.4202), - (-110.0663, -74.7925), - (-108.7149, -74.9101), - (-107.5593, -75.1844), - (-106.1491, -75.1256), - (-104.8760, -74.9493), - (-103.3679, -74.9884), - (-102.0165, -75.1256), - (-100.6455, -75.3020), - (-100.1166, -74.8709), - (-100.7630, -74.5378), - (-101.2527, -74.1850), - (-102.5453, -74.1067), - (-103.1133, -73.7344), - (-103.3287, -73.3620), - (-103.6812, -72.6175), - (-102.9174, -72.7546), - (-101.6052, -72.8134), - (-100.3125, -72.7546), - (-99.1373, -72.9114), - (-98.1188, -73.2053), - (-97.6880, -73.5580), - (-96.3365, -73.6168), - (-95.0439, -73.4797), - (-93.6729, -73.2837), - (-92.4390, -73.1661), - (-91.4205, -73.4013), - (-90.0887, -73.3229), - (-89.2269, -72.5587), - (-88.4239, -73.0093), - (-87.2683, -73.1857), - (-86.0148, -73.0877), - (-85.1922, -73.4797), - (-83.8799, -73.5188), - (-82.6656, -73.6364), - (-81.4709, -73.8519), - (-80.6874, -73.4797), - (-80.2957, -73.1269), - (-79.2968, -73.5188), - (-77.9258, -73.4208), - (-76.9073, -73.6364), - (-76.2218, -73.9695), - (-74.8900, -73.8716), - (-73.8520, -73.6560), - (-72.8335, -73.4013), - (-71.6192, -73.2641), - (-70.2090, -73.1465), - (-68.9359, -73.0093), - (-67.9566, -72.7938), - (-67.3690, -72.4803), - (-67.1340, -72.0492), - (-67.2515, -71.6377), - (-67.5649, -71.2458), - (-67.9174, -70.8539), - (-68.2308, -70.4620), - (-68.4854, -70.1093), - (-68.5442, -69.7173), - (-68.4462, -69.3255), - (-67.9762, -68.9532), - (-67.5844, -68.5417), - (-67.4278, -68.1498), - (-67.6236, -67.7187), - (-67.7411, -67.3268), - (-67.2515, -66.8761), - (-66.7031, -66.5822), - (-66.0568, -66.2099), - (-65.3713, -65.8963), - (-64.5682, -65.6025), - (-64.1765, -65.1714), - (-63.6281, -64.8970), - (-63.0013, -64.6423), - (-62.0416, -64.5835), - (-61.4149, -64.2700), - (-60.7098, -64.0740), - (-59.8872, -63.9565), - (-59.1625, -63.7017), - (-58.5945, -63.3882), - (-57.8111, -63.2706), - (-57.2235, -63.5254), - (-57.5957, -63.8585), - (-58.6141, -64.1524), - (-59.0450, -64.3680), - (-59.7893, -64.2112), - (-60.6119, -64.3092), - (-61.2974, -64.5443), - (-62.0221, -64.7990), - (-62.5117, -65.0930), - (-62.6488, -65.4849), - (-62.5901, -65.8572), - (-62.1200, -66.1903), - (-62.8055, -66.4255), - (-63.7456, -66.5038), - (-64.2941, -66.8370), - (-64.8816, -67.1504), - (-65.5084, -67.5816), - (-65.6650, -67.9538), - (-65.3125, -68.3653), - (-64.7837, -68.6789), - (-63.9611, -68.9139), - (-63.1972, -69.2275), - (-62.7859, -69.6194), - (-62.5705, -69.9917), - (-62.2767, -70.3836), - (-61.8066, -70.7167), - (-61.5129, -71.0890), - (-61.3758, -72.0100), - (-61.0819, -72.3823), - (-61.0036, -72.7742), - (-60.6902, -73.1661), - (-60.8273, -73.6952), - (-61.3758, -74.1067), - (-61.9633, -74.4398), - (-63.2952, -74.5769), - (-63.7456, -74.9297), - (-64.3528, -75.2628), - (-65.8609, -75.6351), - (-67.1928, -75.7919), - (-68.4462, -76.0074), - (-69.7977, -76.2229), - (-70.6007, -76.6344), - (-72.2067, -76.6736), - (-73.9695, -76.6344), - (-75.5559, -76.7128), - (-77.2403, -76.7128), - (-76.9269, -77.1048), - (-75.3992, -77.2810), - (-74.2828, -77.5554), - (-73.6561, -77.9081), - (-74.7725, -78.2216), - (-76.4961, -78.1236), - (-77.9258, -78.3784), - (-77.9846, -78.7899), - (-78.0237, -79.1818), - (-76.8486, -79.5149), - (-76.6332, -79.8872), - (-75.3600, -80.2595), - (-73.2448, -80.4163), - (-71.4429, -80.6906), - (-70.0131, -81.0041), - (-68.1916, -81.3176), - (-65.7042, -81.4744), - (-63.2560, -81.7487), - (-61.5520, -82.0426), - (-59.6914, -82.3758), - (-58.7121, -82.8461), - (-58.2224, -83.2184), - (-57.0081, -82.8656), - (-55.3628, -82.5717), - (-53.6197, -82.2582), - (-51.5436, -82.0035), - (-49.7613, -81.7291), - (-47.2739, -81.7095), - (-44.8257, -81.8467), - (-42.8083, -82.0819), - (-42.1620, -81.6508), - (-40.7714, -81.3568), - (-38.2448, -81.3373), - (-36.2666, -81.1217), - (-34.3863, -80.9061), - (-32.3102, -80.7690), - (-30.0970, -80.5926), - (-28.5498, -80.3379), - (-29.2549, -79.9851), - (-29.6858, -79.6325), - (-29.6858, -79.2602), - (-31.6248, -79.2993), - (-33.6813, -79.4561), - (-35.6399, -79.4561), - (-35.9141, -79.0838), - (-35.7770, -78.3392), - (-35.3265, -78.1236), - (-33.8967, -77.8885), - (-32.2123, -77.6534), - (-30.9980, -77.3595), - (-29.7837, -77.0655), - (-28.8827, -76.6736), - (-27.5117, -76.4973), - (-26.1603, -76.3601), - (-25.4748, -76.2818), - (-23.9275, -76.2425), - (-22.4585, -76.1054), - (-21.2246, -75.9094), - (-20.0103, -75.6743), - (-18.9135, -75.4392), - (-17.5229, -75.1256), - (-16.6415, -74.7925), - (-15.7014, -74.4986), - (-15.4077, -74.1067), - (-16.4653, -73.8716), - (-16.1127, -73.4601), - (-15.4468, -73.1465), - (-14.4088, -72.9505), - (-13.3119, -72.7154), - (-12.2935, -72.4019), - (-11.5100, -72.0100), - (-11.0204, -71.5397), - (-10.2957, -71.2654), - (-9.1010, -71.3242), - (-8.6113, -71.6573), - (-7.4166, -71.6965), - (-7.3774, -71.3242), - (-6.8682, -70.9323), - (-5.7909, -71.0302), - (-5.5363, -71.4026), - (-4.3416, -71.4613), - (-3.0489, -71.2850), - (-1.7954, -71.1674), - (-0.6594, -71.2262), - (-0.2286, -71.6377), - (0.8681, -71.3046), - (1.8866, -71.1282), - (3.0226, -70.9911), - (4.1390, -70.8539), - (5.1575, -70.6187), - (6.2739, -70.4620), - (7.1357, -70.2465), - (7.7428, -69.8937), - (8.4871, -70.1485), - (9.5251, -70.0113), - (10.2498, -70.4816), - (10.8178, -70.8343), - (11.9538, -70.6383), - (12.4042, -70.2465), - (13.4227, -69.9721), - (14.7349, -70.0309), - (15.1267, -70.4032), - (15.9493, -70.0309), - (17.0265, -69.9133), - (18.2017, -69.8741), - (19.2593, -69.8937), - (20.3757, -70.0113), - (21.4529, -70.0701), - (21.9230, -70.4032), - (22.5694, -70.6971), - (23.6661, -70.5208), - (24.8413, -70.4816), - (25.9773, -70.4816), - (27.0937, -70.4620), - (28.0925, -70.3248), - (29.1502, -70.2072), - (30.0315, -69.9329), - (30.9717, -69.7566), - (31.9901, -69.6586), - (32.7540, -69.3842), - (33.3024, -68.8356), - (33.8704, -68.5025), - (34.9084, -68.6592), - (35.3002, -69.0120), - (36.1620, -69.2471), - (37.2000, -69.1687), - (37.9051, -69.5214), - (38.6494, -69.7762), - (39.6678, -69.5410), - (40.0204, -69.1099), - (40.9213, -68.9336), - (41.9594, -68.6005), - (42.9387, -68.4633), - (44.1138, -68.2674), - (44.8972, -68.0518), - (45.7199, -67.8167), - (46.5033, -67.6011), - (47.4434, -67.7187), - (48.3444, -67.3660), - (48.9907, -67.0917), - (49.9308, -67.1113), - (50.7534, -66.8761), - (50.9493, -66.5234), - (51.7915, -66.2491), - (52.6141, -66.0531), - (53.6130, -65.8963), - (54.5335, -65.8180), - (55.4149, -65.8768), - (56.3550, -65.9747), - (57.1580, -66.2491), - (57.2559, -66.6802), - (58.1373, -67.0133), - (58.7445, -67.2876), - (59.9393, -67.4052), - (60.6052, -67.6795), - (61.4278, -67.9538), - (62.3874, -68.0126), - (63.1904, -67.8167), - (64.0523, -67.4052), - (64.9924, -67.6207), - (65.9717, -67.7383), - (66.9118, -67.8559), - (67.8911, -67.9343), - (68.8900, -67.9343), - (69.7126, -68.9727), - (69.6734, -69.2275), - (69.5559, -69.6782), - (68.5962, -69.9329), - (67.8127, -70.3052), - (67.9498, -70.6971), - (69.0663, -70.6775), - (68.9291, -71.0694), - (68.4199, -71.4417), - (67.9498, -71.8532), - (68.7137, -72.1668), - (69.8693, -72.2647), - (71.0248, -72.0884), - (71.5732, -71.6965), - (71.9062, -71.3242), - (72.4546, -71.0107), - (73.0814, -70.7167), - (73.3360, -70.3640), - (73.8648, -69.8741), - (74.4915, -69.7762), - (75.6275, -69.7370), - (76.6264, -69.6194), - (77.6449, -69.4626), - (78.1345, -69.0707), - (78.4283, -68.6984), - (79.1138, -68.3262), - (80.0931, -68.0715), - (80.9353, -67.8755), - (81.4837, -67.5423), - (82.0517, -67.3660), - (82.7764, -67.2092), - (83.7753, -67.3072), - (84.6762, -67.2092), - (85.6555, -67.0917), - (86.7523, -67.1504), - (87.4770, -66.8761), - (87.9862, -66.2099), - (88.3584, -66.4842), - (88.8284, -66.9545), - (89.6706, -67.1504), - (90.6303, -67.2288), - (91.5900, -67.1113), - (92.6085, -67.1896), - (93.5486, -67.2092), - (94.1754, -67.1113), - (95.0175, -67.1701), - (95.7814, -67.3856), - (96.6823, -67.2485), - (97.7596, -67.2485), - (98.6802, -67.1113), - (99.7181, -67.2485), - (100.3841, -66.9153), - (100.8933, -66.5822), - (101.5788, -66.3078), - (102.8324, -65.5632), - (103.4786, -65.7004), - (104.2425, -65.9747), - (104.9084, -66.3275), - (106.1815, -66.9349), - (107.1608, -66.9545), - (108.0813, -66.9545), - (109.1586, -66.8370), - (110.2358, -66.6998), - (111.0584, -66.4255), - (111.7439, -66.1315), - (112.8603, -66.0923), - (113.6046, -65.8768), - (114.3880, -66.0727), - (114.8973, -66.3862), - (115.6023, -66.6998), - (116.6991, -66.6606), - (117.3847, -66.9153), - (118.5794, -67.1701), - (119.8329, -67.2680), - (120.8709, -67.1896), - (121.6544, -66.8761), - (122.3203, -66.5626), - (123.2212, -66.4842), - (124.1222, -66.6214), - (125.1602, -66.7193), - (126.1003, -66.5626), - (127.0014, -66.5626), - (127.8827, -66.6606), - (128.8032, -66.7586), - (129.7042, -66.5822), - (130.7814, -66.4255), - (131.7999, -66.3862), - (132.9358, -66.3862), - (133.8564, -66.2883), - (134.7573, -66.2099), - (135.0315, -65.7200), - (135.0707, -65.3085), - (135.6974, -65.5828), - (135.8738, -66.0335), - (136.2067, -66.4450), - (136.6180, -66.7781), - (137.4602, -66.9545), - (138.5962, -66.8957), - (139.9084, -66.8761), - (140.8094, -66.8173), - (142.1216, -66.8173), - (143.0618, -66.7977), - (144.3740, -66.8370), - (145.4904, -66.9153), - (146.1955, -67.2288), - (145.9996, -67.6011), - (146.6460, -67.8951), - (147.7232, -68.1302), - (148.8396, -68.3850), - (150.1323, -68.5612), - (151.4837, -68.7181), - (152.5022, -68.8748), - (153.6381, -68.8945), - (154.2845, -68.5612), - (155.1658, -68.8356), - (155.9297, -69.1492), - (156.8111, -69.3842), - (158.0255, -69.4822), - (159.1810, -69.5998), - (159.6706, -69.9917), - (160.8066, -70.2268), - (161.5704, -70.5796), - (162.6868, -70.7363), - (163.8424, -70.7167), - (164.9196, -70.7755), - (166.1144, -70.7559), - (167.3090, -70.8343), - (168.4256, -70.9714), - (169.4635, -71.2066), - (170.5016, -71.4026), - (171.2067, -71.6965), - (171.0892, -72.0884), - (170.5604, -72.4411), - (170.1099, -72.8918), - (169.7573, -73.2445), - (169.2873, -73.6560), - (167.9751, -73.8128), - (167.3874, -74.1654), - (166.0948, -74.3810), - (165.6443, -74.7729), - (164.9588, -75.1452), - (164.2341, -75.4588), - (163.8227, -75.8703), - (163.5682, -76.2425), - (163.4702, -76.6933), - (163.4898, -77.0655), - (164.0578, -77.4574), - (164.2733, -77.8297), - (164.7434, -78.1825), - (166.6041, -78.3196), - (166.9957, -78.7507), - (165.1938, -78.9074), - (163.6662, -79.1230), - (161.7663, -79.1622), - (160.9241, -79.7304), - (160.7478, -80.2007), - (160.3169, -80.5730), - (159.7882, -80.9453), - (161.1200, -81.2785), - (161.6292, -81.6900), - (162.4909, -82.0622), - (163.7053, -82.3954), - (165.0959, -82.7089), - (166.6041, -83.0224), - (168.8956, -83.3359), - (169.4047, -83.8258), - (172.2839, -84.0414), - (172.4770, -84.1179), - (173.2240, -84.4137), - (175.9856, -84.1589), - (178.2772, -84.4725), - (180.0, -84.71338), -]; - -pub static WORLD_LOW_RESOLUTION: [(f64, f64); 1166] = [ - (-92.32, 48.24), - (-88.13, 48.92), - (-83.11, 46.27), - (-81.66, 44.76), - (-82.09, 42.29), - (-77.10, 44.00), - (-69.95, 46.92), - (-65.92, 45.32), - (-66.37, 44.25), - (-61.22, 45.43), - (-64.94, 47.34), - (-64.12, 48.52), - (-70.68, 47.02), - (-67.24, 49.33), - (-59.82, 50.48), - (-56.14, 52.46), - (-59.07, 53.58), - (-58.26, 54.21), - (-60.69, 55.33), - (-61.97, 57.41), - (-64.35, 59.49), - (-67.29, 58.15), - (-69.89, 59.91), - (-71.31, 61.45), - (-78.22, 61.97), - (-77.28, 59.53), - (-77.09, 55.88), - (-79.06, 51.68), - (-82.23, 52.70), - (-86.75, 55.72), - (-92.17, 56.86), - (-95.61, 58.82), - (-92.66, 62.02), - (-90.65, 63.24), - (-95.96, 64.12), - (-89.88, 63.98), - (-89.30, 65.22), - (-86.86, 66.12), - (-84.54, 66.88), - (-82.30, 67.76), - (-83.10, 69.68), - (-86.05, 67.98), - (-88.18, 68.20), - (-91.00, 68.82), - (-91.72, 69.69), - (-93.15, 71.09), - (-96.58, 71.05), - (-93.35, 69.52), - (-94.23, 68.25), - (-95.96, 66.73), - (-98.83, 68.27), - (-102.45, 67.69), - (-108.34, 68.43), - (-105.83, 68.05), - (-108.15, 66.60), - (-111.15, 67.63), - (-114.10, 68.23), - (-120.92, 69.44), - (-124.32, 69.26), - (-128.76, 70.50), - (-131.86, 69.19), - (-131.15, 69.79), - (-135.81, 69.13), - (-140.19, 69.37), - (-141.20, 69.58), - (-141.21, 69.56), - (-142.49, 69.83), - (-148.09, 70.26), - (-154.37, 70.96), - (-159.53, 70.38), - (-166.64, 68.25), - (-161.56, 66.55), - (-162.99, 65.97), - (-168.23, 65.49), - (-161.12, 64.49), - (-165.29, 62.57), - (-164.58, 60.06), - (-162.06, 58.36), - (-157.85, 58.12), - (-162.34, 55.06), - (-156.52, 57.11), - (-153.53, 59.32), - (-149.18, 60.81), - (-149.90, 59.50), - (-146.54, 60.36), - (-139.98, 59.73), - (-137.12, 58.28), - (-136.01, 59.12), - (-133.84, 57.12), - (-131.46, 55.98), - (-132.08, 57.20), - (-140.37, 60.25), - (-141.21, 60.16), - (-133.38, 58.93), - (-130.88, 54.83), - (-128.86, 53.90), - (-126.58, 52.12), - (-127.08, 50.80), - (-124.42, 49.66), - (-122.56, 48.91), - (-122.44, 48.92), - (-124.42, 47.18), - (-124.52, 42.48), - (-123.09, 38.45), - (-121.73, 36.62), - (-117.60, 33.34), - (-117.28, 32.64), - (-117.29, 32.48), - (-114.75, 27.80), - (-112.53, 24.80), - (-110.55, 24.07), - (-114.23, 29.59), - (-112.58, 29.99), - (-109.57, 25.94), - (-105.61, 21.94), - (-102.09, 17.87), - (-95.75, 15.94), - (-92.21, 14.97), - (-92.22, 14.71), - (-86.74, 12.06), - (-83.03, 8.65), - (-79.93, 8.74), - (-77.00, 7.82), - (-81.99, 8.97), - (-83.92, 12.70), - (-86.33, 15.80), - (-88.40, 15.92), - (-88.45, 17.42), - (-87.01, 21.33), - (-91.65, 18.72), - (-96.96, 20.37), - (-97.65, 25.67), - (-97.62, 25.82), - (-95.62, 28.84), - (-90.77, 29.03), - (-87.33, 30.22), - (-82.69, 28.15), - (-80.16, 26.66), - (-80.74, 32.31), - (-76.89, 35.43), - (-76.47, 38.21), - (-75.66, 37.67), - (-71.31, 41.76), - (-69.44, 44.17), - (-67.69, 47.03), - (-73.18, 45.14), - (-79.26, 43.28), - (-82.84, 42.59), - (-83.49, 45.32), - (-86.36, 43.65), - (-87.75, 43.42), - (-86.01, 45.96), - (-87.00, 46.59), - (-91.39, 46.79), - (-90.05, 47.96), - (-152.62, 58.41), - (-152.60, 58.40), - (-153.30, 57.80), - (-152.40, 57.48), - (-153.32, 57.79), - (-166.96, 53.96), - (-167.01, 53.95), - (-168.36, 53.50), - (-168.19, 53.36), - (-170.73, 52.68), - (-170.60, 52.55), - (-174.47, 51.94), - (-174.47, 51.92), - (-176.58, 51.71), - (-176.64, 51.73), - (-177.55, 51.76), - (-177.41, 51.63), - (-178.27, 51.75), - (177.35, 51.80), - (177.33, 51.76), - (172.44, 53.00), - (172.55, 53.03), - (-123.40, 48.33), - (-128.00, 50.84), - (-123.50, 48.34), - (-132.49, 52.88), - (-132.44, 52.91), - (-132.64, 53.02), - (-131.97, 53.71), - (-132.63, 53.02), - (-55.36, 51.56), - (-54.66, 49.52), - (-53.65, 47.48), - (-52.98, 46.31), - (-56.12, 46.84), - (-58.47, 47.57), - (-57.61, 50.38), - (-55.39, 51.53), - (-61.37, 49.01), - (-61.80, 49.29), - (-61.38, 49.03), - (-63.01, 46.71), - (-64.42, 46.61), - (-63.04, 46.68), - (-60.14, 46.48), - (-60.14, 46.50), - (-71.97, 41.11), - (-71.97, 41.15), - (-80.79, 27.03), - (-81.01, 26.99), - (-113.01, 42.09), - (-113.10, 42.01), - (-155.74, 20.02), - (-155.73, 19.98), - (-156.51, 20.78), - (-156.51, 20.78), - (-157.12, 21.21), - (-157.08, 20.95), - (-157.87, 21.42), - (-159.53, 22.07), - (-117.44, 66.46), - (-119.59, 65.24), - (-123.95, 65.03), - (-123.69, 66.44), - (-119.21, 66.22), - (-117.44, 66.44), - (-120.71, 64.03), - (-114.91, 62.30), - (-109.07, 62.72), - (-112.62, 61.19), - (-118.68, 61.19), - (-117.01, 61.17), - (-115.97, 62.56), - (-119.46, 64.00), - (-120.59, 63.94), - (-112.31, 58.46), - (-108.90, 59.44), - (-104.14, 58.90), - (-102.56, 56.72), - (-101.82, 58.73), - (-104.65, 58.91), - (-111.00, 58.51), - (-112.35, 58.62), - (-98.74, 50.09), - (-99.75, 52.24), - (-99.62, 51.47), - (-98.82, 50.39), - (-97.02, 50.21), - (-97.50, 54.02), - (-98.69, 52.93), - (-97.19, 51.09), - (-96.98, 50.20), - (-95.34, 49.04), - (-92.32, 50.34), - (-94.14, 49.47), - (-95.36, 48.82), - (-80.39, 56.16), - (-79.22, 55.94), - (-80.34, 56.08), - (-103.56, 58.60), - (-103.60, 58.58), - (-101.82, 58.03), - (-102.33, 58.10), - (-101.77, 58.06), - (-101.88, 55.79), - (-97.92, 57.15), - (-101.22, 55.85), - (-101.88, 55.74), - (-77.61, 6.80), - (-78.70, 0.97), - (-80.75, -4.47), - (-76.19, -14.57), - (-70.44, -18.75), - (-70.68, -26.15), - (-71.44, -32.03), - (-73.38, -37.27), - (-73.06, -42.11), - (-73.17, -46.09), - (-73.52, -48.05), - (-73.67, -51.56), - (-71.06, -53.88), - (-69.14, -50.77), - (-67.51, -46.59), - (-63.49, -42.80), - (-62.14, -40.16), - (-57.12, -36.71), - (-53.17, -34.15), - (-51.26, -32.02), - (-48.16, -25.48), - (-40.73, -22.32), - (-38.88, -15.24), - (-34.60, -7.81), - (-41.95, -3.42), - (-48.02, -1.84), - (-48.44, -1.57), - (-50.81, 0.00), - (-54.47, 5.39), - (-60.59, 8.32), - (-64.19, 9.88), - (-70.78, 10.64), - (-70.97, 11.89), - (-76.26, 8.76), - (-77.61, 6.80), - (-69.14, -52.79), - (-66.16, -55.08), - (-70.01, -54.88), - (-70.55, -53.85), - (-59.29, -51.58), - (-59.35, -51.54), - (-58.65, -51.55), - (-58.55, -51.56), - (-84.39, 21.44), - (-73.90, 19.73), - (-79.27, 21.18), - (-83.74, 21.80), - (-84.32, 21.42), - (-66.96, 17.95), - (-67.05, 17.89), - (-77.88, 17.22), - (-78.06, 16.98), - (-74.47, 18.08), - (-69.88, 18.99), - (-71.10, 17.76), - (-74.45, 17.86), - (-85.28, 73.74), - (-85.79, 70.96), - (-85.13, 71.94), - (-84.74, 72.96), - (-80.61, 73.10), - (-78.45, 72.20), - (-75.44, 72.55), - (-73.89, 71.98), - (-72.56, 71.04), - (-71.49, 70.57), - (-69.78, 70.29), - (-68.12, 69.71), - (-65.91, 69.19), - (-66.92, 68.39), - (-64.08, 67.68), - (-62.50, 66.68), - (-63.07, 65.33), - (-66.11, 66.08), - (-67.48, 65.41), - (-64.05, 63.15), - (-66.58, 63.26), - (-69.04, 62.33), - (-72.22, 63.77), - (-76.88, 64.17), - (-73.25, 65.54), - (-70.09, 66.64), - (-72.05, 67.44), - (-76.32, 68.36), - (-78.34, 70.17), - (-82.12, 69.71), - (-87.64, 70.12), - (-89.68, 71.43), - (-85.28, 73.74), - (-80.90, 76.10), - (-84.21, 76.28), - (-88.94, 76.38), - (-85.47, 77.40), - (-85.43, 77.93), - (-87.01, 78.54), - (-83.17, 78.94), - (-84.87, 79.93), - (-81.33, 79.82), - (-76.27, 80.92), - (-82.88, 80.62), - (-82.58, 81.16), - (-86.51, 81.05), - (-89.36, 81.21), - (-90.45, 81.38), - (-89.28, 81.86), - (-87.21, 82.30), - (-80.51, 82.05), - (-80.16, 82.55), - (-77.83, 82.86), - (-75.51, 83.05), - (-71.18, 82.90), - (-65.10, 82.78), - (-63.34, 81.80), - (-68.26, 81.26), - (-69.46, 80.34), - (-71.05, 79.82), - (-74.40, 79.46), - (-75.42, 79.03), - (-75.48, 78.92), - (-76.01, 78.20), - (-80.66, 77.28), - (-78.07, 76.98), - (-80.90, 76.13), - (-92.86, 74.13), - (-92.50, 72.70), - (-94.89, 73.16), - (-92.96, 74.14), - (-94.80, 76.95), - (-89.68, 76.04), - (-88.52, 75.40), - (-82.36, 75.67), - (-79.39, 74.65), - (-86.15, 74.22), - (-91.70, 74.94), - (-95.60, 76.91), - (-94.87, 76.96), - (-99.96, 73.74), - (-97.89, 72.90), - (-98.28, 71.13), - (-102.04, 72.92), - (-101.34, 73.14), - (-99.69, 73.59), - (-107.58, 73.25), - (-104.59, 71.02), - (-101.71, 69.56), - (-104.07, 68.62), - (-106.61, 69.12), - (-114.09, 69.05), - (-113.89, 70.12), - (-115.88, 70.32), - (-116.10, 71.32), - (-117.45, 72.48), - (-113.53, 72.44), - (-109.84, 72.24), - (-106.62, 71.71), - (-107.43, 73.04), - (-120.96, 74.29), - (-118.37, 72.53), - (-123.06, 71.18), - (-123.40, 73.77), - (-120.93, 74.27), - (-108.83, 76.74), - (-106.25, 75.54), - (-107.08, 74.78), - (-112.99, 74.16), - (-112.28, 74.99), - (-116.04, 75.33), - (-115.27, 76.20), - (-110.95, 75.56), - (-109.77, 76.31), - (-108.82, 76.70), - (-115.70, 77.46), - (-118.10, 76.30), - (-121.13, 76.37), - (-116.04, 77.28), - (-110.01, 77.86), - (-112.36, 77.68), - (-109.96, 77.86), - (-109.60, 78.48), - (-112.20, 78.01), - (-109.60, 78.48), - (-97.87, 76.61), - (-99.21, 75.31), - (-100.86, 75.60), - (-99.40, 76.26), - (-97.79, 76.60), - (-94.72, 75.53), - (-94.66, 75.52), - (-104.10, 79.01), - (-99.19, 77.54), - (-103.22, 78.08), - (-104.30, 78.95), - (-93.74, 77.52), - (-93.74, 77.52), - (-96.88, 78.50), - (-96.91, 77.77), - (-96.94, 78.48), - (-84.69, 65.84), - (-81.58, 63.87), - (-85.00, 62.96), - (-84.63, 65.71), - (-81.84, 62.75), - (-82.01, 62.63), - (-79.88, 62.12), - (-79.88, 62.12), - (-43.53, 59.89), - (-45.29, 60.67), - (-47.91, 60.83), - (-49.90, 62.41), - (-50.71, 64.42), - (-51.39, 64.94), - (-52.96, 66.09), - (-53.62, 67.19), - (-53.51, 67.51), - (-51.84, 68.65), - (-52.19, 70.00), - (-51.85, 71.03), - (-55.41, 71.41), - (-54.63, 72.97), - (-56.98, 74.70), - (-61.95, 76.09), - (-66.38, 75.83), - (-71.13, 77.00), - (-66.81, 77.60), - (-70.78, 77.78), - (-64.96, 79.70), - (-63.38, 81.16), - (-56.89, 82.17), - (-48.18, 82.15), - (-42.08, 82.74), - (-38.02, 83.54), - (-23.96, 82.94), - (-25.97, 81.97), - (-25.99, 80.64), - (-13.57, 80.97), - (-16.60, 80.16), - (-19.82, 78.82), - (-18.80, 77.54), - (-21.98, 76.46), - (-20.69, 75.12), - (-21.78, 74.40), - (-24.10, 73.69), - (-26.54, 73.08), - (-24.63, 72.69), - (-21.84, 71.69), - (-24.62, 71.24), - (-27.16, 70.89), - (-27.21, 70.00), - (-24.10, 69.35), - (-28.35, 68.43), - (-32.48, 68.56), - (-35.26, 66.26), - (-37.90, 65.90), - (-40.04, 65.00), - (-40.49, 64.04), - (-42.01, 63.14), - (-42.88, 61.15), - (-43.09, 60.07), - (-43.56, 59.90), - (-16.26, 66.41), - (-15.32, 64.29), - (-20.14, 63.47), - (-21.76, 64.21), - (-21.33, 64.97), - (-23.04, 65.62), - (-21.76, 66.26), - (-18.77, 66.12), - (-16.23, 66.35), - (0.56, 51.47), - (-1.71, 54.94), - (-3.41, 57.52), - (-5.42, 58.14), - (-5.77, 55.59), - (-3.48, 54.82), - (-4.68, 52.88), - (-2.68, 51.58), - (-3.80, 50.08), - (1.26, 51.14), - (0.65, 51.41), - (-7.17, 54.91), - (-9.97, 53.47), - (-8.52, 51.76), - (-5.69, 54.79), - (-7.34, 55.25), - (-1.33, 60.66), - (-1.17, 60.38), - (-6.18, 58.44), - (-6.09, 58.36), - (-6.47, 57.58), - (-6.33, 57.54), - (-7.30, 57.54), - (-7.46, 57.05), - (-6.54, 56.94), - (-6.00, 55.94), - (-5.09, 55.55), - (-4.44, 54.38), - (-4.30, 54.19), - (-8.08, 71.02), - (-8.21, 70.86), - (16.92, 79.52), - (22.26, 78.46), - (16.86, 76.41), - (16.00, 77.39), - (16.03, 77.92), - (16.81, 79.50), - (14.71, 79.40), - (16.05, 79.12), - (14.02, 77.80), - (13.56, 78.46), - (12.63, 79.26), - (14.68, 79.40), - (22.01, 78.24), - (21.86, 78.23), - (21.54, 77.75), - (23.88, 77.26), - (21.53, 77.67), - (22.79, 77.79), - (23.50, 79.97), - (28.24, 79.54), - (20.85, 78.94), - (19.00, 79.34), - (21.05, 79.88), - (23.41, 79.96), - (46.98, 80.23), - (43.13, 79.97), - (47.18, 80.22), - (50.43, 80.19), - (50.55, 79.88), - (47.77, 79.86), - (50.45, 80.14), - (61.79, 80.18), - (61.79, 80.18), - (65.08, 80.69), - (64.27, 80.59), - (65.13, 80.68), - (-5.13, 35.66), - (4.06, 36.63), - (10.40, 37.12), - (11.36, 33.61), - (20.10, 30.10), - (23.49, 32.17), - (31.65, 30.80), - (35.76, 23.74), - (39.75, 14.82), - (42.93, 11.34), - (51.52, 11.45), - (49.82, 6.99), - (43.13, -0.62), - (39.15, -7.58), - (40.37, -13.20), - (37.74, -18.17), - (35.33, -22.71), - (32.84, -28.15), - (26.50, -34.39), - (19.55, -35.51), - (17.50, -30.88), - (12.24, -18.75), - (13.89, -12.81), - (12.05, -5.55), - (9.67, 0.14), - (7.19, 3.79), - (1.74, 5.39), - (-4.77, 4.59), - (-12.00, 6.75), - (-15.54, 10.98), - (-16.33, 15.50), - (-16.10, 22.29), - (-12.90, 27.12), - (-9.52, 31.09), - (-5.41, 35.58), - (33.71, 0.00), - (33.48, -3.42), - (33.34, -0.20), - (33.71, 0.00), - (49.30, -12.50), - (49.28, -18.79), - (43.95, -25.50), - (44.37, -20.08), - (46.34, -16.31), - (47.91, -14.08), - (49.30, -12.50), - (178.88, 69.10), - (181.20, 68.42), - (183.52, 67.78), - (188.87, 66.38), - (186.54, 64.74), - (182.87, 65.63), - (180.13, 65.14), - (179.48, 64.88), - (178.20, 64.29), - (177.46, 62.62), - (170.42, 60.17), - (164.48, 59.89), - (162.92, 57.34), - (161.82, 54.88), - (156.42, 51.09), - (156.40, 57.76), - (163.79, 61.73), - (159.90, 60.73), - (156.81, 61.68), - (153.83, 59.10), - (148.57, 59.46), - (140.77, 58.39), - (137.10, 54.07), - (140.72, 52.43), - (138.77, 47.30), - (129.92, 42.04), - (128.33, 38.46), - (126.15, 35.18), - (125.12, 39.08), - (121.62, 40.15), - (117.58, 38.21), - (121.77, 36.90), - (120.73, 32.65), - (121.28, 30.25), - (118.83, 24.93), - (112.69, 21.81), - (108.53, 21.73), - (107.55, 16.34), - (107.32, 10.45), - (104.39, 10.37), - (100.01, 13.52), - (100.26, 8.30), - (103.22, 1.56), - (98.21, 9.17), - (97.66, 15.36), - (94.21, 17.79), - (90.05, 21.74), - (90.06, 21.03), - (82.06, 15.95), - (80.05, 11.72), - (76.41, 8.60), - (72.79, 17.43), - (72.02, 20.00), - (68.98, 21.99), - (64.62, 24.41), - (57.83, 24.77), - (53.11, 26.20), - (49.67, 29.41), - (50.96, 25.15), - (54.33, 23.44), - (59.03, 22.57), - (57.87, 18.86), - (52.95, 15.74), - (47.26, 12.96), - (42.75, 14.68), - (39.93, 19.61), - (36.92, 25.78), - (33.30, 28.46), - (32.60, 30.63), - (32.18, 30.58), - (36.08, 35.03), - (32.53, 36.17), - (27.77, 36.94), - (26.51, 39.18), - (31.54, 40.82), - (38.53, 40.48), - (40.35, 43.17), - (39.88, 46.45), - (35.18, 44.99), - (33.50, 44.96), - (30.24, 45.14), - (28.70, 41.48), - (26.55, 39.84), - (23.62, 39.67), - (23.80, 37.34), - (21.90, 36.92), - (18.79, 42.02), - (14.52, 44.31), - (14.58, 42.25), - (18.32, 39.57), - (16.05, 39.35), - (11.52, 42.36), - (6.87, 43.08), - (2.80, 41.09), - (-1.11, 37.14), - (-6.24, 36.70), - (-8.67, 39.57), - (-6.51, 43.13), - (-0.84, 45.55), - (-3.93, 48.40), - (0.48, 49.09), - (4.20, 51.29), - (6.44, 52.92), - (8.42, 55.94), - (11.72, 55.49), - (11.73, 53.66), - (16.78, 54.14), - (21.40, 56.32), - (24.67, 57.20), - (28.94, 59.18), - (24.16, 59.52), - (22.07, 62.66), - (23.76, 65.35), - (18.70, 62.54), - (19.11, 59.67), - (18.40, 58.54), - (15.34, 55.73), - (11.74, 58.08), - (8.37, 57.68), - (5.80, 59.20), - (7.38, 60.86), - (7.51, 61.86), - (9.62, 62.99), - (13.37, 65.46), - (15.46, 67.12), - (18.54, 68.62), - (22.32, 69.64), - (24.77, 70.17), - (25.93, 69.79), - (28.56, 70.46), - (29.75, 69.76), - (33.83, 69.11), - (41.90, 66.85), - (35.14, 66.25), - (33.30, 66.07), - (35.46, 64.15), - (37.68, 64.03), - (41.71, 64.09), - (44.80, 65.58), - (44.87, 68.16), - (45.92, 66.83), - (51.79, 67.85), - (53.70, 67.89), - (59.68, 68.09), - (65.07, 69.08), - (68.56, 69.19), - (68.38, 70.97), - (73.03, 71.62), - (73.80, 68.29), - (69.42, 66.45), - (73.43, 66.36), - (77.51, 68.36), - (80.74, 66.74), - (75.27, 68.67), - (75.11, 71.80), - (78.62, 70.56), - (78.43, 71.90), - (82.72, 71.23), - (84.25, 70.03), - (81.40, 72.76), - (86.50, 74.01), - (87.68, 74.78), - (90.25, 75.23), - (89.68, 75.57), - (95.12, 75.95), - (99.69, 76.09), - (104.10, 77.52), - (106.34, 76.40), - (112.99, 75.60), - (107.88, 73.72), - (110.43, 73.71), - (113.34, 73.37), - (123.10, 73.28), - (128.94, 73.02), - (126.10, 72.24), - (130.53, 70.86), - (135.49, 71.51), - (139.60, 72.23), - (146.04, 72.39), - (146.92, 72.21), - (150.77, 71.28), - (159.92, 70.14), - (167.68, 69.63), - (170.20, 69.99), - (178.88, 69.10), - (68.33, 76.71), - (66.03, 75.62), - (59.10, 74.11), - (54.92, 73.03), - (56.67, 74.10), - (58.56, 75.09), - (63.86, 75.87), - (68.19, 76.70), - (53.04, 72.57), - (58.29, 70.39), - (55.03, 70.78), - (53.44, 72.26), - (53.63, 72.61), - (52.22, 46.50), - (51.73, 44.73), - (52.56, 41.80), - (53.43, 40.40), - (54.22, 37.86), - (49.04, 38.45), - (48.17, 42.76), - (49.33, 45.64), - (52.22, 46.50), - (62.32, 46.32), - (60.32, 43.06), - (59.57, 45.58), - (61.94, 46.33), - (79.55, 46.12), - (74.30, 44.44), - (78.62, 45.79), - (79.66, 46.07), - (76.81, 41.96), - (76.73, 41.86), - (35.15, 35.15), - (34.61, 34.84), - (35.18, 35.17), - (23.84, 35.33), - (24.30, 34.91), - (24.09, 35.39), - (15.54, 37.89), - (13.47, 37.89), - (15.54, 37.89), - (9.56, 40.95), - (8.46, 39.99), - (9.12, 40.69), - (9.72, 42.60), - (9.54, 42.35), - (80.60, 8.95), - (79.73, 5.96), - (80.10, 8.30), - (11.04, 57.44), - (10.67, 57.25), - (-77.92, 24.67), - (-77.98, 24.22), - (-77.61, 23.62), - (-77.18, 23.64), - (-75.55, 24.13), - (-75.41, 24.31), - (-91.40, -0.17), - (-91.52, -0.26), - (-60.25, 46.68), - (-60.71, 46.33), - (-63.89, 49.47), - (-63.45, 49.43), - (142.53, -10.60), - (145.62, -16.34), - (149.79, -22.09), - (153.21, -26.82), - (150.52, -35.19), - (145.60, -38.53), - (140.13, -37.69), - (137.34, -34.77), - (135.76, -34.56), - (131.50, -31.34), - (121.72, -33.65), - (115.62, -33.25), - (114.09, -26.01), - (114.88, -21.27), - (122.34, -18.13), - (125.32, -14.53), - (128.39, -14.90), - (132.35, -11.42), - (136.16, -12.43), - (138.07, -16.45), - (142.25, -10.78), - (144.72, -40.68), - (148.32, -42.14), - (145.57, -42.77), - (146.47, -41.19), - (172.86, -34.23), - (176.10, -37.52), - (177.06, -39.49), - (174.77, -38.03), - (172.83, -34.27), - (172.36, -40.53), - (172.92, -43.81), - (168.41, -46.13), - (170.26, -43.21), - (173.69, -40.94), - (150.74, -10.18), - (143.04, -8.26), - (138.48, -6.97), - (131.95, -2.94), - (130.91, -1.35), - (134.38, -2.64), - (141.24, -2.62), - (148.19, -8.15), - (150.75, -10.27), - (117.24, 7.01), - (117.90, 0.76), - (113.89, -3.50), - (109.44, -0.82), - (113.13, 3.38), - (117.24, 7.01), - (95.31, 5.75), - (102.32, 1.40), - (106.03, -2.98), - (101.46, -2.81), - (95.20, 5.73), - (140.91, 41.53), - (140.79, 35.75), - (136.82, 34.56), - (133.56, 34.72), - (132.49, 35.41), - (136.73, 37.20), - (139.82, 40.00), - (140.68, 41.43), - (133.71, 34.30), - (131.41, 31.58), - (129.38, 33.10), - (133.90, 34.37), - (141.89, 45.50), - (144.12, 42.92), - (140.30, 41.64), - (141.53, 45.30), - (141.89, 45.53), - (142.57, 54.36), - (143.64, 49.19), - (141.99, 45.88), - (141.92, 50.85), - (142.60, 54.34), - (121.92, 25.48), - (120.53, 24.70), - (121.70, 25.51), - (110.81, 20.07), - (109.20, 19.66), - (110.81, 20.07), - (106.51, -6.16), - (114.15, -7.72), - (108.71, -7.89), - (106.51, -6.16), - (164.27, -20.01), - (164.16, -20.27), - (178.61, -17.04), - (178.61, -17.04), - (179.45, -16.43), - (179.35, -16.43), - (-172.55, -13.39), - (-172.61, -13.78), - (122.26, 18.67), - (123.05, 13.86), - (120.73, 13.80), - (120.43, 16.43), - (121.72, 18.40), - (125.34, 9.79), - #[allow(clippy::approx_constant)] - (125.56, 6.28), - (122.38, 7.00), - (125.10, 9.38), - (119.64, 11.35), - (118.81, 10.16), - (119.59, 10.86), - (119.64, 11.35), - (-179.87, 65.14), - (-177.13, 65.63), - (-173.46, 64.74), - (-171.13, 66.38), - (-176.48, 67.78), - (-178.80, 68.42), - (101.96, 79.08), - (101.31, 77.86), - (101.22, 79.04), - (94.29, 79.29), - (95.31, 78.68), - (100.02, 79.43), - (97.26, 79.62), - (95.44, 79.65), - (95.46, 80.62), - (92.39, 79.66), - (95.07, 80.54), - (138.54, 76.05), - (144.93, 75.45), - (140.30, 74.99), - (137.27, 75.44), - (138.29, 75.98), - (146.08, 75.29), - (147.75, 74.73), - (145.85, 75.06), - (141.44, 73.88), - (141.48, 73.84), - (0.01, -71.68), - (6.57, -70.57), - (15.04, -70.44), - (25.10, -70.75), - (33.37, -69.10), - (38.46, -69.77), - (42.85, -68.16), - (46.59, -67.23), - (49.35, -66.96), - (52.90, -65.97), - (58.46, -67.20), - (63.60, -67.58), - (70.63, -68.41), - (69.24, -70.36), - (76.20, -69.44), - (88.08, -66.64), - (94.98, -66.52), - (101.53, -66.09), - (111.31, -65.91), - (118.64, -66.87), - (126.24, -66.24), - (133.09, -66.18), - (139.85, -66.72), - (146.86, -67.96), - (153.65, -68.82), - (159.94, -69.57), - (164.10, -70.67), - (170.19, -71.94), - (165.68, -74.64), - (163.82, -77.60), - (162.10, -78.95), - (166.72, -82.84), - (175.58, -83.86), - (-178.56, -84.37), - (-147.96, -85.40), - (-152.96, -81.12), - (-153.95, -79.50), - (-151.24, -77.48), - (-146.74, -76.44), - (-137.68, -75.16), - (-131.63, -74.63), - (-123.05, -74.41), - (-114.76, -73.97), - (-111.91, -75.41), - (-105.05, -74.77), - (-100.90, -74.21), - (-101.04, -73.18), - (-100.28, -73.06), - (-93.06, -73.33), - (-85.40, -73.18), - (-79.82, -73.04), - (-78.21, -72.52), - (-71.90, -73.41), - (-67.51, -71.10), - (-67.57, -68.92), - (-66.65, -66.83), - (-64.30, -65.28), - (-59.14, -63.74), - (-59.58, -64.37), - (-62.50, -65.94), - (-62.48, -66.66), - (-65.64, -68.02), - (-63.85, -69.07), - (-61.69, -70.87), - (-60.89, -72.71), - (-61.07, -74.30), - (-63.33, -75.88), - (-76.05, -77.06), - (-83.04, -77.12), - (-74.30, -80.83), - (-56.40, -82.14), - (-42.46, -81.65), - (-31.60, -80.17), - (-34.01, -79.20), - (-32.48, -77.28), - (-26.28, -76.18), - (-17.18, -73.45), - (-11.20, -72.01), - (-8.67, -71.98), - (-5.45, -71.45), - (-0.82, -71.74), - (0.07, -71.68), - (164.65, -77.89), - (170.95, -77.37), - (179.67, -78.25), - (-178.74, -78.24), - (-165.76, -78.47), - (-158.42, -77.73), - (-58.98, -64.63), - (-60.99, -68.62), - (-61.02, -71.70), - (-62.01, -74.94), - (-52.00, -77.07), - (-42.23, -77.80), - (-36.22, -78.03), - (-35.03, -77.81), - (-26.13, -75.54), - (-19.35, -73.04), - (-12.16, -71.86), - (-6.15, -70.65), - (-0.57, -69.14), - (4.93, -70.25), - (10.91, -69.99), - (16.52, -69.87), - (25.41, -70.22), - (32.13, -69.29), - (33.62, -69.58), - (70.56, -68.53), - (73.91, -69.51), - (81.42, -67.87), - (84.67, -66.41), - (89.07, -66.73), - (-135.79, -74.67), - (-124.34, -73.22), - (-116.65, -74.08), - (-109.93, -74.64), - (-105.36, -74.56), - (-105.83, -74.77), - (-69.30, -70.06), - (-71.33, -72.68), - (-71.42, -71.85), - (-75.10, -71.46), - (-71.79, -70.55), - (-70.34, -69.26), - (-69.34, -70.13), - (-49.20, -77.83), - (-44.59, -78.79), - (-44.14, -80.13), - (-59.04, -79.95), - (-49.28, -77.84), - (-48.24, -77.81), - (-58.13, -80.12), - (-63.25, -80.20), - (-58.32, -80.12), - (-163.64, -78.74), - (-161.20, -79.93), - (-163.62, -78.74), - (66.82, 66.82), - (66.82, 66.82), -]; diff --git a/src/ratatui/widgets/chart.rs b/src/ratatui/widgets/chart.rs deleted file mode 100644 index a57a392b..00000000 --- a/src/ratatui/widgets/chart.rs +++ /dev/null @@ -1,660 +0,0 @@ -use std::{borrow::Cow, cmp::max}; - -use unicode_width::UnicodeWidthStr; - -use crate::ratatui::layout::Alignment; -use crate::ratatui::{ - buffer::Buffer, - layout::{Constraint, Rect}, - style::{Color, Style}, - symbols, - text::{Span, Spans}, - widgets::{ - canvas::{Canvas, Line, Points}, - Block, Borders, Widget, - }, -}; - -/// An X or Y axis for the chart widget -#[derive(Debug, Clone)] -pub struct Axis<'a> { - /// Title displayed next to axis end - title: Option>, - /// Bounds for the axis (all data points outside these limits will not be represented) - bounds: [f64; 2], - /// A list of labels to put to the left or below the axis - labels: Option>>, - /// The style used to draw the axis itself - style: Style, - /// The alignment of the labels of the Axis - labels_alignment: Alignment, -} - -impl<'a> Default for Axis<'a> { - fn default() -> Axis<'a> { - Axis { - title: None, - bounds: [0.0, 0.0], - labels: None, - style: Default::default(), - labels_alignment: Alignment::Left, - } - } -} - -impl<'a> Axis<'a> { - pub fn title(mut self, title: T) -> Axis<'a> - where - T: Into>, - { - self.title = Some(title.into()); - self - } - - #[deprecated( - since = "0.10.0", - note = "You should use styling capabilities of `text::Spans` given as argument of the `title` method to apply styling to the title." - )] - pub fn title_style(mut self, style: Style) -> Axis<'a> { - if let Some(t) = self.title { - let title = String::from(t); - self.title = Some(Spans::from(Span::styled(title, style))); - } - self - } - - pub fn bounds(mut self, bounds: [f64; 2]) -> Axis<'a> { - self.bounds = bounds; - self - } - - pub fn labels(mut self, labels: Vec>) -> Axis<'a> { - self.labels = Some(labels); - self - } - - pub fn style(mut self, style: Style) -> Axis<'a> { - self.style = style; - self - } - - /// Defines the alignment of the labels of the axis. - /// The alignment behaves differently based on the axis: - /// - Y-Axis: The labels are aligned within the area on the left of the axis - /// - X-Axis: The first X-axis label is aligned relative to the Y-axis - pub fn labels_alignment(mut self, alignment: Alignment) -> Axis<'a> { - self.labels_alignment = alignment; - self - } -} - -/// Used to determine which style of graphing to use -#[derive(Debug, Clone, Copy)] -pub enum GraphType { - /// Draw each point - Scatter, - /// Draw each point and lines between each point using the same marker - Line, -} - -/// A group of data points -#[derive(Debug, Clone)] -pub struct Dataset<'a> { - /// Name of the dataset (used in the legend if shown) - name: Cow<'a, str>, - /// A reference to the actual data - data: &'a [(f64, f64)], - /// Symbol used for each points of this dataset - marker: symbols::Marker, - /// Determines graph type used for drawing points - graph_type: GraphType, - /// Style used to plot this dataset - style: Style, -} - -impl<'a> Default for Dataset<'a> { - fn default() -> Dataset<'a> { - Dataset { - name: Cow::from(""), - data: &[], - marker: symbols::Marker::Dot, - graph_type: GraphType::Scatter, - style: Style::default(), - } - } -} - -impl<'a> Dataset<'a> { - pub fn name(mut self, name: S) -> Dataset<'a> - where - S: Into>, - { - self.name = name.into(); - self - } - - pub fn data(mut self, data: &'a [(f64, f64)]) -> Dataset<'a> { - self.data = data; - self - } - - pub fn marker(mut self, marker: symbols::Marker) -> Dataset<'a> { - self.marker = marker; - self - } - - pub fn graph_type(mut self, graph_type: GraphType) -> Dataset<'a> { - self.graph_type = graph_type; - self - } - - pub fn style(mut self, style: Style) -> Dataset<'a> { - self.style = style; - self - } -} - -/// A container that holds all the infos about where to display each elements of the chart (axis, -/// labels, legend, ...). -#[derive(Debug, Clone, PartialEq, Default)] -struct ChartLayout { - /// Location of the title of the x axis - title_x: Option<(u16, u16)>, - /// Location of the title of the y axis - title_y: Option<(u16, u16)>, - /// Location of the first label of the x axis - label_x: Option, - /// Location of the first label of the y axis - label_y: Option, - /// Y coordinate of the horizontal axis - axis_x: Option, - /// X coordinate of the vertical axis - axis_y: Option, - /// Area of the legend - legend_area: Option, - /// Area of the graph - graph_area: Rect, -} - -/// A widget to plot one or more dataset in a cartesian coordinate system -/// -/// # Examples -/// -/// ``` -/// # use ratatui::symbols; -/// # use ratatui::widgets::{Block, Borders, Chart, Axis, Dataset, GraphType}; -/// # use ratatui::style::{Style, Color}; -/// # use ratatui::text::Span; -/// let datasets = vec![ -/// Dataset::default() -/// .name("data1") -/// .marker(symbols::Marker::Dot) -/// .graph_type(GraphType::Scatter) -/// .style(Style::default().fg(Color::Cyan)) -/// .data(&[(0.0, 5.0), (1.0, 6.0), (1.5, 6.434)]), -/// Dataset::default() -/// .name("data2") -/// .marker(symbols::Marker::Braille) -/// .graph_type(GraphType::Line) -/// .style(Style::default().fg(Color::Magenta)) -/// .data(&[(4.0, 5.0), (5.0, 8.0), (7.66, 13.5)]), -/// ]; -/// Chart::new(datasets) -/// .block(Block::default().title("Chart")) -/// .x_axis(Axis::default() -/// .title(Span::styled("X Axis", Style::default().fg(Color::Red))) -/// .style(Style::default().fg(Color::White)) -/// .bounds([0.0, 10.0]) -/// .labels(["0.0", "5.0", "10.0"].iter().cloned().map(Span::from).collect())) -/// .y_axis(Axis::default() -/// .title(Span::styled("Y Axis", Style::default().fg(Color::Red))) -/// .style(Style::default().fg(Color::White)) -/// .bounds([0.0, 10.0]) -/// .labels(["0.0", "5.0", "10.0"].iter().cloned().map(Span::from).collect())); -/// ``` -#[derive(Debug, Clone)] -pub struct Chart<'a> { - /// A block to display around the widget eventually - block: Option>, - /// The horizontal axis - x_axis: Axis<'a>, - /// The vertical axis - y_axis: Axis<'a>, - /// A reference to the datasets - datasets: Vec>, - /// The widget base style - style: Style, - /// Constraints used to determine whether the legend should be shown or not - hidden_legend_constraints: (Constraint, Constraint), -} - -impl<'a> Chart<'a> { - pub fn new(datasets: Vec>) -> Chart<'a> { - Chart { - block: None, - x_axis: Axis::default(), - y_axis: Axis::default(), - style: Default::default(), - datasets, - hidden_legend_constraints: (Constraint::Ratio(1, 4), Constraint::Ratio(1, 4)), - } - } - - pub fn block(mut self, block: Block<'a>) -> Chart<'a> { - self.block = Some(block); - self - } - - pub fn style(mut self, style: Style) -> Chart<'a> { - self.style = style; - self - } - - pub fn x_axis(mut self, axis: Axis<'a>) -> Chart<'a> { - self.x_axis = axis; - self - } - - pub fn y_axis(mut self, axis: Axis<'a>) -> Chart<'a> { - self.y_axis = axis; - self - } - - /// Set the constraints used to determine whether the legend should be shown or not. - /// - /// # Examples - /// - /// ``` - /// # use ratatui::widgets::Chart; - /// # use ratatui::layout::Constraint; - /// let constraints = ( - /// Constraint::Ratio(1, 3), - /// Constraint::Ratio(1, 4) - /// ); - /// // Hide the legend when either its width is greater than 33% of the total widget width - /// // or if its height is greater than 25% of the total widget height. - /// let _chart: Chart = Chart::new(vec![]) - /// .hidden_legend_constraints(constraints); - /// ``` - pub fn hidden_legend_constraints(mut self, constraints: (Constraint, Constraint)) -> Chart<'a> { - self.hidden_legend_constraints = constraints; - self - } - - /// Compute the internal layout of the chart given the area. If the area is too small some - /// elements may be automatically hidden - fn layout(&self, area: Rect) -> ChartLayout { - let mut layout = ChartLayout::default(); - if area.height == 0 || area.width == 0 { - return layout; - } - let mut x = area.left(); - let mut y = area.bottom() - 1; - - if self.x_axis.labels.is_some() && y > area.top() { - layout.label_x = Some(y); - y -= 1; - } - - layout.label_y = self.y_axis.labels.as_ref().and(Some(x)); - x += self.max_width_of_labels_left_of_y_axis(area, self.y_axis.labels.is_some()); - - if self.x_axis.labels.is_some() && y > area.top() { - layout.axis_x = Some(y); - y -= 1; - } - - if self.y_axis.labels.is_some() && x + 1 < area.right() { - layout.axis_y = Some(x); - x += 1; - } - - if x < area.right() && y > 1 { - layout.graph_area = Rect::new(x, area.top(), area.right() - x, y - area.top() + 1); - } - - if let Some(ref title) = self.x_axis.title { - let w = title.width() as u16; - if w < layout.graph_area.width && layout.graph_area.height > 2 { - layout.title_x = Some((x + layout.graph_area.width - w, y)); - } - } - - if let Some(ref title) = self.y_axis.title { - let w = title.width() as u16; - if w + 1 < layout.graph_area.width && layout.graph_area.height > 2 { - layout.title_y = Some((x, area.top())); - } - } - - if let Some(inner_width) = self.datasets.iter().map(|d| d.name.width() as u16).max() { - let legend_width = inner_width + 2; - let legend_height = self.datasets.len() as u16 + 2; - let max_legend_width = self - .hidden_legend_constraints - .0 - .apply(layout.graph_area.width); - let max_legend_height = self - .hidden_legend_constraints - .1 - .apply(layout.graph_area.height); - if inner_width > 0 - && legend_width < max_legend_width - && legend_height < max_legend_height - { - layout.legend_area = Some(Rect::new( - layout.graph_area.right() - legend_width, - layout.graph_area.top(), - legend_width, - legend_height, - )); - } - } - layout - } - - fn max_width_of_labels_left_of_y_axis(&self, area: Rect, has_y_axis: bool) -> u16 { - let mut max_width = self - .y_axis - .labels - .as_ref() - .map(|l| l.iter().map(Span::width).max().unwrap_or_default() as u16) - .unwrap_or_default(); - - if let Some(first_x_label) = self.x_axis.labels.as_ref().and_then(|labels| labels.get(0)) { - let first_label_width = first_x_label.content.width() as u16; - let width_left_of_y_axis = match self.x_axis.labels_alignment { - Alignment::Left => { - // The last character of the label should be below the Y-Axis when it exists, not on its left - let y_axis_offset = if has_y_axis { 1 } else { 0 }; - first_label_width.saturating_sub(y_axis_offset) - } - Alignment::Center => first_label_width / 2, - Alignment::Right => 0, - }; - max_width = max(max_width, width_left_of_y_axis); - } - // labels of y axis and first label of x axis can take at most 1/3rd of the total width - max_width.min(area.width / 3) - } - - fn render_x_labels( - &mut self, - buf: &mut Buffer, - layout: &ChartLayout, - chart_area: Rect, - graph_area: Rect, - ) { - let y = match layout.label_x { - Some(y) => y, - None => return, - }; - let labels = self.x_axis.labels.as_ref().unwrap(); - let labels_len = labels.len() as u16; - if labels_len < 2 { - return; - } - - let width_between_ticks = graph_area.width / labels_len; - - let label_area = self.first_x_label_area( - y, - labels.first().unwrap().width() as u16, - width_between_ticks, - chart_area, - graph_area, - ); - - let label_alignment = match self.x_axis.labels_alignment { - Alignment::Left => Alignment::Right, - Alignment::Center => Alignment::Center, - Alignment::Right => Alignment::Left, - }; - - Self::render_label(buf, labels.first().unwrap(), label_area, label_alignment); - - for (i, label) in labels[1..labels.len() - 1].iter().enumerate() { - // We add 1 to x (and width-1 below) to leave at least one space before each intermediate labels - let x = graph_area.left() + (i + 1) as u16 * width_between_ticks + 1; - let label_area = Rect::new(x, y, width_between_ticks.saturating_sub(1), 1); - - Self::render_label(buf, label, label_area, Alignment::Center); - } - - let x = graph_area.right() - width_between_ticks; - let label_area = Rect::new(x, y, width_between_ticks, 1); - // The last label should be aligned Right to be at the edge of the graph area - Self::render_label(buf, labels.last().unwrap(), label_area, Alignment::Right); - } - - fn first_x_label_area( - &self, - y: u16, - label_width: u16, - max_width_after_y_axis: u16, - chart_area: Rect, - graph_area: Rect, - ) -> Rect { - let (min_x, max_x) = match self.x_axis.labels_alignment { - Alignment::Left => (chart_area.left(), graph_area.left()), - Alignment::Center => ( - chart_area.left(), - graph_area.left() + max_width_after_y_axis.min(label_width), - ), - Alignment::Right => ( - graph_area.left().saturating_sub(1), - graph_area.left() + max_width_after_y_axis, - ), - }; - - Rect::new(min_x, y, max_x - min_x, 1) - } - - fn render_label(buf: &mut Buffer, label: &Span, label_area: Rect, alignment: Alignment) { - let label_width = label.width() as u16; - let bounded_label_width = label_area.width.min(label_width); - - let x = match alignment { - Alignment::Left => label_area.left(), - Alignment::Center => label_area.left() + label_area.width / 2 - bounded_label_width / 2, - Alignment::Right => label_area.right() - bounded_label_width, - }; - - buf.set_span(x, label_area.top(), label, bounded_label_width); - } - - fn render_y_labels( - &mut self, - buf: &mut Buffer, - layout: &ChartLayout, - chart_area: Rect, - graph_area: Rect, - ) { - let x = match layout.label_y { - Some(x) => x, - None => return, - }; - let labels = self.y_axis.labels.as_ref().unwrap(); - let labels_len = labels.len() as u16; - for (i, label) in labels.iter().enumerate() { - let dy = i as u16 * (graph_area.height - 1) / (labels_len - 1); - if dy < graph_area.bottom() { - let label_area = Rect::new( - x, - graph_area.bottom().saturating_sub(1) - dy, - (graph_area.left() - chart_area.left()).saturating_sub(1), - 1, - ); - Self::render_label(buf, label, label_area, self.y_axis.labels_alignment); - } - } - } -} - -impl<'a> Widget for Chart<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - if area.area() == 0 { - return; - } - buf.set_style(area, self.style); - // Sample the style of the entire widget. This sample will be used to reset the style of - // the cells that are part of the components put on top of the grah area (i.e legend and - // axis names). - let original_style = buf.get(area.left(), area.top()).style(); - - let chart_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - let layout = self.layout(chart_area); - let graph_area = layout.graph_area; - if graph_area.width < 1 || graph_area.height < 1 { - return; - } - - self.render_x_labels(buf, &layout, chart_area, graph_area); - self.render_y_labels(buf, &layout, chart_area, graph_area); - - if let Some(y) = layout.axis_x { - for x in graph_area.left()..graph_area.right() { - buf.get_mut(x, y) - .set_symbol(symbols::line::HORIZONTAL) - .set_style(self.x_axis.style); - } - } - - if let Some(x) = layout.axis_y { - for y in graph_area.top()..graph_area.bottom() { - buf.get_mut(x, y) - .set_symbol(symbols::line::VERTICAL) - .set_style(self.y_axis.style); - } - } - - if let Some(y) = layout.axis_x { - if let Some(x) = layout.axis_y { - buf.get_mut(x, y) - .set_symbol(symbols::line::BOTTOM_LEFT) - .set_style(self.x_axis.style); - } - } - - for dataset in &self.datasets { - Canvas::default() - .background_color(self.style.bg.unwrap_or(Color::Reset)) - .x_bounds(self.x_axis.bounds) - .y_bounds(self.y_axis.bounds) - .marker(dataset.marker) - .paint(|ctx| { - ctx.draw(&Points { - coords: dataset.data, - color: dataset.style.fg.unwrap_or(Color::Reset), - }); - if let GraphType::Line = dataset.graph_type { - for data in dataset.data.windows(2) { - ctx.draw(&Line { - x1: data[0].0, - y1: data[0].1, - x2: data[1].0, - y2: data[1].1, - color: dataset.style.fg.unwrap_or(Color::Reset), - }) - } - } - }) - .render(graph_area, buf); - } - - if let Some(legend_area) = layout.legend_area { - buf.set_style(legend_area, original_style); - Block::default() - .borders(Borders::ALL) - .render(legend_area, buf); - for (i, dataset) in self.datasets.iter().enumerate() { - buf.set_string( - legend_area.x + 1, - legend_area.y + 1 + i as u16, - &dataset.name, - dataset.style, - ); - } - } - - if let Some((x, y)) = layout.title_x { - let title = self.x_axis.title.unwrap(); - let width = graph_area.right().saturating_sub(x); - buf.set_style( - Rect { - x, - y, - width, - height: 1, - }, - original_style, - ); - buf.set_spans(x, y, &title, width); - } - - if let Some((x, y)) = layout.title_y { - let title = self.y_axis.title.unwrap(); - let width = graph_area.right().saturating_sub(x); - buf.set_style( - Rect { - x, - y, - width, - height: 1, - }, - original_style, - ); - buf.set_spans(x, y, &title, width); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - struct LegendTestCase { - chart_area: Rect, - hidden_legend_constraints: (Constraint, Constraint), - legend_area: Option, - } - - #[test] - fn it_should_hide_the_legend() { - let data = [(0.0, 5.0), (1.0, 6.0), (3.0, 7.0)]; - let cases = [ - LegendTestCase { - chart_area: Rect::new(0, 0, 100, 100), - hidden_legend_constraints: (Constraint::Ratio(1, 4), Constraint::Ratio(1, 4)), - legend_area: Some(Rect::new(88, 0, 12, 12)), - }, - LegendTestCase { - chart_area: Rect::new(0, 0, 100, 100), - hidden_legend_constraints: (Constraint::Ratio(1, 10), Constraint::Ratio(1, 4)), - legend_area: None, - }, - ]; - for case in &cases { - let datasets = (0..10) - .map(|i| { - let name = format!("Dataset #{}", i); - Dataset::default().name(name).data(&data) - }) - .collect::>(); - let chart = Chart::new(datasets) - .x_axis(Axis::default().title("X axis")) - .y_axis(Axis::default().title("Y axis")) - .hidden_legend_constraints(case.hidden_legend_constraints); - let layout = chart.layout(case.chart_area); - assert_eq!(layout.legend_area, case.legend_area); - } - } -} diff --git a/src/ratatui/widgets/clear.rs b/src/ratatui/widgets/clear.rs deleted file mode 100644 index a7c8d34b..00000000 --- a/src/ratatui/widgets/clear.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; - -/// A widget to clear/reset a certain area to allow overdrawing (e.g. for popups). -/// -/// This widget **cannot be used to clear the terminal on the first render** as `ratatui` assumes the -/// render area is empty. Use [`crate::Terminal::clear`] instead. -/// -/// # Examples -/// -/// ``` -/// # use ratatui::widgets::{Clear, Block, Borders}; -/// # use ratatui::layout::Rect; -/// # use ratatui::Frame; -/// # use ratatui::backend::Backend; -/// fn draw_on_clear(f: &mut Frame, area: Rect) { -/// let block = Block::default().title("Block").borders(Borders::ALL); -/// f.render_widget(Clear, area); // <- this will clear/reset the area first -/// f.render_widget(block, area); // now render the block widget -/// } -/// ``` -/// -/// # Popup Example -/// -/// For a more complete example how to utilize `Clear` to realize popups see -/// the example `examples/popup.rs` -#[derive(Debug, Clone)] -pub struct Clear; - -impl Widget for Clear { - fn render(self, area: Rect, buf: &mut Buffer) { - for x in area.left()..area.right() { - for y in area.top()..area.bottom() { - buf.get_mut(x, y).reset(); - } - } - } -} diff --git a/src/ratatui/widgets/gauge.rs b/src/ratatui/widgets/gauge.rs deleted file mode 100644 index 6b53b975..00000000 --- a/src/ratatui/widgets/gauge.rs +++ /dev/null @@ -1,313 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::Rect, - style::{Color, Style}, - symbols, - text::{Span, Spans}, - widgets::{Block, Widget}, -}; - -/// A widget to display a task progress. -/// -/// # Examples: -/// -/// ``` -/// # use ratatui::widgets::{Widget, Gauge, Block, Borders}; -/// # use ratatui::style::{Style, Color, Modifier}; -/// Gauge::default() -/// .block(Block::default().borders(Borders::ALL).title("Progress")) -/// .gauge_style(Style::default().fg(Color::White).bg(Color::Black).add_modifier(Modifier::ITALIC)) -/// .percent(20); -/// ``` -#[derive(Debug, Clone)] -pub struct Gauge<'a> { - block: Option>, - ratio: f64, - label: Option>, - use_unicode: bool, - style: Style, - gauge_style: Style, -} - -impl<'a> Default for Gauge<'a> { - fn default() -> Gauge<'a> { - Gauge { - block: None, - ratio: 0.0, - label: None, - use_unicode: false, - style: Style::default(), - gauge_style: Style::default(), - } - } -} - -impl<'a> Gauge<'a> { - pub fn block(mut self, block: Block<'a>) -> Gauge<'a> { - self.block = Some(block); - self - } - - pub fn percent(mut self, percent: u16) -> Gauge<'a> { - assert!( - percent <= 100, - "Percentage should be between 0 and 100 inclusively." - ); - self.ratio = f64::from(percent) / 100.0; - self - } - - /// Sets ratio ([0.0, 1.0]) directly. - pub fn ratio(mut self, ratio: f64) -> Gauge<'a> { - assert!( - (0.0..=1.0).contains(&ratio), - "Ratio should be between 0 and 1 inclusively." - ); - self.ratio = ratio; - self - } - - pub fn label(mut self, label: T) -> Gauge<'a> - where - T: Into>, - { - self.label = Some(label.into()); - self - } - - pub fn style(mut self, style: Style) -> Gauge<'a> { - self.style = style; - self - } - - pub fn gauge_style(mut self, style: Style) -> Gauge<'a> { - self.gauge_style = style; - self - } - - pub fn use_unicode(mut self, unicode: bool) -> Gauge<'a> { - self.use_unicode = unicode; - self - } -} - -impl<'a> Widget for Gauge<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - buf.set_style(area, self.style); - let gauge_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - buf.set_style(gauge_area, self.gauge_style); - if gauge_area.height < 1 { - return; - } - - // compute label value and its position - // label is put at the center of the gauge_area - let label = { - let pct = f64::round(self.ratio * 100.0); - self.label - .unwrap_or_else(|| Span::from(format!("{}%", pct))) - }; - let clamped_label_width = gauge_area.width.min(label.width() as u16); - let label_col = gauge_area.left() + (gauge_area.width - clamped_label_width) / 2; - let label_row = gauge_area.top() + gauge_area.height / 2; - - // the gauge will be filled proportionally to the ratio - let filled_width = f64::from(gauge_area.width) * self.ratio; - let end = if self.use_unicode { - gauge_area.left() + filled_width.floor() as u16 - } else { - gauge_area.left() + filled_width.round() as u16 - }; - for y in gauge_area.top()..gauge_area.bottom() { - // render the filled area (left to end) - for x in gauge_area.left()..end { - // spaces are needed to apply the background styling - buf.get_mut(x, y) - .set_symbol(" ") - .set_fg(self.gauge_style.bg.unwrap_or(Color::Reset)) - .set_bg(self.gauge_style.fg.unwrap_or(Color::Reset)); - } - if self.use_unicode && self.ratio < 1.0 { - buf.get_mut(end, y) - .set_symbol(get_unicode_block(filled_width % 1.0)); - } - } - // set the span - buf.set_span(label_col, label_row, &label, clamped_label_width); - } -} - -fn get_unicode_block<'a>(frac: f64) -> &'a str { - match (frac * 8.0).round() as u16 { - 1 => symbols::block::ONE_EIGHTH, - 2 => symbols::block::ONE_QUARTER, - 3 => symbols::block::THREE_EIGHTHS, - 4 => symbols::block::HALF, - 5 => symbols::block::FIVE_EIGHTHS, - 6 => symbols::block::THREE_QUARTERS, - 7 => symbols::block::SEVEN_EIGHTHS, - 8 => symbols::block::FULL, - _ => " ", - } -} - -/// A compact widget to display a task progress over a single line. -/// -/// # Examples: -/// -/// ``` -/// # use ratatui::widgets::{Widget, LineGauge, Block, Borders}; -/// # use ratatui::style::{Style, Color, Modifier}; -/// # use ratatui::symbols; -/// LineGauge::default() -/// .block(Block::default().borders(Borders::ALL).title("Progress")) -/// .gauge_style(Style::default().fg(Color::White).bg(Color::Black).add_modifier(Modifier::BOLD)) -/// .line_set(symbols::line::THICK) -/// .ratio(0.4); -/// ``` -pub struct LineGauge<'a> { - block: Option>, - ratio: f64, - label: Option>, - line_set: symbols::line::Set, - style: Style, - gauge_style: Style, -} - -impl<'a> Default for LineGauge<'a> { - fn default() -> Self { - Self { - block: None, - ratio: 0.0, - label: None, - style: Style::default(), - line_set: symbols::line::NORMAL, - gauge_style: Style::default(), - } - } -} - -impl<'a> LineGauge<'a> { - pub fn block(mut self, block: Block<'a>) -> Self { - self.block = Some(block); - self - } - - pub fn ratio(mut self, ratio: f64) -> Self { - assert!( - (0.0..=1.0).contains(&ratio), - "Ratio should be between 0 and 1 inclusively." - ); - self.ratio = ratio; - self - } - - pub fn line_set(mut self, set: symbols::line::Set) -> Self { - self.line_set = set; - self - } - - pub fn label(mut self, label: T) -> Self - where - T: Into>, - { - self.label = Some(label.into()); - self - } - - pub fn style(mut self, style: Style) -> Self { - self.style = style; - self - } - - pub fn gauge_style(mut self, style: Style) -> Self { - self.gauge_style = style; - self - } -} - -impl<'a> Widget for LineGauge<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - buf.set_style(area, self.style); - let gauge_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - if gauge_area.height < 1 { - return; - } - - let ratio = self.ratio; - let label = self - .label - .unwrap_or_else(move || Spans::from(format!("{:.0}%", ratio * 100.0))); - let (col, row) = buf.set_spans( - gauge_area.left(), - gauge_area.top(), - &label, - gauge_area.width, - ); - let start = col + 1; - if start >= gauge_area.right() { - return; - } - - let end = start - + (f64::from(gauge_area.right().saturating_sub(start)) * self.ratio).floor() as u16; - for col in start..end { - buf.get_mut(col, row) - .set_symbol(self.line_set.horizontal) - .set_style(Style { - fg: self.gauge_style.fg, - bg: None, - add_modifier: self.gauge_style.add_modifier, - sub_modifier: self.gauge_style.sub_modifier, - }); - } - for col in end..gauge_area.right() { - buf.get_mut(col, row) - .set_symbol(self.line_set.horizontal) - .set_style(Style { - fg: self.gauge_style.bg, - bg: None, - add_modifier: self.gauge_style.add_modifier, - sub_modifier: self.gauge_style.sub_modifier, - }); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[should_panic] - fn gauge_invalid_percentage() { - Gauge::default().percent(110); - } - - #[test] - #[should_panic] - fn gauge_invalid_ratio_upper_bound() { - Gauge::default().ratio(1.1); - } - - #[test] - #[should_panic] - fn gauge_invalid_ratio_lower_bound() { - Gauge::default().ratio(-0.5); - } -} diff --git a/src/ratatui/widgets/list.rs b/src/ratatui/widgets/list.rs deleted file mode 100644 index 9608d299..00000000 --- a/src/ratatui/widgets/list.rs +++ /dev/null @@ -1,268 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::{Corner, Rect}, - style::Style, - text::Text, - widgets::{Block, StatefulWidget, Widget}, -}; -use unicode_width::UnicodeWidthStr; - -#[derive(Debug, Clone, Default)] -pub struct ListState { - offset: usize, - selected: Option, -} - -impl ListState { - pub fn selected(&self) -> Option { - self.selected - } - - pub fn select(&mut self, index: Option) { - self.selected = index; - if index.is_none() { - self.offset = 0; - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ListItem<'a> { - content: Text<'a>, - style: Style, -} - -impl<'a> ListItem<'a> { - pub fn new(content: T) -> ListItem<'a> - where - T: Into>, - { - ListItem { - content: content.into(), - style: Style::default(), - } - } - - pub fn style(mut self, style: Style) -> ListItem<'a> { - self.style = style; - self - } - - pub fn height(&self) -> usize { - self.content.height() - } - - pub fn width(&self) -> usize { - self.content.width() - } -} - -/// A widget to display several items among which one can be selected (optional) -/// -/// # Examples -/// -/// ``` -/// # use ratatui::widgets::{Block, Borders, List, ListItem}; -/// # use ratatui::style::{Style, Color, Modifier}; -/// let items = [ListItem::new("Item 1"), ListItem::new("Item 2"), ListItem::new("Item 3")]; -/// List::new(items) -/// .block(Block::default().title("List").borders(Borders::ALL)) -/// .style(Style::default().fg(Color::White)) -/// .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) -/// .highlight_symbol(">>"); -/// ``` -#[derive(Debug, Clone)] -pub struct List<'a> { - block: Option>, - items: Vec>, - /// Style used as a base style for the widget - style: Style, - start_corner: Corner, - /// Style used to render selected item - highlight_style: Style, - /// Symbol in front of the selected item (Shift all items to the right) - highlight_symbol: Option<&'a str>, - /// Whether to repeat the highlight symbol for each line of the selected item - repeat_highlight_symbol: bool, -} - -impl<'a> List<'a> { - pub fn new(items: T) -> List<'a> - where - T: Into>>, - { - List { - block: None, - style: Style::default(), - items: items.into(), - start_corner: Corner::TopLeft, - highlight_style: Style::default(), - highlight_symbol: None, - repeat_highlight_symbol: false, - } - } - - pub fn block(mut self, block: Block<'a>) -> List<'a> { - self.block = Some(block); - self - } - - pub fn style(mut self, style: Style) -> List<'a> { - self.style = style; - self - } - - pub fn highlight_symbol(mut self, highlight_symbol: &'a str) -> List<'a> { - self.highlight_symbol = Some(highlight_symbol); - self - } - - pub fn highlight_style(mut self, style: Style) -> List<'a> { - self.highlight_style = style; - self - } - - pub fn repeat_highlight_symbol(mut self, repeat: bool) -> List<'a> { - self.repeat_highlight_symbol = repeat; - self - } - - pub fn start_corner(mut self, corner: Corner) -> List<'a> { - self.start_corner = corner; - self - } - - fn get_items_bounds( - &self, - selected: Option, - offset: usize, - max_height: usize, - ) -> (usize, usize) { - let offset = offset.min(self.items.len().saturating_sub(1)); - let mut start = offset; - let mut end = offset; - let mut height = 0; - for item in self.items.iter().skip(offset) { - if height + item.height() > max_height { - break; - } - height += item.height(); - end += 1; - } - - let selected = selected.unwrap_or(0).min(self.items.len() - 1); - while selected >= end { - height = height.saturating_add(self.items[end].height()); - end += 1; - while height > max_height { - height = height.saturating_sub(self.items[start].height()); - start += 1; - } - } - while selected < start { - start -= 1; - height = height.saturating_add(self.items[start].height()); - while height > max_height { - end -= 1; - height = height.saturating_sub(self.items[end].height()); - } - } - (start, end) - } -} - -impl<'a> StatefulWidget for List<'a> { - type State = ListState; - - fn render(mut self, area: Rect, buf: &mut Buffer, state: &mut Self::State) { - buf.set_style(area, self.style); - let list_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - if list_area.width < 1 || list_area.height < 1 { - return; - } - - if self.items.is_empty() { - return; - } - let list_height = list_area.height as usize; - - let (start, end) = self.get_items_bounds(state.selected, state.offset, list_height); - state.offset = start; - - let highlight_symbol = self.highlight_symbol.unwrap_or(""); - let blank_symbol = " ".repeat(highlight_symbol.width()); - - let mut current_height = 0; - let has_selection = state.selected.is_some(); - for (i, item) in self - .items - .iter_mut() - .enumerate() - .skip(state.offset) - .take(end - start) - { - let (x, y) = match self.start_corner { - Corner::BottomLeft => { - current_height += item.height() as u16; - (list_area.left(), list_area.bottom() - current_height) - } - _ => { - let pos = (list_area.left(), list_area.top() + current_height); - current_height += item.height() as u16; - pos - } - }; - let area = Rect { - x, - y, - width: list_area.width, - height: item.height() as u16, - }; - let item_style = self.style.patch(item.style); - buf.set_style(area, item_style); - - let is_selected = state.selected.map(|s| s == i).unwrap_or(false); - for (j, line) in item.content.lines.iter().enumerate() { - // if the item is selected, we need to display the highlight symbol: - // - either for the first line of the item only, - // - or for each line of the item if the appropriate option is set - let symbol = if is_selected && (j == 0 || self.repeat_highlight_symbol) { - highlight_symbol - } else { - &blank_symbol - }; - let (elem_x, max_element_width) = if has_selection { - let (elem_x, _) = buf.set_stringn( - x, - y + j as u16, - symbol, - list_area.width as usize, - item_style, - ); - (elem_x, (list_area.width - (elem_x - x))) - } else { - (x, list_area.width) - }; - buf.set_spans(elem_x, y + j as u16, line, max_element_width); - } - if is_selected { - buf.set_style(area, self.highlight_style); - } - } - } -} - -impl<'a> Widget for List<'a> { - fn render(self, area: Rect, buf: &mut Buffer) { - let mut state = ListState::default(); - StatefulWidget::render(self, area, buf, &mut state); - } -} diff --git a/src/ratatui/widgets/mod.rs b/src/ratatui/widgets/mod.rs deleted file mode 100644 index 5a6167b8..00000000 --- a/src/ratatui/widgets/mod.rs +++ /dev/null @@ -1,184 +0,0 @@ -//! `widgets` is a collection of types that implement [`Widget`] or [`StatefulWidget`] or both. -//! -//! All widgets are implemented using the builder pattern and are consumable objects. They are not -//! meant to be stored but used as *commands* to draw common figures in the UI. -//! -//! The available widgets are: -//! - [`Block`] -//! - [`Tabs`] -//! - [`List`] -//! - [`Table`] -//! - [`Paragraph`] -//! - [`Chart`] -//! - [`BarChart`] -//! - [`Gauge`] -//! - [`Sparkline`] -//! - [`Clear`] - -mod barchart; -mod block; -pub mod canvas; -mod chart; -mod clear; -mod gauge; -mod list; -mod paragraph; -mod reflow; -mod sparkline; -mod table; -mod tabs; - -pub use self::barchart::BarChart; -pub use self::block::{Block, BorderType}; -pub use self::chart::{Axis, Chart, Dataset, GraphType}; -pub use self::clear::Clear; -pub use self::gauge::{Gauge, LineGauge}; -pub use self::list::{List, ListItem, ListState}; -pub use self::paragraph::{Paragraph, Wrap}; -pub use self::sparkline::Sparkline; -pub use self::table::{Cell, Row, Table, TableState}; -pub use self::tabs::Tabs; - -use crate::ratatui::{buffer::Buffer, layout::Rect}; -use bitflags::bitflags; - -bitflags! { - /// Bitflags that can be composed to set the visible borders essentially on the block widget. - pub struct Borders: u8 { - /// Show no border (default) - const NONE = 0b0000; - /// Show the top border - const TOP = 0b0001; - /// Show the right border - const RIGHT = 0b0010; - /// Show the bottom border - const BOTTOM = 0b0100; - /// Show the left border - const LEFT = 0b1000; - /// Show all borders - const ALL = Self::TOP.bits | Self::RIGHT.bits | Self::BOTTOM.bits | Self::LEFT.bits; - } -} - -/// Base requirements for a Widget -pub trait Widget { - /// Draws the current state of the widget in the given buffer. That is the only method required - /// to implement a custom widget. - fn render(self, area: Rect, buf: &mut Buffer); -} - -/// A `StatefulWidget` is a widget that can take advantage of some local state to remember things -/// between two draw calls. -/// -/// Most widgets can be drawn directly based on the input parameters. However, some features may -/// require some kind of associated state to be implemented. -/// -/// For example, the [`List`] widget can highlight the item currently selected. This can be -/// translated in an offset, which is the number of elements to skip in order to have the selected -/// item within the viewport currently allocated to this widget. The widget can therefore only -/// provide the following behavior: whenever the selected item is out of the viewport scroll to a -/// predefined position (making the selected item the last viewable item or the one in the middle -/// for example). Nonetheless, if the widget has access to the last computed offset then it can -/// implement a natural scrolling experience where the last offset is reused until the selected -/// item is out of the viewport. -/// -/// ## Examples -/// -/// ```rust,no_run -/// # use std::io; -/// # use ratatui::Terminal; -/// # use ratatui::backend::{Backend, TestBackend}; -/// # use ratatui::widgets::{Widget, List, ListItem, ListState}; -/// -/// // Let's say we have some events to display. -/// struct Events { -/// // `items` is the state managed by your application. -/// items: Vec, -/// // `state` is the state that can be modified by the UI. It stores the index of the selected -/// // item as well as the offset computed during the previous draw call (used to implement -/// // natural scrolling). -/// state: ListState -/// } -/// -/// impl Events { -/// fn new(items: Vec) -> Events { -/// Events { -/// items, -/// state: ListState::default(), -/// } -/// } -/// -/// pub fn set_items(&mut self, items: Vec) { -/// self.items = items; -/// // We reset the state as the associated items have changed. This effectively reset -/// // the selection as well as the stored offset. -/// self.state = ListState::default(); -/// } -/// -/// // Select the next item. This will not be reflected until the widget is drawn in the -/// // `Terminal::draw` callback using `Frame::render_stateful_widget`. -/// pub fn next(&mut self) { -/// let i = match self.state.selected() { -/// Some(i) => { -/// if i >= self.items.len() - 1 { -/// 0 -/// } else { -/// i + 1 -/// } -/// } -/// None => 0, -/// }; -/// self.state.select(Some(i)); -/// } -/// -/// // Select the previous item. This will not be reflected until the widget is drawn in the -/// // `Terminal::draw` callback using `Frame::render_stateful_widget`. -/// pub fn previous(&mut self) { -/// let i = match self.state.selected() { -/// Some(i) => { -/// if i == 0 { -/// self.items.len() - 1 -/// } else { -/// i - 1 -/// } -/// } -/// None => 0, -/// }; -/// self.state.select(Some(i)); -/// } -/// -/// // Unselect the currently selected item if any. The implementation of `ListState` makes -/// // sure that the stored offset is also reset. -/// pub fn unselect(&mut self) { -/// self.state.select(None); -/// } -/// } -/// -/// # let backend = TestBackend::new(5, 5); -/// # let mut terminal = Terminal::new(backend).unwrap(); -/// -/// let mut events = Events::new(vec![ -/// String::from("Item 1"), -/// String::from("Item 2") -/// ]); -/// -/// loop { -/// terminal.draw(|f| { -/// // The items managed by the application are transformed to something -/// // that is understood by ratatui. -/// let items: Vec= events.items.iter().map(|i| ListItem::new(i.as_ref())).collect(); -/// // The `List` widget is then built with those items. -/// let list = List::new(items); -/// // Finally the widget is rendered using the associated state. `events.state` is -/// // effectively the only thing that we will "remember" from this draw call. -/// f.render_stateful_widget(list, f.size(), &mut events.state); -/// }); -/// -/// // In response to some input events or an external http request or whatever: -/// events.next(); -/// } -/// ``` -pub trait StatefulWidget { - type State; - fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State); -} diff --git a/src/ratatui/widgets/paragraph.rs b/src/ratatui/widgets/paragraph.rs deleted file mode 100644 index 5edfe08e..00000000 --- a/src/ratatui/widgets/paragraph.rs +++ /dev/null @@ -1,214 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::{Alignment, Rect}, - style::Style, - text::{StyledGrapheme, Text}, - widgets::{ - reflow::{LineComposer, LineTruncator, WordWrapper}, - Block, Widget, - }, -}; -use std::iter; -use unicode_width::UnicodeWidthStr; - -fn get_line_offset(line_width: u16, text_area_width: u16, alignment: Alignment) -> u16 { - match alignment { - Alignment::Center => (text_area_width / 2).saturating_sub(line_width / 2), - Alignment::Right => text_area_width.saturating_sub(line_width), - Alignment::Left => 0, - } -} - -/// A widget to display some text. -/// -/// # Examples -/// -/// ``` -/// # use ratatui::text::{Text, Spans, Span}; -/// # use ratatui::widgets::{Block, Borders, Paragraph, Wrap}; -/// # use ratatui::style::{Style, Color, Modifier}; -/// # use ratatui::layout::{Alignment}; -/// let text = vec![ -/// Spans::from(vec![ -/// Span::raw("First"), -/// Span::styled("line",Style::default().add_modifier(Modifier::ITALIC)), -/// Span::raw("."), -/// ]), -/// Spans::from(Span::styled("Second line", Style::default().fg(Color::Red))), -/// ]; -/// Paragraph::new(text) -/// .block(Block::default().title("Paragraph").borders(Borders::ALL)) -/// .style(Style::default().fg(Color::White).bg(Color::Black)) -/// .alignment(Alignment::Center) -/// .wrap(Wrap { trim: true }); -/// ``` -#[derive(Debug, Clone)] -pub struct Paragraph<'a> { - /// A block to wrap the widget in - block: Option>, - /// Widget style - style: Style, - /// How to wrap the text - wrap: Option, - /// The text to display - text: Text<'a>, - /// Scroll - scroll: (u16, u16), - /// Alignment of the text - alignment: Alignment, -} - -/// Describes how to wrap text across lines. -/// -/// ## Examples -/// -/// ``` -/// # use ratatui::widgets::{Paragraph, Wrap}; -/// # use ratatui::text::Text; -/// let bullet_points = Text::from(r#"Some indented points: -/// - First thing goes here and is long so that it wraps -/// - Here is another point that is long enough to wrap"#); -/// -/// // With leading spaces trimmed (window width of 30 chars): -/// Paragraph::new(bullet_points.clone()).wrap(Wrap { trim: true }); -/// // Some indented points: -/// // - First thing goes here and is -/// // long so that it wraps -/// // - Here is another point that -/// // is long enough to wrap -/// -/// // But without trimming, indentation is preserved: -/// Paragraph::new(bullet_points).wrap(Wrap { trim: false }); -/// // Some indented points: -/// // - First thing goes here -/// // and is long so that it wraps -/// // - Here is another point -/// // that is long enough to wrap -/// ``` -#[derive(Debug, Clone, Copy)] -pub struct Wrap { - /// Should leading whitespace be trimmed - pub trim: bool, -} - -impl<'a> Paragraph<'a> { - pub fn new(text: T) -> Paragraph<'a> - where - T: Into>, - { - Paragraph { - block: None, - style: Default::default(), - wrap: None, - text: text.into(), - scroll: (0, 0), - alignment: Alignment::Left, - } - } - - pub fn block(mut self, block: Block<'a>) -> Paragraph<'a> { - self.block = Some(block); - self - } - - pub fn style(mut self, style: Style) -> Paragraph<'a> { - self.style = style; - self - } - - pub fn wrap(mut self, wrap: Wrap) -> Paragraph<'a> { - self.wrap = Some(wrap); - self - } - - pub fn scroll(mut self, offset: (u16, u16)) -> Paragraph<'a> { - self.scroll = offset; - self - } - - pub fn alignment(mut self, alignment: Alignment) -> Paragraph<'a> { - self.alignment = alignment; - self - } -} - -impl<'a> Widget for Paragraph<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - buf.set_style(area, self.style); - let text_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - if text_area.height < 1 { - return; - } - - let style = self.style; - let mut styled = self.text.lines.iter().flat_map(|spans| { - spans - .0 - .iter() - .flat_map(|span| span.styled_graphemes(style)) - // Required given the way composers work but might be refactored out if we change - // composers to operate on lines instead of a stream of graphemes. - .chain(iter::once(StyledGrapheme { - symbol: "\n", - style: self.style, - })) - }); - - let mut line_composer: Box = if let Some(Wrap { trim }) = self.wrap { - Box::new(WordWrapper::new(&mut styled, text_area.width, trim)) - } else { - let mut line_composer = Box::new(LineTruncator::new(&mut styled, text_area.width)); - if let Alignment::Left = self.alignment { - line_composer.set_horizontal_offset(self.scroll.1); - } - line_composer - }; - let mut y = 0; - while let Some((current_line, current_line_width)) = line_composer.next_line() { - if y >= self.scroll.0 { - let mut x = get_line_offset(current_line_width, text_area.width, self.alignment); - for StyledGrapheme { symbol, style } in current_line { - let width = symbol.width(); - if width == 0 { - continue; - } - buf.get_mut(text_area.left() + x, text_area.top() + y - self.scroll.0) - .set_symbol(if symbol.is_empty() { - // If the symbol is empty, the last char which rendered last time will - // leave on the line. It's a quick fix. - " " - } else { - symbol - }) - .set_style(*style); - x += width as u16; - } - } - y += 1; - if y >= text_area.height + self.scroll.0 { - break; - } - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn zero_width_char_at_end_of_line() { - let line = "foo\0"; - let paragraph = Paragraph::new(line); - let mut buf = Buffer::with_lines(vec![line]); - paragraph.render(*buf.area(), &mut buf); - } -} diff --git a/src/ratatui/widgets/reflow.rs b/src/ratatui/widgets/reflow.rs deleted file mode 100644 index 3806b33e..00000000 --- a/src/ratatui/widgets/reflow.rs +++ /dev/null @@ -1,534 +0,0 @@ -use crate::ratatui::text::StyledGrapheme; -use unicode_segmentation::UnicodeSegmentation; -use unicode_width::UnicodeWidthStr; - -const NBSP: &str = "\u{00a0}"; - -/// A state machine to pack styled symbols into lines. -/// Cannot implement it as Iterator since it yields slices of the internal buffer (need streaming -/// iterators for that). -pub trait LineComposer<'a> { - fn next_line(&mut self) -> Option<(&[StyledGrapheme<'a>], u16)>; -} - -/// A state machine that wraps lines on word boundaries. -pub struct WordWrapper<'a, 'b> { - symbols: &'b mut dyn Iterator>, - max_line_width: u16, - current_line: Vec>, - next_line: Vec>, - /// Removes the leading whitespace from lines - trim: bool, -} - -impl<'a, 'b> WordWrapper<'a, 'b> { - pub fn new( - symbols: &'b mut dyn Iterator>, - max_line_width: u16, - trim: bool, - ) -> WordWrapper<'a, 'b> { - WordWrapper { - symbols, - max_line_width, - current_line: vec![], - next_line: vec![], - trim, - } - } -} - -impl<'a, 'b> LineComposer<'a> for WordWrapper<'a, 'b> { - fn next_line(&mut self) -> Option<(&[StyledGrapheme<'a>], u16)> { - if self.max_line_width == 0 { - return None; - } - std::mem::swap(&mut self.current_line, &mut self.next_line); - self.next_line.truncate(0); - - let mut current_line_width = self - .current_line - .iter() - .map(|StyledGrapheme { symbol, .. }| symbol.width() as u16) - .sum(); - - let mut symbols_to_last_word_end: usize = 0; - let mut width_to_last_word_end: u16 = 0; - let mut prev_whitespace = false; - let mut symbols_exhausted = true; - for StyledGrapheme { symbol, style } in &mut self.symbols { - symbols_exhausted = false; - let symbol_whitespace = symbol.chars().all(&char::is_whitespace) && symbol != NBSP; - - // Ignore characters wider that the total max width. - if symbol.width() as u16 > self.max_line_width - // Skip leading whitespace when trim is enabled. - || self.trim && symbol_whitespace && symbol != "\n" && current_line_width == 0 - { - continue; - } - - // Break on newline and discard it. - if symbol == "\n" { - if prev_whitespace { - current_line_width = width_to_last_word_end; - self.current_line.truncate(symbols_to_last_word_end); - } - break; - } - - // Mark the previous symbol as word end. - if symbol_whitespace && !prev_whitespace { - symbols_to_last_word_end = self.current_line.len(); - width_to_last_word_end = current_line_width; - } - - self.current_line.push(StyledGrapheme { symbol, style }); - current_line_width += symbol.width() as u16; - - if current_line_width > self.max_line_width { - // If there was no word break in the text, wrap at the end of the line. - let (truncate_at, truncated_width) = if symbols_to_last_word_end != 0 { - (symbols_to_last_word_end, width_to_last_word_end) - } else { - (self.current_line.len() - 1, self.max_line_width) - }; - - // Push the remainder to the next line but strip leading whitespace: - { - let remainder = &self.current_line[truncate_at..]; - if let Some(remainder_nonwhite) = - remainder.iter().position(|StyledGrapheme { symbol, .. }| { - !symbol.chars().all(&char::is_whitespace) - }) - { - self.next_line - .extend_from_slice(&remainder[remainder_nonwhite..]); - } - } - self.current_line.truncate(truncate_at); - current_line_width = truncated_width; - break; - } - - prev_whitespace = symbol_whitespace; - } - - // Even if the iterator is exhausted, pass the previous remainder. - if symbols_exhausted && self.current_line.is_empty() { - None - } else { - Some((&self.current_line[..], current_line_width)) - } - } -} - -/// A state machine that truncates overhanging lines. -pub struct LineTruncator<'a, 'b> { - symbols: &'b mut dyn Iterator>, - max_line_width: u16, - current_line: Vec>, - /// Record the offset to skip render - horizontal_offset: u16, -} - -impl<'a, 'b> LineTruncator<'a, 'b> { - pub fn new( - symbols: &'b mut dyn Iterator>, - max_line_width: u16, - ) -> LineTruncator<'a, 'b> { - LineTruncator { - symbols, - max_line_width, - horizontal_offset: 0, - current_line: vec![], - } - } - - pub fn set_horizontal_offset(&mut self, horizontal_offset: u16) { - self.horizontal_offset = horizontal_offset; - } -} - -impl<'a, 'b> LineComposer<'a> for LineTruncator<'a, 'b> { - fn next_line(&mut self) -> Option<(&[StyledGrapheme<'a>], u16)> { - if self.max_line_width == 0 { - return None; - } - - self.current_line.truncate(0); - let mut current_line_width = 0; - - let mut skip_rest = false; - let mut symbols_exhausted = true; - let mut horizontal_offset = self.horizontal_offset as usize; - for StyledGrapheme { symbol, style } in &mut self.symbols { - symbols_exhausted = false; - - // Ignore characters wider that the total max width. - if symbol.width() as u16 > self.max_line_width { - continue; - } - - // Break on newline and discard it. - if symbol == "\n" { - break; - } - - if current_line_width + symbol.width() as u16 > self.max_line_width { - // Exhaust the remainder of the line. - skip_rest = true; - break; - } - - let symbol = if horizontal_offset == 0 { - symbol - } else { - let w = symbol.width(); - if w > horizontal_offset { - let t = trim_offset(symbol, horizontal_offset); - horizontal_offset = 0; - t - } else { - horizontal_offset -= w; - "" - } - }; - current_line_width += symbol.width() as u16; - self.current_line.push(StyledGrapheme { symbol, style }); - } - - if skip_rest { - for StyledGrapheme { symbol, .. } in &mut self.symbols { - if symbol == "\n" { - break; - } - } - } - - if symbols_exhausted && self.current_line.is_empty() { - None - } else { - Some((&self.current_line[..], current_line_width)) - } - } -} - -/// This function will return a str slice which start at specified offset. -/// As src is a unicode str, start offset has to be calculated with each character. -fn trim_offset(src: &str, mut offset: usize) -> &str { - let mut start = 0; - for c in UnicodeSegmentation::graphemes(src, true) { - let w = c.width(); - if w <= offset { - offset -= w; - start += c.len(); - } else { - break; - } - } - &src[start..] -} - -#[cfg(test)] -mod test { - use super::*; - use unicode_segmentation::UnicodeSegmentation; - - enum Composer { - WordWrapper { trim: bool }, - LineTruncator, - } - - fn run_composer(which: Composer, text: &str, text_area_width: u16) -> (Vec, Vec) { - let style = Default::default(); - let mut styled = - UnicodeSegmentation::graphemes(text, true).map(|g| StyledGrapheme { symbol: g, style }); - let mut composer: Box = match which { - Composer::WordWrapper { trim } => { - Box::new(WordWrapper::new(&mut styled, text_area_width, trim)) - } - Composer::LineTruncator => Box::new(LineTruncator::new(&mut styled, text_area_width)), - }; - let mut lines = vec![]; - let mut widths = vec![]; - while let Some((styled, width)) = composer.next_line() { - let line = styled - .iter() - .map(|StyledGrapheme { symbol, .. }| *symbol) - .collect::(); - assert!(width <= text_area_width); - lines.push(line); - widths.push(width); - } - (lines, widths) - } - - #[test] - fn line_composer_one_line() { - let width = 40; - for i in 1..width { - let text = "a".repeat(i); - let (word_wrapper, _) = - run_composer(Composer::WordWrapper { trim: true }, &text, width as u16); - let (line_truncator, _) = run_composer(Composer::LineTruncator, &text, width as u16); - let expected = vec![text]; - assert_eq!(word_wrapper, expected); - assert_eq!(line_truncator, expected); - } - } - - #[test] - fn line_composer_short_lines() { - let width = 20; - let text = - "abcdefg\nhijklmno\npabcdefg\nhijklmn\nopabcdefghijk\nlmnopabcd\n\n\nefghijklmno"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - - let wrapped: Vec<&str> = text.split('\n').collect(); - assert_eq!(word_wrapper, wrapped); - assert_eq!(line_truncator, wrapped); - } - - #[test] - fn line_composer_long_word() { - let width = 20; - let text = "abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmno"; - let (word_wrapper, _) = - run_composer(Composer::WordWrapper { trim: true }, text, width as u16); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width as u16); - - let wrapped = vec![ - &text[..width], - &text[width..width * 2], - &text[width * 2..width * 3], - &text[width * 3..], - ]; - assert_eq!( - word_wrapper, wrapped, - "WordWrapper should detect the line cannot be broken on word boundary and \ - break it at line width limit." - ); - assert_eq!(line_truncator, vec![&text[..width]]); - } - - #[test] - fn line_composer_long_sentence() { - let width = 20; - let text = - "abcd efghij klmnopabcd efgh ijklmnopabcdefg hijkl mnopab c d e f g h i j k l m n o"; - let text_multi_space = - "abcd efghij klmnopabcd efgh ijklmnopabcdefg hijkl mnopab c d e f g h i j k l \ - m n o"; - let (word_wrapper_single_space, _) = - run_composer(Composer::WordWrapper { trim: true }, text, width as u16); - let (word_wrapper_multi_space, _) = run_composer( - Composer::WordWrapper { trim: true }, - text_multi_space, - width as u16, - ); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width as u16); - - let word_wrapped = vec![ - "abcd efghij", - "klmnopabcd efgh", - "ijklmnopabcdefg", - "hijkl mnopab c d e f", - "g h i j k l m n o", - ]; - assert_eq!(word_wrapper_single_space, word_wrapped); - assert_eq!(word_wrapper_multi_space, word_wrapped); - - assert_eq!(line_truncator, vec![&text[..width]]); - } - - #[test] - fn line_composer_zero_width() { - let width = 0; - let text = "abcd efghij klmnopabcd efgh ijklmnopabcdefg hijkl mnopab "; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - - let expected: Vec<&str> = Vec::new(); - assert_eq!(word_wrapper, expected); - assert_eq!(line_truncator, expected); - } - - #[test] - fn line_composer_max_line_width_of_1() { - let width = 1; - let text = "abcd efghij klmnopabcd efgh ijklmnopabcdefg hijkl mnopab "; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - - let expected: Vec<&str> = UnicodeSegmentation::graphemes(text, true) - .filter(|g| g.chars().any(|c| !c.is_whitespace())) - .collect(); - assert_eq!(word_wrapper, expected); - assert_eq!(line_truncator, vec!["a"]); - } - - #[test] - fn line_composer_max_line_width_of_1_double_width_characters() { - let width = 1; - let text = "コンピュータ上で文字を扱う場合、典型的には文字\naaaによる通信を行う場合にその\ - 両端点では、"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - assert_eq!(word_wrapper, vec!["", "a", "a", "a"]); - assert_eq!(line_truncator, vec!["", "a"]); - } - - /// Tests WordWrapper with words some of which exceed line length and some not. - #[test] - fn line_composer_word_wrapper_mixed_length() { - let width = 20; - let text = "abcd efghij klmnopabcdefghijklmnopabcdefghijkl mnopab cdefghi j klmno"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - assert_eq!( - word_wrapper, - vec![ - "abcd efghij", - "klmnopabcdefghijklmn", - "opabcdefghijkl", - "mnopab cdefghi j", - "klmno", - ] - ) - } - - #[test] - fn line_composer_double_width_chars() { - let width = 20; - let text = "コンピュータ上で文字を扱う場合、典型的には文字による通信を行う場合にその両端点\ - では、"; - let (word_wrapper, word_wrapper_width) = - run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - assert_eq!(line_truncator, vec!["コンピュータ上で文字"]); - let wrapped = vec![ - "コンピュータ上で文字", - "を扱う場合、典型的に", - "は文字による通信を行", - "う場合にその両端点で", - "は、", - ]; - assert_eq!(word_wrapper, wrapped); - assert_eq!(word_wrapper_width, vec![width, width, width, width, 4]); - } - - #[test] - fn line_composer_leading_whitespace_removal() { - let width = 20; - let text = "AAAAAAAAAAAAAAAAAAAA AAA"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - assert_eq!(word_wrapper, vec!["AAAAAAAAAAAAAAAAAAAA", "AAA",]); - assert_eq!(line_truncator, vec!["AAAAAAAAAAAAAAAAAAAA"]); - } - - /// Tests truncation of leading whitespace. - #[test] - fn line_composer_lots_of_spaces() { - let width = 20; - let text = " "; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - assert_eq!(word_wrapper, vec![""]); - assert_eq!(line_truncator, vec![" "]); - } - - /// Tests an input starting with a letter, followed by spaces - some of the behaviour is - /// incidental. - #[test] - fn line_composer_char_plus_lots_of_spaces() { - let width = 20; - let text = "a "; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - let (line_truncator, _) = run_composer(Composer::LineTruncator, text, width); - // What's happening below is: the first line gets consumed, trailing spaces discarded, - // after 20 of which a word break occurs (probably shouldn't). The second line break - // discards all whitespace. The result should probably be vec!["a"] but it doesn't matter - // that much. - assert_eq!(word_wrapper, vec!["a", ""]); - assert_eq!(line_truncator, vec!["a "]); - } - - #[test] - fn line_composer_word_wrapper_double_width_chars_mixed_with_spaces() { - let width = 20; - // Japanese seems not to use spaces but we should break on spaces anyway... We're using it - // to test double-width chars. - // You are more than welcome to add word boundary detection based of alterations of - // hiragana and katakana... - // This happens to also be a test case for mixed width because regular spaces are single width. - let text = "コンピュ ータ上で文字を扱う場合、 典型的には文 字による 通信を行 う場合にその両端点では、"; - let (word_wrapper, word_wrapper_width) = - run_composer(Composer::WordWrapper { trim: true }, text, width); - assert_eq!( - word_wrapper, - vec![ - "コンピュ", - "ータ上で文字を扱う場", - "合、 典型的には文", - "字による 通信を行", - "う場合にその両端点で", - "は、", - ] - ); - // Odd-sized lines have a space in them. - assert_eq!(word_wrapper_width, vec![8, 20, 17, 17, 20, 4]); - } - - /// Ensure words separated by nbsp are wrapped as if they were a single one. - #[test] - fn line_composer_word_wrapper_nbsp() { - let width = 20; - let text = "AAAAAAAAAAAAAAA AAAA\u{00a0}AAA"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: true }, text, width); - assert_eq!(word_wrapper, vec!["AAAAAAAAAAAAAAA", "AAAA\u{00a0}AAA",]); - - // Ensure that if the character was a regular space, it would be wrapped differently. - let text_space = text.replace('\u{00a0}', " "); - let (word_wrapper_space, _) = - run_composer(Composer::WordWrapper { trim: true }, &text_space, width); - assert_eq!(word_wrapper_space, vec!["AAAAAAAAAAAAAAA AAAA", "AAA",]); - } - - #[test] - fn line_composer_word_wrapper_preserve_indentation() { - let width = 20; - let text = "AAAAAAAAAAAAAAAAAAAA AAA"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: false }, text, width); - assert_eq!(word_wrapper, vec!["AAAAAAAAAAAAAAAAAAAA", " AAA",]); - } - - #[test] - fn line_composer_word_wrapper_preserve_indentation_with_wrap() { - let width = 10; - let text = "AAA AAA AAAAA AA AAAAAA\n B\n C\n D"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: false }, text, width); - assert_eq!( - word_wrapper, - vec!["AAA AAA", "AAAAA AA", "AAAAAA", " B", " C", " D"] - ); - } - - #[test] - fn line_composer_word_wrapper_preserve_indentation_lots_of_whitespace() { - let width = 10; - let text = " 4 Indent\n must wrap!"; - let (word_wrapper, _) = run_composer(Composer::WordWrapper { trim: false }, text, width); - assert_eq!( - word_wrapper, - vec![ - " ", - " 4", - "Indent", - " ", - " must", - "wrap!" - ] - ); - } -} diff --git a/src/ratatui/widgets/sparkline.rs b/src/ratatui/widgets/sparkline.rs deleted file mode 100644 index a05df112..00000000 --- a/src/ratatui/widgets/sparkline.rs +++ /dev/null @@ -1,155 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::Rect, - style::Style, - symbols, - widgets::{Block, Widget}, -}; -use std::cmp::min; - -/// Widget to render a sparkline over one or more lines. -/// -/// # Examples -/// -/// ``` -/// # use ratatui::widgets::{Block, Borders, Sparkline}; -/// # use ratatui::style::{Style, Color}; -/// Sparkline::default() -/// .block(Block::default().title("Sparkline").borders(Borders::ALL)) -/// .data(&[0, 2, 3, 4, 1, 4, 10]) -/// .max(5) -/// .style(Style::default().fg(Color::Red).bg(Color::White)); -/// ``` -#[derive(Debug, Clone)] -pub struct Sparkline<'a> { - /// A block to wrap the widget in - block: Option>, - /// Widget style - style: Style, - /// A slice of the data to display - data: &'a [u64], - /// The maximum value to take to compute the maximum bar height (if nothing is specified, the - /// widget uses the max of the dataset) - max: Option, - /// A set of bar symbols used to represent the give data - bar_set: symbols::bar::Set, -} - -impl<'a> Default for Sparkline<'a> { - fn default() -> Sparkline<'a> { - Sparkline { - block: None, - style: Default::default(), - data: &[], - max: None, - bar_set: symbols::bar::NINE_LEVELS, - } - } -} - -impl<'a> Sparkline<'a> { - pub fn block(mut self, block: Block<'a>) -> Sparkline<'a> { - self.block = Some(block); - self - } - - pub fn style(mut self, style: Style) -> Sparkline<'a> { - self.style = style; - self - } - - pub fn data(mut self, data: &'a [u64]) -> Sparkline<'a> { - self.data = data; - self - } - - pub fn max(mut self, max: u64) -> Sparkline<'a> { - self.max = Some(max); - self - } - - pub fn bar_set(mut self, bar_set: symbols::bar::Set) -> Sparkline<'a> { - self.bar_set = bar_set; - self - } -} - -impl<'a> Widget for Sparkline<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - let spark_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - if spark_area.height < 1 { - return; - } - - let max = match self.max { - Some(v) => v, - None => *self.data.iter().max().unwrap_or(&1u64), - }; - let max_index = min(spark_area.width as usize, self.data.len()); - let mut data = self - .data - .iter() - .take(max_index) - .map(|e| { - if max != 0 { - e * u64::from(spark_area.height) * 8 / max - } else { - 0 - } - }) - .collect::>(); - for j in (0..spark_area.height).rev() { - for (i, d) in data.iter_mut().enumerate() { - let symbol = match *d { - 0 => self.bar_set.empty, - 1 => self.bar_set.one_eighth, - 2 => self.bar_set.one_quarter, - 3 => self.bar_set.three_eighths, - 4 => self.bar_set.half, - 5 => self.bar_set.five_eighths, - 6 => self.bar_set.three_quarters, - 7 => self.bar_set.seven_eighths, - _ => self.bar_set.full, - }; - buf.get_mut(spark_area.left() + i as u16, spark_area.top() + j) - .set_symbol(symbol) - .set_style(self.style); - - if *d > 8 { - *d -= 8; - } else { - *d = 0; - } - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_does_not_panic_if_max_is_zero() { - let widget = Sparkline::default().data(&[0, 0, 0]); - let area = Rect::new(0, 0, 3, 1); - let mut buffer = Buffer::empty(area); - widget.render(area, &mut buffer); - } - - #[test] - fn it_does_not_panic_if_max_is_set_to_zero() { - let widget = Sparkline::default().data(&[0, 1, 2]).max(0); - let area = Rect::new(0, 0, 3, 1); - let mut buffer = Buffer::empty(area); - widget.render(area, &mut buffer); - } -} diff --git a/src/ratatui/widgets/table.rs b/src/ratatui/widgets/table.rs deleted file mode 100644 index d987a8d9..00000000 --- a/src/ratatui/widgets/table.rs +++ /dev/null @@ -1,504 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::{Constraint, Direction, Layout, Rect}, - style::Style, - text::Text, - widgets::{Block, StatefulWidget, Widget}, -}; -use unicode_width::UnicodeWidthStr; - -/// A [`Cell`] contains the [`Text`] to be displayed in a [`Row`] of a [`Table`]. -/// -/// It can be created from anything that can be converted to a [`Text`]. -/// ```rust -/// # use ratatui::widgets::Cell; -/// # use ratatui::style::{Style, Modifier}; -/// # use ratatui::text::{Span, Spans, Text}; -/// # use std::borrow::Cow; -/// Cell::from("simple string"); -/// -/// Cell::from(Span::from("span")); -/// -/// Cell::from(Spans::from(vec![ -/// Span::raw("a vec of "), -/// Span::styled("spans", Style::default().add_modifier(Modifier::BOLD)) -/// ])); -/// -/// Cell::from(Text::from("a text")); -/// -/// Cell::from(Text::from(Cow::Borrowed("hello"))); -/// ``` -/// -/// You can apply a [`Style`] on the entire [`Cell`] using [`Cell::style`] or rely on the styling -/// capabilities of [`Text`]. -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct Cell<'a> { - content: Text<'a>, - style: Style, -} - -impl<'a> Cell<'a> { - /// Set the `Style` of this cell. - pub fn style(mut self, style: Style) -> Self { - self.style = style; - self - } -} - -impl<'a, T> From for Cell<'a> -where - T: Into>, -{ - fn from(content: T) -> Cell<'a> { - Cell { - content: content.into(), - style: Style::default(), - } - } -} - -/// Holds data to be displayed in a [`Table`] widget. -/// -/// A [`Row`] is a collection of cells. It can be created from simple strings: -/// ```rust -/// # use ratatui::widgets::Row; -/// Row::new(vec!["Cell1", "Cell2", "Cell3"]); -/// ``` -/// -/// But if you need a bit more control over individual cells, you can explicitly create [`Cell`]s: -/// ```rust -/// # use ratatui::widgets::{Row, Cell}; -/// # use ratatui::style::{Style, Color}; -/// Row::new(vec![ -/// Cell::from("Cell1"), -/// Cell::from("Cell2").style(Style::default().fg(Color::Yellow)), -/// ]); -/// ``` -/// -/// You can also construct a row from any type that can be converted into [`Text`]: -/// ```rust -/// # use std::borrow::Cow; -/// # use ratatui::widgets::Row; -/// Row::new(vec![ -/// Cow::Borrowed("hello"), -/// Cow::Owned("world".to_uppercase()), -/// ]); -/// ``` -/// -/// By default, a row has a height of 1 but you can change this using [`Row::height`]. -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct Row<'a> { - cells: Vec>, - height: u16, - style: Style, - bottom_margin: u16, -} - -impl<'a> Row<'a> { - /// Creates a new [`Row`] from an iterator where items can be converted to a [`Cell`]. - pub fn new(cells: T) -> Self - where - T: IntoIterator, - T::Item: Into>, - { - Self { - height: 1, - cells: cells.into_iter().map(|c| c.into()).collect(), - style: Style::default(), - bottom_margin: 0, - } - } - - /// Set the fixed height of the [`Row`]. Any [`Cell`] whose content has more lines than this - /// height will see its content truncated. - pub fn height(mut self, height: u16) -> Self { - self.height = height; - self - } - - /// Set the [`Style`] of the entire row. This [`Style`] can be overridden by the [`Style`] of a - /// any individual [`Cell`] or event by their [`Text`] content. - pub fn style(mut self, style: Style) -> Self { - self.style = style; - self - } - - /// Set the bottom margin. By default, the bottom margin is `0`. - pub fn bottom_margin(mut self, margin: u16) -> Self { - self.bottom_margin = margin; - self - } - - /// Returns the total height of the row. - fn total_height(&self) -> u16 { - self.height.saturating_add(self.bottom_margin) - } -} - -/// A widget to display data in formatted columns. -/// -/// It is a collection of [`Row`]s, themselves composed of [`Cell`]s: -/// ```rust -/// # use ratatui::widgets::{Block, Borders, Table, Row, Cell}; -/// # use ratatui::layout::Constraint; -/// # use ratatui::style::{Style, Color, Modifier}; -/// # use ratatui::text::{Text, Spans, Span}; -/// Table::new(vec![ -/// // Row can be created from simple strings. -/// Row::new(vec!["Row11", "Row12", "Row13"]), -/// // You can style the entire row. -/// Row::new(vec!["Row21", "Row22", "Row23"]).style(Style::default().fg(Color::Blue)), -/// // If you need more control over the styling you may need to create Cells directly -/// Row::new(vec![ -/// Cell::from("Row31"), -/// Cell::from("Row32").style(Style::default().fg(Color::Yellow)), -/// Cell::from(Spans::from(vec![ -/// Span::raw("Row"), -/// Span::styled("33", Style::default().fg(Color::Green)) -/// ])), -/// ]), -/// // If a Row need to display some content over multiple lines, you just have to change -/// // its height. -/// Row::new(vec![ -/// Cell::from("Row\n41"), -/// Cell::from("Row\n42"), -/// Cell::from("Row\n43"), -/// ]).height(2), -/// ]) -/// // You can set the style of the entire Table. -/// .style(Style::default().fg(Color::White)) -/// // It has an optional header, which is simply a Row always visible at the top. -/// .header( -/// Row::new(vec!["Col1", "Col2", "Col3"]) -/// .style(Style::default().fg(Color::Yellow)) -/// // If you want some space between the header and the rest of the rows, you can always -/// // specify some margin at the bottom. -/// .bottom_margin(1) -/// ) -/// // As any other widget, a Table can be wrapped in a Block. -/// .block(Block::default().title("Table")) -/// // Columns widths are constrained in the same way as Layout... -/// .widths(&[Constraint::Length(5), Constraint::Length(5), Constraint::Length(10)]) -/// // ...and they can be separated by a fixed spacing. -/// .column_spacing(1) -/// // If you wish to highlight a row in any specific way when it is selected... -/// .highlight_style(Style::default().add_modifier(Modifier::BOLD)) -/// // ...and potentially show a symbol in front of the selection. -/// .highlight_symbol(">>"); -/// ``` -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Table<'a> { - /// A block to wrap the widget in - block: Option>, - /// Base style for the widget - style: Style, - /// Width constraints for each column - widths: &'a [Constraint], - /// Space between each column - column_spacing: u16, - /// Style used to render the selected row - highlight_style: Style, - /// Symbol in front of the selected rom - highlight_symbol: Option<&'a str>, - /// Optional header - header: Option>, - /// Data to display in each row - rows: Vec>, -} - -impl<'a> Table<'a> { - pub fn new(rows: T) -> Self - where - T: IntoIterator>, - { - Self { - block: None, - style: Style::default(), - widths: &[], - column_spacing: 1, - highlight_style: Style::default(), - highlight_symbol: None, - header: None, - rows: rows.into_iter().collect(), - } - } - - pub fn block(mut self, block: Block<'a>) -> Self { - self.block = Some(block); - self - } - - pub fn header(mut self, header: Row<'a>) -> Self { - self.header = Some(header); - self - } - - pub fn widths(mut self, widths: &'a [Constraint]) -> Self { - let between_0_and_100 = |&w| match w { - Constraint::Percentage(p) => p <= 100, - _ => true, - }; - assert!( - widths.iter().all(between_0_and_100), - "Percentages should be between 0 and 100 inclusively." - ); - self.widths = widths; - self - } - - pub fn style(mut self, style: Style) -> Self { - self.style = style; - self - } - - pub fn highlight_symbol(mut self, highlight_symbol: &'a str) -> Self { - self.highlight_symbol = Some(highlight_symbol); - self - } - - pub fn highlight_style(mut self, highlight_style: Style) -> Self { - self.highlight_style = highlight_style; - self - } - - pub fn column_spacing(mut self, spacing: u16) -> Self { - self.column_spacing = spacing; - self - } - - fn get_columns_widths(&self, max_width: u16, has_selection: bool) -> Vec { - let mut constraints = Vec::with_capacity(self.widths.len() * 2 + 1); - if has_selection { - let highlight_symbol_width = - self.highlight_symbol.map(|s| s.width() as u16).unwrap_or(0); - constraints.push(Constraint::Length(highlight_symbol_width)); - } - for constraint in self.widths { - constraints.push(*constraint); - constraints.push(Constraint::Length(self.column_spacing)); - } - if !self.widths.is_empty() { - constraints.pop(); - } - let chunks = Layout::default() - .direction(Direction::Horizontal) - .constraints(constraints) - .expand_to_fill(false) - .split(Rect { - x: 0, - y: 0, - width: max_width, - height: 1, - }); - let mut chunks = &chunks[..]; - if has_selection { - chunks = &chunks[1..]; - } - chunks.iter().step_by(2).map(|c| c.width).collect() - } - - fn get_row_bounds( - &self, - selected: Option, - offset: usize, - max_height: u16, - ) -> (usize, usize) { - let offset = offset.min(self.rows.len().saturating_sub(1)); - let mut start = offset; - let mut end = offset; - let mut height = 0; - for item in self.rows.iter().skip(offset) { - if height + item.height > max_height { - break; - } - height += item.total_height(); - end += 1; - } - - let selected = selected.unwrap_or(0).min(self.rows.len() - 1); - while selected >= end { - height = height.saturating_add(self.rows[end].total_height()); - end += 1; - while height > max_height { - height = height.saturating_sub(self.rows[start].total_height()); - start += 1; - } - } - while selected < start { - start -= 1; - height = height.saturating_add(self.rows[start].total_height()); - while height > max_height { - end -= 1; - height = height.saturating_sub(self.rows[end].total_height()); - } - } - (start, end) - } -} - -#[derive(Debug, Clone, Default)] -pub struct TableState { - offset: usize, - selected: Option, -} - -impl TableState { - pub fn selected(&self) -> Option { - self.selected - } - - pub fn select(&mut self, index: Option) { - self.selected = index; - if index.is_none() { - self.offset = 0; - } - } - - /// Returns a copy of the receiver's scroll offset. - /// - /// This is useful, for example, if you need to "synchronize" the scrolling of a `Table` and a `Paragraph`. - pub fn offset(&self) -> usize { - self.offset - } -} - -impl<'a> StatefulWidget for Table<'a> { - type State = TableState; - - fn render(mut self, area: Rect, buf: &mut Buffer, state: &mut Self::State) { - if area.area() == 0 { - return; - } - buf.set_style(area, self.style); - let table_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - let has_selection = state.selected.is_some(); - let columns_widths = self.get_columns_widths(table_area.width, has_selection); - let highlight_symbol = self.highlight_symbol.unwrap_or(""); - let blank_symbol = " ".repeat(highlight_symbol.width()); - let mut current_height = 0; - let mut rows_height = table_area.height; - - // Draw header - if let Some(ref header) = self.header { - let max_header_height = table_area.height.min(header.total_height()); - buf.set_style( - Rect { - x: table_area.left(), - y: table_area.top(), - width: table_area.width, - height: table_area.height.min(header.height), - }, - header.style, - ); - let mut col = table_area.left(); - if has_selection { - col += (highlight_symbol.width() as u16).min(table_area.width); - } - for (width, cell) in columns_widths.iter().zip(header.cells.iter()) { - render_cell( - buf, - cell, - Rect { - x: col, - y: table_area.top(), - width: *width, - height: max_header_height, - }, - ); - col += *width + self.column_spacing; - } - current_height += max_header_height; - rows_height = rows_height.saturating_sub(max_header_height); - } - - // Draw rows - if self.rows.is_empty() { - return; - } - let (start, end) = self.get_row_bounds(state.selected, state.offset, rows_height); - state.offset = start; - for (i, table_row) in self - .rows - .iter_mut() - .enumerate() - .skip(state.offset) - .take(end - start) - { - let (row, col) = (table_area.top() + current_height, table_area.left()); - current_height += table_row.total_height(); - let table_row_area = Rect { - x: col, - y: row, - width: table_area.width, - height: table_row.height, - }; - buf.set_style(table_row_area, table_row.style); - let is_selected = state.selected.map(|s| s == i).unwrap_or(false); - let table_row_start_col = if has_selection { - let symbol = if is_selected { - highlight_symbol - } else { - &blank_symbol - }; - let (col, _) = - buf.set_stringn(col, row, symbol, table_area.width as usize, table_row.style); - col - } else { - col - }; - let mut col = table_row_start_col; - for (width, cell) in columns_widths.iter().zip(table_row.cells.iter()) { - render_cell( - buf, - cell, - Rect { - x: col, - y: row, - width: *width, - height: table_row.height, - }, - ); - col += *width + self.column_spacing; - } - if is_selected { - buf.set_style(table_row_area, self.highlight_style); - } - } - } -} - -fn render_cell(buf: &mut Buffer, cell: &Cell, area: Rect) { - buf.set_style(area, cell.style); - for (i, spans) in cell.content.lines.iter().enumerate() { - if i as u16 >= area.height { - break; - } - buf.set_spans(area.x, area.y + i as u16, spans, area.width); - } -} - -impl<'a> Widget for Table<'a> { - fn render(self, area: Rect, buf: &mut Buffer) { - let mut state = TableState::default(); - StatefulWidget::render(self, area, buf, &mut state); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[should_panic] - fn table_invalid_percentages() { - Table::new(vec![]).widths(&[Constraint::Percentage(110)]); - } -} diff --git a/src/ratatui/widgets/tabs.rs b/src/ratatui/widgets/tabs.rs deleted file mode 100644 index 9b5f5469..00000000 --- a/src/ratatui/widgets/tabs.rs +++ /dev/null @@ -1,129 +0,0 @@ -use crate::ratatui::{ - buffer::Buffer, - layout::Rect, - style::Style, - symbols, - text::{Span, Spans}, - widgets::{Block, Widget}, -}; - -/// A widget to display available tabs in a multiple panels context. -/// -/// # Examples -/// -/// ``` -/// # use ratatui::widgets::{Block, Borders, Tabs}; -/// # use ratatui::style::{Style, Color}; -/// # use ratatui::text::{Spans}; -/// # use ratatui::symbols::{DOT}; -/// let titles = ["Tab1", "Tab2", "Tab3", "Tab4"].iter().cloned().map(Spans::from).collect(); -/// Tabs::new(titles) -/// .block(Block::default().title("Tabs").borders(Borders::ALL)) -/// .style(Style::default().fg(Color::White)) -/// .highlight_style(Style::default().fg(Color::Yellow)) -/// .divider(DOT); -/// ``` -#[derive(Debug, Clone)] -pub struct Tabs<'a> { - /// A block to wrap this widget in if necessary - block: Option>, - /// One title for each tab - titles: Vec>, - /// The index of the selected tabs - selected: usize, - /// The style used to draw the text - style: Style, - /// Style to apply to the selected item - highlight_style: Style, - /// Tab divider - divider: Span<'a>, -} - -impl<'a> Tabs<'a> { - pub fn new(titles: Vec>) -> Tabs<'a> { - Tabs { - block: None, - titles, - selected: 0, - style: Default::default(), - highlight_style: Default::default(), - divider: Span::raw(symbols::line::VERTICAL), - } - } - - pub fn block(mut self, block: Block<'a>) -> Tabs<'a> { - self.block = Some(block); - self - } - - pub fn select(mut self, selected: usize) -> Tabs<'a> { - self.selected = selected; - self - } - - pub fn style(mut self, style: Style) -> Tabs<'a> { - self.style = style; - self - } - - pub fn highlight_style(mut self, style: Style) -> Tabs<'a> { - self.highlight_style = style; - self - } - - pub fn divider(mut self, divider: T) -> Tabs<'a> - where - T: Into>, - { - self.divider = divider.into(); - self - } -} - -impl<'a> Widget for Tabs<'a> { - fn render(mut self, area: Rect, buf: &mut Buffer) { - buf.set_style(area, self.style); - let tabs_area = match self.block.take() { - Some(b) => { - let inner_area = b.inner(area); - b.render(area, buf); - inner_area - } - None => area, - }; - - if tabs_area.height < 1 { - return; - } - - let mut x = tabs_area.left(); - let titles_length = self.titles.len(); - for (i, title) in self.titles.into_iter().enumerate() { - let last_title = titles_length - 1 == i; - x = x.saturating_add(1); - let remaining_width = tabs_area.right().saturating_sub(x); - if remaining_width == 0 { - break; - } - let pos = buf.set_spans(x, tabs_area.top(), &title, remaining_width); - if i == self.selected { - buf.set_style( - Rect { - x, - y: tabs_area.top(), - width: pos.0.saturating_sub(x), - height: 1, - }, - self.highlight_style, - ); - } - x = pos.0.saturating_add(1); - let remaining_width = tabs_area.right().saturating_sub(x); - if remaining_width == 0 || last_title { - break; - } - let pos = buf.set_span(x, tabs_area.top(), &self.divider, remaining_width); - x = pos.0; - } - } -} -- cgit v1.3.1