怎样判断一个点在多边形内

毕业论文需要用到的一个点

参考自 

https://solos.im/2015/3/27/%E6%80%8E%E6%A0%B7%E5%88%A4%E6%96%AD%E4%B8%80%E4%B8%AA%E7%82%B9%E5%9C%A8%E5%A4%9A%E8%BE%B9%E5%BD%A2%E5%86%85/

 

缘起

最近头脑发热,突然想研究下怎么判断一个坐标点是否在一个多边形内,这个问题解决之后就可以根据一个坐标点计算出这个点所在的行政区划。

算法

从网上找了一下,发现了一个很巧妙的算法,算法如下:

  • 把整个平面分为两个部分(x>0&&y==0||y>0部分和x<0&&y==0||y<0部分)
  • 顺序扫描多边形每一个顶点,当某个顶点和前一个顶点处于不同部分时,判断一下从前一个点到该点的方向相对于原点是顺时针还是逆时针(用叉积判断),如果是顺时针r++,否则r--(r初始为0)
  • 如果结果r==2||r==-2,则原点在该多边形内部,否则不是。

python实现

def is_point_in(x, y, points):
    count = 0
    x1, y1 = points[0]
    x1_part = (y1 > y) or ((x1 - x > 0) and (y1 == y)) # x1在哪一部分中
    x2, y2 = '', ''  # points[1]
    points.append((x1, y1))
    for point in points[1:]:
        x2, y2 = point
        x2_part = (y2 > y) or ((x2 > x) and (y2 == y)) # x2在哪一部分中
        if x2_part == x1_part:
            x1, y1 = x2, y2
            continue
        mul = (x1 - x)*(y2 - y) - (x2 - x)*(y1 - y)
        if mul > 0:  # 叉积大于0 逆时针
            count += 1
        elif mul < 0:
            count -= 1
        x1, y1 = x2, y2
        x1_part = x2_part
    if count == 2 or count == -2:
        return True
    else:
        return False


if __name__ == '__main__':
    points = [[117.1510864068032,40.0705150448258],[117.2866776871509,40.10934259697606], ... ]
    y = 39.99
    x = 116.468006
    for i in xrange(10000):
        is_point_in(x + i * 0.01, y + i * 0.01, points)

运行时间
time python point.py

real    0m8.746s
user    0m8.680s
sys 0m0.034s

执行了10,000次,耗时8.746秒,太慢了有木有, 改成go试试

 

package main

import (
    //"fmt"
)


func is_point_in(x float64, y float64, points [][]float64) bool {
    count := 0
    x1, y1 := points[0][0], points[0][1]
    x1_part := (y1 > y) || ((x1 - x > 0) && (y1 == y))
    var a = []float64{x1, y1}
    p := append(points, a)
    for i := range p {
        if (i == 0) {
            continue
        }
        point := p[i]
        x2, y2 := point[0], point[1]
        x2_part := (y2 > y) || ((x2 > x) && (y2 == y))
        if (x2_part == x1_part){
            x1, y1 = x2, y2
            continue
        }
        mul := (x1 - x)*(y2 - y) - (x2 - x)*(y1 - y)
        if mul > 0 {
            count += 1
        } else {
            if( mul < 0) {
                count -= 1
            }
        }
        x1, y1 = x2, y2
        x1_part = x2_part
    }

    if (count == 2 || count == -2){
        return true
    } else {
        return false
    }
}

func main() {
    points := [][]float64{{117.1510864068032,40.0705150448258},{117.2866776871509,40.10934259697606}, ... ,}
    y := 39.99
    x := 116.468006
    for i:=1; i < 10000; i++ {
        _ = is_point_in(x + float64(i)*0.01, y + float64(i) * 0.01, points)
    }
}

执行时间:

go build point.go
time ./point

real    0m0.038s
user    0m0.035s
sys 0m0.005s

 

 
posted @ 2019-07-28 17:51  clemente  阅读(902)  评论(0编辑  收藏  举报