use crate::{
buffer::{fragment_buffer::fragment::polygon::Polygon, Cell, Fragment},
fragment::{marker_line, Bounds, Circle, Marker, MarkerLine},
util, Direction, Point,
};
use parry2d::query::PointQuery;
use parry2d::{bounding_volume::AABB, shape::Polyline};
use parry2d::{
math::Isometry,
shape::{Segment, Shape},
};
use std::{cmp::Ordering, fmt};
use crate::fragment::Arc;
use sauron::{html::attributes::*, 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 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().round() as i32;
match angle {
0..=10 => 0.0,
11..=50 => 63.435, //45.0,
51..=80 => 63.435,
81..=100 => 90.0,
101..=130 => 116.565,
131..=170 => 116.565, //135.0,
171..=190 => 180.0,
191..=230 => 243.435, //225.0,
231..=260 => 243.435,
261..=280 => 270.0,
281..=310 => 296.565,
311..=350 => 296.565, //315.0,
351..=360 => 0.0,
_ => 0.0,
}
}
/// 0 0
/// 45 45
/// 63.435 63
/// 90 90
/// 116.565 117
/// 135 135
/// 180 180
/// 225 225
/// 243.435 243
/// 270 270
/// 296.565 297
/// 315 315
/// 360 360
pub(crate) fn heading(&self) -> Direction {
match self.line_angle().round()