在Excel图中寻找交点

时间:2013-11-19 22:46:16

标签: excel intersection scatter-plot

我有一个实验获得的值的散点图和一条x = y的线,我希望找到趋势线和x = y之间的所有交点,是否有方法/函数这样做?

没有等式可以很好地近似趋势线来代数求解。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我认为删除唯一的答案是一个差劲的举动,尽管我觉得实际工作表中的解释会更好,但是从工作簿中获取代码还是可以的。

代码来自这里:

http://andypope.info/charts/intersection.htm

'
' Algebra taken from various sources on the WWW
'
Option Explicit
Public Function IntersectComplex(x1 As Double, y1 As Double, x2 As Double, y2 As Double, LineCoordinates As Range, Axis As Boolean) As Variant
'
' Complex Intersect.
' Because the line segments are not uniformly spaced the (xy,y1)(x2,y2) could cross
' at any point along the other line
'
' Return
' If intersection
'    requested coordinate
' else
'    nothing
' endif
' Axis=True returns X value
' Axis=False returns Y value
'
    Dim dblCrossX As Double
    Dim dblCrossY As Double
    Dim dblTestx1 As Double
    Dim dblTesty1 As Double
    Dim dblTestx2 As Double
    Dim dblTesty2 As Double
    Dim intSegment As Integer

    With LineCoordinates
        For intSegment = 1 To .Rows.Count - 1
            dblTestx1 = .Cells(intSegment, 1)
            dblTesty1 = .Cells(intSegment, 2)
            dblTestx2 = .Cells(intSegment + 1, 1)
            dblTesty2 = .Cells(intSegment + 1, 2)
            If m_CalculateIntersection(x1, y1, x2, y2, dblTestx1, dblTesty1, dblTestx2, dblTesty2, dblCrossX, dblCrossY) Then
                If Axis Then
                    IntersectComplex = dblCrossX
                Else
                    IntersectComplex = dblCrossY
                End If
                Exit Function
            End If
        Next

        ' Special check for last pairing
        intSegment = .Rows.Count
        dblTestx1 = .Cells(intSegment, 1)
        dblTesty1 = .Cells(intSegment, 2)
        dblTestx2 = .Cells(intSegment, 1)
        dblTesty2 = .Cells(intSegment, 2)
        If m_CalculateIntersection(x1, y1, x2, y2, dblTestx1, dblTesty1, dblTestx2, dblTesty2, dblCrossX, dblCrossY) Then
            If Axis Then
                IntersectComplex = dblCrossX
            Else
                IntersectComplex = dblCrossY
            End If
            Exit Function
        End If

    End With
    IntersectComplex = CVErr(xlErrNA)    ' Null

End Function
Private Function m_CalculateIntersection(x1 As Double, y1 As Double, x2 As Double, y2 As Double, _
    x3 As Double, y3 As Double, x4 As Double, y4 As Double, _
    ByRef CrossX As Double, ByRef CrossY As Double) As Variant

'Call with x1,y1,x2,y2,x3,y3,x4,y4 and returns intersect,x,y
'
'Where:
' x1,y1,x2,y2,x3,y3,x4,y4 are the end points of two line segments
'Returns:
' intersect is true/false, and x,y is the interecting point if intersect is true
'
'Description:
'
'Equations for the lines are:
' Pa = P1 + Ua(P2 - P1)
' Pb = P3 + Ub(P4 - P3)
'
'Solving for the point where Pa = Pb gives the following equations for ua and ub
'
' Ua = ((x4 - x3) * (y1 - y3) - (y4 - y3 ) * (x1 - x3)) / ((y4 - y3) * (x2 - x1)
'     - (x4 - x3) * (y2 - y1))
' Ub = ((x2 - x1) * (y1 - y3) - (y2 - y1 ) * (x1 - x3)) / ((y4 - y3) * (x2 - x1)
'     - (x4 - x3) * (y2 - y1))
'
'Substituting either of these into the corresponding equation for the line gives
'     the intersection point.
'For example the intersection point (x,y) is
' x = x1 + Ua(x2 - x1)
' y = y1 + Ua(y2 - y1)
'
'Notes:
' - The denominators are the same.
'
' - If the denominator above is 0 then the two lines are parallel.
'
' - If the denominator and numerator are 0 then the two lines are coincident.
'
' - The equations above apply to lines,
'     if the intersection of line segments is
'     required then it is only necessary to test if ua and ub lie between 0 and 1.
'     Whichever one lies within that range then the corresponding line segment
'     contains the intersection point. If both lie within the range of 0 to 1 then
'     the intersection point is within both line segments.
'
    Dim dblDenominator As Double
    Dim dblUa As Double
    Dim dblUb As Double
    'Pre calc the denominator, if zero then
    '     both lines are parallel and there is no
    '     intersection
    dblDenominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))

    If dblDenominator <> 0 Then
        'Solve for the simultaneous equations
        dblUa = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / dblDenominator
        dblUb = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / dblDenominator
    Else

        If (x1 = x3) And (y1 = y3) Then
            CrossX = x1
            CrossY = y1
            m_CalculateIntersection = True
        Else
            m_CalculateIntersection = False
        End If
        Exit Function
    End If

    'Could the lines intersect?
    If dblUa >= 0 And dblUa <= 1 And dblUb >= 0 And dblUb <= 1 Then
        'Calculate the intersection point
        CrossX = x1 + dblUa * (x2 - x1)
        CrossY = y1 + dblUa * (y2 - y1)
        'Yes, they do
        m_CalculateIntersection = True
    Else
        'No, they do not
        m_CalculateIntersection = False
    End If

End Function