#pragma once #include #include #include #include #include #include class Math { private: /* data */ public: Math(/* args */) = default; ~Math() = default; public: static void InitRandomSeed() { static bool seeded = false; if (!seeded) { srand(static_cast(time(nullptr))); seeded = true; } } // 1. 获取X轴方向(0:目标在左侧,1:目标在右侧) static int getDirectionToTargetX(float objX, float x) { return (objX > x) ? 0 : 1; } // 2. 生成[Min, Max]范围内的随机整数(左闭右闭) static int Rand(int Min, int Max) { InitRandomSeed(); // 确保随机数种子已初始化 if (Min > Max) { throw std::invalid_argument("Rand: Min must be less than or equal to Max"); } // 计算随机数范围:(Max - Min + 1)个可能值 int range = Max - Min + 1; // rand()返回[0, RAND_MAX],通过取模和偏移实现范围映射 return Min + (rand() % range); } // 3. 从数组中随机获取一个元素(支持任意可索引容器) template static T GetRandomElementFromArray(const std::vector &arr) { if (arr.empty()) { throw std::invalid_argument("GetRandomElementFromArray: Array is empty"); } int randomIndex = Rand(0, static_cast(arr.size()) - 1); return arr[randomIndex]; } // 5. 根据方向计算偏移后的X坐标 static float GetDistancePos(float startX, int direction, float offsetX) { return (direction == 0) ? (startX - offsetX) : (startX + offsetX); } // 6. 通过两点坐标计算旋转角度(预留实现,需根据具体需求补充) static float getRorateAngleByCurrentPos(float x1, float y1, float z1, float x2, float y2, float z2) { // 示例实现:计算X-Z平面内的角度(可根据需求调整为3D角度) float dx = x2 - x1; float dz = z2 - z1; // atan2(dz, dx):返回与X轴正方向的夹角(弧度),范围[-π, π] return std::atan2(dz, dx); } // 8. 标准抛物线计算(y = a(x - c/2)² + b,开口向下) static float sq_Parabola(float x, float b, float c) { if (c == 0) { throw std::invalid_argument("sq_Parabola: c cannot be zero"); } // 计算抛物线系数a(确保顶点在x=c/2,y=b) float a = (-4.0f * b) / (c * c); return a * (x - c / 2.0f) * (x - c / 2.0f) + b; } // 9. 计算2D平面两点距离(Y轴权重0.29,用于透视校正) static float Get2D_Distance(float x1, float y1, float x2, float y2) { float offsetX = x1 - x2; float offsetY = (y1 - y2) * 0.29f; // 勾股定理计算距离 return std::sqrt(offsetX * offsetX + offsetY * offsetY); } // 10. 判断角度是否在[startA, endA]形成的锐角范围内(角度单位:度) static bool CheckAngleIsInArea(float judge, float startA, float endA) { // 步骤1:将角度标准化到[0, 360)范围 auto normalizeAngle = [](float angle) { angle = std::fmod(angle, 360.0f); return (angle < 0) ? (angle + 360.0f) : angle; }; startA = normalizeAngle(startA); endA = normalizeAngle(endA); judge = normalizeAngle(judge); // 特殊情况:范围跨0度(如startA=350°,endA=10°) if (startA > 270.0f && startA < 360.0f && endA > 0.0f && endA < 90.0f) { return (judge >= startA && judge <= 360.0f) || (judge >= 0.0f && judge <= endA); } // 普通情况:范围不跨0度 else { // 处理startA > endA的正常范围(如startA=30°,endA=60°) if (startA > endA) { std::swap(startA, endA); } return (judge >= startA && judge <= endA); } } // 11. 弧度转角度 static float toDegree(float radian) { return radian * 57.2957795f; // 180/π ≈ 57.2957795 } // 12. 角度转弧度 static float toRadian(float degree) { return degree * 0.0174532925f; // π/180 ≈ 0.0174532925 } // 13. 判断点是否在立方体内(立方体由对角点定义) static bool pointIsInCubeArea(float px, float py, float pz, float startX, float startY, float startZ, float endX, float endY, float endZ) { // 计算立方体中心点和半边长 float cubeCenterX = (startX + endX) / 2.0f; float cubeXLen = std::fabs(startX - endX) / 2.0f; float cubeCenterY = (startY + endY) / 2.0f; float cubeYLen = std::fabs(startY - endY) / 2.0f; float cubeCenterZ = (startZ + endZ) / 2.0f; float cubeZLen = std::fabs(startZ - endZ) / 2.0f; // 点到各轴中心点的距离 ≤ 半边长 → 在立方体内 return (std::fabs(px - cubeCenterX) <= cubeXLen + 1e-6f) && (std::fabs(py - cubeCenterY) <= cubeYLen + 1e-6f) && (std::fabs(pz - cubeCenterZ) <= cubeZLen + 1e-6f); } // 14. 立方体与立方体碰撞检测(基于顶点和中心点判断) static bool CubeAndCubeCollection(float c1StartX, float c1StartY, float c1StartZ, float c1EndX, float c1EndY, float c1EndZ, float c2StartX, float c2StartY, float c2StartZ, float c2EndX, float c2EndY, float c2EndZ) { // 优化说明:原Squirrel代码判断过多冗余点,此处保留核心顶点+中心点判断 const std::vector> c1Points = { // 立方体1的8个顶点 {c1StartX, c1StartY, c1StartZ}, {c1EndX, c1StartY, c1StartZ}, {c1StartX, c1EndY, c1StartZ}, {c1EndX, c1EndY, c1StartZ}, {c1StartX, c1StartY, c1EndZ}, {c1EndX, c1StartY, c1EndZ}, {c1StartX, c1EndY, c1EndZ}, {c1EndX, c1EndY, c1EndZ}, // 立方体1的中心点 {(c1StartX + c1EndX) / 2, (c1StartY + c1EndY) / 2, (c1StartZ + c1EndZ) / 2}}; const std::vector> c2Points = { // 立方体2的8个顶点 {c2StartX, c2StartY, c2StartZ}, {c2EndX, c2StartY, c2StartZ}, {c2StartX, c2EndY, c2StartZ}, {c2EndX, c2EndY, c2StartZ}, {c2StartX, c2StartY, c2EndZ}, {c2EndX, c2StartY, c2EndZ}, {c2StartX, c2EndY, c2EndZ}, {c2EndX, c2EndY, c2EndZ}, // 立方体2的中心点 {(c2StartX + c2EndX) / 2, (c2StartY + c2EndY) / 2, (c2StartZ + c2EndZ) / 2}}; // 检查立方体1的点是否在立方体2内 for (const auto &[x, y, z] : c1Points) { if (pointIsInCubeArea(x, y, z, c2StartX, c2StartY, c2StartZ, c2EndX, c2EndY, c2EndZ)) { return true; } } // 检查立方体2的点是否在立方体1内 for (const auto &[x, y, z] : c2Points) { if (pointIsInCubeArea(x, y, z, c1StartX, c1StartY, c1StartZ, c1EndX, c1EndY, c1EndZ)) { return true; } } return false; } // 15. 计算三角形面积(叉乘法,避免开方,效率更高) static float get3PointArea(float x1, float y1, float x2, float y2, float x3, float y3) { // 面积公式:0.5 * |x1(y2-y3) + x2(y3-y1) + x3(y1-y2)| return 0.5f * std::fabs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)); } // 16. 计算四边形面积(拆分为两个三角形面积之和) static float get4PointArea(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { // 四边形拆分为:(x1,y1)-(x2,y2)-(x3,y3) 和 (x2,y2)-(x3,y3)-(x4,y4) float area1 = get3PointArea(x1, y1, x2, y2, x3, y3); float area2 = get3PointArea(x2, y2, x3, y3, x4, y4); return area1 + area2; } // 17. 判断点是否在四边形内(面积比较法,要求四边形顶点按顺序排列) static bool pointIsIn4PointArea(float px, float py, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { const float eps = 10.0f; // 容差(原Squirrel代码定义为10.0) float totalArea = get4PointArea(x1, y1, x2, y2, x3, y3, x4, y4); // 点与四边形各边组成的4个三角形面积之和 float sumArea = get3PointArea(x1, y1, x2, y2, px, py) + get3PointArea(x2, y2, x3, y3, px, py) + get3PointArea(x3, y3, x4, y4, px, py) + get3PointArea(x4, y4, x1, y1, px, py); // 面积差在容差范围内 → 点在四边形内 return std::fabs(totalArea - sumArea) < eps; } // 18. 判断点是否在矩形内(矩形由坐标数组定义,格式:[x, y, width, height]) static bool PointIsInSquare(float x1, float y1, const std::vector &SquareArr) { if (SquareArr.size() != 4) { throw std::invalid_argument("PointIsInSquare: SquareArr must have 4 elements (x, y, width, height)"); } float sqX = SquareArr[0]; float sqY = SquareArr[1]; float sqWidth = SquareArr[2]; float sqHeight = SquareArr[3]; // 点的X在[sqX, sqX+width],Y在[sqY, sqY+height] → 在矩形内 return (x1 >= sqX - 1e-6f) && (x1 <= sqX + sqWidth + 1e-6f) && (y1 >= sqY - 1e-6f) && (y1 <= sqY + sqHeight + 1e-6f); } static float getUniformVelocity(float sv, float ev, float currentRate, float maxRate) { // 避免除零错误 if (maxRate <= 0.0f) { throw std::invalid_argument("maxRate must be greater than 0"); } // 计算当前进度比例(0.0到1.0之间) float rate = currentRate / maxRate; // 限制比例在[0, 1]范围内,避免超出边界 rate = std::clamp(rate, 0.0f, 1.0f); // 计算变化量并返回当前值 float varyValue = ev - sv; return sv + varyValue * rate; } };