cesium视频投影

先看效果视频投影效果图
使用cesium做视频投影效果,而且还要跟随无人机移动而移动,我现在用定时器更新无人机的坐标来实现效果具体代码如下:
1、CesiumVideo3d.js(某个cesium技术群大佬分享的)

// import ECEF from "./CoordinateTranslate";
let CesiumVideo3d = (function () {

    var videoShed3dShader = "\r\n\r\n\r\n\r\nuniform float mixNum;\r\nuniform sampler2D colorTexture;\r\nuniform sampler2D stcshadow; \r\nuniform sampler2D videoTexture;\r\nuniform sampler2D depthTexture;\r\nuniform mat4 _shadowMap_matrix; \r\nuniform vec4 shadowMap_lightPositionEC; \r\nuniform vec4 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness; \r\nuniform vec4 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth; \r\nvarying vec2 v_textureCoordinates;\r\nvec4 toEye(in vec2 uv, in float depth){\r\n    vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));\r\n    vec4 posInCamera =czm_inverseProjection * vec4(xy, depth, 1.0);\r\n    posInCamera =posInCamera / posInCamera.w;\r\n    return posInCamera;\r\n}\r\nfloat getDepth(in vec4 depth){\r\n    float z_window = czm_unpackDepth(depth);\r\n    z_window = czm_reverseLogDepth(z_window);\r\n    float n_range = czm_depthRange.near;\r\n    float f_range = czm_depthRange.far;\r\n    return (2.0 * z_window - n_range - f_range) / (f_range - n_range);\r\n}\r\nfloat _czm_sampleShadowMap(sampler2D shadowMap, vec2 uv){\r\n    return texture2D(shadowMap, uv).r;\r\n}\r\nfloat _czm_shadowDepthCompare(sampler2D shadowMap, vec2 uv, float depth){\r\n    return step(depth, _czm_sampleShadowMap(shadowMap, uv));\r\n}\r\nfloat _czm_shadowVisibility(sampler2D shadowMap, czm_shadowParameters shadowParameters){\r\n    float depthBias = shadowParameters.depthBias;\r\n    float depth = shadowParameters.depth;\r\n    float nDotL = shadowParameters.nDotL;\r\n    float normalShadingSmooth = shadowParameters.normalShadingSmooth;\r\n    float darkness = shadowParameters.darkness;\r\n    vec2 uv = shadowParameters.texCoords;\r\n    depth -= depthBias;\r\n    vec2 texelStepSize = shadowParameters.texelStepSize;\r\n    float radius = 1.0;\r\n    float dx0 = -texelStepSize.x * radius;\r\n    float dy0 = -texelStepSize.y * radius;\r\n    float dx1 = texelStepSize.x * radius;\r\n    float dy1 = texelStepSize.y * radius;\r\n    float visibility = \r\n    (\r\n    _czm_shadowDepthCompare(shadowMap, uv, depth)\r\n    +_czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy0), depth) +\r\n    _czm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy0), depth) +\r\n    _czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy0), depth) +\r\n    _czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, 0.0), depth) +\r\n    _czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, 0.0), depth) +\r\n    _czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy1), depth) +\r\n    _czm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy1), depth) +\r\n    _czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy1), depth)\r\n    ) * (1.0 / 9.0)\r\n    ;\r\n    return visibility;\r\n}\r\nvec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point){\r\n    vec3 v01 = point -planeOrigin;\r\n    float d = dot(planeNormal, v01) ;\r\n    return (point - planeNormal * d);\r\n}\r\nfloat ptm(vec3 pt){\r\n    return sqrt(pt.x*pt.x + pt.y*pt.y + pt.z*pt.z);\r\n}\r\nvoid main() \r\n{ \r\n    const float PI = 3.141592653589793;\r\n    vec4 color = texture2D(colorTexture, v_textureCoordinates);\r\n    vec4 currD = texture2D(depthTexture, v_textureCoordinates);\r\n    if(currD.r>=1.0){\r\n        gl_FragColor = color;\r\n        return;\r\n    }\r\n    \r\n    float depth = getDepth(currD);\r\n    vec4 positionEC = toEye(v_textureCoordinates, depth);\r\n    vec3 normalEC = vec3(1.0);\r\n    czm_shadowParameters shadowParameters; \r\n    shadowParameters.texelStepSize = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.xy; \r\n    shadowParameters.depthBias = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.z; \r\n    shadowParameters.normalShadingSmooth = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.w; \r\n    shadowParameters.darkness = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.w; \r\n    shadowParameters.depthBias *= max(depth * 0.01, 1.0); \r\n    vec3 directionEC = normalize(positionEC.xyz - shadowMap_lightPositionEC.xyz); \r\n    float nDotL = clamp(dot(normalEC, -directionEC), 0.0, 1.0); \r\n    vec4 shadowPosition = _shadowMap_matrix * positionEC; \r\n    shadowPosition /= shadowPosition.w; \r\n    if (any(lessThan(shadowPosition.xyz, vec3(0.0))) || any(greaterThan(shadowPosition.xyz, vec3(1.0)))) \r\n    { \r\n        gl_FragColor = color;\r\n        return;\r\n    }\r\n\r\n    shadowParameters.texCoords = shadowPosition.xy; \r\n    shadowParameters.depth = shadowPosition.z; \r\n    shadowParameters.nDotL = nDotL; \r\n    float visibility = _czm_shadowVisibility(stcshadow, shadowParameters); \r\n\r\n    vec4 videoColor = texture2D(videoTexture,shadowPosition.xy);\r\n    if(visibility==1.0){\r\n        gl_FragColor = mix(color,vec4(videoColor.xyz,1.0),mixNum*videoColor.a);\r\n    }else{\r\n        if(abs(shadowPosition.z-0.0)<0.01){\r\n            return;\r\n        }\r\n        gl_FragColor = color;\r\n    }\r\n} ";
    var Cesium=null

    var videoShed3d=function(cesium,viewer, param) {
        Cesium=cesium
        this.ECEF = new ECEF();        
        this.param = param;
        var option = this._initCameraParam();
        this.optionType = {
            Color: 1,
            Image: 2,
            Video: 3
        }
        this.near = option.near ? option.near : 0.1;
        if (option || (option = {}), this.viewer = viewer, this._cameraPosition = option.cameraPosition, this._position = option.position,
            this.type = option.type, this._alpha = option.alpha || 1, this.url = option.url, this.color = option.color,
            this._debugFrustum = Cesium.defaultValue(option.debugFrustum, !0), this._aspectRatio = option.aspectRatio || this._getWinWidHei(),
            this._camerafov = option.fov || Cesium.Math.toDegrees(this.viewer.scene.camera.frustum.fov), this.texture = option.texture || new Cesium.Texture({
                context: this.viewer.scene.context,
                source: {
                    width: 1,
                    height: 1,
                    arrayBufferView: new Uint8Array([255, 255, 255, 255])
                },
                flipY: !1
            }), this._videoPlay = Cesium.defaultValue(option.videoPlay, !0), this.defaultShow = Cesium.defaultValue(option.show, !0), !this.cameraPosition || !this.position) return void console.log('初始化失败:请确认相机位置与视点位置正确!');
        switch (this.type) {
            default:
            case this.optionType.Video:
                this.activeVideo(this.url);
                break;
            case this.optionType.Image:
                this.activePicture(this.url);
                this.deActiveVideo();
                break;
            case this.optionType.Color:
                this.activeColor(this.color),
                    this.deActiveVideo();
        }
        this._createShadowMap(),
            this._getOrientation(),
            this._addCameraFrustum()
        this._addPostProcess()
        this.viewer.scene.primitives.add(this)
    }
    Object.defineProperties(videoShed3d.prototype, {
        alpha: {
            get: function () {
                return this._alpha
            },
            set: function (e) {
                return this._alpha = e
            }
        },
        aspectRatio: {
            get: function () {
                return this._aspectRatio
            },
            set: function (e) {
                this._aspectRatio = e,
                    this._changeVideoWidHei()
            }
        },
        debugFrustum: {
            get: function () {
                return this._debugFrustum
            },
            set: function (e) {
                this._debugFrustum = e,
                    this.cameraFrustum.show = e
            }
        },
        fov: {
            get: function () {
                return this._camerafov
            },
            set: function (e) {
                this._camerafov = e,
                    this._changeCameraFov()
            }
        },
        cameraPosition: {
            get: function () {
                return this._cameraPosition
            },
            set: function (e) {
                e && (this._cameraPosition = e, this._changeCameraPos())
            }
        },
        position: {
            get: function () {
                return this._position
            },
            set: function (e) {
                e && (this._position = e, this._changeViewPos())
            }
        },
        videoPlay: {
            get: function () {
                return this._videoPlay
            },
            set: function (e) {
                this._videoPlay = Boolean(e),
                    this._videoEle && (this.videoPlay ? this._videoEle.paly() : this._videoEle.pause())
            }
        },
        params: {
            get: function () {
                var t = {}
                return t.type = this.type,
                    this.type == this.optionType.Color ? t.color = this.color : t.url = this.url,
                    t.position = this.position,
                    t.cameraPosition = this.cameraPosition,
                    t.fov = this.fov,
                    t.aspectRatio = this.aspectRatio,
                    t.alpha = this.alpha,
                    t.debugFrustum = this.debugFrustum,
                    t
            }
        },
        show: {
            get: function () {
                return this.defaultShow
            },
            set: function (e) {
                this.defaultShow = Boolean(e),
                    this._switchShow()
            }
        }
    })
    videoShed3d.prototype._initCameraParam = function () {
        var viewPoint = this.ECEF.enu_to_ecef({ longitude: this.param.position.x * 1, latitude: this.param.position.y * 1, altitude: this.param.position.z * 1 },
            { distance: this.param.far, azimuth: this.param.rotation.y * 1, elevation: this.param.rotation.x * 1 });
        var position = Cesium.Cartesian3.fromDegrees(viewPoint.longitude, viewPoint.latitude, viewPoint.altitude);
        var cameraPosition = Cesium.Cartesian3.fromDegrees(this.param.position.x * 1, this.param.position.y * 1, this.param.position.z * 1);
        return {
            type: 3,
            url: this.param.url,
            cameraPosition: cameraPosition,
            position: position,
            alpha: this.param.alpha,
            near: this.param.near,
            fov: this.param.fov,
            debugFrustum: this.param.debugFrustum
        }
    }
    /**
     * 旋转
     */
    videoShed3d.prototype._changeRotation = function (e) {
        if (e) {
            this.param.rotation = e;
            var option = this._initCameraParam();
            this.position = option.position;
        }
    }
    /**
     * 相机位置
     */
    videoShed3d.prototype._changeCameraPosition = function (e) {
        if (e) {
            this.param.position = e;
            var option = this._initCameraParam();
            this.cameraPosition = option.cameraPosition;
        }
    }
    videoShed3d.prototype._changeFar = function (e) {
        if (e) {
            this.param.far = e;
            var option = this._initCameraParam();
            this.position = option.position;
        }
    }
    videoShed3d.prototype._changeNear = function (e) {
        if (e) {
            this.param.near = e;
            this.near = this.param.near;
            this._changeCameraPos();
        }
    }
    /**获取三维地图容器像素大小
     */
    videoShed3d.prototype._getWinWidHei = function () {
        var viewer = this.viewer.scene;
        return viewer.canvas.clientWidth / viewer.canvas.clientHeight;
    }
    videoShed3d.prototype._changeCameraFov = function () {
        this.viewer.scene.postProcessStages.remove(this.postProcess)
        this.viewer.scene.primitives.remove(this.cameraFrustum),
            this._createShadowMap(this.cameraPosition, this.position),
            this._getOrientation(),
            this._addCameraFrustum(),
            this._addPostProcess()
    }
    videoShed3d.prototype._changeVideoWidHei = function () {
        this.viewer.scene.postProcessStages.remove(this.postProcess),
            this.viewer.scene.primitives.remove(this.cameraFrustum)
        this._createShadowMap(this.cameraPosition, this.position),
            this._getOrientation(),
            this._addCameraFrustum(),
            this._addPostProcess()
    }
    videoShed3d.prototype._changeCameraPos = function () {
        this.viewer.scene.postProcessStages.remove(this.postProcess),
            this.viewer.scene.primitives.remove(this.cameraFrustum),
            this.viewShadowMap.destroy(),
            this.cameraFrustum.destroy(),
            this._createShadowMap(this.cameraPosition, this.position),
            this._getOrientation(),
            this._addCameraFrustum(),
            this._addPostProcess()
    }
    videoShed3d.prototype._changeViewPos = function () {
        this.viewer.scene.postProcessStages.remove(this.postProcess),
            this.viewer.scene.primitives.remove(this.cameraFrustum),
            this.viewShadowMap.destroy(),
            this.cameraFrustum.destroy(),
            this._createShadowMap(this.cameraPosition, this.position),
            this._getOrientation(),
            this._addCameraFrustum(),
            this._addPostProcess()
    }
    videoShed3d.prototype._switchShow = function () {
        this.show ? !this.postProcess && this._addPostProcess() : (this.viewer.scene.postProcessStages.remove(this.postProcess), delete this.postProcess, this.postProcess = null),
            this.cameraFrustum.show = this.show
    }
    /** 创建视频Element
     * @param {String} url 视频地址
     **/
    videoShed3d.prototype._createVideoEle = function (url) {
        this.videoId = "visualDomId";
        var t = document.createElement("SOURCE");
        t.type = "video/mp4",
            t.src = url;
        var i = document.createElement("SOURCE");
        i.type = "video/quicktime",
            i.src = url;
        var a = document.createElement("VIDEO");
        return a.setAttribute("autoplay", !0),
            a.setAttribute("loop", !0),
            a.setAttribute("crossorigin", !0),
            a.appendChild(t),
            a.appendChild(i),
            //document.body.appendChild(a),
            this._videoEle = a,
            a
    }
    /** 视频投射
     * @param {String} url 视频地址
     */
    videoShed3d.prototype.activeVideo = function (url) {
        var video = this._createVideoEle(url),
            that = this;
        if (video) {
            this.type = that.optionType.Video;
            var viewer = this.viewer;
            this.activeVideoListener || (this.activeVideoListener = function () {
                that.videoTexture && that.videoTexture.destroy(),
                    that.videoTexture = new Cesium.Texture({
                        context: viewer.scene.context,
                        source: video,
                        width: 1,
                        height: 1,
                        pixelFormat: Cesium.PixelFormat.RGBA,
                        pixelDatatype: Cesium.PixelDatatype.UNSIGNED_BYTE
                    })
            }),
                viewer.clock.onTick.addEventListener(this.activeVideoListener)
        }
    }
    videoShed3d.prototype.deActiveVideo = function () {
        if (this.activeVideoListener) {
            this.viewer.clock.onTick.removeEventListener(this.activeVideoListener),
                delete this.activeVideoListener
        }
    }
    /** 图片投放
     * @param {String} url 图片地址
     **/
    videoShed3d.prototype.activePicture = function (url) {
        this.videoTexture = this.texture;
        var that = this,
            img = new Image;
        img.onload = function () {
            that.type = that.optionType.Image,
                that.videoTexture = new Cesium.Texture({
                    context: that.viewer.scene.context,
                    source: img
                })
        },
            img.onerror = function () {
                console.log('图片加载失败:' + url)
            },
            img.src = url
    }
    videoShed3d.prototype.locate = function () {
        var cameraPosition = Cesium.clone(this.cameraPosition),
            position = Cesium.clone(this.position);
        this.viewer.Camera.position = cameraPosition,
            this.viewer.camera.direction = Cesium.Cartesian3.subtract(position, cameraPosition, new Cesium.Cartesian3(0, 0, 0)),
            this.viewer.camera.up = Cesium.Cartesian3.normalize(cameraPosition, new Cesium.Cartesian3(0, 0, 0))
    }
    videoShed3d.prototype.update = function (e) {
        this.viewShadowMap && this.viewer.scene.frameState.shadowMaps.push(this.viewShadowMap) // *重点* 多投影
    }
    videoShed3d.prototype.destroy = function () {
        this.viewer.scene.postProcessStages.remove(this.postProcess),
            this.viewer.scene.primitives.remove(this.cameraFrustum),
            //this._videoEle && this._videoEle.parentNode.removeChild(this._videoEle),
            this.activeVideoListener && this.viewer.clock.onTick.removeEventListener(this.activeVideoListener),
            this.activeVideoListener && delete this.activeVideoListener,
            delete this.postProcess,
            delete this.viewShadowMap,
            delete this.color,
            delete this.viewDis,
            delete this.cameraPosition,
            delete this.position,
            delete this.alpha,
            delete this._camerafov,
            delete this._cameraPosition,
            delete this.videoTexture,
            delete this.cameraFrustum,
            delete this._videoEle,
            delete this._debugFrustum,
            delete this._position,
            delete this._aspectRatio,
            delete this.url,
            delete this.orientation,
            delete this.texture,
            delete this.videoId,
            delete this.type,
            this.viewer.scene.primitives.remove(this),
            delete this.viewer
    }
    // 创建shadowmap
    videoShed3d.prototype._createShadowMap = function () {
        var e = this.cameraPosition,
            t = this.position,
            i = this.viewer.scene,
            a = new Cesium.Camera(i);
        a.position = e,
            a.direction = Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3(0, 0, 0)), //计算两个笛卡尔的组分差异。
            a.up = Cesium.Cartesian3.normalize(e, new Cesium.Cartesian3(0, 0, 0)); // 归一化
        var n = Cesium.Cartesian3.distance(t, e);
        this.viewDis = n,
            a.frustum = new Cesium.PerspectiveFrustum({
                fov: Cesium.Math.toRadians(this.fov),
                aspectRatio: this.aspectRatio,
                near: this.near,
                far: n
            });
        this.viewShadowMap = new Cesium.ShadowMap({
            lightCamera: a,
            enable: !1,
            isPointLight: !1,
            isSpotLight: !0,
            cascadesEnabled: !1,
            context: i.context,
            pointLightRadius: n
        })
    }
    // 获取shadowmap位置
    videoShed3d.prototype._getOrientation = function () {
        var e = this.cameraPosition,
            t = this.position,
            i = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3), new Cesium.Cartesian3),
            a = Cesium.Cartesian3.normalize(e, new Cesium.Cartesian3),
            n = new Cesium.Camera(this.viewer.scene);
        n.position = e,
            n.direction = i,
            n.up = a,
            i = n.directionWC,
            a = n.upWC;
        var r = n.rightWC,
            o = new Cesium.Cartesian3,
            l = new Cesium.Matrix3,
            u = new Cesium.Quaternion;
        r = Cesium.Cartesian3.negate(r, o);
        var d = l;
        Cesium.Matrix3.setColumn(d, 0, r, d),
            Cesium.Matrix3.setColumn(d, 1, a, d),
            Cesium.Matrix3.setColumn(d, 2, i, d);
        var c = Cesium.Quaternion.fromRotationMatrix(d, u);





        /*var viewMatrix=n.viewMatrix;
        var inverseViewMatrix=n.inverseViewMatrix;
        console.log("视图矩阵=",viewMatrix);
        console.log("逆视图矩阵=",inverseViewMatrix);
        
        var frustum = new Cesium.PerspectiveFrustum({
            fov :20,
            aspectRatio : 0.75,
            near : 1.0,
            far : 10.0
        });
 
        var projectionMatrix=frustum.projectionMatrix;
        var infiniteProjectionMatrix=frustum.infiniteProjectionMatrix;
        console.log("投影矩阵=",projectionMatrix);
        console.log("透视投影矩阵=",infiniteProjectionMatrix);
         
        //透视投 影矩阵反转
       var inverseInfiniteProjectionMatrix=new Cesium.Matrix4();
       Cesium.Matrix4.inverse(infiniteProjectionMatrix,inverseInfiniteProjectionMatrix);
       console.log("透视投 影矩阵反转=",inverseInfiniteProjectionMatrix);
       
       //逆视图投影矩阵
       var inverseViewProjectionMatrix=new Cesium.Matrix4();
       Cesium.Matrix4.multiply(inverseInfiniteProjectionMatrix,inverseViewMatrix,inverseViewProjectionMatrix)
       console.log("逆视图投影矩阵=",inverseViewProjectionMatrix);
       
       //视图投影矩阵
       var viewProjectionMatrix=new Cesium.Matrix4();
       Cesium.Matrix4.inverse(inverseViewProjectionMatrix,viewProjectionMatrix);
       console.log("视图投影矩阵=",viewProjectionMatrix);
       
       //远平面标准模型矩阵
       var matrix4 = Cesium.Matrix4.fromUniformScale(10);
       console.log("远平面标准模型矩阵=",matrix4);
       
       //模型矩阵
       var modelMatrix=new Cesium.Matrix4();
       Cesium.Matrix4.multiply(inverseViewMatrix,matrix4,modelMatrix)
       console.log("模型矩阵=",modelMatrix);
       
       //视图矩阵与逆视图投影矩阵相乘得到立方体模型视图
       var uBoxMV=new Cesium.Matrix4();
       Cesium.Matrix4.multiply(viewMatrix,inverseViewProjectionMatrix,uBoxMV)
       console.log("立方体模型视图=",uBoxMV);
       
       //逆立方体模型视图
       var uInverseBoxMV=new Cesium.Matrix4();
       Cesium.Matrix4.multiply(viewMatrix,viewProjectionMatrix,uInverseBoxMV)
       console.log("立方体模型视图=",uInverseBoxMV);
       
       //将这两个模型视图赋予分类基元类的一致性映射 参数便可以最终实现视频监控图像与实景三维场景的融 合
       
         var geometry =this.creacteGeometry(5,5);
         var instance = new Cesium.GeometryInstance({
               // geometry: //new Cesium.Geometry({}),
               // geometry: new Cesium.GeometryInstance({
               //   geometry:new Cesium.FrustumOutlineGeometry ({
               //     origin: Cesium.Cartesian3.fromDegrees(cameraLong,cameraLat, cameraHeight),
               //     orientation:orientation,
               //     frustum: perspectiveFrustum,
               //     _drawNearPlane: true
               //   }),
               geometry:geometry,
               classificationType:Cesium.ClassificationType.BOTH,
               // modelMatrix: modelMatrix,
               attributes : {
                 color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromCssColorString('#ff0000').withAlpha(1.0)),
                 show : new Cesium.ShowGeometryInstanceAttribute(true)
               }
               });
         var videoElement = this._createVideoEle("http://localhost:7070/video/北京路与天马路交叉口高点枪机.mkv");
         var material = Cesium.Material.fromType('Image');
        material.uniforms.image = videoElement;
         var _uniformMap ={
                   u_boxMV:uBoxMV,
                   u_inverseBoxMV:uInverseBoxMV
                 };
         this.viewer.scene.primitives.add(new Cesium.Primitive({
               geometryInstances: instance,
               appearance: new Cesium.MaterialAppearance ({
                 material: material,
                 close:false,
               }),
               modelMatrix: modelMatrix,
               _uniformMap:_uniformMap,
               asynchronous:false,
               compressVertices:false,
               allowPicking:false
             }));*/

        //ClassificationPrimitive
        return this.orientation = c,
            c
    }
    videoShed3d.prototype.creacteGeometry = function (width, height) {
        var hwidth = width / 2.0;
        var hheigt = height / 2.0;
        var positions = new Float64Array([hwidth, 0.0, hheigt, -hwidth, 0.0, hheigt, -hwidth, 0.0, -hheigt, hwidth, 0.0, -hheigt]);
        var sts = new Float32Array([1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0]);
        var indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
        var ge = this._createGeometry(positions, sts, indices);
        return ge;
    },
    videoShed3d.prototype._createGeometry = function (positions, sts, indices) {
        /* var Cesium = this.Cesium;*/
        return new Cesium.Geometry({
            attributes: {
                position: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                    componentsPerAttribute: 3,
                    values: positions
                }),
                normal: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.FLOAT,
                    componentsPerAttribute: 3,
                    values: new Float32Array([255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 255.0, 0.0, 0.0])
                    // values: new Float32Array([0.0, 0.0, 0.0,0.0, 0.0, 0.0,0.0, 0.0, 0.0,0.0, 0.0, 0.0])
                }),
                st: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.FLOAT,
                    componentsPerAttribute: 2,
                    values: sts
                })
            },
            indices: indices,
            primitiveType: Cesium.PrimitiveType.TRIANGLES,
            vertexFormat: new Cesium.VertexFormat({
                position: true,
                color: true
            }),
            boundingSphere: Cesium.BoundingSphere.fromVertices(positions)
        });
    },
    //创建视锥
    videoShed3d.prototype._addCameraFrustum = function () {
        var e = this;
        this.cameraFrustum = new Cesium.Primitive({
            geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.FrustumOutlineGeometry({
                    origin: e.cameraPosition,
                    orientation: e.orientation,
                    frustum: this.viewShadowMap._lightCamera.frustum,
                    _drawNearPlane: !0
                }),
                attributes: {
                    color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(0, 0.5, 0.5))
                }
            }),
            appearance: new Cesium.PerInstanceColorAppearance({
                translucent: !1,
                flat: !0
            }),
            asynchronous: !1,
            show: this.debugFrustum && this.show
        }),
            this.viewer.scene.primitives.add(this.cameraFrustum)
    }
    videoShed3d.prototype._addPostProcess = function () {
        var e = this,
            t = videoShed3dShader,
            i = e.viewShadowMap._isPointLight ? e.viewShadowMap._pointBias : e.viewShadowMap._primitiveBias;
        this.postProcess = new Cesium.PostProcessStage({
            fragmentShader: t,
            uniforms: {
                mixNum: function () {
                    return e.alpha
                },
                stcshadow: function () {
                    return e.viewShadowMap._shadowMapTexture
                },
                videoTexture: function () {
                    return e.videoTexture
                },
                _shadowMap_matrix: function () {
                    return e.viewShadowMap._shadowMapMatrix
                },
                shadowMap_lightPositionEC: function () {
                    return e.viewShadowMap._lightPositionEC
                },
                shadowMap_texelSizeDepthBiasAndNormalShadingSmooth: function () {
                    var t = new Cesium.Cartesian2;
                    return t.x = 1 / e.viewShadowMap._textureSize.x,
                        t.y = 1 / e.viewShadowMap._textureSize.y,
                        Cesium.Cartesian4.fromElements(t.x, t.y, i.depthBias, i.normalShadingSmooth, this.combinedUniforms1)
                },
                shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness: function () {
                    return Cesium.Cartesian4.fromElements(i.normalOffsetScale, e.viewShadowMap._distance, e.viewShadowMap.maximumDistance, e.viewShadowMap._darkness, this.combinedUniforms2)
                }

            }
        }),
        this.viewer.scene.postProcessStages.add(this.postProcess);
    }
    return videoShed3d;
})()

