2010-08-31 97 views
4

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

// 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 

我需要找到如果和这条曲线相交这些段(A):

alt text

如果它的任何帮助,startX总是< endX

我感觉有一个相当简单的方式来做到这一点,但我真的不知道该怎么寻找,我也不是非常好精通“正确的”数学,所以真正的代码示例将非常值得赞赏。

UPDATE:

我有交集的工作,但我的解决方案给我的坐标y轴的反面。

更换我分别用A和B的目标COORDS,给出了这个方程的情节:

(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值进行相同的操作来纠正此问题,但那感觉像是一种黑客攻击。

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); 
} 
+0

Yor解决方案与我的解决方案相同。我认为你应该采取积极的选择(+ A * Math.sqrt)而不是( - A * Math.sqrt),并让其他方法保持不变///二次方程式。有两种解决方案...只需选择其他解决方案 – 2010-08-31 15:10:41

+1

注意////您的(B /(A * A))=我的A – 2010-08-31 15:16:35

+0

+1发布解决方案 – 2010-08-31 22:49:45

回答

6

或者,更明确了。

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

和您的线路是 y(x) = m x + b (Eq 2)

两个可能的解决方案(+和 - )为X的

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

你应该检查你的段端点(在x中)包含这两点中的任何一点。如果他们这样做,只需更换相应的X在y = mx + b中方程得到y坐标相交

编辑>

为了得到最后的等式,你刚才说的“Y”在等式1中等于等式2中的“y”(因为你正在寻找一个交点!)。 这就给了你:

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

和重组

A x2+ (B-m) x + (C-b) = 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!

+0

我不明白你如何从曲线/线的函数移动到最后一个方程,常量(4/2)从哪里来? – grapefrukt 2010-08-31 13:08:14

+0

@grapefrukt查看编辑 – 2010-08-31 13:17:22

+0

我已经更新了我的问题了一下! – grapefrukt 2010-08-31 15:01:48

0

换句话说,你需要calulate公式为每个线段y = Ax + B把它比作曲线方程y = Cx^2 + Dx + E所以Ax + B - Cx^2 - Dx - E = 0,看看是否有startXendX值之间的解决方案。

3

取曲线的方程,并将你的直线放入y = mx + b形式。求解x,然后确定X是否在你的线段开始和结束点之间。

结账:http://mathcentral.uregina.ca/QQ/database/QQ.09.03/senthil1.html

+0

“解决x”几乎就是我遇到问题,我会很感激任何阐述! – grapefrukt 2010-08-31 13:46:11

+0

对!对不起使用笔和纸来解决X很容易,但使用电脑是另一回事。 所以我们想用矩阵来求解我们的线性方程组。这里是一个C#示例http://www.extremeoptimization.com/QuickStart/StructuredLinearEquationsCS.aspx 如果这样做没有帮助,还有其他几个使用矩阵求解线性方程的资源,但最终这就是你需要做的。 – Matthew 2010-08-31 14:37:47

+0

这里有一些更多的资源: http://www.daniweb.com/forums/thread263798.html和http://www.codeproject.com/KB/recipes/matrixoperations.aspx 让我知道如果你需要更多帮助:) – Matthew 2010-08-31 14:39:21

3

你是否经常这样做,以至于在实际计算交叉点之前需要单独测试以查看交叉点是否存在?如果是这样,考虑一个事实,即抛物线是为函数f(x,y)= y - (B * x * x)/(A * A)设定的一个水平 - 具体地说,就是f(x, y)= 0.将两个端点插入f(x,y) - 如果它们具有相同的符号,则它们位于抛物线的同一侧,而如果它们具有不同的符号,则它们位于抛物线。

现在,您仍然可能会有一段与抛物线相交两次,并且此测试未捕获该段。但是,有关您定义问题的方式会让我觉得这对您的应用程序可能没有问题。

+0

这将是我的下一步行动,但事实证明,这足够快速完成全面检查。我使用它来检查之前生成的样条线段,我可以在大约30ms内针对3k样条线上的所有80k段运行。我和一个在十五行代码上花费六个小时的人一样快乐! ;) – grapefrukt 2010-08-31 20:15:24

+0

+1这非常聪明! – 2010-09-01 02:37:13