use crate::*;
pub struct Vertex<'a> {
pub i: usize,
pub x: f64,
pub y: f64,
pub topdown: bool,
pub top: f64,
pub bottom: f64,
pub left: f64,
pub right: f64,
pub sign: bool,
pub valid: bool,
pub sects: Option<Vec<*mut Sect<'a>>>,
pub prev: *mut Vertex<'a>,
pub next: *mut Vertex<'a>,
pub next_sect: *mut Sect<'a>,
}
pub struct Sect<'a> {
pub i: usize,
pub x: f64,
pub y: f64,
pub dual: *mut Sect<'a>,
pub next: *mut Sect<'a>,
pub other: *mut Vertex<'a>,
pub sign: bool,
pub valid: bool,
}
#[derive(Debug)]
pub struct RedunSect {
pub i: usize,
pub dir: bool,
pub angle: f64,
pub is_straight: bool,
}
pub struct SimpleCycle<'a> {
pub point: *mut Point<'a>,
pub len: usize,
}
pub struct Point<'a> {
pub i: usize,
pub x: f64,
pub y: f64,
pub reflex: bool,
pub prev: *mut Point<'a>,
pub next: *mut Point<'a>,
}
impl Vertex<'_> {
pub fn new(i: usize, x0: f64, y0: f64, x1: f64, y1: f64, last: *mut Vertex) -> *mut Vertex {
let mut topdown = true;
let mut top = y0;
let mut bottom = y1;
let mut left = x0;
let mut right = x1;
if y1>y0 {
topdown = false;
top = y1;
bottom = y0;
} else if y1==y0 {
if x0>x1 {
topdown = false;
}
}
if x0>x1 {
right = x0;
left = x1;
}
let v = Box::into_raw(Box::new(Vertex{i: i, x: x0, y: y0,
topdown: topdown,
top: top,
bottom: bottom,
left: left,
right: right,
sign: true,
valid: true,
sects: None,
prev: ptr::null_mut(),
next: ptr::null_mut(),
next_sect: ptr::null_mut(),
}));
unsafe {
if last.is_null() {
(*v).prev = v;
(*v).next = v;
} else {
(*v).next = (*last).next;
(*v).prev = last;
(*(*last).next).prev = v;
(*last).next = v;
}
}
return v;
}
pub fn equals(&self, other: &Self) -> bool {
if (self.x==other.x) && (self.y==other.y) {
true
} else {
false
}
}
pub fn is_adjacent(&self, other: &Self, len: usize) -> bool {
let i = self.i;
let j = other.i;
if (i==0) || (j==0) {
if i + j == len-1 {
return true;
}
}
let abs = if i>j {i-j} else {j-i};
if abs==1 {
return true;
}
false
}
}
impl PartialEq<Vertex<'_>> for Vertex<'_> {
fn eq(&self, other: &Vertex) -> bool {
self.x==other.x && self.y==other.y && self.i==other.i
}
}
impl PartialOrd for Vertex<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let cmpy = (&self.y).partial_cmp(&other.y); match cmpy {
Some(Ordering::Equal) => {
let cmpx = (&other.x).partial_cmp(&self.x); match cmpx {
Some(Ordering::Equal) => {
(&other.i).partial_cmp(&self.i) },
_ => cmpx,
}
},
_ => cmpy,
}
}
}
impl PartialEq<Sect<'_>> for Sect<'_> {
fn eq(&self, other: &Sect) -> bool {
self.x==other.x && self.y==other.y
}
}
impl PartialOrd for Sect<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let cmpy = (&self.y).partial_cmp(&other.y); match cmpy {
Some(Ordering::Equal) => {
(&other.x).partial_cmp(&self.x) },
_ => cmpy,
}
}
}
impl RedunSect {
pub fn new(i: usize, vx:f64, vy:f64, px:f64, py:f64, ox:f64, oy:f64) -> (RedunSect, RedunSect) {
let local_wind = area(vx, vy, px, py, ox, oy);
let a2 = (ox-px).powi(2) + (oy-py).powi(2);
let b2 = (vx-px).powi(2) + (vy-py).powi(2);
let c2 = (ox-vx).powi(2) + (oy-vy).powi(2);
let mut deno = 2.*(a2.sqrt())*(b2.sqrt());
if deno==0. {deno+=1e-10};
let cos_c: f64 = (a2+b2-c2) / deno;
let mut angle: f64 = cos_c.acos();
if local_wind==Winding::CW { angle = std::f64::consts::PI*2.-angle;
}
let mut angle2 = angle + std::f64::consts::PI;
if angle2 > std::f64::consts::PI*2. {
angle2 -= std::f64::consts::PI*2.;
}
let r1 = RedunSect{ i: i, dir: true, angle: angle, is_straight: false };
let r2 = RedunSect{ i: i, dir: false, angle: angle2, is_straight: false };
(r1, r2)
}
}
impl PartialEq<RedunSect> for RedunSect {
fn eq(&self, other: &RedunSect) -> bool {
self.angle == other.angle
}
}
impl PartialOrd for RedunSect {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let cmp = (&self.angle).partial_cmp(&other.angle);
match cmp {
Some(Ordering::Equal) => {
if self.dir {
if !other.dir { Some(Ordering::Greater) } else {
Some(Ordering::Equal)
}
} else {
if other.dir { Some(Ordering::Less) } else {
Some(Ordering::Equal)
}
}
},
_ => cmp
}
}
}
impl Point<'_> {
pub fn new<'a>(i:usize, x:f64, y:f64, last: *mut Point<'a>) -> *mut Point<'a> {
let p = Box::into_raw(Box::new(
Point{ i:i, x:x, y:y, reflex:true, prev:ptr::null_mut(), next:ptr::null_mut() }
));
unsafe {
if last.is_null() {
(*p).prev = p;
(*p).next = p;
} else {
(*p).next = (*last).next;
(*p).prev = last;
(*(*last).next).prev = p;
(*last).next = p;
}
}
return p;
}
}