Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion visualize/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub(crate) mod model;
pub use model::{Model, Technique};
pub use model::Model;
13 changes: 7 additions & 6 deletions visualize/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,19 @@ fn create_model(app: &App) -> Model {
fn raw_window_event(app: &App, model: &mut Model, event: &WindowEvent) {
// Let egui handle things like keyboard and mouse input.
model.egui.handle_raw_event(event);
model.mouse_position = None;
model.set_mouse_position(None);

// Get the egui context
let ctx = model.egui.ctx();

// Handle mouse input
if let WindowEvent::MouseInput { state, button, .. } = event {
let point = Point::new(&[app.mouse.x, app.mouse.y]);
model.mouse_position = Some(point);
if !ctx.wants_pointer_input() {
// Only add points if egui is not handling the pointer input
let wants_pointer_input = ctx.wants_pointer_input();
model.set_mouse_position(Some(point));

// Only add points if egui is not handling the pointer input
if !wants_pointer_input {
// Left-click (adding point manually)
if *button == MouseButton::Left && *state == ElementState::Pressed {
model.add_point(point);
Expand All @@ -50,7 +51,7 @@ fn raw_window_event(app: &App, model: &mut Model, event: &WindowEvent) {
}
} else if let WindowEvent::CursorMoved { .. } = event {
let point = Point::new(&[app.mouse.x, app.mouse.y]);
model.mouse_position = Some(point);
model.set_mouse_position(Some(point));
}
}

Expand All @@ -66,7 +67,7 @@ fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();

// Draw the points, mouse query circle and QuadTree rectangles
model.draw_app(&draw, &model.points);
model.draw_app(&draw);

// Draw FPS counter
let fps = app.fps();
Expand Down
36 changes: 11 additions & 25 deletions visualize/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,11 @@ const RADIUS: f32 = 100.0;
const DOT_SIZE: f32 = 7.5;
type Point2D = Point<2>;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Technique {
/// Use comparision of coordinates to determine distance
Cartesian,
/// Use a quadtree to determine distance
Quadtree,
}

pub struct Model {
pub egui: Egui,
pub points: Vec<Point2D>,
pub mouse_position: Option<Point2D>,
pub region: Region<2>,
points: Vec<Point2D>,
mouse_position: Option<Point2D>,
region: Region<2>,
rng: StdRng,
}

Expand All @@ -49,6 +41,10 @@ impl Model {
})
}

pub fn set_mouse_position(&mut self, position: Option<Point2D>) {
self.mouse_position = position;
}

pub fn add_point(&mut self, point: Point2D) {
self.points.push(point);
}
Expand All @@ -71,18 +67,7 @@ impl Model {
qt
}

fn points_within_distance(
&self,
qt: &QuadTree<2, Point2D>,
center: &Point2D,
distance: f64,
) -> HashSet<Point2D> {
// Query
let distance_squared = center.to_distance_based_query(distance);
qt.query(&distance_squared).cloned().collect()
}

pub fn draw_app(&self, draw: &Draw, points: &[Point2D]) {
pub fn draw_app(&self, draw: &Draw) {
let qt = self.quadtree();
// Draw circle around the mouse position if it exists, and find points within that circle.
let points_inside_query = match &self.mouse_position {
Expand All @@ -95,13 +80,14 @@ impl Model {
.stroke_weight(2.0)
.no_fill();

self.points_within_distance(&qt, &Point::new(coords), RADIUS as f64)
let distance_query = &Point::new(coords).to_distance_based_query(RADIUS as f64);
qt.query(distance_query).cloned().collect()
}
None => HashSet::new(),
};

// Draw the points, colouring them based on whether they are inside the query circle.
for point in points {
for point in &self.points {
let coords = point.dimension_values();
let color = if points_inside_query.contains(point) {
GREEN
Expand Down