通过射线法判定POI是否在多边形区块内。
方法简介:
1、射线法:由目标点横向或纵向引出一条射线,和多边形区块的边相交,若相关点个数为奇数,则目标点在该区块内,否则不在该区块内;
2、根据已有的POI中心点坐标poi_xy和多边形区块wkt坐标,判断POI是否在多边形区块内。
from odps.udf import annotate
@annotate("string,string->bigint")
class IsInBusinessDistrict(object):
def evaluate(self, poi_coordinate, multipolygon_str):
try:
multipolygon_list = multipolygon_str.split(",")
poi_point = poi_coordinate.split(",")
eps = 10**-8
num = 0
for i in range(len(multipolygon_list)-2):
point1 = multipolygon_list[i].split(" ")
point2 = multipolygon_list[i+1].split(" ")
y_min = min(float(point1[1]), float(point2[1]))
y_max = max(float(point1[1]), float(point2[1]))
x = (float(poi_point[1])-float(point1[1]))*(float(point2[0])-float(point1[0]))/(float(point2[1])-float(point1[1]) + eps) + float(point1[0])
if round(x, len(poi_point[0].split(".")[1])) == float(poi_point[0]):
return 1
elif x < float(poi_point[0]) and float(poi_point[1]) <= y_max and float(poi_point[1]) >= y_min:
# print (multipolygon_list[i], multipolygon_list[i+1], x, y_min, y_max)
num += 1
print (num)
if num % 2 == 1:
return 1
else :
return 0
except:
return 0
if __name__ == "__main__":
# case1
poi_xy = "116.345736,39.917016"
# sq1
multi_str = "116.334202 39.932311,116.334353 39.932328,116.343731 39.932281,116.355389 39.932249,116.355395 39.932143,116.355505 39.930468,116.355512 39.930336,116.355623 39.928324,116.355744 39.925789,116.355503 39.925059,116.355421 39.924839,116.355457 39.923889,116.355293 39.923788,116.346404 39.923526,116.337348 39.923216,116.334995 39.923175,116.334784 39.923257,116.334510 39.925302,116.334179 39.930500,116.334144 39.930922,116.334098 39.931998,116.334098 39.932212,116.334202 39.932311"
res = IsInBusinessDistrict().evaluate(poi_xy, multi_str)
print(res)