Michael-F-Bryan / arcs

A Rust CAD System
https://michael-f-bryan.github.io/arcs
Apache License 2.0
253 stars 22 forks source link

Grid implementation #29

Open samsamai opened 4 years ago

samsamai commented 4 years ago

Thanks for your work on this library, I have been playing around with it and I would like to see it develop further. I was hoping to contribute to it but some guidance would be helpful.

I'm looking to implement a grid, was wondering what your thoughts were regarding how it should be done, should it be another primitive type or should it be described as a window style? Or some other way?

Michael-F-Bryan commented 4 years ago

How I've implemented grids in the past is to have some sort of Grid object which keeps track of things like the current grid spacing and maybe object snap settings.

Then whenever a mouse event comes in and you need to do something (e.g. drag a point around the canvas) you pass the raw mouse location to the Grid and ask what the "effective" mouse location is.

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Point {
    x: f64,
    y: f64,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Snaps {
    grid_spacing: Option<f64>,
}

impl Snaps {
    pub fn effective_location(&self, raw_mouse_location: Point) -> Point {
        match self.grid_spacing {
            Some(spacing) => {
                Point {
                    x: raw_mouse_location.x % spacing,
                    y: raw_mouse_location.y % spacing,
                }
            }
            None => raw_mouse_location,
        }
    }
}

Actually rendering the grid should really be done by the CAD engine as part of its rendering process. I'd probably implement some sort of layering system where a drawing contains a Vec<Box<dyn Layer>> ordered by z-level and you ask each layer to render in turn. Normal layers would draw objects as normal (cull objects outside the viewport, convert from drawing space to canvas space, render to the canvas with normal line/arc/spline drawing algorithms, etc.), but then you have custom logic for things like the grid and background.

This ties in with how users normally organise their drawings (e.g. you might have a layer for dimension lines, a layer for the drawing itself, and a layer for page outline and title boxes), except things like the grid and background would be treated as "system" layers that are inaccessible to users.

samsamai commented 4 years ago

Thanks for your detailed response @Michael-F-Bryan, I'll start working on this.

samsamai commented 4 years ago

Hi @Michael-F-Bryan, I have the basic snapping and grid working in this experimental app based on your old demo: https://github.com/samsamai/arcs-wasm-experiment I ended up making the grid another primitive type as I was just learning about ECS but looking back at it now, it could probably be a resource. With the snapping, I created a new system which modifies the supplied cursor position to the ECS, this then affects other systems (such as the mover) down stream.