Jump to content
celludriel

Find a random position on radial

Recommended Posts

Hey,

 

I'm working on an idea to spawn squads in three layers from a specific center position.  Mathematical I would take a random radial from a center position move upon that radial x distance and put a spot there to work with.  Take this conceptual drawing as food for thought.

 

spawn_idea.png

 

I can do this fairly simple in C# or Java but in sqf/BIS I'm not sure there is a function to call a radial and move up or down from it.  I was thinking of using the x and y coords of the pos array.  However this is where my old high school math is failing me.  the distance is pretty easy I believe I go up the Y-axis a set amount of meters.  Now to find if I have to go right or left on the X-axis for any radial 0-180 I have to go right and 181 to 360 I have to go left.  The distance however depends on the angle between the line I went up Y and the radial.  I just don't remember how to calculate that distance.  It has something to do with A² + B² = C².  I was also thinking about sin, cos and tang ... but argh ...

 

Also if there is a better way then whatever is going on in my mind right now with these equations PLEASE :)  I would be happy to hear it :)

Share this post


Link to post
Share on other sites

idk if i got what u want todo but i just try...

you could do any 2d vector which points to desired direction. just normalize it then its length is 1. multiply it with ur desired length. after that u just add the vector to the position(center of circle). commands follow with edits...

edit:

vectorNormalize

vectorMultiply

vectorAdd

  • Like 1

Share this post


Link to post
Share on other sites

_pos = getPosATL player;

_vec =[random 1, random1, 0];

_dist = 1000;

_pos = ((vectorNormalize _vec) vectorMultiply _dist) vectorAdd _pos;

thats the idea...

Share this post


Link to post
Share on other sites

idk if i got what u want todo but i just try...

you could do any 2d vector which points to desired direction. just normalize it then its length is 1. multiply it with ur desired length. after that u just add the vector to the position(center of circle). commands follow with edits...

edit:

vectorNormalize

vectorMultiply

vectorAdd

 

Thanks I didn't knew about the vector functions my search criteria was limited to radial and sin, cos.  These will help !

Share this post


Link to post
Share on other sites

Just in case you still need some high scool maths :)

gXsL7AD.png

 

Thanks my mind thanks you :)  hey at least I still remembered it was cosinus and sinus to use ;)

Share this post


Link to post
Share on other sites

So radians is from 0 to 2pi, right? Now, you're looking for a point that is r units away from (0,0) on point (r, theta), so you're looking at 2 equations:

r * cos(theta) //x-axis movement

r * sin(theta) //y-axis movement

 

So let's say you're looking for a new point that is 30 degrees away from your origin(approximately the blue line in your diagram), with radius 10, you're looking at the equations,

10 * cos(30 degrees) alternatively 10 * cos(30*pi/180) for radians, note that radians has no unit behind the number but degrees are marked with a little raised circle

10 * sin(30) alternatively 10 * sin(30*pi/180) for radians

These will give you a point that will be equal to 10 meters in the direction of 30 degrees (note that this is mathematical and not compass-based) from your starting point, simply add the result of those equations to the x and y values of the object or point you're applying it to to get a correct new position.

Also when you're looking for the distance you're correct with Pythagorean's Theorem (A+ B2 = C2), but in the context of triangles, I find that it's much easier to think of this equation in terms of X+ Y2 = H(or R2), with H being hypotenuse or R being radius. The specific name for this kind of mathematics is Trigonometry (tri meaning 3, for triangles, it is triangle-based).

 

Hope this helps

  • Like 2

Share this post


Link to post
Share on other sites

I'm probably missing something and going to sound stupid, but would getPos help?

 

_pos = _center getpos [_distance, _direction];

  • Like 5

Share this post


Link to post
Share on other sites

So radians is from 0 to 2pi, right?

Trigonometric functions in Arma take degrees as arguments.

For compass directions (clockwise, from y axis) see the right part of figure in my post above (with β as an angle).

 

 


I'm probably missing something and going to sound stupid, but would getPos help?

 

_pos = _center getpos [_distance, _direction];

That's not stupid, that's the best solution in the thread :)

  • Like 1

Share this post


Link to post
Share on other sites

Trigonometric functions in Arma take degrees as arguments.

For compass directions (clockwise, from y axis) see the right part of figure in my post above (with β as an angle).

 

 


