Skip to content

Commit

Permalink
store edges on intersections, fmt degrees
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-williams committed Aug 19, 2023
1 parent f3cd0f7 commit 17e6a32
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 68 deletions.
9 changes: 4 additions & 5 deletions src/circle.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::{fmt::Display, ops::{Mul, Add}, f64::consts::PI};
use std::{fmt::Display, ops::{Mul, Add}, rc::Rc, cell::RefCell};

use derive_more::From;
use serde::{Deserialize, Serialize};
use crate::{
r2::R2,
region::Region,
intersection::Intersection, edge::Edge, dual::Dual
intersection::Intersection, dual::{D, Dual},
};

#[derive(Debug, Clone, Copy, From, Serialize, Deserialize)]
Expand All @@ -15,7 +14,7 @@ pub struct Circle<D> {
pub r: D,
}

type D = Dual;
pub type C = Rc<RefCell<Circle<D>>>;

impl Circle<f64> {
pub fn dual<'a>(&self, pre_zeros: usize, post_zeros: usize) -> Circle<D> {
Expand Down Expand Up @@ -56,7 +55,7 @@ impl Circle<D> {
let p = R2 { x: x.clone(), y: y.clone() };
let t0 = c0.theta(p.clone());
let t1 = c1.theta(p.clone());
Intersection { x, y, c0idx: c0.idx, c1idx: c1.idx, t0, t1 }
Intersection { x, y, c0idx: c0.idx, c1idx: c1.idx, t0, t1, edges: Vec::new(), }
});
intersections
}
Expand Down
12 changes: 11 additions & 1 deletion src/deg.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
use std::f64::consts::PI;

use crate::dual::Dual;
use crate::{dual::Dual, math::round};

pub trait Deg {
fn deg(&self) -> Self;
fn deg_str(&self) -> String;
}

impl Deg for f64 {
fn deg(&self) -> f64 {
self * 180.0 / PI
}
fn deg_str(&self) -> String {
let deg = round(&self.deg());
format!("{:4}", deg)
}
}

