哪些点是共线的&顺序(即我介于两点之间)

时间:2013-09-19 03:38:01

标签: vb.net geolocation gps

我有我的位置的经度和纬度,我有一个位置列表,按照道路上的点(长/纬)列表排序。我怎么知道我介于哪两点?

如果我只搜索两个最近的点,我将在图片中以P2和P3结束。 我想知道如何发现我在点p1和p2之间。

我将搜索的点列表将是包含纬度和经度的数据库行,因此指向如何构建sql-query,linq-query或伪代码的指针,欢迎指向最佳解决方案的所有内容。我是地理定位的新手和围绕它的数学所以把我当成新手。 ;)

(点数列表将被订购,因此P1的id为1,p2的id为2,依此类推。)

enter image description here

2 个答案:

答案 0 :(得分:1)

请记住,您提出的建议可能会变得非常复杂(在相同条件下的许多点)并因此提供准确的算法将需要(更多)更多的工作。照顾更简单的情况(如图中的情况)并不困难;你必须包括以下内容:

  • 将纬度/经度值转换为笛卡尔坐标(为了便于计算;尽管您甚至可以跳过此步骤)。在this link,你可以在这方面得到一些启发;它在C#中,但无论如何都是清晰的。

  • 通过“夫妇”迭代所有可用点,并检查要分析的点(Mypos)是否落入由它们形成的线中间位置。如下面的代码所示,这个计算非常简单,因此您不需要进行任何预过滤(之前寻找更接近的点)。

Dim point1() As Double = New Double() {0, 0} 'x,y
Dim point2() As Double = New Double() {0, 3}
Dim pointToCheck() As Double = New Double() {0.05, 2}

Dim similarityRatio As Double = 0.9
Dim minValSimilarDistance As Double = 0.001
Dim similarityDistance As Double = 0.5

Dim eq1 As Double = (point2(0) - point1(0)) * (pointToCheck(1) - point1(1))
Dim eq2 As Double = (point2(1) - point1(1)) * (pointToCheck(0) - point1(0))
Dim maxVal As Double = eq1
If (eq2 > eq1) Then maxVal = eq2

Dim inLine = False
Dim isInBetween As Boolean = False

If (eq1 = eq2 OrElse (maxVal > 0 AndAlso Math.Abs(eq1 - eq2) / maxVal <= (1 - similarityRatio))) Then
    inLine = True
ElseIf (eq1 <= minValSimilarDistance AndAlso eq2 <= similarityDistance) Then
    inLine = True
ElseIf (eq2 <= minValSimilarDistance AndAlso eq1 <= similarityDistance) Then
    inLine = True
End If

If (inLine) Then
    'pointToCheck part of the line formed by point1 and point2, but not necessarily between them
    Dim insideX As Boolean = False
    If (pointToCheck(0) >= point1(0) AndAlso pointToCheck(0) <= point2(0)) Then
        insideX = True
    Else If (pointToCheck(0) >= point2(0) AndAlso pointToCheck(0) <= point1(0)) Then
        insideX = True
    End If
    if(insideX) Then
        If (pointToCheck(1) >= point1(1) AndAlso pointToCheck(1) <= point2(1)) Then
            isInBetween = True
        ElseIf (pointToCheck(1) >= point2(1) AndAlso pointToCheck(1) <= point1(1)) Then
            isInBetween = True
        End If
    End If
End If

If (isInBetween) Then
    'pointToCheck is between point1 and point2
End If

正如你所看到的,我已经包含了各种比率,允许你调整确切的条件(这些点很可能不会完全落在线上)。 similarityRatio说明“方程式”或多或少相似(也就是说,X和Y值不完全适合在线内但足够接近)。 similarityRatio无法正确处理涉及零的案例(例如,相同的X或Y),这是minValSimilarDistancesimilarityDistance的用途。您可以调整这些值或仅重新定义比率(相对于点之间的X / Y变化,而不是相对于“方程式”)。

答案 1 :(得分:0)

为了清晰起见,Scala中的等效解决方案:

def colinearAndInOrder(a: Point, b: Point, c: Point) = {

  lazy val colinear: Boolean =
    math.abs((a.lng - b.lng) * (a.lat - c.lat) - 
      (a.lng - c.lng) * (a.lat - b.lat)) <= 1e-9

  lazy val bounded: Boolean =
    ((a.lat < b.lat && b.lat < c.lat) || (a.lat > b.lat && b.lat > c.lat)) &&
      ((a.lng < b.lng && b.lng < c.lng) || (a.lng > b.lng && b.lng > c.lng))

  close(a,b) || close(b,c) || (colinear && bounded)
}

def close(a: Point, b: Point): Boolean = {
  math.abs(a.lat - b.lng) <= 1e-4 && math.abs(a.lat - b.lng) <= 1e-4
}