【前言】
前段时间,做地面雷达投影项目,有这么个需求,需要在画面的圆中才能交互出特效,思索了几天,弄了几种圆内的判断方案,分享一下。
配图:1.0版本雷达项目截图,需要在圆中交互,右中上闪动的点为交互生成特效
【方案梳理】建议用方案2,简单代码少
【方案1简介】
最初做的基于圆内(不是椭圆),作等边三角形(类似于等边三角形的外接圆),然后用检测的点和圆上三个点传递进方法里做算法,以下见代码。
配图:圆上取ABC三点作等边三角形,A点坐标(圆心x,圆心y+上半径y),B点坐标(左半径中点的x,下半径中点的y),C点坐标(右半径中点的x,下半径中点的y)
【放出代码】
做法参照CSDN帖子(https://blog.csdn.net/mrbaolong/article/details/48227685)改的C#代码
/// <summary>
/// 如果点(p)位于由三角形(p1,p2,p3)组成的圆周内,则返回true
/// </summary>
/// <remarks>
///注意:边缘上有一个点在外圈内
/// </remarks>
/// <param name="p">检测的点</param>
/// <param name="p1">圆上的第一点</param>
/// <param name="p2">圆上的第二点</param>
/// <param name="p3">圆上的第三点</param>
/// <returns>如果p在圆内,则为真</returns>
private static bool InCircle(Vector2 p, Vector2 p1, Vector2 p2, Vector2 p3)
{
//Return TRUE if the point (xp,yp) lies inside the circumcircle
//made up by points (x1,y1) (x2,y2) (x3,y3)
//NOTE: A point on the edge is inside the circumcircle
if (System.Math.Abs(p1.y - p2.y) < double.Epsilon && System.Math.Abs(p2.y - p3.y) < double.Epsilon)
{
//INCIRCUM - F - Points are coincident !!
return false;
}
double m1, m2;
double mx1, mx2;
double my1, my2;
double xc, yc;
if (System.Math.Abs(p2.y - p1.y) < double.Epsilon)
{
m2 = -(p3.x - p2.x) / (p3.y - p2.y);
mx2 = (p2.x + p3.x) * 0.5;
my2 = (p2.y + p3.y) * 0.5;
//Calculate CircumCircle center (xc,yc)
xc = (p2.x + p1.x) * 0.5;
yc = m2 * (xc - mx2) + my2;
}
else if (System.Math.Abs(p3.y - p2.y) < double.Epsilon)
{
m1 = -(p2.x - p1.x) / (p2.y - p1.y);
mx1 = (p1.x + p2.x) * 0.5;
my1 = (p1.y + p2.y) * 0.5;
//Calculate CircumCircle center (xc,yc)
xc = (p3.x + p2.x) * 0.5;
yc = m1 * (xc - mx1) + my1;
}
else
{
m1 = -(p2.x - p1.x) / (p2.y - p1.y);
m2 = -(p3.x - p2.x) / (p3.y - p2.y);
mx1 = (p1.x + p2.x) * 0.5;
mx2 = (p2.x + p3.x) * 0.5;
my1 = (p1.y + p2.y) * 0.5;
my2 = (p2.y + p3.y) * 0.5;
//Calculate CircumCircle center (xc,yc)
xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
yc = m1 * (xc - mx1) + my1;
}
double dx = p2.x - xc;
double dy = p2.y - yc;
double rsqr = dx * dx + dy * dy;
//double r = Math.Sqrt(rsqr); //外接圆半径
dx = p.x - xc;
dy = p.y - yc;
double drsqr = dx * dx + dy * dy;
return (drsqr <= rsqr);
}
【方案2简介】
上图中x0和y0是检测点相对于圆心的x,y坐标,a,b分别是椭圆的长半径和短半径,参照点在圆内的计算公式就能写出算法,以下见代码。
配图:为网图,仅作参照
【放出代码】
/// <summary>
/// 判断点在圆内
/// </summary>
/// <param name="point">检测的点</param>
/// <param name="centerPoint">圆心点</param>
/// <param name="x">x的半径长</param>
/// <param name="y">y的半径</param>
/// <returns></returns>
private bool inOval(Vector2 point, Vector2 centerPoint, float x, float y)
{
double v = Mathf.Pow(centerPoint.x - point.x, 2) / Mathf.Pow(x, 2) + Mathf.Pow(centerPoint.y - point.y, 2) / Mathf.Pow(y, 2);
return v < 1;
}
【最后想说】
最近去鹅厂做UE4客户端,也正在适应Unity转UE4这个过程,过段时间会分享一些相关的心得,也是很久没更新文章了,所以借此时机,再更新一些之前对Unity使用的一些技巧,请多多支持鸭。