Skip to content

Commit

Permalink
start working on EvolutionLog and OpLog
Browse files Browse the repository at this point in the history
  • Loading branch information
MattFerraro committed Apr 10, 2024
1 parent faedbe0 commit 86901b6
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 1 deletion.
7 changes: 7 additions & 0 deletions packages/cadmium/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/cadmium/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ geo = "0.26.0"
serde_with = "3.4.0"
crc32fast = "1.3.2"
indexmap = "2.1.0"
highhash = "0.2.0"

[patch.crates-io]
tsify = { git = "https://github.com/siefkenj/tsify" }
Expand Down
1 change: 1 addition & 0 deletions packages/cadmium/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use wasm_bindgen::prelude::*;
extern crate console_error_panic_hook;

pub mod extrusion;
pub mod oplog;
pub mod project;
pub mod sketch;

Expand Down
48 changes: 47 additions & 1 deletion packages/cadmium/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,63 @@
#![allow(dead_code, unused)]

use std::ops::{Sub, SubAssign};
use std::sync::Arc;

use cadmium::extrusion::fuse;
use cadmium::oplog::EvolutionLog;
use cadmium::oplog::Operation;
use cadmium::project::Plane;
use cadmium::{oplog, Realization};
use truck_meshalgo::filters::OptimizingFilter;
use truck_meshalgo::tessellation::{MeshableShape, MeshedShape};
use truck_modeling::builder::{translated, tsweep, vertex};
use truck_modeling::{Plane, Point3, Surface, Vector3};
use truck_modeling::{Point3, Surface, Vector3};
use truck_polymesh::{obj, InnerSpace, Invertible, ParametricSurface, Tolerance};
use truck_shapeops::{and, or, ShapeOpsCurve, ShapeOpsSurface};
use truck_topology::{Shell, Solid};

// use oplog::Operation;

fn main() {
let mut el = EvolutionLog::new();
el.append(Operation::NewPlane {
name: "Front".to_string(),
plane: Plane::front(),
});
let new_sketch_hash = el.append(Operation::NewSketch {
name: "Sketch1".to_string(),
plane_name: "Front".to_string(),
});
el.append(Operation::NewRectangle {
sketch_name: "Sketch1".to_string(),
x: 0.0,
y: 0.0,
width: 100.0,
height: 100.0,
});
let extrude_sha = el.append(Operation::NewExtrusion {
name: "Extrude1".to_string(),
sketch_name: "Sketch1".to_string(),
click_x: 50.0,
click_y: 50.0,
depth: 100.0,
});

// Actually, let's try something different
el.checkout(new_sketch_hash);
el.append(Operation::NewCircle {
sketch_name: "Sketch1".to_string(),
x: 50.0,
y: 50.0,
radius: 50.0,
});
el.cherry_pick(extrude_sha);

el.pretty_print();

}

