• 电子围栏


     1、找了个电子围栏算法,也就是多边形找点,在图形内还是图形外

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import json
    import math
    lnglatlist = []
    data = '[{"name":"武汉市三环","points":[{"lng":114.193437,"lat":30.513069},{"lng":114.183376,"lat":30.509211},{"lng":114.188191,"lat":30.505291},{"lng":114.187975,"lat":30.504731},{"lng":114.201773,"lat":30.492782},{"lng":114.213559,"lat":30.48855},{"lng":114.239143,"lat":30.484006},{"lng":114.248341,"lat":30.470062},{"lng":114.267888,"lat":30.470062},{"lng":114.286286,"lat":30.46309},{"lng":114.294335,"lat":30.459105},{"lng":114.298934,"lat":30.459105},{"lng":114.305833,"lat":30.459105},{"lng":114.341478,"lat":30.453128},{"lng":114.422613,"lat":30.462591},{"lng":114.424337,"lat":30.453688},{"lng":114.444316,"lat":30.456303},{"lng":114.466809,"lat":30.466078},{"lng":114.473708,"lat":30.549713},{"lng":114.443813,"lat":30.624326},{"lng":114.407593,"lat":30.683478},{"lng":114.388621,"lat":30.703352},{"lng":114.3616,"lat":30.704843},{"lng":114.311582,"lat":30.678466999999998},{"lng":114.241442,"lat":30.64123},{"lng":114.201773,"lat":30.63079},{"lng":114.182226,"lat":30.63427},{"lng":114.165553,"lat":30.626812},{"lng":114.162679,"lat":30.6109},{"lng":114.170153,"lat":30.59598},{"lng":114.167853,"lat":30.552201},{"lng":114.179351,"lat":30.529309}],"type":0}]'
    data = json.loads(data)
    if 'points' in data[0]:
        for point in data[0]['points']:
            #print(str(point['lng'])+" "+str(point['lat']))
            lnglat = []
            lnglat.append(float(str(point['lng'])))
            lnglat.append(float(str(point['lat'])))
            lnglatlist.append(lnglat)
    
    def windingNumber(point, poly):
        poly.append(poly[0])
        px = point[0]
        py = point[1]
        sum = 0
        length = len(poly)-1
    
        for index in range(0,length):
            sx = poly[index][0]
            sy = poly[index][1]
            tx = poly[index+1][0]
            ty = poly[index+1][1]
    
            #点与多边形顶点重合或在多边形的边上
            if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):
                return "on"
            #点与相邻顶点连线的夹角
            angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)
    
            #确保夹角不超出取值范围(-π 到 π)
            if(angle >= math.pi):
                angle = angle - math.pi * 2
            elif(angle <= -math.pi):
                angle = angle + math.pi * 2
            sum += angle
    
            #计算回转数并判断点和多边形的几何关系
        result = 'out' if int(sum / math.pi) == 0 else 'in'
        return result
    
    point = [114.193437,30.513068]
    print(windingNumber(point,lnglatlist))

    转自

    http://blog.51cto.com/yixianwei/2089075

    2、我的项目json文件比较复杂,需要用个二维数据来存储坐标数据

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import json
    import math
    
    def windingNumber(point, poly):
        poly.append(poly[0])
        px = point[0]
        py = point[1]
        sum = 0
        length = len(poly)-1
    
        for index in range(0,length):
            sx = poly[index][0]
            sy = poly[index][1]
            tx = poly[index+1][0]
            ty = poly[index+1][1]
    
            #点与多边形顶点重合或在多边形的边上
            if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):
                return "on"
            #点与相邻顶点连线的夹角
            angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)
    
            #确保夹角不超出取值范围(-π 到 π)
            if(angle >= math.pi):
                angle = angle - math.pi * 2
            elif(angle <= -math.pi):
                angle = angle + math.pi * 2
            sum += angle
    
            #计算回转数并判断点和多边形的几何关系
        result = 'out' if int(sum / math.pi) == 0 else 'in'
        return result
    
    
    if __name__ == "__main__":
    
        with open("railwayFence.json", 'r') as f:
            data = json.loads(f.read())
            data = data['railwayFence']
            #print(len(data))
            #print(data[65]['areaName'])
    
        lnglatlist = [[]]*len(data)
        point_test = [115.259161584,38.813623816]
        point_test1 = [115.243922249,38.836012517]
    
        for i in range(0,len(data)):
            for point in data[i]['coordinates']:
                #print(str(point['L'])+" "+str(point['B']))
                lnglat = []
                lnglat.append(float(str(point['L'])))
                lnglat.append(float(str(point['B'])))
                lnglatlist[i].append(lnglat)
            ret = windingNumber(point_test1,lnglatlist[i])
    
            if ret == 'in' or ret == 'on':
                break
             
        print ret
    
        

    3、解析出json中的坐标点,可以描出电子围栏,打点测试就很方便了

    test.txt

    截取几个点,格式如下

    38.836013 115.243822
    38.836012 115.243818
    38.836013 115.243813
    38.836013 115.243809
    38.836015 115.243805
    38.836017 115.243801
    38.836019 115.243898
    38.836022 115.243895
    38.836023 115.243895
    38.836092 115.243850
    38.836160 115.243806
    38.836189 115.243788
    38.836218 115.243769
    38.836416 115.243642
    38.836613 115.243515
    38.837036 115.243243

    plot.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import matplotlib.pyplot as plt
    import numpy as np
    import json
    
    with open("railwayFence.json", 'r') as f:
        data = json.loads(f.read())
        data = data['railwayFence']
        fo = open("tmp", "w")
        for i in range(0,len(data)):
            for point in data[i]['coordinates']:
                d = '%(x).9f %(y).9f
    '%{'x':float(str(point['B'])),'y':float(str(point['L']))}
                fo.write( d ) 
        fo.close()
    
    data = np.loadtxt('tmp')
    plt.plot(data[:,0],data[:,1])
    
    #plt.annotate('test point', xy=(39.82775139,116.250658818),arrowprops=dict(facecolor='red', shrink=0))
    #plt.annotate('test point', xy=(39.823400546,116.25345992),arrowprops=dict(facecolor='red', shrink=0))
    plt.annotate('test point', xy=(39.813623816,116.259161584),arrowprops=dict(facecolor='red', shrink=0))
    plt.show()

    python plot.py

    4、计算单个围栏

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import json
    import math
    lnglatlist = []
    
    with open("65.json", 'r') as f:
        data = json.loads(f.read())
        #print(data)
        print(data['areaName'])
    
    #data = json.loads(data)
    if 'coordinates' in data:
        for point in data['coordinates']:
            #print(str(point['L'])+" "+str(point['B']))
            lnglat = []
            lnglat.append(float(str(point['L'])))
            lnglat.append(float(str(point['B'])))
            lnglatlist.append(lnglat)
    
    def windingNumber(point, poly):
        poly.append(poly[0])
        px = point[0]
        py = point[1]
        sum = 0
        length = len(poly)-1
    
        for index in range(0,length):
            sx = poly[index][0]
            sy = poly[index][1]
            tx = poly[index+1][0]
            ty = poly[index+1][1]
    
            #点与多边形顶点重合或在多边形的边上
            if((sx - px) * (px - tx) >= 0 and (sy - py) * (py - ty) >= 0 and (px - sx) * (ty - sy) == (py - sy) * (tx - sx)):
                return "on"
            #点与相邻顶点连线的夹角
            angle = math.atan2(sy - py, sx - px) - math.atan2(ty - py, tx - px)
    
            #确保夹角不超出取值范围(-π 到 π)
            if(angle >= math.pi):
                angle = angle - math.pi * 2
            elif(angle <= -math.pi):
                angle = angle + math.pi * 2
            sum += angle
    
            #计算回转数并判断点和多边形的几何关系
        result = 'out' if int(sum / math.pi) == 0 else 'in'
        return result
    
    point = [115.259161584,38.813623816]
    print(windingNumber(point,lnglatlist))

    5、展示单个围栏

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import matplotlib.pyplot as plt
    import numpy as np
    import json
    
    '''
    with open("railwayFence.json", 'r') as f:
        data = json.loads(f.read())
        data = data['railwayFence']
        fo = open("tmp", "w")
        for i in range(0,len(data)):
            for point in data[i]['coordinates']:
                d = '%(x).9f %(y).9f
    '%{'x':float(str(point['B'])),'y':float(str(point['L']))}
                fo.write( d ) 
        fo.close()
    '''
    
    data = np.loadtxt('65.txt')
    plt.plot(data[:,0],data[:,1])
    
    #plt.annotate('test point', xy=(38.82775139,115.250658818),arrowprops=dict(facecolor='red', shrink=0))
    #plt.annotate('test point', xy=(38.823400546,115.25345992),arrowprops=dict(facecolor='red', shrink=0))
    plt.annotate('test point', xy=(38.813623816,115.259161584),arrowprops=dict(facecolor='red', shrink=0))
    plt.show()

    6、用c语言解析json也行

    main.c

    /*
            reference documentation
            https://blog.csdn.net/stsahana/article/details/79638992
            https://blog.csdn.net/fengxinlinux/article/details/53121287
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
    #include "cJSON.h"
    
    char *json_file_path = "./railwayFence.json";
    
    char *json_loader(char *path)
    {
      FILE *f;
      long len;
      char *content;
      f=fopen(path,"rb");
      fseek(f,0,SEEK_END);
      len=ftell(f);
      fseek(f,0,SEEK_SET);
      content=(char*)malloc(len+1);
      fread(content,1,len,f);
      fclose(f);
      return content;
    }
    
    int main(void)
    {
        FILE *fp1;
        fp1=fopen("test.txt","w+");
    
        char *json_str = json_loader(json_file_path);
    
            cJSON *root=cJSON_Parse(json_str);
            if (!root) {
                printf("Error before: [%s]
    ",cJSON_GetErrorPtr());
            }
    
            //railwayFence array
            cJSON *railwayFenceArray = cJSON_GetObjectItem(root, "railwayFence");  
            if(!railwayFenceArray){  
                printf("Error before: [%s]
    ",cJSON_GetErrorPtr()); 
            }
            int railwayFence_array_size = cJSON_GetArraySize(railwayFenceArray);  
            printf("railwayFence array size is %d
    ",railwayFence_array_size);
            int i = 0;
            char *p  = NULL; 
            cJSON *it; 
            for(i=0; i< railwayFence_array_size; i++) {  
                    FILE *fp;
                    char  buffer[32];
                    sprintf( buffer, "./data/%d.txt", i );
                    fp=fopen(buffer,"w+");
                cJSON *railwayFenceItem = cJSON_GetArrayItem(railwayFenceArray,i);
                p = cJSON_PrintUnformatted(railwayFenceItem);  
                it = cJSON_Parse(p); 
                if(!it)  
                continue ;
    
                cJSON *areaName,*dangerType;
                areaName = cJSON_GetObjectItem(it, "areaName");  
                printf("areaName is %s
    ",areaName->valuestring);  
                dangerType = cJSON_GetObjectItem(it, "dangerType");  
                printf("dangerType is %s
    ",dangerType->valuestring);
    
                //Coordinate array
                cJSON *CoordinateArray = cJSON_GetObjectItem(railwayFenceItem, "coordinates");  
                if(!CoordinateArray){  
                    printf("Error before: [%s]
    ",cJSON_GetErrorPtr()); 
                }
                int Coordinate_array_size = cJSON_GetArraySize(CoordinateArray);  
                printf("Coordinate array size is %d
    ",Coordinate_array_size);
                int j = 0;
                char *q  = NULL; 
                cJSON *jt;  
                for(j=0; j< Coordinate_array_size; j++) {
                    cJSON *CoordinateItem = cJSON_GetArrayItem(CoordinateArray,j);
                    q = cJSON_PrintUnformatted(CoordinateItem);  
                    jt = cJSON_Parse(q); 
                    if(!jt)  
                        continue ;
    
                    cJSON *B,*L;
                    B = cJSON_GetObjectItem(jt, "B");  
                    printf("B is %f
    ",B->valuedouble);  
                    L = cJSON_GetObjectItem(jt, "L");  
                    printf("L is %f
    ",L->valuedouble);
                    fprintf(fp1,"%f %f
    ",B->valuedouble,L->valuedouble);
                    fprintf(fp,"%f %f
    ",B->valuedouble,L->valuedouble);
                
                    free(q); cJSON_Delete(jt);                
                }
                free(p); cJSON_Delete(it);
            }
            if(root) { 
                cJSON_Delete(root);  
                    //return 0;  
            }
    
      return 0;
    }

    Makefile

    复制代码
    OBJ= main 
    all: ${OBJ}
    main:
        gcc -g -o main main.c cJSON.c -lm
    
    clean:
        rm -f ${OBJ}
    .PHONY: ${OBJ}
    复制代码

    7、nodejs解析json文件更简单

    main.js

    复制代码
    var fs = require("fs");
    var contents = fs.readFileSync("railwayFence.json");
    var obj = JSON.parse(contents);
    //console.log("<<<<<<<<<<<<<<<<<<<<"+JSON.stringify(obj));
    for(var i in obj.railwayFence){
        console.log('>>>>>>>>>>>>>>>>>>>>>>>>put areaName: ' + obj.railwayFence[i].areaName)
        console.log('>>>>>>>>>>>>>>>>>>>>>>>>put dangerTypeName: ' + obj.railwayFence[i].danggerTypeName)
        for(var j in obj.railwayFence[i].coordinates){
            console.log('>>>>>>>>>>>>>>>>>>>>>>>>put B: ' + obj.railwayFence[i].coordinates[j].B)
            console.log('>>>>>>>>>>>>>>>>>>>>>>>>put L: ' + obj.railwayFence[i].coordinates[j].L)            
        }
    }
    复制代码

    8、同事找的c算法,记录一下

    /**
     * 功能:判断点是否在多边形内
     * 方法:求解通过该点的水平线(射线)与多边形各边的交点
     * 结论:单边交点为奇数,成立!
     * 参数:p 指定的某个点
             ptPolygon 多边形的各个顶点坐标(首末点可以不一致) 
             nCount 多边形定点的个数
     * 说明:
     */
    // 注意:在有些情况下x值会计算错误,可把double类型改为long类型即可解决。
    int PtInPolygon(Point_t* p, Point_t* ptPolygon, int nCount) 
    { 
        int nCross = 0, i;
        double x;
        Point_t p1, p2;
        
        for (i = 0; i < nCount; i++) 
        { 
            p1 = ptPolygon[i]; 
            p2 = ptPolygon[(i + 1) % nCount];
            // 求解 y=p->y 与 p1p2 的交点
            if ( p1.y == p2.y ) // p1p2 与 y=p->y平行 
                continue;
            if ( p->y < min(p1.y, p2.y) ) // 交点在p1p2延长线上 
                continue; 
            if ( p->y >= max(p1.y, p2.y) ) // 交点在p1p2延长线上 
                continue;
            // 求交点的 X 坐标 -------------------------------------------------------------- 
            x = (double)(p->y - p1.y) * (double)(p2.x - p1.x) / (double)(p2.y - p1.y) + p1.x;
            if ( x > p->x ) 
            {
                nCross++; // 只统计单边交点 
            }
        }
        // 单边交点为偶数,点在多边形之外 --- 
        return (nCross % 2 == 1); 
    }
    
    /*******************************************************************************
     * 名称: pointInPolygon
     * 功能: 当前平面坐标点是否在区域面内
     * 形参: point:需判断点
     *      points:区域面点集合
     *      count:区域面点个数
     * 返回: 判断结果 1在区域内 0在区域外
     * 说明: 无
     ******************************************************************************/
    int pointInPolygon(Point_t *point, Point_t *points,int count) 
    {
     int   i,j=count-1 ;
     int  oddNodes = 0 ;
     double  x,y;  
    
     if(point == NULL || points == NULL)
      return -1;
    
     x = point->x, y = point->y; 
     for (i=0;i<count; i++)
     {
      if((points[i].y< y && points[j].y>=y
       || points[j].y<y && points[i].y>=y)
       && (points[i].x<=x || points[j].x<=x)) 
      {
       oddNodes^=(points[i].x+(y-points[i].y)/(points[j].y-points[i].y)*(points[j].x-points[i].x)<x);
      }
      j=i;
     }
    
      return oddNodes;
    }

    怎么处理都行,怎么方便怎么用。

    end

  • 相关阅读:
    PHP 基础复习 2018-06-21
    PHP 基础复习 2018-06-17
    php 基础复习 2018-06-20
    [Android] ImageView.ScaleType设置图解
    Android中滑屏实现----触摸滑屏以及Scroller类详解 .
    Android Scroller简单用法 --View滚动
    Android下如何理解onMeasure,onLayout的过程
    ( 转)从四分钟到两秒——谈谈客户端性能优化的一些最佳实践
    8种形式的Android Dialog使用举例
    Android加载图片导致内存溢出(Out of Memory异常)
  • 原文地址:https://www.cnblogs.com/dong1/p/10220116.html
Copyright © 2020-2023  润新知