randy andy tw1 12 Posted July 6, 2015 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
Joe98 92 Posted July 6, 2015 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
SilentSpike 84 Posted July 6, 2015 (edited) 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 July 6, 2015 by SilentSpike Marker isn't centred on the origin Share this post Link to post Share on other sites
randy andy tw1 12 Posted July 6, 2015 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. ---------- 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 Share this post Link to post Share on other sites
SilentSpike 84 Posted July 6, 2015 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
randy andy tw1 12 Posted July 6, 2015 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
SilentSpike 84 Posted July 6, 2015 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
randy andy tw1 12 Posted July 6, 2015 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
SilentSpike 84 Posted July 6, 2015 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
randy andy tw1 12 Posted July 6, 2015 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
killzone_kid 1333 Posted July 6, 2015 I'm sorry but I have to do this ;) Eclipse - https://en.wikipedia.org/wiki/Eclipse Ellipse - https://en.wikipedia.org/wiki/Ellipse Share this post Link to post Share on other sites
SilentSpike 84 Posted July 6, 2015 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
randy andy tw1 12 Posted July 6, 2015 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! Share this post Link to post Share on other sites
SilentSpike 84 Posted July 6, 2015 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