diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index a74356985..557180a32 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -3797,6 +3797,22 @@ do -- COORDINATE function COORDINATE:GetRandomPointVec3InRadius( OuterRadius, InnerRadius ) return COORDINATE:NewFromVec3( self:GetRandomVec3InRadius( OuterRadius, InnerRadius ) ) end + + +--- Search for clear zones in a given area. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery. +-- @param #number SearchRadius Radius of the search area. +-- @param #number PosRadius Required clear radius around each position. +-- @param #number NumPositions Number of positions to find. +-- @return #table A table of Core.Point#COORDINATE that are clear of map objects within the given PosRadius. + function COORDINATE:GetSimpleZones(SearchRadius, PosRadius, NumPositions) + local clearPositions = UTILS.GetSimpleZones(self:GetVec3(), SearchRadius, PosRadius, NumPositions) + local coords = {} + for _, pos in ipairs(clearPositions) do + local coord = COORDINATE:NewFromVec2(pos) + table.insert(coords, coord) + end + return coords + end end diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 6664364ed..a44698097 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -1509,6 +1509,43 @@ function ZONE_RADIUS:IsVec3InZone( Vec3 ) return InZone end +--- Search for clear ground spawn zones within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery. +-- @param #number PosRadius Required clear radius around each position. +-- @param #number NumPositions Number of positions to find. +-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. nil if no clear positions are found. +function ZONE_RADIUS:GetClearZonePositions(PosRadius, NumPositions) + local clearPositions = UTILS.GetSimpleZones(self:GetVec3(), self:GetRadius(), PosRadius, NumPositions) + if clearPositions or #clearPositions > 0 then + local validZones = {} + for _, vec2 in pairs(clearPositions) do + if self:IsVec2InZone(vec2) then + table.insert(validZones, vec2) + end + end + if #validZones > 0 then + return validZones + end + end + return nil +end + + +--- Search for a random clear ground spawn coordinate within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery. +-- @param #number PosRadius (Optional) Required clear radius around each position. (Default is math.min(Radius/10, 200)) +-- @param #number NumPositions (Optional) Number of positions to find. (Default 50) +-- @return Core.Point#COORDINATE A random coordinate for a clear zone. nil if no clear positions are found. +-- @return #number Assigned radius for the found zones. nil if no clear positions are found. +function ZONE_RADIUS:GetRandomClearZoneCoordinate(PosRadius, NumPositions) + local radius = PosRadius or math.min(self.Radius/10, 200) + local clearPositions = self:GetClearZonePositions(radius, NumPositions or 50) + if clearPositions or #clearPositions > 0 then + local randomPosition = clearPositions[math.random(1, #clearPositions)] + return COORDINATE:NewFromVec2(randomPosition), radius + end + + return nil +end + --- Returns a random Vec2 location within the zone. -- @param #ZONE_RADIUS self -- @param #number inner (Optional) Minimal distance from the center of the zone. Default is 0. diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index b184e46aa..aeddb7fa9 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -4630,3 +4630,13 @@ function UTILS.DestroyScenery(name, level) net.dostring_in("mission",string.format("a_scenery_destruction_zone(%d, %d)", z.zoneId, level)) end end + +--- Search for clear zones in a given area. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery. +-- @param DCS##Vec3 Center position vector for the search area. +-- @param #number SearchRadius Radius of the search area. +-- @param #number PosRadius Required clear radius around each position. +-- @param #number NumPositions Number of positions to find. +-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. +function UTILS.GetSimpleZones(Vec3, SearchRadius, PosRadius, NumPositions) + return Disposition.getSimpleZones(Vec3, SearchRadius, PosRadius, NumPositions) +end diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 520f8b923..80c4d20cb 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -1467,7 +1467,7 @@ function AIRBASE:Register(AirbaseName) self.descriptors=self:GetDesc() -- Debug info. - --self:I({airbase=AirbaseName, descriptors=self.descriptors}) + --self:T({airbase=AirbaseName, descriptors=self.descriptors}) -- Category. self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME @@ -2634,6 +2634,7 @@ function AIRBASE:_InitRunways(IncludeInverse) --runway.name=string.format("%02d", tonumber(name)) runway.magheading=tonumber(runway.name)*10 + runway.idx=runway.magheading runway.heading=heading runway.width=width or 0 runway.length=length or 0 @@ -2946,6 +2947,7 @@ function AIRBASE:GetRunwayData(magvar, mark) local runway={} --#AIRBASE.Runway runway.heading=hdg runway.idx=idx + runway.magheading=idx runway.length=c1:Get2DDistance(c2) runway.position=c1 runway.endpoint=c2 @@ -2961,6 +2963,57 @@ function AIRBASE:GetRunwayData(magvar, mark) -- Add runway. table.insert(runways, runway) + end + + -- Look for identical (parallel) runways, e.g. 03L and 03R at Nellis. + local rpairs={} + for i,_ri in pairs(runways) do + local ri=_ri --#AIRBASE.Runway + for j,_rj in pairs(runways) do + local rj=_rj --#AIRBASE.Runway + if i 0 + return ((b.z - a.z)*(c.x - a.x) - (b.x - a.x)*(c.z - a.z)) > 0 + end + + for i,j in pairs(rpairs) do + local ri=runways[i] --#AIRBASE.Runway + local rj=runways[j] --#AIRBASE.Runway + + -- Draw arrow. + --ri.center:ArrowToAll(rj.center) + + local c0=ri.center + + -- Vector in the direction of the runway. + local a=UTILS.VecTranslate(c0, 1000, ri.heading) + + -- Vector from runway i to runway j. + local b=UTILS.VecSubstract(rj.center, ri.center) + b=UTILS.VecAdd(ri.center, b) + + -- Check if rj is left of ri. + local left=isLeft(c0, a, b) + + --env.info(string.format("Found pair %s: i=%d, j=%d, left==%s", ri.name, i, j, tostring(left))) + + if left then + ri.isLeft=false + rj.isLeft=true + else + ri.isLeft=true + rj.isLeft=false + end + + --break end return runways