Search code examples
vectorspread

Add random spread to directional vector


Let's say I have a unit vector a = Vector(0,1,0) and I want to add a random spread of something between x = Vector(-0.2,0,-0.2) and y = Vector(0.2,0,0.2), how would I go about doing that?

If I were to simply generate a random vector between x and y, I'd get a value somewhere in the bounds of a square:

square

What I'd like instead is a value within the circle made up by x and y:

circle

This seems like a simple problem but I can't figure out the solution right now. Any help would be appreciated.

(I didn't ask this on mathoverflow since this isn't really a 'research level mathematics question')


Solution

  • If I read your question correctly, you want a vector in a random direction that's within a particular length (the radius of your circle).

    The formula for a circle is: x2 + y2 = r2

    So, if you have a maximum radius, r, that constrains the vector length, perhaps proceed something like this:

    1. Choose a random value for x, that lies between -r and +r
    2. Calculate a limit for randomising y, based on your chosen x, so ylim = sqrt(r2 - x2)
    3. Finally, choose a random value of y between -ylim and +ylim

    That way, you get a random direction in x and a random direction in y, but the vector length will remain within 0 to r and so will be constrained within a circle of that radius.

    In your example, it seems that r should be sqrt(0.22) which is approximately 0.28284.

    UPDATE

    As 3D vector has length (or magnitude) sqrt(x2+y2+z2) you could extend the technique to 3D although I would probably favour a different approach (which would also work for 2D).

    1. Choose a random direction by choosing any x, y and z
    2. Calculate the magnitude m = sqrt(x2+y2+z2)
    3. Normalise the direction vector (by dividing each element by its magnitude), so x = x/m, y = y/m, z=z/m
    4. Now choose a random length, L between 0 and r
    5. Scale the direction vector by the random length. So x = x * L, y = y * L, z = z * L