// export default CesiumVideo3d

2、CoordinateTranslate.js(同上,也是技术群大佬分享的)

let ECEF = (function () {
	var _=function () {
		this.PI = 3.141592653589793238;
		this.a = 6378137.0;
		this.b = 6356752.3142
		this.f = (this.a - this.b) / this.a;
		this.e_sq = this.f * (2.0 - this.f);
		this.ee = 0.00669437999013;
		this.WGSF = 1 / 298.257223563;
		this.WGSe2 = this.WGSF * (2 - this.WGSF);
		this.WGSa = 6378137.00000;
		this.EPSILON = 1.0e-12;
	}
	_.prototype.CalculateCoordinates = function (point, azimuth, elevation, distance) {
		var vertical_height = distance * Math.sin(2 * this.PI / 360 * elevation);//垂直高度
		var horizontal_distance = distance * Math.cos(2 * this.PI / 360 * elevation);//水平距离
		if (azimuth > 360) azimuth = azimuth % 360;
		if (azimuth < 0) azimuth = 360 + (azimuth % 360);

		var point1 = this.lonLat2WebMercator(point);
		var lnglat = null;
		
		var x_length , y_length
		if (azimuth <= 90) {//第四象限
			x_length = horizontal_distance * Math.cos(2 * this.PI / 360 * azimuth);
			y_length = horizontal_distance * Math.sin(2 * this.PI / 360 * azimuth);
			lnglat = {
				x: point1.x + x_length,
				y: point1.y - y_length
			}
		} else if (azimuth > 90 && azimuth <= 180) {//第三象限
			x_length = horizontal_distance * Math.sin(2 * this.PI / 360 * (azimuth - 90));
			y_length = horizontal_distance * Math.cos(2 * this.PI / 360 * (azimuth - 90));
			lnglat = {
				x: point1.x - x_length,
				y: point1.y - y_length
			}
		} else if (azimuth > 180 && azimuth <= 270) {//第二象限
			x_length = horizontal_distance * Math.cos(2 * this.PI / 360 * (azimuth - 180));
			y_length = horizontal_distance * Math.sin(2 * this.PI / 360 * (azimuth - 180));
			lnglat = {
				x: point1.x - x_length,
				y: point1.y + y_length
			}
		} else {//第一象限
			x_length = horizontal_distance * Math.sin(2 * this.PI / 360 * (azimuth - 270));
			y_length = horizontal_distance * Math.cos(2 * this.PI / 360 * (azimuth - 270));
			lnglat = {
				x: point1.x + x_length,
				y: point1.y + y_length
			}
		}
		lnglat = this.webMercator2LonLat(lnglat);
		return {
			lng: lnglat.x,
			lat: lnglat.y,
			height: vertical_height
		}
	}
	/*
	   *经纬度转Web墨卡托
	   *@lonLat 经纬度
	   */
	_.prototype.lonLat2WebMercator = function (lonLat) {
		let x = lonLat.x * this.a / 180;
		let y = Math.log(Math.tan((90 + lonLat.y) * this.PI / 360)) / (this.PI / 180);
		y = y * this.a / 180;
		return {
			x: x,
			y: y
		}
	}

	/*
	   *Web墨卡托转经纬度
	   *@mercator 平面坐标
	   */
	_.prototype.webMercator2LonLat = function (mercator) {
		let x = mercator.x / this.a * 180;
		let y = mercator.y / this.a * 180;
		y = 180 / this.PI * (2 * (Math.exp(y * this.PI / 180)) - this.PI / 2);
		return {
			x: x,
			y: y
		}
	}

	_.prototype.get_atan = function (z, y) {
		let x;
		if (z == 0) {
			x = this.PI / 2;
		} else {
			if (y == 0) {
				x = this.PI;
			} else {
				x = Math.atan(Math.abs(y / z));
				if ((y > 0) && (z < 0)) {
					x = this.PI - x;
				} else if ((y < 0) && (z < 0)) {
					x = this.PI + x;
				} else if ((y < 0) && (z > 0)) {
					x = 2 * this.M_PI - x;
				}
			}
		}
		return x;
	}
	//WGS84转ECEF坐标系
	_.prototype.ConvertLLAToXYZ = function (LLACoor) {
		let lon = this.PI / 180 * LLACoor.longitude;
		let lat = this.PI / 180 * LLACoor.latitude;
		let H = LLACoor.altitude;
		let N0 = this.a / Math.sqrt(1.0 - this.ee * Math.sin(lat) * Math.sin(lat));
		let x = (N0 + H) * Math.cos(lat) * Math.cos(lon);
		let y = (N0 + H) * Math.cos(lat) * Math.sin(lon);
		let z = (N0 * (1.0 - this.ee) + H) * Math.sin(lat);
		return {
			x: x,
			y: y,
			z: z
		}
	}

	//ECEF坐标系转WGS84
	_.prototype.ConvertXYZToLLA = function (XYZCoor) {
		let longitude = this.get_atan(XYZCoor.x, XYZCoor.y);
		if (longitude < 0) {
			longitude = longitude + this.PI;
		}
		let latitude = this.get_atan(Math.sqrt(XYZCoor.x * XYZCoor.x + XYZCoor.y * XYZCoor.y), XYZCoor.z);

		let W = Math.sqrt(1 - this.WGSe2 * Math.sin(latitude) * Math.sin(latitude));
		let N = this.WGSa / W;
		let B1;
		do {
			B1 = latitude;
			W = Math.sqrt(1 - this.WGSe2 * Math.sin(B1) * Math.sin(B1));
			N = this.WGSa / W;
			latitude = this.get_atan(Math.sqrt(XYZCoor.x * XYZCoor.x + XYZCoor.y * XYZCoor.y), (XYZCoor.z + N * this.WGSe2 * Math.sin(B1)));
		}
		while (Math.abs(latitude - B1) > this.EPSILON);

		var altitude = Math.sqrt(XYZCoor.x * XYZCoor.x + XYZCoor.y * XYZCoor.y) / Math.cos(latitude) - this.WGSa / Math.sqrt(1 - this.WGSe2 * Math.sin(latitude) * Math.sin(latitude));

		return {
			longitude: longitude * 180 / this.PI,
			latitude: latitude * 180 / this.PI,
			altitude: altitude
		}
	}
	/*北东天坐标系转WGS84
	@ a A点坐标
	@ p 相对参数,距离、方位角、仰角
	*/
	//	俯视角pitch -elevation 
	//航向角heading(yaw) -azimuth 
	_.prototype.enu_to_ecef = function (a, p) {
		//距离
		let distance = p.distance;
		//方位角
		let azimuth = p.azimuth;
		//仰角
		let elevation = p.elevation;

		let zUp = elevation >= 0 ? distance * Math.sin(this.PI / 180 * elevation) : (-1) * distance * Math.sin(this.PI / 180 * Math.abs(elevation));

		let d = distance * Math.cos(this.PI / 180 * Math.abs(elevation));
		let xEast;
		let yNorth;
		if (azimuth <= 90) {
			xEast = d * Math.sin(this.PI / 180 * azimuth);
			yNorth = d * Math.cos(this.PI / 180 * azimuth);
		} else if (azimuth > 90 && azimuth < 180) {
			xEast = d * Math.cos(this.PI / 180 * (azimuth - 90));
			yNorth = (-1) * d * Math.sin(this.PI / 180 * (azimuth - 90));
		} else if (azimuth > 180 && azimuth < 270) {
			xEast = (-1) * d * Math.sin(this.PI / 180 * (azimuth - 180));
			yNorth = (-1) * d * Math.cos(this.PI / 180 * (azimuth - 180));
		} else {
			xEast = (-1) * d * Math.sin(this.PI / 180 * (360 - azimuth));
			yNorth = d * Math.cos(this.PI / 180 * (360 - azimuth));
		}

		let lamb = this.radians(a.latitude);
		let phi = this.radians(a.longitude);
		let h0 = a.altitude;

		let s = Math.sin(lamb);
		let N = this.a / Math.sqrt(1.0 - this.e_sq * s * s);

		let sin_lambda = Math.sin(lamb);
		let cos_lambda = Math.cos(lamb);

		let sin_phi = Math.sin(phi);
		let cos_phi = Math.cos(phi);

		let x0 = (h0 + N) * cos_lambda * cos_phi;
		let y0 = (h0 + N) * cos_lambda * sin_phi;
		let z0 = (h0 + (1 - this.e_sq) * N) * sin_lambda;

		let t = cos_lambda * zUp - sin_lambda * yNorth;

		let zd = sin_lambda * zUp + cos_lambda * yNorth;
		let xd = cos_phi * t - sin_phi * xEast;
		let yd = sin_phi * t + cos_phi * xEast;

		return this.ConvertXYZToLLA({
			x: xd + x0,
			y: yd + y0,
			z: zd + z0
		})
	}
	_.prototype.radians = function (degree) {
		return this.PI / 180 * degree;
	}	
	return _
})()

