一.java实现
所用jar包:
<dependency>
<groupId>nl.cloudfarming.client</groupId>
<artifactId>lib-geotools</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
</dependency>
1.传入点或多边形的wkt字符串
/**
* 判断点是否在某个多边形上
* @param pointWkt
* @param ploygonWkt
* @param isContainsEdge 是否包含边界,如果为true,那么在边界上时也算在多边形内
* @return
*/
public static boolean judgePointIfInRegion(String pointWkt, String ploygonWkt,
boolean isContainsEdge) {
WKTReader reader = new WKTReader(JTSFactoryFinder.getGeometryFactory(null));
Geometry point = null;
Geometry poly = null;
try {
point = reader.read(pointWkt);
poly = reader.read(ploygonWkt);
} catch (Exception e) {
e.printStackTrace();
}
if(!isContainsEdge){
// 判断是否在区域内
return poly.contains(point);
}else{
// 判断是否相交或在区域内
return poly.intersects(point) || poly.contains(point);
}
}
测试:
public static void main(String[] args) {
String wktPoly = "POLYGON ((116.37150802 39.76183098000003,116.38340802 39.76183098000003,116.38340802 39.7579994886348,116.3798506328265 39.75717762188538,116.3780662872948 39.75685062893655,116.3769283831572 39.75675043493624,116.376230979047 39.75674108396044,116.3755731966328 39.75678290806371,116.3742240792109 39.75690322058387,116.3735865028596 39.75704296592238,116.3731405117154 39.75722575706936,116.372299771974 39.75765971936517,116.3718584872889 39.75793849075126,116.3715491604592 39.75817657788684,116.37150802 39.75821656329189,116.37150802 39.76183098000003))"; //请自行搜素了解wkt格式
String wktPoint = "POINT (116.37150802 39.76183098000003)";
System.out.println(judgePointIfInRegion(wktPoint,wktPoly,true));
}
输出:
true
2.传入点或多边形的坐标列表
/**
* 判断点是否在某个多边形上
* @param pointCoord
* @param ploygonCoords
* @param isContainsEdge 是否包含边界,如果为true,那么在边界上时也算在多边形内
* @return
*/
public static boolean judgePointIfInRegion(List<Double> pointCoord,
List<List<List<Double>>> ploygonCoords,boolean isContainsEdge) {
String pointWkt = "POINT " + pointCoord.toString().
replace("[","(").replace("]",")").
replace(","," ");
String ploygonWkt = "POLYGON " + ploygonCoords.toString().replace(" ", "").
replace("]],[[", ");(").replace("],[", ";").
replace("[[[", "((").replace("]]]", "))").
replace(",", " ").replace(";", ",");
WKTReader reader = new WKTReader(JTSFactoryFinder.getGeometryFactory(null));
Geometry point = null;
Geometry poly = null;
try {
point = reader.read(pointWkt);
poly = reader.read(ploygonWkt);
} catch (Exception e) {
e.printStackTrace();
}
if(!isContainsEdge){
// 判断是否在区域内
return poly.contains(point);
}else{
// 判断是否相交或在区域内
return poly.intersects(point) || poly.contains(point);
}
}
测试:
public static void main(String[] args) {
Gson gson = new Gson();
String pointCoordStr = "[113.775698, 30.236892]";
List pointCoord = gson.fromJson(pointCoordStr,List.class);
String ploygonCoordsStr = "[[[113.76708006000003,30.231097985000019],[113.77808006000006,30.231097985000019],[113.77808006000006,30.240197984999959]," +
"[113.76708006000003,30.240197984999959],[113.76708006000003,30.231097985000019]]]";
List ploygonCoords = gson.fromJson(ploygonCoordsStr,List.class);
System.out.println(judgePointIfInRegion(pointCoord,ploygonCoords,true));
}
输出:
true
二.Python实现
射线法实现
法一:
'''
判断某个坐标是否在某个封闭区域内
'''
# 判断该点是否在该条线上
# point:点坐标,如:[113.775698, 30.236892]
# o : 该条线的起点
# d : 该条线的终点
def is_in_line(point, o, d):
# 先判断该点是否在线段范围内,如果不在,
# 则就算在该方程的直线上但也不在该线段上
if o[1] > point[1] and d[1] > point[1]: # 该点纵坐标小于线段最小纵坐标
return False
if o[1] < point[1] and d[1] < point[1]: # 该点纵坐标大于线段最大纵坐标
return False
if o[0] > point[0] and d[0] > point[0]: # 该点横坐标小于线段最小横坐标
return False
if o[0] < point[0] and d[0] < point[0]: # 该点横坐标大于线段最大横坐标
return False
# 若线段为垂直直线,则该点的横坐标等于该线段的横坐标才说明在该线段上
if o[0] == d[0]:
return True if point[0] == o[0] else False
# 通过输入的两个点计算一元一次方程,通过输入x,计算y
a = (d[1] - o[1]) / (d[0] - o[0])
b = (d[0] * o[1] - o[0] * d[1]) / (d[0] - o[0])
y = a * point[0] + b
return True if y == point[1] else False
# 假设以该点向右水平做射线,判断该点是否与该线段有交点(只要线段与射线相交则为true)
# point:点坐标,如:[113.775698, 30.236892]
# o : 该条线的起点
# d : 该条线的终点
def is_ray_intersects_segment(point, o, d):
if o[1] == d[1]: # 如果线段是水平直线,则直接无交点
return False
# 先判断该点是否在线段范围内,如果不在,
# 则就算在该方程的直线上但也不在该线段上
if o[1] > point[1] and d[1] > point[1]: # 该点纵坐标小于等于线段最小纵坐标
return False
if o[1] < point[1] and d[1] < point[1]: # 该点纵坐标大于等于线段最大纵坐标
return False
# 先求出一元一次方程求交点
# 若线段为垂直直线,则该点的横坐标应该小于该点的横坐标才能有交点
# if o[0] == d[0]:
# return True if point[0] < o[0] else False
#
# # 通过输入的两个点计算一元一次方程,通过输入x,计算y
# a = (d[1] - o[1]) / (d[0] - o[0])
# b = (d[0] * o[1] - o[0] * d[1]) / (d[0] - o[0])
# x = (point[1] - b) / a
# 利用三角形比例关系求交点
x = d[0] - (d[0] - o[0]) * (d[1] - point[1]) / (d[1] - o[1])
# 如果该点的横坐标小于相同水平线上交点的横坐标,则有交点
return True if point[0] < x else False
"""
判断是否在矩形区域内
point_coord:点坐标,如:[113.775698, 30.236892]
polygon_coords:封闭多边形,如:[[[113.76708006000003,30.231097985000019],
[113.77808006000006,30.231097985000019],[113.76708006000003,30.231097985000019]]]
is_contains_edge: 是否包含边界,如果为true,那么在边界上时也算在多边形内
"""
def is_point_in_polygon(point_coord, polygon_coords, is_contains_edge):
intersect_count = 0 # 交点个数
for polygon in polygon_coords:
# 循环每条边
for i in range(len(polygon) - 1):
origin_point = polygon[i]
destination_point = polygon[i + 1]
# 是否包含存在直线上的点
if is_in_line(point_coord, origin_point, destination_point):
return True if is_contains_edge else False
if is_ray_intersects_segment(point_coord, origin_point, destination_point):
# 有交点就加1
intersect_count += 1
# 如果恰好与端点相交,则查看相应的端点,并减去与该点相同纵坐标且在该点右侧的点的个数
endpoint_intersects_count = 0
for polygon in polygon_coords:
# 遍历每一个点,但是因为最后一个点和第一个点是重复的,所以最后一个不遍历
for i in polygon[:-1]:
if i[1] == point_coord[1] and i[0] > point_coord[0]:
endpoint_intersects_count += 1
intersect_count -= endpoint_intersects_count
return True if intersect_count % 2 == 1 else False
poly = [[
[2.0, 4.0],
[2.0, 6.0],
[4.0, 8.0],
[6.0, 8.0],
[8.0, 6.0],
[8.0, 4.0],
[6.0, 2.0],
[4.0, 2.0],
[2.0, 4.0]
],
[
[3.0, 5.0],
[4.0, 7.0],
[6.0, 7.0],
[7.0, 6.0],
[6.0, 5.0],
[3.0, 5.0]
]
]
poi = [6.5, 7]
print(is_point_in_polygon(poi, poly, False))
法二:
'''
判断某个坐标是否在某个封闭区域内
'''
# 判断该点是否在该条线上
# point:点坐标,如:[113.775698, 30.236892]
# o : 该条线的起点
# d : 该条线的终点
def is_in_line(point, o, d):
# 先判断该点是否在线段范围内,如果不在,
# 则就算在该方程的直线上但也不在该线段上
if o[1] > point[1] and d[1] > point[1]: # 该点纵坐标小于线段最小纵坐标
return False
if o[1] < point[1] and d[1] < point[1]: # 该点纵坐标大于线段最大纵坐标
return False
if o[0] > point[0] and d[0] > point[0]: # 该点横坐标小于线段最小横坐标
return False
if o[0] < point[0] and d[0] < point[0]: # 该点横坐标大于线段最大横坐标
return False
# 若线段为垂直直线,则该点的横坐标等于该线段的横坐标才说明在该线段上
if o[0] == d[0]:
return True if point[0] == o[0] else False
# 通过输入的两个点计算一元一次方程,通过输入x,计算y
a = (d[1] - o[1]) / (d[0] - o[0])
b = (d[0] * o[1] - o[0] * d[1]) / (d[0] - o[0])
y = a * point[0] + b
return True if y == point[1] else False
# 假设以该点向右水平做射线,判断该点是否与该线段有交点(当射线与线段下端点相交时为False)
# point:点坐标,如:[113.775698, 30.236892]
# o : 该条线的起点
# d : 该条线的终点
def is_ray_intersects_segment(point, o, d):
if o[1] == d[1]: # 如果线段是水平直线,则直接无交点
return False
# 先判断该点是否在线段范围内,如果不在,
# 则就算在该方程的直线上但也不在该线段上
if o[1] > point[1] and d[1] > point[1]: # 该点纵坐标小于等于线段最小纵坐标
return False
if o[1] < point[1] and d[1] < point[1]: # 该点纵坐标大于等于线段最大纵坐标
return False
if o[1] == point[1] and d[1] > point[1]: # 若o点为下端点且交点为下端点时
return False
if d[1] == point[1] and o[1] > point[1]: # 交d点为下端点且交点为下端点时
return False
# 注释部分为 先求出一元一次方程求交点
# 若线段为垂直直线,则该点的横坐标应该小于该点的横坐标才能有交点
# if o[0] == d[0]:
# return True if point[0] < o[0] else False
#
# # 通过输入的两个点计算一元一次方程,通过输入x,计算y
# a = (d[1] - o[1]) / (d[0] - o[0])
# b = (d[0] * o[1] - o[0] * d[1]) / (d[0] - o[0])
# x = (point[1] - b) / a
# 利用三角形比例关系求交点
x = d[0] - (d[0] - o[0]) * (d[1] - point[1]) / (d[1] - o[1])
# 如果该点的横坐标小于相同水平线上交点的横坐标,则有交点
return True if point[0] < x else False
"""
判断是否在矩形区域内
point_coord:点坐标,如:[113.775698, 30.236892]
polygon_coords:封闭多边形,如:[[[113.76708006000003,30.231097985000019],
[113.77808006000006,30.231097985000019],[113.76708006000003,30.231097985000019]]]
is_contains_edge: 是否包含边界,如果为true,那么在边界上时也算在多边形内
"""
def is_point_in_polygon(point_coord, polygon_coords, is_contains_edge):
intersect_count = 0 # 交点个数
for polygon in polygon_coords:
# 循环每条边
for i in range(len(polygon) - 1):
origin_point = polygon[i]
destination_point = polygon[i + 1]
# 是否包含存在直线上的点
if is_in_line(point_coord, origin_point, destination_point):
return True if is_contains_edge else False
if is_ray_intersects_segment(point_coord, origin_point, destination_point):
# 有交点就加1
intersect_count += 1
return True if intersect_count % 2 == 1 else False
poly = [[
[2.0, 4.0],
[2.0, 6.0],
[4.0, 8.0],
[6.0, 8.0],
[8.0, 6.0],
[8.0, 4.0],
[6.0, 2.0],
[4.0, 2.0],
[2.0, 4.0]
],
[
[3.0, 5.0],
[4.0, 7.0],
[6.0, 7.0],
[7.0, 6.0],
[6.0, 5.0],
[3.0, 5.0]
]
]
poi = [5, 5]
print(is_point_in_polygon(poi, poly, False))