当前位置: 首页 > article >正文

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=nullvar videoShed3d=function(cesium,viewer, param) {Cesium=cesiumthis.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}// 创建shadowmapvideoShed3d.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}));*///ClassificationPrimitivereturn 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.3142this.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_lengthif (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>// 初始化 CesiumCesium.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 相关代码,替换为 setIntervallet 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.whenCesium.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> 

相关文章:

cesium视频投影

先看效果 使用cesium做视频投影效果&#xff0c;而且还要跟随无人机移动而移动&#xff0c;我现在用定时器更新无人机的坐标来实现效果具体代码如下&#xff1a; 1、CesiumVideo3d.js(某个cesium技术群大佬分享的) // import ECEF from "./CoordinateTranslate"; le…...

[算法学习笔记]1. 枚举与暴力

一、枚举算法 定义 枚举是基于已有知识来猜测答案的问题求解策略。即在已知可能答案的范围内&#xff0c;通过逐一尝试寻找符合条件的解。 2. 核心思想 穷举验证&#xff1a;对可能答案集合中的每一个元素进行尝试终止条件&#xff1a;找到满足条件的解&#xff0c;或遍历完…...

Burp Suite基本使用(web安全)

工具介绍 在网络安全的领域&#xff0c;你是否听说过抓包&#xff0c;挖掘漏洞等一系列的词汇&#xff0c;这篇文章将带你了解漏洞挖掘的热门工具——Burp Suite的使用。 Burp Suite是一款由PortSwigger Web Security公司开发的集成化Web应用安全检测工具&#xff0c;它主要用于…...

RabbitMQ 3.12.2:单节点与集群部署实战指南

前言&#xff1a;在当今的分布式系统架构中&#xff0c;消息队列已经成为不可或缺的组件之一。它不仅能够实现服务之间的解耦&#xff0c;还能有效提升系统的可扩展性和可靠性。RabbitMQ 作为一款功能强大且广泛使用的开源消息中间件&#xff0c;凭借其高可用性、灵活的路由策略…...

【故障处理】- 11G expdp导出缓慢 + Streams AQ: enqueue blocked on low memory等待事件

【故障处理】- 11G expdp导出缓慢 Streams AQ: enqueue blocked on low memory等待事件 一、概述二、故障原因三、解决方法 一、概述 该问题的数据库版本是11.2.0.4&#xff0c;执行expdp导出的时候&#xff0c;小表导出非常缓慢&#xff0c;同时有Streams AQ: enqueue blocke…...

mac相关命令

显示和隐藏usr等隐藏文件文件 terminal输入: defaults write com.apple.Finder AppleShowAllFiles YESdefaults write com.apple.Finder AppleShowAllFiles NO让.bashrc每次启动shell自动生效 编辑vim ~/.bash_profile 文件, 加上 if [ -f ~/.bashrc ]; then. ~/.bashrc fi注…...

30 款 Windows 和 Mac 下的复制粘贴软件对比

在日常电脑操作中&#xff0c;复制粘贴是极为高频的操作&#xff0c;一款好用的复制粘贴软件能极大提升工作效率。以下为你详细介绍 30 款 Windows 和 Mac 下的复制粘贴软件&#xff0c;并对比它们的优缺点&#xff0c;同时附上官网下载地址&#xff0c;方便大家获取软件。 Pa…...

MYSQL下载安装及使用

MYSQL官网下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 也可以直接在服务器执行指令下载&#xff0c;但是下载速度比较慢。还是自己下载好拷贝过来比较快。 wget https://dev.mysql.com/get/Downloads/mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz 1…...

《仙台有树》里的馅料(序)

《仙台有树》一起追剧吧&#xff08;二&#xff09;&#xff1a;馅料合集概览 ●德爱武美玩&#xff0c;全面发展 ●猜猜我是谁&真假美清歌 ●失忆的风还是吹到了仙台 ●霸道师徒强制收&你拜我&#xff0c;我拜你&#xff0c;师徒徒师甜蜜蜜 ●霸道总裁强制爱 ●仙台有…...

