Exclude mesh neighbors from collision detection

This commit is contained in:
Mikolaj Wielgus 2023-08-16 19:55:12 +02:00
parent 1a599951cd
commit 4f473bacec
4 changed files with 78 additions and 24 deletions

View File

@ -63,7 +63,7 @@ impl<T> Index<T> {
} }
} }
pub fn retag(&self, weight: TaggedWeight) -> TaggedIndex { pub fn retag(&self, weight: &TaggedWeight) -> TaggedIndex {
match weight { match weight {
TaggedWeight::Dot(..) => TaggedIndex::Dot(DotIndex { TaggedWeight::Dot(..) => TaggedIndex::Dot(DotIndex {
index: self.index, index: self.index,

View File

@ -177,11 +177,41 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot5 = layout
.add_dot(DotWeight {
net: 0,
circle: Circle {
pos: (150.5, 100.5).into(),
r: 8.0,
},
})
.unwrap();
let dot6 = layout
.add_dot(DotWeight {
net: 0,
circle: Circle {
pos: (190.5, 100.5).into(),
r: 8.0,
},
})
.unwrap();
let dot7 = layout
.add_dot(DotWeight {
net: 0,
circle: Circle {
pos: (230.5, 70.5).into(),
r: 8.0,
},
})
.unwrap();
let barrier1_dot1 = layout let barrier1_dot1 = layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 0, net: 0,
circle: Circle { circle: Circle {
pos: (250.5, 150.5).into(), pos: (250.5, 250.5).into(),
r: 8.0, r: 8.0,
}, },
}) })
@ -217,16 +247,20 @@ fn main() {
.unwrap(); .unwrap();
let _ = layout.add_seg(barrier2_dot1, barrier2_dot2, 16.0); let _ = layout.add_seg(barrier2_dot1, barrier2_dot2, 16.0);
let head = layout.route_start(dot5);
let head = layout.route_around_dot(head, dot6, true, 5.0).unwrap();
let _ = layout.route_finish(head, dot7, 5.0);
/*render_times(&mut event_pump, &mut canvas, &mut layout, None, -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 let head = layout
.route_around_dot(head, barrier1_dot1, true, 5.) .route_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout let head = layout
.route_around_dot(head, barrier2_dot1, true, 5.) .route_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
@ -236,12 +270,12 @@ fn main() {
let head = layout.route_start(dot2_1); let head = layout.route_start(dot2_1);
let head = layout let head = layout
.shove_around_dot(head, barrier1_dot1, true, 5.) .shove_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout let head = layout
.shove_around_dot(head, barrier2_dot1, true, 5.) .shove_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
@ -253,16 +287,16 @@ fn main() {
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout let head = layout
.shove_around_dot(head, barrier1_dot1, true, 5.) .shove_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout let head = layout
.shove_around_dot(head, barrier2_dot1, true, 5.) .shove_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let _ = layout.route_finish(head, dot3_2, 5.); let _ = layout.route_finish(head, dot3_2, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
@ -270,16 +304,16 @@ fn main() {
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout let head = layout
.shove_around_dot(head, barrier1_dot1, true, 5.) .shove_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let head = layout let head = layout
.shove_around_dot(head, barrier2_dot1, true, 5.) .shove_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
let _ = layout.route_finish(head, dot4_2, 5.);*/ let _ = layout.route_finish(head, dot4_2, 5.0);*/
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1); render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
render_times( render_times(

View File

@ -45,14 +45,14 @@ impl Mesh {
// Unnecessary retag. It should be possible to elide it. // Unnecessary retag. It should be possible to elide it.
let weight = *self.graph.node_weight(index.index).unwrap(); let weight = *self.graph.node_weight(index.index).unwrap();
let wrapper = RTreeWrapper::new(self.primitive(index).shape(), index.retag(weight)); let wrapper = RTreeWrapper::new(self.primitive(index).shape(), index.retag(&weight));
assert!(self.rtree.remove(&wrapper).is_some()); assert!(self.rtree.remove(&wrapper).is_some());
self.graph.remove_node(index.index); self.graph.remove_node(index.index);
} }
pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> { pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> {
let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight))); let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight)));
self.fail_and_remove_if_collides(dot)?; //self.fail_and_remove_if_collides_except(dot, &[])?;
self.rtree.insert(RTreeWrapper::new( self.rtree.insert(RTreeWrapper::new(
self.primitive(dot).shape(), self.primitive(dot).shape(),
@ -68,11 +68,11 @@ impl Mesh {
weight: SegWeight, weight: SegWeight,
) -> Result<SegIndex, ()> { ) -> Result<SegIndex, ()> {
let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight))); let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight)));
self.fail_and_remove_if_collides(seg)?;
self.graph.add_edge(from.index, seg.index, Label::End); self.graph.add_edge(from.index, seg.index, Label::End);
self.graph.add_edge(seg.index, to.index, Label::End); self.graph.add_edge(seg.index, to.index, Label::End);
//self.fail_and_remove_if_collides_except(seg, &[from.tag(), to.tag()])?;
self.insert_into_rtree(seg.tag()); self.insert_into_rtree(seg.tag());
Ok(seg) Ok(seg)
} }
@ -99,7 +99,7 @@ impl Mesh {
weight: BendWeight, weight: BendWeight,
) -> Result<BendIndex, ()> { ) -> Result<BendIndex, ()> {
let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight))); let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight)));
self.fail_and_remove_if_collides(bend)?; //self.fail_and_remove_if_collides_except(bend, &[from.tag(), to.tag(), core.tag()])?;
self.graph.add_edge(from.index, bend.index, Label::End); self.graph.add_edge(from.index, bend.index, Label::End);
self.graph.add_edge(bend.index, to.index, Label::End); self.graph.add_edge(bend.index, to.index, Label::End);
@ -173,7 +173,7 @@ impl Mesh {
dot_weight.circle.pos = to; dot_weight.circle.pos = to;
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight); *self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight);
if let Some(..) = self.detect_collision(&self.primitive(dot).shape()) { if let Some(..) = self.detect_collision_except(dot, &[]) {
// Restore original state. // Restore original state.
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(old_weight); *self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(old_weight);
self.insert_into_rtree(dot.tag()); self.insert_into_rtree(dot.tag());
@ -209,20 +209,34 @@ impl Mesh {
Bow::new(bend, &self.graph) Bow::new(bend, &self.graph)
} }
fn fail_and_remove_if_collides<Weight: std::marker::Copy>( fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>(
&mut self, &mut self,
index: Index<Weight>, index: Index<Weight>,
except: &[TaggedIndex],
) -> Result<(), ()> { ) -> Result<(), ()> {
/*if self.detect_collision(&self.primitive(index).shape()) { if let Some(..) = self.detect_collision_except(index, except) {
self.remove(index); self.remove(index);
return Err(()); return Err(());
}*/ }
Ok(()) Ok(())
} }
fn detect_collision(&self, shape: &Shape) -> Option<TaggedIndex> { fn detect_collision_except<Weight: std::marker::Copy>(
&self,
index: Index<Weight>,
except: &[TaggedIndex],
) -> Option<TaggedIndex> {
let primitive = self.primitive(index);
let shape = primitive.shape();
self.rtree self.rtree
.locate_in_envelope_intersecting(&shape.envelope()) .locate_in_envelope_intersecting(&shape.envelope())
.filter(|wrapper| {
!primitive
.neighbors()
.any(|neighbor| neighbor == wrapper.data)
})
.filter(|wrapper| !except.contains(&wrapper.data))
.filter(|wrapper| shape.intersects(wrapper.geom())) .filter(|wrapper| shape.intersects(wrapper.geom()))
.map(|wrapper| wrapper.data) .map(|wrapper| wrapper.data)
.next() .next()

View File

@ -49,6 +49,12 @@ impl<'a, Weight> Primitive<'a, Weight> {
} }
} }
pub fn neighbors(&self) -> impl Iterator<Item = TaggedIndex> + '_ {
self.graph
.neighbors_undirected(self.index.index)
.map(|index| Index::<Label>::new(index).retag(self.graph.node_weight(index).unwrap()))
}
pub fn next(&self) -> Option<TaggedIndex> { pub fn next(&self) -> Option<TaggedIndex> {
self.graph self.graph
.neighbors_directed(self.index.index, Outgoing) .neighbors_directed(self.index.index, Outgoing)
@ -58,7 +64,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
.unwrap() .unwrap()
.is_end() .is_end()
}) })
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap())) .map(|ni| Index::<Label>::new(ni).retag(self.graph.node_weight(ni).unwrap()))
.next() .next()
} }
@ -98,7 +104,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
.unwrap() .unwrap()
.is_end() .is_end()
}) })
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap())) .map(|ni| Index::<Label>::new(ni).retag(self.graph.node_weight(ni).unwrap()))
.next() .next()
} }
@ -144,7 +150,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn tagged_index(&self) -> TaggedIndex { pub fn tagged_index(&self) -> TaggedIndex {
self.index self.index
.retag(*self.graph.node_weight(self.index.index).unwrap()) .retag(self.graph.node_weight(self.index.index).unwrap())
} }
pub fn tagged_weight(&self) -> TaggedWeight { pub fn tagged_weight(&self) -> TaggedWeight {