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


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

    参考自 

    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
     
  • 相关阅读:
    PHP输出日志,json美化
    php获取项目路径
    16进制颜色,正则
    doctrine/instantiator
    cn.archive.ubuntu.com 慢的问题
    yzalis/identicon 像素头像
    Shell 判断进程是否存在
    shell 2>&1
    shell 判断是否继续
    shell
  • 原文地址:https://www.cnblogs.com/clemente/p/11260214.html
Copyright © 2020-2023  润新知