// export default CoordinateTranslate

3、index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <title>无人机视频投影</title>
    <script src="../Cesium/Cesium.js"></script>
    <script src="../jquery-2.1.4.js"></script>
    <script src="../CoordinateTranslate.js"></script>
    <script src="../CesiumVideo3d.js"></script>
    <style>
        @import url('../Cesium/Widgets/widgets.css');
        html, body, #cesiumContainer {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
    // 初始化 Cesium
    Cesium.Ion.defaultAccessToken = '你的cesium token令牌'
    const viewer = new Cesium.Viewer('cesiumContainer', {
        imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
            url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
            maximumLevel: 18,
        }),
        terrainProvider: Cesium.createWorldTerrain({
            requestVertexNormals: true,
            requestWaterMask: true
        }),
        shouldAnimate: true,
        selectionIndicator: false,
        infoBox: false,
        geocoder: false,
        baseLayerPicker: false,
        timeline: false,
        homeButton: false,
        fullscreenButton: false,
        animation: false,
        sceneModePicker: false,
        navigationHelpButton: false,
    });

    viewer.cesiumWidget.creditContainer.style.display = "none";
    viewer.scene.globe.depthTestAgainstTerrain = true;
    viewer.scene.globe.enableLighting = true;

    // 设置初始视角以更好地观察地形
    viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(
            120.619907115, // 经度
            31.317987368,  // 纬度
            2000          // 高度
        ),
        orientation: {
            heading: 0.0,
            pitch: Cesium.Math.toRadians(-45),
            roll: 0.0
        }
    });

    // 添加高清影像图层
    viewer.imageryLayers.addImageryProvider(new Cesium.IonImageryProvider({
        assetId: 3 // Bing Maps Aerial 影像
    }));

    // 初始化无人机位置和视频投影
    let dronePosition = {
        lng: 120.619907115,
        lat: 31.317987368,
        height: 500
    };
    // 创建无人机模型实体
    const drone = viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(dronePosition.lng, dronePosition.lat, dronePosition.height),
        model: {
            uri: '../CesiumDrone.glb',//你的无人机模型
            minimumPixelSize: 100,
            maximumScale: 2000,
            scale: 0.5,
        },
        orientation: new Cesium.CallbackProperty(() => {
            // 添加90度偏移来修正朝向
            const headingOffset = Cesium.Math.toRadians(-90);
            return Cesium.Transforms.headingPitchRollQuaternion(
                Cesium.Cartesian3.fromDegrees(dronePosition.lng, dronePosition.lat, dronePosition.height),
                new Cesium.HeadingPitchRoll(droneHeading + headingOffset, 0, 0)
            );
        }, false)
    });

    // 初始化视频投影
    let videoProjection = new CesiumVideo3d(Cesium, viewer, {
        position: {
            x: dronePosition.lng,  // 投影相机位置的经度
            y: dronePosition.lat,  // 投影相机位置的纬度
            z: dronePosition.height // 投影相机位置的高度(单位:米)
        },
        far: 1000,    // 视锥体远裁剪面距离,决定投影的最大距离(单位:米)
        rotation: {
            y: 0,     // 航向角,决定投影方向的水平旋转角度(0度为正北,90度为正东)
            x: -45    // 俯仰角,决定投影的垂直倾斜角度(-90度为垂直向下,0度为水平)
        },
        url: '../demo.mp4',  // 要投影的视频文件路径
        alpha: 0.8,   // 投影的透明度(0-1之间,1为完全不透明)
        near: 0.5,    // 视锥体近裁剪面距离,决定投影的最小距离(单位:米)
        fov: 60,      // 视场角,决定投影的张角大小(单位:度,值越大投影范围越大)
        debugFrustum: true  // 是否显示视锥体的线框,用于调试
    });

    // 删除 WebSocket 相关代码,替换为 setInterval
    let droneHeading = 0;
    let lastPosition = null;
    let time = 0;

    // 使用 setInterval 模拟位置更新
    setInterval(() => {
        time += 0.05;
        
        // 模拟圆形飞行路径
        const radius = 0.005;
        const centerLng = 120.619907115;
        const centerLat = 31.317987368;
        
        // 计算新位置
        const newLng = centerLng + radius * Math.cos(time);
        const newLat = centerLat + radius * Math.sin(time);
        
        // 获取地形高度
        const positions = [Cesium.Cartographic.fromDegrees(newLng, newLat)];
        
        // 使用 Promise 替代 Cesium.when
        Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, positions)
            .then(function(updatedPositions) {
                // 地形高度加上偏移量作为飞行高度
                const terrainHeight = updatedPositions[0].height || 0;
                const flyHeight = terrainHeight + 300; // 300米的相对高度
                
                const newPosition = {
                    lng: newLng,
                    lat: newLat,
                    height: flyHeight
                };
                
                // 更新无人机位置
                dronePosition = newPosition;
                
                // 计算航向角
                if (lastPosition) {
                    const deltaLng = dronePosition.lng - lastPosition.lng;
                    const deltaLat = dronePosition.lat - lastPosition.lat;
                    droneHeading = Math.atan2(deltaLng, deltaLat);
                }
                lastPosition = {...dronePosition};
                
                // 更新无人机实体位置
                drone.position = Cesium.Cartesian3.fromDegrees(
                    dronePosition.lng,
                    dronePosition.lat,
                    dronePosition.height
                );
                
                // 更新视频投影位置和方向
                videoProjection._changeCameraPosition({
                    x: dronePosition.lng,
                    y: dronePosition.lat,
                    z: dronePosition.height
                });
                
                videoProjection._changeRotation({
                    y: Cesium.Math.toDegrees(droneHeading),
                    x: -45
                });
                
                // 相机跟随
                if(time == 0.2) {
                    viewer.camera.setView({
                        destination: Cesium.Cartesian3.fromDegrees(
                            dronePosition.lng,
                            dronePosition.lat,
                            dronePosition.height + 1000
                        ),
                        orientation: {
                            heading: droneHeading,
                            pitch: Cesium.Math.toRadians(-45),
                            roll: 0
                        }
                    });
                }
            })
            .catch(function(error) {
                console.error('Error sampling terrain:', error);
            });
    }, 50); // 每50毫秒更新一次位置

    // 修改清理函数
    function cleanup() {
        if (videoProjection) {
            videoProjection.destroy();
        }
        viewer.entities.remove(drone);
    }

    // 页面关闭时清理资源
    window.onbeforeunload = cleanup;
