Jump to content
Sign in to follow this  
randy andy tw1

Marker Radius Random position help.

Recommended Posts

Hi all,

I have been trying to figure out how to select a position to place a marker down based upon the circumference of an eclipse marker

I have a marker called BASE thats a 100x100 eclipse marker (for testing)

what i want to do, is try to select a random point, that is only on the edge of the eclipse, and then place a second eclipse marker (to use as a position)

any ideas? thank you

Share this post


Link to post
Share on other sites

Place (say) 5 markers in a line.

Give each marker a name.

Set the size of each marker to 0,0. When a marker is that size it is invisible.

Create 5 triggers. Trigger 1 will change the size of marker 1. Trigger 2 will change the size of marker 2 etc etc etc

From the players point of view he fires a trigger and a marker suddenly appears on the map!

==========================================================

You can create 5 more triggers that cause the size of the various markers to return to size 0,0 if you need to.

Share this post


Link to post
Share on other sites

If I understand correctly you want to generate a random point on the edge of an ellipse?

If so:

_mark = "BASE";
_phi = random(360);
_x = cos(_phi);
_y = sin(_phi);

_posVector = [_x * ((markerSize _mark) select 0), _y * ((markerSize _mark) select 1), 0];
_newPos = (markerPos _mark) vectorAdd _posVector;

I think this should work assuming the marker isn't rotated (unless it's a circle, in which case it doesn't matter)

Edited by SilentSpike
Marker isn't centred on the origin

Share this post


Link to post
Share on other sites

Ah, this would give the illusion of having no markers, and then when the condition of the trigger is met, it would make the marker appear??

Ive posted a picture to try to help explain what i would ultimately like to achieve.

the base marker is a holding point or a starting position of the script

the script will look at the circumference of the marker and then choose a position along that circumference.

when it has that position, it will spawn in another 100x100 eclipse on that position

the next marker.. which is very tricky, will select a position along the circumference of the previous marker, and use that position to spawn another marker. HOWEVER at some point, i would like it so the positions it chooses do not enter a previous area of a marker, almost like a venn diagram, BUT the areas that cross (or the points along that circumference) are not selected as points.

IMAG0929_zpslk4ssfoq.jpg

---------- Post added at 01:00 PM ---------- Previous post was at 12:58 PM ----------

ultimately, it provides four-5 positions to be used as place holders for things to spawn on, positions for objectives etc. this way it would create positions that are x amount of meters from eachother, but it would be pretty random

---------- Post added at 01:13 PM ---------- Previous post was at 01:00 PM ----------

If I understand correctly you want to generate a random point on the edge of an ellipse?

If so:

_mark = "BASE";
_phi = random(360);
_x = cos(_phi);
_y = sin(_phi);

_pos = [_x * ((markerSize _mark) select 0), _y * ((markerSize _mark) select 1), 0];

I think this should work assuming the marker isn't rotated (unless it's a circle, in which case it doesn't matter)

Yes, this looks like the backbone of what I am looking for. Will try to get this to work and reply shortly. Thank you :thumbsup:

Share this post


Link to post
Share on other sites

I've updated the above code again, I forgot to account for the marker not being centred on the origin.

Share this post


Link to post
Share on other sites

im probably doing this the complete wrong way, but how would the marker spawn? so far i have

_mark = "BASE";
_phi = random(360);
_x = cos(_phi);
_y = sin(_phi);

_posVector = [_x * ((markerSize _mark) select 0), _y * ((markerSize _mark) select 1), 0];
_newPos = (markerPos _mark) vectorAdd _posVector;

_Marker1 = createMarker ["marker1", _newpos];
_Marker1 setMarkerAlpha 1;
_Marker1 setMarkerShape "ellipse";
_Marker1 setMarkerSize [100,100];
_Marker1 setMarkerPos getPosATL _newpos;

Share this post


Link to post
Share on other sites

