use termtree; use glam::{Vec3A}; use std::fmt; pub trait Field: fmt::Debug { fn sample(&self, pos: Vec3A) -> f32; } #[derive(Debug)] pub enum FieldOp { Add, Sub, Mul, Div, } impl fmt::Display for FieldOp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut name = String::new(); match *self { Add => { name = "+".to_string() }, Sub => { name = "-".to_string() }, Mul => { name = "*".to_string() }, Div => { name = "/".to_string() }, _ => { name = "?".to_string() } } write!(f, "{}", name) } } use FieldOp::*; #[derive(Debug)] pub struct FieldNode { pub field: Box, pub op: FieldOp, pub children: Vec, } impl FieldNode { pub fn sample(&self, pos: Vec3A) -> f32 { let mut result = self.field.sample(pos); for child in self.children.iter() { let child_result = child.sample(pos); result = match child.op { Add => { result + child_result }, Sub => { result - child_result }, Mul => { result * child_result }, Div => { result / child_result } } } result } pub fn to_termtree(&self) -> termtree::Tree { // Turn the node structure into a tree let mut node_label = String::new(); if self.children.is_empty() { node_label = format!("{} {:?}", self.op, self.field); } else { node_label = format!("{} {:?} = {:?}", self.op, self.field, self.sample(Vec3A::ZERO)); } let mut tree: termtree::Tree = termtree::Tree::new(node_label); for child in self.children.iter() { tree.push(child.to_termtree()); } tree } } impl fmt::Display for FieldNode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.to_termtree()) } }