zoukankan      html  css  js  c++  java
  • 怎样判断一个点在多边形内

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

    参考自 

    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
     
  • 相关阅读:
    (转)性能测试---并发用户理解
    (转)基于DDD的现代ASP.NET开发框架--ABP分层架构
    (转)Web自动化测试中的接口测试
    (转) 一致性Hash算法在Memcached中的应用
    Memcached工作原理及常见问题
    Memcached介绍及相关知识
    .net 面试题总结
    使用IDEA工具配置和运行vue项目(详细其中的坑)
    关于伪分布zookeeper集群启动出错(Error contacting service. It is probably not running.)
    常用查找和排序
  • 原文地址:https://www.cnblogs.com/clemente/p/11260214.html
Copyright © 2011-2022 走看看