Hi rust community!
I want to create a program which will define the angle between two vectors !
Is cgmath the way to do that ?
Typing something like "angle between two vectors" or "angle between two vectors 3d" into google is the way to do that.
Of course if you add "rust" to your search term you soon find a Crate to help. For example: ami::Vector - Rust
use cgmath::Rad;
pub struct Vector {
pub x: f32,
pub y: f32,
}
impl Vector {
pub fn angle(self, rhs: Self) -> f32 {
(self.dot(rhs) / self.length()).acos()
}
}
fn main() {
}
Am I in a good way ?
Hi, if you're planning on using cgmath
, use InnerSpace::angle
. This is implemented for Vector3
, so you can use it through that.
Can you give me an example code with the InnerSpace::angle ?
use cgmath::{prelude::*, Vector3};
fn main() {
let v1 = Vector3::new(0.3, 1.0, 0.5);
let v2 = Vector3::new(1.0, 0.5, 0.9);
println!("v1: {:?}", v1);
println!("v2: {:?}", v2);
println!("angle: {:?}", v1.angle(v2));
}
v1: Vector3 [0.3, 1.0, 0.5]
v2: Vector3 [1.0, 0.5, 0.9]
angle: 0.7191634638561107 rad
Oh this is even better !!
i was trying this one ;
use cgmath::Rad;
use cgmath::prelude::*;
fn main() {
let angle: Rad<f32> = Rad::acos(0.5);
println!("{:?}", angle)
}
I was just playing around , thank you parasyte
and here it convert it to degrees;
use cgmath::{prelude::*, Vector3};
fn main() {
let mut pointx: Vec<f32> = Vec::new();
pointx.push(20.0);
pointx.push(1.0);
pointx.push(0.0);
let mut pointy: Vec<f32> = Vec::new();
pointy.push(1.0);
pointy.push(40.0);
pointy.push(0.0);
let pointx = Vector3::new(pointx[0], pointx[1], pointx[2]);
let pointy = Vector3::new(pointy[0], pointy[1], pointy[2]);
println!("angle: {:?}", pointx.angle(pointy) * 180.0 / 3.14159);
}
Deg<S>
implements From<Rad<S>>
so you can just do:
use cgmath::Deg;
println!("angle: {:?}", Deg::from(pointx.angle(pointy)));
And for the distance between two values .. like in nalgebra is quiet simple;
use nalgebra::distance;
(point1.coordinates() - point2.coordinates()).norm()
Is the Point3 method for the distance in cgmath ? ; cgmath::Point3 - Rust
That nalgebra example actually calculates the normal vector from In point1
to point2
.cgmath
, you calculate the distance between two points using MetricSpace::distance
, like so:
let p1 = Vector3 {
x: 32.0,
y: 14.0,
z: -3.0
};
let p2 = Vector3 {
x: -5.6,
y: 8.9,
z: 0.0,
};
let dist = p1.distance(p2);
See below, @marcianx's post.
ohh this is exactly what i did before 2 minutes, so i am correct thank you Optimist !!
Check out my code;
Input;
use cgmath::{prelude::*, Vector3, Deg};
fn main() {
let mut pointx: Vec<f32> = Vec::new();
pointx.push(20.0);
pointx.push(1.0);
pointx.push(0.0);
let mut pointy: Vec<f32> = Vec::new();
pointy.push(1.0);
pointy.push(40.0);
pointy.push(0.0);
let mut pointz: Vec<f32> = Vec::new();
pointz.push(-60.0);
pointz.push(-1.0);
pointz.push(0.0);
let point1 = Vector3::new(pointx[0], pointx[1], pointx[2]);
let point2 = Vector3::new(pointy[0], pointy[1], pointy[2]);
let point3 = Vector3::new(pointz[0], pointz[1], pointz[2]);
println!("Angle of Point1 & Point2 & Point3 is: {:?}", Deg::from(point1.angle(point2) +
point2.angle(point3)));
println!("Distance between Point1 to Point2 is: {:?}", point1.distance(point2))
}
Ouput;
Angle of Point1 & Point2 & Point3 is: 178.09244°
Distance between Point1 to Point2 is: 43.382023
Hey, you don't have to create a Vec
to be able to create a Vector3
:
//Constructor:
let point_a = Vector3 {
x: 10.0,
y: 20.0,
z: 30.0,
};
//Using an array:
let point_b: Vector3<f32> = [40.0, 50.0, 60.0].into();
am Yeah this is better Now the most extreme i want to do is the orientation,
If i walk from point 1 to point 2,do I have to turn left,right or straight on,to get to point 3. Can rotation method help me do this; cgmath::Rotation - Rust
That sounds a lot like the Orientation::of()
function from the arcs
crate. The crate is MIT licensed, so feel free to browse the source or copy code.
These sorts of algorithms aren't necessarily specific to a single crate or the Rust language, I've had to do a lot of computational geometry things for work and resources like this geeks-for-geeks page are super useful!
Ok i did it, check out my code;
use cgmath::{prelude::*, Vector3, Deg};
use arcs::{Point, Orientation};
fn main() {
//Constructor
let point_a = Vector3 {
x: 20.0,
y: 1.0,
z: 0.0,
};
let point_b = Vector3 {
x: 1.0,
y: 40.0,
z: 0.0,
};
let point_c = Vector3 {
x: -60.0,
y: -1.0,
z: 0.0,
};
//Angle
println!("Angle of Point A & Point B is: {:?}", Deg::from(point_a.angle(point_b)));
println!("Angle of Point B & Point C is: {:?}", Deg::from(point_b.angle(point_c)));
println!("Angle of Point A & Point B & Point C is: {:?}",
Deg::from(point_a.angle(point_b) + point_b.angle(point_c)));
//Distance
println!("Distance between Point A to Point B is: {:?}", point_a.distance(point_b));
println!("Distance between Point B to point C is: {:?}", point_b.distance(point_c));
println!("Distacne between Point A to Point C is: {:?}", point_a.distance(point_c));
let first = Point::new(20.0, 1.0);
let second = Point::new(1.0, 40.0);
let third = Point::new(-60.0, -1.0);
let value = (second.y - first.y) * (third.x - second.x)
- (second.x - first.x) * (third.y - second.y);
if value > 0.0 {
println!("Go right");
} else if value < 0.0 {
println!("Go left");
} else {
println!("Go Straight on");
}
}
The output is : Go left .
It looks correct, but actually i want the orientation from point 2 to point 3, so i have to change the value calculations
nalgebra's norm
actually does compute the norm (= magnitude) of the vector from point1
to point2
. This is the same as the distance between the two points.
(Also, a little nit: I suppose you meant to write "normalized" vector? The normal vector to a 3D vector is not well-defined -- there's a whole plane that's normal to a 3D vector.)
Ah, interesting, and yes I did mean to write normalized vector. I have edited my post above.
I want the result for the orientation from second point to third point ;
let _first = Point::new(20.0, 1.0);
let second = Point::new(1.0, 40.0);
let third = Point::new(-60.0, -1.0);
let value = (second.x - third.x) * (second.y - third.y);
println!("Orientation Value: {}", value);
if value > 0.0 {
//arcs::Orientation::Clockwise
println!("Walking from Point A to Point B && after turn Left to reach Point C!");
} else if value < 0.0 {
//arcs::Orientation::Anticlockwise
println!("Walking from Point A to Point B && after turn Right to reach Point C!");
} else {
//arcs::Orientation::Collinear
println!("Walking from Point A to Point B && after Go Straight on to reach Point C!");
}
is the value correct ?
Or maybe i should change the value calculations to (second.x - first.x) * (second.x - third.x).. ?
So, I don't remember much of linear algebra, but, I believe that this code should suffice:
let reference_point = Point3(...);
let first_target = Point3(...);
let second_target = Point3(...);
let first_vector = first_target - reference_point;
let second_vector = second_target - first_target;
let up = Vector3 {
x: 0.,
y: 1.,
z: 0.,
};
let cross = up.cross(first_vector.normalize()).normalize();
let dot = cross.dot(second_vector.normalize());
if dot == 1.0 {
println!("Go left");
} else if dot == 0.0 {
println!("Go forward or backward or up or down");
} else if dot == -1.0 {
println!("Go right");
}
This with some kind of a buffer could work.