Quadtrees are up and running! Let's render them!
This commit is contained in:
parent
0628e1bc68
commit
7add9d30bd
84
src/ctx.rs
84
src/ctx.rs
|
@ -1,32 +1,74 @@
|
|||
use std::marker::PhantomData;
|
||||
use crate::quad::{Quad, Node, Embed};
|
||||
|
||||
/// Represents a context with shared state.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Ctx<A: Embed, B: Embed> {
|
||||
_phantom_a: PhantomData<A>,
|
||||
_phantom_b: PhantomData<B>,
|
||||
pub trait Approx<A: Embed, B: Embed, S>: Default {
|
||||
fn color_base(state: &mut S, base: A) -> [u8; 4];
|
||||
|
||||
fn compress_node(state: &mut S, compr: [B; 4]) -> B;
|
||||
fn expand_node(state: &mut S, compr: B) -> [B; 4];
|
||||
|
||||
fn compress_base(state: &mut S, embed: A) -> B;
|
||||
fn expand_base(state: &mut S, compr: B) -> A;
|
||||
}
|
||||
|
||||
impl<A: Embed, B: Embed> Ctx<A, B> {
|
||||
/// Creates a new uninitialized context.
|
||||
pub fn new_empty() -> Self {
|
||||
Default::default()
|
||||
#[derive(Default)]
|
||||
pub struct Basic;
|
||||
|
||||
impl Approx<u8, u8, ()> for Basic {
|
||||
fn color_base(state: &mut (), base: u8) -> [u8; 4] {
|
||||
[base;4]
|
||||
}
|
||||
|
||||
/// Combines 4 child node representations into a single representation
|
||||
/// Using a neural network.
|
||||
pub fn combine(&mut self, compr: [B; 4]) -> B {
|
||||
todo!("Build new B from 4 child B");
|
||||
fn compress_node(state: &mut (), c: [u8; 4]) -> u8 {
|
||||
c[0]/4 + c[1]/4 + c[2]/4 + c[3]/4
|
||||
}
|
||||
|
||||
fn expand_node(state: &mut (), compr: u8) -> [u8; 4] {
|
||||
[compr;4]
|
||||
}
|
||||
|
||||
fn compress_base(state: &mut (), embed: u8) -> u8 {
|
||||
embed
|
||||
}
|
||||
|
||||
fn expand_base(state: &mut (), compr: u8) -> u8 {
|
||||
compr
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a context with shared state.
|
||||
#[derive(Debug)]
|
||||
pub struct Ctx<A: Embed, B: Embed, S, N: Approx<A, B, S>> {
|
||||
_phantom_a: PhantomData<A>,
|
||||
_phantom_b: PhantomData<B>,
|
||||
state: S,
|
||||
networks: N,
|
||||
}
|
||||
|
||||
impl<A: Embed, B: Embed, S, N: Approx<A, B, S>> Ctx<A, B, S, N> {
|
||||
/// Creates a new uninitialized context.
|
||||
pub fn new(state: S, networks: N) -> Self {
|
||||
Ctx {
|
||||
_phantom_a: PhantomData,
|
||||
_phantom_b: PhantomData,
|
||||
state,
|
||||
networks,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn color_base(&mut self, base: A) -> [u8; 4] {
|
||||
N::color_base(&mut self.state, base)
|
||||
}
|
||||
|
||||
/// Compresses a base-level cell into a vector.
|
||||
pub fn compress_base(&mut self, base: A) -> B {
|
||||
todo!("Turn Base Cell into a vector B");
|
||||
N::compress_base(&mut self.state, base)
|
||||
}
|
||||
|
||||
pub fn color_base(&mut self, base: &A) -> [u8; 4] {
|
||||
todo!();
|
||||
/// Combines 4 child node representations into a single representation
|
||||
/// Using a neural network.
|
||||
pub fn compress_node(&mut self, compr: [B; 4]) -> B {
|
||||
N::compress_node(&mut self.state, compr)
|
||||
}
|
||||
|
||||
/// Compresses a single node into a vector representation.
|
||||
|
@ -36,7 +78,7 @@ impl<A: Embed, B: Embed> Ctx<A, B> {
|
|||
match quad {
|
||||
Quad::Base(b) => Some(self.compress_base(*b)),
|
||||
Quad::Node(n) => Some(
|
||||
self.combine([
|
||||
self.compress_node([
|
||||
n[0].compr,
|
||||
n[1].compr,
|
||||
n[2].compr,
|
||||
|
@ -48,12 +90,12 @@ impl<A: Embed, B: Embed> Ctx<A, B> {
|
|||
}
|
||||
|
||||
/// Compresses a base-level cell into a vector.
|
||||
fn expand_base(&mut self, compr: B) -> A {
|
||||
todo!("Turn compressed B into the A that made it");
|
||||
pub fn expand_base(&mut self, compr: B) -> A {
|
||||
N::expand_base(&mut self.state, compr)
|
||||
}
|
||||
|
||||
fn expand_node(&mut self, compr: B) -> [B; 4] {
|
||||
todo!("Turn compressed B into 4 child B that made it");
|
||||
pub fn expand_node(&mut self, compr: B) -> [B; 4] {
|
||||
N::expand_node(&mut self.state, compr)
|
||||
}
|
||||
|
||||
/// Expands the compressed representation of a node into a node with 4 children.
|
||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -6,9 +6,15 @@ mod render;
|
|||
fn main() {
|
||||
println!("Warming up...");
|
||||
|
||||
let mut ctx = ctx::Ctx::new_empty();
|
||||
let mut ctx = ctx::Ctx::new((), ctx::Basic);
|
||||
|
||||
let mut base = vec![];
|
||||
for i in 0..16 {
|
||||
base.push(i);
|
||||
}
|
||||
|
||||
let quad: quad::Node<u8, u8> = quad::Node::new_from_square(
|
||||
&mut ctx, vec![0xFF;64],
|
||||
&mut ctx, base,
|
||||
);
|
||||
|
||||
// render::graphics();
|
||||
|
|
30
src/quad.rs
30
src/quad.rs
|
@ -1,7 +1,7 @@
|
|||
use crate::ctx::Ctx;
|
||||
use crate::ctx::{Ctx, Approx};
|
||||
|
||||
pub trait Embed: Default + Copy + Sized + std::fmt::Debug {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// Represents the data present in a quad-tree node.
|
||||
|
@ -32,7 +32,12 @@ pub struct Node<A: Embed, B: Embed> {
|
|||
}
|
||||
|
||||
impl<A: Embed, B: Embed> Node<A, B> {
|
||||
pub fn sample_color(self, ctx: &mut Ctx<A, B>, x: isize, y: isize) -> (Self, [u8; 4]) {
|
||||
pub fn sample_color<S, N: Approx<A, B, S>>(
|
||||
self,
|
||||
ctx: &mut Ctx<A, B, S, N>,
|
||||
x: isize,
|
||||
y: isize,
|
||||
) -> (Self, [u8; 4]) {
|
||||
// self = ctx.expand(self);
|
||||
// if let Quad::Base(b) = self.data {
|
||||
// return (self, ctx.color_base(&b));
|
||||
|
@ -54,12 +59,12 @@ impl<A: Embed, B: Embed> Node<A, B> {
|
|||
}
|
||||
|
||||
/// Creates a new tree with a single empty base node
|
||||
pub fn new_empty(ctx: &mut Ctx<A, B>) -> Self {
|
||||
pub fn new_empty<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>) -> Self {
|
||||
Self::new_base(ctx, Default::default())
|
||||
}
|
||||
|
||||
/// Creates a new tree from a single base node
|
||||
pub fn new_base(ctx: &mut Ctx<A, B>, base: A) -> Self {
|
||||
pub fn new_base<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>, base: A) -> Self {
|
||||
Node {
|
||||
depth: 0,
|
||||
compr: ctx.compress_base(base),
|
||||
|
@ -67,7 +72,7 @@ impl<A: Embed, B: Embed> Node<A, B> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_node(ctx: &mut Ctx<A, B>, children: [Node<A, B>;4]) -> Self {
|
||||
pub fn new_node<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>, children: [Node<A, B>;4]) -> Self {
|
||||
// Make sure the depths check out
|
||||
assert_eq!(children[0].depth, children[1].depth);
|
||||
assert_eq!(children[1].depth, children[2].depth);
|
||||
|
@ -88,8 +93,8 @@ impl<A: Embed, B: Embed> Node<A, B> {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_square(
|
||||
ctx: &mut Ctx<A, B>,
|
||||
fn build_square<S, N: Approx<A, B, S>>(
|
||||
ctx: &mut Ctx<A, B, S, N>,
|
||||
square: &[A],
|
||||
abs_size: usize,
|
||||
depth: usize,
|
||||
|
@ -106,16 +111,17 @@ impl<A: Embed, B: Embed> Node<A, B> {
|
|||
let half = size / 2;
|
||||
// in a z-like pattern
|
||||
let children = [
|
||||
Self::build_square(ctx, square, abs_size, depth - 1, x + half, y ),
|
||||
Self::build_square(ctx, square, abs_size, depth - 1, x , y ),
|
||||
Self::build_square(ctx, square, abs_size, depth - 1, x + half, y + half),
|
||||
Self::build_square(ctx, square, abs_size, depth - 1, x + half, y ),
|
||||
Self::build_square(ctx, square, abs_size, depth - 1, x , y + half),
|
||||
Self::build_square(ctx, square, abs_size, depth - 1, x + half, y + half),
|
||||
|
||||
];
|
||||
Self::new_node(ctx, children)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_square(ctx: &mut Ctx<A, B>, square: Vec<A>) -> Self {
|
||||
pub fn new_from_square<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>, square: Vec<A>) -> Self {
|
||||
// get the side length, ensure this is a pow2 square
|
||||
let area = square.len();
|
||||
let size = ((area as f64).sqrt() + 0.5) as usize;
|
||||
|
@ -135,7 +141,7 @@ impl<A: Embed, B: Embed> Node<A, B> {
|
|||
|
||||
/// Creates a new node double the size by centering the current node
|
||||
/// on a node double the size.
|
||||
pub fn pad_empty(self, ctx: &mut Ctx<A, B>) -> Self {
|
||||
pub fn pad_empty<S, N: Approx<A, B, S>>(self, ctx: &mut Ctx<A, B, S, N>) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use crate::ctx::Ctx;
|
||||
use crate::ctx::{Ctx, Approx};
|
||||
use crate::quad::{Node, Embed};
|
||||
|
||||
pub fn step<A: Embed, B: Embed>(ctx: &mut Ctx<A, B>, node: Node<A, B>) -> Node<A, B> {
|
||||
pub fn step<A: Embed, B: Embed, S, N: Approx<A, B, S>>(
|
||||
ctx: &mut Ctx<A, B, S, N>,
|
||||
node: Node<A, B>
|
||||
) -> Node<A, B> {
|
||||
// pad the graph if needed.
|
||||
|
||||
// if we're at the base, run the cellular automation rule:
|
||||
|
|
Reference in a new issue