use crate::{buffer::Cell, map::unicode_map::FRAGMENTS_UNICODE, Point};
pub use crate::{Property, Settings, Signal};
pub use arc::Arc;
pub use circle::Circle;
pub use line::Line;
pub use marker_line::{Marker, MarkerLine};
use ncollide2d::query::PointQuery;
use ncollide2d::{
bounding_volume::AABB,
math::Isometry,
query::{proximity, Proximity},
shape::{Polyline, Segment},
};
pub use polygon::{Polygon, PolygonTag};
pub use rect::Rect;
use sauron::Node;
use std::{cmp::Ordering, fmt};
pub use text::{CellText, Text};
mod arc;
mod circle;
mod line;
mod marker_line;
mod polygon;
mod rect;
mod text;
/// ```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
#[derive(Debug, Clone)]
pub enum Fragment {
Line(Line),
MarkerLine(MarkerLine),
Circle(Circle),
Arc(Arc),
Polygon(Polygon),
Rect(Rect),
// cell base
CellText(CellText),
// point base
Text(Text),
}
/// get the boundary of a fragment
/// this is used for sorting the fragments
/// in a consistent sorted order
pub trait Bounds {
fn bounds(&self) -> (Point, Point);
fn mins(&self) -> Point {
self.bounds().0
}
fn maxs(&self) -> Point {
self.bounds().1
}
}
impl Fragment {
/// get the character that matches the shape present on this cell
pub fn match_unicode(fragments: &Vec<Self>) -> Option<char> {
let mut sorted_shapes = fragments.clone();
sorted_shapes.sort();
//assert!(sorted_shapes.is_sorted());
FRAGMENTS_UNICODE.get(&sorted_shapes).map(|c| *c)
}
/// check to see if this fragment is a line and that line
/// can completely overlap line a b
/// TODO: only checking for solid, also expose API for broken
pub(in crate) fn line_overlap(&self, a: Point, b: Point) -> bool {
match self {
Fragment::Line(line) => line.overlaps(a, b),
_ => false,
}
}
/// check if any of the fragment end point is touching p
pub(in crate) fn has_endpoint(&self, p: Point) -> bool {
match self {
Fragment::Line(line) => line.has_endpoint(p),
Fragment::Arc(arc) => arc.has_endpoint(p),
_ => false,
}
}
/// check to see if this fragment is an arc
/// overlaps from point a to b
pub(in crate) fn arcs_to(&self, a: Point, b: Point) -> bool {
match self {
Fragment::Arc(arc) => arc.arcs_to(a, b),
_ => false,
}
}
/// merge this fragment to the other fragment if it is possible
/// returns None if the fragment can not be merge
pub fn merge(&self, other: &Self, settings: &Settings) -> Option<Self> {
match (self, other) {
// line and line
(Fragment::Line(line), Fragment::Line(other_line)) => {
if let Some(merged_line) = line.merge(other_line) {
Some(Fragment::Line(merged_line))
} else {
None
}
}
// line and polygon
(Fragment::Line(line), Fragment::Polygon(polygon)) => {
if settings.merge_line_with_shapes {
line.merge_line_polygon(polygon)
} else {
None
}
}
// polygon and line
(Fragment::Polygon(polygon), Fragment::Line(line)) => {
if settings.merge_line_with_shapes {
line.merge_line_polygon(polygon)
} else {
None
}
}
// line and marker_line
(Fragment::Line(line), Fragment::MarkerLine(mline)) => {
if settings.merge_line_with_shapes {
line.merge_marker_line(mline)
} else {
None
}
}
// marker_line and line
(Fragment::MarkerLine(mline), Fragment::Line(line)) => {
if settings.merge_line_with_shapes {
line.merge_marker_line(mline)
} else {
None
}
}
(Fragment::MarkerLine(mline), Fragment::Polygon(polygon)) => {