</script>
</body>
</html> 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973670.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

滚珠花键在使用时需注意什么?

滚珠花键是一种直线运动系统&#xff0c;当花键套利用其中的钢球在经过精密磨削的花键轴上直线运动时&#xff0c;可以传递扭矩。在使用滚珠花键时&#xff0c;需要注意以下几个重要的事项&#xff1a; 1、不要擅自拆卸滚珠花键的各部分&#xff0c;因为这样可能会导致异物进入…

AI助力下的PPT革命:DeepSeek 与Kimi的高效创作实践

清华大学出品《DeepSeek&#xff1a;从入门到精通》分享 在忙碌的职场中&#xff0c;制作一份高质量的PPT往往需要投入大量时间和精力&#xff0c;尤其是在临近截止日期时。今天&#xff0c;我们将探索如何借助 AI 工具 —— DeepSeek 和 Kimi —— 让 PPT 制作变得既快捷又高…

PcVue : 点亮马来西亚砂拉越偏远村庄

导读 背景简介 新项目的需求 实施亮点 成果 背景简介 2021年&#xff0c;砂拉越能源公司&#xff08;Sarawak Energy Berhad&#xff09;启动了一项意义非凡的项目-借助太阳能、微型水力发电机等可再生能源&#xff0c;为砂拉越州偏远村庄送去光明与动力。然而&#xff0c…