impl Deg for Dual {
fn deg(&self) -> Dual {
self * 180.0 / PI
}
fn deg_str(&self) -> String {
let v = round(&self.deg().v());
let d = self.deg().d().iter().map(|t| t.deg()).map(|d| round(&d)).map(|i| format!("{:4}", i)).collect::<Vec<String>>().join(", ");
format!("{:4} [{}]", v, d)
}
}
2 changes: 2 additions & 0 deletions src/dual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use nalgebra::{Dyn, RealField, U1, allocator::Allocator, DefaultAllocator, Matri
use num_dual::{DualVec64, DualDVec64, DualNum, Derivative, DualVec};
use serde::{Deserialize, Serialize};

pub type D = Dual;

#[derive(Clone, PartialEq, PartialOrd)]
pub struct Dual(
DualDVec64,
Expand Down
9 changes: 5 additions & 4 deletions src/edge.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::{fmt::Display, ops::{Div, Mul}, rc::Rc, cell::RefCell};
use std::{fmt::Display, rc::Rc, cell::RefCell};

use crate::{circle::Circle, intersection::{Intersection, Node}, dual::Dual};
use crate::{circle::C, intersection::Node, dual::D};

type C = Rc<RefCell<Circle<D>>>;
type D = Dual;
pub type E = Rc<RefCell<Edge>>;

#[derive(Debug, Clone)]
pub struct Edge {
pub c: C,
pub c0: C,
pub c1: C,
pub i0: Node,
pub i1: Node,
pub containers: Vec<C>,
Expand Down
23 changes: 18 additions & 5 deletions src/intersection.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use std::cell::RefCell;
use std::f64::consts::PI;
use std::fmt::Display;
use std::ops::{Mul, Div};
use std::rc::Rc;

use crate::circle::Circle;
use crate::deg::Deg;
use crate::dual::Dual;
use crate::edge::Edge;
use crate::edge::E;
use crate::r2::R2;

type D = Dual;
pub type Node = Rc<RefCell<Intersection>>;
Expand All @@ -20,7 +18,7 @@ pub struct Intersection {
pub c1idx: usize,
pub t0: D,
pub t1: D,
// pub edges: [ [usize; 2]; 2],
pub edges: Vec<E>,
}

impl Intersection {
Expand All @@ -33,6 +31,21 @@ impl Intersection {
panic!("Invalid circle index {} ({}, {})", idx, self.c0idx, self.c1idx);
}
}
pub fn add_edge(&mut self, edge: E) {
self.edges.push(edge);
}
pub fn p(&self) -> R2<D> {
R2 { x: self.x.clone(), y: self.y.clone() }
}
pub fn other(&self, cidx: usize) -> usize {
if cidx == self.c0idx {
self.c1idx
} else if cidx == self.c1idx {
self.c0idx
} else {
panic!("Invalid circle index {} ({}, {})", cidx, self.c0idx, self.c1idx);
}
}
}

impl Display for Intersection {
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod deg;
mod dual;
mod edge;
mod intersection;
mod math;
mod r2;
mod region;
mod shapes;
Expand Down
116 changes: 63 additions & 53 deletions src/shapes.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
use std::{borrow::BorrowMut, cell::RefCell, rc::Rc};
use std::{cell::RefCell, rc::Rc};

use crate::{dual::Dual, circle::Circle, intersection::{Intersection, Node}, edge, region::Region, r2::R2};
use crate::{circle::{Circle, C}, intersection::Node, edge::{self, E}, r2::R2};

type C = Rc<RefCell<Circle<D>>>;
type D = Dual;
type Edge = Rc<RefCell<edge::Edge>>;

struct Shapes {
pub struct Shapes {
shapes: Vec<Circle<f64>>,
duals: Vec<C>,
nodes: Vec<Node>,
nodes_by_shape: Vec<Vec<Node>>,
nodes_by_shapes: Vec<Vec<Vec<Node>>>,
edges: Vec<Edge>,
edges: Vec<E>,
// regions: Vec<Region>,
}

Expand Down Expand Up @@ -46,15 +42,15 @@ impl Shapes {
}

// Sort each circle's nodes in order of where they appear on the circle (from -PI to PI)
for (idx, mut nodes) in nodes_by_shape.iter_mut().enumerate() {
for (idx, nodes) in nodes_by_shape.iter_mut().enumerate() {
nodes.sort_by_cached_key(|n| n.borrow().theta(idx))
}

let mut edges: Vec<Edge> = Vec::new();
let mut edges_by_shape: Vec<Vec<Edge>> = Vec::new();
let mut edges: Vec<E> = Vec::new();
let mut edges_by_shape: Vec<Vec<E>> = Vec::new();
for idx in 0..n {
let nodes = &nodes_by_shape[idx];
let mut shape_edges: Vec<Edge> = Vec::new();
let mut shape_edges: Vec<E> = Vec::new();
let m = n;
let n = nodes.len();
let c = duals[idx].clone();
Expand All @@ -64,23 +60,35 @@ impl Shapes {
let midpoint = R2 {
x: (&i0.borrow().x + &i1.borrow().x) / 2.,
y: (&i0.borrow().y + &i1.borrow().y) / 2.,
};
let mut containers: Vec<C> = Vec::new();
let mut containments: Vec<bool> = Vec::new();
for cdx in 0..m {
if cdx == idx {
continue;
}
let container = duals[cdx].clone();
let contained = container.borrow().contains(&midpoint);
if contained {
containers.push(container);
}
containments.push(contained);
}
let edge = Rc::new(RefCell::new(edge::Edge { c: c.clone(), i0, i1, containers, containments }));
};
let mut containers: Vec<C> = Vec::new();
let mut containments: Vec<bool> = Vec::new();
for cdx in 0..m {
if cdx == idx {
continue;
}
let container = duals[cdx].clone();
let contained = container.borrow().contains(&midpoint);
if contained {
containers.push(container);
}
containments.push(contained);
}
let c0idx = i0.borrow().other(idx);
let c1idx = i1.borrow().other(idx);
let edge = Rc::new(RefCell::new(edge::Edge {
c: c.clone(),
c0: duals[c0idx].clone(),
c1: duals[c1idx].clone(),
i0,
i1,
containers,
containments,
}));
edges.push(edge.clone());
shape_edges.push(edge.clone());
edge.borrow_mut().i0.borrow_mut().add_edge(edge.clone());
edge.borrow_mut().i1.borrow_mut().add_edge(edge.clone());
}
edges_by_shape.push(shape_edges);
}
Expand All @@ -92,6 +100,8 @@ impl Shapes {
#[cfg(test)]
mod tests {
use crate::deg::Deg;
use crate::dual::Dual;
use crate::math::round;
use crate::r2::R2;

use super::*;
Expand All @@ -104,14 +114,6 @@ mod tests {
let circles = vec![c0, c1, c2];
let shapes = Shapes::new(circles);

fn round(f: &f64) -> i64 {
if f >= &0. {
(f + 0.5) as i64
} else {
(f - 0.5) as i64
}
}

let check = |idx: usize, x: Dual, y: Dual, c0idx: usize, deg0v: i64, deg0d: [i64; 9], c1idx: usize, deg1v: i64, deg1d: [i64; 9]| {
let n = shapes.nodes[idx].borrow();
assert_relative_eq!(n.x, x, epsilon = 1e-3);
Expand Down Expand Up @@ -142,25 +144,33 @@ mod tests {
check(idx, x, y, *c0idx, *deg0v, *deg0d, *c1idx, *deg1v, *deg1d);
}

for node in shapes.nodes.iter() {
println!("{}", node.borrow());
}
println!();
for (idx, nodes) in shapes.nodes_by_shape.iter().enumerate() {
println!("nodes_by_shape[{}]: {}", idx, nodes.len());
for node in nodes.iter() {
println!(" {}", node.borrow());
}
// for node in shapes.nodes.iter() {
// println!("{}", node.borrow());
// }
// println!();
// for (idx, nodes) in shapes.nodes_by_shape.iter().enumerate() {
// println!("nodes_by_shape[{}]: {}", idx, nodes.len());
// for node in nodes.iter() {
// println!(" {}", node.borrow());
// }
// }
// println!();
// for (idx, shapes_nodes) in shapes.nodes_by_shapes.iter().enumerate() {
// println!("nodes_by_shapes[{}]:", idx);
// for (jdx, nodes) in shapes_nodes.iter().enumerate() {
// println!(" nodes_by_shapes[{}][{}]: {}", idx, jdx, nodes.len());
// for node in nodes.iter() {
// println!(" {}", node.borrow());
// }
// }
// }

assert_eq!(shapes.edges.len(), 12);
println!("edges:");
for edge in shapes.edges.iter() {
let edge = edge.borrow();
println!("C{}: {}({}) → {}({})", edge.c.borrow().idx, edge.t0().v().deg_str(), edge.c0.borrow().idx, edge.t1().v().deg_str(), edge.c1.borrow().idx);
}
println!();
for (idx, shapes_nodes) in shapes.nodes_by_shapes.iter().enumerate() {
println!("nodes_by_shapes[{}]:", idx);
for (jdx, nodes) in shapes_nodes.iter().enumerate() {
println!(" nodes_by_shapes[{}][{}]: {}", idx, jdx, nodes.len());
for node in nodes.iter() {
println!(" {}", node.borrow());
}
}
}
}
}

0 comments on commit 17e6a32

Please sign in to comment.