Calculate angle between two vectors (probably @Igor :)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Calculate angle between two vectors (probably @Igor :)

MartinW
Hello,
i probably made some embarassing mistake, but as i cannot find it, i ask you to have a look at this method.
It should calculate the angle between two vectors. And vectors are instances of Point (perhaps here is already a misconception?).
It is used in my flocking simulation PharoBoids (http://smalltalkhub.com/#!/~MartinWalk/Boids)

Here is my version of the method:

angleBetween: vector1 and: vector2 onError: aBlock
        | cosinusOfAngle innerProductOfVectors productOfVectorsLengths|
        innerProductOfVectors := (vector1 dotProduct: vector2).
        productOfVectorsLengths := (vector1 r) * (vector2 r).
        productOfVectorsLengths = 0 ifTrue: [ ^ aBlock value ].
        cosinusOfAngle := innerProductOfVectors / productOfVectorsLengths.
        ^ cosinusOfAngle arcCos
       
But my Boids behave wrong when i use it. I found another implementation of the same problem by Igor Stasenko which works and looks like this:

angleBetween: p1 and: p2 ifDegenerate: aBlock
" Calculate an angle (in radians) between two vectors.
Evaluate a block, in case if calculation not possible because one of the vectors has zero length "

        | x1 y1 x2 y2 dot2 n2 |
        x1 := p1 x.
        y1 := p1 y.
        x2 := p2 x.
        y2 := p2 y.
       
        dot2 := x1 * x2 + (y1 * y2).
        dot2 := dot2 * dot2.
       
        n2 := (x1*x1 + (y1*y1)) * (x2*x2 + (y2*y2)).
       
        n2 = 0 ifTrue: [ ^ aBlock value ].
       
        ^ (dot2 / n2) arcCos
       
Can anybody explain the problem of my method? M.
Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

Nicolai Hess
Rounding error?

This may be the reason, igor's version is working with
cos = (a dot b)^2 / (|ab|^2)
while you are using
cos = (a dot b) / |ab|





2014-03-16 17:01 GMT+01:00 MartinW <[hidden email]>:
Hello,
i probably made some embarassing mistake, but as i cannot find it, i ask you
to have a look at this method.
It should calculate the angle between two vectors. And vectors are instances
of Point (perhaps here is already a misconception?).
It is used in my flocking simulation PharoBoids
(http://smalltalkhub.com/#!/~MartinWalk/Boids)

Here is my version of the method:

angleBetween: vector1 and: vector2 onError: aBlock
        | cosinusOfAngle innerProductOfVectors productOfVectorsLengths|
        innerProductOfVectors := (vector1 dotProduct: vector2).
        productOfVectorsLengths := (vector1 r) * (vector2 r).
        productOfVectorsLengths = 0 ifTrue: [ ^ aBlock value ].
        cosinusOfAngle := innerProductOfVectors / productOfVectorsLengths.
        ^ cosinusOfAngle arcCos

But my Boids behave wrong when i use it. I found another implementation of
the same problem by Igor Stasenko which works and looks like this:

angleBetween: p1 and: p2 ifDegenerate: aBlock
" Calculate an angle (in radians) between two vectors.
Evaluate a block, in case if calculation not possible because one of the
vectors has zero length "

        | x1 y1 x2 y2 dot2 n2 |
        x1 := p1 x.
        y1 := p1 y.
        x2 := p2 x.
        y2 := p2 y.

        dot2 := x1 * x2 + (y1 * y2).
        dot2 := dot2 * dot2.

        n2 := (x1*x1 + (y1*y1)) * (x2*x2 + (y2*y2)).

        n2 = 0 ifTrue: [ ^ aBlock value ].

        ^ (dot2 / n2) arcCos

Can anybody explain the problem of my method? M.



--
View this message in context: http://forum.world.st/Calculate-angle-between-two-vectors-probably-Igor-tp4749351.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

Alain Busser
In reply to this post by MartinW
First of all, you could simplify your code with dotProduct, writing

dot2 := p1 dotProduct: p2.

But maybe you just need

((p1 normalized) dotProduct: (p2 normalized)) arcCos         ;-)

You can also explore the polar coordinates...

Alain


On Sun, Mar 16, 2014 at 8:01 PM, MartinW <[hidden email]> wrote:
Hello,
i probably made some embarassing mistake, but as i cannot find it, i ask you
to have a look at this method.
It should calculate the angle between two vectors. And vectors are instances
of Point (perhaps here is already a misconception?).
It is used in my flocking simulation PharoBoids
(http://smalltalkhub.com/#!/~MartinWalk/Boids)

Here is my version of the method:

angleBetween: vector1 and: vector2 onError: aBlock
        | cosinusOfAngle innerProductOfVectors productOfVectorsLengths|
        innerProductOfVectors := (vector1 dotProduct: vector2).
        productOfVectorsLengths := (vector1 r) * (vector2 r).
        productOfVectorsLengths = 0 ifTrue: [ ^ aBlock value ].
        cosinusOfAngle := innerProductOfVectors / productOfVectorsLengths.
        ^ cosinusOfAngle arcCos

But my Boids behave wrong when i use it. I found another implementation of
the same problem by Igor Stasenko which works and looks like this:

angleBetween: p1 and: p2 ifDegenerate: aBlock
" Calculate an angle (in radians) between two vectors.
Evaluate a block, in case if calculation not possible because one of the
vectors has zero length "

        | x1 y1 x2 y2 dot2 n2 |
        x1 := p1 x.
        y1 := p1 y.
        x2 := p2 x.
        y2 := p2 y.

        dot2 := x1 * x2 + (y1 * y2).
        dot2 := dot2 * dot2.

        n2 := (x1*x1 + (y1*y1)) * (x2*x2 + (y2*y2)).

        n2 = 0 ifTrue: [ ^ aBlock value ].

        ^ (dot2 / n2) arcCos

Can anybody explain the problem of my method? M.



--
View this message in context: http://forum.world.st/Calculate-angle-between-two-vectors-probably-Igor-tp4749351.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

Nicolai Hess
In reply to this post by Nicolai Hess
This was of course wrong, I don't know what the
other method computes, but not the angle between two vectors.

Now the question is, why do you think your method is wrong / the boids  behave wrong?




2014-03-16 18:41 GMT+01:00 Nicolai Hess <[hidden email]>:
Rounding error?

This may be the reason, igor's version is working with
cos = (a dot b)^2 / (|ab|^2)
while you are using
cos = (a dot b) / |ab|





2014-03-16 17:01 GMT+01:00 MartinW <[hidden email]>:

Hello,
i probably made some embarassing mistake, but as i cannot find it, i ask you
to have a look at this method.
It should calculate the angle between two vectors. And vectors are instances
of Point (perhaps here is already a misconception?).
It is used in my flocking simulation PharoBoids
(http://smalltalkhub.com/#!/~MartinWalk/Boids)

Here is my version of the method:

angleBetween: vector1 and: vector2 onError: aBlock
        | cosinusOfAngle innerProductOfVectors productOfVectorsLengths|
        innerProductOfVectors := (vector1 dotProduct: vector2).
        productOfVectorsLengths := (vector1 r) * (vector2 r).
        productOfVectorsLengths = 0 ifTrue: [ ^ aBlock value ].
        cosinusOfAngle := innerProductOfVectors / productOfVectorsLengths.
        ^ cosinusOfAngle arcCos

But my Boids behave wrong when i use it. I found another implementation of
the same problem by Igor Stasenko which works and looks like this:

angleBetween: p1 and: p2 ifDegenerate: aBlock
" Calculate an angle (in radians) between two vectors.
Evaluate a block, in case if calculation not possible because one of the
vectors has zero length "

        | x1 y1 x2 y2 dot2 n2 |
        x1 := p1 x.
        y1 := p1 y.
        x2 := p2 x.
        y2 := p2 y.

        dot2 := x1 * x2 + (y1 * y2).
        dot2 := dot2 * dot2.

        n2 := (x1*x1 + (y1*y1)) * (x2*x2 + (y2*y2)).

        n2 = 0 ifTrue: [ ^ aBlock value ].

        ^ (dot2 / n2) arcCos

Can anybody explain the problem of my method? M.



--
View this message in context: http://forum.world.st/Calculate-angle-between-two-vectors-probably-Igor-tp4749351.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.



Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

Nicolai Hess
Another observation in

Boids>>isInFieldOfVision: aBoid
...
ownDirection := self velocity - self position.


the own direction should be the same as the velocity.

Consider a Boid at position 100@0 with velocity 100@0 would give
ownDirection = 0@0.
But of course, the steering direction is still 1@0.






2014-03-17 10:07 GMT+01:00 Nicolai Hess <[hidden email]>:
This was of course wrong, I don't know what the
other method computes, but not the angle between two vectors.

Now the question is, why do you think your method is wrong / the boids  behave wrong?




2014-03-16 18:41 GMT+01:00 Nicolai Hess <[hidden email]>:

Rounding error?

This may be the reason, igor's version is working with
cos = (a dot b)^2 / (|ab|^2)
while you are using
cos = (a dot b) / |ab|





2014-03-16 17:01 GMT+01:00 MartinW <[hidden email]>:

Hello,
i probably made some embarassing mistake, but as i cannot find it, i ask you
to have a look at this method.
It should calculate the angle between two vectors. And vectors are instances
of Point (perhaps here is already a misconception?).
It is used in my flocking simulation PharoBoids
(http://smalltalkhub.com/#!/~MartinWalk/Boids)

Here is my version of the method:

angleBetween: vector1 and: vector2 onError: aBlock
        | cosinusOfAngle innerProductOfVectors productOfVectorsLengths|
        innerProductOfVectors := (vector1 dotProduct: vector2).
        productOfVectorsLengths := (vector1 r) * (vector2 r).
        productOfVectorsLengths = 0 ifTrue: [ ^ aBlock value ].
        cosinusOfAngle := innerProductOfVectors / productOfVectorsLengths.
        ^ cosinusOfAngle arcCos

But my Boids behave wrong when i use it. I found another implementation of
the same problem by Igor Stasenko which works and looks like this:

angleBetween: p1 and: p2 ifDegenerate: aBlock
" Calculate an angle (in radians) between two vectors.
Evaluate a block, in case if calculation not possible because one of the
vectors has zero length "

        | x1 y1 x2 y2 dot2 n2 |
        x1 := p1 x.
        y1 := p1 y.
        x2 := p2 x.
        y2 := p2 y.

        dot2 := x1 * x2 + (y1 * y2).
        dot2 := dot2 * dot2.

        n2 := (x1*x1 + (y1*y1)) * (x2*x2 + (y2*y2)).

        n2 = 0 ifTrue: [ ^ aBlock value ].

        ^ (dot2 / n2) arcCos

Can anybody explain the problem of my method? M.



--
View this message in context: http://forum.world.st/Calculate-angle-between-two-vectors-probably-Igor-tp4749351.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.




Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

Ben Coman
> ownDirection := self velocity - self position.
Taking that purely at face value, it doesn't look right mixing distance(m) & velocity(m.s^-1) in a calculation.  I guess you are integrating velocity over one unit of time...
(m.s^-1)*(s)  - (m) 
= (m) - (m)
= (m)

cheers -ben

Nicolai Hess wrote:
Another observation in

Boids>>isInFieldOfVision: aBoid
...
ownDirection := self velocity - self position.


the own direction should be the same as the velocity.

Consider a Boid at position 100@0 with velocity 100@0 would give
ownDirection = 0@0.
But of course, the steering direction is still 1@0.






2014-03-17 10:07 GMT+01:00 Nicolai Hess <[hidden email]>:
This was of course wrong, I don't know what the
other method computes, but not the angle between two vectors.

Now the question is, why do you think your method is wrong / the boids  behave wrong?




2014-03-16 18:41 GMT+01:00 Nicolai Hess <[hidden email]>:

Rounding error?

This may be the reason, igor's version is working with
cos = (a dot b)^2 / (|ab|^2)
while you are using
cos = (a dot b) / |ab|





2014-03-16 17:01 GMT+01:00 MartinW <[hidden email]>:

Hello,
i probably made some embarassing mistake, but as i cannot find it, i ask you
to have a look at this method.
It should calculate the angle between two vectors. And vectors are instances
of Point (perhaps here is already a misconception?).
It is used in my flocking simulation PharoBoids
(http://smalltalkhub.com/#!/~MartinWalk/Boids)

Here is my version of the method:

angleBetween: vector1 and: vector2 onError: aBlock
        | cosinusOfAngle innerProductOfVectors productOfVectorsLengths|
        innerProductOfVectors := (vector1 dotProduct: vector2).
        productOfVectorsLengths := (vector1 r) * (vector2 r).
        productOfVectorsLengths = 0 ifTrue: [ ^ aBlock value ].
        cosinusOfAngle := innerProductOfVectors / productOfVectorsLengths.
        ^ cosinusOfAngle arcCos

But my Boids behave wrong when i use it. I found another implementation of
the same problem by Igor Stasenko which works and looks like this:

angleBetween: p1 and: p2 ifDegenerate: aBlock
" Calculate an angle (in radians) between two vectors.
Evaluate a block, in case if calculation not possible because one of the
vectors has zero length "

        | x1 y1 x2 y2 dot2 n2 |
        x1 := p1 x.
        y1 := p1 y.
        x2 := p2 x.
        y2 := p2 y.

        dot2 := x1 * x2 + (y1 * y2).
        dot2 := dot2 * dot2.

        n2 := (x1*x1 + (y1*y1)) * (x2*x2 + (y2*y2)).

        n2 = 0 ifTrue: [ ^ aBlock value ].

        ^ (dot2 / n2) arcCos

Can anybody explain the problem of my method? M.



--
View this message in context: http://forum.world.st/Calculate-angle-between-two-vectors-probably-Igor-tp4749351.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.





Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

MartinW
In reply to this post by Nicolai Hess
Nicolai Hess wrote
This was of course wrong, I don't know what the
other method computes, but not the angle between two vectors.
Yes i also wrote a test and i think my method is right.

Nicolai Hess wrote
Now the question is, why do you think your method is wrong / the boids
behave wrong?
When i use my method to calculate the field of vision the Boids always fly from top left to down right and if i turn on the circling option, they crowd in the bottom right quadrant.
If i give them a 360 degree field of vision by always returning true for isInFieldOfVision they behave correctly. This means they fly in a nice circle around the center and if circling is turned off, the swarm flies in different directions each time you start the simulation.

Perhaps the problem is not the calculation of the angle but is in the isInFieldOfVision: method...
Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

Nicolai Hess
2014-03-19 8:49 GMT+01:00 MartinW <[hidden email]>:
Nicolai Hess wrote
> This was of course wrong, I don't know what the
> other method computes, but not the angle between two vectors.

Yes i also wrote a test and i think my method is right.


Nicolai Hess wrote
> Now the question is, why do you think your method is wrong / the boids
> behave wrong?

When i use my method to calculate the field of vision the Boids always fly
from top left to down right and if i turn on the circling option, they crowd
in the bottom right quadrant.
If i give them a 360 degree field of vision by always returning true for
isInFieldOfVision they behave correctly. This means they fly in a nice
circle around the center and if circling is turned off, the swarm flies in
different directions each time you start the simulation.

Perhaps the problem is not the calculation of the angle but is in the
isInFieldOfVision: method...

:) yes and I think the testcases in testIsInFieldOfVision
are wrong, or I misunderstand how the boids are moving.

in testIsInFieldOfVision
subject has velocity 100@0, I understand this as "moves from left to right".
testobject other2 and other3 are above and below subect, and not behind and
in front, both should be visible with the fieldOfView.
Btw. the field of view is rather big, 0.75*Float Pi is 135 degree, but  clock *and* counterclockwise
->  270 degree field of view.


And it is funny to change the field of view to 0, after the boids started.
 



--
View this message in context: http://forum.world.st/Calculate-angle-between-two-vectors-probably-Igor-tp4749351p4749697.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

Igor Stasenko
In reply to this post by MartinW



On 16 March 2014 17:01, MartinW <[hidden email]> wrote:
Hello,
i probably made some embarassing mistake, but as i cannot find it, i ask you
to have a look at this method.
It should calculate the angle between two vectors. And vectors are instances
of Point (perhaps here is already a misconception?).
It is used in my flocking simulation PharoBoids
(http://smalltalkhub.com/#!/~MartinWalk/Boids)

Here is my version of the method:

angleBetween: vector1 and: vector2 onError: aBlock
        | cosinusOfAngle innerProductOfVectors productOfVectorsLengths|
        innerProductOfVectors := (vector1 dotProduct: vector2).
        productOfVectorsLengths := (vector1 r) * (vector2 r).
        productOfVectorsLengths = 0 ifTrue: [ ^ aBlock value ].
        cosinusOfAngle := innerProductOfVectors / productOfVectorsLengths.
        ^ cosinusOfAngle arcCos


 
But my Boids behave wrong when i use it. I found another implementation of
the same problem by Igor Stasenko which works and looks like this:

angleBetween: p1 and: p2 ifDegenerate: aBlock
" Calculate an angle (in radians) between two vectors.
Evaluate a block, in case if calculation not possible because one of the
vectors has zero length "

        | x1 y1 x2 y2 dot2 n2 |
        x1 := p1 x.
        y1 := p1 y.
        x2 := p2 x.
        y2 := p2 y.

        dot2 := x1 * x2 + (y1 * y2).
        dot2 := dot2 * dot2.

        n2 := (x1*x1 + (y1*y1)) * (x2*x2 + (y2*y2)).

        n2 = 0 ifTrue: [ ^ aBlock value ].

        ^ (dot2 / n2) arcCos

Can anybody explain the problem of my method? M.


yours looks correct.
i'm just using squares to avoid taking square roots of vector lengths.
 

--
View this message in context: http://forum.world.st/Calculate-angle-between-two-vectors-probably-Igor-tp4749351.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.




--
Best regards,
Igor Stasenko.
Reply | Threaded
Open this post in threaded view
|

Re: Calculate angle between two vectors (probably @Igor :)

MartinW
In reply to this post by Nicolai Hess
Nicolai Hess wrote
in testIsInFieldOfVision
subject has velocity 100@0, I understand this as "moves from left to right".
testobject other2 and other3 are above and below subect, and not behind and
in front, both should be visible with the fieldOfView.
Oh, thank you. I made a new testcase. Which is unfortunately passing :( So i am still looking for a solution…
Bird with 270 degrees field of vision

Nicolai Hess wrote
Btw. the field of view is rather big, 0.75*Float Pi is 135 degree, but
clock *and* counterclockwise
->  270 degree field of view.
That's correct. Most birds have the eyes on the sides of their heads - thus they have a wide visual field. Some as wide as 360 degrees.