图论 之 迪斯科特拉算法求解最短路径

文章目录 题目743.网络延迟时间3341.到达最后一个房间的最少时间I 求解最短路径的问题&#xff0c;分为使用BFS和使用迪斯科特拉算法&#xff0c;这两种算法求解的范围是有区别的 BFS适合求解&#xff0c;边的权值都是1的图中的最短路径的问题 图论 之 BFS迪斯科特拉算法适合求…

在mfc中使用自定义三维向量类和计算多个三维向量的平均值

先添加一个普通类, Vector3.h, // Vector3.h: interface for the Vector3 class. // //#if !defined(AFX_VECTOR3_H__53D34D26_95FF_4377_BD54_57F4271918A4__INCLUDED_) #define AFX_VECTOR3_H__53D34D26_95FF_4377_BD54_57F4271918A4__INCLUDED_#if _MSC_VER > 1000 #p…

DM执行计划

DM执行计划 1. 引言 理解执行计划对于优化查询性能、诊断慢查询问题至关重要。本文将从基础概念入手&#xff0c;逐步深入探讨执行计划的各个组成部分&#xff0c;并通过设计用例来验证所学知识。 2. SQL 执行计划基础 SQL 执行计划是数据库引擎在执行 SQL 语句时生成的一个…

【鸿蒙开发】第四十三章 Notification Kit(用户通知服务)

