Jump to content
Sign in to follow this  
gc8

Function for free landing zone?

Recommended Posts

hi

is it possible to find clear landing zone for helicopter?

I tried this code but it often returns places at tree lines or inside forest.


_exp = "(1 + meadow) * (1 - forest) * (1 - trees)";
_bestplace = selectBestPlaces [_pos,_radius,_exp,50,1];

thx

Share this post


Link to post
Share on other sites

look into the command isFlatEmpty on the wiki, its more streamlined for open spaces

Share this post


Link to post
Share on other sites

Actually I need multible landingzones.. the isFlatEmpty allows to look for one only...

thats why i tried to use selectbestplaces. But thanks anyway

Share this post


Link to post
Share on other sites
Actually I need multible landingzones..

You can give the following function a try:

fn_randomCirclePositions.sqf:

/*
 Author: rübe

 Description:
 Generate random positions around a center position within 
 the given limitations (distance, sector and findSafePos).

 The function does not guarantee to return the desired 
 amount of positions and may return an empty array anyway!

   - Beware: You could get positions on islands though... :/

  Parameter(s):
   _this: parameters (array of array [key (string), value (any)])

          - required:

            - "position" (position)

            - "number" (int)
              - number of positions to be returned, though it's 
                not guaranteed that this many will be returned.

          - optional:

            - "range" (array of [minDistance (scalar), maxDistance (scalar)])
              - default: [0, 250]

            - "sector" (array of [minAngle (scalar), maxAngle (scalar)])
              - default: [0, 360]

            - "objDistance" (scalar)
              - minimal distance to other/nearest objects
              - default = 1

            - "posDistance" (scalar)
              - minimal distance between returned positions
              - default = "objDistance" * 2

            - "adjustPos" (scalar)
              - if greater than zero, the sample position may be adjusted
                at max. the given distance to better fit isFlatEmpty criteria.
              - default: 0  

            - "roadDistance" (scalar)
              - 0: doesn't matter/no check
              - n > 0: minimal distance to any roads 
              - default: 0

            - "locationDistance" (scalar)
              - 0: doesn't matter/no check
              - n > 0: minimal distance to nearest location
              - default: 0

            - "locations" (array of strings)
              - define what is considered a location
              - affects "locationDistance"
              - default: ["NameCityCapital", "NameCity", "NameVillage"]

            - "blacklist" (array of positions)
              - default = empty

            - "blacklistDistance" (scalar)
               min. distance to stay away from points in the blacklist,
               aka a radius, if you like.
              - default = 500;  

            - "maxGradient"   (scalar from 0.0 to 1.0)
              - default = 1.0;

            - "gradientRadius" (scalar in m)
              - default = "objDistance"

            - "waterMode" (int from 0 to 2)
               - 0: cannot be in water
               - 1: can either be in water or not
               - 2: must be in water
               - default: 0

            - "onShore" (boolean/int from 0 to 1)
               - 0: does not have to be at a shore
               - 1: must be at a shore
               - default: 0


 Example:
     _positions = [
        ["position", _campCenterPosition],
        ["number", 7],
        ["range", [0, 120]],
        ["sector", [0, 360]],
        ["objDistance", (_tentLength * 0.5)],
        ["maxGradient", 0.3]
     ] call RUBE_randomCirclePositions; 

 Returns:
  array-of-positions OR empty-array

*/

private ["_thePositions", "_pos", "_numPos", "_distMin", "_distMax", "_dirMin", "_dirMax", "_objDistance", "_posDistance", "_adjustPos", "_maxGradient", "_gradientRadius", "_waterMode", "_onShore", "_roadDistance", "_locationDistance", "_locationDefinition", "_entities", "_i", "_maxIter", "_accepted", "_diceDir", "_diceDist", "_dicePos", "_blacklist", "_blacklistDistance"];

_thePositions = [];

// catch arguments
_pos = [0,0,0];
_numPos = 1;
_distMin = 0;
_distMax = 250;
_dirMin = 0;
_dirMax = 360;
_objDistance = 1;
_posDistance = false;
_adjustPos = 0;
_maxGradient = 1.0;
_gradientRadius = false;
_waterMode = 0;
_onShore = false;
_roadDistance = 0;
_locationDistance = 0;
_locationDefinition = [
  "NameCityCapital",
  "NameCity",
  "NameVillage"
];
_blacklist = [];
_blacklistDistance = 500;

