use crate::{
buffer::{
fragment_buffer::fragment::{polygon::Polygon, PolygonTag},
Cell, CellGrid, Fragment,
},
fragment::{marker_line, Bounds, Circle, Marker, MarkerLine},
util, Direction, Point,
};
use ncollide2d::{
math::Isometry,
query::point_internal::point_query::PointQuery,
shape::{Segment, Shape},
};
use std::{cmp::Ordering, fmt};
use crate::fragment::Arc;
use sauron::{
svg,
svg::{attributes::*, *},
Node,
};
#[derive(Debug, Clone)]
pub struct Line {
pub start: Point,
pub end: Point,
pub is_broken: bool,
}
impl Line {
/// creates a new line and reorder the points swapping the end points if necessary
/// such that the start is the most top-left and end point is the most bottom-right
pub(in crate) fn new(start: Point, end: Point, is_broken: bool) -> Self {
let mut line = Line {
start,
end,
is_broken,
};
line.sort_reorder_end_points();
line
}
/// creates a new line, but don't reorder the points
pub(in crate) fn new_noswap(start: Point, end: Point, is_broken: bool) -> Self {
Line {
start,
end,
is_broken,
}
}
/// reorder the end points swap end points such that
/// start < end
pub(in crate) fn sort_reorder_end_points(&mut self) {
if self.start > self.end {
self.swap()
}
}
fn swap(&mut self) {
let tmp_start = self.start;
self.start = self.end;
self.end = tmp_start;
}
/// does this line can completely cover line a b?
pub(in crate) fn overlaps(&self, a: Point, b: Point) -> bool {
let segment = Segment::new(*self.start, *self.end);
let identity = &Isometry::identity();
segment.contains_point(identity, &a) && segment.contains_point(identity, &b)
}
fn contains_point(&self, p: Point) -> bool {
let segment = Segment::new(*self.start, *self.end);
let identity = &Isometry::identity();
segment.contains_point(identity, &p)
}
fn touching_line(&self, other: &Self) -> bool {
self.contains_point(other.start) || self.contains_point(other.end)
}
fn octant(&self) -> u8 {
let mut dx = self.end.x - self.start.x;
let mut dy = -(self.end.y * 2.0 - self.start.y * 2.0);
let mut octant = 0;
if dy < 0.0 {
dx = -dx;
dy = -dy;
octant += 4;
}
if dx < 0.0 {
let tmp = dx;
dx = dy;
dy = -tmp;
octant += 2
}
if dx < dy {
octant += 1
}
octant
}
//phi = atan(m1) - atan(m2);
fn angle_rad(&self) -> f32 {
let m1 = self.slope();
0.0 - m1.atan()
}
fn angle_deg(&self) -> f32 {
self.angle_rad().to_degrees()
}
fn slope(&self) -> f32 {
(2.0 * self.end.y as f32 - 2.0 * self.start.y as f32)
/ (self.end.x as f32 - self.start.x as f32)
}
fn full_angle(&self) -> f32 {
let angle = self.angle_deg().abs();
match self.octant() {
0..=1 => angle,
2..=3 => 180.0 - angle,
4..=5 => 180.0 + angle,
6..=7 => 360.0 - angle,
_ => angle,
}
}
/// round angle closest to
///
/// slash line is not really 60% but 63.435
/// 63.435 0 63.435
/// 180 116.565
/// 180 243.435
/// 360 296.565
///
///
fn line_angle(&self) -> f32 {
let angle = self.full_angle();
match angle {
0.0..=10.0 => 0.0,
10.0..=50.0 => 63.435, //45.0,
50.0..=80.0 => 63.435,
80.0..=100.0 => 90.0,
100.0..=130.0 => 116.565,
130.0..=170.0 => 116.565, //135.0,
170.0..=190.0 => 180.0,
190.0..=230.0 => 243.435, //225.0,
230.0..=260.0 => 243.435,
260.0..=280.0 => 270.0,
280.0..=310.0 => 296.565,
310.0..=350.0 => 296.565, //315.0,
350.0..=360.0 => 0.0,
_ => 0.0,
}
}
/// 0 0
/// 45 45