抛物线与线段的交点

发布于 2024-09-16 12:26:52 字数 2986 浏览 6 评论 0原文

在用户单击图形的情况下,我有一个与指定点相交的抛物线方程。

 // this would typically be mouse coords on the graph
 var _target:Point = new Point(100, 50);

 public static function plot(x:Number, target:Point):Number{
  return (x * x) / target.x * (target.y / target.x);
 }

这给出了如下图:

parabolic curve

我还有一系列由开始和结束坐标定义的线段:

startX:Number, startY:Number, endX:Number, endY:Number

I需要找到该曲线是否以及在何处与这些线段相交 (A):

alt text

如果有任何帮助,startX 始终是 < endX

我感觉有一种相当直接的方法可以做到这一点,但我真的不知道要搜索什么,也不太精通“正确的”数学,所以实际的代码示例将非常非常感谢。

更新:

我已经得到了交集,但我的解决方案给了我 y 轴错误一侧的坐标。

分别用 A 和 B 替换我的目标坐标,给出了该图的方程式:

(x * x) / A * (B/A)

// this simplifies down to:
(B * x * x) / (A * A)

// which i am the equating to the line's equation
(B * x * x) / (A * A) =  m * x + b

// i run this through wolfram alpha (because i have no idea what i'm doing) and get:
(A * A * m - A * Math.sqrt(A * A * m * m + 4 * b * B)) / (2 * B)

这是一个正确的答案,但我想要第二种可能的变化。 我已经设法通过在计算之前将 m 乘以 -1 并对最后一次计算返回的 x 值执行相同的操作来纠正此问题,但这感觉像是一个 hack。

解决方案:

 public static function intersectsSegment(targetX:Number, targetY:Number, startX:Number, startY:Number, endX:Number, endY:Number):Point {
  // slope of the line
  var m:Number = (endY - startY) / (endX - startX);

  // where the line intersects the y-axis
  var b:Number = startY - startX * m;

  // solve the two variatons of the equation, we may need both
  var ix1:Number = solve(targetX, targetY, m, b);
  var ix2:Number = solveInverse(targetX, targetY, m, b);

  var intersection1:Point;
  var intersection2:Point;

  // if the intersection is outside the line segment startX/endX it's discarded
  if (ix1 > startX && ix1 < endX) intersection1 = new Point(ix1, plot(ix1, targetX, targetY));
  if (ix2 > startX && ix2 < endX) intersection2 = new Point(ix2, plot(ix2, targetX, targetY));

  // somewhat fiddly code to return the smallest set intersection
  if (intersection1 && intersection2) {
   // return the intersection with the smaller x value
   return intersection1.x < intersection2.x ? intersection1 : intersection2;
  } else if (intersection1) {
   return intersection1;
  }

  // this effectively means that we return intersection2 or if that's unset, null
  return intersection2;
 }

 private static function solve(A:Number, B:Number, m:Number, b:Number):Number {
  return (m + Math.sqrt(4 * (B / (A * A)) * b + m * m)) / (2 * (B / (A * A)));
 }

 private static function solveInverse(A:Number, B:Number, m:Number, b:Number):Number {
  return (m - Math.sqrt(4 * (B / (A * A)) * b + m * m)) / (2 * (B / (A * A)));
 }

 public static function plot(x:Number, targetX:Number, targetY:Number):Number{
  return (targetY * x * x) / (targetX * targetX);
 }

I have an equation for a parabolic curve intersecting a specified point, in my case where the user clicked on a graph.

 // this would typically be mouse coords on the graph
 var _target:Point = new Point(100, 50);

 public static function plot(x:Number, target:Point):Number{
  return (x * x) / target.x * (target.y / target.x);
 }

This gives a graph such as this:

parabolic curve

I also have a series of line segments defined by start and end coordinates:

startX:Number, startY:Number, endX:Number, endY:Number

I need to find if and where this curve intersects these segments (A):

alt text

If it's any help, startX is always < endX

I get the feeling there's a fairly straight forward way to do this, but I don't really know what to search for, nor am I very well versed in "proper" math, so actual code examples would be very much appreciated.

UPDATE:

I've got the intersection working, but my solution gives me the coordinate for the wrong side of the y-axis.

Replacing my target coords with A and B respectively, gives this equation for the plot:

(x * x) / A * (B/A)

// this simplifies down to:
(B * x * x) / (A * A)

// which i am the equating to the line's equation
(B * x * x) / (A * A) =  m * x + b

// i run this through wolfram alpha (because i have no idea what i'm doing) and get:
(A * A * m - A * Math.sqrt(A * A * m * m + 4 * b * B)) / (2 * B)

This is a correct answer, but I want the second possible variation.
I've managed to correct this by multiplying m with -1 before the calculation and doing the same with the x value the last calculation returns, but that feels like a hack.

