给定一个点 (pX, pY) 和一个已知圆心 (cX,cY) 和半径 (r) 的圆,您可以想出最短的代码量来找到圆上最接近 (pX) 的点, pY) ?
我有一些代码可以工作,但它涉及将圆转换为 (x - cX)^2 + (y - cY)^2 = r^2 (其中 r 是半径)形式的方程并使用从点 (pX, pY) 到 (cX, cY) 的直线方程,以创建要求解的二次方程。
一旦我解决了错误,它就会解决问题,但这似乎是一个不优雅的解决方案。
其中 P 是点,C 是中心,R 是半径,用合适的“数学”语言来说:
V = (P - C); Answer = C + V / |V| * R;
其中 |V|是 V 的长度。
好的,好的
double vX = pX - cX;
double vY = pY - cY;
double magV = sqrt(vX*vX + vY*vY);
double aX = cX + vX / magV * R;
double aY = cY + vY / magV * R;
易于扩展到>2维。
我会从中心到点画一条线,并计算该图与圆相交的位置oO我认为并不那么困难
首先用数学方法解决它,然后转化为代码。 请记住,点和圆的边缘之间的最短线也将穿过其中心(如@litb所述)。
最短距离点位于圆周与穿过中心和输入点的线的交点处。而且中心、输入和输出点位于一条直线上
设中心为 (xc, yc),输入 (xi, yi) 的最短点为 (x,y) sqrt((xc-x)^2 + (yc-y)^2) = r
由于中心,输入和输出点位于一条直线上,计算斜率 其中任何两点都应该相同。
(yc-yi)/(xc-xi) = (y-yc)/(x-xc)
4.解方程2和3应该可以得到最短点。
您要求最短的代码,所以就在这里。 尽管还有二次方,但四行就可以完成。 我认为这个点在圆之外。 我没有考虑如果该点位于圆心正上方或正下方会发生什么,即 cX=pX。
m=(cY-pY)/(cX-pX); //slope
b=cY-m*cX; //or Py-m*Px. Now you have a line in the form y=m*x+b
X=( (2mcY)*((-2*m*cY)^2-4*(cY^2+cX^2-b^2-2*b*cY-r^2)*(-1-m^2))^(1/2) )/(2*(cY^2+cX^2-b^2-2*bc*Y-r^2));
Y=mX+b;
1] 得到连接该点和圆心的直线方程。
2] 沿直线距离圆心移动一个半径的距离,找到圆上的点。 即:radius=a^2+b^2 即:r=((cY-Y)+(cX-X))^(1/2)
3] 求解二次方程。 X=quadratic_solver(r=((cY-Y)+(cX-X))^(1/2),X) 如果你用 Y=m*X+b 代替,你会得到上面的地狱。
4] X 和 Y 是你在圆上的结果。
我很确定我在某个地方犯了错误,如果有人发现了什么,请发表评论。 当然这是退化的,一个答案离你的观点最远,另一个答案最接近。
三角函数,乘以 r,并根据需要添加 pX 或 pY。
以圆心为原点,将 (pX, pY) 坐标转换为极坐标,(theta, r') 将 r' 替换为原圆的 r 并转换回笛卡尔坐标(并调整原点)。
用图片来思考,也很容易转化为代码:取从中心到点的向量(pX - cX,pY - cY)。除以长度 sqrt(blah blah blah),乘以半径。将其添加到 (cX, cY)。
这是我已经使用了一段时间的 Python 程序。 (p2X,p2Y) 是从 (pX,pY) 到 (cX,cY) 的最近点 它确实使用了 trig,事实上它是用 Python 编写的,这可能使它变得相当慢,但它只有 5 行。
import math
pX, pY = 1, 1
cX, cY = 0, 0
r = 25
slopeX = pX-cX
slopeY = pY-cY
dir=(math.atan(slopeX/slopeY)+(180*(slopeY<0)))
p2X = cX+math.sin(dir)*r
p2Y = cY+math.cos(dir)*r
这是我统一使用的一个简单方法......用于我们之间的数学知识。 它取决于变换方向,但效果很好。我正在做一个 postion.z = 0 但只是加粗你没有使用的 2d 圆的轴。
//Find closest point on circle
Vector3 closestPoint = transform.InverseTransformPoint(m_testPosition.position);
closestPoint.z = 0;
closestPoint = closestPoint.normalized * m_radius;
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.TransformPoint(closestPoint), 0.01f);