目录​​​​​​​ 1 简介 1.1 使用场景 1.2 能力范围 1.3 业务流程 1.4 通知样式 1.5 约束限制 1.6 与相关Kit的关系 2 请求通知授权 2.1 接口说明 2.2 开发步骤 3 管理通知角标 3.1 接口说明 3.2 开发步骤 4 管理通知渠道 4.1 通知渠道类型说明 4.2 接口说明…

SpringBoot:SSL证书部署+SpringBoot实现HTTPS安全访问

一、前言 SSL协议介于TCP/IP协议栈的第四层&#xff08;传输层&#xff09;和第七层&#xff08;应用层&#xff09;之间&#xff0c;为基于TCP的应用层协议&#xff08;如HTTP&#xff09;提供安全连接。它通过在客户端和服务器之间建立一个加密的通道&#xff0c;确保数据在传…

【数学】数论干货(疑似密码学基础)

文章目录 前言一. 整除、算术基本定理、同余、同余类、剩余系的基本定义1.整除2.算数基本定理3.同余4.同余类&#xff08;也叫剩余类&#xff09;5.剩余系 二. 费马小定理的内容及其证明1.费马小定理基本内容2.费马小定理的证明&#xff08;interesting 版&#xff09; 三. 欧拉…

[实现Rpc] 消息抽象层的具体实现