fn main_old() {
let point_a = vertex(Point3::new(0.0, 0.0, 0.0));
let line_a = tsweep(&point_a, Vector3::new(1.0, 0.0, 0.0));
let square_a = tsweep(&line_a, Vector3::new(0.0, 1.0, 0.0));
Expand Down
258 changes: 258 additions & 0 deletions packages/cadmium/src/oplog/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
use highhash::Murmur3Hasher;
use serde::{Deserialize, Serialize};
use std::hash::{Hash, Hasher};
use std::process::id;

use crate::project::Plane;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpLog {
commits: Vec<Commit>,
}

impl OpLog {
pub fn new() -> Self {
Self { commits: vec![] }
}

pub fn init(&mut self) {
let creation_commit = Commit::init();
self.commits.push(creation_commit);
}

pub fn append(&mut self, parent: &Sha, operation: Operation) -> Commit {
let op_hash = operation.hash();
let parent = parent.clone();
let new_commit = Commit {
id: id_from_op_and_parent(&operation, &parent),
operation,
content_hash: op_hash,
parent,
};
self.commits.push(new_commit.clone());
new_commit
}

pub fn last(&self) -> Option<Commit> {
match self.commits.last() {
Some(commit) => Some(commit.clone()),
None => None,
}
}

pub fn get_length(&self) -> usize {
self.commits.len()
}
}

fn id_from_op_and_parent(operation: &Operation, parent: &Sha) -> Sha {
let h = operation.hash();
let mut hasher = Murmur3Hasher::default();
hasher.write(format!("{h}-{parent}").as_bytes());
format!("{:x}", hasher.finish())
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvolutionLog {
pub cursor: Sha,
pub oplog: OpLog, // TODO: work out the lifetimes here so that we can have multiple evolutionLogs at once?
}

impl EvolutionLog {
pub fn new() -> Self {
let mut ol = OpLog::new();
ol.init();
Self {
cursor: ol.last().unwrap().id.clone(),
oplog: ol,
}
}

pub fn append(&mut self, operation: Operation) -> Sha {
self.cursor = self.oplog.append(&self.cursor, operation).id;
self.cursor.clone()
}

pub fn pretty_print(&self) {
for commit in &self.oplog.commits {
println!("{}", commit.pretty_print());
}
}

pub fn checkout(&mut self, sha: Sha) -> Result<(), String> {
// check that the sha exists in the oplog before doing this
for commit in &self.oplog.commits {
if commit.id == sha {
self.cursor = sha;
return Ok(());
}
}
Err(format!("SHA {} not found in oplog", sha))
}

pub fn cherry_pick(&mut self, sha: Sha) -> Result<(), String> {
// check that the sha exists in the oplog before doing this
for commit in &self.oplog.commits {
if commit.id == sha {
self.append(commit.operation.clone());
return Ok(());
}
}
Err(format!("SHA {} not found in oplog", sha))
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Commit {
pub operation: Operation,
pub content_hash: Sha,
pub parent: Sha,
pub id: Sha, // this is the SHA of "operation + parent"
}

impl Commit {
pub fn init() -> Self {
let init_op = Operation::Create {
nonce: "Hello World".to_string(), // TODO: replace with actual seeded random string
};
let parent_sha = "".to_owned();
Self {
id: id_from_op_and_parent(&init_op, &parent_sha),
content_hash: init_op.hash(),
operation: init_op,
parent: parent_sha,
}
}

pub fn pretty_print(&self) -> String {
format!("{}: {}", self.id, self.operation.pretty_print())
}
}

pub type Sha = String;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Operation {
Create {
nonce: String,
},
Describe {
description: String,
commit: Sha,
},
NewPlane {
name: String,
plane: Plane,
},
NewSketch {
name: String,
plane_name: String,
},
NewRectangle {
sketch_name: String,
x: f64,
y: f64,
width: f64,
height: f64,
},
NewExtrusion {
name: String,
sketch_name: String,
click_x: f64,
click_y: f64,
depth: f64,
},
NewCircle {
sketch_name: String,
x: f64,
y: f64,
radius: f64,
},
}

impl Operation {
pub fn hash(&self) -> Sha {
let mut hasher = Murmur3Hasher::default();
hasher.write("cadmium".as_bytes()); // mm, salt
match self {
Operation::Create { nonce } => hasher.write(format!("{nonce}").as_bytes()),
Operation::Describe {
description,
commit,
} => hasher.write(format!("{description}-{commit}").as_bytes()),
Operation::NewPlane { name, plane } => {
hasher.write(format!("{name}-{plane:?}").as_bytes())
}
Operation::NewSketch { name, plane_name } => {
hasher.write(format!("{name}-{plane_name:?}").as_bytes())
}
Operation::NewRectangle {
sketch_name,
x,
y,
width,
height,
} => hasher.write(format!("{sketch_name}-{x}-{y}-{width}-{height}").as_bytes()),
Operation::NewExtrusion {
name,
sketch_name,
click_x,
click_y,
depth,
} => {
hasher.write(format!("{name}-{sketch_name}-{click_x}-{click_y}-{depth}").as_bytes())
}
Operation::NewCircle {
sketch_name,
x,
y,
radius,
} => hasher.write(format!("{sketch_name}-{x}-{y}-{radius}").as_bytes()),
}

format!("{:x}", hasher.finish())
}

pub fn pretty_print(&self) -> String {
match self {
Operation::Create { nonce } => format!("Create: {}", nonce),
Operation::Describe {
description,
commit,
} => format!("Describe: {} '{}'", commit, description),
Operation::NewPlane { name, plane } => format!("NewPlane: '{}'", name),
Operation::NewSketch { name, plane_name } => {
format!("NewSketch: '{}' on plane '{}'", name, plane_name)
}
Operation::NewRectangle {
sketch_name,
x,
y,
width,
height,
} => format!(
"NewRectangle: {} {} {} {} on '{}'",
x, y, width, height, sketch_name
),
Operation::NewExtrusion {
name,
sketch_name,
click_x,
click_y,
depth,
} => format!(
"NewExtrusion: '{}' on '{}' ({},{}) depth: {}",
name, sketch_name, click_x, click_y, depth
),
Operation::NewCircle {
sketch_name,
x,
y,
radius,
} => format!(
"NewCircle: ({},{}) radius: {} on '{}'",
x, y, radius, sketch_name
),
}
}
}

0 comments on commit 86901b6

Please sign in to comment.