This is the kind of thing I would do (the comments should generally explain what's going on):

// Define a function for repeately used code
_fnc_newPos = {
   private ["_mark","_phi","_x","_y","_posVector"];
   _mark = _this;


   // Generate a position on circle of radius 1
   _phi = random(360);
   _x = cos(_phi);
   _y = sin(_phi);


   // Scale to ellipse axes and offset from centre
   _posVector = [_x * ((markerSize _mark) select 0), _y * ((markerSize _mark) select 1), 0];
   (markerPos _mark) vectorAdd _posVector
};


_oldMark = "BASE";
for "_i" from 1 to 5 do {
   _newPos = _oldMark call _fnc_newPos;
   _newMark = "Marker" + str(_i); // Produce unique name

   createMarker [_newMark, _newPos];
   _newMark setMarkerShape "ELLIPSE";
   _newMark setMarkerSize [100,100];


   _oldMark = _newMark;
};

Share this post


Link to post
Share on other sites

thank you very much, this works very well! ive tried it a few times and its really good!

The only other thing i think it needs, but not even sure if it is possible is adding a line that excludes an area on the circumference to be used as a point

so like

Base mark spawns mark2

mark2 then looks along its circumference and thinks, base mark intercepts 270-360 so i can only use 0-270 degrees to place mark3

then mark three thinks, the same but take into account base marks and mark2s position.

this way it would generate ellipses that form more of a waypointed path? I must stress, the help you have given me is really appreciated!

Share this post


Link to post
Share on other sites

Unfortunately my geometry isn't quite up to scratch to come up with an elegant solution for ignoring previous markers.

However we can just use rejection sampling to get positions that don't lie within them. Are all of your markers going to be perfect circles? The code will be simpler if so, but it can also be done for ellipses.

Share this post


Link to post
Share on other sites

Yes, perfect circles. The reason why im using circles is so that i can see exactly where the centre is created along each mark. this would hopefully create a structure that forms a path, or like a patrol path. this way, using the centre of randomly generated circles, i can then (hopefully) use each marks position as a small AO to spawn enemy in.

This way every time the script loads, it loads a random patrol where each point is 100m (or soon to be 500m) away from eachother but the points dont intersect so the players patrol areas they havent necessarily been through. if this makes sense???? :/

---------- Post added at 02:23 PM ---------- Previous post was at 02:21 PM ----------

there is probably a better way to generate a random path to patrol but i kindof chose marker shapes to work with as they have a set distance and have a point which can be saved to be used later

Share this post


Link to post
Share on other sites

This will make sure the marker centres don't lie within one another:

// Define a function for repeately used code
_fnc_newPos = {
   private ["_mark","_phi","_x","_y","_posVector"];
   _mark = _this;


   // Generate a position on circle of radius 1
   _phi = random(360);
   _x = cos(_phi);
   _y = sin(_phi);


   // Scale to ellipse axes and offset from centre
   _posVector = [_x * ((markerSize _mark) select 0), _y * ((markerSize _mark) select 1), 0];
   (markerPos _mark) vectorAdd _posVector
};


_oldMark = "BASE";
_markArray = [];
for "_i" from 1 to 5 do {
   _newMark = "Marker" + str(_i); // Produce unique name
   _radius = (markerSize _oldMark) select 0;


   // Find a position that doesn't lie within any previous marker using rejection sampling
   _newPos = _oldMark call _fnc_newPos;
   while {
       ({ if ((_newPos vectorDistance (markerPos _x)) < _radius) exitWith {1}; false } count _markArray) > 0
   } do {
       _newPos = _oldMark call _fnc_newPos;
   };


   createMarker [_newMark, _newPos];
   _newMark setMarkerShape "ELLIPSE";
   _newMark setMarkerSize [_radius,_radius];


   _markArray pushBack _oldMark;
   _oldMark = _newMark;
};

Share this post


Link to post
Share on other sites
I'm sorry but I have to do this ;)

Eclipse - https://en.wikipedia.org/wiki/Eclipse

Ellipse - https://en.wikipedia.org/wiki/Ellipse

Doh!... if No one came back in time from the future to warn me, how bad could it be? :P

---------- Post added at 03:02 PM ---------- Previous post was at 02:59 PM ----------

This will make sure the marker centres don't lie within one another:

// Define a function for repeately used code
_fnc_newPos = {
   private ["_mark","_phi","_x","_y","_posVector"];
   _mark = _this;


   // Generate a position on circle of radius 1
   _phi = random(360);
   _x = cos(_phi);
   _y = sin(_phi);


   // Scale to ellipse axes and offset from centre
   _posVector = [_x * ((markerSize _mark) select 0), _y * ((markerSize _mark) select 1), 0];
   (markerPos _mark) vectorAdd _posVector
};


_oldMark = "BASE";
_markArray = [];
for "_i" from 1 to 5 do {
   _newMark = "Marker" + str(_i); // Produce unique name
   _radius = (markerSize _oldMark) select 0;


   // Find a position that doesn't lie within any previous marker using rejection sampling
   _newPos = _oldMark call _fnc_newPos;
   while {
       ({ if ((_newPos vectorDistance (markerPos _x)) < _radius) exitWith {1}; false } count _markArray) > 0
   } do {
       _newPos = _oldMark call _fnc_newPos;
   };


   createMarker [_newMark, _newPos];
   _newMark setMarkerShape "ELLIPSE";
   _newMark setMarkerSize [_radius,_radius];


   _markArray pushBack _oldMark;
   _oldMark = _newMark;
};

This is exactly what I need! Thank you very much for giving me your time to help me with this SilentSpike!

image?image_id=672

Share this post


Link to post
Share on other sites

This thread inspired me to write a new function for CBA, it uses totally vanilla commands though. Here it is for anyone interested:

private ["_zRef","_zSize","_zDir","_zRect","_zPos","_perimeter","_posVector"];
_zRef = _this select 0;
_perimeter = if (count _this > 1) then {_this select 1} else {false};


switch (typeName _zRef) do {
   case "STRING" : {
       if ((markerShape _zRef) in ["RECTANGLE","ELLIPSE"]) then {
           _zSize = markerSize _zRef;
           _zDir = markerDir _zRef;
           _zRect = (markerShape _zRef) == "RECTANGLE";
           _zPos = markerPos _zRef;
       };
   };
   case "OBJECT" : {
       if !((triggerArea _zRef) isEqualTo []) then {
           _zSize = triggerArea _zRef;
           _zDir = _zSize select 2;
           _zRect = _zSize select 3;
           _zPos = getPos _zRef;
       };
   };
};


if (isNil "_zSize") exitWith {[]};


private ["_x","_y","_a","_b","_rho","_phi","_x1","_x2","_y1","_y2"];
if (_zRect) then {
   _x = _zSize select 0;
   _y = _zSize select 1;
   _a = _x*2;
   _b = _y*2;


   if (_perimeter) then {
       _rho = random (2*(_a + _b));


       _x1 = (_rho min _a);
       _y1 = ((_rho - _x1) min _b) max 0;
       _x2 = ((_rho - _x1 - _y1) min _a) max 0;
       _y2 = ((_rho - _x1 - _y1 - _x2) min _b) max 0;
       _posVector = [(_x1 - _x2) - _x, (_y1 - _y2) - _y, 0];
   } else {
       _posVector = [random(_a) - _x, random(_b) - _y, 0];
   };
} else {
   _rho = if (_perimeter) then {1} else {random 1};
   _phi = random 360;
   _x = sqrt(_rho) * cos(_phi);
   _y = sqrt(_rho) * sin(_phi);


   _posVector = [_x * (_zSize select 0), _y * (_zSize select 1), 0];
};


_posVector = [_posVector, -_zDir] call BIS_fnc_rotateVector2D;


_zPos vectorAdd _posVector

It takes a marker/trigger and returns a random position within it. If a second boolean parameter is supplied as true then it will return only positions on the perimeter.

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  

×