目录 具象层 _ 消息抽象的实现 信息的抽象类 实现 JsonMessage JsonRequest & JsonResponse 消息-不同消息分装实现 实现 Request RpcRequest TopicRequest ServiceRequest Response RpcResponse TopicResponse ServiceResponse 实现 生产工厂 本篇文章继 …

《A++ 敏捷开发》- 16 评审与结对编程

客户&#xff1a;我们的客户以银行为主&#xff0c;他们很注重质量&#xff0c;所以一直很注重评审。他们对需求评审、代码走查等也很赞同&#xff0c;也能找到缺陷&#xff0c;对提升质量有作用。但他们最困惑的是通过设计评审很难发现缺陷。 我&#xff1a;你听说过敏捷的结对…

PHP房屋出租出售高效预约系统小程序源码

&#x1f3e0; 房屋出租出售高效预约系统 —— 您的智能找房新选择 &#x1f4a1; 这是一款集智慧与匠心于一体的房屋出租出售预约系统&#xff0c;它巧妙地融合了ThinkPHP与Uniapp两大先进框架&#xff0c;精心打造而成。无论是小程序、H5网页&#xff0c;还是APP端&#xff…

给老系统做个安全检查——Burp SqlMap扫描注入漏洞

背景 在AI技术突飞猛进的今天&#xff0c;类似Cursor之类的工具已经能写出堪比大部分程序员水平的代码了。然而&#xff0c;在我们的代码世界里&#xff0c;仍然有不少"老骥伏枥"的系统在兢兢业业地发光发热。这些祖传系统的代码可能早已过时&#xff0c;架构可能岌…

