CarlGustaffa 4 Posted November 7, 2007 Hi Is there any way to quickly test if a point is located anywhere within a marker? Rectangle or ellipse at any sizes and angle. Share this post Link to post Share on other sites
fasad 1 Posted November 7, 2007 You can create a trigger covering the same area, and use the list command. It should be reasonably easy to create a script function that checks the given position against the marker's position, shape, angle and area, but I don't know about you, but my maths is a bit rusty Share this post Link to post Share on other sites
sbsmac 0 Posted November 7, 2007 I have code to do this for rectangular and elliptical markers which I use for a minefield script. One annoying problem is that there is no way to detect whether a marker is rectangular or elliptical (ie there is no 'markerShape' function) so you need to know in advance which function you are going to call. For a rectangle the basic principle is to get the relative position of the point of interest from the center of the rectangle, rotate the resulting point by -1 times the angle of the rectangle, then test the x and y coordinates against the a and b dimensions of the rectangle. For ellipses, the quickest method is to precompute the position of the two focii. Do this by calculating the distance of the focii from the center point d= sqrt (b^2 - a^2) The focii (F1,F2) lie at points d away from the center, in the direction the ellipse is rotated. From then on , a point is inside the ellipse if distance from P to F1 added to distance from P to F2 is less than 2a. I'll post code here over the weekend if you are interested. Share this post Link to post Share on other sites
dr_eyeball 16 Posted November 8, 2007 Quick way for all - no. Quick way for some - yes. Check the UPS script, it does all these checks for any marker shape and angle. Share this post Link to post Share on other sites
CarlGustaffa 4 Posted November 8, 2007 Yes, I thought about using triggers. But then I'd have to create an object and check its existence (?) within the trigger. Seemed a way over the top I have managed to create random points within rectangular offsetted area at an angle, but still not a way to check. I guess the maths is similar, but yeah, maths skills deterioate quickly I guess Naturally I have the ups, I'll check that one. Thanks for pointing this one out. Share this post Link to post Share on other sites
fasad 1 Posted November 8, 2007 Since I didn't know how to check the ellipse, I found out, and did it. My maths is pretty bad these days and they have not been checked for either logic or scripting mistakes, but they seem to work in my testing Two functions, one for rectangles, one for elipses (elipsii?). They return true if given position is inside the marker area, otherwise false. Feel free to do anything with these, I'm sure they could be improved upon. Example of use: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">insideMarkerR = compile preprocessFile "insideMarkerR.sqf"; _inMarker = [getPos player, "testMarker"] call insideMarkerR; insideMarkerR.sqf <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> //returns true if given position is within the given rectangular marker //all angles are math style, cause I'm stupid :) //rectangle version private ["_posi","_markerName","_markerPos","_markerSize","_markerDir","_relDist","_relAngle","_markAngle"]; //_position is a 3d position array _posi = _this select 0; //marker name must be a string _markerName = _this select 1; //3d position array _markerPos = markerPos _markerName; //2d array, x-radius, y-radius _markerSize = markerSize _markerName; //change dir to maths dir _markerDir = 90 -(markerDir _markerName); //distance between marker center and position _relDist = (_markerPos distance _posi); //check if distance is greater than 1.42 (approx sqrt 2) if ((_relDist > (1.42*(_markerSize select 0))) && (_relDist > (1.42*(_markerSize select 1)))) exitWith {false}; // if ((_relDist < _markerSize select 0) && (_relDist < _markerSize select 1)) exitWith {true}; //angle between 0 and a line between marker and posi _relAngle = (90 - ((_posi select 0) - (_markerPos select 0)) atan2 ((_posi select 1) - (_markerPos select 1))); if (_relAngle > 180) then {_relAngle = -(360 - _relAngle)}; //angle between marker's direction and a line between marker and posi _markAngle = 90 - (_markerDir - _relAngle); if (_markAngle > 180) then {_markAngle = -(360 - _markAngle)}; /*//sidechat feedback used in testing player sideChat format ["rel angle is %1",_relAngle]; player sideChat format ["mark angle is %1",_markAngle]; player sideChat format ["relX is %1, relY is %2",(_relDist*(cos _markAngle)), (_relDist*(sin _markAngle))];*/ if ((abs (_relDist*(cos _markAngle)) < _markerSize select 0) && (abs (_relDist*(sin _markAngle)) < _markerSize select 1) ) exitWith {true}; //if not inside, must be outside! false insideMarkerR.sqf <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> //returns true if given position is within the given eliptical marker //all angles are math style (north = +90), cause I'm stupid :) //elipse version private ["_posi","_markerName","_markerPos","_markerSize","_markerDir","_relDist","_relAngle","_markAngle"]; //_position is a 3d position array _posi = _this select 0; //marker name must be a string _markerName = _this select 1; //3d position array _markerPos = markerPos _markerName; //2d array, x-radius, y-radius _markerSize = markerSize _markerName; //change dir to maths dir _markerDir = 90 -(markerDir _markerName); //distance between marker center and position _relDist = (_markerPos distance _posi); //check if distance is greater than large axis if (_relDist > ((_markerSize select 0) max (_markerSize select 1))) exitWith {false}; //check if distance is less than smaller axis if (_relDist < ((_markerSize select 0) min (_markerSize select 1))) exitWith {true}; //angle between 0 and a line between marker and posi _relAngle = (90 - ((_posi select 0) - (_markerPos select 0)) atan2 ((_posi select 1) - (_markerPos select 1))); if (_relAngle > 180) then {_relAngle = -(360 - _relAngle)}; //angle between marker's direction and a line between marker and posi _markAngle = 90 - (_markerDir - _relAngle); if (_markAngle > 180) then {_markAngle = -(360 - _markAngle)}; /*sidechat feedback used in testing player sideChat format ["rel angle is %1",_relAngle]; player sideChat format ["mark angle is %1",_markAngle]; player sideChat format ["relX is %1, relY is %2",(_relDist*(cos _markAngle)), (_relDist*(sin _markAngle))]; player sideChat format["checkSum is %1", (((_relDist*(cos _markAngle))*(_relDist*(cos _markAngle)))/((_markerSize select 0)*(_markerSize select 0))) + (((_relDist*(sin _markAngle))*(_relDist*(sin _markAngle)))/((_markerSize select 1)*(_markerSize select 1)))]; */ //check if posi is in elipse. equation was found on wikipedia if ((((_relDist*(cos _markAngle))*(_relDist*(cos _markAngle)))/((_markerSize select 0)*(_markerSize select 0))) + (((_relDist*(sin _markAngle))*(_relDist*(sin _markAngle)))/((_markerSize select 1)*(_markerSize select 1))) < 1) exitWith {true}; //if not inside, must be outside! false 'love those brackets Share this post Link to post Share on other sites
CarlGustaffa 4 Posted November 8, 2007 Thanks for the reply. But I've spent most of my working day with excel today, and I came up with this. It does appear to work just from quick testing in init.sqf on the mission. Easy to rewrite for more global use though I think. Here is the result: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> sleep 0.1; //Begin Script _px = position player select 0; _py = position player select 1; _mpx = getMarkerPos "mTest" select 0; _mpy = getMarkerPos "mTest" select 1; _msx = getMarkerSize "mTest" select 0; _msy = getMarkerSize "mTest" select 1; _ma = -markerDir "mTest"; _xmin = _mpx - _msx; _xmax = _mpx + _msx; _ymin = _mpy - _msy; _ymax = _mpy + _msy; //Now, rotate point to investigate around markers center in order to check against a nonrotated marker _rpx = Â ( (_px - _mpx) * cos(_ma) ) + ( (_py - _mpy) * sin(_ma) ) + _mpx; _rpy = (-(_px - _mpx) * sin(_ma) ) + ( (_py - _mpy) * cos(_ma) ) + _mpy; //Now for the actual test against markersize. hint format ["px %1\npy %2\nmpx %3\nmpy %4\nmsx %5\nmsy %6\nma %7\nxmin %8\nxmax %9\nymin %10\nymax %11\nrpx %12\nrpy %13", _px, _py, _mpx, _mpy, _msx, _msy, _ma, _xmin, _xmax, _ymin, _ymax, _rpx, _rpy]; if (((_rpx > _xmin) && (_rpx < _xmax)) && ((_rpy > _ymin) && (_rpy < _ymax))) then { Â Â player globalChat "player inside marker"; } else { Â Â player globalChat "player outside marker"; }; //End of Script And here is the end of the script but for elliptical markers, after rotated points _rpx and _rpy has been calculated: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> _res = (((_rpx-_mpx)^2)/(_msx^2)) + (((_rpy-_mpy)^2)/(_msy^2)); if ( _res < 1 ) then { player globalChat "player inside marker"; } else { player globalChat "player outside marker"; }; Not quite sure how much parantheses is really needed. Share this post Link to post Share on other sites
CarlGustaffa 4 Posted November 10, 2007 I've written this into function form. Maybe someone could test if it works properly? Does *seem* to work for me though. Have included enough comments for newbies to understand what is going on. The point of it all is to check if a point; object or an icon  marker, lies inside a rectangular or elliptical area marker of any size and angle. In order to reduce the complexity of the angle maths, I rotate the point to inventigate the oposite amount of degrees the marker is rotated, about the markers center point. I needed this because I need No-Fire-Zones for certain types of munitions for my artillery in my mission, and these zones are marked with, well, area markers The function: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> // call with check = ["markerpoint", "markertocheckagainst", "type"] call markerCheck; for markers // call with check = [object, "markertocheckagainst", "type"] call markerCheck; for objects // object is an object, i.e. player or uTankNumber3. "markerpoint" can be used for automatically generated markers, such as "mTargetMarker" // "markertocheckagainst" is the name of the marker as a string that is the area you want to check against. // Type is a string indicating "R" or "E" to enable rectangular or elliptical checks respectively. //variables needs to be set private for function to work private ["_p","_m", "_t", "_px", "_py", "_mpx", "_mpy", "_msx", "_msy", "_rpx", "_rpy", "_xmin", "_xmax", "_ymin", "_ymax", "_ma", "_res", "_ret"]; //description of variable names //_p   point to investigate, typically an object or marker with a position //_m   marker to check against //_t   marker type, string "R" or "E" for rectangular or elliptical markers respectively //_px  x value of point //_py  y value of point //_mpx  markerpos x //_mpy  markerpos y //_msx  markersize x //_msy  markersize y //_rpx  rotated position point x //_rpy  rotated position point y //_xmin minimum point x in a rectangular marker //_xmax maximum point x in a rectangular marker //_ymin minimum point y in a rectangular marker //_ymax maximum point y in a rectangular marker //_ma  marker angle //_res  result carrier in elliptic marker //_ret  return value _p = _this select 0; //object _m = _this select 1; //always a marker _t = _this select 2; //marker shape, "E" or "R" if (typeName _p == "OBJECT") then {   _px = position _p select 0;   _py = position _p select 1; } else {   _px = getMarkerPos _p select 0;   _py = getMarkerPos _p select 1; }; _mpx = getMarkerPos _m select 0; _mpy = getMarkerPos _m select 1; _msx = getMarkerSize _m select 0; _msy = getMarkerSize _m select 1; _ma = -markerDir _m; _rpx = ( (_px - _mpx) * cos(_ma) ) + ( (_py - _mpy) * sin(_ma) ) + _mpx; _rpy = (-(_px - _mpx) * sin(_ma) ) + ( (_py - _mpy) * cos(_ma) ) + _mpy; if (_t == "R") then {   _xmin = _mpx - _msx;   _xmax = _mpx + _msx;   _ymin = _mpy - _msy;   _ymax = _mpy + _msy;   if (((_rpx > _xmin) && (_rpx < _xmax)) && ((_rpy > _ymin) && (_rpy < _ymax))) then   {     _ret=true;   }   else   {     _ret=false;   }; } else {   _res = (((_rpx-_mpx)^2)/(_msx^2)) + (((_rpy-_mpy)^2)/(_msy^2));   if ( _res < 1 ) then   {     _ret=true;   }   else   {     _ret=false;   }; }; _ret; In the init.sqf: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> markerCheck = compile preprocessFile "checkinsidemarker.sqf"; Check with following: <table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE"> check = ["mTest", "mR001_AB", "E"] call markerCheck; //check if marker lies inside an elliptical marker called mR001_AB check = [player, "mR001_AB", "R"] call markerCheck; //check if player lies inside a rectangular marker called mR001_AB Function returns true or false. Yippi, my first ever function  Share this post Link to post Share on other sites
Armitxes 36 Posted December 24, 2014 (edited) I know that this thread is very old but it's still relevant and Nr. 1 displayed in google :) The above code snippets can't be read and are outdated. Here a new improved version of it: // call with check = ["markerpoint", "markertocheckagainst"] call fnc_isInMarker; for markers // call with check = [object, "markertocheckagainst"] call fnc_isInMarker; for objects fnc_isInMarker = { private ["_p","_m", "_px", "_py", "_mpx", "_mpy", "_msx", "_msy", "_rpx", "_rpy", "_xmin", "_xmax", "_ymin", "_ymax", "_ma", "_res", "_ret"]; _p = _this select 0; // object _m = _this select 1; // marker if (typeName _p == "OBJECT") then { _px = position _p select 0; _py = position _p select 1; } else { _px = getMarkerPos _p select 0; _py = getMarkerPos _p select 1; }; _mpx = getMarkerPos _m select 0; _mpy = getMarkerPos _m select 1; _msx = getMarkerSize _m select 0; _msy = getMarkerSize _m select 1; _ma = -markerDir _m; _rpx = ( (_px - _mpx) * cos(_ma) ) + ( (_py - _mpy) * sin(_ma) ) + _mpx; _rpy = (-(_px - _mpx) * sin(_ma) ) + ( (_py - _mpy) * cos(_ma) ) + _mpy; if ((markerShape _m) == "RECTANGLE") then { _xmin = _mpx - _msx;_xmax = _mpx + _msx;_ymin = _mpy - _msy;_ymax = _mpy + _msy; if (((_rpx > _xmin) && (_rpx < _xmax)) && ((_rpy > _ymin) && (_rpy < _ymax))) then { _ret=true; } else { _ret=false; }; } else { _res = (((_rpx-_mpx)^2)/(_msx^2)) + (((_rpy-_mpy)^2)/(_msy^2)); if ( _res < 1 ) then{ _ret=true; }else{ _ret=false; }; }; _ret; }; Cheers and happy X-Mas Edited December 24, 2014 by Armitxes Share this post Link to post Share on other sites
madrussian 347 Posted December 28, 2014 Here's a quick method using locations (call as func): private ["_pos","_mark","_inside","_shape","_loc"]; _pos = _this select 0; _mark = _this select 1; _inside = false; _shape = markerShape _mark; if (! (_shape == "ICON")) then { _loc = createLocation (["Name", markerPos _mark] + (markerSize _mark)); if (_shape == "RECTANGLE") then { _loc setRectangular true }; _loc setDirection (markerDir _mark); if (_pos in _loc) then { _inside = true }; deleteLocation _loc; }; _inside Share this post Link to post Share on other sites