Cesium-Examples/examples/cesiumEx/CircleScanSystem.js
2025-03-11 17:51:04 +08:00

268 lines
15 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***
* @category 场景
* @classdesc 场景特效-扩散及扫描特效
* @param {Object} options - 参数。
* @param {String} options.type - 扫描类型 Circle:圆形扩大扫描圈 Radar:区域雷达扫描。
* @param {Boolean} options.lon - 经度 。
* @param {Boolean} options.lat -纬度 。
* @param {String} options.radius - 扫描半径 (默认 1000).
* @param {String} options.scanColor - 颜色 注意颜色必须是 new Cesium.Color(1.0, 0.0, 0.0, 1);rgba形式的red#fff都不行默认 new Cesium.Color(1.0, 0.0, 0.0, 1).
* @param {String} options.interval - 时间 (默认 3000.
*/
class CircleScanSystem {
constructor(viewer,options){
this.viewer = viewer;
var data = {
radius: options.radius || '100',
scanColor: new Cesium.Color(1.0, 0.0, 0.0, 1),
interval:'3000'
}
this.data= Object.assign(data,options);
this.primitives = null;
if(options.type == 'Circle'){
this.primitives = addCircleScan(this.viewer,this.data);
}else if(options.type == 'Radar'){
this.primitives = addRadarScan(this.viewer,this.data);
}
}
/**
*清除
* */
remove(){
this.viewer.scene.postProcessStages.remove(this.primitives);
}
}
/**
*圆形扩大扫描圈
* */
function AddCircleScanPostStage(viewer, cartographicCenter, maxRadius, scanColor, duration) {
var ScanSegmentShader =
"uniform sampler2D colorTexture;\n" +
"uniform sampler2D depthTexture;\n" +
"in vec2 v_textureCoordinates;\n" +
"uniform vec4 u_scanCenterEC;\n" +
"uniform vec3 u_scanPlaneNormalEC;\n" +
"uniform float u_radius;\n" +
"uniform vec4 u_scanColor;\n" +
"out vec4 fragColor;\n" +
"vec4 toEye(in vec2 uv, in float depth)\n" +
" {\n" +
" vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));\n" +
" vec4 posInCamera =czm_inverseProjection * vec4(xy, depth, 1.0);\n" +
" posInCamera =posInCamera / posInCamera.w;\n" +
" return posInCamera;\n" +
" }\n" +
"vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point)\n" +
"{\n" +
"vec3 v01 = point -planeOrigin;\n" +
"float d = dot(planeNormal, v01) ;\n" +
"return (point - planeNormal * d);\n" +
"}\n" +
"float getDepth(in vec4 depth)\n" +
"{\n" +
"float z_window = czm_unpackDepth(depth);\n" +
"z_window = czm_reverseLogDepth(z_window);\n" +
"float n_range = czm_depthRange.near;\n" +
"float f_range = czm_depthRange.far;\n" +
"return (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n" +
"}\n" +
"void main()\n" +
"{\n" +
"fragColor = texture(colorTexture, v_textureCoordinates);\n" +
"float depth = getDepth( texture(depthTexture, v_textureCoordinates));\n" +
"vec4 viewPos = toEye(v_textureCoordinates, depth);\n" +
"vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);\n" +
"float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);\n" +
"if(dis < u_radius)\n" +
"{\n" +
"float f = 1.0 -abs(u_radius - dis) / u_radius;\n" +
"f = pow(f, 4.0);\n" +
"fragColor = mix(fragColor, u_scanColor, f);\n" +
"}\n" +
"}\n";
var _Cartesian3Center = Cesium.Cartographic.toCartesian(cartographicCenter);
var _Cartesian4Center = new Cesium.Cartesian4(_Cartesian3Center.x, _Cartesian3Center.y, _Cartesian3Center.z, 1);
var _CartographicCenter1 = new Cesium.Cartographic(cartographicCenter.longitude, cartographicCenter.latitude, cartographicCenter.height + 500);
var _Cartesian3Center1 = Cesium.Cartographic.toCartesian(_CartographicCenter1);
var _Cartesian4Center1 = new Cesium.Cartesian4(_Cartesian3Center1.x, _Cartesian3Center1.y, _Cartesian3Center1.z, 1);
var _time = (new Date()).getTime();
var _scratchCartesian4Center = new Cesium.Cartesian4();
var _scratchCartesian4Center1 = new Cesium.Cartesian4();
var _scratchCartesian3Normal = new Cesium.Cartesian3();
var ScanPostStage = new Cesium.PostProcessStage({
fragmentShader: ScanSegmentShader,
uniforms: {
u_scanCenterEC: function () {
return Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
},
u_scanPlaneNormalEC: function () {
var temp = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
var temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
_scratchCartesian3Normal.x = temp1.x - temp.x;
_scratchCartesian3Normal.y = temp1.y - temp.y;
_scratchCartesian3Normal.z = temp1.z - temp.z;
Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
return _scratchCartesian3Normal;
},
u_radius: function () {
return maxRadius * (((new Date()).getTime() - _time) % duration) / duration;
},
u_scanColor: scanColor
}
});
viewer.scene.postProcessStages.add(ScanPostStage);
return (ScanPostStage);
}
/**
*添加圆形扩大扫描圈
返回当前圆形扩大扫描圈对象
* */
function addCircleScan(viewer,data){
viewer.scene.globe.depthTestAgainstTerrain = true; //防止移动、放大缩小会视觉偏移depthTestAgainstTerrain // 设置该属性为true之后标绘将位于地形的顶部如果设为false默认值那么标绘将位于平面上。缺陷开启该属性有可能在切换图层时会引发标绘消失的bug。
var CartographicCenter = new Cesium.Cartographic(Cesium.Math.toRadians(data.lon), Cesium.Math.toRadians(data.lat), 0); //中心位子
return AddCircleScanPostStage(viewer, CartographicCenter, data.radius, data.scanColor, data.interval);
}
/**
*区域雷达扫描
* */
function AddRadarScanPostStage(viewer, cartographicCenter, radius, scanColor, duration) {
var ScanSegmentShader =
"uniform sampler2D colorTexture;\n" +
"uniform sampler2D depthTexture;\n" +
"in vec2 v_textureCoordinates;\n" +
"uniform vec4 u_scanCenterEC;\n" +
"uniform vec3 u_scanPlaneNormalEC;\n" +
"uniform vec3 u_scanLineNormalEC;\n" +
"uniform float u_radius;\n" +
"uniform vec4 u_scanColor;\n" +
"out vec4 fragColor;\n" +
"vec4 toEye(in vec2 uv, in float depth)\n" +
" {\n" +
" vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));\n" +
" vec4 posInCamera =czm_inverseProjection * vec4(xy, depth, 1.0);\n" +
" posInCamera =posInCamera / posInCamera.w;\n" +
" return posInCamera;\n" +
" }\n" +
"bool isPointOnLineRight(in vec3 ptOnLine, in vec3 lineNormal, in vec3 testPt)\n" +
"{\n" +
"vec3 v01 = testPt - ptOnLine;\n" +
"normalize(v01);\n" +
"vec3 temp = cross(v01, lineNormal);\n" +
"float d = dot(temp, u_scanPlaneNormalEC);\n" +
"return d > 0.5;\n" +
"}\n" +
"vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point)\n" +
"{\n" +
"vec3 v01 = point -planeOrigin;\n" +
"float d = dot(planeNormal, v01) ;\n" +
"return (point - planeNormal * d);\n" +
"}\n" +
"float distancePointToLine(in vec3 ptOnLine, in vec3 lineNormal, in vec3 testPt)\n" +
"{\n" +
"vec3 tempPt = pointProjectOnPlane(lineNormal, ptOnLine, testPt);\n" +
"return length(tempPt - ptOnLine);\n" +
"}\n" +
"float getDepth(in vec4 depth)\n" +
"{\n" +
"float z_window = czm_unpackDepth(depth);\n" +
"z_window = czm_reverseLogDepth(z_window);\n" +
"float n_range = czm_depthRange.near;\n" +
"float f_range = czm_depthRange.far;\n" +
"return (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n" +
"}\n" +
"void main()\n" +
"{\n" +
"fragColor = texture(colorTexture, v_textureCoordinates);\n" +
"float depth = getDepth( texture(depthTexture, v_textureCoordinates));\n" +
"vec4 viewPos = toEye(v_textureCoordinates, depth);\n" +
"vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);\n" +
"float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);\n" +
"float twou_radius = u_radius * 2.0;\n" +
"if(dis < u_radius)\n" +
"{\n" +
"float f0 = 1.0 -abs(u_radius - dis) / u_radius;\n" +
"f0 = pow(f0, 64.0);\n" +
"vec3 lineEndPt = vec3(u_scanCenterEC.xyz) + u_scanLineNormalEC * u_radius;\n" +
"float f = 0.0;\n" +
"if(isPointOnLineRight(u_scanCenterEC.xyz, u_scanLineNormalEC.xyz, prjOnPlane.xyz))\n" +
"{\n" +
"float dis1= length(prjOnPlane.xyz - lineEndPt);\n" +
"f = abs(twou_radius -dis1) / twou_radius;\n" +
"f = pow(f, 3.0);\n" +
"}\n" +
"fragColor = mix(fragColor, u_scanColor, f + f0);\n" +
"}\n" +
"}\n";
var _Cartesian3Center = Cesium.Cartographic.toCartesian(cartographicCenter);
var _Cartesian4Center = new Cesium.Cartesian4(_Cartesian3Center.x, _Cartesian3Center.y, _Cartesian3Center.z, 1);
var _CartographicCenter1 = new Cesium.Cartographic(cartographicCenter.longitude, cartographicCenter.latitude, cartographicCenter.height + 500);
var _Cartesian3Center1 = Cesium.Cartographic.toCartesian(_CartographicCenter1);
var _Cartesian4Center1 = new Cesium.Cartesian4(_Cartesian3Center1.x, _Cartesian3Center1.y, _Cartesian3Center1.z, 1);
var _CartographicCenter2 = new Cesium.Cartographic(cartographicCenter.longitude + Cesium.Math.toRadians(0.001), cartographicCenter.latitude, cartographicCenter.height);
var _Cartesian3Center2 = Cesium.Cartographic.toCartesian(_CartographicCenter2);
var _Cartesian4Center2 = new Cesium.Cartesian4(_Cartesian3Center2.x, _Cartesian3Center2.y, _Cartesian3Center2.z, 1);
var _RotateQ = new Cesium.Quaternion();
var _RotateM = new Cesium.Matrix3();
var _time = (new Date()).getTime();
var _scratchCartesian4Center = new Cesium.Cartesian4();
var _scratchCartesian4Center1 = new Cesium.Cartesian4();
var _scratchCartesian4Center2 = new Cesium.Cartesian4();
var _scratchCartesian3Normal = new Cesium.Cartesian3();
var _scratchCartesian3Normal1 = new Cesium.Cartesian3();
var ScanPostStage = new Cesium.PostProcessStage({
fragmentShader: ScanSegmentShader,
uniforms: {
u_scanCenterEC: function () {
return Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
},
u_scanPlaneNormalEC: function () {
var temp = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
var temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
_scratchCartesian3Normal.x = temp1.x - temp.x;
_scratchCartesian3Normal.y = temp1.y - temp.y;
_scratchCartesian3Normal.z = temp1.z - temp.z;
Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
return _scratchCartesian3Normal;
},
u_radius:function () {
return radius * 1;
} ,
u_scanLineNormalEC: function () {
var temp = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
var temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
var temp2 = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center2, _scratchCartesian4Center2);
_scratchCartesian3Normal.x = temp1.x - temp.x;
_scratchCartesian3Normal.y = temp1.y - temp.y;
_scratchCartesian3Normal.z = temp1.z - temp.z;
Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
_scratchCartesian3Normal1.x = temp2.x - temp.x;
_scratchCartesian3Normal1.y = temp2.y - temp.y;
_scratchCartesian3Normal1.z = temp2.z - temp.z;
var tempTime = (((new Date()).getTime() - _time) % duration) / duration;
Cesium.Quaternion.fromAxisAngle(_scratchCartesian3Normal, tempTime * Cesium.Math.PI * 2, _RotateQ);
Cesium.Matrix3.fromQuaternion(_RotateQ, _RotateM);
Cesium.Matrix3.multiplyByVector(_RotateM, _scratchCartesian3Normal1, _scratchCartesian3Normal1);
Cesium.Cartesian3.normalize(_scratchCartesian3Normal1, _scratchCartesian3Normal1);
return _scratchCartesian3Normal1;
},
u_scanColor: scanColor
}
});
viewer.scene.postProcessStages.add(ScanPostStage);
return (ScanPostStage);
}
/**
*添加区域雷达扫描
返回当前雷达扫描对象
* */
function addRadarScan(viewer,data){
viewer.scene.globe.depthTestAgainstTerrain = true; //防止移动、放大缩小会视觉偏移depthTestAgainstTerrain // 设置该属性为true之后标绘将位于地形的顶部如果设为false默认值那么标绘将位于平面上。缺陷开启该属性有可能在切换图层时会引发标绘消失的bug。
var CartographicCenter = new Cesium.Cartographic(Cesium.Math.toRadians(data.lon), Cesium.Math.toRadians(data.lat),0); //中心位子
return AddRadarScanPostStage(viewer, CartographicCenter, data.radius, data.scanColor, data.interval);
}