I (a newbie in Rust) am trying to sort a vector of structs (first by X-coordinate, and then by Y-coordinates) in Rust. The MWE below does the sorting along 'X', how do I include the sorting along 'Y' ?
Desired result -> [(0.0,0.0), (0.0,2.0), (2.0,0.0), (2.0,2.0)]
Your help will be be greatly appreciated. Thanks!
#![allow(unused)]
use std::cmp::Ordering;
#[derive(Debug)]
struct Point {
x: f64,
y: f64
}
impl PartialOrd for Point {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.x.partial_cmp(&other.x)
}
}
impl PartialEq for Point {
fn eq(&self, other: &Self) -> bool {
self.x == other.x
}
}
fn main() {
let p1 = Point { x: 0.0, y: 0.0 };
let p2 = Point { x: 2.0, y: 0.0 };
let p3 = Point { x: 2.0, y: 2.0 };
let p4 = Point { x: 0.0, y: 2.0 };
let mut pts = vec![];
pts.push(p1);
pts.push(p2);
pts.push(p3);
pts.push(p4);
pts.sort_by(|a, b| b.x.partial_cmp(&a.x).unwrap());
println!("{:?}",pts); // -> [(2.0,0.0), (2.0,2.0), (0.0,0.0), (0.0,2.0)]
}
Use a tuple for the comparision:
pts.sort_by(|a, b| (a.x, a.y).partial_cmp(&(b.x, b.y)).unwrap());
Playground
Related
I have a simple QuadTree. For readability and to help me understand what is happening, It avoids recursion and has a static depth. The QuadTree stores references to the points that are owned by another container.
struct QuadLeaf<'a> {
vec: Vec<&'a (f32,f32)>,
rect: (f32, f32, f32, f32)
}
struct QuadTwig<'a> {
cells: [QuadLeaf<'a>; 4],
}
struct QuadBranch<'a> {
cells: [QuadTwig<'a>; 4],
}
struct QuadTree<'a> {
cells: [QuadBranch<'a>; 4],
}
Constructing and inserting into this tree is relatively simple. The QuadLeaf is constructed with a bounding rect and an empty vec, and has a method that attempts to insert a point. It returns true if the point is within the rect and has been inserted.
impl<'a> QuadLeaf<'a> {
fn new(rect: (f32, f32, f32, f32)) -> Self {
QuadLeaf {vec: Vec::new(),rect}
}
fn insert(&mut self, point: &'a (f32, f32)) -> bool {
if is_point_in_rect(point.0, point.1, self.rect) {
self.vec.push(point);
true
} else {
false
}
}
}
The QuadTwig new function splits the bounding rect into 4 and creates 4 new QuadLeafs . It's insert function attempts to insert into each leaf, short circuiting when it is successful, and returning false if unsuccessful.
impl<'a> QuadTwig<'a> {
fn new(rect: (f32, f32, f32, f32)) -> Self {
let rects = divide_into_4(rect);
QuadTwig {
cells: [
QuadLeaf::new(rects[0]),
QuadLeaf::new(rects[1]),
QuadLeaf::new(rects[2]),
QuadLeaf::new(rects[3])
]
}
}
fn insert(&mut self, point: &'a (f32, f32)) -> bool {
for cell in self.cells.iter_mut() {
if cell.insert(point) {
return true;
}
}
false
}
}
The implementations for QuadBranch and QuadTree are exactly the same, but the new function just constructs the next level down in the tree. This could be refactored later for less code duplication, but for demonstration purposes I will leave it. I also think it does not matter for the context of this question.
Question:
I want to create an Iterator that yields each point in the tree, and the 9 leaves that it is close to (or inside of).
I have managed to create a simpler version, that just yields each point and the leaf it is in:
/// An Iterator that yields each point and the leaf it is in
struct PointAndLeafIterator<'a> {
ptr: &'a QuadTree<'a>,
index: (usize, usize, usize, usize)
}
/// An Iterator that yields each point and the leaf it is in
impl<'a> Iterator for PointAndLeafIterator<'a> {
/// Returns (point, leaf)
type Item = (&'a (f32, f32), Vec<&'a (f32, f32)>);
/// Starts at (0,0,0,0) and ends at (3, 3, 3, num_points_in_leaf)
/// It increases the index by 1 each time, and if it reaches the end of the cell, it moves to the next cell
fn next(&mut self) -> Option<Self::Item> {
let (branch_index, twig_index, leaf_index, point_index) = &mut self.index;
let branch = &self.ptr.cells[*branch_index];
let twig = &branch.cells[*twig_index];
let leaf = &twig.cells[*leaf_index];
let point = leaf.vec.get(*point_index);
//go through all the points in the leaf
if let Some(point) = point {
*point_index += 1;
return Some((point, leaf.vec.clone()));
}
//if we reach the end of the leaf, go to the next leaf
*point_index = 0;
*leaf_index += 1;
if *leaf_index < 4 {
return self.next();
}
//if we reach the end of the twig, go to the next twig
*leaf_index = 0;
*twig_index += 1;
if *twig_index < 4 {
return self.next();
}
//if we reach the end of the branch, go to the next branch
*twig_index = 0;
*branch_index += 1;
if *branch_index < 4 {
return self.next();
}
//if we reach the end of the tree, we are done
None
}
}
This can be used like this:
fn main() {
let points: Vec<(f32, f32)> = vec![
(0.0, 0.0),
(1.0, 1.0),
(31.0,31.0),
(2.0, 2.0),
(3.0, 3.0),
(32.0,32.0),
];
let mut quadtree = QuadTree::new((0.0, 0.0, 40.0, 40.0));
for point in points.iter() {
quadtree.insert(point);
}
for (point, leaf) in quadtree.into_point_and_leaf_iter() {
println!("Point: {:?}", point);
println!("Leaf: {:?}", leaf);
}
}
However the neighbouring version is proving to be much more difficult. How can I write this algorithm?
/// An Iterator that yields each point, the leaf it is in, and the neighbouring leaves
struct PointAndLeafAndNeighboursIterator<'a> {
ptr: &'a QuadTree<'a>,
index: (usize, usize, usize, usize)
}
impl<'a> Iterator for PointAndLeafAndNeighboursIterator<'a> {
///Return the 9 leaves that surround the point
///If there is no leaf in a direction, it will return an empty leaf
type Item = (&'a (f32, f32), [Vec<&'a (f32, f32)>; 9]);
/// Starts at (0,0,0,0) and ends at (3, 3, 3, num_points_in_leaf)
/// It increases the index by 1 each time, and if it reaches the end of the cell, it moves to the next cell
fn next(&mut self) -> Option<Self::Item> {
unimplemented!()
}
}
Here is a Rust playground link to all code in this question.
My implementation.
First I added indexing by leaf indices since the QuadTree struct is basically an 8x8 matrix of leaves.
use std::ops::Index;
#[derive(Clone, Copy, Debug)]
struct QuadLeafId {
x: i8,
y: i8,
}
impl QuadLeafId {
fn new(x: i8, y: i8) -> Self {
Self { x, y }
}
fn level_index(&self, level: usize) -> usize {
(((self.y >> level) % 2) * 2 + ((self.x >> level) % 2)) as usize
}
/// Extract the QuadTwig array index containing this leaf
fn twig_index(&self) -> usize {
self.level_index(0)
}
/// Extract the QuadBranch array index containing this leaf
fn branch_index(&self) -> usize {
self.level_index(1)
}
/// Extract the QuadTree array index containing this leaf
fn tree_index(&self) -> usize {
self.level_index(2)
}
}
impl<'a> Index<QuadLeafId> for QuadTwig<'a> {
type Output = QuadLeaf<'a>;
fn index(&self, index: QuadLeafId) -> &Self::Output {
&self.cells[index.twig_index()]
}
}
impl<'a> Index<QuadLeafId> for QuadBranch<'a> {
type Output = QuadLeaf<'a>;
fn index(&self, index: QuadLeafId) -> &Self::Output {
&self.cells[index.branch_index()][index]
}
}
impl<'a> Index<QuadLeafId> for QuadTree<'a> {
type Output = QuadLeaf<'a>;
fn index(&self, index: QuadLeafId) -> &Self::Output {
&self.cells[index.tree_index()][index]
}
}
Then added iterating over nearby leaves in a QuadTree
impl QuadLeafId {
/// The ids of the 9 nearby leaves
fn near_ids(self) -> impl Iterator<Item = Self> {
(-1..=1).flat_map(move |x| {
(-1..=1).map(move |y| Self {
x: self.x + x,
y: self.y + y,
})
})
}
fn is_valid(&self) -> bool {
0 <= self.y && self.y < 8 && 0 <= self.x && self.x < 8
}
}
impl<'a> QuadTree<'a> {
fn get_leaf(&self, id: QuadLeafId) -> Option<&QuadLeaf<'a>> {
id.is_valid().then(|| &self[id])
}
fn near_leaves(&self, id: QuadLeafId) -> impl Iterator<Item = Option<&QuadLeaf<'a>>> {
id.near_ids().map(|id| self.get_leaf(id))
}
}
Implementing the iterator afterwards is straightforward:
impl QuadLeafId {
fn next_id(mut self) -> Option<Self> {
self.x += 1;
if self.x < 8 {
return Some(self);
}
self.x = 0;
self.y += 1;
(self.y < 8).then_some(self)
}
}
impl<'a> QuadTree<'a> {
fn into_point_and_leaf_and_neighbours_iter(
&'a mut self,
) -> PointAndLeafAndNeighboursIterator<'a> {
PointAndLeafAndNeighboursIterator::<'a> {
ptr: self,
index: Some(QuadLeafId::new(0, 0)),
point_index: 0,
}
}
}
/// An Iterator that yields each point, the leaf it is in, and the neighboring leaves
struct PointAndLeafAndNeighboursIterator<'a> {
ptr: &'a QuadTree<'a>,
index: Option<QuadLeafId>,
point_index: usize,
}
impl<'a> Iterator for PointAndLeafAndNeighboursIterator<'a> {
///Return the 9 leaves that surround the point
///If there is no leaf in a direction, it will return an empty leaf
type Item = (&'a (f32, f32), [Vec<&'a (f32, f32)>; 9]);
/// Starts at (0,0,0,0) and ends at (3, 3, 3, num_points_in_leaf)
/// It increases the index by 1 each time, and if it reaches the end of the cell, it moves to the next cell
fn next(&mut self) -> Option<Self::Item> {
loop {
let ind = self.index?;
let leaf = &self.ptr[ind];
if let Some(point) = leaf.vec.get(self.point_index) {
self.point_index += 1;
let mut iter = self
.ptr
.near_leaves(ind)
.map(|leaf| leaf.map(|leaf| leaf.vec.clone()).unwrap_or_default());
return Some((*point, [(); 9].map(|_| iter.next().unwrap())));
}
self.point_index = 0;
self.index = ind.next_id();
}
}
}
I'm using binary trees to create a simple computation graph. I understand that linked lists are a pain in Rust, but it's a very convenient data structure for what I'm doing. I tried using Box and Rc<RefCell> for the children nodes, but it didn't work out how I wanted, so I used unsafe:
use std::ops::{Add, Mul};
#[derive(Debug, Copy, Clone)]
struct MyStruct {
value: i32,
lchild: Option<*mut MyStruct>,
rchild: Option<*mut MyStruct>,
}
impl MyStruct {
unsafe fn print_tree(&mut self, set_to_zero: bool) {
if set_to_zero {
self.value = 0;
}
println!("{:?}", self);
let mut nodes = vec![self.lchild, self.rchild];
while nodes.len() > 0 {
let child;
match nodes.pop() {
Some(popped_child) => child = popped_child.unwrap(),
None => continue,
}
if set_to_zero {
(*child).value = 0;
}
println!("{:?}", *child);
if !(*child).lchild.is_none() {
nodes.push((*child).lchild);
}
if !(*child).rchild.is_none() {
nodes.push((*child).rchild);
}
}
println!("");
}
}
impl Add for MyStruct {
type Output = Self;
fn add(self, other: Self) -> MyStruct {
MyStruct{
value: self.value + other.value,
lchild: Some(&self as *const _ as *mut _),
rchild: Some(&other as *const _ as *mut _),
}
}
}
impl Mul for MyStruct {
type Output = Self;
fn mul(self, other: Self) -> Self {
MyStruct{
value: self.value * other.value,
lchild: Some(&self as *const _ as *mut _),
rchild: Some(&other as *const _ as *mut _),
}
}
}
fn main() {
let mut tree: MyStruct;
{
let a = MyStruct{ value: 10, lchild: None, rchild: None };
let b = MyStruct{ value: 20, lchild: None, rchild: None };
let c = a + b;
println!("c.value: {}", c.value); // 30
let mut d = a + b;
println!("d.value: {}", d.value); // 30
d.value = 40;
println!("d.value: {}", d.value); // 40
let mut e = c * d;
println!("e.value: {}", e.value); // 1200
unsafe {
e.print_tree(false); // correct values
e.print_tree(true); // all zeros
e.print_tree(false); // all zeros, everything is set correctly
}
tree = e;
}
unsafe { tree.print_tree(false); } // same here, only zeros
}
Link to the playground
I honestly don't mind that much using unsafe, but is there a safe way doing it? How bad is the use of unsafe here?
You can just box both of the children, since you have a unidirectional tree:
use std::ops::{Add, Mul};
use std::fmt;
#[derive(Clone)]
struct MyStruct {
value: i32,
lchild: Option<Box<MyStruct>>,
rchild: Option<Box<MyStruct>>,
}
impl fmt::Debug for MyStruct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("MyStruct")
.field("value", &self.value)
.field("lchild", &self.lchild.as_deref())
.field("rchild", &self.rchild.as_deref())
.finish()
}
}
impl MyStruct {
fn print_tree(&mut self, set_to_zero: bool) {
if set_to_zero {
self.value = 0;
}
println!("MyStruct {{ value: {:?}, lchild: {:?}, rchild: {:?} }}", self.value, &self.lchild as *const _, &self.rchild as *const _);
if let Some(child) = &mut self.lchild {
child.print_tree(set_to_zero);
}
if let Some(child) = &mut self.rchild {
child.print_tree(set_to_zero);
}
}
}
impl Add for MyStruct {
type Output = Self;
fn add(self, other: Self) -> MyStruct {
MyStruct {
value: self.value + other.value,
lchild: Some(Box::new(self)),
rchild: Some(Box::new(other)),
}
}
}
impl Mul for MyStruct {
type Output = Self;
fn mul(self, other: Self) -> Self {
MyStruct {
value: self.value * other.value,
lchild: Some(Box::new(self)),
rchild: Some(Box::new(other)),
}
}
}
fn main() {
let tree = {
let a = MyStruct {
value: 10,
lchild: None,
rchild: None,
};
let b = MyStruct {
value: 20,
lchild: None,
rchild: None,
};
let c = a.clone() + b.clone();
println!("c.value: {}", c.value); // 30
let mut d = a.clone() + b.clone();
println!("d.value: {}", d.value); // 30
d.value = 40;
println!("d.value: {}", d.value); // 40
let mut e = c * d;
println!("e.value: {}", e.value); // 1200
println!("");
e.print_tree(false); // correct values
println!("");
e.print_tree(true); // all zeros
println!("");
e.print_tree(false); // all zeros, everything is set correctly
println!("");
e
};
dbg!(tree);
}
I implemented Debug manually and reimplemented print_tree recursively. I don't know if there is a way to implement print_tree as mutable like that without recursion, but it's certainly possible if you take &self instead (removing the set_to_zero stuff).
playground
Edit: Turns out it is possible to mutably iterate over the tree values without recursion. The following code is derived from the playground in this comment by #Shepmaster.
impl MyStruct {
fn zero_tree(&mut self) {
let mut node_stack = vec![self];
let mut value_stack = vec![];
// collect mutable references to each value
while let Some(MyStruct { value, lchild, rchild }) = node_stack.pop() {
value_stack.push(value);
if let Some(child) = lchild {
node_stack.push(child);
}
if let Some(child) = rchild {
node_stack.push(child);
}
}
// iterate over mutable references to values
for value in value_stack {
*value = 0;
}
}
}
In glsl and hlsl, I can define a function like this:
float voronoi(vec2 x, out int2 cell) {
cell = ...
return ...
}
However, it doesn't seem like this is possible in wgsl.
What's the intended replacement for this? I guess I could define a VoronoiResult struct, but it seems overly boilerplate heavy:
struct VoronoiResult {
cell: vec2<i32>;
distance: f32;
};
fn voronoi(x: vec2<f32>) -> VoronoiResult {
// ...
var ret: VoronoiResult;
ret.distance = distance;
ret.cell = cell;
return ret;
}
The equivalent would be to use a pointer argument:
fn voronoi(x: vec2<f32>, cell: ptr<function, vec2<i32>>) -> f32 {
*cell = vec2(1, 2);
return 1.f;
}
#compute #workgroup_size(1)
fn main() {
var a: vec2<i32>;
var f = voronoi(vec2(1.f, 1.f), &a);
}
This produces the HLSL:
float voronoi(float2 x, inout int2 cell) {
cell = int2(1, 2);
return 1.0f;
}
[numthreads(1, 1, 1)]
void main() {
int2 a = int2(0, 0);
float f = voronoi((1.0f).xx, a);
return;
}
You can also make the struct version shorter by using the struct initializer:
struct Out {
cell: vec2<i32>,
val: f32,
}
fn voronoi(x: vec2<f32>) -> Out {
return Out(vec2(1, 2), 1.f);
}
#compute #workgroup_size(1)
fn main() {
var f = voronoi(vec2(1.f, 1.f));
}
I need to iterate over a mutable vector, and inside of the for loop I also need to pass the vector into a function that modifies the current object.
pub struct Vector2 {
x: f64,
y: f64,
}
pub struct Planet {
position: Vector2,
init_velocity: Vector2,
curr_velocity: Vector2,
radius: f64,
mass: f64,
}
impl Planet {
pub fn update_velocity(
&mut self,
other_planets: &Vec<Planet>,
grav_constant: f64,
timestep: f64,
) {
for p in other_planets {
// Calculate self's velocity relative to all other planets
}
}
pub fn update_position(&mut self) {
self.position.x = self.position.x + self.curr_velocity.x;
self.position.y = self.position.y + self.curr_velocity.y;
}
}
fn main() {
let mut planets = Vec::<Planet>::new();
planets.push(Planet {
position: Vector2 { x: 10.0, y: 10.0 },
init_velocity: Vector2 { x: 1.0, y: 1.0 },
curr_velocity: Vector2 { x: 1.0, y: 1.0 },
radius: 20.0,
mass: 500.0,
});
for p in &mut planets {
p.update_velocity(&planets, 0.0000000000674 as f64, 0.0);
p.update_position();
}
}
error[E0502]: cannot borrow `planets` as immutable because it is also borrowed as mutable
--> src/main.rs:42:27
|
41 | for p in &mut planets {
| ------------
| |
| mutable borrow occurs here
| mutable borrow later used here
42 | p.update_velocity(&planets, 0.0000000000674 as f64, 0.0);
| ^^^^^^^^ immutable borrow occurs here
Because a mutable borrow of planets exists, it's not possible to make an immutable or even another mutable value and I can't see a way around this conundrum.
Unfortunately you can't easily do that, compiler only allow one mutable borrow or multiple borrow at the same time. Even if you feel like this should be legal from the point of view of rust it isn't.
There is several way to fix it:
use index directly
use interior mutability
have a better solution that avoid the problem
In your case I think use index make sense, because you don't want to have the current planets in other planet, so we can mutate the vector to put the current planet at the end and make a sub slice of other planets:
#[derive(Debug)]
pub struct Vector2 {
x: f64,
y: f64,
}
#[derive(Debug)]
pub struct Planet {
position: Vector2,
init_velocity: Vector2,
curr_velocity: Vector2,
radius: f64,
mass: f64,
}
impl Planet {
pub fn update_velocity(&mut self, other_planets: &[Planet], grav_constant: f64, timestep: f64) {
println!("{:#?}", other_planets);
}
pub fn update_position(&mut self) {
self.position.x = self.position.x + self.curr_velocity.x;
self.position.y = self.position.y + self.curr_velocity.y;
}
}
struct Guard<'a, T> {
slice: &'a mut [T],
a: usize,
b: usize,
}
impl<'a, T> Guard<'a, T> {
fn new(slice: &'a mut [T], a: usize, b: usize) -> Self {
slice.swap(a, b);
Self { slice, a, b }
}
fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
self.slice.split_last_mut()
}
}
impl<'a, T> Drop for Guard<'a, T> {
fn drop(&mut self) {
self.slice.swap(self.a, self.b);
}
}
fn main() {
let mut planets = Vec::<Planet>::new();
planets.push(Planet {
position: Vector2 { x: 10.0, y: 10.0 },
init_velocity: Vector2 { x: 1.0, y: 1.0 },
curr_velocity: Vector2 { x: 1.0, y: 1.0 },
radius: 20.0,
mass: 500.0,
});
planets.push(Planet {
position: Vector2 { x: 20.0, y: 20.0 },
init_velocity: Vector2 { x: 2.0, y: 2.0 },
curr_velocity: Vector2 { x: 2.0, y: 2.0 },
radius: 40.0,
mass: 1000.0,
});
planets.push(Planet {
position: Vector2 { x: 40.0, y: 40.0 },
init_velocity: Vector2 { x: 4.0, y: 4.0 },
curr_velocity: Vector2 { x: 4.0, y: 4.0 },
radius: 80.0,
mass: 2000.0,
});
let len = planets.len();
let last = len - 1;
for i in 0..len {
let mut g = Guard::new(&mut planets, i, last);
let (p, other_planets) = g.split_last_mut().unwrap(); // can't fail
p.update_velocity(&other_planets, 0.0000000000674 as f64, 0.0);
p.update_position();
}
}
Playground, Guard only exist to avoid mistake, the key function is split_last_mut() that will split our planets into the one we want to process and the rest.
See:
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?
You could try using indexes to refer to a specific planet without applying the borrowing rules. And you should avoid splitting a vec of planets into two parts (the actual and the others).
pub struct Vector2 {
x: f64,
y: f64,
}
pub struct Planet {
position: Vector2,
init_velocity: Vector2,
curr_velocity: Vector2,
radius: f64,
mass: f64,
}
impl Planet {
fn update_velocity_of_all_planets(
self_idx: usize,
planets: &mut Vec<Planet>,
grav_constant: f64,
timestep: f64,
) {
for p in planets {
// Do maths stuff with other planets
}
}
pub fn update_position(&mut self) {
self.position.x = self.position.x + self.curr_velocity.x;
self.position.y = self.position.y + self.curr_velocity.y;
}
}
fn main() {
let mut planets = Vec::<Planet>::new();
planets.push(Planet {
position: Vector2 { x: 10.0, y: 10.0 },
init_velocity: Vector2 { x: 1.0, y: 1.0 },
curr_velocity: Vector2 { x: 1.0, y: 1.0 },
radius: 20.0,
mass: 500.0,
});
for idx in 0..planets.len() {
Planet::update_velocity_of_all_planets(idx, &mut planets, 0.0000000000674 as f64, 0.0);
planets[idx].update_position();
}
}
I'm trying to implement a method:
struct Point<T> {
x: T,
y: T,
}
struct Line<T> {
start: Point<T>,
end: Point<T>,
}
impl Line {
fn length(&self) -> f64 {
let dx: f64 = self.start.x - self.end.x;
let dy: f64 = self.start.y - self.end.y;
(dx * dx + dy * dy).sqrt()
}
}
fn main() {
let point_start: Point<f64> = Point { x: 1.4, y: 1.24 };
let point_end: Point<f64> = Point { x: 20.4, y: 30.64 };
let line_a: Line<f64> = Line {
start: point_start,
end: point_end,
};
println!("length of line_a = {}", line_a.length());
}
I'm getting this error:
error[E0243]: wrong number of type arguments: expected 1, found 0
--> src/main.rs:11:6
|
11 | impl Line {
| ^^^^ expected 1 type argument
What is causing this problem?
You need to add a type parameter to the impl:
impl Line<f64> {
fn length(&self) -> f64 {
let dx: f64 = self.start.x - self.end.x;
let dy: f64 = self.start.y - self.end.y;
(dx * dx + dy * dy).sqrt()
}
}