電子圍欄


 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\n'%{'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\n'%{'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]\n",cJSON_GetErrorPtr());
        }

        //railwayFence array
        cJSON *railwayFenceArray = cJSON_GetObjectItem(root, "railwayFence");  
        if(!railwayFenceArray){  
            printf("Error before: [%s]\n",cJSON_GetErrorPtr()); 
        }
        int railwayFence_array_size = cJSON_GetArraySize(railwayFenceArray);  
        printf("railwayFence array size is %d\n",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\n",areaName->valuestring);  
            dangerType = cJSON_GetObjectItem(it, "dangerType");  
            printf("dangerType is %s\n",dangerType->valuestring);

            //Coordinate array
            cJSON *CoordinateArray = cJSON_GetObjectItem(railwayFenceItem, "coordinates");  
            if(!CoordinateArray){  
                printf("Error before: [%s]\n",cJSON_GetErrorPtr()); 
            }
            int Coordinate_array_size = cJSON_GetArraySize(CoordinateArray);  
            printf("Coordinate array size is %d\n",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\n",B->valuedouble);  
                L = cJSON_GetObjectItem(jt, "L");  
                printf("L is %f\n",L->valuedouble);
                fprintf(fp1,"%f %f\n",B->valuedouble,L->valuedouble);
                fprintf(fp,"%f %f\n",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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM