fidget_core/lib.rs
1//! Core infrastructure for evaluating complex closed-form implicit surfaces.
2//!
3//! ```
4//! use fidget_core::{
5//! context::Context,
6//! shape::EzShape,
7//! vm::VmShape
8//! };
9//! let mut ctx = Context::new();
10//! let x = ctx.x();
11//! let y = ctx.y();
12//! let x_squared = ctx.mul(x, x)?;
13//! let y_squared = ctx.mul(y, y)?;
14//! let radius = ctx.add(x_squared, y_squared)?;
15//! let circle = ctx.sub(radius, 1.0)?;
16//!
17//! let shape = VmShape::new(&ctx, circle)?;
18//! let mut eval = VmShape::new_point_eval();
19//! let tape = shape.ez_point_tape();
20//!
21//! let (v, _trace) = eval.eval(&tape, 0.0, 0.0, 0.0)?;
22//! assert_eq!(v, -1.0);
23//!
24//! let (v, _trace) = eval.eval(&tape, 1.0, 0.0, 0.0)?;
25//! assert_eq!(v, 0.0);
26//!
27//! const N: usize = 15;
28//! for i in 0..N {
29//! for j in 0..N {
30//! let x = (i as f32 + 0.5) / (N as f32 / 2.0) - 1.0;
31//! let y = (j as f32 + 0.5) / (N as f32 / 2.0) - 1.0;
32//! let (v, _trace) = eval.eval(&tape, x, y, 0.0)?;
33//! print!("{}", if v < 0.0 { "##" } else { " " });
34//! }
35//! println!();
36//! }
37//!
38//! // This will print
39//! // ##########
40//! // ##################
41//! // ######################
42//! // ##########################
43//! // ##########################
44//! // ##############################
45//! // ##############################
46//! // ##############################
47//! // ##############################
48//! // ##############################
49//! // ##########################
50//! // ##########################
51//! // ######################
52//! // ##################
53//! // ##########
54//! # Ok::<(), Box<dyn std::error::Error>>(())
55//! ```
56#![warn(missing_docs)]
57
58pub mod context;
59pub use context::Context;
60
61pub mod compiler;
62pub mod eval;
63pub mod render;
64pub mod rng;
65pub mod shape;
66pub mod types;
67pub mod var;
68pub mod vm;
69
70#[cfg(test)]
71mod test {
72 use crate::context::*;
73 use crate::var::Var;
74
75 #[test]
76 fn it_works() {
77 let mut ctx = Context::new();
78 let x1 = ctx.x();
79 let x2 = ctx.x();
80 assert_eq!(x1, x2);
81
82 let a = ctx.constant(1.0);
83 let b = ctx.constant(1.0);
84 assert_eq!(a, b);
85 assert_eq!(ctx.get_const(a).unwrap(), 1.0);
86 assert!(matches!(ctx.get_const(x1), Err(ConstError::NotAConst)));
87
88 let c = ctx.add(a, b).unwrap();
89 assert_eq!(ctx.get_const(c).unwrap(), 2.0);
90
91 let c = ctx.neg(c).unwrap();
92 assert_eq!(ctx.get_const(c).unwrap(), -2.0);
93 }
94
95 #[test]
96 fn test_constant_folding() {
97 let mut ctx = Context::new();
98 let a = ctx.constant(1.0);
99 assert_eq!(ctx.len(), 1);
100 let b = ctx.constant(-1.0);
101 assert_eq!(ctx.len(), 2);
102 let _ = ctx.add(a, b);
103 assert_eq!(ctx.len(), 3);
104 let _ = ctx.add(a, b);
105 assert_eq!(ctx.len(), 3);
106 let _ = ctx.mul(a, b);
107 assert_eq!(ctx.len(), 3);
108 }
109
110 #[test]
111 fn test_eval() {
112 let mut ctx = Context::new();
113 let x = ctx.x();
114 let y = ctx.y();
115 let v = ctx.add(x, y).unwrap();
116
117 assert_eq!(
118 ctx.eval(v, &[(Var::X, 1.0), (Var::Y, 2.0)].into_iter().collect())
119 .unwrap(),
120 3.0
121 );
122 assert_eq!(ctx.eval_xyz(v, 2.0, 3.0, 0.0).unwrap(), 5.0);
123 }
124}