Repeated Sequence

记suma[1]a[2]a[3]...a[n]。 该序列以a[1]&#xff0c;a[2]&#xff0c;a[3]....a[n]为循环节&#xff0c;明显的&#xff0c;问题可转化为:s%sum是否为该序列的某个连续子序列和。 断环为链。将a复制一份。 枚举a[i]为左端点的所有区间的和。再查找s是否存在。二分O&#x…

【DeepSeek】Mac m1电脑部署DeepSeek

一、电脑配置 个人电脑配置 二、安装ollama 简介&#xff1a;Ollama 是一个强大的开源框架&#xff0c;是一个为本地运行大型语言模型而设计的工具&#xff0c;它帮助用户快速在本地运行大模型&#xff0c;通过简单的安装指令&#xff0c;可以让用户执行一条命令就在本地运…

dockerfile 使用环境变量

ARG&#xff1a; Defining build-time variables ARG指令允许您定义在构建阶段可以访问但在构建映像之后不可用的变量。例如&#xff0c;我们将使用这个Dockerfile来构建一个映像&#xff0c;我们在构建过程中使用ARG指令指定的变量。 FROM ubuntu:latest ARG THEARG"fo…

基于WebGIS技术的校园地图导航系统架构与核心功能设计

本文专为IT技术人员、地理信息系统&#xff08;GIS&#xff09;开发者、智慧校园解决方案架构师及相关领域的专业人士撰写。本文提出了一套基于WebGIS技术的校园地图导航系统构建与优化方案&#xff0c;旨在为用户提供高效、智能、个性化的导航体验。如需获取校园地图导航系统技…

idea连接gitee(使用idea远程兼容gitee)

文章目录 先登录你的gitee拿到你的邮箱找到idea的设置选择密码方式登录填写你的邮箱和密码登录成功 先登录你的gitee拿到你的邮箱 具体位置在gitee–>设置–>邮箱管理 找到idea的设置 选择密码方式登录 填写你的邮箱和密码 登录成功

【从0做项目】Java音缘心动(3)———加密算法 MD5 BCrypt

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 零&#xff1a;项目结果展示 一&#xff1a;音乐播放器Web网页介绍 二&#xff1a;加密算法介绍 1&…

新数据结构(12)——代理

什么是代理 在进行操作时有时不希望用户直接接触到目标&#xff0c;这时需要使用代理让用户间接接触到目标 给目标对象提供一个代理对象&#xff0c;并且由代理对象控制着对目标对象的引用 图解&#xff1a; 代理的目的 控制访问&#xff1a;通过代理对象的方式间接的访问目…