C语言题目:链表数据求和操作

题目描述 读入10个复数&#xff0c;建立对应链表&#xff0c;然后求所有复数的和。 输入格式 无 输出格式 无 样例输入 1 2 1 3 4 5 2 3 3 1 2 1 4 2 2 2 3 3 1 1 样例输出 2323i 代码功能概述 createNode 函数&#xff1a; 创建一个包含 10 个复数节点的链表。 每个…...

如何在不依赖函数调用功能的情况下结合工具与大型语言模型

当大型语言模型&#xff08;LLM&#xff09;原生不支持函数调用功能时&#xff0c;如何实现智能工具调度&#xff1f;本文通过自然语言解析结构化输出控制的方法来实现。 GitHub代码地址 核心实现步骤 定义工具函数 使用tool装饰器声明可调用工具&#xff1a; from langcha…...

统信服务器操作系统V20 1070A 安装docker新版本26.1.4

应用场景&#xff1a; 硬件/整机信息&#xff1a;x86平台、深信服超融合平台 OS版本信息&#xff1a;统信V20 1070a 1.获取docker二进制包 链接: https://pan.baidu.com/s/1SukBlra0mQxvslTfFakzGw?pwd5s5y 提取码: 5s5y tar xvf docker-26.1.4.tgz groupadd docker ch…...

【Linux】文件系统:文件fd

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;linux笔记仓 目录 01.回顾C文件接口02.系统文件I/O02.1 openflags 参数&#xff08;文件打开模式&#xff09;标记位传参1. 访问模式&#xff08;必须指定一个&#xff09;2. 额外控制标志&#xf…...

电脑系统损坏,备份文件

一、工具准备 1.U盘&#xff1a;8G以上就够用&#xff0c;注意会格式化U盘&#xff0c;提前备份U盘内容 2.电脑&#xff1a;下载Windows系统并进行启动盘制作 二、Windows启动盘制作 1.微软官网下载启动盘制作工具微软官网下载启动盘制作工具https://www.microsoft.com/zh-c…...

View Binding小记

View Binding 1.简介 View Binding 是 Android 开发中的一项功能&#xff0c;它允许开发者以类型安全的方式直接访问布局文件中的视图&#xff0c;而无需使用 findViewById View Binding 生成的绑定类中的字段类型与布局文件中的视图类型完全一致&#xff0c;避免了 findVie…...

Python网络运维自动化:从零开始学习NetDevOps

零基础入门NetDevOps&#xff0c;让网络运维更简单、更高效。 Python网络运维自动化 1.从理论到实战&#xff1a;从基础理论入手&#xff0c;通过实战案例教学&#xff0c;手把手教读者掌握Python网络运维自动化&#xff0c;解决运维工作中的日常问题&#xff0c;提升运维效率…...

公网远程家里局域网电脑过程详细记录,包含设置路由器。

由于从校内迁居小区,校内需要远程控制访问小区内个人电脑,于是早些时间刚好自己是电信宽带,可以申请公网ipv4不需要花钱,所以就打电话直接申请即可,申请成功后访问光猫设备管理界面192.168.1.1,输入用户名密码登录超管(密码是网上查下就有了)设置了光猫为桥接模式,然后…...

网络安全示意图 网络安全路线图

其实网络安全本身的知识点并不算难&#xff0c;但需要学的东西比较多&#xff0c;如果想要从事网络安全领域&#xff0c;肯定是需要系统、全面地掌握清楚需要用到的技能的。 自学的方式基本是通过看视频或者相关的书籍&#xff0c;不论是什么方法&#xff0c;都是很难的&#…...

【多线程异步和MQ有什么区别?】

