1、找了个电子围栏算法,也就是多边形找点,在图形内还是图形外
#!/usr/bin/env python# -*- coding: utf-8 -*-import jsonimport mathlnglatlist = []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 resultpoint = [114.193437,30.513068]print(windingNumber(point,lnglatlist))
转自
2、我的项目json文件比较复杂,需要用个二维数据来存储坐标数据
#!/usr/bin/env python# -*- coding: utf-8 -*-import jsonimport mathdef 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 resultif __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.24381838.836013 115.24381338.836013 115.24380938.836015 115.24380538.836017 115.24380138.836019 115.24389838.836022 115.24389538.836023 115.24389538.836092 115.24385038.836160 115.24380638.836189 115.24378838.836218 115.24376938.836416 115.24364238.836613 115.24351538.837036 115.243243
plot.py
#!/usr/bin/env python# -*- coding: utf-8 -*-import matplotlib.pyplot as pltimport numpy as npimport jsonwith 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 jsonimport mathlnglatlist = []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 resultpoint = [115.259161584,38.813623816]print(windingNumber(point,lnglatlist))
5、展示单个围栏
#!/usr/bin/env python# -*- coding: utf-8 -*-import matplotlib.pyplot as pltimport numpy as npimport 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#include #include #include #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 -lmclean: 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=y || points[j].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)
怎么处理都行,怎么方便怎么用。
end