That's not stupid, that's the best solution in the thread :)

 

ssssssssssst nobody ever saw that answer ... (or my blatent mistake of reading getPos documentation better)

 

hey look on the bright side , some of us got to refresh their high school math again ... it has been like 18 years ago for me ...

Share this post


Link to post
Share on other sites

I just did a similar spawn method last night using one line for each circle because of the BIS_fnc_findSafePos function. Literally takes a center point, picks a random spot between X and Y distance from the center outputs a map position.

 

for example:

_Center = player;
_Circle1 = [_Center, 150, 150, 0, 0, 20, 0] call BIS_fnc_findSafePos;
_Circle2 = [_Center, 250, 250, 0, 0, 20, 0] call BIS_fnc_findSafePos;
_Circle3 = [_Center, 350, 350, 0, 0, 20, 0] call BIS_fnc_findSafePos;

Each "_circle" will be a random azimuth exactly 150, 250, and 350 meters away from the center. The first number is the minimum distance from center, the second is the maximum, so you can adjust for "fatter" circles so they don't just pick something in a thin line of a circle.

 

If you don't want *RANDOM* positions, you can still use this command to find a safe spawn point based on a few parameters needed, then just alter the array that it outputs to change X, Y or Z by another variable. You may also want to look at BIS_fnc_relPos. The example shows how to use a bit a math to do circular stuff.

  • Like 1

Share this post


Link to post
Share on other sites

_start = position player;

 

_dir = random 360;
_dist = random 500;
 
_pos = [(_start select 0) + cos _dir * _dist, (_start select 1) - sin _dir * _dist, 0];
  • Like 1

Share this post


Link to post
Share on other sites

Or just because it's more fun to over complicate everything, why not use spherical coordinates? :D

_radius = 2;
_origin = (getPosASL player) vectorAdd [0,0,20];

for "_i" from 1 to 300 do {
    _veh = createVehicle ["Sign_Sphere10cm_F", ASLtoAGL _origin, [], 0, "CAN_COLLIDE"];
    _veh enableSimulation false;

    _theta = ((2 * pi * _i)/300) * (180/pi);
    _phi = acos((2 * (random 1)) - 1);

    _x = _radius * sin(_phi) * cos(_theta);
    _y = _radius * sin(_phi) * sin(_theta);
    _z = _radius * cos(_phi);

    _veh setPosASL (_origin vectorAdd [_x, _y, _z]);
};

Produces random positions on the surface of a sphere. Not meant to be the most ideal solution  ;) 

  • Like 2

Share this post


Link to post
Share on other sites

Or just because it's more fun to over complicate everything, why not use spherical coordinates? :D

_radius = 2;
_origin = (getPosASL player) vectorAdd [0,0,20];

for "_i" from 1 to 300 do {
    _veh = createVehicle ["Sign_Sphere10cm_F", ASLtoAGL _origin, [], 0, "CAN_COLLIDE"];
    _veh enableSimulation false;

    _theta = ((2 * pi * _i)/300) * (180/pi);
    _phi = acos((2 * (random 1)) - 1);

    _x = _radius * sin(_phi) * cos(_theta);
    _y = _radius * sin(_phi) * sin(_theta);
    _z = _radius * cos(_phi);

    _veh setPosASL (_origin vectorAdd [_x, _y, _z]);
};

Produces random positions on the surface of a sphere. Not meant to be the most ideal solution  ;)

 

I can use this, actually. Make it for player spawn position modules. If they are in the air, you spawn with a parachute. So this can make the spawnpoint randomly on the ground or in the air. :)

Share this post


Link to post
Share on other sites

I can use this, actually. Make it for player spawn position modules. If they are in the air, you spawn with a parachute. So this can make the spawnpoint randomly on the ground or in the air. :)

 

It'll only produce position on the surface of the sphere. To produce a random position within the sphere, use:

_theta = (2 * pi * (random 1)) * (180/pi);

Moreover, it can produce positions underneath the terrain, too.

Share this post


Link to post
Share on other sites

Moreover, it can produce positions underneath the terrain, too.

 

Whoa. I didn't even think that was possible. It doesn't even let me clip through the ground when in the editor. I suppose I'd have to add a condition that says if the position is underground, to move it to 0 Z.

Share this post


Link to post
Share on other sites

