<script setup>
/**
 * 围栏组件
 * 在3D地图上生成特定区域的围栏，用于标识仓库中的重点监控区域
 * 基于THREE.js实现3D围栏的渲染和管理
 */
import { inject, onBeforeUnmount } from "vue"
import { useFence } from "../hooks/useFence" // 导入围栏生成自定义钩子

/**
 * 从VgoMap获取THREE.js实例
 * THREE.js是一个JavaScript 3D库，用于3D模型的渲染、动画和交互
 * 此处用于创建围栏的3D几何体并添加到地图场景中
 */
const { THREE } = VgoMap

/**
 * 注入上级组件（Map.vue）提供的数据
 * 使用Vue的provide/inject机制获取父组件共享的数据
 */
// 从父组件注入地图实例，用于将围栏添加到地图场景
const map = inject("map")
// 从父组件注入所有多边形数据，包含仓库中所有建筑的点位信息
const polygonDataAll = inject("polygonDataAll")

/**
 * 筛选出需要包含在围栏内的建筑点位
 * 从所有多边形数据中筛选出指定名称的建筑
 */
const inFencePoints = polygonDataAll.value.filter(p => {
  // 筛选条件：建筑名称包含在指定的重点区域列表中
  // 这里选择了'保卫部', '智慧大楼', '能源部办公楼'作为重点监控区域
  return ['保卫部', '智慧大楼', '能源部办公楼'].includes(p.name)
}).map(p => p.points).flat() // 提取所有筛选出建筑的点位数据并扁平化数组

/**
 * 使用自定义hook创建围栏生成函数
 * 从useFence钩子中解构出generateFence函数，用于生成围栏几何体
 * @param {Object} options - 围栏配置参数
 * @param {number} options.height - 围栏高度，此处设置为60单位
 * @param {boolean} options.isCloseTop - 是否封闭顶部，true表示生成封闭的围栏
 */
const { generateFence } = useFence({
  height: 60, // 围栏高度，单位与地图坐标系一致
  isCloseTop: true, // 是否封闭顶部，设置为true可生成顶部封闭的围栏
})

/**
 * 创建围栏组，用于统一管理和销毁围栏对象
 * 使用THREE.Group可以方便地组织和管理多个3D对象
 */
const fenceGroup = new THREE.Group() // 创建THREE.js组对象用于集中管理所有围栏相关的3D对象
map.value.scene.add(fenceGroup) // 将围栏组添加到地图场景中，使其可见

/**
 * 生成围栏并添加到围栏组
 * 使用getMinBoxPoints计算出的最小包围矩形作为围栏的边界
 */
// 调用generateFence函数生成围栏几何体，传入通过getMinBoxPoints计算的最小矩形顶点
const fence = generateFence(getMinBoxPoints(inFencePoints))
// 将生成的围栏几何体添加到围栏组中
fenceGroup.add(fence)

/**
 * 组件生命周期钩子：卸载前执行
 * 清理围栏资源，避免内存泄漏
 */
onBeforeUnmount(() => {
  // 安全检查：确保fenceGroup存在
  if (fenceGroup) {
    fenceGroup.clear() // 清除围栏组中的所有子对象
    // 安全检查：确保map和map.scene存在
    if (map.value && map.value.scene) {
      map.value.scene.remove(fenceGroup) // 从地图场景中移除围栏组
    }
  }
})

/**
 * 根据所有包含的点位，计算并获取最小包围矩形的顶点数组
 * 算法原理：使用THREE.Box2计算点集的最小包围盒，然后提取四个顶点
 * @param {Array<THREE.Vector3>} points - 输入的点位数组，包含需要包围的所有点
 * @returns {Array<THREE.Vector3>} - 最小矩形的四个顶点坐标（按顺时针顺序）
 */
function getMinBoxPoints(points) {
  const box = new THREE.Box2() // 创建二维包围盒对象
  box.setFromPoints(points) // 根据输入点集计算最小包围盒
  
  // 返回最小矩形的四个顶点（按顺时针顺序）
  // 注意：这里z坐标统一设置为0，表示在地图的平面上
  return [
    new THREE.Vector3(box.min.x, box.min.y, 0), // 左下角顶点
    new THREE.Vector3(box.max.x, box.min.y, 0), // 右下角顶点
    new THREE.Vector3(box.max.x, box.max.y, 0), // 右上角顶点
    new THREE.Vector3(box.min.x, box.max.y, 0)  // 左上角顶点
  ];
}
</script>

<template>
  <!-- 围栏组件容器 -->
  <!-- 注意：此组件主要通过JavaScript在3D场景中渲染围栏，DOM元素仅作为组件的挂载点 -->
  <div class="fence"></div>
</template>