# 判断一个点是否在楼层的轮廓里
## 前置条件
    
    业务空间必须有轮廓, 且合法
    
## 处理逻辑

    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   失败