1. 程式人生 > 實用技巧 >python之 判斷點是否在多邊形範圍內

python之 判斷點是否在多邊形範圍內

#coding=UTF-8

import csv
import json


# 點是否在外包矩形內
def isPoiWithinBox(poi, sbox, toler=0.0001):
    # sbox=[[x1,y1],[x2,y2]]
    # 不考慮在邊界上,需要考慮就加等號
    if poi[0] > sbox[0][0] and poi[0] < sbox[1][0] and poi[1] > sbox[0][1] and poi[1] < sbox[1][1]:
        return True
    if toler > 0:
        pass
return False # 射線與邊是否有交點 def isRayIntersectsSegment(poi, s_poi, e_poi): # [x,y] [lng,lat] if s_poi[1] == e_poi[1]: # 排除與射線平行、重合,線段首尾端點重合的情況 return False if s_poi[1] > poi[1] and e_poi[1] > poi[1]: return False if s_poi[1] < poi[1] and e_poi[1] < poi[1]:
return False if s_poi[1] == poi[1] and e_poi[1] > poi[1]: return False if e_poi[1] == poi[1] and s_poi[1] > poi[1]: return False if s_poi[0] < poi[0] and e_poi[1] < poi[1]: return False xseg = e_poi[0] - (e_poi[0] - s_poi[0]) * (e_poi[1] - poi[1]) / (e_poi[1] - s_poi[1]) #
求交 if xseg < poi[0]: return False return True #只適用簡單多邊形 def isPoiWithinSimplePoly(poi, simPoly, tolerance=0.0001): # 點;多邊形陣列;容限 # simPoly=[[x1,y1],[x2,y2],……,[xn,yn],[x1,y1]] # 如果simPoly=[[x1,y1],[x2,y2],……,[xn,yn]] i迴圈到終點後還需要判斷[xn,yx]和[x1,y1] # 先判斷點是否在外包矩形內 if not isPoiWithinBox(poi, [[0, 0], [180, 90]], tolerance): return False polylen = len(simPoly) sinsc = 0 # 交點個數 for i in range(polylen - 1): s_poi = simPoly[i] e_poi = simPoly[i + 1] if isRayIntersectsSegment(poi, s_poi, e_poi): sinsc += 1 return True if sinsc % 2 == 1 else False def isPoiWithinPoly(poi, poly, tolerance=0.0001): # 點;多邊形三維陣列;容限 # poly=[[[x1,y1],[x2,y2],……,[xn,yn],[x1,y1]],[[w1,t1],……[wk,tk]]] 三維陣列 # 先判斷點是否在外包矩形內 if not isPoiWithinBox(poi, [[0, 0], [180, 90]], tolerance): return False sinsc = 0 # 交點個數 for epoly in poly: #逐個二維陣列進行判斷 for i in range(len(epoly) - 1): # [0,len-1] s_poi = epoly[i] e_poi = epoly[i + 1] if isRayIntersectsSegment(poi, s_poi, e_poi): sinsc += 1 return sinse %2 !=0 #這樣更簡潔些 #return True if sinsc % 2 == 1 else False ### 比較完備的版本 def pointInPolygon(cin_path,out_path,gfile,t=0): pindex = [2,3] # wgslng,wgslat 2,3 with open(out_path, 'w', newline='') as cut_file: fin = open(cin_path, 'r', encoding='gbk') gfn = open(gfile, 'r', encoding='utf-8') gjson = json.load(gfn) if gjson["features"][0]["geometry"]['type']=="MultiPolygon": plist=gjson["features"][0]["geometry"]['coordinates'] #四維 filewriter = csv.writer(cut_file, delimiter=',') w = 0 for line in csv.reader(fin, delimiter=','): if w == 0: filewriter.writerow(line) w = 1 continue point = [float(line[pindex[0]]), float(line[pindex[1]])] for polygon in plist: # if isPoiWithinPoly(point, polygon): filewriter.writerow(line) break fin.close() gfn.close() elif gjson["features"][0]["geometry"]['type']=="Polygon": polygon=gjson["features"][0]["geometry"]['coordinates'] #三維 filewriter = csv.writer(cut_file, delimiter=',') w = 0 for line in csv.reader(fin, delimiter=','): if w == 0: filewriter.writerow(line) w = 1 continue point = [float(line[pindex[0]]), float(line[pindex[1]])] if isPoiWithinPoly(point, polygon): filewriter.writerow(line) fin.close() gfn.close() else: print('check',gfile) print('end') #呼叫 def baTch(): import os import glob wpath="D:/DigitalC_data/coordConvert" #檔案路徑 sname="D:/DigitalC_data/coordConvertOut" gpath='D:/cityBoundaryJson/guangzhou_wgs84.json' for input_file in glob.glob(os.path.join(wpath, '*.csv')): fname=input_file.split('\\') pointInPolygon(input_file,os.path.join(sname,fname[1]),gpath) print(fname[1]) ## 應用 ### 應用3 ''' 對一個csv資料,如果點在多邊形內,給某一列(tag)(或者加一列)加上這個多邊形的屬性(有多個多邊形) ''' def givePolyTag(): pass ### 應用方式1 def pointInPolygon1(): gfile = 'E:/ComputerGraphicsProj/Geojson2kml/J2K_data/深圳poly_bd09.geojson' cin_path = 'L:/OtherSys/DigitalCityData/深圳特徵圖層/city_site_poi_sec_shenzhen.csv' out_path = 'L:/OtherSys/DigitalCityData/深圳特徵圖層/city_site_poi_sec_shenzhen_out1.csv' pindex = [4, 5] # wgslng,wgslat 2,3 with open(out_path, 'w', newline='') as cut_file: fin = open(cin_path, 'r', encoding='gbk') gfn = open(gfile, 'r', encoding='utf-8') gjson = json.load(gfn) polygon = gjson["features"][0]["geometry"]['coordinates'][0] filewriter = csv.writer(cut_file, delimiter=',') w = 0 for line in csv.reader(fin, delimiter=','): if w == 0: filewriter.writerow(line) w = 1 continue point = [float(line[pindex[0]]), float(line[pindex[1]])] if isPoiWithinSimplePoly(point, polygon): filewriter.writerow(line) fin.close() gfn.close() print('done') #pointInPolygon1() def csvToDArrary(csvpath):#csv檔案轉二維陣列 cdata = [] with open(csvpath, 'r', encoding='gbk') as rfile: for line in csv.reader(rfile, delimiter=','): cdata.append(line) return cdata ### 應用方式2 def pointInPolygon2(): gfile = 'E:/ComputerGraphicsProj/Geojson2kml/J2K_data/深圳poly_bd09.geojson' cin_path = 'L:/OtherSys/DigitalCityData/深圳特徵圖層/shenzhen_tAllNotIn.csv' out_path = 'L:/OtherSys/DigitalCityData/深圳特徵圖層/shenzhen_tAllNotIn_out2.csv' pindex = [4, 5] # wgslng,wgslat 2,3 with open(out_path, 'w', newline='') as cut_file: gfn = open(gfile, 'r', encoding='utf-8') gjson = json.load(gfn) polygon = gjson["features"][0]["geometry"]['coordinates'][0] filewriter = csv.writer(cut_file, delimiter=',') w = 0 cdata = csvToDArrary(cin_path) for line in cdata: if w == 0: filewriter.writerow(line) w = 1 continue point = [float(line[pindex[0]]), float(line[pindex][1])] if isPoiWithinSimplePoly(point, polygon): filewriter.writerow(line) gfn.close() print('done') pointInPolygon()