Jump to content
Sign in to follow this  
roguetrooper

Mathematical: random pos in an 'oblique' rectangle ?

Recommended Posts

How can you return a random position within a rectangle whose angle is not zero degrees? (angle zero is no problem... :rolleyes: )

You have the coordinates of its center, x-axis length, y-axis length and the angle (!=0)

Share this post


Link to post
Share on other sites

I guess you actually mean a random position in a parallelogram whose angle != 90° , lets say A = (angle between two side - 90°) this can be interpreted as the 'oblique' angle.

I assumed your parallelogram was along the North=y East = x axis. If we number the 4 vertices in anti-clock wise direction , starting from the lower left one, we find the equaton for the left and right sides are :

left : y = cotan(A)*x + y1 - cotan(A)*x1

right: y = cotan(A)*x + y1 - cotan(A)*x2

NB: there is no cotan() command in arma , but that's not a problem because cotan(A) = (1/tan(A))

so now pick a random x between x1 and x3 :

Rand_x = (random (x3-x1))+x1;

calculate the 2 y corresponding to this x

lim_y1 = (1/tan(A))*Rand_x + y1 - cotan(A)*x1;

lim_y2 = (1/tan(A))*Rand_x + y1 - cotan(A)*x2;

we check if those are greater than the height of the parallelogram :

if (lim_y1 > y4) then {lim_y1 = y4};

if (lim_y2 < y1) then {lim_y2 = y1};

pick a random y between those two limits :

Rand_y = (random (lim_y1-lim_y2))+lim_y2;

[Rand_x,Rand_y] is a random coordinate in the parallelogram.

I hope I didn't make this too complicated, this won't work if your parallelogram isn't aligned on the North-East axis , there is just slightly more computation for a general case.

Edited by luckyhendrix

Share this post


Link to post
Share on other sites

I use such code with good result:

_pos = position (_this select 0);//_pos is center point
_angle = _this select 1;
_rg1 = _this select 2;//x-axis
_rg2 = _this select 3;//y-axis

_px = _pos select 0;
_py = _pos select 1;

_MpX = _pX - _rg1 + (2*(random _rg1));
_MpY = _pY - _rg2 + (2*(random _rg2));
_trans = _pos distance [_MpX,_MpY,0];
_angleI = (_MpX - _pX) atan2 (_MpY - _pY);

_dX =_trans * (sin (_angleI + _angle));
_dY = _trans * (cos (_angleI + _angle));
_MpX = _pX + _dX;
_MpY = _pY + _dY;
_Mpos2D = [_MpX,_MpY];//result

EDIT: this is in turn for "twisted" "real" rectangle, not parallelogram. In this way I understood yours question.

Edited by Rydygier

Share this post


Link to post
Share on other sites

By far the easiest way is to place an object in the center and make use of the magical "modelToWorld" command.

(that nifty command automatically takes the orientation of the center-object into account)

http://community.bistudio.com/wiki/modelToWorld

private ["_center","_xx","_yy","_rndPos"];

_center = _this select 0; //center object
_center setDir = _this select 1; //angle
_xx = _this select 2; //x-axis
_yy = _this select 3; //y-axis

_xx = (random _xx) - (0.5 * _xx);
_yy = (random _yy) - (0.5 * _yy);

_rndPos = _center modelToWorld [_xx,_yy,0];

_rndPos; //output

The angle-parameter could also be left out if you decide to set the angle of the object in the editor.

Share this post


Link to post
Share on other sites

Indeed, I don't mean a parallelogram, but a rectangle with 4 90-degree angles and whose y-axis just isn't aligned straight north-south. Thanks to all of you.

Share this post


Link to post
Share on other sites

True, easier, Tajin, but I'm wondering if also more efficient? After all behind modelToWorld, and behind creating an object are hidden calculations too.

As for more "exotic" methods:

_pos = position (_this select 0);
_angle = _this select 1;
_rg1 = _this select 2;
_rg2 = _this select 3;

_Loc = createLocation ["Name", _pos, _rg1, _rg2];
_Loc setDirection _angle;
_Loc setRectangular true;

_range = 2 * (sqrt ((_rg1 * _rg1) + (_rg2 * _rg2)));

_px = _pos select 0;
_py = _pos select 1;


_MpX = _pX + (random _range) - (_range/2);
_MpY = _pY + (random _range) - (_range/2);


while {not ([_Mpx,_Mpy] in _Loc)} do
{
_MpX = _pX + (random _range) - (_range/2);
_MpY = _pY + (random _range) - (_range/2);
};

_result = [_MpX,_MpY];

deleteLocation _Loc;

Edited by Rydygier

Share this post


Link to post
Share on other sites
True, easier, Tajin, but I'm wondering if also more efficient? After all behind modelToWorld, and behind creating an object are hidden calculations too.

Yeh, I have no idea which one is actually more efficient. One could assume that native functions are faster than scripted solutions... then again, that function might include some calculations that are unnecessary for this specific case. Well, I guess the difference is minimal, but that remains to be tested.

Your last example seems rather inefficient though.

Edited by Tajin

Share this post


Link to post
Share on other sites

Yeah, last one is rather as "curiosity".

---------- Post added at 17:57 ---------- Previous post was at 17:28 ----------

I was curios about that, so did some tests, where each code has to generate 10000 positions. Two series: first, when looped is only minimum (neccessary only) amount of code (eg object or location is generated and deleted only once):

"time: 1.896" - my "math" method;

"time: 0.717" - "object" method (used small can);

"time: 2.267" - "location" method;

Second, where looped is everything:

"time: 2.823" - my "math" method;

"time: 2.847" - "object" method (used small can);

"time: 4.564" - "location" method.

As you can see object method is best, when may be launched once for all positions. Otherwise "weight" of creating objects makes math and object methods equally efficient.

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
Sign in to follow this  

×