import * as Cesium from 'cesium'
|
|
export const RING_STYLES = [
|
{
|
inner: 0,
|
outer: 2000,
|
gradient: ['#FF6A57', '#A11806'],
|
alpha: 0.42,
|
outlineAlpha: 0.85,
|
innerRatio: 0.12,
|
},
|
]
|
|
export const MATERIAL_TYPE = 'RadialGradientMaterial'
|
export const DRONE_TRACK_MATERIAL_TYPE = 'DroneTrackFlowMaterial'
|
|
let materialRegistered = false
|
let droneTrackMaterialRegistered = false
|
let texturedVertexFormat = null
|
|
export const getTexturedVertexFormat = () => {
|
if (!texturedVertexFormat) {
|
texturedVertexFormat =
|
Cesium.MaterialAppearance?.MaterialSupport?.TEXTURED?.vertexFormat || Cesium.VertexFormat.POSITION_AND_ST
|
}
|
return texturedVertexFormat
|
}
|
|
export const registerRadialGradientMaterial = () => {
|
if (materialRegistered || !Cesium?.Material) return
|
materialRegistered = true
|
Cesium.Material._materialCache.addMaterial(MATERIAL_TYPE, {
|
fabric: {
|
type: MATERIAL_TYPE,
|
uniforms: {
|
color1: new Cesium.Color(1.0, 1.0, 1.0, 1.0),
|
color2: new Cesium.Color(0.0, 0.0, 0.0, 1.0),
|
gamma: 1.7,
|
innerCutoff: 0.0,
|
},
|
source: `
|
uniform vec4 color1;
|
uniform vec4 color2;
|
uniform float gamma;
|
uniform float innerCutoff;
|
|
czm_material czm_getMaterial(czm_materialInput materialInput) {
|
czm_material material = czm_getDefaultMaterial(materialInput);
|
vec2 st = materialInput.st - vec2(0.5);
|
float t = clamp(length(st) * 2.0, 0.0, 1.0);
|
vec4 color = mix(color1, color2, t);
|
float ramp = smoothstep(innerCutoff, 1.0, t);
|
float shaped = pow(t, gamma);
|
float alpha = color.a * ramp * shaped;
|
material.diffuse = color.rgb;
|
material.alpha = alpha;
|
return material;
|
}
|
`,
|
},
|
translucent: () => true,
|
})
|
}
|
|
export const registerDroneTrackMaterial = () => {
|
if (droneTrackMaterialRegistered || !Cesium?.Material) return
|
droneTrackMaterialRegistered = true
|
Cesium.Material._materialCache.addMaterial(DRONE_TRACK_MATERIAL_TYPE, {
|
fabric: {
|
type: DRONE_TRACK_MATERIAL_TYPE,
|
uniforms: {
|
color: new Cesium.Color(1.0, 0.28, 0.18, 1.0),
|
speed: 4.0,
|
headWidth: 0.18,
|
glowPower: 1.6,
|
backgroundAlpha: 0.22,
|
},
|
source: `
|
uniform vec4 color;
|
uniform float speed;
|
uniform float headWidth;
|
uniform float glowPower;
|
uniform float backgroundAlpha;
|
|
czm_material czm_getMaterial(czm_materialInput materialInput) {
|
czm_material material = czm_getDefaultMaterial(materialInput);
|
vec2 st = materialInput.st;
|
float time = fract(czm_frameNumber * speed / 1000.0);
|
float flow = fract(st.s - time);
|
float head = smoothstep(headWidth, 0.0, flow) * smoothstep(0.0, headWidth, flow);
|
float alpha = mix(backgroundAlpha, 1.0, head);
|
vec3 rgb = color.rgb;
|
material.diffuse = rgb;
|
material.emission = rgb * alpha * glowPower;
|
material.alpha = color.a * alpha;
|
return material;
|
}
|
`,
|
},
|
translucent: () => true,
|
})
|
}
|
|
export const createRadialGradientMaterial = (color1, color2, options = {}) => {
|
registerRadialGradientMaterial()
|
return Cesium.Material.fromType(MATERIAL_TYPE, { color1, color2, ...(options || {}) })
|
}
|
|
export const createDroneTrackMaterial = options => {
|
registerDroneTrackMaterial()
|
return Cesium.Material.fromType(DRONE_TRACK_MATERIAL_TYPE, {
|
color: new Cesium.Color(1.0, 0.28, 0.18, 1.0),
|
speed: 4.0,
|
headWidth: 0.18,
|
glowPower: 1.6,
|
backgroundAlpha: 0.22,
|
...(options || {}),
|
})
|
}
|
|
export const buildCirclePositions = (center, radiusMeters, steps = 64) => {
|
const positions = []
|
const latRad = Cesium.Math.toRadians(center.latitude)
|
const metersToLat = 1 / 111320
|
const metersToLon = 1 / (111320 * Math.cos(latRad))
|
for (let i = 0; i <= steps; i += 1) {
|
const angle = Cesium.Math.toRadians((i / steps) * 360)
|
const dx = radiusMeters * Math.cos(angle)
|
const dy = radiusMeters * Math.sin(angle)
|
const lon = center.longitude + dx * metersToLon
|
const lat = center.latitude + dy * metersToLat
|
positions.push(Cesium.Cartesian3.fromDegrees(lon, lat))
|
}
|
return positions
|
}
|
|
export const addDeviceRings = (center, ringFillInstancesByStyle, ringOutlineInstancesByStyle, rangeMeters) => {
|
if (!ringFillInstancesByStyle) return
|
const centerPosition = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, 0)
|
const vertexFormat = getTexturedVertexFormat()
|
RING_STYLES.forEach((ring, index) => {
|
if (!ringFillInstancesByStyle[index]) return
|
const outer = Number.isFinite(rangeMeters) && rangeMeters > 0 ? rangeMeters : ring.outer
|
ringFillInstancesByStyle[index].push(
|
new Cesium.GeometryInstance({
|
geometry: new Cesium.EllipseGeometry({
|
center: centerPosition,
|
semiMajorAxis: outer,
|
semiMinorAxis: outer,
|
vertexFormat,
|
}),
|
})
|
)
|
})
|
if (!ringOutlineInstancesByStyle) return
|
RING_STYLES.forEach((ring, index) => {
|
if (!ringOutlineInstancesByStyle[index]) return
|
const outer = Number.isFinite(rangeMeters) && rangeMeters > 0 ? rangeMeters : ring.outer
|
const positions = buildCirclePositions(center, outer)
|
const outlineAlpha = typeof ring.outlineAlpha === 'number' ? ring.outlineAlpha : 0.8
|
ringOutlineInstancesByStyle[index].push(
|
new Cesium.GeometryInstance({
|
geometry: new Cesium.GroundPolylineGeometry({
|
positions,
|
width: 2,
|
}),
|
attributes: {
|
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
|
Cesium.Color.fromCssColorString(ring.gradient[0]).withAlpha(outlineAlpha)
|
),
|
},
|
})
|
)
|
})
|
}
|
|
export class RadialGradientMaterialProperty {
|
constructor(color1, color2) {
|
this._definitionChanged = new Cesium.Event()
|
this.color1 = color1
|
this.color2 = color2
|
}
|
|
get isConstant () {
|
return true
|
}
|
|
get definitionChanged () {
|
return this._definitionChanged
|
}
|
|
getType () {
|
return MATERIAL_TYPE
|
}
|
|
getValue (time, result) {
|
const target = result || {}
|
target.color1 = this.color1
|
target.color2 = this.color2
|
return target
|
}
|
|
equals (other) {
|
return (
|
other instanceof RadialGradientMaterialProperty &&
|
Cesium.Color.equals(this.color1, other.color1) &&
|
Cesium.Color.equals(this.color2, other.color2)
|
)
|
}
|
}
|