use crate::geom::{self, Point3, Vector3};
use crate::math::BaseFloat;
use daggy::petgraph::visit::{GraphBase, IntoNeighbors, Visitable};
use daggy::{self, Walker};
use std::iter;
use std::ops;
use std::option;
pub use self::edge::Edge;
pub use self::node::Node;
pub mod edge;
pub mod node;
#[derive(Clone, Debug)]
pub struct Graph<S = geom::scalar::Default>
where
S: BaseFloat,
{
dag: Dag<S>,
origin: node::Index,
}
pub type Dag<S = geom::scalar::Default> = daggy::Dag<Node<S>, Edge<S>, usize>;
pub struct Parents<S = geom::scalar::Default>
where
S: BaseFloat,
{
parents: daggy::Parents<Node<S>, Edge<S>, usize>,
}
pub struct Children<S = geom::scalar::Default>
where
S: BaseFloat,
{
children: daggy::Children<Node<S>, Edge<S>, usize>,
}
pub type RawNodes<'a, S = geom::scalar::Default> = daggy::RawNodes<'a, Node<S>, usize>;
pub type RawEdges<'a, S = geom::scalar::Default> = daggy::RawEdges<'a, Edge<S>, usize>;
pub type WouldCycle<S = geom::scalar::Default> = daggy::WouldCycle<Edge<S>>;
pub type RecursiveWalk<F, S = geom::scalar::Default> = daggy::walker::Recursive<Graph<S>, F>;
type ThreeNodes = iter::Chain<
iter::Chain<option::IntoIter<node::Index>, option::IntoIter<node::Index>>,
option::IntoIter<node::Index>,
>;
pub type PositionParents = ThreeNodes;
pub type OrientationParents = ThreeNodes;
pub type ScaleParents = ThreeNodes;
pub type XParents = ThreeNodes;
pub type YParents = ThreeNodes;
pub type ZParents = ThreeNodes;
pub struct WalkVertices<'a, F, I, S: 'a = geom::scalar::Default>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
S: BaseFloat,
{
dfs: &'a mut node::Dfs<S>,
vertices_fn: F,
node: Option<node::TransformedVertices<I::IntoIter, S>>,
}
pub struct WalkTriangles<'a, F, I, V, S: 'a = geom::scalar::Default>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
S: BaseFloat,
{
dfs: &'a mut node::Dfs<S>,
triangles_fn: F,
node: Option<node::TransformedTriangles<I::IntoIter, V, S>>,
}
pub struct Vertices<'a, 'b, F, I, S: 'a + 'b = geom::scalar::Default>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
S: BaseFloat,
{
graph: &'a Graph<S>,
walker: WalkVertices<'b, F, I, S>,
}
pub struct Triangles<'a, 'b, F, I, V, S: 'a + 'b = geom::scalar::Default>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
S: BaseFloat,
{
graph: &'a Graph<S>,
walker: WalkTriangles<'b, F, I, V, S>,
}
impl<'a, F, I, S> WalkVertices<'a, F, I, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
I::Item: node::ApplyTransform<S>,
S: BaseFloat,
{
pub fn next(&mut self, graph: &Graph<S>) -> Option<I::Item> {
let WalkVertices {
ref mut dfs,
ref vertices_fn,
ref mut node,
} = *self;
loop {
if let Some(v) = node.as_mut().and_then(|n| n.next()) {
return Some(v);
}
match dfs.next_vertices(graph, vertices_fn) {
Some((_n, vs)) => *node = Some(vs),
None => return None,
}
}
}
}
impl<'a, F, I, V, S> WalkTriangles<'a, F, I, V, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator<Item = geom::Tri<V>>,
V: geom::Vertex + node::ApplyTransform<S>,
S: BaseFloat,
{
pub fn next(&mut self, graph: &Graph<S>) -> Option<geom::Tri<V>> {
let WalkTriangles {
ref mut dfs,
ref triangles_fn,
ref mut node,
} = *self;
loop {
if let Some(v) = node.as_mut().and_then(|n| n.next()) {
return Some(v);
}
match dfs.next_triangles(graph, triangles_fn) {
Some((_n, ts)) => *node = Some(ts),
None => return None,
}
}
}
}
impl<'a, 'b, F, I, S> Iterator for Vertices<'a, 'b, F, I, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
I::Item: node::ApplyTransform<S>,
S: BaseFloat,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.walker.next(self.graph)
}
}
impl<'a, 'b, F, I, V, S> Iterator for Triangles<'a, 'b, F, I, V, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator<Item = geom::Tri<V>>,
V: geom::Vertex + node::ApplyTransform<S>,
S: BaseFloat,
{
type Item = geom::Tri<V>;
fn next(&mut self) -> Option<Self::Item> {
self.walker.next(self.graph)
}
}
impl<S> Graph<S>
where
S: BaseFloat,
{
pub fn new() -> Self {
Graph::default()
}
pub fn origin(&self) -> node::Index {
self.origin
}
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
let mut dag = Dag::with_capacity(nodes, edges);
let origin = dag.add_node(Node::Point);
Graph { dag, origin }
}
pub fn node_count(&self) -> usize {
self.dag.node_count()
}
pub fn edge_count(&self) -> usize {
self.dag.edge_count()
}
pub fn node(&self, idx: node::Index) -> Option<&Node<S>> {
self.dag.node_weight(idx)
}
pub fn node_transform(&self, idx: node::Index) -> Option<node::Transform<S>> {
if self.node(idx).is_none() {
return None;
}
let mut transform = node::Transform::default();
for (e, parent) in self.parents(idx).iter(self) {
let parent_transform = self
.node_transform(parent)
.expect("no node for yielded parent");
let edge = &self[e];
transform.apply_edge(&parent_transform, edge);
}
Some(transform)
}
pub fn node_vertices<I>(
&self,
idx: node::Index,
vertices: I,
) -> Option<node::TransformedVertices<I::IntoIter, S>>
where
I: IntoIterator,
I::Item: node::ApplyTransform<S>,
{
self.node_transform(idx)
.map(|transform| transform.vertices(vertices.into_iter()))
}
pub fn node_triangles<I, V>(
&self,
idx: node::Index,
triangles: I,
) -> Option<node::TransformedTriangles<I::IntoIter, V, S>>
where
I: IntoIterator<Item = geom::Tri<V>>,
V: geom::Vertex + node::ApplyTransform<S>,
{
self.node_transform(idx)
.map(|transform| transform.triangles(triangles.into_iter()))
}
pub fn edge(&self, idx: edge::Index) -> Option<&Edge<S>> {
self.dag.edge_weight(idx)
}
pub fn raw_nodes(&self) -> RawNodes<S> {
self.dag.raw_nodes()
}
pub fn raw_edges(&self) -> RawEdges<S> {
self.dag.raw_edges()
}
pub fn clear(&mut self) {
self.dag.clear();
let origin = self.dag.add_node(Node::Point);
self.origin = origin;
}
pub fn edge_endpoints(&self, idx: edge::Index) -> Option<(node::Index, node::Index)> {
self.dag.edge_endpoints(idx)
}
pub fn recursive_walk<F>(&self, start: node::Index, recursive_fn: F) -> RecursiveWalk<F, S>
where
F: FnMut(&Self, node::Index) -> Option<(edge::Index, node::Index)>,
{
RecursiveWalk::new(start, recursive_fn)
}
pub fn dag(&self) -> &Dag<S> {
&self.dag
}
pub fn add_node(&mut self, node: Node<S>) -> node::Index {
let origin = self.origin();
let zero = S::zero();
let (x, y, z) = (zero, zero, zero);
let edges = edge::displace(Vector3 { x, y, z });
let (_es, n) = self.add_child(origin, edges.iter().cloned(), node);
n
}
fn remove_edge(&mut self, idx: edge::Index) -> Option<Edge<S>> {
self.dag.remove_edge(idx)
}
pub fn set_edge(
&mut self,
a: node::Index,
b: node::Index,
edge: Edge<S>,
) -> Result<edge::Index, WouldCycle<S>> {
let mut parents = self.parents(b);
let mut already_set = None;
while let Some((in_edge_idx, in_node_idx)) = parents.walk_next(self) {
if edge.kind == self[in_edge_idx].kind {
if in_node_idx == a {
self.dag[in_edge_idx].weight = edge.weight;
already_set = Some(in_edge_idx);
} else {
self.remove_edge(in_edge_idx);
}
break;
}
}
match already_set {
Some(edge_idx) => Ok(edge_idx),
None => self.dag.add_edge(a, b, edge),
}
}
pub fn add_child<E>(
&mut self,
parent: node::Index,
edges: E,
node: Node<S>,
) -> (edge::Indices, node::Index)
where
E: IntoIterator<Item = Edge<S>>,
{
let n = self.dag.add_node(node);
let mut edges = edges.into_iter().peekable();
match edges.next() {
None => panic!("`edges` must contain at least one edge"),
Some(first) => {
let edges = Some(first).into_iter().chain(edges).map(|e| (parent, n, e));
let edge_indices = self
.dag
.add_edges(edges)
.expect("cannot create a cycle when adding a new child");
(edge_indices, n)
}
}
}
pub fn add_children<C, E>(
&mut self,
parent: node::Index,
children: C,
) -> Vec<(edge::Indices, node::Index)>
where
C: IntoIterator<Item = (E, Node<S>)>,
E: IntoIterator<Item = Edge<S>>,
{
let mut children_indices = vec![];
for (edges, node) in children {
let child_indices = self.add_child(parent, edges, node);
children_indices.push(child_indices);
}
children_indices
}
pub fn walk_vertices<'a, F, I>(
&self,
dfs: &'a mut node::Dfs<S>,
vertices_fn: F,
) -> WalkVertices<'a, F, I, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
I::Item: node::ApplyTransform<S>,
{
let node = None;
WalkVertices {
dfs,
vertices_fn,
node,
}
}
pub fn walk_triangles<'a, F, I, V>(
&self,
dfs: &'a mut node::Dfs<S>,
triangles_fn: F,
) -> WalkTriangles<'a, F, I, V, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator<Item = geom::Tri<V>>,
V: geom::Vertex + node::ApplyTransform<S>,
{
let node = None;
WalkTriangles {
dfs,
triangles_fn,
node,
}
}
pub fn vertices<'a, 'b, F, I>(
&'a self,
dfs: &'b mut node::Dfs<S>,
vertices_fn: F,
) -> Vertices<'a, 'b, F, I, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator,
I::Item: node::ApplyTransform<S>,
{
let walker = self.walk_vertices(dfs, vertices_fn);
let graph = self;
Vertices { graph, walker }
}
pub fn triangles<'a, 'b, F, I, V>(
&'a self,
dfs: &'b mut node::Dfs<S>,
triangles_fn: F,
) -> Triangles<'a, 'b, F, I, V, S>
where
F: Fn(&node::Index) -> I,
I: IntoIterator<Item = geom::Tri<V>>,
V: geom::Vertex + node::ApplyTransform<S>,
{
let walker = self.walk_triangles(dfs, triangles_fn);
let graph = self;
Triangles { graph, walker }
}
pub fn bounding_cuboid<F, I>(
&self,
dfs: &mut node::Dfs<S>,
vertices_fn: F,
) -> Option<geom::Cuboid<S>>
where
F: Fn(&node::Index) -> I,
I: IntoIterator<Item = Point3<S>>,
{
let vertices = self.vertices(dfs, vertices_fn);
geom::bounding_cuboid(vertices)
}
pub fn parents(&self, child: node::Index) -> Parents<S> {
let parents = self.dag.parents(child);
Parents { parents }
}
pub fn edge_parent(&self, idx: node::Index, edge: edge::Kind) -> Option<node::Index> {
self.parents(idx)
.iter(self)
.find(|&(e, _)| self[e].kind == edge)
.map(|(_, n)| n)
}
pub fn position_parent(&self, idx: node::Index, axis: edge::Axis) -> Option<node::Index> {
let kind = edge::Kind::new(axis, edge::Relative::Position);
self.edge_parent(idx, kind)
}
pub fn x_position_parent(&self, idx: node::Index) -> Option<node::Index> {
self.position_parent(idx, edge::Axis::X)
}
pub fn y_position_parent(&self, idx: node::Index) -> Option<node::Index> {
self.position_parent(idx, edge::Axis::Y)
}
pub fn z_position_parent(&self, idx: node::Index) -> Option<node::Index> {
self.position_parent(idx, edge::Axis::Z)
}
pub fn position_parents(&self, idx: node::Index) -> PositionParents {
self.x_position_parent(idx)
.into_iter()
.chain(self.y_position_parent(idx))
.chain(self.z_position_parent(idx))
}
pub fn orientation_parent(&self, idx: node::Index, axis: edge::Axis) -> Option<node::Index> {
let kind = edge::Kind::new(axis, edge::Relative::Orientation);
self.edge_parent(idx, kind)
}
pub fn x_orientation_parent(&self, idx: node::Index) -> Option<node::Index> {
self.orientation_parent(idx, edge::Axis::X)
}
pub fn y_orientation_parent(&self, idx: node::Index) -> Option<node::Index> {
self.orientation_parent(idx, edge::Axis::Y)
}
pub fn z_orientation_parent(&self, idx: node::Index) -> Option<node::Index> {
self.orientation_parent(idx, edge::Axis::Z)
}
pub fn orientation_parents(&self, idx: node::Index) -> OrientationParents {
self.x_orientation_parent(idx)
.into_iter()
.chain(self.y_orientation_parent(idx))
.chain(self.z_orientation_parent(idx))
}
pub fn scale_parent(&self, idx: node::Index, axis: edge::Axis) -> Option<node::Index> {
let kind = edge::Kind::new(axis, edge::Relative::Scale);
self.edge_parent(idx, kind)
}
pub fn x_scale_parent(&self, idx: node::Index) -> Option<node::Index> {
self.scale_parent(idx, edge::Axis::X)
}
pub fn y_scale_parent(&self, idx: node::Index) -> Option<node::Index> {
self.scale_parent(idx, edge::Axis::Y)
}
pub fn z_scale_parent(&self, idx: node::Index) -> Option<node::Index> {
self.scale_parent(idx, edge::Axis::Z)
}
pub fn scale_parents(&self, idx: node::Index) -> ScaleParents {
self.x_scale_parent(idx)
.into_iter()
.chain(self.y_scale_parent(idx))
.chain(self.z_scale_parent(idx))
}
pub fn x_parents(&self, idx: node::Index) -> XParents {
self.x_position_parent(idx)
.into_iter()
.chain(self.x_orientation_parent(idx))
.chain(self.x_scale_parent(idx))
}
pub fn y_parents(&self, idx: node::Index) -> YParents {
self.y_position_parent(idx)
.into_iter()
.chain(self.y_orientation_parent(idx))
.chain(self.y_scale_parent(idx))
}
pub fn z_parents(&self, idx: node::Index) -> ZParents {
self.z_position_parent(idx)
.into_iter()
.chain(self.z_orientation_parent(idx))
.chain(self.z_scale_parent(idx))
}
pub fn children(&self, parent: node::Index) -> Children<S> {
let children = self.dag.children(parent);
Children { children }
}
}
impl<S> Default for Graph<S>
where
S: BaseFloat,
{
fn default() -> Self {
let mut dag = Dag::new();
let origin = dag.add_node(Node::Point);
Graph { dag, origin }
}
}
impl<S> GraphBase for Graph<S>
where
S: BaseFloat,
{
type NodeId = node::Index;
type EdgeId = edge::Index;
}
impl<S> Visitable for Graph<S>
where
S: BaseFloat,
{
type Map = <Dag<S> as Visitable>::Map;
fn visit_map(&self) -> Self::Map {
self.dag.visit_map()
}
fn reset_map(&self, map: &mut Self::Map) {
self.dag.reset_map(map)
}
}
impl<'a, S> IntoNeighbors for &'a Graph<S>
where
S: BaseFloat,
{
type Neighbors = <&'a Dag<S> as IntoNeighbors>::Neighbors;
fn neighbors(self, n: Self::NodeId) -> Self::Neighbors {
self.dag.neighbors(n)
}
}
impl<S> ops::Index<node::Index> for Graph<S>
where
S: BaseFloat,
{
type Output = Node<S>;
fn index<'a>(&'a self, id: node::Index) -> &'a Self::Output {
self.node(id).unwrap()
}
}
impl<S> ops::Index<edge::Index> for Graph<S>
where
S: BaseFloat,
{
type Output = Edge<S>;
fn index<'a>(&'a self, idx: edge::Index) -> &'a Self::Output {
self.edge(idx).unwrap()
}
}
impl<'a, S> Walker<&'a Graph<S>> for Children<S>
where
S: BaseFloat,
{
type Item = (edge::Index, node::Index);
#[inline]
fn walk_next(&mut self, graph: &'a Graph<S>) -> Option<Self::Item> {
self.children.walk_next(&graph.dag)
}
}
impl<'a, S> Walker<&'a Graph<S>> for Parents<S>
where
S: BaseFloat,
{
type Item = (edge::Index, node::Index);
#[inline]
fn walk_next(&mut self, graph: &'a Graph<S>) -> Option<Self::Item> {
self.parents.walk_next(&graph.dag)
}
}