use crate::{
buffer::{CellBuffer, Contacts, Span},
fragment,
fragment::Arc,
fragment::Circle,
Cell, Point, Settings,
};
use indexmap::IndexMap;
use lazy_static::lazy_static;
use std::{collections::BTreeMap, collections::HashMap, iter::FromIterator};
/// skip the first 3 circles for constructing our arcs, otherwise it will just be a mess
pub const CIRCLES_TO_SKIP_FOR_ARC: usize = 3;
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
/// edge cases of the circle art
pub enum Horizontal {
/// circle arc is touching the left edge of the first cell
/// ie: if the left most cell is `/` then it is touching the dge
LeftEdge,
/// if the left most cell is `(` or `|` then it starts at half the cell
Half,
}
pub struct CircleArt {
/// the ascii art of the circel
/// empty lines are ignored
/// empty vertical columns are ignored
ascii_art: &'static str,
start_edge: Horizontal,
/// distance in cell units, from the left edge of the ascii art to the center.x of the circle
offset_center_x: f32,
/// distance in cell units, from the top edge of the ascii art to the center.y of the circle
offset_center_y: f32,
}
impl CircleArt {
/// calculate the centel cell of this circle art
/// based on offset center
fn center_cell(&self) -> Cell {
let mut center_cell_x = self.offset_center_x - self.edge_increment_x();
// if no shared x (meaning even number of ascii art along x axis)
// we want to use the cell before it as the center cell
if !self.is_shared_x() {
center_cell_x -= 0.5;
}
let mut center_cell_y = self.offset_center_y;
if !self.is_shared_y() {
center_cell_y -= 0.5;
}
Cell::new(center_cell_x.floor() as i32, center_cell_y.floor() as i32)
}
/// returns the width in cells of the ascii art of this circle
fn width(&self) -> f32 {
let cb = CellBuffer::from(self.ascii_art);
let (lo, hi) = cb.bounds().expect("circle must have bounds");
match self.start_edge {
Horizontal::LeftEdge => (hi.x - lo.x) as f32 + 1.0,
Horizontal::Half => (hi.x - lo.x) as f32,
}
}
fn center(&self) -> Point {
let center_x = self.radius() + self.edge_increment_x();
let center_y = self.offset_center_y * 2.0;
Point::new(center_x, center_y)
}
fn edge_increment_x(&self) -> f32 {
match self.start_edge {
Horizontal::LeftEdge => 0.0,
Horizontal::Half => 0.5,
}
}
fn radius(&self) -> f32 {
self.width() / 2.0
}
fn diameter(&self) -> i32 {
(self.radius() * 2.0).floor() as i32
}
/// center cell at x will be shared if it is on the odd count
fn is_shared_x(&self) -> bool {
self.offset_center_x * 2.0 % 2.0 == 1.0
}
/// center cell at y will be shared if it is on the odd count
fn is_shared_y(&self) -> bool {
self.offset_center_y * 2.0 % 2.0 == 1.0
}
}
pub struct ArcSpans {
diameter: i32,
arc_spans: Vec<(Arc, Span)>,
is_shared_x: bool,
is_shared_y: bool,
}
// These are circle map, when a group is detected to have these set of characters
// arrange together in such this way, then endorse them as a circle
// Each of these character formation will have a certain circle parameters: center, and radius.
//
lazy_static! {
/// ```ignore
/// 0 1 2 3 4 B C D
/// 0┌─┬─┬─┬─┐ A┌─┬─┬─┬─┐E
/// 1├─┼─┼─┼─┤ │ │ │ │ │
/// 2├─┼─┼─┼─┤ F├─G─H─I─┤J
/// 3├─┼─┼─┼─┤ │ │ │ │ │
/// 4├─┼─┼─┼─┤ K├─L─M─N─┤O
/// 5├─┼─┼─┼─┤ │ │ │ │ │
/// 6├─┼─┼─┼─┤ P├─Q─R─S─┤T
/// 7├─┼─┼─┼─┤ │ │ │ │ │
/// 8└─┴─┴─┴─┘ U└─┴─┴─┴─┘Y
/// ``` V W X
/// (
/// art - the ascii art of the circle, the empty space is automatically removed
/// edge_case - where the edge from the left most cell of the circle
/// f32 - how many cell from the left most to the center.x of the circle
/// f32 - how many cell from the top most to the center.y of the circle,
/// Cell - center cell in arc2
/// )
static ref CIRCLE_ART_MAP: Vec<(&'static str, Horizontal, f32, f32, Cell)> =
vec![
// CIRCLE_1
//center 1,0,k, radius = 0.5
// 2 cell width , radius formula: (n-1)/2 = (2-1)/2 = 0.5
// where n is the number of cells used
// if edge_case starts at edge then n is added by 1.
// vert_mid: half (0.5/1.0)
// cx_lies: edge
// cy_lies: mid
//
// edge_case: start_half = 0.5, start_edge = 0.0
// if radius + edge_case has 0.5 then mid, 0.0 then edge
//
//
(r#"
()
"#, Horizontal::Half, 1.0, 0.5, Cell::new(0,0)),
// CIRCLE_2
//center = 1,1,m radius = 1.0
// 3 cell width, (n-1)/2 = (3-1)/2 = 1.0
// vert_mid: half (0.5/1.0)
// cx_lies: mid