93 lines
3.1 KiB
Lua
93 lines
3.1 KiB
Lua
|
math = math == nil and {} or math;
|
||
|
|
||
|
math.pi = math.pi == nil and 3.14159265358979 or math.pi;
|
||
|
|
||
|
---clamp
|
||
|
---@param v number @number
|
||
|
---@param Min number @min
|
||
|
---@param Max number @max
|
||
|
---@return number @clamp v between Min and Max
|
||
|
function math.clamp(v, Min, Max)
|
||
|
local min = math.min(Min, Max)
|
||
|
local max = math.max(Min, Max)
|
||
|
if v < min then return min end
|
||
|
if v > max then return max end
|
||
|
return v
|
||
|
end
|
||
|
|
||
|
--- 随机bool变量
|
||
|
function math.randBool() return math.pop() > 0.5; end
|
||
|
|
||
|
---clamp
|
||
|
---@param a number @First number to compare
|
||
|
---@param b number @Second number to compare
|
||
|
---@param Tolerance number @Maximum allowed difference for considering them as 'nearly equal'
|
||
|
---@return boolean @true if a and b are nearly equal
|
||
|
function math.isNearlyEqual(a, b, Tolerance)
|
||
|
if Tolerance == nil then Tolerance = 0.01 end
|
||
|
return math.abs(a - b) <= Tolerance;
|
||
|
end
|
||
|
|
||
|
--- 一个存放随机数的列表
|
||
|
math.RandomList = {};
|
||
|
|
||
|
function math.init(InCount)
|
||
|
-- 初始化的时候进行随机种子
|
||
|
math.randomseed(os.time())
|
||
|
for i = 1, InCount do table.insert(math.RandomList, math.random()); end
|
||
|
end
|
||
|
|
||
|
function math.pop()
|
||
|
local val = math.RandomList[1]
|
||
|
if val == nil then
|
||
|
math.init(100);
|
||
|
return math.pop();
|
||
|
end
|
||
|
table.remove(math.RandomList, 1);
|
||
|
return val;
|
||
|
end
|
||
|
|
||
|
--- 在给定圆内随机生成一个给定半径的圆,返回圆的中心点
|
||
|
---@param Center FVector 给定圆
|
||
|
---@param Radius float 给定圆的半径
|
||
|
---@param MinRadius float 目标生成圆的半径圆的半径
|
||
|
function math.randomCircleInCircle(Center, Radius, MinRadius)
|
||
|
local TargetRadius = Radius - MinRadius;
|
||
|
if TargetRadius < 0 then return nil; end
|
||
|
if TargetRadius == 0 then return Center; end
|
||
|
|
||
|
local X = Center.X + (math.randBool() and 1 or -1) * math.pop() * TargetRadius;
|
||
|
local Y = Center.Y + (math.randBool() and 1 or -1) * math.pop() * TargetRadius;
|
||
|
|
||
|
local ResCenter = {};
|
||
|
local ANum = math.sqrt((X - Center.X) ^ 2 + (Y - Center.Y) ^ 2)
|
||
|
if ANum > TargetRadius then
|
||
|
ResCenter = { X = Center.X - TargetRadius + ANum, Y = Center.Y - TargetRadius + ANum, Z = Center.Z, };
|
||
|
end
|
||
|
ResCenter = { X = X, Y = Y, Z = Center.Z, };
|
||
|
-- 检查一下距离
|
||
|
local Dis = math.sqrt((ResCenter.X - Center.X) ^ 2 + (ResCenter.Y - Center.Y) ^ 2 + (Center.Z and (ResCenter.Z - Center.Z) ^ 2 or 0))
|
||
|
if Dis > TargetRadius then return math.randomCircleInCircle(Center, Radius, MinRadius); end
|
||
|
return ResCenter;
|
||
|
end
|
||
|
|
||
|
---@param c FVector
|
||
|
---@param R float
|
||
|
---@param r float
|
||
|
function math.randCircle(c, R, r)
|
||
|
local x = math.pop() * 2 * (R - r) + (c.X - (R - r));
|
||
|
local a = math.pop() * math.pi;
|
||
|
local p = math.getCirclePoint(c, math.abs(x), { X = x, Y = c.Y, }, a);
|
||
|
return { X = p.X, Y = p.Y, Z = c.Z, };
|
||
|
end
|
||
|
|
||
|
--- 获取圆上一点与圆心连接的线形成 θ 角度的另一个点(逆时针)
|
||
|
---@param o FVector2D 圆点所在坐标
|
||
|
---@param r float 圆的半径
|
||
|
---@param p FVector2D 圆上的一点
|
||
|
---@param t float 跟 @p 到 @o 形成夹角为 t 的线,弧度值
|
||
|
function math.getCirclePoint(o, r, p, t)
|
||
|
local angle = math.atan((p.Y - o.Y) / (p.X - o.X)) + t
|
||
|
return { X = o.X + r * math.cos(angle), Y = o.Y + r * math.sin(angle), };
|
||
|
end
|