多线程异步和MQ有什么区别? 多线程异步MQ(消息队列)多线程异步与MQ的区别多线程异步 概念: 多线程异步是指在单个应用程序内部创建和管理多个线程,这些线程并行处理任务。 多线程主要用于提升应用程序的性能,特别是在处理计算密集型任务(如科学计算、图像处理、数据分…...

Annie导航2.0 新增加5个模版 开源免授权

新增5个模版 修复部分模版样式问题 采用最新技术tinkphp8.0 php8.1 mysql5.7 Funadmin框架 后台一键式统计访问人数 网站设置 分类设置 网站管理 工具管理 友情链接 广告管理 [color=var(–comiis-color)]联系方式 主题管理 配置多套模版随意切换 已更新市面上热门的几个模版...

Spring AI发布!让Java紧跟AI赛道!

1. 序言 在当今技术发展的背景下&#xff0c;人工智能&#xff08;AI&#xff09;已经成为各行各业中不可忽视的重要技术。无论是在互联网公司&#xff0c;还是传统行业&#xff0c;AI技术的应用都在大幅提升效率、降低成本、推动创新。从智能客服到个性化推荐&#xff0c;从语…...

一个简洁高效的Flask用户管理示例

Flask-Login 是 Flask 的用户管理扩展&#xff0c;提供 用户身份验证、会话管理、权限控制 等功能。 适用于&#xff1a; • 用户登录、登出 • 记住用户&#xff08;“记住我” 功能&#xff09; • 限制未登录用户访问某些页面 • 用户会话管理 1. 安装 Flask-Login pi…...

HTML之JavaScript Form表单事件

HTML之JavaScript Form表单事件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title…...

[文末数据集]ML.NET库学习010:URL是否具有恶意性分类

文章目录 ML.NET库学习010:URL是否具有恶意性分类项目主要目的和原理项目概述主要功能和步骤总结数据集地址ML.NET库学习010:URL是否具有恶意性分类 项目主要目的和原理 项目主要目的: 本项目的目的是通过分析URL的特征,构建一个机器学习模型来判断给定的URL是否具有恶意…...

百度地图接入DeepSeek技术解析:AI如何重塑地图搜索体验?

百度地图接入DeepSeek技术解析&#xff1a;AI如何重塑地图搜索体验&#xff1f; 百度地图接入DeepSeek技术解析&#xff1a;AI如何重塑地图搜索体验&#xff1f;引言一、技术背景与核心能力1.1 DeepSeek的技术优势1.2 百度地图API的技术底座 二、技术实现路径2.1 系统架构设计2…...

C语言——深入理解指针(2)(数组与指针)

文章目录 数组名的理解使用指针访问数组一维数组传参的本质冒泡排序二级指针指针数组指针数组模拟二维数组 数组名的理解 之前我们在使用指针访问数组内容时&#xff0c;有这样的代码&#xff1a; int arr[10]{1,2,3,4,5,6,7,8,9,10}; int* p&arr[0];这里我们使用&ar…...

Open-WebUI官方部署文档

Github地址&#xff1a;GitHub - open-webui/open-webui: User-friendly AI Interface (Supports Ollama, OpenAI API, ...) 打开 WebUI &#x1f44b; 如果你是零基础的小白&#xff0c;不知道什么是DeepSeek的话&#xff1f;不知道如何本地化部署&#xff0c;我强烈建议先看…...

爬虫破解网页禁止F12

右击页面显示如下 先点击f12再输入网址&#xff0c;回车后没有加载任何数据 目前的一种解决方法&#xff1a; 先 AltD &#xff0c;再 CtrlShifti...

vuex 简单使用

vuex 简单使用 示例&#xff1a;管理一个对象状态 假设我们要管理一个用户对象 user&#xff0c;包含 name 和 age 两个属性。 1. 定义 Vuex Store 在 store/index.js 中定义状态、mutations、actions 和 getters&#xff1a; import { createStore } from vuex;const store…...

机器学习_16 朴素贝叶斯知识点总结

朴素贝叶斯&#xff08;Naive Bayes&#xff09;是一种基于贝叶斯定理的概率分类算法&#xff0c;广泛应用于文本分类、垃圾邮件检测和情感分析等领域。它通过计算后验概率来进行分类&#xff0c;核心假设是特征之间相互独立。今天&#xff0c;我们就来深入探讨朴素贝叶斯的原理…...