using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YKMoon.Math
{
public partial class YKMath
{
public static Vector2 GetVector2IgnoreYAxis(Vector2 v)
{
v.y = 0;
return v;
}
public static Vector2 GetDeltaIgnoreZAxis(Vector3 from, Vector3 to)
{
return new Vector2((to - from).x, (to - from).y);
}
public static Vector2 GetDisIgnoreZAxis(Vector3 posA, Vector3 posB)
{
return new Vector2(Mathf.Abs((posA - posB).x), Mathf.Abs((posA - posB).y));
}
///
/// 三点确认抛物线, 获得抛物线内的percent%的点
///
/// 起点
/// 终点
/// 轨迹内任意点
/// 最高点
/// 百分比
///
public static Vector2 GetParabolaPos(Vector2 P1, Vector2 P2, Vector2 P3, out Vector2 maxHeightPos, float percent)
{
float a, b, c;
CalculateABC(P1, P2, P3, out a, out b, out c);
float x = Mathf.Lerp(P1.x, P2.x, percent);
float y = a * x * x + b * x + c;
Vector2 position = new Vector2(x, y);
maxHeightPos.x = -b / (2 * a);
maxHeightPos.y = c - b * b / (4 * a);
return position;
}
///
/// 三点确认抛物线, 获得抛物线内的percent%的点,只计算XY平面投影
///
///
///
///
///
///
///
public static Vector3 GetParabolaPos3DXY(Vector3 P1, Vector3 P2, Vector3 P3, out Vector3 maxHeightPos, float percent)
{
//先计算2D投影
float a, b, c;
CalculateABC(P1, P2, P3, out a, out b, out c);
float x = Mathf.Lerp(P1.x, P2.x, percent);
float y = a * x * x + b * x + c;
float z = Mathf.Lerp(P1.z, P2.z, percent);
Vector3 position = new Vector3(x, y, z);
maxHeightPos.x = -b / (2 * a);
maxHeightPos.y = c - b * b / (4 * a);
maxHeightPos.z = Mathf.Lerp(P1.z, P2.z, (maxHeightPos.x - P1.x) / (P2.x - P1.x));
return position;
}
///
/// 三点确认抛物线,获得抛物线的二次方程abc参数, ax^2+bx+c=0
///
private static void CalculateABC(Vector2 P1, Vector2 P2, Vector2 P3, out float a, out float b, out float c)
{
float x1 = P1.x;
float y1 = P1.y;
float x2 = P3.x;
float y2 = P3.y;
float x3 = P2.x;
float y3 = P2.y;
a = (y1 * x2) + (x1 * y3) + (y2 * x3) - (y3 * x2) - (x3 * y1) - (y2 * x1);
a /= x1 * x1 * x2 + x3 * x3 * x1 + x3 * x2 * x2 - x3 * x3 * x2 - x3 * x1 * x1 - x2 * x2 * x1;
b = x1 * x1 * y2 + y1 * x3 * x3 + x2 * x2 * y3 - x3 * x3 * y2 - x1 * x1 * y3 - x2 * x2 * y1;
b /= x1 * x1 * x2 + x3 * x3 * x1 + x3 * x2 * x2 - x3 * x3 * x2 - x3 * x1 * x1 - x2 * x2 * x1;
c = (x1 * x1 * x2 * y3) + (x1 * y2 * x3 * x3) + (y1 * x3 * x2 * x2) - (x3 * x3 * x2 * y1) - (x3 * y2 * x1 * x1) - (y3 * x1 * x2 * x2);
c /= x1 * x1 * x2 + x3 * x3 * x1 + x3 * x2 * x2 - x3 * x3 * x2 - x3 * x1 * x1 - x2 * x2 * x1;
}
///
/// 在圆内均匀分布点。
///
/// 圆的半径,要生成点在该半径的圆内
/// 要生成点的数量
///
public static List RandomPointInCircle(float radius, int count, float minDisBetweenPos)
{
List result = new List();
/*float r;//公式的r系数
float theta;//公式的角度系数
float x;
float y;
float randomValue;//0-1的随机值
System.Random random = new System.Random();
for(int i = 0; i < count; i++) {
// Tip 此处要注意! r和theta的生成要分别生成随机数,公式概念中明确说明,r和theta要互不相干
randomValue = (float)random.NextDouble();
r = math.sqrt(randomValue) * radius;
randomValue = (float)random.NextDouble();
theta = 2 * math.PI * randomValue;
//生成x,y坐标,
x = (float)r * math.cos(theta);
y = (float)r * math.sin(theta);
result.Add(new Vector2(x, y));//* 0.5; 若要变成椭圆,将X和Y结果值乘上你想要的比例系数即可
}*/
while(result.Count < count) {
var pos = UnityEngine.Random.insideUnitCircle * radius;
bool isMatch = true;
for(int i = 0; i < result.Count; i++) {
if(Vector3.Distance(result[i], pos) < minDisBetweenPos) {
isMatch = false;
break;
}
}
if(isMatch) {
result.Add(pos);
} else {
break;
}
}
while(result.Count < count) {
var pos = UnityEngine.Random.insideUnitCircle * radius;
result.Add(pos);
}
return result;
}
///
/// 生成随机点均匀分布在圆内
///
/// 半径
/// 点个数
///
public static List RandomPointsInCircleUniformly(float radius, int count)
{
List result = new List();
System.Random random = new System.Random();
for(int i=0; i
/// 简谐运动cos版
///
/// 时间点
/// 振幅
/// 频率 = 1/一个周期时长
/// 初相位,单位为弧度
/// if true use cos else sin.
/// 位移
public static float SimpleHarmonicMotion(float time, float frequency, float Amplitude = 0.5f, float phi = 0, bool isCos = true)
{
//位移时间方程 x = Acos(ωt + φ)
//圆频率ω = 2πf
//频率f
//相位φ
//振幅A
float omega = 2 * Mathf.PI * frequency;
if(isCos) {
return Amplitude * Mathf.Cos(omega * time + phi);
} else {
return Amplitude * Mathf.Sin(omega * time + phi);
}
}
}
}