<template>
    <div>
        <div id="containerThreeProjectInfo"></div>
    </div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { ConvexGeometry } from "three/examples/jsm/geometries/ConvexGeometry.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
const ThreeBSP = require('three-js-csg')(THREE)
// import {
//     showFullScreenLoading,
//     tryHideFullScreenLoading,
// } from "../../../axios/filter";
import { mapState } from "vuex";

export default {
    name: "threeProjectInfo", // 项目详情中的threeJS
    components: {},

    data() {
        return {
            publicPath: process.env.BASE_URL,
            scene: null,
            camera: null,
            renderer: null,
            light: null,
            transformControls: null,
            geometryName: null,
            controls: null,
            mesh: null,
            cube: null,
            cacheList: [],
            container: null,
            car: null,
            cubeTexture: null,
            raf: null,
            canDrag: true, // 是否可移动
            dragControls: null,
            sensor: null, // 当前操作的传感器配置
            ogt: null,
            // scale: 2, // 物体加载换算倍数
            // rate: 20, // 坐标换算倍数
            configList: {},
            ogtObj: null,
            loadingFull: false,
            bsp: {
                camera: {},
                ogt: {},
                lidar: {},
            },
            a1: null,
            b1: null,
            c1: null,
            d1: null,
            a2: null,
            b2: null,
            c2: null,
            d2: null,
            x1: null,
            y1: null,
            z1: null,
            w1: null,
            x2: null,
            y2: null,
            z2: null,
            w2: null,
        };
    },

    computed: {
        ...mapState(["scale", "scaleRate"]),
        // 坐标换算倍数
        rate() {
            return 40 / this.scale;
        },
    },

    props: {
        carModel: {
            type: String,
            default: "",
        },
        allSensor: {
            default: function () {
                return {};
            },
            type: Object,
        },
        // configList: {
        //     type: Object,
        //     default: {
        //         camera: [],
        //         ogt: [],
        //         lidar: [],
        //         gps: [],
        //     },
        // },
    },

    watch: {
        carModel(newVal, oldVal) {
            if (newVal && newVal != oldVal) {
                this.initCar(newVal);
            }
        },
        // configList(newVal, oldVal) {
        // newVal, oldVal都没有值
        //     if (newVal && newVal != oldVal) {
        //         if (
        //             newVal.camera.length > 0 ||
        //             newVal.ogt.length > 0 ||
        //             newVal.lidar.length > 0 ||
        //             newVal.gps.length > 0
        //         ) {
        //             this.showAll();
        //         }
        //     }
        // },
    },

    methods: {
        // 场景
        initScene() {
            this.scene = new THREE.Scene();
            let axes = new THREE.AxesHelper(12000);
            this.scene.add(axes);
            const gridHelper = new THREE.GridHelper(21000, 2100);
            gridHelper.material.opacity = 0.25;
            gridHelper.material.transparent = true;
            this.scene.add(gridHelper);
        },
        // 相机
        initCamera() {
            this.camera = new THREE.PerspectiveCamera(
                75,
                this.container.clientWidth / this.container.clientHeight,
                0.1,
                30000
            );
            this.camera.position.set(200, 200, 200);
            this.scene.add(this.camera);
        },
        // 渲染器
        initRenderer() {
            this.renderer = new THREE.WebGLRenderer({
                antialias: true,
                alpha: true,
            });
            this.renderer.setSize(
                this.container.clientWidth,
                this.container.clientHeight
            );
            this.renderer.setClearColor("#272727");
            this.container.appendChild(this.renderer.domElement);
        },
        // 初始化灯光
        initLight() {
            var hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
            hemiLight.position.set(0, 20, 0);
            this.scene.add(hemiLight);

            // 环境光会均匀的照亮场景中的所有物体
            const light = new THREE.AmbientLight(0x5c5c5c, 0.4); // soft white light
            this.scene.add(light);

            // 平行光是沿着特定方向发射的光
            const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
            this.scene.add(dirLight);
        },
        // 初始化模型
        initContent1(r, position, rotation, type) {
            var cubeGeometry = new THREE.ConeGeometry(
                r || 45 * this.scale,
                150 * this.scale,
                4,
                1,
                false
            );
            cubeGeometry.translate(0, -75 * this.scale, 0);

            let obj = {
                color: 0x4c4c4c,
                transparent: true,
                opacity: 0.3,
                lightMapIntensity: 0.1,
            };

            if (type === "camera") {
                obj.emissive = 0x0000ff;
            } else if (type === "ogt") {
                obj.emissive = 0x008000;
            } else if (type === "lidar") {
                obj.emissive = 0xff4500;
            } else if (type === "gps") {
                obj.emissive = 0x8a2be2;
            }

            var cubeMaterial = new THREE.MeshLambertMaterial(obj);
            this.cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            this.cube.name = this.geometryName || "cube";

            if (position) {
                this.cube.position.x = position.x;
                this.cube.position.y = position.y;
                this.cube.position.z = position.z;
            }

            if (rotation) {
                this.cube.rotateX(rotation.x);
                this.cube.rotateY(rotation.y);
                this.cube.rotateZ(rotation.z);
            }

            this.scene.add(this.cube);

            if (this.transformControls) {
                this.transformControls.attach(this.cube);
            }
        },
        /**
         * 初始化模型
         * @param {*} position 位置
         * @param {*} rotation 旋转
         * @param {*} type 传感器类型
         * @param {*} index 该传感器所在数组下标
         * @param {*} canMove 如果用于单独展示则可拖拽，用于全部预览则不可拖拽
         */
        initContent(position, rotation, type, index, canMove) {
            // console.log(this.configList);
            // console.log(this.allSensor);
            let sensorId = this.configList[type][index].sensorId;
            let coordinate = this.allSensor[type].find(
                (i) => i.id === sensorId
            );

            if (!coordinate) {
                coordinate = {
                    farDistance: 60,
                    nearDistance: 0,
                    fovH: 60,
                    fovV: 60,
                    fovHLeft: 60,
                    fovVTop: 60,
                    fovHRight: 60,
                    fovVBottom: 60,
                };
            }

            let r = coordinate.farDistance * 100;
            let r1 = coordinate.nearDistance * 100;

            if (r <= 0 || r1 < 0 || r <= r1) {
                return;
            }

            if (type != "ogt") {
                this.initSenA(
                    position,
                    rotation,
                    coordinate,
                    r / (this.scale / 0.6),
                    r1 / (this.scale / 0.6),
                    type,
                    canMove
                );
            } else {
                this.initSenB(
                    position,
                    rotation,
                    coordinate,
                    r / (this.scale / 0.6),
                    r1 / (this.scale / 0.6),
                    type,
                    canMove
                );
            }
        },
        initContent0(coordinate, vh, nf) {
            let r = 0, deg = 0, rate = 1;
            // let a = 100 / (this.scale / 0.6);
            let a = 1;

            // 若探测距离超出最大值，则默认为10000，盲区距离按比例展示 
            // 值为测试出来的预估值 超过的话ThreeBSP会报内存溢出
            let maxR = 10000;

            if ((coordinate.farDistance * a) > maxR) {
                if (nf === 'n') {
                    rate = (coordinate.farDistance * a) / maxR;
                    r = ((coordinate.nearDistance * a) / rate).toFixed();
                } else {
                    r = maxR - 3.3;
                }
            } else {
                if (nf === 'n') {
                    r = coordinate.nearDistance * a;
                } else {
                    r = coordinate.farDistance * a;
                }
            }

            if (vh === 'v') {
                deg = coordinate.fovV;
                // if (coordinate.fovH >= 47 && coordinate.fovH <= 53 && coordinate.fovV == 30) {
                //     deg = 31;
                // }

                // if (deg == 80) deg = 79;
                // if (deg == 20) deg = 19;
                // if (deg % 10 === 0 && deg % 90 != 0) deg = deg + 0.7;
            } else {
                deg = coordinate.fovH / 2;
                // if (deg >= 47 && deg <= 53) deg = 53;
                // if (deg >= 17 && deg <= 23) deg = 17;
                // if (deg >= 117 && deg <= 123) deg = 121;
                // if (deg >= 147 && deg <= 153) deg = 148;
            }

            // 180°时融合有问题
            // if (deg % 90 === 0) deg = deg - 0.5;


            let phiStart = Math.PI * ((90 - deg) / 180),
                phiLength = Math.PI * (deg * 2 / 180),
                thetaStart = 0,
                thetaLength = Math.PI;

            const geometry = new THREE.SphereGeometry(
                r, // radius — 球体半径，默认为1
                32, // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32
                16, // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16
                phiStart, // phiStart — 指定水平（经线）起始角度，默认值为0
                phiLength, // phiLength — 指定水平（经线）扫描角度的大小，默认值为 Math.PI * 2
                thetaStart, // thetaStart — 指定垂直（纬线）起始角度，默认值为0
                thetaLength // thetaLength — 指定垂直（纬线）扫描角度大小，默认值为 Math.PI
            );
            const material = new THREE.MeshBasicMaterial({ color: 0xff00ff, side: THREE.DoubleSide });
            const sphere = new THREE.Mesh(geometry, material);


            const geometry1 = new THREE.CircleGeometry(
                r, // radius — 圆形的半径，默认值为1
                32, // segments — 分段（三角面）的数量，最小值为3，默认值为32
                0, // thetaStart — 第一个分段的起始角度，默认为0。（three o'clock position）
                Math.PI * 1 // thetaLength — 圆形扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆
            );
            const material1 = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });
            const circle1 = new THREE.Mesh(geometry1, material1); // left top



            const geometry2 = new THREE.CircleGeometry(
                r, // radius — 圆形的半径，默认值为1
                32, // segments — 分段（三角面）的数量，最小值为3，默认值为32
                0, // thetaStart — 第一个分段的起始角度，默认为0。（three o'clock position）
                Math.PI * 1 // thetaLength — 圆形扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆
            );
            const material2 = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });
            const circle2 = new THREE.Mesh(geometry2, material2); // right bottom


            if (vh === 'v') {
                sphere.rotateZ(Math.PI * 0.5);
                circle1.rotateX(phiStart);
                circle2.rotateX(-phiStart - Math.PI);

                if (nf === 'n') {
                    this.x2 = new ThreeBSP(sphere);
                    this.y2 = new ThreeBSP(circle1);
                    this.z2 = new ThreeBSP(circle2);
                } else {
                    this.a2 = new ThreeBSP(sphere);
                    this.b2 = new ThreeBSP(circle1);
                    this.c2 = new ThreeBSP(circle2);
                }
            } else {
                circle1.rotateZ(Math.PI * -0.5);
                circle1.rotateX(phiStart);
                circle2.rotateZ(Math.PI * 0.5);
                circle2.rotateX(phiStart);

                if (nf === 'n') {
                    this.x1 = new ThreeBSP(sphere);
                    this.y1 = new ThreeBSP(circle1);
                    this.z1 = new ThreeBSP(circle2);
                } else {
                    this.a1 = new ThreeBSP(sphere);
                    this.b1 = new ThreeBSP(circle1);
                    this.c1 = new ThreeBSP(circle2);
                }
            }


            if (deg >= 360) {
                const sphere1 = new THREE.SphereGeometry(
                    r, // radius — 球体半径，默认为1
                    32, // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32
                    16, // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16
                    0, // phiStart — 指定水平（经线）起始角度，默认值为0
                    Math.PI * 2, // phiLength — 指定水平（经线）扫描角度的大小，默认值为 Math.PI * 2
                    0, // thetaStart — 指定垂直（纬线）起始角度，默认值为0
                    Math.PI // thetaLength — 指定垂直（纬线）扫描角度大小，默认值为 Math.PI
                );

                this.a1 = new ThreeBSP(sphere1);
            }
        },
        initContent01(coordinate) {
            let far = coordinate.farDistance,
                near = coordinate.nearDistance,
                fovV = coordinate.fovV / 2;

            if (fovV >= 90) fovV = 89.9;

            let h = Math.sin(THREE.MathUtils.degToRad(fovV)) * far,
                r1 = Math.cos(THREE.MathUtils.degToRad(fovV)) * far;

            const cone1 = new THREE.ConeGeometry(
                r1, // radius — 圆锥底部的半径，默认值为1
                h, // height — 圆锥的高度，默认值为1
                32, // radialSegments — 圆锥侧面周围的分段数，默认为32
                1, // heightSegments — 圆锥侧面沿着其高度的分段数，默认值为1
                false, // openEnded — 一个Boolean值，指明该圆锥的底面是开放的还是封顶的。默认值为false，即其底面默认是封顶的
                0, // thetaStart — 第一个分段的起始角度，默认为0
                2 * Math.PI, // thetaLength — 圆锥底面圆扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆锥
            );

            cone1.translate(0, -h / 2, 0);
            cone1.rotateX(Math.PI * 1);

            const cone2 = new THREE.ConeGeometry(
                r1, // radius — 圆锥底部的半径，默认值为1
                h, // height — 圆锥的高度，默认值为1
                32, // radialSegments — 圆锥侧面周围的分段数，默认为32
                1, // heightSegments — 圆锥侧面沿着其高度的分段数，默认值为1
                false, // openEnded — 一个Boolean值，指明该圆锥的底面是开放的还是封顶的。默认值为false，即其底面默认是封顶的
                0, // thetaStart — 第一个分段的起始角度，默认为0
                2 * Math.PI, // thetaLength — 圆锥底面圆扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆锥
            );
            cone2.translate(0, -h / 2, 0);



            const circle01 = new THREE.CircleGeometry(h * 0.1, 32);
            circle01.rotateX(Math.PI * 0.5);
            circle01.translate(0, h, 0);

            const circle02 = new THREE.CircleGeometry(h * 0.1, 32);
            circle02.rotateX(Math.PI * 0.5);
            circle02.translate(0, -h, 0);


            if (near > 0) {
                const sphere1 = new THREE.SphereGeometry(
                    near, // radius — 球体半径，默认为1
                    32, // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32
                    16, // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16
                    0, // phiStart — 指定水平（经线）起始角度，默认值为0
                    Math.PI * 2, // phiLength — 指定水平（经线）扫描角度的大小，默认值为 Math.PI * 2
                    0, // thetaStart — 指定垂直（纬线）起始角度，默认值为0
                    Math.PI // thetaLength — 指定垂直（纬线）扫描角度大小，默认值为 Math.PI
                );
                this.z1 = new ThreeBSP(sphere1);
            }


            this.x1 = new ThreeBSP(circle01); // up
            this.y1 = new ThreeBSP(cone1);
            this.x2 = new ThreeBSP(circle02); // down
            this.y2 = new ThreeBSP(cone2);
        },
        /**
         * 初始化ogt模型
         * @param {*} coordinate 配置参数
         * @param {*} vh v 垂直  h 水平
         * @param {*} nf n 盲区距离  f 探测距离
         */
        initContentOgt(coordinate, vh, nf) {
            let r = 0, deg = 0, deg1 = 0, rate = 1;
            // let a = 100 / (this.scale / 0.6);
            let a = 1;

            let maxR = 10000;

            // 10000为预估 超过的话ThreeBSP会报内存溢出
            // 若探测距离超出最大值，则默认为10000，盲区距离按比例展示
            if ((coordinate.farDistance * a) > maxR) {
                if (nf === 'n') {
                    rate = (coordinate.farDistance * a) / maxR;
                    r = (coordinate.nearDistance * a) / rate;
                } else {
                    r = maxR - 3;
                }
            } else {
                if (nf === 'n') {
                    r = coordinate.nearDistance * a;
                } else {
                    r = coordinate.farDistance * a;
                }
            }

            if (vh === 'v') {
                deg = coordinate.fovVBottom;
                deg1 = coordinate.fovVTop;
            } else {
                deg = coordinate.fovHRight;
                deg1 = coordinate.fovHLeft;
            }

            if (deg == 0) deg = 1
            if (deg1 == 0) deg1 = 1

            // 180°时融合有问题
            // if ((deg + deg1) % 180 === 0) {
            //     if (deg > 1) {
            //         deg = deg - 0.1;
            //     } else {
            //         deg1 = deg1 - 0.1;
            //     }
            // }


            let phiStart = Math.PI * ((90 - deg) / 180),
                phiLength = Math.PI * (deg / 180),
                thetaStart = 0,
                thetaLength = Math.PI;

            const geometry = new THREE.SphereGeometry(
                r, // radius — 球体半径，默认为1
                32, // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32
                16, // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16
                phiStart, // phiStart — 指定水平（经线）起始角度，默认值为0
                phiLength, // phiLength — 指定水平（经线）扫描角度的大小，默认值为 Math.PI * 2
                thetaStart, // thetaStart — 指定垂直（纬线）起始角度，默认值为0
                thetaLength // thetaLength — 指定垂直（纬线）扫描角度大小，默认值为 Math.PI
            );
            const material = new THREE.MeshBasicMaterial({ color: 0xff00ff, side: THREE.DoubleSide });

            const sphere = new THREE.Mesh(geometry, material); // 右 下




            let phiStart0 = Math.PI * (90 / 180),
                phiLength0 = Math.PI * (deg1 / 180),
                thetaStart0 = 0,
                thetaLength0 = Math.PI;

            const geometry0 = new THREE.SphereGeometry(
                r, // radius — 球体半径，默认为1
                32, // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32
                16, // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16
                phiStart0, // phiStart — 指定水平（经线）起始角度，默认值为0
                phiLength0, // phiLength — 指定水平（经线）扫描角度的大小，默认值为 Math.PI * 2
                thetaStart0, // thetaStart — 指定垂直（纬线）起始角度，默认值为0
                thetaLength0 // thetaLength — 指定垂直（纬线）扫描角度大小，默认值为 Math.PI
            );
            const material0 = new THREE.MeshBasicMaterial({ color: 0xff00ff, side: THREE.DoubleSide });

            const sphere0 = new THREE.Mesh(geometry0, material0); // 左 上



            const geometry1 = new THREE.CircleGeometry(
                r, // radius — 圆形的半径，默认值为1
                32, // segments — 分段（三角面）的数量，最小值为3，默认值为32
                0, // thetaStart — 第一个分段的起始角度，默认为0。（three o'clock position）
                Math.PI // thetaLength — 圆形扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆
            );

            const material1 = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });
            const circle1 = new THREE.Mesh(geometry1, material1); // left top



            const geometry2 = new THREE.CircleGeometry(
                r, // radius — 圆形的半径，默认值为1
                32, // segments — 分段（三角面）的数量，最小值为3，默认值为32
                0, // thetaStart — 第一个分段的起始角度，默认为0。（three o'clock position）
                Math.PI // thetaLength — 圆形扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆
            );

            const material2 = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });
            const circle2 = new THREE.Mesh(geometry2, material2); // right bottom



            if (vh === 'v') {
                sphere.rotateZ(Math.PI * 0.5);
                sphere0.rotateZ(Math.PI * 0.5);
                circle1.rotateX(Math.PI * ((90 - deg1) / 180));
                circle2.rotateX(-phiStart - Math.PI);

                if (nf === 'n') {
                    this.x2 = new ThreeBSP(sphere);
                    this.y2 = new ThreeBSP(circle1);
                    this.z2 = new ThreeBSP(circle2);
                    this.w2 = new ThreeBSP(sphere0);
                } else {
                    this.a2 = new ThreeBSP(sphere);
                    this.b2 = new ThreeBSP(circle1);
                    this.c2 = new ThreeBSP(circle2);
                    this.d2 = new ThreeBSP(sphere0);
                }
            } else {
                circle1.rotateZ(Math.PI * -0.5);
                circle1.rotateX(Math.PI * ((90 - deg1) / 180));
                circle2.rotateZ(Math.PI * 0.5);
                circle2.rotateX(phiStart);

                if (nf === 'n') {
                    this.x1 = new ThreeBSP(sphere);
                    this.y1 = new ThreeBSP(circle1);
                    this.z1 = new ThreeBSP(circle2);
                    this.w1 = new ThreeBSP(sphere0);
                } else {
                    this.a1 = new ThreeBSP(sphere);
                    this.b1 = new ThreeBSP(circle1);
                    this.c1 = new ThreeBSP(circle2);
                    this.d1 = new ThreeBSP(sphere0);
                }
            }


            if (deg + deg1 >= 360) {
                const sphere1 = new THREE.SphereGeometry(
                    r, // radius — 球体半径，默认为1
                    32, // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32
                    16, // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16
                    0, // phiStart — 指定水平（经线）起始角度，默认值为0
                    Math.PI * 2, // phiLength — 指定水平（经线）扫描角度的大小，默认值为 Math.PI * 2
                    0, // thetaStart — 指定垂直（纬线）起始角度，默认值为0
                    Math.PI // thetaLength — 指定垂直（纬线）扫描角度大小，默认值为 Math.PI
                );

                this.a1 = new ThreeBSP(sphere1);
            }
        },
        initContentOgt1(coordinate) {
            let far = coordinate.farDistance,
                near = coordinate.nearDistance,
                fv = coordinate.fovVTop,
                fb = coordinate.fovVBottom;

            if (fv >= 90) fv = 89.9
            if (fb >= 90) fb = 89.9

            let r = Math.cos(THREE.MathUtils.degToRad(fv)) * far,
                h = Math.sin(THREE.MathUtils.degToRad(fv)) * far,
                r1 = Math.cos(THREE.MathUtils.degToRad(fb)) * far,
                h1 = Math.sin(THREE.MathUtils.degToRad(fb)) * far

            // 上方圆锥
            const cone1 = new THREE.ConeGeometry(
                r, // radius — 圆锥底部的半径，默认值为1
                h, // height — 圆锥的高度，默认值为1
                32, // radialSegments — 圆锥侧面周围的分段数，默认为32
                1, // heightSegments — 圆锥侧面沿着其高度的分段数，默认值为1
                false, // openEnded — 一个Boolean值，指明该圆锥的底面是开放的还是封顶的。默认值为false，即其底面默认是封顶的
                0, // thetaStart — 第一个分段的起始角度，默认为0
                2 * Math.PI, // thetaLength — 圆锥底面圆扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆锥
            );

            cone1.translate(0, -h / 2, 0);
            cone1.rotateX(Math.PI * 1);

            // 下方圆锥
            const cone2 = new THREE.ConeGeometry(
                r1, // radius — 圆锥底部的半径，默认值为1
                h1, // height — 圆锥的高度，默认值为1
                32, // radialSegments — 圆锥侧面周围的分段数，默认为32
                1, // heightSegments — 圆锥侧面沿着其高度的分段数，默认值为1
                false, // openEnded — 一个Boolean值，指明该圆锥的底面是开放的还是封顶的。默认值为false，即其底面默认是封顶的
                0, // thetaStart — 第一个分段的起始角度，默认为0
                2 * Math.PI, // thetaLength — 圆锥底面圆扇区的中心角，通常被称为“θ”（西塔）。默认值是2*Pi，这使其成为一个完整的圆锥
            );
            cone2.translate(0, -h1 / 2, 0);


            const circle1 = new THREE.CircleGeometry(r, 32);
            circle1.rotateX(Math.PI * 0.5);
            circle1.translate(0, h, 0);

            const circle2 = new THREE.CircleGeometry(r1, 32);
            circle2.rotateX(Math.PI * 0.5);
            circle2.translate(0, -h1, 0);


            if (near > 0) {
                const sphere1 = new THREE.SphereGeometry(
                    near, // radius — 球体半径，默认为1
                    32, // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32
                    16, // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16
                    0, // phiStart — 指定水平（经线）起始角度，默认值为0
                    Math.PI * 2, // phiLength — 指定水平（经线）扫描角度的大小，默认值为 Math.PI * 2
                    0, // thetaStart — 指定垂直（纬线）起始角度，默认值为0
                    Math.PI // thetaLength — 指定垂直（纬线）扫描角度大小，默认值为 Math.PI
                );
                this.z1 = new ThreeBSP(sphere1);
            }


            this.x1 = new ThreeBSP(circle1); // up
            this.y1 = new ThreeBSP(cone1);
            this.x2 = new ThreeBSP(circle2); // down
            this.y2 = new ThreeBSP(cone2);
        },
        initSensorBSP(position, rotation, type, index, canMove) {
            let sensorId = this.configList[type][index].sensorId;

            if (!this.bsp[type][sensorId]) {
                let coordinate = this.allSensor[type].find(
                    (i) => i.id === sensorId
                );

                if (!coordinate) {
                    coordinate = {
                        farDistance: 60,
                        nearDistance: 0,
                        fovH: 60,
                        fovV: 60,
                        fovHLeft: 60,
                        fovVTop: 60,
                        fovHRight: 60,
                        fovVBottom: 60,
                    };
                }

                // console.log(coordinate)

                if (coordinate.farDistance <= 0 || coordinate.farDistance <= coordinate.nearDistance) return;

                let color = null;

                if (type === "camera") {
                    color = 0x0000ff;
                } else if (type === "ogt") {
                    color = 0x008000;
                } else if (type === "lidar") {
                    color = 0xff4500;
                } else {
                    color = 0x0000ff;
                }

                // let m = new THREE.MeshPhongMaterial({
                //     emissive: color,
                //     color: 0x4c4c4c,
                //     transparent: true,
                //     // opacity: 0.3,
                //     // lightMapIntensity: 0.1,
                //     side: THREE.DoubleSide,
                // });

                // let m = new THREE.MeshBasicMaterial({ color: 0xffaa00, transparent: true, side: THREE.DoubleSide, blending: THREE.AdditiveBlending });
                // let m = new THREE.MeshPhongMaterial({ emissive: color, color: 0x4c4c4c, wireframe: true, transparent: true, opacity: 0.3, side: THREE.DoubleSide });
                let m = new THREE.MeshPhongMaterial({ emissive: color, color: 0x4c4c4c, transparent: true, opacity: 0.3, side: THREE.DoubleSide });

                // showFullScreenLoading();
                // console.log(showFullScreenLoading);

                // console.log(6);

                // const loading = this.$loading({
                //     lock: true,
                //     text: "模型加载中，请稍等...",
                //     // spinner: "el-icon-loading",
                //     background: "rgba(0, 0, 0, 0.2)",
                // });

                // this.loadingFull = true;

                coordinate.farDistance = coordinate.farDistance / 100;
                coordinate.nearDistance = coordinate.nearDistance / 100;

                if (type != "ogt") {
                    if (coordinate.fovH <= 0 || coordinate.fovV <= 0) return;

                    this.toCube(coordinate, m);
                } else {
                    if ((coordinate.fovHLeft + coordinate.fovHRight <= 0) || (coordinate.fovVTop + coordinate.fovVBottom <= 0)) return;

                    this.toCubeOgt(coordinate, m);
                }
                // console.log(66);
                // loading.close();
                // tryHideFullScreenLoading();
                // console.log(666);

                this.bsp[type][sensorId] = this.cube;
            } else {
                this.cube = this.bsp[type][sensorId];
            }

            // 为了修复半径过大导致bsp死循环，所以先缩小半径，渲染出mesh后再放大
            let a = (100 / (this.scale / 0.6)) * 16.5;

            this.cube.scale.set(a, a, a);


            if (position) {
                this.cube.position.x = position.x;
                this.cube.position.y = position.y;
                this.cube.position.z = position.z;
            }

            if (canMove) {
                this.cube.name = this.geometryName || "cube";

                if (rotation) {
                    this.cube.rotateX(rotation.x);
                    this.cube.rotateY(rotation.y);
                    this.cube.rotateZ(rotation.z);
                }

                if (this.transformControls) {
                    this.transformControls.attach(this.cube);
                }
            } else {
                if (rotation) {
                    this.cube.rotation.set(
                        (rotation.x * Math.PI) / 180,
                        (rotation.y * Math.PI) / 180,
                        (rotation.z * Math.PI) / 180
                    );
                }

                this.cube.name = this.geometryName || "cubeA";
                this.cacheList.push(this.cube);
            }

            this.scene.add(this.cube);
        },
        toCube0(coordinate, m) {
            let { fovH, fovV, nearDistance } = coordinate;

            this.initContent0(coordinate, 'h', 'f');
            this.initContent0(coordinate, 'v', 'f');

            if (nearDistance > 0) {
                // 带盲区
                this.initContent0(coordinate, 'h', 'n');
                this.initContent0(coordinate, 'v', 'n');

                // 有至少一个方向是等于360的
                if (fovH >= 180 || fovV >= 180) {
                    if (fovH >= 180 && fovV < 180) {
                        if (fovV <= 90) {
                            this.cube = this.a2.subtract(this.b2).intersect(this.c2).subtract(this.x2.subtract(this.y2).intersect(this.z2)).toMesh(m);
                        } else {
                            this.cube = this.a2.subtract(this.b2.subtract(this.c2)).subtract(this.x2.subtract(this.y2.subtract(this.z2))).toMesh(m);
                        }
                    } else if (fovH < 180 && fovV >= 180) {
                        if (fovH <= 90) {
                            this.cube = this.a1.subtract(this.b1).subtract(this.c1).subtract(this.x1.subtract(this.y1).subtract(this.z1)).toMesh(m);
                        } else {
                            this.cube = this.a1.subtract(this.b1.intersect(this.c1)).subtract(this.x1.subtract(this.y1.intersect(this.z1))).toMesh(m);
                        }
                    } else if (fovH >= 180 && fovV >= 180) {
                        this.cube = this.a1.toMesh(m);
                    }
                } else {
                    if (fovH <= 90 && fovV <= 90) {
                        // 都小于90
                        this.cube = this.a1.subtract(this.b1).subtract(this.c1).intersect(this.a2.subtract(this.b2).intersect(this.c2))
                            .subtract(this.x1.subtract(this.y1).subtract(this.z1).intersect(this.x2.subtract(this.y2).intersect(this.z2))).toMesh(m);
                    } else if (fovH > 90 && fovV <= 90) {
                        // h大于90 v小于90
                        // this.cube = this.a1.subtract(this.b1.intersect(this.c1)).intersect(this.a2.subtract(this.b2).intersect(this.c2))
                        // .subtract(this.x1.subtract(this.y1.intersect(this.z1)).intersect(this.x2.subtract(this.y2).intersect(this.z2))).toMesh(m);
                        this.cube = this.a2.subtract(this.b2).intersect(this.c2).subtract(this.x2.subtract(this.y2).intersect(this.z2)).toMesh(m);
                    } else if (fovH <= 90 && fovV > 90) {
                        // h小于90 v大于90
                        // this.cube = this.a1.subtract(this.b1).subtract(this.c1).intersect(this.a2.subtract(this.b2.subtract(this.c2)))
                        //     .subtract(this.x1.subtract(this.y1).subtract(this.z1).intersect(this.x2.subtract(this.y2.subtract(this.z2)))).toMesh(m);
                        this.cube = this.a1.subtract(this.b1).subtract(this.c1).subtract(this.x1.subtract(this.y1).subtract(this.z1)).toMesh(m);
                    } else if (fovH > 90 && fovV > 90) {
                        // 都大于90
                        this.cube = this.a1.subtract(this.b1.intersect(this.c1)).intersect(this.a2.subtract(this.b2.subtract(this.c2)))
                            .subtract(this.x1.subtract(this.y1.intersect(this.z1)).intersect(this.x2.subtract(this.y2.subtract(this.z2)))).toMesh(m);
                    }
                }
            } else {
                // 有至少一个方向是等于360的
                if (fovH >= 180 || fovV >= 180) {
                    if (fovH >= 180 && fovV < 180) {
                        if (fovV <= 90) {
                            this.cube = this.a2.subtract(this.b2).intersect(this.c2).toMesh(m);
                        } else {
                            this.cube = this.a2.subtract(this.b2.subtract(this.c2)).toMesh(m);
                        }
                    } else if (fovH < 180 && fovV >= 180) {
                        if (fovH <= 90) {
                            this.cube = this.a1.subtract(this.b1).subtract(this.c1).toMesh(m);
                        } else {
                            this.cube = this.a1.subtract(this.b1.intersect(this.c1)).toMesh(m);
                        }
                    } else if (fovH >= 180 && fovV >= 180) {
                        this.cube = this.a1.toMesh(m);
                    }
                } else {
                    if (fovH <= 90 && fovV <= 90) {
                        // 都小于90
                        this.cube = this.a1.subtract(this.b1).subtract(this.c1).intersect(this.a2.subtract(this.b2).intersect(this.c2)).toMesh(m);
                    } else if (fovH > 90 && fovV <= 90) {
                        // h大于90 v小于90
                        // this.cube = this.a1.subtract(this.b1.intersect(this.c1)).intersect(this.a2.subtract(this.b2).intersect(this.c2)).toMesh(m);
                        this.cube = this.a2.subtract(this.b2).intersect(this.c2).toMesh(m);
                    } else if (fovH <= 90 && fovV > 90) {
                        // h小于90 v大于90
                        // this.cube = this.a1.subtract(this.b1).subtract(this.c1).intersect(this.a2.subtract(this.b2.subtract(this.c2))).toMesh(m);
                        this.cube = this.a1.subtract(this.b1).subtract(this.c1).toMesh(m);
                    } else if (fovH > 90 && fovV > 90) {
                        // 都大于90
                        this.cube = this.a1.subtract(this.b1.intersect(this.c1)).intersect(this.a2.subtract(this.b2.subtract(this.c2))).toMesh(m);
                    }
                }
            }


            this.a1 = null;
            this.b1 = null;
            this.c1 = null;
            this.d1 = null;
            this.a2 = null;
            this.b2 = null;
            this.c2 = null;
            this.d2 = null;
            this.x1 = null;
            this.y1 = null;
            this.z1 = null;
            this.w1 = null;
            this.x2 = null;
            this.y2 = null;
            this.z2 = null;
            this.w2 = null;
        },
        toCube(coordinate, m) {
            let { fovH, fovV, nearDistance } = coordinate;

            this.initContent0(coordinate, 'h', 'f');
            // this.initContent0(coordinate, 'v', 'f');

            this.initContent01(coordinate);


            // 水平小于等于180
            if (fovH <= 180) {
                // 带盲区 
                if (nearDistance > 0) {
                    this.cube = this.a1.subtract(this.b1).subtract(this.c1)
                        .subtract(this.x1).subtract(this.y1).intersect(this.x2).subtract(this.y2).subtract(this.z1)
                        .toMesh(m);
                } else {
                    this.cube = this.a1.subtract(this.b1).subtract(this.c1)
                        .subtract(this.x1).subtract(this.y1).intersect(this.x2).subtract(this.y2)
                        .toMesh(m);
                }
            } else if (fovH > 180 && fovH < 360) {
                // 180-360之间
                if (nearDistance > 0) {
                    this.cube = this.a1.subtract(this.b1.intersect(this.c1))
                        .subtract(this.x1).subtract(this.y1).subtract(this.y2).intersect(this.x2).subtract(this.z1)
                        .toMesh(m);
                } else {
                    this.cube = this.a1.subtract(this.b1.intersect(this.c1))
                        .subtract(this.x1).subtract(this.y1).subtract(this.y2).intersect(this.x2)
                        .toMesh(m);
                }
            } else {
                // 大于等于360
                if (nearDistance > 0) {
                    this.cube = this.a1
                        .subtract(this.x1).subtract(this.y1).subtract(this.y2).intersect(this.x2).subtract(this.z1)
                        .toMesh(m);
                } else {
                    this.cube = this.a1
                        .subtract(this.x1).subtract(this.y1).subtract(this.y2).intersect(this.x2)
                        .toMesh(m);
                }
            }


            this.a1 = null;
            this.b1 = null;
            this.c1 = null;
            this.d1 = null;
            this.a2 = null;
            this.b2 = null;
            this.c2 = null;
            this.d2 = null;
            this.x1 = null;
            this.y1 = null;
            this.z1 = null;
            this.w1 = null;
            this.x2 = null;
            this.y2 = null;
            this.z2 = null;
            this.w2 = null;
        },
        toCubeOgt0(coordinate, m) {
            let { fovHLeft, fovHRight, fovVTop, fovVBottom, nearDistance } = coordinate;

            this.initContentOgt(coordinate, 'h', 'f');
            this.initContentOgt(coordinate, 'v', 'f');

            if (nearDistance > 0) {
                // 带盲区
                this.initContentOgt(coordinate, 'h', 'n');
                this.initContentOgt(coordinate, 'v', 'n');

                // 有至少一个方向是大于360的
                if ((fovHLeft + fovHRight >= 360) || (fovVTop + fovVBottom >= 360)) {
                    if ((fovHLeft + fovHRight >= 360) && (fovVTop + fovVBottom < 360)) {
                        if (fovVTop + fovVBottom <= 180) {
                            this.cube = this.a2.intersect(this.d2).subtract(this.b2).intersect(this.c2)
                                .subtract(this.x2.intersect(this.w2).subtract(this.y2).intersect(this.z2))
                                .toMesh(m);
                        } else {
                            this.cube = this.a2.intersect(this.d2).subtract(this.b2.subtract(this.c2))
                                .subtract(this.x2.intersect(this.w2).subtract(this.y2.subtract(this.z2)))
                                .toMesh(m);
                        }
                    } else if ((fovHLeft + fovHRight < 360) && (fovVTop + fovVBottom >= 360)) {
                        if (fovHLeft + fovHRight <= 180) {
                            this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1)
                                .subtract(this.x1.intersect(this.w1).subtract(this.y1).subtract(this.z1))
                                .toMesh(m);
                        } else {
                            this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1))
                                .subtract(this.x1.intersect(this.w1).subtract(this.y1.intersect(this.z1)))
                                .toMesh(m);
                        }
                    } else if ((fovHLeft + fovHRight >= 360) && (fovVTop + fovVBottom >= 360)) {
                        this.cube = this.a1.intersect(this.d1).toMesh(m);
                    }
                } else {
                    // 不带盲区
                    if ((fovHLeft + fovHRight <= 180) && (fovVTop + fovVBottom <= 180)) {
                        // 相加都小于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1).intersect(this.a2.intersect(this.d2).subtract(this.b2).intersect(this.c2))
                            .subtract(this.x1.intersect(this.w1).subtract(this.y1).subtract(this.z1).intersect(this.x2.intersect(this.w2).subtract(this.y2).intersect(this.z2)))
                            .toMesh(m);
                    } else if ((fovHLeft + fovHRight > 180) && (fovVTop + fovVBottom <= 180)) {
                        // 左右相加大于180  上下相加小于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1)).intersect(this.a2.intersect(this.d2).subtract(this.b2).intersect(this.c2))
                            .subtract(this.x1.intersect(this.w1).subtract(this.y1.intersect(this.z1)).intersect(this.x2.intersect(this.w2).subtract(this.y2).intersect(this.z2)))
                            .toMesh(m);
                    } else if ((fovHLeft + fovHRight <= 180) && (fovVTop + fovVBottom > 180)) {
                        // 左右相加小于180  上下相加大于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1).intersect(this.a2.intersect(this.d2).subtract(this.b2.subtract(this.c2)))
                            .subtract(this.x1.intersect(this.w1).subtract(this.y1).subtract(this.z1).intersect(this.x2.intersect(this.w2).subtract(this.y2.subtract(this.z2))))
                            .toMesh(m);
                    } else if ((fovHLeft + fovHRight > 180) && (fovVTop + fovVBottom > 180)) {
                        // 相加都大于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1)).intersect(this.a2.intersect(this.d2).subtract(this.b2.subtract(this.c2)))
                            .subtract(this.x1.intersect(this.w1).subtract(this.y1.intersect(this.z1)).intersect(this.x2.intersect(this.w2).subtract(this.y2.subtract(this.z2))))
                            .toMesh(m);
                    }
                }
            } else {
                // 有至少一个方向是大于360的
                if ((fovHLeft + fovHRight >= 360) || (fovVTop + fovVBottom >= 360)) {
                    if ((fovHLeft + fovHRight >= 360) && (fovVTop + fovVBottom < 360)) {
                        if (fovVTop + fovVBottom <= 180) {
                            this.cube = this.a2.intersect(this.d2).subtract(this.b2).intersect(this.c2).toMesh(m);
                        } else {
                            this.cube = this.a2.intersect(this.d2).subtract(this.b2.subtract(this.c2)).toMesh(m);
                        }
                    } else if ((fovHLeft + fovHRight < 360) && (fovVTop + fovVBottom >= 360)) {
                        if (fovHLeft + fovHRight <= 180) {
                            this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1).toMesh(m);
                        } else {
                            this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1)).toMesh(m);
                        }
                    } else if ((fovHLeft + fovHRight >= 360) && (fovVTop + fovVBottom >= 360)) {
                        this.cube = this.a1.intersect(this.d1).toMesh(m);
                    }
                } else {
                    if ((fovHLeft + fovHRight <= 180) && (fovVTop + fovVBottom <= 180)) {
                        // 相加都小于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1).intersect(this.a2.intersect(this.d2).subtract(this.b2).intersect(this.c2)).toMesh(m);
                    } else if ((fovHLeft + fovHRight > 180) && (fovVTop + fovVBottom <= 180)) {
                        // 左右相加大于180  上下相加小于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1)).intersect(this.a2.intersect(this.d2).subtract(this.b2).intersect(this.c2)).toMesh(m);
                    } else if ((fovHLeft + fovHRight <= 180) && (fovVTop + fovVBottom > 180)) {
                        // 左右相加小于180  上下相加大于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1).intersect(this.a2.intersect(this.d2).subtract(this.b2.subtract(this.c2))).toMesh(m);
                    } else if ((fovHLeft + fovHRight > 180) && (fovVTop + fovVBottom > 180)) {
                        // 相加都大于180
                        this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1)).intersect(this.a2.intersect(this.d2).subtract(this.b2.subtract(this.c2))).toMesh(m);
                    }
                }
            }

            this.a1 = null;
            this.b1 = null;
            this.c1 = null;
            this.d1 = null;
            this.a2 = null;
            this.b2 = null;
            this.c2 = null;
            this.d2 = null;
            this.x1 = null;
            this.y1 = null;
            this.z1 = null;
            this.w1 = null;
            this.x2 = null;
            this.y2 = null;
            this.z2 = null;
            this.w2 = null;
        },
        toCubeOgt(coordinate, m) {
            let { fovHLeft, fovHRight, fovVTop, fovVBottom, nearDistance } = coordinate;

            if (fovHLeft + fovHRight > 360) {
                coordinate.fovHLeft = 180
                coordinate.fovHRight = 180
            }

            this.initContentOgt(coordinate, 'h', 'f');
            // this.initContentOgt(coordinate, 'v', 'f');

            this.initContentOgt1(coordinate);


            // 水平小于等于180
            if (fovHLeft + fovHRight <= 180) {
                // 带盲区 
                if (nearDistance > 0) {
                    this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1)
                        .subtract(this.x1).subtract(this.y1).intersect(this.x2).subtract(this.y2).subtract(this.z1)
                        .toMesh(m);
                } else {
                    this.cube = this.a1.intersect(this.d1).subtract(this.b1).subtract(this.c1)
                        .subtract(this.x1).subtract(this.y1).intersect(this.x2).subtract(this.y2)
                        .toMesh(m);
                }
                // 180-360之间
            } else if ((fovHLeft + fovHRight > 180) && (fovHLeft + fovHRight < 360)) {
                if (nearDistance > 0) {
                    this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1))
                        .subtract(this.x1).subtract(this.y1).subtract(this.y2).intersect(this.x2).subtract(this.z1)
                        .toMesh(m);
                } else {
                    this.cube = this.a1.intersect(this.d1).subtract(this.b1.intersect(this.c1))
                        .subtract(this.x1).subtract(this.y1).subtract(this.y2).intersect(this.x2)
                        .toMesh(m);
                }
            } else {
                // 大于等于360
                if (nearDistance > 0) {
                    this.cube = this.a1
                        .subtract(this.x1).subtract(this.y1).intersect(this.x2).subtract(this.y2).subtract(this.z1)
                        .toMesh(m);
                } else {
                    this.cube = this.a1
                        .subtract(this.x1).subtract(this.y1).intersect(this.x2).subtract(this.y2)
                        .toMesh(m);
                }
            }

            this.a1 = null;
            this.b1 = null;
            this.c1 = null;
            this.d1 = null;
            this.a2 = null;
            this.b2 = null;
            this.c2 = null;
            this.d2 = null;
            this.x1 = null;
            this.y1 = null;
            this.z1 = null;
            this.w1 = null;
            this.x2 = null;
            this.y2 = null;
            this.z2 = null;
            this.w2 = null;
        },
        // 处理轴对称物体
        initSenA(position, rotation, coordinate, r, r1, type, canMove) {
            let x = 0,
                y = 0,
                z = r;

            let a = coordinate.fovH,
                b = coordinate.fovV;

            if (a >= 90) a = 89.99;
            if (b >= 90) b = 89.99;

            x = Math.tan(THREE.MathUtils.degToRad(a)) * r;
            y = Math.tan(THREE.MathUtils.degToRad(b)) * r;

            let pointsArr = [];

            if (r1 === 0) {
                pointsArr = [
                    [0, 0, 0],
                    [x, y, z],
                    [x, -y, z],
                    [-x, -y, z],
                    [-x, y, z],
                ];
            } else {
                let x1 = 0,
                    y1 = 0,
                    z1 = r1;

                x1 = Math.tan(THREE.MathUtils.degToRad(a)) * r1;
                y1 = Math.tan(THREE.MathUtils.degToRad(b)) * r1;

                pointsArr = [
                    [x1, y1, z1],
                    [x1, -y1, z1],
                    [-x1, -y1, z1],
                    [-x1, y1, z1],
                    [x, y, z],
                    [x, -y, z],
                    [-x, -y, z],
                    [-x, y, z],
                ];
            }

            this.initMesh(position, rotation, pointsArr, type, canMove);
        },
        // 处理非轴对称物体
        initSenB(position, rotation, coordinateA, r, r1, type, canMove) {
            let x1 = 0,
                x2 = 0,
                y1 = 0,
                y2 = 0,
                z1 = r;

            let a = coordinateA.fovHLeft,
                b = coordinateA.fovVTop,
                c = coordinateA.fovHRight,
                d = coordinateA.fovVBottom;

            if (a >= 90) a = 89.99;
            if (b >= 90) b = 89.99;
            if (c >= 90) c = 89.99;
            if (d >= 90) d = 89.99;

            x1 = Math.tan(THREE.MathUtils.degToRad(a)) * r;
            y1 = Math.tan(THREE.MathUtils.degToRad(b)) * r;
            x2 = Math.tan(THREE.MathUtils.degToRad(c)) * r;
            y2 = Math.tan(THREE.MathUtils.degToRad(d)) * r;

            let pointsArr = [];

            if (r1 === 0) {
                pointsArr = [
                    [0, 0, 0],
                    [x1, y1, z1],
                    [x1, -y2, z1],
                    [-x2, -y2, z1],
                    [-x2, y1, z1],
                ];
            } else {
                let m1 = 0,
                    m2 = 0,
                    n1 = 0,
                    n2 = 0,
                    z2 = r1;

                m1 = Math.tan(THREE.MathUtils.degToRad(a)) * r1;
                n1 = Math.tan(THREE.MathUtils.degToRad(b)) * r1;
                m2 = Math.tan(THREE.MathUtils.degToRad(c)) * r1;
                n2 = Math.tan(THREE.MathUtils.degToRad(d)) * r1;

                pointsArr = [
                    [m1, n1, z2],
                    [m1, -n2, z2],
                    [-m2, -n2, z2],
                    [-m2, n1, z2],
                    [x1, y1, z1],
                    [x1, -y2, z1],
                    [-x2, -y2, z1],
                    [-x2, y1, z1],
                ];
            }

            this.initMesh(position, rotation, pointsArr, type, canMove);
        },
        // canMove 如果用于单独展示则可拖拽，用于全部预览则不可拖拽
        initMesh(position, rotation, pointsArr, type, canMove = false) {
            let points = pointsArr.map(
                (d) => new THREE.Vector3(d[0], d[1], d[2])
            );

            let color = null;
            if (type === "camera") {
                color = 0x0000ff;
            } else if (type === "ogt") {
                color = 0x008000;
            } else if (type === "lidar") {
                color = 0xff4500;
            } else {
                color = 0x0000ff;
            }

            let material = new THREE.MeshPhongMaterial({
                emissive: color,
                color: 0x4c4c4c,
                transparent: true,
                opacity: 0.3,
                lightMapIntensity: 0.1,
                side: THREE.DoubleSide,
            });

            let tixing = new ConvexGeometry(points);
            //通过ConvexGeometry凸包绘制一个梯台，当然也可以使用ExtrudeGeometry挤压几何体，
            this.cube = new THREE.Mesh(tixing, material);
            // this.cube.name = this.geometryName || "cube";

            if (position) {
                this.cube.position.x = position.x;
                this.cube.position.y = position.y;
                this.cube.position.z = position.z;
            }

            // if (rotation) {
            //     this.cube.rotateX(rotation.x);
            //     this.cube.rotateY(rotation.y);
            //     this.cube.rotateZ(rotation.z);
            // }

            if (canMove) {
                this.cube.name = this.geometryName || "cube";

                if (rotation) {
                    this.cube.rotateX(rotation.x);
                    this.cube.rotateY(rotation.y);
                    this.cube.rotateZ(rotation.z);
                }

                if (this.transformControls) {
                    this.transformControls.attach(this.cube);
                }
            } else {
                if (rotation) {
                    this.cube.rotation.set(
                        (rotation.x * Math.PI) / 180,
                        (rotation.y * Math.PI) / 180,
                        (rotation.z * Math.PI) / 180
                    );
                }

                this.cube.name = this.geometryName || "cubeA";
                this.cacheList.push(this.cube);
            }

            this.scene.add(this.cube);
        },
        initCar0(model) {
            if (this.car) {
                this.scene.remove(this.car);
                this.removeObj(this.car);
                this.car = null;
            }

            // showFullScreenLoading();

            var that = this;
            var loader = new GLTFLoader(); //创建一个FBX加载器

            const dracoLoader = new DRACOLoader(); //
            dracoLoader.setDecoderPath(`${this.publicPath}draco/`); // 设置public下的解码路径，注意最后面的/
            dracoLoader.setDecoderConfig({ type: "js" }); // 使用兼容性强的draco_decoder.js解码器
            dracoLoader.preload(); // 初始化_initDecoder 解码器
            loader.setDRACOLoader(dracoLoader); // gltfloader使用dracoLoader

            loader.load(
                model,
                function (obj) {
                    // tryHideFullScreenLoading();
                    that.$emit('loadingDone', 'carDone');

                    obj.scene.rotation.set(
                        (-90 * Math.PI) / 180,
                        0,
                        (-180 * Math.PI) / 180
                    );

                    let s = 0;
                    if (model.includes("928.glb")) {
                        s = that.scale / that.scaleRate;
                    } else {
                        s = that.scale;
                    }

                    let scale = 30 * s;
                    obj.scene.scale.set(scale, scale, scale);

                    that.scene.add(obj.scene);
                    that.car = obj.scene;
                },
                (xhr) => {
                    // console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
                },
                (error) => {
                    // tryHideFullScreenLoading();
                    that.$emit('loadingDone', 'carDone');
                    console.error(error);
                }
            );
        },
        // 初始化车模型
        initCar(model) {
            if (!model) return;
            if (!model.includes(".glb")) return;

            this.initCar0(model);
        },
        // 初始化
        init() {
            this.initScene();
            this.initCamera();
            this.initRenderer();
            this.initLight();

            this.controls = new OrbitControls(
                this.camera,
                this.renderer.domElement
            ); //创建控件对象
            this.controls.minDistance = 30;
            this.controls.maxDistance = 18000;
            this.controls.update();
        },
        animate() {
            this.raf = requestAnimationFrame(this.animate);
            this.renderer.render(this.scene, this.camera);
            if (this.transformControls) {
                this.transformControls.update();
            }

            this.controls.update();
        },
        onWindowResize() {
            this.camera.aspect =
                this.container.clientWidth / this.container.clientHeight;
            this.camera.updateProjectionMatrix();
            this.renderer.setSize(
                this.container.clientWidth,
                this.container.clientHeight
            );
        },
        go() {
            this.container = document.getElementById(
                "containerThreeProjectInfo"
            );
            this.init();
            this.animate();

            window.addEventListener("resize", this.onWindowResize);
        },
        /**
         * 每编辑一个传感器则重新生成对应的物体
         * @param {*} type 传感器类型
         * @param {*} index 该传感器所在数组下标
         * @param {*} onlyClear 是否只用来清空效果
         */
        reset(type, index = -1, onlyClear = false) {
            this.canDrag = true;

            if (this.cacheList.length > 0) {
                this.scene.remove(...this.cacheList);
                this.cacheList.forEach((i) => {
                    this.clearCache(i);
                });
                this.cacheList = [];
            }

            this.sensor = null;

            const obj1 = this.scene.getObjectByName("cube");
            if (obj1) {
                this.scene.remove(obj1);
            }

            this.xAngle = 0;
            this.yAngle = 0;
            this.zAngle = 0;

            if (this.dragControls) {
                this.dragControls.deactivate();
                this.dragControls.dispose();
                this.dragControls = null;
            }

            if (this.transformControls) {
                this.transformControls.detach();
            }

            // onlyClear若为true，表示只清除当前展示的东西，没有可增加展示的
            if (onlyClear) return;

            let z = +this.$parent.formA.sensorX || 0;
            let x = +this.$parent.formA.sensorY || 0;
            let y = +this.$parent.formA.sensorZ || 0;
            let h = +this.$parent.formA.sensorP || 0;
            let p = +this.$parent.formA.sensorR || 0;
            let r = +this.$parent.formA.sensorH || 0;

            x = Math.floor(x / this.rate);
            y = Math.floor(y / this.rate);
            z = Math.floor(z / this.rate);

            if (type != "gps") {
                setTimeout(() => {
                    this.initSensorBSP(
                        { x, y, z },
                        {
                            // x: (-90 * Math.PI) / 180,
                            x: 0,
                            y: 0,
                            z: 0,
                        },
                        type,
                        index,
                        true
                    );

                    setTimeout(() => {
                        this.initSensor({ x, y, z }, type, true);

                        const obj = this.scene.getObjectByName("cube");

                        if (!obj) return;

                        obj.position.x = x;
                        obj.position.y = y;
                        obj.position.z = z;

                        // obj.rotateX(0 * -1);
                        // obj.rotateX((h * Math.PI) / 180);
                        // this.xAngle = ((h - 90) * Math.PI) / 180;
                        this.xAngle = (h * Math.PI) / 180;

                        // obj.rotateY(0 * -1);
                        // obj.rotateY((p * Math.PI) / 180);
                        this.yAngle = (p * Math.PI) / 180;

                        // obj.rotateZ(0 * -1);
                        // obj.rotateZ((r * Math.PI) / 180);
                        this.zAngle = (r * Math.PI) / 180;
                        obj.rotation.set(this.xAngle, this.yAngle, this.zAngle);
                    }, 0);

                }, 100)
            } else {
                setTimeout(() => {
                    this.initSensor({ x, y, z }, type, true);

                    const obj = this.scene.getObjectByName("cube");

                    if (!obj) return;

                    obj.position.x = x;
                    obj.position.y = y;
                    obj.position.z = z;

                    // obj.rotateX(0 * -1);
                    // obj.rotateX((h * Math.PI) / 180);
                    // this.xAngle = ((h - 90) * Math.PI) / 180;
                    this.xAngle = (h * Math.PI) / 180;

                    // obj.rotateY(0 * -1);
                    // obj.rotateY((p * Math.PI) / 180);
                    this.yAngle = (p * Math.PI) / 180;

                    // obj.rotateZ(0 * -1);
                    // obj.rotateZ((r * Math.PI) / 180);
                    this.zAngle = (r * Math.PI) / 180;
                    obj.rotation.set(this.xAngle, this.yAngle, this.zAngle);
                }, 0);
            }

        },
        // 初始化传感器
        initSensor(
            pos = { x: 0, y: 0, z: 0 },
            type = "camera",
            canMove = false
        ) {
            let Loader = new MTLLoader(); //材质文件加载器
            let loader = new OBJLoader(); //obj加载器
            let that = this;
            let mtlUrl = "";
            let objUrl = "";

            if (type === "camera") {
                mtlUrl = `${that.publicPath}sensor/camera/camera.mtl`;
                objUrl = `${that.publicPath}sensor/camera/camera.obj`;
            } else if (type === "ogt") {
                mtlUrl = `${that.publicPath}sensor/ogt/millimeter_wave_radar.mtl`;
                objUrl = `${that.publicPath}sensor/ogt/millimeter_wave_radar.obj`;
            } else if (type === "lidar") {
                mtlUrl = `${that.publicPath}sensor/lidar/LIDAR.mtl`;
                objUrl = `${that.publicPath}sensor/lidar/LIDAR.obj`;
            } else if (type === "gps") {
                mtlUrl = `${that.publicPath}sensor/gps/lidar.mtl`;
                objUrl = `${that.publicPath}sensor/gps/lidar.obj`;
            }

            // if (type === "ogt") {
            //     showFullScreenLoading();
            // }

            if (type === "ogt") {
                if (this.ogtObj) {
                    let a = this.ogtObj;

                    a.position.set(pos.x, pos.y, pos.z);

                    if (canMove) {
                        this.sensor = a;
                    }

                    this.cacheList.push(a);

                    this.scene.add(a); //返回的组对象插入场景中
                    return;
                }


                // this.$emit('loadingDone', 'carStart');

                var loader1 = new GLTFLoader(); //创建一个FBX加载器

                loader1.load(
                    `${that.publicPath}sensor/ogt/ogt.glb`,
                    function (obj) {
                        // that.$emit('loadingDone', 'carDone');

                        that.cacheList.push(obj.scene);

                        that.ogtObj = obj.scene;

                        let s = that.scale;

                        let scale = 0.1;
                        obj.scene.scale.set(scale, scale, scale);

                        obj.scene.position.set(pos.x, pos.y, pos.z);
                        // obj.scene.name = "sensor";

                        if (canMove) {
                            that.sensor = obj.scene;
                        }

                        that.scene.add(obj.scene); //返回的组对象插入场景中
                    },
                    (xhr) => { },
                    (error) => {
                        // that.$emit('loadingDone', 'carDone');

                        console.error(error);
                    }
                );

                return
            }

            Loader.load(
                mtlUrl,
                function (materials) {
                    loader.setMaterials(materials);
                    loader.load(objUrl, function (obj) {
                        // if (type === "ogt") {
                        //     tryHideFullScreenLoading();
                        // }

                        that.cacheList.push(obj);
                        for (let i = 0; i < obj.children.length; i++) {
                            if (type === "camera") {
                                // obj.children[i].scale.set(0.8, 0.8, 0.8);
                                obj.children[i].scale.set(0.4, 0.4, 0.4);
                            } else if (type === "ogt") {
                                obj.children[i].scale.set(0.2, 0.2, 0.2);
                            } else if (type === "lidar") {
                                // obj.children[i].scale.set(0.1, 0.1, 0.1);
                                obj.children[i].scale.set(0.06, 0.06, 0.06);
                            } else if (type === "gps") {
                                obj.children[i].scale.set(40, 40, 40);
                            }
                        }
                        obj.position.set(pos.x, pos.y, pos.z);

                        if (canMove) {
                            that.sensor = obj;
                        }

                        that.scene.add(obj); //返回的组对象插入场景中
                    });
                },
                (xhr) => {
                    // console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
                },
                (error) => {
                    // if (type === "ogt") {
                    //     tryHideFullScreenLoading();
                    // }
                    console.error(error);
                }
            );
        },
        // 初始化已保存过的传感器
        initContentToShow(r, position, rotation, type) {
            var cubeGeometry = new THREE.ConeGeometry(
                r || 45 * this.scale,
                150 * this.scale,
                4,
                1,
                false
            );
            cubeGeometry.translate(0, -75 * this.scale, 0);

            let obj = {
                transparent: true,
                opacity: 0.3,
                lightMapIntensity: 0.1,
                color: 0x4c4c4c,
            };

            if (type === "camera") {
                obj.emissive = 0x000080;
            } else if (type === "ogt") {
                obj.emissive = 0x008000;
            } else if (type === "lidar") {
                obj.emissive = 0xff4500;
            } else if (type === "gps") {
                obj.emissive = 0x8a2be2;
            }

            var cubeMaterial = new THREE.MeshLambertMaterial(obj);

            var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            cube.name = this.geometryName || "cubeA";
            cube.rotateX((-90 * Math.PI) / 180);

            if (position) {
                cube.position.x = position.x;
                cube.position.y = position.y;
                cube.position.z = position.z;
            }
            if (rotation) {
                cube.rotation.set(
                    ((rotation.x - 90) * Math.PI) / 180,
                    (rotation.y * Math.PI) / 180,
                    (rotation.z * Math.PI) / 180
                );
            }
            this.cacheList.push(cube);
            this.scene.add(cube);
        },
        // 生成一种类型的全部显示器
        showSensor(sensor, type) {
            if (sensor && Array.isArray(sensor) && sensor.length > 0) {
                sensor.forEach((item, index) => {
                    /* this.initContentToShow(
                        null,
                        {
                            z: Math.floor(item.sensorX / this.rate || 0),
                            x: Math.floor(item.sensorY / this.rate || 0),
                            y: Math.floor(item.sensorZ / this.rate || 0),
                        },
                        {
                            x: +item.sensorP,
                            y: +item.sensorR,
                            z: +item.sensorH,
                        },
                        type
                    ); */

                    if (type != "gps") {
                        // this.initContent(
                        this.initSensorBSP(
                            {
                                z: Math.floor(item.sensorX / this.rate || 0),
                                x: Math.floor(item.sensorY / this.rate || 0),
                                y: Math.floor(item.sensorZ / this.rate || 0),
                            },
                            {
                                x: +item.sensorP,
                                y: +item.sensorR,
                                z: +item.sensorH,
                            },
                            type,
                            index,
                            false
                        );
                    }

                    this.initSensor(
                        {
                            z: Math.floor(item.sensorX / this.rate || 0),
                            x: Math.floor(item.sensorY / this.rate || 0),
                            y: Math.floor(item.sensorZ / this.rate || 0),
                        },
                        type,
                        false
                    );
                });
            }
        },
        // 显示全部
        showAll(configList) {
            // 避免重复加载所有传感器
            if (!this.canDrag) return;

            this.configList = configList;

            this.canDrag = false;
            if (this.cacheList.length > 0) {
                this.scene.remove(...this.cacheList);
                this.cacheList = [];
            }

            const obj = this.scene.getObjectByName("cube");
            if (obj) {
                this.scene.remove(obj);
            }

            if (this.dragControls) {
                this.dragControls.deactivate();
                this.dragControls.dispose();
                this.dragControls = null;
            }

            if (this.transformControls) {
                this.transformControls.detach();
            }

            this.showSensor(configList.camera, "camera");
            this.showSensor(configList.ogt, "ogt");
            this.showSensor(configList.lidar, "lidar");
            this.showSensor(configList.gps, "gps");
        },
        removeScene() {
            this.clearScene();
        },
        clearCache(item) {
            if (item.geometry && item.geometry.dispose) item.geometry.dispose();
            if (item.material && item.material.dispose) item.material.dispose();
        },
        clearScene() {
            this.removeObj(this.scene);
        },
        removeObj(obj) {
            let arr = obj.children.filter((x) => x);
            arr.forEach((item) => {
                if (item.children.length) {
                    this.removeObj(item);
                } else {
                    this.clearCache(item);
                    item.clear();
                }
            }),
                obj.clear();
            arr = null;
        },
    },

    mounted() {
        this.go();
    },
    destroyed() {
        window.removeEventListener("resize", this.onWindowResize);
        cancelAnimationFrame(this.raf);

        if (this.renderer) {
            this.renderer.renderLists.dispose();
            this.renderer.dispose();
            this.renderer.forceContextLoss();
            this.renderer.domElement = null;
            this.renderer.content = null;
            this.renderer = null;
        }

        if (this.dragControls) {
            this.dragControls.deactivate();
            this.dragControls.dispose();
            this.dragControls = null;
        }

        if (this.controls) {
            this.controls.dispose();
            this.controls = null;
        }

        if (this.transformControls) {
            this.transformControls.detach();
            this.transformControls.dispose();
            this.transformControls = null;
        }

        if (this.cacheList.length > 0) {
            this.cacheList = [];
        }

        this.clearScene();

        this.scene = null;
        this.camera = null;
        this.light = null;
        this.geometryName = null;
        this.mesh = null;
        this.cube = null;
        this.container = null;
        this.car = null;
        this.cubeTexture = null;
        this.raf = null;

        this.ogtObj = null;
        this.bsp = null;
        this.a1 = null;
        this.b1 = null;
        this.c1 = null;
        this.d1 = null;
        this.a2 = null;
        this.b2 = null;
        this.c2 = null;
        this.d2 = null;
        this.x1 = null;
        this.y1 = null;
        this.z1 = null;
        this.w1 = null;
        this.x2 = null;
        this.y2 = null;
        this.z2 = null;
        this.w2 = null;

        THREE.Cache.clear();
    },
};
</script>

<style lang="less" scoped>
#containerThreeProjectInfo {
    width: 100%;
    height: calc(100vh - 125px);
}
</style>
