tools

作者: 宿州刘德华 | 来源:发表于2020-07-23 10:25 被阅读0次
    /**
     * @class 工具类
     * @constructor
     */
    
    export let GeoInfoTools = {
    
    
        radiansPerDegree: Math.PI / 180.0,//角度转化为弧度(rad)
        degreesPerRadian: 180.0 / Math.PI,//弧度转化为角度
        /**
         * 错误
         */
        Error: {
            /**
             * 返回错误
             * @param msg
             * @returns {Error}
             */
            setError: function (msg) {
                if (msg) {
                    return new Error(msg);
                }
                return new Error("Error in Parameter!");
            },
        },
    
        /**
         * 计算
         */
        Count: {
    
            /**
             * 获取两点之间的距离
             * @param p1
             * @param p2
             * @returns {*}
             */
            countDistanceBetweenTwoPoints: function (p1, p2) {
                if (!p1 || !p2) {
                    throw GeoInfoTools.Error.setError();
                }
                p1 = GeoInfoTools.Transform.toCartesian(p1);
                p2 = GeoInfoTools.Transform.toCartesian(p2);
                return Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2) + Math.pow((p1.z - p2.z), 2));
            },
    
            /**
             * 点到线段的最短距离
             * @param a 直线上一个点
             * @param b 直线上另一个点
             * @param s 该点到ab的最短距离
             * @returns {number}
             */
            countPoint2LineDistance: function (a, b, s) {
                if (!a || !b || !s) {
                    throw GeoInfoTools.Error.setError();
                }
                a = GeoInfoTools.Transform.toCartesian(a);
                b = GeoInfoTools.Transform.toCartesian(b);
                s = GeoInfoTools.Transform.toCartesian(s);
                let ab = Math.sqrt(Math.pow((a.x - b.x), 2.0) + Math.pow((a.y - b.y), 2.0) + Math.pow((a.z - b.z), 2.0));
                let as = Math.sqrt(Math.pow((a.x - s.x), 2.0) + Math.pow((a.y - s.y), 2.0) + Math.pow((a.z - s.z), 2.0));
                let bs = Math.sqrt(Math.pow((s.x - b.x), 2.0) + Math.pow((s.y - b.y), 2.0) + Math.pow((s.z - b.z), 2.0));
                let cos_A = (Math.pow(as, 2.0) + Math.pow(ab, 2.0) - Math.pow(bs, 2.0)) / (2 * ab * as);
                let sin_A = Math.sqrt(1 - Math.pow(cos_A, 2.0));
                let t = ((a.x - s.x) * (a.x - b.x) + (a.y - s.y) * (a.y - b.y) + (a.z - s.z) * (a.z - b.z)) / (Math.pow((a.x - b.x), 2.0) + Math.pow((a.y - b.y), 2.0) + Math.pow((a.z - b.z), 2.0));
                if (t < 0) {
                    return as;
                } else if (t <= 1 && t >= 0) {
                    return as * sin_A;
                } else if (t > 1) {
                    return bs;
                }
            },
    
            /**
             * 求三角形面积;返回-1为不能组成三角形;
             * @param a
             * @param b
             * @param c
             * @returns {*}
             */
            countAreaByThreePoints: function (a, b, c) {
                if ((!a) || (!b) || (!c)) {
                    throw GeoInfoTools.Error.setError();
                }
                a = GeoInfoTools.Transform.toCartesian(a);
                b = GeoInfoTools.Transform.toCartesian(b);
                c = GeoInfoTools.Transform.toCartesian(c);
                let area = -1;
                let side = [];//存储三条边的长度;
                side[0] = Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2) + Math.pow(a.z - b.z, 2));
                side[1] = Math.sqrt(Math.pow(a.x - c.x, 2) + Math.pow(a.y - c.y, 2) + Math.pow(a.z - c.z, 2));
                side[2] = Math.sqrt(Math.pow(c.x - b.x, 2) + Math.pow(c.y - b.y, 2) + Math.pow(c.z - b.z, 2));
                //不能构成三角形;
                if (side[0] + side[1] <= side[2] || side[0] + side[2] <= side[1] || side[1] + side[2] <= side[0]) {
                    return area;
                }
                //利用海伦公式。area =sqr(p*(p-a)(p-b)(p-c));
                let p = (side[0] + side[1] + side[2]) / 2; //半周长;
                area = Math.sqrt(p * (p - side[0]) * (p - side[1]) * (p - side[2]));
                return area;
            },
    
            /**
             * 求多边形的面积
             * @param arr
             * @returns {*}
             */
            countArea: function (arr) {
                if ((!arr) || (arr.length < 3)) {
                    throw GeoInfoTools.Error.setError();
                } else {
                    let area = 0;
                    for (let i = 0; i < arr.length; i++) {
                        let j = (i + 1) % arr.length;
                        let p1 = arr[i], p2 = arr[j];
                        p1 = GeoInfoTools.Transform.toCartesian(p1);
                        p2 = GeoInfoTools.Transform.toCartesian(p2);
                        area += p1.x * p2.y;
                        area -= p1.y * p2.x;
                    }
                    area /= 2;
                    return Math.abs(area);
                }
    
            },
    
            /**
             * 计算向量叉乘
             * @param v1
             * @param v2
             * @returns {number}
             */
            countCrossMul: function (v1, v2) {
                if (!v1 || !v2) {
                    throw GeoInfoTools.Error.setError();
                }
                v1 = GeoInfoTools.Transform.toDegrees(v1);
                v2 = GeoInfoTools.Transform.toDegrees(v2);
                return v1.lng * v2.lat - v1.lat * v2.lng;
            },
    
        },
    
        /**
         * 转换
         */
        Transform: {
    
            /**
             * 世界坐标系转屏幕坐标
             * @param point
             * @param viewer
             */
            toWindowCoordinates: function (point, viewer) {
                if (viewer && point && point.x && point.y && point.z) {
                    return Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, point);
                } else if (viewer && point.lng && point.lat && point.alt) {
                    return Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, GeoInfoTools.Transform.toCartesianFromDegrees(point));
                } else {
                    throw GeoInfoTools.Error.setError();
                }
            },
    
            /**
             * 笛卡尔坐标转世界坐标
             * @param point
             */
            toDegreesFromCartesian: function (point) {
                if (point.x && point.y && point.z) {
                    let cartesian33 = new Cesium.Cartesian3(point.x, point.y, point.z);
                    let cartographic = Cesium.Cartographic.fromCartesian(cartesian33);
                    return {
                        lng: parseFloat(Cesium.Math.toDegrees(cartographic.longitude).toFixed(8)),
                        lat: parseFloat(Cesium.Math.toDegrees(cartographic.latitude).toFixed(8)),
                        alt: parseFloat(cartographic.height.toFixed(8))
                    };
                } else {
                    throw GeoInfoTools.Error.setError();
                }
            }
            ,
    
            /**
             * 世界坐标转笛卡尔坐标
             * @param point
             */
            toCartesianFromDegrees: function (point) {
                if (point.lng && point.lat) {
                    return Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.alt || 0);
                } else {
                    throw GeoInfoTools.Error.setError();
                }
            }
            ,
            /**
             * 转化成经纬度
             * @param point
             */
            toDegrees: function (point) {
                if (GeoInfoTools.Judge.isDegreesOrCartesian(point)) {
                    if (point.x && point.y && point.z) {
                        point = GeoInfoTools.Transform.toDegreesFromCartesian(point);
                    }
                    return point;
                } else {
                    throw GeoInfoTools.Error.setError();
                }
            },
    
            /**
             * 转化成笛卡尔坐标
             * @param point
             */
            toCartesian: function (point) {
                if (GeoInfoTools.Judge.isDegreesOrCartesian(point)) {
                    if (point.lng && point.lat) {
                        point = GeoInfoTools.Transform.toCartesianFromDegrees(point);
                    }
                    return point;
                } else {
                    throw GeoInfoTools.Error.setError();
                }
            },
    
    
            /**
             * 距离(米)转换为纬度  一米对应的纬度为定值
             * @param meter 距离多少米
             * @returns {number}
             */
            meter2Lat: function (meter) {
                let pi = Math.PI;
                let lngInMeter = (6371 * 2 * pi) / 360;
                return (meter / lngInMeter) / 1000;
            },
    
            /**
             * 距离(米)转换为经度  一米对应的经度与所在有关纬度
             * @param meter 距离
             * @param lat 所在纬度
             * @returns {number}
             */
            meter2Lng: function (meter, lat) {
                let pi = Math.PI;
                let latInMeter = (Math.cos(lat * pi / 180) * 6371 * 2 * pi) / 360;
                return (meter / latInMeter) / 1000;
            },
    
        },
    
        /**
         * 信息
         */
        Info: {
            /**
             * 获取当前相机姿态信息
             * 包括经度、纬度、高程、Heading、Pitch、Roll
             * @param viewer
             */
            getCameraInfo: function (viewer) {
                if (viewer && viewer.camera && viewer.camera.position && viewer.camera.heading) {
                    let p = GeoInfoTools.Transform.toDegrees(viewer.camera.position);
                    let heading = Cesium.Math.toDegrees(viewer.camera.heading);
                    let pitch = Cesium.Math.toDegrees(viewer.camera.pitch);
                    let roll = Cesium.Math.toDegrees(viewer.camera.roll);
                    return {
                        heading: parseFloat(heading).toFixed(5),
                        pitch: parseFloat(pitch).toFixed(5),
                        roll: parseFloat(roll).toFixed(5),
                        lng: parseFloat(p.lng).toFixed(7),
                        lat: parseFloat(p.lat).toFixed(7),
                        alt: parseFloat(p.alt).toFixed(2)
                    }
                } else {
                    throw GeoInfoTools.Error.setError();
                }
            }
        },
    
        Judge: {
            /**
             * 判断点是否在面的内部 不包含高程
             * @param point
             * @param coordinates
             * @returns {boolean}
             */
            isPointInPolygon: function (point, coordinates) {
                if ((!coordinates) || (!(coordinates instanceof Array)) || (coordinates.length < 3)) {
                    throw GeoInfoTools.Error.setError();
                }
                point = GeoInfoTools.Transform.toDegrees(point);
                let x = point.lng, y = point.lat;
                let inside = false;
                for (let i = 0, j = coordinates.length - 1; i < coordinates.length; j = i++) {
                    let vsi = GeoInfoTools.Transform.toDegrees(coordinates[i]),
                        vsj = GeoInfoTools.Transform.toDegrees(coordinates[j]);
                    let xi = vsi.lng, yi = vsi.lat;
                    let xj = vsj.lng, yj = vsj.lat;
                    let intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
                    if (intersect) {
                        inside = !inside;
                    }
                }
                return inside;
            },
    
            /**
             * 判断两条线段是否相交
             * @param p1
             * @param p2
             * @param p3
             * @param p4
             * @returns {boolean}
             */
            isLineCross: function (p1, p2, p3, p4) {
                p1 = GeoInfoTools.Transform.toDegrees(p1);
                p2 = GeoInfoTools.Transform.toDegrees(p2);
                p3 = GeoInfoTools.Transform.toDegrees(p3);
                p4 = GeoInfoTools.Transform.toDegrees(p4);
                let v1 = {lng: p1.lng - p3.lng, lat: p1.lat - p3.lat},
                    v2 = {lng: p2.lng - p3.lng, lat: p2.lat - p3.lat},
                    v3 = {lng: p4.lng - p3.lng, lat: p4.lat - p3.lat},
                    v = GeoInfoTools.Count.countCrossMul(v1, v3) * GeoInfoTools.Count.countCrossMul(v2, v3);
                v1 = {lng: p3.lng - p1.lng, lat: p3.lat - p1.lat};
                v2 = {lng: p4.lng - p1.lng, lat: p4.lat - p1.lat};
                v3 = {lng: p2.lng - p1.lng, lat: p2.lat - p1.lat};
                return (v <= 0 && GeoInfoTools.Count.countCrossMul(v1, v3) * GeoInfoTools.Count.countCrossMul(v2, v3) <= 0) ? true : false
            },
    
            /**
             * 判断该点是否是经纬度或者笛卡尔坐标
             * @param point
             */
            isDegreesOrCartesian: function (point) {
                if (!point) {
                    throw GeoInfoTools.Error.setError();
                }
                if (('number' === typeof point.x) && ('number' === typeof point.y) && ('number' === typeof point.z)) {
                    return true
                }
                if (('number' === typeof point.lng) && ('number' === typeof point.lat)) {
                    return true
                }
                return false;
            },
    
            /**
             * 判断线面是否相交
             * @param line
             * @param polygon
             * @constructor
             */
            isLineIntersectPolygon: function (line, polygon) {
                if (!line || !polygon || line.length !== 2 || polygon.length < 3) {
                    throw GeoInfoTools.Error.setError();
                }
                let firstPoint = GeoInfoTools.Transform.toDegrees(line[0]),
                    secondPoint = GeoInfoTools.Transform.toDegrees(line[1]), temp1, temp2,
                    result = false;
                for (let poly = 0; poly < polygon.length; poly++) {
                    if (poly == polygon.length - 1) {
                        temp1 = GeoInfoTools.Transform.toDegrees(polygon[poly]);
                        temp2 = GeoInfoTools.Transform.toDegrees(polygon[0]);
                    } else {
                        temp1 = GeoInfoTools.Transform.toDegrees(polygon[poly]);
                        temp2 = GeoInfoTools.Transform.toDegrees(polygon[poly + 1]);
                    }
                    if (GeoInfoTools.Judge.isLineCross(firstPoint, secondPoint, temp1, temp2)) {
                        return true;
                    }
                }
                return result;
            },
    
        },
    
        /**
         * 获取UUID
         * @returns {string}
         */
        getUUID: function () {
            let s = [];
            let hexDigits = "0123456789abcdef";
            for (let i = 0; i < 36; i++) {
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
            }
            s[14] = "4";
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
            s[8] = s[13] = s[18] = s[23] = "-";
            let uuid = s.join("");
            uuid = uuid.replace(/-/g, '');
            return uuid;
        },
    
        /**
         * 格式化日期格式 1900-01-01 12.12.12
         * @param date
         * @returns {string}
         * @constructor
         */
        formatDateTime: function (date) {
            if ((!date) || (!(date instanceof Date))) {
                throw GeoInfoTools.Error.setError();
            }
            let y = date.getFullYear();
            let m = date.getMonth() + 1;
            m = m < 10 ? ('0' + m) : m;
            let d = date.getDate();
            d = d < 10 ? ('0' + d) : d;
            let h = date.getHours();
            h = h < 10 ? ('0' + h) : h;
            let minute = date.getMinutes();
            minute = minute < 10 ? ('0' + minute) : minute;
            let second = date.getSeconds();
            second = second < 10 ? ('0' + second) : second;
            return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
        },
        /**
         * 调整Cesium3DTileset位置
         * @param tileset
         * @param params
         */
        update3dtilesMaxtrix: function (tileset, item) {
            let params = item.params;
            //旋转
            let mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
            let my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
            let mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
            let rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
            let rotationY = Cesium.Matrix4.fromRotationTranslation(my);
            let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
            //平移
            let position = Cesium.Cartesian3.fromDegrees(params.tx, params.ty, params.tz);
            let m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
            Cesium.Matrix4.multiply(m, rotationX, m);
            Cesium.Matrix4.multiply(m, rotationY, m);
            Cesium.Matrix4.multiply(m, rotationZ, m);
            // 赋值给tileset
            tileset._root.transform = m;
            if (item.alpha) {
                GeoInfoTools.setAlpha(tileset, item.alpha);
            }
        },
                updateTilePosition:function(tile, params) {
                    //旋转
                    let mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.position.heading));
                    let my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.position.pitch));
                    let mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.position.roll));
                    let rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
                    let rotationY = Cesium.Matrix4.fromRotationTranslation(my);
                    let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
                    //平移
                    let position = Cesium.Cartesian3.fromDegrees(params.position.lng, params.position.lat, params.position.alt);
                    let m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
                    Cesium.Matrix4.multiply(m, rotationX, m);
                    Cesium.Matrix4.multiply(m, rotationY, m);
                    Cesium.Matrix4.multiply(m, rotationZ, m);
                    //缩放
                    let scale = Cesium.Matrix4.fromUniformScale(params.scale);
                    Cesium.Matrix4.multiply(m, scale, m);
                    // 赋值给tileset
                    tile._root.transform = m;
                },
        /**
         * 获取当前实体的位置
         * @param entity
         * @returns {*}
         */
        getEntityPosition: function (entity) {
            return entity.position._value || Cesium.Property.getValueOrUndefined(entity.position, viewer.clock.currentTime || Cesium.JulianDate.now(), new Cesium.Cartesian3());
        },
        /**
         * 透明度
         * @param Cesium
         * @param tileset
         * @param al
         */
        setAlpha: function (tileset, al) {
            let alpha = parseFloat(al) / 100;
            let style = new Cesium.Cesium3DTileStyle({
                color: "color('white', " + alpha + ")",
                show: true
            });
            tileset.style = style;
        },
    
        /**
         *  销毁handler
         */
        handlerDestroy: function () {
            if (handler) {
                handler.destroy();
            }
        },
    
        /**
         * 计算 管线的管子的半径和边数
         * @param radius
         * @param itemp
         * @returns {Array}
         */
        computeCircleR: function (radius, itemp) {
            let result = [];
            for (let i = 0; i < 360; i += itemp) {
                let radians = Cesium.Math.toRadians(i);
                result.push(new Cesium.Cartesian2(radius * Math.sin(radians), radius * Math.cos(radians)));
            }
            return result;
        },
        /**
         * 点击按钮执行横断面分析的方法
         * @constructor
         */
        CroAn: function (minHeights, maxHeights, callback) {
            let minH = minHeights || -10, maxH = maxHeights || 100;
            GeoInfoTools.handlerDestroy();
            handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
            let positions = [];
            let options = {};
            let poly = undefined;
            viewer.entities.removeById('CrossAnalysis');
            let wallPoly = (function () {
                function _(positions) {
                    options = {
                        id: "CrossAnalysis",
                        wall: {
                            positions: [],
                            minimumHeights: [minH, minH],
                            material: Cesium.Color.fromCssColorString("#409ad5")
                        }
                    };
                    _.prototype._init()
                }
    
                _.prototype._init = function () {
                    let _update = function () {
                        let dp = [];
                        for (let i = 0; i < 2; i++) {
                            let cartesian3 = new Cesium.Cartesian3(positions[i].x, positions[i].y, positions[i].z);
                            let cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian3);
                            let lat = Cesium.Math.toDegrees(cartographic.latitude);
                            let lng = Cesium.Math.toDegrees(cartographic.longitude);
                            let alt = cartographic.height;
                            dp.push(lng);
                            dp.push(lat);
                            dp.push(maxH);
                        }
                        return Cesium.Cartesian3.fromDegreesArrayHeights(dp);
                    };
                    options.wall.positions = new Cesium.CallbackProperty(_update, false);
                    // let wallEntity = viewer.entities.getOrCreateEntity("CrossAnalysis");
                    // wallEntity.id = options.id;
                    // wallEntity.wall = options.wall;
                    viewer.entities.add(options)
                };
                return _;
            })();
            handler.setInputAction(function (movement) {
                let cartesian = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
                if (positions.length == 0) {
                    positions.push(cartesian.clone());
                }
                if (positions.length >= 3) {
                    handler.destroy();
                    // CrossAnalysis();
                }
                positions.push(cartesian);
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
            handler.setInputAction(function (movement) {
                let cartesian = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
                if (positions.length >= 3) {
                    handler.destroy();
                    // CrossAnalysis();
                } else if (positions.length >= 1) {
                    if (!Cesium.defined(poly)) {
                        poly = new wallPoly(positions);
                    } else {
                        positions.pop();
                        positions.push(cartesian);
                    }
                }
    
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
            handler.setInputAction(function (movement) {
                GeoInfoTools.handlerDestroy();
                CrossAnalysis(callback);
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
        },
        /**
         * 在canvas 上绘制横断面的信息
         * @param p
         */
        getCrossAnalysisResultToContext: function (p) {
            let maxAlt = 0;
            let minAlt = Infinity;
            p.forEach(function (data) {
                if (data.alt > maxAlt) {
                    maxAlt = data.alt;
                }
                if (data.alt < minAlt) {
                    minAlt = data.alt;
                }
            });
            maxAlt += 6;
            minAlt -= 3;
            let pixelPerMetre = 180 / (maxAlt - minAlt);
            let unitHeight = (maxAlt - minAlt) / 6;//最高的减去最低的除六
            // addDivCanvas()
            let canvas = document.getElementById('crossAnalysisResultCanvas'); /// 拿到画板
            let webWidth = 1920, webHeight = 948;//页面宽高
            let panelHeight = webHeight / 2, panelWidth = webWidth / 2;
            canvas.width = panelWidth;
            canvas.height = panelHeight + 50;
            let ctx = canvas.getContext('2d');   /// 拿到上下文
            // 四边框
            ctx.beginPath();   /// 绘制直线
            ctx.strokeStyle = 'black';   /// 设置线条的颜色
            ctx.lineWidth = 4;   /// 设置线条的宽度
            ctx.moveTo(10, 30);   /// 起点
            ctx.lineTo(panelWidth - 10, 30);    /// 终点
            ctx.lineTo(panelWidth - 10, panelHeight + 15);
            ctx.lineTo(10, panelHeight + 15);   /// 终点   /// 终点
            ctx.lineTo(10, 30);   /// 终点
            ctx.closePath();
            // 文字说明
            ctx.font = "20px Courier New";
            ctx.fillStyle = "black";
            ctx.fillText("横断面图", panelHeight - 40, 60);
            ctx.stroke();
            // 横纵坐标轴 以及文字
            ctx.font = "14px Courier New";   ///设置字体样式
            ctx.fillStyle = "black";   ///设置字体填充颜色
            ctx.strokeStyle = 'black';   /// 设置线条的颜色
            ctx.lineWidth = 1;   /// 设置线条的宽度
            ctx.beginPath();   /// 绘制直线
            let rectH = 32;
            let hTemp = 60;
            let rectW = 150;
            ctx.lineWidth = 1;
            //纵坐标 竖线
            ctx.moveTo(rectW, 130);
            ctx.lineTo(rectW, canvas.height - 35);
            for (let i = 0; i < canvas.height; i++) {
                if (i > 0 && i <= 7) {
                    let n = hTemp -= 10;
                    ctx.fillText((maxAlt - ((i - 1) * unitHeight)).toFixed(1) + "(m)", 80, rectH * i + 105);
                    ctx.moveTo(150, rectH * i + 100);
                    ctx.lineTo(165, rectH * i + 100);
                }
                if (i > 8 && i < 12) {
                    ctx.moveTo(10, rectH * i + 100);
                    ctx.lineTo(canvas.width - 10, rectH * i + 100);
                }
            }
            ctx.stroke();
            ctx.font = "15px Courier New";   ///设置字体样式
            ctx.fillStyle = "black";   ///设置字体填充颜色
            ctx.fillText("横截点高程(m)", 20, 410);
            ctx.fillText("间距(m)", 20, 440);
            ctx.fillText("管径(mm)", 20, 470);
            ctx.stroke();
            let CurveList = [];
            let realPoints = p;
            let unitDistance = (panelWidth - 300) / (realPoints.length);//根据相交的点数 计算间隔
            for (let k = 0; k < realPoints.length; k++) {
                // todo 管线信息调整
                let pipeDiameter = realPoints[k].pipeDiameter || 10;//canvas绘制的圆形的管径
                let pipeSpecification = realPoints[k].pipeSpecification || '1000';//规格
                let twoDistance;//两点之间的距离
                if (realPoints.length == 1) {
                    twoDistance = "";
                } else {
                    if (k != realPoints.length - 1) {
                        twoDistance = GeoInfoTools.Count.countDistanceBetweenTwoPoints(realPoints[k], realPoints[k + 1]).toFixed(3);
                    } else {
                        twoDistance = GeoInfoTools.Count.countDistanceBetweenTwoPoints(realPoints[k], realPoints[0]).toFixed(3);
                    }
                }
                CurveList.push([panelWidth - 230 - unitDistance * k, 310 - (parseFloat(realPoints[k].alt.toFixed(3)) - minAlt) * pixelPerMetre]);
                ctx.beginPath();
                //以点为中心 画圆
                ctx.arc(panelWidth - 230 - unitDistance * k, 310 - (realPoints[k].alt.toFixed(3) - minAlt) * pixelPerMetre, pipeDiameter, 0, Math.PI * 2, true);
                //写经纬度信息
                ctx.fillText("经度:" + realPoints[k].lng.toFixed(8), (panelWidth - 230 - unitDistance * k), 300 - (realPoints[k].alt.toFixed(3) - minAlt) * pixelPerMetre);
                ctx.fillText("纬度:" + realPoints[k].lat.toFixed(8), (panelWidth - 230 - unitDistance * k), 280 - (realPoints[k].alt.toFixed(3) - minAlt) * pixelPerMetre);
                ctx.fillText("高程:" + realPoints[k].alt.toFixed(3), (panelWidth - 230 - unitDistance * k), 260 - (realPoints[k].alt.toFixed(3) - minAlt) * pixelPerMetre);
                //管线高程 指点的高程
                ctx.fillText(realPoints[k].alt.toFixed(3), panelWidth - 230 - unitDistance * k, 410);
                //两点之间的间距 横截面为两个点的时候 可当作两点之间的距离
                ctx.fillText(twoDistance, panelWidth - 230 - unitDistance * k, 440);
                //管径规格
                ctx.fillText(pipeSpecification, panelWidth - 230 - unitDistance * k, 470);
                ctx.closePath();
                ctx.stroke();
                //竖直的虚线
                drawDashedLine(ctx, {
                    x: panelWidth - 230 - unitDistance * k,
                    y: 310 - (realPoints[k].alt.toFixed(3) - minAlt) * pixelPerMetre
                }, {
                    x: panelWidth - 230 - unitDistance * k,
                    y: 390
                }, [3, 3]);
                //水平的虚线
                drawDashedLine(ctx, {
                    x: panelWidth - 230 - unitDistance * k,
                    y: 310 - (realPoints[k].alt.toFixed(3) - minAlt) * pixelPerMetre
                }, {
                    x: 150,
                    y: 310 - (realPoints[k].alt.toFixed(3) - minAlt) * pixelPerMetre
                }, [3, 3]);
            }
    
            //连接横截面点 可以不使用
            // if(CurveList&&CurveList.length>0){
            //     if (CurveList.length == 1) {
            //         ctx.strokeStyle = "#060606";
            //         ctx.beginPath();
            //         ctx.arc(CurveList[0][0], CurveList[0][1], 1, 0, Math.PI * 2, true);
            //         ctx.stroke();
            //         ctx.closePath();
            //     } else if (CurveList.length > 1) {
            //         ctx.strokeStyle = "#060606";
            //         ctx.beginPath();
            //         ctx.moveTo(CurveList[0][0], CurveList[0][1]);
            //         for (let cl = 1; cl < CurveList.length; cl++) {
            //             ctx.lineTo(CurveList[cl][0], CurveList[cl][1]);
            //         }
            //         ctx.stroke();
            //         ctx.closePath();
            //     }
            // }
    
    
        },
        /**
         * 添加Cesium3DTileset
         * @param model_trans
         * @returns {*}
         */
        addCesium3DTileset: function (model_trans, view) {
            let Cesium3DTileset = new Cesium.Cesium3DTileset({
                url: model_trans.url,
                show: model_trans.show || true,
                scale: model_trans.scale
            });
            let tileset = view.scene.primitives.add(Cesium3DTileset);
            tileset.readyPromise.then(function (t) {
                GeoInfoTools.update3dtilesMaxtrix(tileset, model_trans);
            });
            return tileset;
        },
        /**
         * 根据范围来控制model的显示隐藏
         * @param show
         * @param area
         */
        showAreaEntiy: function (show, area) {
            let entities = viewer.entities.values;
            entities.forEach(function (item, index) {
                if (item.model && item.model._uri) {
                    let position = GeoInfoTools.getEntityPosition(item);
                    if (GeoInfoTools.Judge.isPointInPolygon(position, area)) {
                        item.show = show;
                    } else {
                        item.show = !show;
                    }
                } else {
                    item.show = false;
                }
            });
        },
        /**
         * 根据位置来自动旋转视角
         * @param viewOptions
         */
        roundExtentView: function (viewOptions) {
            if (viewOptions && viewOptions.position) {
                flyExtent(viewOptions);
            }
        },
        /**
         * 根据矩形区域来生成clippingPlanes,然后计算旋转视角
         * @param range
         * @param viewOptions
         */
        specialView: function (range, viewOptions) {
            let primitives = viewer.scene.primitives._primitives;
            primitives.forEach(function (item, index) {
                if (item._url && item._url.indexOf("tileset.json") > 0) {
                    let clippingPlanes = tilesetAddClippingPlanes(range, item);
                    item.clippingPlanes = clippingPlanes;
                }
            });
            viewOptions = {};
            viewOptions.position = Cesium.Cartesian3.fromDegrees((range[0].lng + range[2].lng) / 2, (range[0].lat + range[2].lat) / 2, 0);
            let dis = GeoInfoTools.Count.countDistanceBetweenTwoPoints(range[0], range[2]);
            if (dis) {
                viewOptions.distance = dis * 2;
            }
            flyExtent(viewOptions);
            GeoInfoTools.showAreaEntiy(true, range);
        },
    
        showExtent(extent) {
    
            let primitives = viewer.scene.primitives._primitives;
            primitives.forEach(function (item, index) {
                if (item._url && item._url.indexOf("tileset.json") > 0) {
                    let clippingPlanes = tilesetAddClippingPlanes(extent, item);
                    item.clippingPlanes = clippingPlanes;
                }
            });
            GeoInfoTools.showParticleSystems(false);
            GeoInfoTools.showAreaEntiy(true, extent);
        },
        showAll(){
            GeoInfoTools.showParticleSystems(true);
            let primitives = viewer.scene.primitives._primitives;
            primitives.forEach(function (item, index) {
                if (item._url && item._url.indexOf("tileset.json") > 0) {
                    if (item.clippingPlanes && item.clippingPlanes.unionClippingRegions) {
                        item.clippingPlanes.unionClippingRegions = false;
                    }
                }
    
            });
            //改变模型的显示隐藏
            let entities = viewer.entities.values;
            entities.forEach(function (item, index) {
                item.show = true;
            });
        },
        /**
         * 添加右键结束提醒
         * @param cartesian
         */
        addTip: function (cartesian) {
            if (cartesian && cartesian.x && cartesian.y) {
                let p = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, cartesian);
                if (document.getElementById("_____tip")) {
                    let divChild = document.getElementById("_____tip");
                    divChild.style.left = (p.x + 10) + "px";
                    divChild.style.top = (p.y + 10) + "px";
                } else {
                    let divChild = document.createElement("Div");
                    divChild.innerHTML = "<label style='color: #000000'> 右键结束 </label>";
                    divChild.id = "_____tip";
                    divChild.style.width = "75px";
                    divChild.style.left = (p.x + 10) + "px";
                    divChild.style.top = (p.y + 10) + "px";
                    divChild.style.height = "20px";
                    divChild.style.position = "absolute";
                    divChild.style.background = "#f2f4ff";
                    divChild.style.borderRadius = "5px";
                    divChild.style.show = "block";
                    divChild.style.textAlign = "center";
                    divChild.style.zIndex = "9999999999";
                    document.body.append(divChild);
                }
    
            }
        },
        /**
         * 删除右键提示提醒
         */
        clearTip: function () {
            let my = document.getElementById("_____tip");
            if (my != null) {
                my.parentNode.removeChild(my);
            }
        },
        /**
         * 改变模型的显示隐藏和颜色
         * @param item
         * @param show
         * @param color
         * @param alpha
         */
        changeEntityModelView: function (item, show, color, alpha) {
            if (typeof show === "boolean") {
                item.show = show;
            }
            item.model.color = Cesium.Color.fromCssColorString(color).withAlpha(parseFloat(alpha));
        },
    
        /**
         * 改变model和tiles的显示隐藏和样式
         * @param type
         * @param pickEntity
         */
        changeModelAndTileStyle: function (type, pickEntity) {
            let primitives = viewer.scene.primitives._primitives;
            let entities = viewer.entities.values;
            if (type) {
                primitives.forEach(function (item, index) {
                    GeoInfoTools.changeTileView(item, 'keep', '#67ADDF', 0.15)
                })
                entities.forEach(function (item, index) {
                    if (item.model && item.model._uri._value) {
                        if (pickEntity.id === item.id) {
                            item.model.color = Cesium.Color.WHITE.withAlpha(1);
                            item.model.colorBlendMode = Cesium.ColorBlendMode['MIX'];
                            item.model.lightColor = new Cesium.Cartesian3(40, 40, 0);
                        } else {
                            item.model.color = Cesium.Color.fromCssColorString('#67ADDF').withAlpha(0.15);
                            item.model.colorBlendMode = Cesium.ColorBlendMode['HIGHLIGHT'];
                            item.model.lightColor = new Cesium.Cartesian3(0, 0, 0);
                        }
    
                    }
                });
    
            } else {
                if (GeoInfoTools.pipeLineLabels instanceof Array && GeoInfoTools.pipeLineLabels.length > 0) {
                    GeoInfoTools.pipeLineLabels.forEach(function (item, index) {
                        viewer.entities.remove(item);
                    })
                }
                entities.forEach(function (item, index) {
                    if (item.model && item.model._uri._value) {
                        item.model.color = Cesium.Color.WHITE.withAlpha(1);
                        item.model.lightColor = new Cesium.Cartesian3(0, 0, 0);
                        item.model.colorBlendMode = Cesium.ColorBlendMode['HIGHLIGHT'];
                    }
                });
    
                primitives.forEach(function (item, index) {
                    if (item instanceof Cesium.Cesium3DTileset) {
                        if (item && item._url && item._url.indexOf("tile/pipeline/tileset.json") >= 0) {
                            item.tileVisible.removeEventListener(GeoInfoTools.changTileColor); //清除管线效果
                        }
                        GeoInfoTools.changeTileView(item, 'keep', '#ffffff', 1);
                    }
                })
            }
    
        },
        /***
         * 计算entity的时间和位置绑定
         * @param startTime
         * @param positions
         * @param uniformSpeed
         * @param speed
         * @param entity
         * @returns {Cesium.SampledPositionProperty}
         */
        computePositionProperty: function (startTime, positions, uniformSpeed, speed, entity) {
            if (!positions && positions.length < 2) {
                return
            }
            let property = new Cesium.SampledPositionProperty();
            let seconds = 0;
            //是否匀速
            if (uniformSpeed) {
                property.addSample(startTime, Cesium.Cartesian3.fromDegrees(positions[0].lng, positions[0].lat, positions[0].alt));
                positions.forEach(function (item, index) {
                    if (index < positions.length - 1) {
                        // GeoInfoTools.Count.countDistanceBetweenTwoPoints(positions[index], positions[index + 1]);
                        let p1 = Cesium.Cartesian3.fromDegrees(positions[index].lng, positions[index].lat, positions[index].alt);
                        let p2 = Cesium.Cartesian3.fromDegrees(positions[index + 1].lng, positions[index + 1].lat, positions[index + 1].alt);
                        let distance = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2) + Math.pow((p1.z - p2.z), 2));
                        seconds += (distance / speed);
                        // console.log(seconds, (distance / speed));
                        let time = Cesium.JulianDate.addSeconds(startTime, seconds, new Cesium.JulianDate);
                        let position = Cesium.Cartesian3.fromDegrees(positions[index + 1].lng, positions[index + 1].lat, positions[index + 1].alt);
                        // 添加位置,和时间对应
                        property.addSample(time, position);
                    }
                })
    
            } else {
                positions.forEach(function (item, index) {
                    let time = Cesium.JulianDate.addSeconds(startTime, item.seconds, new Cesium.JulianDate);
                    let position = Cesium.Cartesian3.fromDegrees(item.lng, item.lat, item.alt);
                    property.addSample(time, position);
                })
                seconds = positions[positions.length - 1].seconds;
            }
            if (entity) {
                entity.position = property;
                entity.orientation = new Cesium.VelocityOrientationProperty(property);
                entity.availability = new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
                    start: startTime,
                    stop: Cesium.JulianDate.addSeconds(startTime, seconds, new Cesium.JulianDate)
                })]);
            }
            return property;
        },
        /**
         * 添加管线的label 和billboard用于显示信息
         * @param options
         * @returns {void | ActiveX.IXMLDOMNamedNodeMap | number | IDBRequest<IDBValidKey> | DataTransferItem | Promise<void>}
         */
        addPipeLineExplain: function (options) {
            return viewer.entities.add({
                id: options.id || getUUID(),
                name: options.name || "",
                position: Cesium.Cartesian3.fromDegrees(options.position.lng, options.position.lat, options.position.alt),
                billboard: {
                    distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 300),
                    image: options.imageUrl,//'../images/billLine2.png',
                    show: true, // default
                    pixelOffset: new Cesium.Cartesian2(0, 10), // default: (0, 0)
                    eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0), // default
                    horizontalOrigin: Cesium.HorizontalOrigin.RIGHT, // default
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // default: CENTER
                    // color: Cesium.Color.YELLOW, // default: WHITE
                    // width: options.imageWidth || 300, // default: undefined
                    // height: options.imageHeight || 100 // default: undefined
                },
                label: {
                    position: Cesium.Cartesian3.fromDegrees(options.position.lng, options.position.lat, options.position.alt),
                    pixelOffset: new Cesium.Cartesian2(-140, -(options.imageWidth / 2)),
                    distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 300),
                    horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
                    fillColor: new Cesium.Color.fromCssColorString('#ffffff'),
                    font: '15px sans-serif',
                    outlineColor: new Cesium.Color.fromCssColorString('#000000'),
                    outlineWidth: 10,
                    text: options.text || ""
                }
            });
        },
        execution: undefined,
        pipeLineLabels: [],
        /**
         * 修改管线feature6、16的颜色和透明度
         * @param tile
         */
        changTileColor: function (tile) {
            let content = tile.content;
            let feature6 = content.getFeature(6);
            let feature16 = content.getFeature(16);
            feature6.color = Cesium.Color.fromCssColorString('rgba(20,166,255,0.5)');
            feature16.color = Cesium.Color.fromCssColorString('rgba(20,166,255,0.5)');
        },
        /**
         * 删除视角旋转
         */
        removeExecution: function () {
            if (GeoInfoTools.execution) {
                viewer.clock.onTick.removeEventListener(GeoInfoTools.execution);
            }
        }
    // end
    };
    
    
    /**
     * UUID
     * @returns {string}
     */
    function getUUID() {
        var s = [];
        var hexDigits = "0123456789abcdef";
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
        s[8] = s[13] = s[18] = s[23] = "-";
    
        var uuid = s.join("");
        return uuid;
    }
    
    /**
     * 旋转环视
     * @param options
     * @returns {TimeExecution}
     */
    function flyExtent(options) {
        let seconds = options.seconds || 120;
        let pitch = Cesium.Math.toRadians(options.pitch || -30);
        let angle = 360 / seconds;
        let distance = options.distance || 200;
        let startTime = Cesium.JulianDate.fromDate(new Date());
        let stopTime = Cesium.JulianDate.addSeconds(startTime, seconds, new Cesium.JulianDate());
        viewer.clock.startTime = startTime.clone();
        viewer.clock.stopTime = stopTime.clone();
        viewer.clock.currentTime = startTime.clone(); // 当前时间
        viewer.clock.clockRange = Cesium.ClockRange.CLAMPED; // 行为方式
        viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK; // 时钟设置为当前系统时间; 忽略所有其他设置。
        let initialHeading = viewer.camera.heading;
        GeoInfoTools.execution = function TimeExecution() {
            let delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime);
            let heading = Cesium.Math.toRadians(delTime * angle) + initialHeading;
            viewer.scene.camera.setView({
                destination: options.position, // 点的坐标
                orientation: {
                    heading: heading,
                    pitch: pitch,
                }
            });
            viewer.scene.camera.moveBackward(distance);
            // if (Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime) >= 0) {
            //     // viewer.clock.onTick.removeEventListener(execution);
            // }
        };
        viewer.clock.onTick.addEventListener(GeoInfoTools.execution);
        return GeoInfoTools.execution;
    }
    
    /**
     *为3dties添加裁剪面
     * @param range
     * @param tileset
     */
    function tilesetAddClippingPlanes(range, tileset) {
        if ((!range) || (!tileset) || (range.length < 4)) {
            return
        }
    
        function getInverseTransform(tileSet) {
            let transform = undefined;
            let tmp = tileSet.root.transform;
            if ((tmp && tmp.equals(Cesium.Matrix4.IDENTITY)) || !tmp) {
                // 如果root.transform不存在,则3DTiles的原点变成了boundingSphere.center
                transform = Cesium.Transforms.eastNorthUpToFixedFrame(tileSet.boundingSphere.center)
            } else {
                transform = Cesium.Matrix4.fromArray(tileSet.root.transform)
            }
            return Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4())
        }
    
        function getOriginCoordinateSystemPoint(point, inverseTransform) {
            let val = Cesium.Cartesian3.fromDegrees(point.lng, point.lat)
            return Cesium.Matrix4.multiplyByPoint(inverseTransform, val, new Cesium.Cartesian3(0, 0, 0))
        }
    
        function createPlane(p1, p2, inverseTransform) {
            // 将仅包含经纬度信息的p1,p2,转换为相应坐标系的cartesian3对象
            let p1C3 = getOriginCoordinateSystemPoint(p1, inverseTransform)
            let p2C3 = getOriginCoordinateSystemPoint(p2, inverseTransform)
            // 定义一个垂直向上的向量up
            let up = new Cesium.Cartesian3(0, 0, 10)
            //  right 实际上就是由p1指向p2的向量
            let right = Cesium.Cartesian3.subtract(p2C3, p1C3, new Cesium.Cartesian3())
            // 计算normal, right叉乘up,得到平面法向量,这个法向量指向right的右侧
            let normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3())
            normal = Cesium.Cartesian3.normalize(normal, normal)
            //由于已经获得了法向量和过平面的一点,因此可以直接构造Plane,并进一步构造ClippingPlane
            let planeTmp = Cesium.Plane.fromPointNormal(p1C3, normal)
            return Cesium.ClippingPlane.fromPlane(planeTmp)
        }
    
        let inverseTransform = getInverseTransform(tileset);
        let clippingPlanes = new Cesium.ClippingPlaneCollection({
            unionClippingRegions: true
        });
        for(let i=0;i<range.length;i++){
    
            if(i===range.length-1){
                clippingPlanes.add(createPlane(range[range.length-1], range[0], inverseTransform));
            }else {
                clippingPlanes.add(createPlane(range[i], range[i+1], inverseTransform));
            }
    
        }
        // clippingPlanes.add(createPlane(range[0], range[1], inverseTransform));
        // clippingPlanes.add(createPlane(range[1], range[2], inverseTransform));
        // clippingPlanes.add(createPlane(range[2], range[3], inverseTransform));
        // clippingPlanes.add(createPlane(range[3], range[0], inverseTransform));
        // tileset.clippingPlanes = clippingPlanes;
        return clippingPlanes;
    
    }
    
    /**
     * 求交点 线面相交 求交点
     * @param line
     * @param polygon
     * @returns {boolean|Array}
     */
    function getPointInPolygon(line, polygon) {
        let normal = getNormal(polygon[0], polygon[1], polygon[2]);
        let lineNormal = [];
        let lineX = line[0].x - line[1].x;
        let lineY = line[0].y - line[1].y;
        let lineZ = line[0].z - line[1].z;
        lineNormal.push({"x": lineX, "y": lineY, "z": lineZ});
        let result = CalPlaneLineIntersectPoint(normal, polygon[1], lineNormal, line[0]);
        if (result) {
            return result;
        }
        return false;
    }
    
    /**
     * 求交点是否在区域内部
     * @param point
     * @param polygon
     * @returns {boolean}
     * @constructor
     */
    function JudgePointInPolygon(point, polygon) {
        let p1 = polygon[0];
        let p2 = polygon[1];
        let p3 = polygon[2];
        let p4 = polygon[3];
        let n1, n2, n3, n4, n5, n6, n7, n8;
        n1 = {"x": p2.x - p1.x, "y": p2.y - p1.y, "z": p2.z - p1.z};
        n2 = {"x": point.x - p1.x, "y": point.y - p1.y, "z": point.z - p1.z};
        n3 = {"x": p4.x - p3.x, "y": p4.y - p3.y, "z": p4.z - p3.z};
        n4 = {"x": point.x - p3.x, "y": point.y - p3.y, "z": point.z - p3.z};
        n5 = {"x": p3.x - p2.x, "y": p3.y - p2.y, "z": p3.z - p2.z};
        n6 = {"x": point.x - p2.x, "y": point.y - p2.y, "z": point.z - p2.z};
        n7 = {"x": p4.x - p1.x, "y": p4.y - p1.y, "z": p4.z - p1.z};
        n8 = {"x": point.x - p4.x, "y": point.y - p4.y, "z": point.z - p4.z};
    
        return !(VectorMultiplication(n1, n2) * VectorMultiplication(n3, n3) >= 0 && VectorMultiplication(n5, n6) * VectorMultiplication(n7, n8) >= 0);
    }
    
    /**
     * 两个向量的叉积和
     * @param n
     * @param m
     * @returns {number}
     * @constructor
     */
    function VectorMultiplication(n, m) {
        return n.y * m.z - m.y * n.z + n.z * m.x - n.x * m.z + n.x * m.y - n.y * m.x;
    }
    
    /**
     * 求交点是否在线段上
     * @param point
     * @param polyline
     * @returns {boolean}
     * @constructor
     */
    function JudgePointInPolyline(point, polyline) {
        let lineLength = Math.sqrt(Math.pow((polyline[0].x - polyline[1].x), 2) + Math.pow((polyline[0].y - polyline[1].y), 2) + Math.pow((polyline[0].z - polyline[1].z), 2));
        let one = Math.sqrt(Math.pow((point.x - polyline[1].x), 2) + Math.pow((point.y - polyline[1].y), 2) + Math.pow((point.z - polyline[1].z), 2));
        let two = Math.sqrt(Math.pow((point.x - polyline[0].x), 2) + Math.pow((point.y - polyline[0].y), 2) + Math.pow((point.z - polyline[0].z), 2));
        let di = one + two - lineLength;
        if (di * 100 < 1) {
            return true;
        }
        return false;
    
    }
    
    /**
     * 求线面交点 线面平行返回undefined
     * @param planeVector 平面的法线向量,长度为3
     * @param planePoint 平面经过的一点坐标,长度为3
     * @param lineVector 直线的方向向量,长度为3
     * @param linePoint 直线经过的一点坐标,长度为3
     * @returns {Array}  返回交点坐标,长度为3
     * @constructor
     */
    function CalPlaneLineIntersectPoint(planeVector, planePoint, lineVector, linePoint) {
        let returnResult = [];
        let vp1, vp2, vp3, n1, n2, n3, v1, v2, v3, m1, m2, m3, t, vpt;
        vp1 = planeVector[0].x;
        vp2 = planeVector[0].y;
        vp3 = planeVector[0].z;
        n1 = planePoint.x;
        n2 = planePoint.y;
        n3 = planePoint.z;
        v1 = lineVector[0].x;
        v2 = lineVector[0].y;
        v3 = lineVector[0].z;
        m1 = linePoint.x;
        m2 = linePoint.y;
        m3 = linePoint.z;
        vpt = v1 * vp1 + v2 * vp2 + v3 * vp3;
        //首先判断直线是否与平面平行
        if (vpt == 0) {
            returnResult = undefined;
        } else {
            t = ((n1 - m1) * vp1 + (n2 - m2) * vp2 + (n3 - m3) * vp3) / vpt;
            returnResult.x = m1 + v1 * t;
            returnResult.y = m2 + v2 * t;
            returnResult.z = m3 + v3 * t;
        }
        return returnResult;
    }
    
    /**
     * 已知三点坐标,求平面的法向量
     * @param p1
     * @param p2
     * @param p3
     * @returns {[]}
     */
    function getNormal(p1, p2, p3) {
        let point = [];
        let x = ((p2.y - p1.y) * (p3.z - p1.z) - (p2.z - p1.z) * (p3.y - p1.y));
        let y = ((p2.z - p1.z) * (p3.x - p1.x) - (p2.x - p1.x) * (p3.z - p1.z));
        let z = ((p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x));
        point.push({"x": x, "y": y, "z": z});
        return point;
    }
    
    /**
     * 根据3个点,计算空间平面的方程
     * Ax+By+Cz+D=0
     * 输入参数:point3fArray---空间中3个点的坐标,大小为3;输入点>3时,只取前3个点
     * 输出参数A,B,C,D
     * 返回值:true---计算成功;false----计算失败
     * @param point3fArray
     * @returns {boolean}
     * @constructor
     */
    function GetPanelEquation(point3fArray) {
        if (point3fArray.length < 3) {
            return undefined;
        }
        let A, B, C, D;
        A = point3fArray[0].y * (point3fArray[1].z - point3fArray[2].z) +
            point3fArray[1].y * (point3fArray[2].z - point3fArray[0].z) +
            point3fArray[2].y * (point3fArray[0].z - point3fArray[1].z);
    
        B = point3fArray[0].z * (point3fArray[1].x - point3fArray[2].x) +
            point3fArray[1].z * (point3fArray[2].x - point3fArray[0].x) +
            point3fArray[2].z * (point3fArray[0].x - point3fArray[1].x);
    
        C = point3fArray[0].x * (point3fArray[1].y - point3fArray[2].y) +
            point3fArray[1].x * (point3fArray[2].y - point3fArray[0].y) +
            point3fArray[2].x * (point3fArray[0].y - point3fArray[1].y);
    
        D = -point3fArray[0].x * (point3fArray[1].y * point3fArray[2].z - point3fArray[2].y * point3fArray[1].z) -
            point3fArray[1].x * (point3fArray[2].y * point3fArray[0].z - point3fArray[0].y * point3fArray[2].z) -
            point3fArray[2].x * (point3fArray[0].y * point3fArray[1].z - point3fArray[1].y * point3fArray[0].z);
    
    
        return {A: A, B: B, C: C, D: D};
    
    
    }
    
    /**
     * canvas 绘制虚线
     * @param ctx
     * @param moveTo
     * @param lineTo
     * @param pattern
     */
    function drawDashedLine(ctx, moveTo, lineTo, pattern) {
        ctx.beginPath();
        ctx.setLineDash(pattern);
        ctx.moveTo(moveTo.x, moveTo.y);
        ctx.lineTo(lineTo.x, lineTo.y);
        ctx.stroke();
        ctx.closePath();
        ctx.setLineDash([]);
    }
    
    
    /**
     * 动态创建DIV 和 canvas
     */
    function addDivCanvas() {
        let div = document.getElementById("crossAnalysisResultCanvasDiv");
        if (!div) {
            div = document.createElement("div");
            div.id = "crossAnalysisResultCanvasDiv";
            // div.style.position = "absolute";
            // div.style.top = "25%";
            // div.style.left = "25%";
            div.style.backgroundColor = "#ffffff";
            // div.style.zIndex = 999999999;
            div.style.width = "960px";
            div.style.height = "524px";
            div.style.border = "1px #0366bf solid";
            div.style.borderRadius = "6px";
            let canvas = document.createElement("canvas");
            canvas.id = 'crossAnalysisResultCanvas';
            div.append(canvas)
            document.body.appendChild(div);
        }
    }
    
    //根据墙实体ID CrossAnalysis横断面分析所有的 polylineVolume
    function CrossAnalysis(callback) {
        let wallEntity = viewer.entities.getOrCreateEntity("CrossAnalysis");
        //判断是否有横截面
        if (wallEntity && wallEntity.wall) {
            let wallPositions = wallEntity._wall.positions.getValue(), wallPositions2 = [];
            for (let u in wallPositions) {
                wallPositions2.push(GeoInfoTools.Transform.toDegrees(wallPositions[u]))
            }
            //平面的第三、四点
            wallPositions2.push({lng: wallPositions2[1].lng, lat: wallPositions2[1].lat, alt: -10});
            wallPositions2.push({lng: wallPositions2[0].lng, lat: wallPositions2[0].lat, alt: -10});
            let polylineVolumes = [], entities = viewer.entities._entities.values;
            //找entities中的管线
            for (let k in entities) {
                if (entities[k] && entities[k].polylineVolume) {
                    polylineVolumes.push(entities[k]);
                }
            }
    
            //截面            相交点
            let polygon = [], intersections = [];
            //将polygon转化成笛卡尔坐标系
            for (let po in wallPositions2) {
                polygon.push(GeoInfoTools.Transform.toCartesian(wallPositions2[po]))
            }
            // console.log(GetPanelEquation(polygon))
            //便利管线进行横断面分析
            if (polylineVolumes.length > 0) {
                //遍历polylineVolumes
                for (let n in polylineVolumes) {
                    //获取polylineVolume的位置信息
                    let polylineVolumePositions = polylineVolumes[n].polylineVolume.positions.getValue();
                    //遍历位置信息
                    for (let p = 0; p < polylineVolumePositions.length - 1; p++) {
                        let line = [];
                        line.push(polylineVolumePositions[p]);
                        line.push(polylineVolumePositions[p + 1]);
    
                        let point = getPointInPolygon(line, polygon);
                        if (point) {
                            if (JudgePointInPolyline(point, line)) {
                                if (JudgePointInPolygon(point, polygon)) {
                                    intersections.push(point);
                                }
                            }
                        }
                    }
    
                }
            }
    
            //交点表示
            // for (let position in intersections) {
            //     addPoint(intersections[position])
            // }
    
            // console.log(intersections);
            let results = [];
            for (let t in intersections) {
                results.push(GeoInfoTools.Transform.toDegrees(intersections[t]));
            }
            // console.log(results)
            if (results.length > 0) {
                callback(results);
                // getCrossAnalysisResultToContext(results)
            } else {
                //todo 没有横断面的结果
            }
    
        }
    
        return undefined;
    }
    
    
    
    
    
    

    相关文章

      网友评论

          本文标题:tools

          本文链接:https://www.haomeiwen.com/subject/xcuclktx.html