Implement basic interactive dragging and stretching

This commit is contained in:
Mikolaj Wielgus 2023-07-29 22:29:08 +02:00
parent e5a1c52655
commit f9ec5a0ef7
4 changed files with 64 additions and 29 deletions

View File

@ -89,7 +89,8 @@ impl Layout {
let outer = self.mesh.primitive(around).outer().unwrap(); let outer = self.mesh.primitive(around).outer().unwrap();
let head = self.route_around_dot(head, around, cw, width); let head = self.route_around_dot(head, around, cw, width);
self.mesh.reattach_bend(outer, head.bend.unwrap()); self.mesh.reattach_bend(outer, head.bend.unwrap());
self.displace_outers(head.bend.unwrap());
self.reroute_outward(outer);
head head
} }
@ -116,7 +117,8 @@ impl Layout {
let outer = self.mesh.primitive(around).outer().unwrap(); let outer = self.mesh.primitive(around).outer().unwrap();
let head = self.route_around_bend(head, around, cw, width); let head = self.route_around_bend(head, around, cw, width);
self.mesh.reattach_bend(outer, head.bend.unwrap()); self.mesh.reattach_bend(outer, head.bend.unwrap());
self.displace_outers(head.bend.unwrap());
self.reroute_outward(outer);
head head
} }
@ -148,32 +150,41 @@ impl Layout {
Head {dot: bend_to, bend: Some(bend)} Head {dot: bend_to, bend: Some(bend)}
} }
fn displace_outers(&mut self, bend: BendIndex) { fn reroute_outward(&mut self, bend: BendIndex) {
let mut endss: Vec<[DotIndex; 2]> = vec![]; let mut endss: Vec<[DotIndex; 2]> = vec![];
let mut interiors: Vec<Vec<TaggedIndex>> = vec![]; let mut interiors: Vec<Vec<TaggedIndex>> = vec![];
let cw = self.mesh.primitive(bend).weight().cw; let cw = self.mesh.primitive(bend).weight().cw;
let mut cur_bend = bend; let mut cur_bend = bend;
while let Some(outer) = self.mesh.primitive(cur_bend).outer() { loop {
let bow = self.mesh.bow(outer); let bow = self.mesh.bow(cur_bend);
endss.push(bow.ends()); endss.push(bow.ends());
interiors.push(bow.interior()); interiors.push(bow.interior());
cur_bend = outer;
cur_bend = match self.mesh.primitive(cur_bend).outer() {
Some(new_bend) => new_bend,
None => break,
}
} }
let core = self.mesh.primitive(bend).core().unwrap();
let mut maybe_inner = self.mesh.primitive(bend).inner();
for interior in interiors { for interior in interiors {
self.mesh.remove_open_set(interior); self.mesh.remove_open_set(interior);
} }
let mut cur_bend = bend;
for ends in endss { for ends in endss {
let head = self.route_start(ends[0]); let mut head = self.route_start(ends[0]);
//let width = self.mesh.primitive(head.dot).weight().circle.r * 2.0;
let width = 5.0; let width = 5.0;
let head = self.route_around_bend(head, cur_bend, cw, width); if let Some(inner) = maybe_inner {
cur_bend = head.bend.unwrap(); head = self.route_around_bend(head, inner, cw, width);
} else {
head = self.route_around_dot(head, core, cw, width);
}
maybe_inner = head.bend;
self.route_finish(head, ends[1], width); self.route_finish(head, ends[1], width);
} }
} }
@ -191,6 +202,14 @@ impl Layout {
Head {dot: to_index, bend: None} Head {dot: to_index, bend: None}
} }
pub fn move_dot(&mut self, dot: DotIndex, to: Point) {
self.mesh.move_dot(dot, to);
if let Some(outer) = self.mesh.primitive(dot).outer() {
self.reroute_outward(outer);
}
}
fn head_guidecircle(&self, head: &Head, width: f64) -> Circle { fn head_guidecircle(&self, head: &Head, width: f64) -> Circle {
let maybe_bend = head.bend; let maybe_bend = head.bend;

View File

@ -10,6 +10,7 @@ mod shape;
mod math; mod math;
use std::time::Duration; use std::time::Duration;
use graph::{TaggedIndex, Tag};
use sdl2::EventPump; use sdl2::EventPump;
use sdl2::pixels::Color; use sdl2::pixels::Color;
use sdl2::event::Event; use sdl2::event::Event;
@ -98,57 +99,61 @@ fn main() {
let dot3_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (260.5, 260.5).into(), r: 8.0}}); let dot3_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (260.5, 260.5).into(), r: 8.0}});
let dot4_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (290.5, 290.5).into(), r: 8.0}}); let dot4_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (290.5, 290.5).into(), r: 8.0}});
let dot1_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (500.5, 200.5).into(), r: 8.0}}); let dot1_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (600.5, 200.5).into(), r: 8.0}});
let dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (470.5, 230.5).into(), r: 8.0}}); let dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (570.5, 230.5).into(), r: 8.0}});
let dot3_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (440.5, 260.5).into(), r: 8.0}}); let dot3_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (540.5, 260.5).into(), r: 8.0}});
let dot4_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (410.5, 290.5).into(), r: 8.0}}); let dot4_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (510.5, 290.5).into(), r: 8.0}});
let barrier_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (350.5, 150.5).into(), r: 8.0}}); let barrier_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (400.5, 150.5).into(), r: 8.0}});
let barrier_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (350.5, 500.5).into(), r: 8.0}}); let barrier_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (400.5, 500.5).into(), r: 8.0}});
layout.add_seg(barrier_dot1, barrier_dot2, 16.0); layout.add_seg(barrier_dot1, barrier_dot2, 16.0);
render_times(&mut event_pump, &mut canvas, &mut layout, -1); render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
let head = layout.route_start(dot1_1); let head = layout.route_start(dot1_1);
let head = layout.route_around_dot(head, barrier_dot1, true, 5.0); let head = layout.route_around_dot(head, barrier_dot1, true, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
layout.route_finish(head, dot1_2, 5.0); layout.route_finish(head, dot1_2, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout.route_start(dot2_1); let head = layout.route_start(dot2_1);
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0); let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
layout.route_finish(head, dot2_2, 5.0); layout.route_finish(head, dot2_2, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout.route_start(dot3_1); let head = layout.route_start(dot3_1);
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0); let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
layout.route_finish(head, dot3_2, 5.0); layout.route_finish(head, dot3_2, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout.route_start(dot4_1); let head = layout.route_start(dot4_1);
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0); let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
layout.route_finish(head, dot4_2, 5.0); layout.route_finish(head, dot4_2, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, -1); render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
render_times(&mut event_pump, &mut canvas, &mut layout, Some(barrier_dot1.tag()), -1);
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
} }
fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout: &mut Layout, times: i64) { fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout: &mut Layout,
follower: Option<TaggedIndex>, times: i64)
{
let mut i = 0; let mut i = 0;
'running: loop { 'running: loop {
@ -165,6 +170,12 @@ fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout:
} }
} }
if let Some(follower) = follower {
let state = event_pump.mouse_state();
layout.move_dot(*follower.as_dot().unwrap(), (state.x() as f64, state.y() as f64).into());
}
for shape in layout.shapes() { for shape in layout.shapes() {
if let Some(center) = shape.center { if let Some(center) = shape.center {
let circle = shape.circle().unwrap(); let circle = shape.circle().unwrap();

View File

@ -105,6 +105,11 @@ impl Mesh {
pub fn extend_bend(&mut self, bend: BendIndex, dot: DotIndex, to: Point) { pub fn extend_bend(&mut self, bend: BendIndex, dot: DotIndex, to: Point) {
self.remove_from_rtree(bend.tag()); self.remove_from_rtree(bend.tag());
self.move_dot(dot, to);
self.insert_into_rtree(bend.tag());
}
pub fn move_dot(&mut self, dot: DotIndex, to: Point) {
self.remove_from_rtree(dot.tag()); self.remove_from_rtree(dot.tag());
let mut dot_weight = self.primitive(dot).weight(); let mut dot_weight = self.primitive(dot).weight();
@ -112,7 +117,6 @@ impl Mesh {
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight); *self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight);
self.insert_into_rtree(dot.tag()); self.insert_into_rtree(dot.tag());
self.insert_into_rtree(bend.tag());
} }
pub fn nodes(&self) -> impl Iterator<Item=TaggedIndex> + '_ { pub fn nodes(&self) -> impl Iterator<Item=TaggedIndex> + '_ {

View File

@ -6,6 +6,7 @@ use petgraph::stable_graph::StableDiGraph;
use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label}; use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label};
use crate::shape::Shape; use crate::shape::Shape;
#[derive(Debug)]
pub struct Primitive<'a, Weight> { pub struct Primitive<'a, Weight> {
pub index: Index<Weight>, pub index: Index<Weight>,
graph: &'a StableDiGraph<TaggedWeight, Label, usize>, graph: &'a StableDiGraph<TaggedWeight, Label, usize>,