简体   繁体   English

在最接近给定点的圆上找到点的最佳方法

[英]Best way to find a point on a circle closest to a given point

Given a point (pX, pY) and a circle with a known center (cX,cY) and radius (r), what is the shortest amount of code you can come up with to find the point on the circle closest to (pX, pY)?给定一个点 (pX, pY) 和一个已知圆心 (cX,cY) 和半径 (r) 的圆,您可以用最短的代码量找到圆上最接近 (pX, cY) 的点pY)?

I've got some code kind of working but it involves converting the circle to an equation of the form (x - cX)^2 + (y - cY)^2 = r^2 (where r is radius) and using the equation of the line from point (pX, pY) to (cX, cY) to create a quadratic equation to be solved.我有一些代码可以工作,但它涉及将圆转换为 (x - cX)^2 + (y - cY)^2 = r^2 形式的方程(其中 r 是半径)并使用方程从点 (pX, pY) 到 (cX, cY) 的线创建要求解的二次方程。

Once I iron out the bugs it'll do, but it seems such an inelegant solution.一旦我解决了它会做的错误,但它似乎是一个不优雅的解决方案。

where P is the point, C is the center, and R is the radius, in a suitable "mathy" language: 用合适的“数学”语言,其中P是点,C是中心,R是半径:

V = (P - C); Answer = C + V / |V| * R;

where |V| | V | is length of V. 是V的长度。

OK, OK 好的好的

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;

easy to extend to >2 dimensions. 易于扩展到> 2维。

我会从中心到点画一条线,然后计算该图与圆的交点oO我认为并不那么困难

Solve it mathematically first, then translate into code. 首先用数学方法解决它,然后翻译成代码。 Remember that the shortest line between a point and the edge of a circle will also pass through its center (as stated by @litb). 请记住,点与圆的边缘之间的最短线也将穿过其中心(如@litb所述)。

  1. The shortest distance point lies at the intersection of circumference and line passing through the center and the input point. 最短的距离点位于通过中心点和输入点的圆周线的交点。 Also center, input and output points lie on a straight line 中心点,输入点和输出点也位于一条直线上

  2. let the center be (xc, yc) and shortest point from input (xi, yi) be (x,y) then sqrt((xc-x)^2 + (yc-y)^2) = r 设中心为(xc,yc),输入(xi,yi)的最短点为(x,y),然后sqrt((xc-x)^ 2 +(yc-y)^ 2)= r

  3. since center, input and output points lie on a straight line, slope calculated between any of two of these points should be same. 由于中心点,输入点和输出点位于一条直线上,因此在这两个点中的任意一个之间计算的斜率应该相同。

(yc-yi)/(xc-xi) = (y-yc)/(x-xc) (yc-yi)/(xc-xi)=(y-yc)/(x-xc)

4.solving equations 2&3 should give us the shortest point. 4.求解方程式2&3应该给我们最短的时间。

触发函数,乘以r,然后适当加上pX或pY。

将圆心作为原点,将(pX,pY)的坐标转换为极坐标,(theta,r')将r'替换为原始圆的r,然后转换回直角坐标(并调整原点)。

You asked for the shortest code, so here it is. 您要求输入最短的代码,就在这里。 In four lines it can be done, although there is still a quadratic. 尽管仍然存在二次方,但可以用四行完成。 I've considered the point to be outside the circle. 我认为这一点不在圆上。 I've not considered what happens if the point is directly above or below the circle center, that is cX=pX. 我没有考虑过如果点在圆心的正上方或正下方,即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] Get an equation for a line connecting the point and the circle center. 1]得到一条连接点和圆心的直线方程。

2] Move along the line a distance of one radius from the center to find the point on the circle. 2]沿着直线从中心移动一个半径,以找到圆上的点。 That is: radius=a^2+b^2 which is: r=((cY-Y)+(cX-X))^(1/2) 即:radius = a ^ 2 + b ^ 2,即:r =((cY-Y)+(cX-X))^(1/2)

3] Solve quadratically. 3]二次求解。 X=quadratic_solver(r=((cY-Y)+(cX-X))^(1/2),X) which if you substitute in Y=m*X+b you get that hell above. X = quadratic_solver(r =(((cY-Y)+(cX-X))^(1/2),X)如果将其代入Y = m * X + b,则会得到上述结果。

4] X and Y are your results on the circle. 4] X和Y是您在圆上的结果。

I am rather certain I have made an error somewhere, please leave a comment if anyone finds something. 我相当确定我在某个地方出错了,如果有人发现问题,请发表评论。 Of course it is degenerate, one answer is furthest from your point and the other is closest. 当然,它是简并的,一个答案离您的观点最远,而另一个则最接近。

Easy way to think about it in terms of a picture, and easy to turn into code: Take the vector (pX - cX, pY - cY) from the center to the point. 从图片的角度考虑的简单方法,也容易将其转换为代码:从中心到点取向量(pX-cX,pY-cY)。 Divide by its length sqrt(blah blah blah), multiply by radius. 用其长度sqrt(blah blah blah)除以半径。 Add this to (cX, cY). 将此添加到(cX,cY)。

Here is a simple method I use in unity... for the math kn00bs amongst us.这是我统一使用的一个简单方法……用于我们中间的数学 kn00bs。 Its dependent on the transform orientation but it works nicely.它取决于变换方向,但效果很好。 I am doing a postion.z = 0 but just fatten the axis of the 2d circle you are not using.我正在做一个 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM