TimoL
August 25, 2020, 11:14am
1
I have another maths/coding question.
Im trying to figure out the average heading of an array of PVectors.
At first I tried adding up the heading values and dividing that by the count. But there are scenarios where the average is not the desired vector.
I think this has to do with ‘heading()’ returning a value between -PI & PI.
So there are 2 vectors; A with a heading of 225° & B with a heading of 135°.
using the above method my average works out to 0°, when the desired result is actually 180°.
I’ve tried changing the heading to a value from 0 to TWO_PI, but the problem still exists.
here is some code to show what I mean.
I hope I’ve explained myself properly.
PVector A;
PVector B;
PVector C;
float aA = 225; // change this to a number below 180 degrees
float aB = 135;
float angle = 135;
float averageHeading;
void setup () {
size (300, 300);
}
void draw() {
background(200);
stroke(0);
noFill();
circle(width/2, height/2, width);
pushMatrix();
translate(width/2, height/2);
A = PVector.fromAngle(radians(aA));
B = PVector.fromAngle(radians(aB));
A.setMag(150);
B.setMag(150);
stroke(255, 0, 0);
line(0, 0, A.x, A.y);
line(0, 0, B.x, B.y);
averageHeading = A.heading() + B.heading();
averageHeading = averageHeading/2;
C = PVector.fromAngle(averageHeading);
C.setMag(150);
stroke(255, 0, 255);
line(0, 0, C.x, C.y);
popMatrix();
}
1 Like
glv
August 25, 2020, 12:24pm
2
Hello,
Intuitively, I would get the heading of the sum of the two vectors for this example.
:)
If heading < 0
, then heading = 2PI+heading
?
In a one-liner: heading = (heading+angle)%2PI;
Just for a laugh I tried this in JRubyArt:-
attr_reader :aaa, :abb
def settings
size(300, 300)
end
def setup
sketch_title "Average Heading"
@aaa = 225
@abb = 135
end
def draw
background(200)
stroke(0)
noFill
circle(width / 2, height / 2, width)
push_matrix
translate(width / 2, height / 2)
vector_a = Vec2D.from_angle(aaa.radians)
vector_b = Vec2D.from_angle(abb.radians)
stroke(255, 0, 0)
line(0, 0, vector_a.x * 150, vector_a.y * 150)
line(0, 0, vector_b.x * 150, vector_b.y * 150)
averageHeading = ((vector_a + vector_b) / 2.0).heading
vector_c = Vec2D.from_angle(averageHeading)
vector_c.set_mag(150)
stroke(255, 0, 255)
line(0, 0, vector_c.x, vector_c.y)
pop_matrix
end
Works with 45 and -45 degrees gets:-
2 Likes
glv
August 25, 2020, 7:41pm
5
glv:
Intuitively
I took this out for a spin:
PVector A;
PVector B;
PVector C;
float aA = 225; // change this to a number below 180 degrees
float aB = 135;
float angle = 135;
float averageHeading;
float theta;
void setup ()
{
size (300, 300);
A = new PVector(0, 0);
B = new PVector(0, 0);
C = new PVector(0, 0);
}
void draw()
{
background(200);
stroke(0);
noFill();
circle(width/2, height/2, width);
theta+= TAU/360;
pushMatrix();
translate(width/2, height/2);
A = PVector.fromAngle(theta);
B = PVector.fromAngle(radians(aB));
A.setMag(150);
B.setMag(150);
stroke(255, 0, 0);
line(0, 0, A.x, A.y);
line(0, 0, B.x, B.y);
//averageHeading = A.heading() + B.heading();
//averageHeading = averageHeading/2;
//C = PVector.fromAngle(averageHeading);
//C.setMag(150);
C.set(A.add(B));
stroke(255, 0, 255);
line(0, 0, C.x, C.y);
popMatrix();
}
I will leave the rest with you.
:)
2 Likes
TimoL
August 26, 2020, 6:27am
6
thanks guys. I guess I went wrong by trying to divide the sum of the headings.
Here’s the code that now gets the average of an array of vectors.
PVector [] vectors = new PVector [3];
PVector C = new PVector(0, 0);
void setup () {
size (300, 300);
for (int i = 0; i < vectors.length; i ++) {
vectors[i] = PVector.random2D();
}
C = new PVector(0, 0);
}
void draw() {
background(200);
stroke(0);
noFill();
circle(width/2, height/2, width);
pushMatrix();
translate(width/2, height/2);
for (int i = 0; i < vectors.length; i ++) {
C.add(vectors[i]);
vectors[i].setMag(150);
line(0, 0, vectors[i].x, vectors[i].y);
}
stroke(255, 0, 0);
C.setMag(150);
stroke(255, 0, 255);
line(0, 0, C.x, C.y);
popMatrix();
}
2 Likes
glv
August 26, 2020, 2:54pm
7
Hello,
@monkstone
I do not use JRubyArt… so correct me if I am wrong on this.
This will return the heading for the result of vector A + vector B.
The /2.0 is not necessary and may confound some visitors; I did not understand this but I have experience and was able to follow through on my initial intuition on this with a Processing version.
:)
1 Like
You are absolutely correct, the divide by two isn’t needed, I quickly threw together code and was thinking about averaging turning moments. The dried up code:-
attr_reader :aaa, :abb, :scale
def settings
size(300, 300)
end
def setup
sketch_title 'Average Heading'
@aaa = 225
@abb = 135
@scale = 150
end
def draw_line(vec, scale)
vec *= scale
line(0, 0, vec.x, vec.y)
end
def draw
background(200)
stroke(0)
no_fill
circle(width / 2, height / 2, width)
push_matrix
translate(width / 2, height / 2)
vector_a = Vec2D.from_angle(aaa.radians)
vector_b = Vec2D.from_angle(abb.radians)
stroke 255, 0, 0
draw_line vector_a, scale
draw_line vector_b, scale
stroke 255, 0, 255
draw_line (vector_a + vector_b), scale
pop_matrix
end
No need for heading
or set_mag
, I just thought it might be interesting to see the Vec2D operators +
, *
instead of add
and mult
etc.
2 Likes
glv
August 27, 2020, 4:41pm
9
1 Like