// read parameters
{
  switch (_x select 0) do
  {
     case "position": { _pos = _x select 1; };
     case "number": { _numPos = _x select 1; };
     case "range": { 
        _distMin = (_x select 1) select 0; 
        _distMax = (_x select 1) select 1; 
     };
     case "sector": { 
        _dirMin = (_x select 1) select 0; 
        _dirMax = (_x select 1) select 1; 
     };
     case "adjustPos": { _adjustPos = _x select 1; };
     case "objDistance": { _objDistance = _x select 1; };
     case "posDistance": { _posDistance = _x select 1; };
     case "blacklist": { _blacklist = _x select 1; };
     case "blacklistDistance": { _blacklistDistance = _x select 1; };
     case "maxGradient": { _maxGradient = _x select 1; };
     case "gradientRadius": { _gradientRadius = _x select 1; };
     case "waterMode": { _waterMode = _x select 1; };
     case "onShore": { 
        if ((typeName (_x select 1)) == "BOOL") then
        {
           _onShore = _x select 1; 
        } else {
           if ((_x select 1) == 1) then
           {
              _onShore = true;
           }; 
        };
     };
     case "roadDistance": { _roadDistance = _x select 1; }; 
     case "locationDistance": { _locationDistance = _x select 1; };
     case "locations": { _locationDefinition = _x select 1; };
  };
} forEach _this;

// set adaptive auto default values
if ((typeName _posDistance) == "BOOL") then
{
  _posDistance = _objDistance * 2;
};

if ((typeName _gradientRadius) == "BOOL") then
{
  _gradientRadius = _objDistance;
};

if ((count _blacklist) == 0) then
{
  _blacklistDistance = 0;
};


// we may need more iterations if we need a minimum distance between the positions
_i = 0;
_maxIter = 1000;
if (_posDistance > 0) then
{
  // roughly approximated..
  _maxIter = _maxIter + (_posDistance * _numPos);
};

// search n positions
while {(count _thePositions) < _numPos} do
{
  _diceDir = _dirMin + (random (_dirMax - _dirMin));
  _diceDist = _distMin + (random (_distMax - _distMin));
  _dicePos = [
     ((_pos select 0) + (_diceDist * (sin _diceDir))),
     ((_pos select 1) + (_diceDist * (cos _diceDir))),
     0
  ];

  // check if the position is safe
  if ((count (_dicePos isFlatEmpty[_objDistance, _adjustPos, _maxGradient, _gradientRadius, _waterMode, _onShore, objNull])) > 0) then
  {
     // check if dicePos is not too near to an already accepted position
     _accepted = true;
     if (_posDistance > 0) then
     {
        {
           if ((_dicePos distance _x) < _posDistance) then
           {
              _accepted = false;
           };
        } forEach _thePositions;
     };

     if (_roadDistance > 0) then
     {
        _entities = _dicePos nearRoads _roadDistance;
        if ((count _entities) > 0) then
        {
           _accepted = false;
        };
     };

     if (_locationDistance > 0) then
     {
        _entities = nearestLocations [_dicePos, _locationDefinition, _locationDistance];
        if ((count _entities) > 0) then
        {
           _accepted = false;
        };
     };      

     if (_blacklistDistance > 0) then
     {
        {
           if ((_dicePos distance _x) < _blacklistDistance) exitWith
           {
              _accepted = false;
           };
        } forEach _blacklist;
     };      

     // all sub-tests passed?
     if (_accepted) then
     {
        _thePositions = _thePositions + [_dicePos];
     };
  };

  // we do not wanna search forever...
  if (_i > _maxIter) exitWith {};
  _i = _i + 1;
}; 


// return
_thePositions

Use the parameter "objDistance" to define the size of the needed area and set a reasonable max gradient with "maxGradient".

Since the function doesn't guarantee to return the desired amount of positions, the strategy would be to call that function in a while loop until it does return enough positions, while loosening the restrictions every iteration (for example you could increase the search radius or up maxGradient slightly or something).

If you need an example on how to use this function, you could look into my RUBE Fire Ants mission.

Share this post


Link to post
Share on other sites

i used this in my prareinforce v 1.2 script, works everytime, need function module:

_hPad = editorplaced_hPad_name;  // object we place at the found LZ.

_findGoodSpot = true;
_maxdist = 100;  // max initial range from below position to search for LZ.
_LZpos = getPos player;  // position where a safe LZ should be found.
while {_findGoodSpot} do {
_posTemp = [_LZpos, 0, _maxdist, 10, 0, 0.5, 0] call BIS_fnc_findSafePos;
_maxdist = _maxdist + 10;  // add to the range to check if no LZ found.
sleep 2;
_string = format _posTemp;
sleep 1;
if (!isNil ("_string")) then {
	_hPad setPos _posTemp;  // place the hPad at the found LZ and exit while loop.
	_findGoodSpot = false;
};
};

Share this post


Link to post
Share on other sites
You can give the following function a try:

fn_randomCirclePositions.sqf:

Great script thanks! you wrote it?

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  

×