-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
play with Fornjot models in TypeScript
- Loading branch information
1 parent
7a0f3e5
commit 54cc260
Showing
11 changed files
with
1,078 additions
and
778 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,24 @@ | ||
# mycelia | ||
# sandkit | ||
|
||
## run | ||
A functional CAD playground to create and compose products. | ||
|
||
_At the moment only a proof-of-concept for using [Fornjot](https://fornjot.app) in TypeScript_ | ||
|
||
Mad science for and by [Village Kit](https://villagekit.com). | ||
|
||
## demo | ||
|
||
```shell | ||
cargo run --release | ||
git clone https://github.com/villagekit/sandkit | ||
cd sandkit | ||
``` | ||
|
||
See model in [`./models/demo.ts`](./models/demo.ts). | ||
|
||
```shell | ||
cargo run | ||
``` | ||
|
||
## license | ||
|
||
Apache-2.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
export const params = [ | ||
{ | ||
name: 'outer', | ||
type: 'number', | ||
default: 1.0, | ||
min: ({ inner }) => inner * 1.01, | ||
}, | ||
{ | ||
name: 'inner', | ||
type: 'number', | ||
default: 0.5, | ||
max: ({ outer }) => outer * 0.99, | ||
}, | ||
{ | ||
name: 'height', | ||
type: 'number', | ||
default: 1.0, | ||
}, | ||
] | ||
export function shape(params: ParamValues) { | ||
const { outer, inner, height } = params | ||
|
||
const outerEdge = Sketch.fromCircle(Circle.fromRadius(outer)) | ||
const innerEdge = Sketch.fromCircle(Circle.fromRadius(inner)) | ||
|
||
const footprint = Difference2d.fromShapes(outerEdge, innerEdge) | ||
const spacer = Sweep.fromPath(footprint, [0, 0, height]) | ||
|
||
console.log('JavaScript shape:', spacer) | ||
|
||
return spacer | ||
} | ||
|
||
/* type helpers */ | ||
|
||
// TODO derive from param definition | ||
interface ParamValues { | ||
outer: number | ||
inner: number | ||
height: number | ||
} | ||
|
||
declare global { | ||
export class Circle { | ||
static fromRadius: (radius: number) => Circle | ||
} | ||
export class Sketch { | ||
static fromCircle: (circle: Circle) => Sketch | ||
} | ||
interface Difference2dFromShapes { | ||
(a: Sketch, b: Sketch): Difference2d | ||
(a: Difference2d, b: Sketch): Difference2d | ||
(a: Sketch, b: Difference2d): Difference2d | ||
(a: Difference2d, b: Difference2d): Difference2d | ||
} | ||
export class Difference2d { | ||
static fromShapes: Difference2dFromShapes | ||
} | ||
interface SweepFromPath { | ||
(shape: Sketch, path: Array<number>): Sweep | ||
(shape: Difference2d, path: Array<number>): Sweep | ||
} | ||
export class Sweep { | ||
static fromPath: SweepFromPath | ||
} | ||
} | ||
|
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,31 @@ | ||
use anyhow::Error; | ||
use deno_core::resolve_path; | ||
use fj_operations::shape_processor::ShapeProcessor; | ||
use futures_lite::future; | ||
use nannou::draw::Draw; | ||
use nannou::prelude::*; | ||
|
||
mod engine; | ||
mod loader; | ||
mod model; | ||
mod module; | ||
mod viewer; | ||
|
||
use crate::engine::Engine; | ||
|
||
struct Model { | ||
engine: Engine, | ||
draw: Draw, | ||
fps: Option<f32>, | ||
} | ||
|
||
fn main() { | ||
nannou::app(model) | ||
.event(event) | ||
.update(update) | ||
.simple_window(view) | ||
.run(); | ||
} | ||
|
||
fn model(app: &App) -> Model { | ||
let draw = app.draw(); | ||
let mut engine = Engine::new(draw.clone()); | ||
use crate::model::ModelLoader; | ||
use crate::viewer::Viewer; | ||
|
||
fn main() -> Result<(), Error> { | ||
let mut loader = ModelLoader::new(); | ||
let current_dir = std::env::current_dir().expect("Unable to get CWD"); | ||
let sketch_path = resolve_path("./sketches/demo.ts", ¤t_dir).unwrap(); | ||
|
||
future::block_on(engine.compile(sketch_path)).unwrap(); | ||
|
||
Model { | ||
engine, | ||
draw: draw.clone(), | ||
fps: None, | ||
} | ||
} | ||
let model_path = resolve_path("./models/demo.ts", ¤t_dir)?; | ||
|
||
fn update(app: &App, model: &mut Model, _update: Update) { | ||
let draw = &model.draw; | ||
future::block_on(loader.load(model_path))?; | ||
|
||
draw.reset(); | ||
draw.background().color(BLUE); | ||
let shape = future::block_on(loader.get_shape())?; | ||
let shape_processor = ShapeProcessor { tolerance: None }; | ||
let processed_shape = shape_processor.process(&shape)?; | ||
|
||
future::block_on(model.engine.run(app.time)).unwrap(); | ||
let mut viewer = Viewer::new(processed_shape)?; | ||
|
||
/* | ||
let n = 5000; | ||
let t = app.time * 0.1; | ||
for i in 0..n { | ||
let a = i as f32 / n as f32; | ||
let b = (a + t) % 1.0; | ||
let x = (b * PI * 16.0).sin() * 500.0 * a; | ||
let y = (b * PI * 16.0).cos() * 500.0 * a; | ||
draw.rect().x_y(x, y).w_h(4.0, 4.0).color(PLUM); | ||
while viewer.render() { | ||
viewer.step() | ||
} | ||
*/ | ||
|
||
match model.fps { | ||
Some(fps) => model.fps = Some((app.fps() + fps) / 2.0), | ||
None => model.fps = Some(app.fps()), | ||
} | ||
} | ||
|
||
fn event(_app: &App, _model: &mut Model, _event: Event) {} | ||
|
||
fn view(app: &App, model: &Model, frame: Frame) { | ||
let draw = &model.draw; | ||
|
||
let fps = model.fps.unwrap_or(0.0).round(); | ||
|
||
let win = app.window_rect(); | ||
let win_p = win.pad(25.0); | ||
|
||
let rect = Rect::from_w_h(0.0, 0.0).top_left_of(win_p); | ||
draw.text(&fps.to_string()).xy(rect.xy()).font_size(20); | ||
|
||
draw.to_frame(app, &frame).unwrap(); | ||
Ok(()) | ||
} |
Oops, something went wrong.