SOLUTION:

 public static function intersectsSegment(targetX:Number, targetY:Number, startX:Number, startY:Number, endX:Number, endY:Number):Point {
  // slope of the line
  var m:Number = (endY - startY) / (endX - startX);

  // where the line intersects the y-axis
  var b:Number = startY - startX * m;

  // solve the two variatons of the equation, we may need both
  var ix1:Number = solve(targetX, targetY, m, b);
  var ix2:Number = solveInverse(targetX, targetY, m, b);

  var intersection1:Point;
  var intersection2:Point;

  // if the intersection is outside the line segment startX/endX it's discarded
  if (ix1 > startX && ix1 < endX) intersection1 = new Point(ix1, plot(ix1, targetX, targetY));
  if (ix2 > startX && ix2 < endX) intersection2 = new Point(ix2, plot(ix2, targetX, targetY));

  // somewhat fiddly code to return the smallest set intersection
  if (intersection1 && intersection2) {
   // return the intersection with the smaller x value
   return intersection1.x < intersection2.x ? intersection1 : intersection2;
  } else if (intersection1) {
   return intersection1;
  }

  // this effectively means that we return intersection2 or if that's unset, null
  return intersection2;
 }

 private static function solve(A:Number, B:Number, m:Number, b:Number):Number {
  return (m + Math.sqrt(4 * (B / (A * A)) * b + m * m)) / (2 * (B / (A * A)));
 }

 private static function solveInverse(A:Number, B:Number, m:Number, b:Number):Number {
  return (m - Math.sqrt(4 * (B / (A * A)) * b + m * m)) / (2 * (B / (A * A)));
 }

 public static function plot(x:Number, targetX:Number, targetY:Number):Number{
  return (targetY * x * x) / (targetX * targetX);
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天气好吗我好吗 2024-09-23 12:26:52

或者,更明确一点。

如果你的抛物线是
<代码>
y(x)= A x2+ B x + C (Eq 1)

并且您的行是
<代码>
y(x) = mx + b (方程 2)

x 的两个可能的解决方案(+ 和 -)是

x = ((-B + m +- Sqrt[4 A b + B^2 - 4 A C - 2 B m + m^2])/(2 A))   (Eq 3)

您应该检查您的线段端点(x 中)是否包含这两个点中的任何一个。如果是这样,只需替换 y=mx + b 方程中相应的 x 即可得到交点的 y 坐标

Edit>

要得到最后一个方程,您只需说方程 1 中的“y”等于方程 2 中的“y”(因为您正在寻找交集!)。
这给你:


A x2+ B x + C = mx + b

并重新分组


A x2+ (Bm) x + (Cb) = 0

这是一个二次方程。

方程 3 只是该二次方程的两个可能的解。

编辑2>

重新阅读你的代码,似乎你的抛物线是由
<代码>
y(x) = A x2

哪里
<代码>
A = (target.y / (target.x)2)

所以在你的情况下,方程 3 就变成了

 x = ((m +- Sqrt[4 A b + m^2])/(2 A))   (Eq 3b)  

HTH!

Or, more explicit yet.

If your parabolic curve is

y(x)= A x2+ B x + C (Eq 1)

and your line is

y(x) = m x + b (Eq 2)

The two possible solutions (+ and -) for x are

x = ((-B + m +- Sqrt[4 A b + B^2 - 4 A C - 2 B m + m^2])/(2 A))   (Eq 3)

You should check if your segment endpoints (in x) contains any of these two points. If they do, just replace the corresponding x in the y=m x + b equation to get the y coordinate for the intersection

Edit>

To get the last equation you just say that the "y" in eq 1 is equal to the "y" in eq 2 (because you are looking for an intersection!).
That gives you:


A x2+ B x + C = m x + b

and regrouping


A x2+ (B-m) x + (C-b) = 0

Which is a quadratic equation.

Equation 3 are just the two possible solutions for this quadratic.

Edit 2>

re-reading your code, it seems that your parabola is defined by

y(x) = A x2

where

A = (target.y / (target.x)2)

So in your case Eq 3 becomes simply

 x = ((m +- Sqrt[4 A b + m^2])/(2 A))   (Eq 3b)  

HTH!

っ左 2024-09-23 12:26:52

求出曲​​线方程并将直线代入 y = mx +b 形式。求解 x,然后确定 X 是否位于线段的起点和终点之间。

查看:http://mathcentral.uregina.ca/QQ/database /QQ.09.03/senthill1.html

Take the equation for the curve and put your line into y = mx +b form. Solve for x and then determine if X is between your your start and end points for you line segment.

Check out: http://mathcentral.uregina.ca/QQ/database/QQ.09.03/senthil1.html

梦回梦里 2024-09-23 12:26:52

您是否经常这样做,以至于希望在实际计算交点之前进行单独的测试以查看是否存在交点?如果是这样,请考虑这样一个事实:抛物线是函数 f(x, y) = y - (B * x * x) / (A * A) 的水平集——具体来说,就是 f(x, y) = 0。将两个端点代入 f(x,y) - 如果它们具有相同的符号,则它们位于抛物线的同一侧,而如果它们具有不同的符号,则它们位于抛物线的不同侧抛物线。

现在,您仍然可能有一个与抛物线相交两次的线段,而这个测试没有捕获到这一点。但是您定义问题的方式让我觉得这可能适合您的应用程序。

Are you doing this often enough to desire a separate test to see if an intersection exists before actually computing the intersection point? If so, consider the fact that your parabola is a level set for the function f(x, y) = y - (B * x * x) / (A * A) -- specifically, the one for which f(x, y) = 0. Plug your two endpoints into f(x,y) -- if they have the same sign, they're on the same side of the parabola, while if they have different signs, they're on different sides of the parabola.

Now, you still might have a segment that intersects the parabola twice, and this test doesn't catch that. But something about the way you're defining the problem makes me feel that maybe that's OK for your application.

橘和柠 2024-09-23 12:26:52

换句话说,您需要计算每个线段的方程 y = Ax + B 将其与曲线方程 y = Cx^2 + Dx + E 进行比较,因此 Ax + B - Cx^2 - Dx - E = 0 并查看 startXendX 值之间是否存在解决方案。

In other words, you need to calulate the equation for each line segment y = Ax + B compare it to curve equation y = Cx^2 + Dx + E so Ax + B - Cx^2 - Dx - E = 0 and see if there is a solution between startX and endX values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文