|
@@ -0,0 +1,142 @@
|
|
|
|
+# 判断一个点是否在楼层的轮廓里
|
|
|
|
+## 前置条件
|
|
|
|
+
|
|
|
|
+ 业务空间必须有轮廓, 且合法
|
|
|
|
+
|
|
|
|
+## 处理逻辑
|
|
|
|
+
|
|
|
|
+ 1. 业务空间外轮廓数据格式由如下示例所示, 由若干个元空间(子轮廓)的轮廓组成
|
|
|
|
+ 2. 判断点在是否在某一个子轮廓内, 如果在, 则点在业务空间内(返回true)
|
|
|
|
+ 1). 判断点在子轮廓内, 需要判断点在子轮廓的外轮廓内, 且不在任意1个子轮廓被排除的轮廓内
|
|
|
|
+
|
|
|
|
+## 业务空间轮廓结构示例
|
|
|
|
+```
|
|
|
|
+[
|
|
|
|
+ [
|
|
|
|
+ [
|
|
|
|
+ {点坐标的XYZ信息},
|
|
|
|
+ {点坐标的XYZ信息}...
|
|
|
|
+ ], // 子轮廓的外轮廓
|
|
|
|
+ [
|
|
|
|
+ {点坐标的XYZ信息},
|
|
|
|
+ {点坐标的XYZ信息}...
|
|
|
|
+ ], // 子轮廓的第n个需要被排除的轮廓, 可能有若干个
|
|
|
|
+ ], // 子轮廓
|
|
|
|
+ [
|
|
|
|
+ [
|
|
|
|
+ {点坐标的XYZ信息},
|
|
|
|
+ {点坐标的XYZ信息}...
|
|
|
|
+ ]
|
|
|
|
+ ],
|
|
|
|
+]
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+# 函数
|
|
|
|
+## 版本1
|
|
|
|
+
|
|
|
|
+<details>
|
|
|
|
+<summary>输入为浮点型</summary>
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+CREATE OR REPLACE FUNCTION "public"."is_point_in_polygon_v3"("x" float8, "y" float8, "json_poly" jsonb)
|
|
|
|
+ RETURNS "pg_catalog"."bool" AS $BODY$
|
|
|
|
+from matplotlib.path import Path
|
|
|
|
+import json
|
|
|
|
+
|
|
|
|
+def is_in_meta_polygon(point, single_poly, radius):
|
|
|
|
+ poly_len = len(single_poly)
|
|
|
|
+ poly = []
|
|
|
|
+ for i in range(poly_len):
|
|
|
|
+ pair = single_poly[i]
|
|
|
|
+ poly.append((pair["X"], pair["Y"]))
|
|
|
|
+ p = Path(poly)
|
|
|
|
+ return p.contains_points([point], None, radius)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def is_in_polygon(point, polygons):
|
|
|
|
+ length = len(polygons)
|
|
|
|
+ if length == 0:
|
|
|
|
+ return False
|
|
|
|
+ for j in range(length):
|
|
|
|
+ polygon = polygons[j]
|
|
|
|
+ if j == 0:
|
|
|
|
+ if not is_in_meta_polygon(point, polygon, -0.001):
|
|
|
|
+ return False
|
|
|
|
+ else:
|
|
|
|
+ if is_in_meta_polygon(point, polygon, 0.001):
|
|
|
|
+ return False
|
|
|
|
+ return True
|
|
|
|
+
|
|
|
|
+try:
|
|
|
|
+ polygon_list = json.loads(json_poly)
|
|
|
|
+ total_len = len(polygon_list)
|
|
|
|
+ point_pair = (x, y)
|
|
|
|
+ for index in range(total_len):
|
|
|
|
+ if is_in_polygon(point_pair, polygon_list[index]):
|
|
|
|
+ return True
|
|
|
|
+ return False
|
|
|
|
+except Exception as e:
|
|
|
|
+ return False
|
|
|
|
+$BODY$
|
|
|
|
+ LANGUAGE plpython3u VOLATILE
|
|
|
|
+ COST 100
|
|
|
|
+```
|
|
|
|
+</details>
|
|
|
|
+
|
|
|
|
+## 版本2
|
|
|
|
+<details>
|
|
|
|
+<summary>输入为字符串类型</summary>
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+CREATE OR REPLACE FUNCTION "public"."is_point_in_polygon_v3_str"("x" varchar, "y" varchar, "json_poly" jsonb)
|
|
|
|
+ RETURNS "pg_catalog"."bool" AS $BODY$
|
|
|
|
+from matplotlib.path import Path
|
|
|
|
+import json
|
|
|
|
+
|
|
|
|
+def is_in_meta_polygon(point, single_poly, radius):
|
|
|
|
+ poly_len = len(single_poly)
|
|
|
|
+ poly = []
|
|
|
|
+ for i in range(poly_len):
|
|
|
|
+ pair = single_poly[i]
|
|
|
|
+ poly.append((pair["X"], pair["Y"]))
|
|
|
|
+ p = Path(poly)
|
|
|
|
+ return p.contains_points([point], None, radius)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def is_in_polygon(point, polygons):
|
|
|
|
+ length = len(polygons)
|
|
|
|
+ if length == 0:
|
|
|
|
+ return False
|
|
|
|
+ for j in range(length):
|
|
|
|
+ polygon = polygons[j]
|
|
|
|
+ if j == 0:
|
|
|
|
+ if not is_in_meta_polygon(point, polygon, -0.001):
|
|
|
|
+ return False
|
|
|
|
+ else:
|
|
|
|
+ if is_in_meta_polygon(point, polygon, 0.001):
|
|
|
|
+ return False
|
|
|
|
+ return True
|
|
|
|
+
|
|
|
|
+try:
|
|
|
|
+ polygon_list = json.loads(json_poly)
|
|
|
|
+ total_len = len(polygon_list)
|
|
|
|
+ point_pair = (float(x), float(y))
|
|
|
|
+ for index in range(total_len):
|
|
|
|
+ if is_in_polygon(point_pair, polygon_list[index]):
|
|
|
|
+ return True
|
|
|
|
+ return False
|
|
|
|
+except Exception as e:
|
|
|
|
+ return False
|
|
|
|
+$BODY$
|
|
|
|
+ LANGUAGE plpython3u VOLATILE
|
|
|
|
+ COST 100
|
|
|
|
+```
|
|
|
|
+</details>
|
|
|
|
+
|
|
|
|
+## 输入
|
|
|
|
+ 1. 点的x坐标
|
|
|
|
+ 2. 点的y坐标
|
|
|
|
+ 3. 业务空间的轮廓
|
|
|
|
+## 返回结果
|
|
|
|
+ true 成功
|
|
|
|
+ false 失败
|