Jump to content
Sign in to follow this  
mind

Finding random position in area with uniform distribution

Recommended Posts

Hey,

 

Small topic for those who love to play around with randomness.

Have you ever tried to find random point in circle? Let`s try find a random point around player in 1000 meters radius. So we can write something like.

player getRelPos [random 1000, random 360];

And here we go, seems cool right? No it is not. Let`s try do that 5000 times, and put a marker for each resulting position.

for "_i" from 0 to 5000 do { 
   _pos = player getRelPos [random 1000, random 360]; 
   _markerstr = createMarkerLocal [str random 100,_pos];  
   _markerstr setMarkerShapeLocal "ICON";  
   _markerstr setMarkerTypeLocal "hd_dot"; 
};

Here what we gonna have.

Spoiler

wrong.png

As you can see it is not random at all. Dots are concentrated towards center.

 

So how can we have unified distribution? We can write following:

for "_i" from 0 to 5000 do {
	_radius = 1000;
	_randomValue = random _radius;
	_distributedValue = _randomValue;
	if ((1-(_randomValue/_radius)) > (random 1)) then {
		_distributedValue = (_randomValue + (random (_radius - _randomValue)))
	};
	_pos = player getRelPos [_distributedValue, random 360]; 
	_markerstr = createMarkerLocal [str random 100,_pos];  
	_markerstr setMarkerShapeLocal "ICON";  
	_markerstr setMarkerTypeLocal "hd_dot"; 
};

So here is what we gonna have as result

Spoiler

good.png

 

Basically what we do here is: As smaller the random value we get as bigger the chance that we will add to this value a bit. (In simple words ;p)

 

Have a good day

  • Like 2

Share this post


Link to post
Share on other sites
39 minutes ago, mind said:

Have you ever tried to find random point in circle?

 

Pretty cool, and I appreciate you bringing this up. However the solution is actually much much simpler:

 

for "_i" from 0 to 5000 do 
{ 
   _pos = player getPos [1000 * sqrt random 1, random 360];
   _marker = createMarkerLocal [str _i,_pos];  
   _marker setMarkerShapeLocal "ICON";  
   _marker setMarkerTypeLocal "hd_dot"; 
};

 

The sqrt is all you need

  • Like 3

Share this post


Link to post
Share on other sites

Code:

InAreaRandomPosition = {// parameters: [center, a, b, angle, isRectangle] - see inArea command alternative syntax
	params ["_pos", "_sza", "_szb", "_dir", "_rct"]; _pos params ["_psx", "_psy"];
	if (_rct) then {
		private _dsx = random _sza * 2 - _sza;
		private _dsy = random _szb * 2 - _szb;			
		[_psx + _dsx * cos -_dir - _dsy * sin -_dir, _psy + _dsx * sin -_dir + _dsy * cos -_dir]
	} else {
		private _ang = random 360;
		private _rad = sqrt random 1.0;
		private _dsx = _sza * _rad * sin _ang;
		private _dsy = _szb * _rad * cos _ang;
		[_psx + _dsx * cos -_dir - _dsy * sin -_dir, _psy + _dsx * sin -_dir + _dsy * cos -_dir]
	}
};

Results (right column from a deliberately broken algorithm):

Areapos.png

 

Test mission (VR map, Test option in action menu)

* ellipse distribution updated

  • Like 1

Share this post


Link to post
Share on other sites

Tnx KK, indeed, simpler. But harder to understand from pure logic point of view.

Not like I knew that solution before :tounge2:, so, yeah i guess i became a bit smarter :thumb_down:

Share this post


Link to post
Share on other sites

Ehh, it's true. But my version is much shorter and twice as fast, although less universal :P

Share this post


Link to post
Share on other sites
2 minutes ago, serena said:

Ehh, it's true. But my version is much shorter and twice as fast, although less universal :P


after you convert it to function and put in library and add all the checks it will lose quite some speed

Share this post


Link to post
Share on other sites
16 hours ago, killzone_kid said:

The sqrt is all you need

 

There I was, thought I'd seen it all, when out of the blue a sqrt hit me straight to the face.

 

Cheers

  • Like 4

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  

×