mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
* Adding a new TerminalType (100)that seems to be introduced in the update that brought Muwaffaq Salti. The base has a couple of spots (like 04, 05, 06) that can only accommodate smaller type fixed wing aircraft, like the F-16, but not bigger types like the Warthog of the Strike Eagle. Because we weren't checking for this new type, spawning in these particular spots always resulted in an airstart, because `_CheckTerminalType` would always return `false` * Adding Shapes over from old MOOSE branch * cleanup * adding HEXtoRGBA * removing Arrow.lua, it's part of Polygon.lua
260 lines
9.2 KiB
Lua
260 lines
9.2 KiB
Lua
--
|
|
--
|
|
-- ### Author: **nielsvaes/coconutcockpit**
|
|
--
|
|
-- ===
|
|
-- @module Shapes.CIRCLE
|
|
|
|
--- CIRCLE class.
|
|
-- @type CIRCLE
|
|
-- @field #string ClassName Name of the class.
|
|
-- @field #number Radius Radius of the circle
|
|
|
|
--- *It's NOT hip to be square* -- Someone, somewhere, probably
|
|
--
|
|
-- ===
|
|
--
|
|
-- # CIRCLE
|
|
-- CIRCLEs can be fetched from the drawings in the Mission Editor
|
|
|
|
-- This class has some of the standard CIRCLE functions you'd expect. One function of interest is CIRCLE:PointInSector() that you can use if a point is
|
|
-- within a certain sector (pizza slice) of a circle. This can be useful for many things, including rudimentary, "radar-like" searches from a unit.
|
|
|
|
-- @field #CIRCLE
|
|
|
|
--- CIRCLE class with properties and methods for handling circles.
|
|
CIRCLE = {
|
|
ClassName = "CIRCLE",
|
|
Radius = nil,
|
|
}
|
|
--- Finds a circle on the map by its name. The circle must have been added in the Mission Editor
|
|
-- @param #string shape_name Name of the circle to find
|
|
-- @return #CIRCLE The found circle, or nil if not found
|
|
function CIRCLE:FindOnMap(shape_name)
|
|
local self = BASE:Inherit(self, SHAPE_BASE:FindOnMap(shape_name))
|
|
for _, layer in pairs(env.mission.drawings.layers) do
|
|
for _, object in pairs(layer["objects"]) do
|
|
if string.find(object["name"], shape_name, 1, true) then
|
|
if object["polygonMode"] == "circle" then
|
|
self.Radius = object["radius"]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Finds a circle by its name in the database.
|
|
-- @param #string shape_name Name of the circle to find
|
|
-- @return #CIRCLE The found circle, or nil if not found
|
|
function CIRCLE:Find(shape_name)
|
|
return _DATABASE:FindShape(shape_name)
|
|
end
|
|
|
|
--- Creates a new circle from a center point and a radius.
|
|
-- @param #table vec2 The center point of the circle
|
|
-- @param #number radius The radius of the circle
|
|
-- @return #CIRCLE The new circle
|
|
function CIRCLE:New(vec2, radius)
|
|
local self = BASE:Inherit(self, SHAPE_BASE:New())
|
|
self.CenterVec2 = vec2
|
|
self.Radius = radius
|
|
return self
|
|
end
|
|
|
|
--- Gets the radius of the circle.
|
|
-- @return #number The radius of the circle
|
|
function CIRCLE:GetRadius()
|
|
return self.Radius
|
|
end
|
|
|
|
--- Checks if a point is contained within the circle.
|
|
-- @param #table point The point to check
|
|
-- @return #bool True if the point is contained, false otherwise
|
|
function CIRCLE:ContainsPoint(point)
|
|
if ((point.x - self.CenterVec2.x) ^ 2 + (point.y - self.CenterVec2.y) ^ 2) ^ 0.5 <= self.Radius then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Checks if a point is contained within a sector of the circle. The start and end sector need to be clockwise
|
|
-- @param #table point The point to check
|
|
-- @param #table sector_start The start point of the sector
|
|
-- @param #table sector_end The end point of the sector
|
|
-- @param #table center The center point of the sector
|
|
-- @param #number radius The radius of the sector
|
|
-- @return #bool True if the point is contained, false otherwise
|
|
function CIRCLE:PointInSector(point, sector_start, sector_end, center, radius)
|
|
center = center or self.CenterVec2
|
|
radius = radius or self.Radius
|
|
|
|
local function are_clockwise(v1, v2)
|
|
return -v1.x * v2.y + v1.y * v2.x > 0
|
|
end
|
|
|
|
local function is_in_radius(rp)
|
|
return rp.x * rp.x + rp.y * rp.y <= radius ^ 2
|
|
end
|
|
|
|
local rel_pt = {
|
|
x = point.x - center.x,
|
|
y = point.y - center.y
|
|
}
|
|
|
|
local rel_sector_start = {
|
|
x = sector_start.x - center.x,
|
|
y = sector_start.y - center.y,
|
|
}
|
|
|
|
local rel_sector_end = {
|
|
x = sector_end.x - center.x,
|
|
y = sector_end.y - center.y,
|
|
}
|
|
|
|
return not are_clockwise(rel_sector_start, rel_pt) and
|
|
are_clockwise(rel_sector_end, rel_pt) and
|
|
is_in_radius(rel_pt, radius)
|
|
end
|
|
|
|
--- Checks if a unit is contained within a sector of the circle. The start and end sector need to be clockwise
|
|
-- @param #string unit_name The name of the unit to check
|
|
-- @param #table sector_start The start point of the sector
|
|
-- @param #table sector_end The end point of the sector
|
|
-- @param #table center The center point of the sector
|
|
-- @param #number radius The radius of the sector
|
|
-- @return #bool True if the unit is contained, false otherwise
|
|
function CIRCLE:UnitInSector(unit_name, sector_start, sector_end, center, radius)
|
|
center = center or self.CenterVec2
|
|
radius = radius or self.Radius
|
|
|
|
if self:PointInSector(UNIT:FindByName(unit_name):GetVec2(), sector_start, sector_end, center, radius) then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Checks if any unit of a group is contained within a sector of the circle. The start and end sector need to be clockwise
|
|
-- @param #string group_name The name of the group to check
|
|
-- @param #table sector_start The start point of the sector
|
|
-- @param #table sector_end The end point of the sector
|
|
-- @param #table center The center point of the sector
|
|
-- @param #number radius The radius of the sector
|
|
-- @return #bool True if any unit of the group is contained, false otherwise
|
|
function CIRCLE:AnyOfGroupInSector(group_name, sector_start, sector_end, center, radius)
|
|
center = center or self.CenterVec2
|
|
radius = radius or self.Radius
|
|
|
|
for _, unit in pairs(GROUP:FindByName(group_name):GetUnits()) do
|
|
if self:PointInSector(unit:GetVec2(), sector_start, sector_end, center, radius) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Checks if all units of a group are contained within a sector of the circle. The start and end sector need to be clockwise
|
|
-- @param #string group_name The name of the group to check
|
|
-- @param #table sector_start The start point of the sector
|
|
-- @param #table sector_end The end point of the sector
|
|
-- @param #table center The center point of the sector
|
|
-- @param #number radius The radius of the sector
|
|
-- @return #bool True if all units of the group are contained, false otherwise
|
|
function CIRCLE:AllOfGroupInSector(group_name, sector_start, sector_end, center, radius)
|
|
center = center or self.CenterVec2
|
|
radius = radius or self.Radius
|
|
|
|
for _, unit in pairs(GROUP:FindByName(group_name):GetUnits()) do
|
|
if not self:PointInSector(unit:GetVec2(), sector_start, sector_end, center, radius) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
--- Checks if a unit is contained within a radius of the circle.
|
|
-- @param #string unit_name The name of the unit to check
|
|
-- @param #table center The center point of the radius
|
|
-- @param #number radius The radius to check
|
|
-- @return #bool True if the unit is contained, false otherwise
|
|
function CIRCLE:UnitInRadius(unit_name, center, radius)
|
|
center = center or self.CenterVec2
|
|
radius = radius or self.Radius
|
|
|
|
if UTILS.IsInRadius(center, UNIT:FindByName(unit_name):GetVec2(), radius) then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Checks if any unit of a group is contained within a radius of the circle.
|
|
-- @param #string group_name The name of the group to check
|
|
-- @param #table center The center point of the radius
|
|
-- @param #number radius The radius to check
|
|
-- @return #bool True if any unit of the group is contained, false otherwise
|
|
function CIRCLE:AnyOfGroupInRadius(group_name, center, radius)
|
|
center = center or self.CenterVec2
|
|
radius = radius or self.Radius
|
|
|
|
for _, unit in pairs(GROUP:FindByName(group_name):GetUnits()) do
|
|
if UTILS.IsInRadius(center, unit:GetVec2(), radius) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Checks if all units of a group are contained within a radius of the circle.
|
|
-- @param #string group_name The name of the group to check
|
|
-- @param #table center The center point of the radius
|
|
-- @param #number radius The radius to check
|
|
-- @return #bool True if all units of the group are contained, false otherwise
|
|
function CIRCLE:AllOfGroupInRadius(group_name, center, radius)
|
|
center = center or self.CenterVec2
|
|
radius = radius or self.Radius
|
|
|
|
for _, unit in pairs(GROUP:FindByName(group_name):GetUnits()) do
|
|
if not UTILS.IsInRadius(center, unit:GetVec2(), radius) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
--- Returns a random Vec2 within the circle.
|
|
-- @return #table The random Vec2
|
|
function CIRCLE:GetRandomVec2()
|
|
local angle = math.random() * 2 * math.pi
|
|
|
|
local rx = math.random(0, self.Radius) * math.cos(angle) + self.CenterVec2.x
|
|
local ry = math.random(0, self.Radius) * math.sin(angle) + self.CenterVec2.y
|
|
|
|
return {x=rx, y=ry}
|
|
end
|
|
|
|
--- Returns a random Vec2 on the border of the circle.
|
|
-- @return #table The random Vec2
|
|
function CIRCLE:GetRandomVec2OnBorder()
|
|
local angle = math.random() * 2 * math.pi
|
|
|
|
local rx = self.Radius * math.cos(angle) + self.CenterVec2.x
|
|
local ry = self.Radius * math.sin(angle) + self.CenterVec2.y
|
|
|
|
return {x=rx, y=ry}
|
|
end
|
|
|
|
--- Calculates the bounding box of the circle. The bounding box is the smallest rectangle that contains the circle.
|
|
-- @return #table The bounding box of the circle
|
|
function CIRCLE:GetBoundingBox()
|
|
local min_x = self.CenterVec2.x - self.Radius
|
|
local min_y = self.CenterVec2.y - self.Radius
|
|
local max_x = self.CenterVec2.x + self.Radius
|
|
local max_y = self.CenterVec2.y + self.Radius
|
|
|
|
return {
|
|
{x=min_x, y=min_x}, {x=max_x, y=min_y}, {x=max_x, y=max_y}, {x=min_x, y=max_y}
|
|
}
|
|
end
|
|
|