Whoa. I didn't even think that was possible. It doesn't even let me clip through the ground when in the editor. I suppose I'd have to add a condition that says if the position is underground, to move it to 0 Z.

I haven't tested it in game but from the function a negative z value can be produced. For example, if the origin had a value z=0, and a radius >0 then a negative z could occur.

 

Could just change z to its abs value

Share this post


Link to post
Share on other sites

Since trig has always been a bit of mystery to me, I wondered how would I do that spherical thingy.

_source = eyepos player;
_distance = 5;

for "_i" from 1 to 1000 do {
	_veh = createVehicle ["Sign_Sphere10cm_F", _source, [], 0, "CAN_COLLIDE"];
	_pos = _source vectorAdd (vectorNormalized [(random 2)-1,(random 2)-1,(random 2)-1] vectorMultiply _distance);
	_veh setposasl _pos;
};

But then the possible underground positions started to bug me, and all I could think of was either use a brute force loop to discard unsuitable positions or create a sort of hemisphere placement with:

_pos set [2,(getTerrainHeightASL _pos) max (_pos select 2)];

Yeah, this is way off topic but I really like solving imaginary scripting problems. :)

  • Like 1

Share this post


Link to post
Share on other sites

Since trig has always been a bit of mystery to me, I wondered how would I do that spherical thingy.

_source = eyepos player;
_distance = 5;

for "_i" from 1 to 1000 do {
	_veh = createVehicle ["Sign_Sphere10cm_F", _source, [], 0, "CAN_COLLIDE"];
	_pos = _source vectorAdd (vectorNormalized [(random 2)-1,(random 2)-1,(random 2)-1] vectorMultiply _distance);
	_veh setposasl _pos;
};
But then the possible underground positions started to bug me, and all I could think of was either use a brute force loop to discard unsuitable positions or create a sort of hemisphere placement with:

_pos set [2,(getTerrainHeightASL _pos) max (_pos select 2)];
Yeah, this is way off topic but I really like solving imaginary scripting problems. :)

I think one could do it this way to avoid positions underneath Surface:

_source = ASLToAGL(eyepos Player);
_distance = 5;

for "_i" from 1 to 1000 do {
_veh = createVehicle ["Sign_Sphere10cm_F", _source, [], 0, "CAN_COLLIDE"];
_pos = _source vectorAdd (vectorNormalized [(random 2)-1,(random 2)-1,(random 1)] vectorMultiply _distance);
_veh setposAGLS _pos;
};

Share this post


Link to post
Share on other sites

Or just because it's more fun to over complicate everything, why not use spherical coordinates? :D

_radius = 2;
_origin = (getPosASL player) vectorAdd [0,0,20];

for "_i" from 1 to 300 do {
    _veh = createVehicle ["Sign_Sphere10cm_F", ASLtoAGL _origin, [], 0, "CAN_COLLIDE"];
    _veh enableSimulation false;

    _theta = ((2 * pi * _i)/300) * (180/pi);
    _phi = acos((2 * (random 1)) - 1);

    _x = _radius * sin(_phi) * cos(_theta);
    _y = _radius * sin(_phi) * sin(_theta);
    _z = _radius * cos(_phi);

    _veh setPosASL (_origin vectorAdd [_x, _y, _z]);
};

Produces random positions on the surface of a sphere. Not meant to be the most ideal solution  ;)

Dude, you're overcomplicating too much :D

This

_theta = ((2 * pi * _i)/300) * (180/pi);
_phi = acos((2 * (random 1)) - 1);

can be easily simplified to 

 _theta = 1.2 * _i; // 360 * _i / 300;
_phi = random 180;

Though the second line gives different distribution of points. Random with one argument gives even distribution. But when acos is applied to it, you'll have non-even distribution, see pic below (left part). One might probably want even distribution of angles (right part) instead of values passed to acos. It will also remove unnecessary back and forth calculation of acos and cos on the same value.

PifHqgh.png

 

If, for some reasons, even distribution for acos argument is what you've always wanted, you can use something like:

_cosPhi = -1 + random 2;
_sinPhi = sqrt(1-_cosPhi*_cosPhi);

Not meant to be the most ideal solution either :)

  • Like 2

Share this post


Link to post
Share on other sites

I so like all these math equations :) takes me back twenty years.  Good solutions all of them especially the spawn in sphere is a nice one

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×