feat:后台管理通用航线加载相关方法、hook、航线材质等处理
1 files modified
3 files added
| New file |
| | |
| | | import * as Cesium from 'cesium' |
| | | |
| | | import { analyzeKmzFile, removeTextKey, XMLToJSON } from '@/utils/cesium/kmz' |
| | | import { camelToSnake } from '@/utils/util' |
| | | import _, { cloneDeep, throttle } from 'lodash' |
| | | import * as turf from '@turf/turf' |
| | | |
| | | /** |
| | | * 判断action里面是否有key |
| | | * @param action |
| | | * @param key |
| | | * @returns {{hasKey: boolean, val: *}|{hasKey: boolean, val: null}} |
| | | */ |
| | | export function actionHasKey (action, key) { |
| | | const curActionParams = action?.action_actuator_func_param |
| | | const val = curActionParams?.[key] |
| | | if (val !== undefined) { |
| | | return { hasKey: true, val } |
| | | } else { |
| | | return { hasKey: false, val: null } |
| | | } |
| | | } |
| | | |
| | | // 解析kmz文件的时候处理pointList 写在这里 |
| | | export function handlePointListForKmz ({ placemark, startPoint, execute_height_mode, auto_flight_speed }) { |
| | | if (!placemark?.length) return [] |
| | | const isWGS84 = execute_height_mode === 'WGS84' |
| | | const list = placemark.map(item => { |
| | | const [longitude, latitude] = item.point.coordinates.trim().split(',') |
| | | let action_modes = item?.action_group?.action || [] |
| | | action_modes = Array.isArray(action_modes) ? action_modes : [action_modes] |
| | | return { |
| | | longitude: _.round(longitude, 8), |
| | | latitude: _.round(latitude, 8), |
| | | height: isWGS84 ? item.execute_height : item.execute_height + startPoint.height, |
| | | waypoint_speed: item.waypoint_speed, |
| | | action_modes, |
| | | } |
| | | }) |
| | | const pointStart = { |
| | | ...startPoint, |
| | | flyRotateYaw: 0, |
| | | pointType: 'start', |
| | | waypoint_speed: auto_flight_speed, |
| | | heading: 0, // 椎体 heading |
| | | arrowHeading: 0, // 飞行器 heading |
| | | pitch: 0, //椎体俯仰角 |
| | | fov: 19.5, // 这个是椎体的展示截面大小 |
| | | } |
| | | list.forEach(item => { |
| | | item?.action_modes?.forEach(item1 => { |
| | | let { hasKey: has_focal_length, val: focal_length } = actionHasKey(item1, 'focal_length') |
| | | // 处理focalLength需要/24 focalLength可能是‘1,024’ |
| | | if (has_focal_length && focal_length) { |
| | | focal_length = typeof focal_length === 'string' ? focal_length.replace(/,/g, '') : focal_length |
| | | item1.action_actuator_func_param.focal_length = Number(focal_length) / 24 |
| | | } |
| | | }) |
| | | item.arrowHeading = 0 |
| | | }) |
| | | return [pointStart, ...list] |
| | | } |
| | | |
| | | export async function analysisPointLineKmz (kmzUrl) { |
| | | const res = await analyzeKmzFile(`${kmzUrl}?_t=${new Date().getTime()}`) |
| | | const templateXML = await res.fileInfoObj['wpmz/template.kml'] |
| | | const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml'] |
| | | const templateXMLJSON = XMLToJSON(templateXML)?.['Document'] |
| | | const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document'] |
| | | const templateXMLObj = camelToSnake(removeTextKey(templateXMLJSON)) |
| | | const waylinesXMLObj = camelToSnake(removeTextKey(waylinesXMLJSON)) |
| | | const { |
| | | mission_config: { |
| | | take_off_ref_point, |
| | | drone_info: { drone_enum_value, drone_sub_enum_value } = {} |
| | | } = {}, |
| | | folder: { |
| | | payload_param: { image_format } = {}, |
| | | placemark: { |
| | | polygon |
| | | }, |
| | | global_height, auto_flight_speed, |
| | | template_type: templateType |
| | | } = {}, |
| | | } = templateXMLObj |
| | | |
| | | const { |
| | | mission_config: { take_off_security_height } = {}, |
| | | folder: polygonPointFolder |
| | | } = waylinesXMLObj |
| | | |
| | | let execute_height_mode = '', pointPlacemark |
| | | |
| | | if (templateType === "mapping3d") { |
| | | execute_height_mode = polygonPointFolder[0].execute_height_mode |
| | | pointPlacemark = polygonPointFolder.map(i => i.placemark) |
| | | } else { |
| | | execute_height_mode = polygonPointFolder.execute_height_mode |
| | | pointPlacemark = polygonPointFolder.placemark |
| | | } |
| | | |
| | | const [latitude, longitude, height] = take_off_ref_point.split(',').map(item => _.round(item, 6)) |
| | | let startPoint = { latitude, longitude, height } |
| | | |
| | | // 取出点位 |
| | | const coordinates = polygon?.outer_boundary_is.linear_ring |
| | | .coordinates?.split('\n') || [] |
| | | |
| | | // 数组转换 |
| | | let polygonList = coordinates.map((coordinate) => |
| | | coordinate |
| | | .replace(/\s+/g, '') |
| | | .split(',') |
| | | .map((v) => Number(v)), |
| | | ) |
| | | |
| | | polygonList.pop() |
| | | |
| | | return { |
| | | image_format, |
| | | startPoint, |
| | | global_height, |
| | | auto_flight_speed, |
| | | take_off_ref_point, |
| | | drone_enum_value, |
| | | drone_sub_enum_value, |
| | | take_off_security_height, |
| | | execute_height_mode, |
| | | templateType, |
| | | pointPlacemark, |
| | | polygonList |
| | | } |
| | | } |
| | | |
| | | // 获取连接地面线 |
| | | export function getPolyLine (viewer, pointList, index) { |
| | | return { |
| | | positions: new Cesium.CallbackProperty(() => { |
| | | const point = pointList.value[index] |
| | | const pointPosition = Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height) |
| | | if (!pointPosition) return [] |
| | | // 获取点的位置 |
| | | const cartographic = Cesium.Cartographic.fromCartesian(pointPosition) |
| | | // 获取地形高度 |
| | | const terrainHeight = viewer.scene.globe.getHeight(cartographic) || 0 |
| | | // 创建地面点位置 |
| | | const groundPosition = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, terrainHeight) |
| | | |
| | | return [pointPosition, groundPosition] |
| | | }, false), |
| | | width: 0.5, |
| | | material: Cesium.Color.WHITE, |
| | | } |
| | | } |
| | | |
| | | export function getNewPolygonData (data) { |
| | | const polygonData = data.reduce((pre, cur) => { |
| | | let arr = cur.data.map(i => { |
| | | if ('point' in i) return i.point.coordinates.split(',') |
| | | if ('Point' in i) { |
| | | if (_.isObject(i.Point.coordinates) && '#text' in i.Point.coordinates) return i.Point.coordinates['#text'].split(',') |
| | | return i.Point.coordinates.split(',') |
| | | } |
| | | }).map(i => turf.point([Number(i[0]), Number(i[1])])) |
| | | |
| | | return pre.push(...arr), pre |
| | | }, []) |
| | | |
| | | const hull = turf.convex(turf.featureCollection(polygonData)) |
| | | |
| | | return hull.geometry.coordinates[0] |
| | | } |
| New file |
| | |
| | | import * as Cesium from 'cesium' |
| | | |
| | | import { |
| | | analysisPointLineKmz, |
| | | handlePointListForKmz, |
| | | getPolyLine, |
| | | getNewPolygonData, |
| | | } from '@/hooks/common' |
| | | |
| | | import rwqfdImg from '@/assets/images/signMachineNest/rwqfd.png' |
| | | import endPointImg from '@/assets/images/EndPointicon.png' |
| | | |
| | | import { ArrowLineMaterialProperty } from '@/utils/cesium/Material' |
| | | import { flyVisual } from '@/utils/cesium/mapUtil' |
| | | |
| | | let arrowLineMaterialProperty = new ArrowLineMaterialProperty({ |
| | | color: new Cesium.Color(128 / 255, 215 / 255, 255 / 255, 1), |
| | | directionColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineWidth: 0, |
| | | speed: 5, |
| | | }) |
| | | |
| | | export function useRouteLine () { |
| | | let viewer = null |
| | | let previewDataSource = null |
| | | |
| | | const curRouteLineData = ref({ |
| | | data: [], |
| | | polygonList: '', |
| | | templateType: '', |
| | | startPoint: '', |
| | | execute_height_mode: '', |
| | | auto_flight_speed: '', |
| | | wayline_type: '', |
| | | }) |
| | | |
| | | const routeLineListClick = async data => { |
| | | if (data.select) return |
| | | curRouteLineData.value.data.forEach(i => (i.select = false)) |
| | | data.select = true |
| | | await renderRouteLine(data.data) |
| | | } |
| | | |
| | | async function renderPreviewLine (kmzUrl, wayline_type, cb = () => { }) { |
| | | resetCurRouteLineData() |
| | | |
| | | const { pointPlacemark, polygonList, templateType, startPoint, execute_height_mode, auto_flight_speed } = |
| | | await analysisPointLineKmz(kmzUrl) |
| | | |
| | | curRouteLineData.value = { |
| | | polygonList, |
| | | templateType, |
| | | startPoint, |
| | | execute_height_mode, |
| | | auto_flight_speed, |
| | | wayline_type, |
| | | } |
| | | |
| | | cb(curRouteLineData.value.polygonList.map(item => [Number(item[0]), Number(item[1])])) |
| | | |
| | | if (templateType === 'mapping3d') { |
| | | curRouteLineData.value.data = pointPlacemark.map(item => ({ |
| | | data: item, |
| | | select: false, |
| | | })) |
| | | routeLineListClick(curRouteLineData.value.data[0]) |
| | | } else { |
| | | curRouteLineData.value.data = [] |
| | | await renderRouteLine(pointPlacemark) |
| | | } |
| | | } |
| | | |
| | | async function renderRouteLine (data) { |
| | | if (previewDataSource) { |
| | | removePreviewLine() |
| | | } else { |
| | | previewDataSource = new Cesium.CustomDataSource('previewDataSource') |
| | | await viewer.dataSources.add(previewDataSource) |
| | | } |
| | | |
| | | let lineMaterial = [2, 4].includes(Number(curRouteLineData.value.wayline_type)) |
| | | ? Cesium.Color.fromCssColorString('#00D690') |
| | | : arrowLineMaterialProperty |
| | | |
| | | if ([2, 4].includes(Number(curRouteLineData.value.wayline_type))) { |
| | | if (curRouteLineData.value.templateType === 'mapping3d') { |
| | | let newPolygonData = getNewPolygonData(curRouteLineData.value.data) |
| | | |
| | | let newPolygonDisposePositions = newPolygonData.map(i => |
| | | Cesium.Cartesian3.fromDegrees(Number(i[0]), Number(i[1])) |
| | | ) |
| | | |
| | | previewDataSource.entities.add({ |
| | | polygon: { |
| | | hierarchy: new Cesium.CallbackProperty(() => { |
| | | return new Cesium.PolygonHierarchy(newPolygonDisposePositions) |
| | | }, false), |
| | | material: Cesium.Color.fromBytes(255, 228, 22, 44), |
| | | outline: false, |
| | | outlineWidth: 2, |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | let polygonDisposePositions = curRouteLineData.value.polygonList.map(item => { |
| | | return Cesium.Cartesian3.fromDegrees(Number(item[0]), Number(item[1]), Number(item[2])) |
| | | }) |
| | | |
| | | previewDataSource.entities.add({ |
| | | polygon: { |
| | | hierarchy: new Cesium.CallbackProperty(() => { |
| | | return new Cesium.PolygonHierarchy(polygonDisposePositions) |
| | | }, false), |
| | | material: Cesium.Color.fromBytes(45, 140, 240, 99), |
| | | outline: false, |
| | | outlineWidth: 2, |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | }, |
| | | |
| | | polyline: { |
| | | width: 2, |
| | | material: Cesium.Color.fromBytes(45, 140, 240, 255), |
| | | clampToGround: true, |
| | | positions: new Cesium.CallbackProperty(() => { |
| | | return [...polygonDisposePositions, polygonDisposePositions[0]] |
| | | }, false), |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | | let pointList = handlePointListForKmz({ |
| | | placemark: data, |
| | | startPoint: curRouteLineData.value.startPoint, |
| | | execute_height_mode: curRouteLineData.value.execute_height_mode, |
| | | auto_flight_speed: curRouteLineData.value.auto_flight_speed, |
| | | }) |
| | | |
| | | pointList.shift() |
| | | |
| | | const routePositions = pointList.map(i => Cesium.Cartesian3.fromDegrees(Number(i.longitude), Number(i.latitude), Number(i.height))) |
| | | |
| | | previewDataSource.entities.add({ |
| | | polyline: { |
| | | width: 4, |
| | | positions: routePositions, |
| | | material: lineMaterial, |
| | | clampToGround: false, |
| | | }, |
| | | }) |
| | | |
| | | // 落点线 |
| | | ; (pointList || [])?.forEach((item, index) => { |
| | | const topPosition = Cesium.Cartesian3.fromDegrees(Number(item.longitude), Number(item.latitude), Number(item.height)) |
| | | let setting = { |
| | | position: topPosition, |
| | | polyline: getPolyLine(viewer, { value: pointList }, index), |
| | | } |
| | | previewDataSource.entities.add(setting) |
| | | }) |
| | | |
| | | // 终点 |
| | | previewDataSource.entities.add({ |
| | | position: routePositions[routePositions.length - 1], |
| | | billboard: { |
| | | image: new Cesium.ConstantProperty(endPointImg), |
| | | width: 30, |
| | | height: 30, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 底部对齐 |
| | | }, |
| | | }) |
| | | // 起点 |
| | | previewDataSource.entities.add({ |
| | | position: routePositions[0], |
| | | billboard: { |
| | | image: rwqfdImg, |
| | | width: 50, |
| | | height: 50, |
| | | }, |
| | | }) |
| | | |
| | | flyVisual( |
| | | pointList.map(i => [Number(i.longitude), Number(i.latitude), Number(i.height)]), |
| | | viewer, |
| | | 20 |
| | | ) |
| | | } |
| | | |
| | | function removePreviewLine () { |
| | | previewDataSource?.entities.removeAll() |
| | | } |
| | | |
| | | function resetCurRouteLineData () { |
| | | curRouteLineData.value = { |
| | | data: [], |
| | | polygonList: '', |
| | | templateType: '', |
| | | startPoint: '', |
| | | execute_height_mode: '', |
| | | auto_flight_speed: '', |
| | | wayline_type: '', |
| | | } |
| | | } |
| | | |
| | | const initViewer = (v) => { |
| | | viewer = v |
| | | } |
| | | |
| | | onBeforeUnmount(() => { |
| | | resetCurRouteLineData() |
| | | removePreviewLine() |
| | | }) |
| | | |
| | | return { |
| | | curRouteLineData, |
| | | routeLineListClick, |
| | | initViewer, |
| | | renderPreviewLine, |
| | | removePreviewLine, |
| | | resetCurRouteLineData |
| | | } |
| | | } |
| New file |
| | |
| | | import * as Cesium from 'cesium' |
| | | |
| | | // 多边形渐变材质 |
| | | let pM = "PolyGradientMaterial" |
| | | Cesium.Material._materialCache.addMaterial(pM, { |
| | | strict: true, |
| | | fabric: { |
| | | type: pM, |
| | | uniforms: { |
| | | color: new Cesium.Color(1.0, 1.0, 0.0, 0.5), |
| | | diffusePower: 1.6, |
| | | alphaPower: 1.5, |
| | | center: new Cesium.Cartesian2(0.5, 0.5), |
| | | isInner: false, |
| | | globalAlpha: 1.0, |
| | | }, |
| | | source: ` |
| | | uniform vec4 color; |
| | | uniform float diffusePower; |
| | | uniform float alphaPower; |
| | | uniform float globalAlpha; |
| | | uniform vec2 center; |
| | | uniform bool isInner; |
| | | |
| | | czm_material czm_getMaterial(czm_materialInput materialInput) { |
| | | czm_material material = czm_getDefaultMaterial(materialInput); |
| | | vec2 st = materialInput.st; |
| | | float alphaMars3D = distance(st, center); |
| | | |
| | | if(isInner) { |
| | | material.alpha = (1.0 - (color.a * alphaMars3D * alphaPower)) * globalAlpha; |
| | | if(material.alpha < 0.0) material.alpha = 0.0; |
| | | } else { |
| | | material.alpha = color.a * alphaMars3D * alphaPower * globalAlpha; |
| | | } |
| | | |
| | | material.diffuse = color.rgb * diffusePower; |
| | | return material; |
| | | } |
| | | `, |
| | | }, |
| | | translucent: true, |
| | | }) |
| | | class MaterialProperty { |
| | | constructor(options = {}) { |
| | | this._definitionChanged = new Cesium.Event() |
| | | |
| | | this._color = undefined |
| | | this._glowPower = undefined |
| | | this._taperPower = undefined |
| | | this._directionColor = undefined |
| | | this._outlineColor = undefined |
| | | this._outlineWidth = undefined |
| | | this._opacity = undefined |
| | | this._alphaPower = undefined |
| | | this._speed = undefined |
| | | |
| | | this.color = options.color || Cesium.Color.fromBytes(0, 255, 255, 255) |
| | | this.glowPower = .25 |
| | | this.taperPower = 1 |
| | | this.directionColor = options.directionColor || Cesium.Color.fromBytes(255, 255, 255, 255) |
| | | this.outlineColor = options.outlineColor || Cesium.Color.fromBytes(255, 255, 255, 255) |
| | | this.outlineWidth = 0 |
| | | this.opacity = options.opacity || 0.5 |
| | | this.alphaPower = options.alphaPower || 1.5 |
| | | this.speed = options.speed || 5 |
| | | } |
| | | |
| | | get isConstant () { |
| | | return false |
| | | } |
| | | |
| | | get definitionChanged () { |
| | | return this._definitionChanged |
| | | } |
| | | |
| | | getType (time) { |
| | | return null |
| | | } |
| | | |
| | | getValue (time, result) { |
| | | result = Cesium.defaultValue(result, {}) |
| | | return result |
| | | } |
| | | |
| | | equals (other) { |
| | | return this === other |
| | | } |
| | | } |
| | | class PolyGradientMaterial extends MaterialProperty { |
| | | constructor(options = {}) { |
| | | super(options) |
| | | } |
| | | |
| | | getType (time) { |
| | | return pM |
| | | } |
| | | |
| | | getValue (time, result) { |
| | | if (!result) { |
| | | result = {} |
| | | } |
| | | |
| | | result.color = Cesium.Property.getValueOrUndefined(this._color, time) |
| | | result.globalAlpha = Cesium.Property.getValueOrUndefined(this._opacity, time) |
| | | result.alphaPower = Cesium.Property.getValueOrUndefined(this._alphaPower, time) |
| | | return result |
| | | } |
| | | |
| | | equals (other) { |
| | | return ( |
| | | this === other || |
| | | (other instanceof PolyGradientMaterial && |
| | | Cesium.Property.equals(this._color, other._color) && |
| | | Cesium.Property.equals(this._opacity, other._opacity) && |
| | | Cesium.Property.equals(this._alphaPower, other._alphaPower)) |
| | | ) |
| | | } |
| | | } |
| | | |
| | | Object.defineProperties(PolyGradientMaterial.prototype, { |
| | | color: Cesium.createPropertyDescriptor('color'), |
| | | opacity: Cesium.createPropertyDescriptor('opacity'), |
| | | alphaPower: Cesium.createPropertyDescriptor('alphaPower'), |
| | | }) |
| | | |
| | | // 轨迹线材质 |
| | | let lT = "LineTrailMaterial" |
| | | Cesium.Material._materialCache.addMaterial(lT, { |
| | | fabric: { |
| | | uniforms: { |
| | | color: new Cesium.Color(1.0, 1.0, 0.0, 0.7), |
| | | bgColor: new Cesium.Color(0.0, 1.0, 0.0, 0.0), |
| | | speed: 5, |
| | | globalAlpha: 1.0 |
| | | }, |
| | | source: ` |
| | | uniform vec4 bgColor; |
| | | uniform vec4 color; |
| | | uniform float speed; |
| | | uniform float globalAlpha; |
| | | |
| | | 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); |
| | | vec3 colorMars3D = color.rgb; |
| | | |
| | | if (st.t > 0.45 && st.t < 0.55) { |
| | | colorMars3D = vec3(1.0); |
| | | } |
| | | |
| | | material.alpha = color.a * 1.5 * smoothstep(0.0, 1.0, fract(st.s - time)); |
| | | material.diffuse = max(colorMars3D.rgb * material.alpha, colorMars3D.rgb); |
| | | |
| | | if (material.alpha < bgColor.a) { |
| | | material.alpha = bgColor.a; |
| | | material.diffuse = bgColor.rgb; |
| | | } |
| | | |
| | | material.alpha = material.alpha * globalAlpha; |
| | | return material; |
| | | } |
| | | ` |
| | | }, |
| | | translucent: true |
| | | }) |
| | | class LineTrailMaterial extends MaterialProperty { |
| | | constructor(options = {}) { |
| | | super(options) |
| | | } |
| | | |
| | | getType (time) { |
| | | return lT |
| | | } |
| | | |
| | | getValue (time, result) { |
| | | if (!result) { |
| | | result = {} |
| | | } |
| | | |
| | | result.color = Cesium.Property.getValueOrUndefined(this._color, time) |
| | | result.globalAlpha = Cesium.Property.getValueOrUndefined(this._opacity, time) |
| | | result.speed = Cesium.Property.getValueOrUndefined(this._speed, time) |
| | | return result |
| | | } |
| | | |
| | | equals (other) { |
| | | return ( |
| | | this === other || |
| | | (other instanceof LineTrailMaterial && |
| | | Cesium.Property.equals(this._color, other._color) && |
| | | Cesium.Property.equals(this._opacity, other._opacity) && |
| | | Cesium.Property.equals(this._speed, other._speed)) |
| | | ) |
| | | } |
| | | } |
| | | |
| | | Object.defineProperties(LineTrailMaterial.prototype, { |
| | | color: Cesium.createPropertyDescriptor('color'), |
| | | opacity: Cesium.createPropertyDescriptor('opacity'), |
| | | speed: Cesium.createPropertyDescriptor('speed'), |
| | | }) |
| | | |
| | | |
| | | let arrowLineMaterialType = "ArrowLineMaterial" |
| | | Cesium.Material._materialCache.addMaterial(arrowLineMaterialType, { |
| | | fabric: { |
| | | type: arrowLineMaterialType, |
| | | uniforms: { |
| | | color: new Cesium.Color(0, 1, 1, 1), |
| | | directionColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineWidth: 0, |
| | | speed: 0, // Added speed uniform with default 0 (no animation) |
| | | }, |
| | | source: ` |
| | | #ifdef GL_OES_standard_derivatives |
| | | #extension GL_OES_standard_derivatives : enable |
| | | #endif |
| | | |
| | | uniform vec4 color; |
| | | uniform vec4 directionColor; |
| | | uniform vec4 outlineColor; |
| | | uniform float outlineWidth; |
| | | uniform float speed; // Added speed uniform |
| | | |
| | | in float v_width; |
| | | in float v_polylineAngle; |
| | | |
| | | const float fragLength = 100.0; |
| | | const float startPosition = 0.45; |
| | | const float endPosition = 0.55; |
| | | |
| | | mat2 rotate(float rad) { |
| | | float c = cos(rad); |
| | | float s = sin(rad); |
| | | return mat2(c, s, -s, c); |
| | | } |
| | | |
| | | float getPointOnLine(vec2 p0, vec2 p1, float x) { |
| | | float slope = (p0.y - p1.y) / (p0.x - p1.x); |
| | | return slope * (x - p0.x) + p0.y; |
| | | } |
| | | |
| | | 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 halfInteriorWidth = 0.5 * (v_width - outlineWidth) / v_width; |
| | | float b = step(0.5 - halfInteriorWidth, st.t); |
| | | b *= 1.0 - step(0.5 + halfInteriorWidth, st.t); |
| | | |
| | | float d1 = abs(st.t - (0.5 - halfInteriorWidth)); |
| | | float d2 = abs(st.t - (0.5 + halfInteriorWidth)); |
| | | float dist = min(d1, d2); |
| | | |
| | | vec4 currentColor = mix(outlineColor, color, b); |
| | | vec4 outColor = czm_antialias(outlineColor, color, currentColor, dist); |
| | | outColor = czm_gammaCorrect(outColor); |
| | | |
| | | vec2 pos = rotate(v_polylineAngle) * gl_FragCoord.xy; |
| | | |
| | | // Modified to include animation based on speed and time |
| | | float animationOffset = speed * time; |
| | | float maskS = fract((pos.x / (fragLength * czm_pixelRatio)) - animationOffset); |
| | | |
| | | float maskT = st.t; |
| | | bool isDirection = (maskS > startPosition) && (maskS <= endPosition); |
| | | |
| | | vec4 fragColor; |
| | | if (isDirection) { |
| | | float arrowWidth = (endPosition - startPosition) / 2.0; |
| | | float midS = startPosition + arrowWidth; |
| | | |
| | | float t = 1.0; |
| | | if (maskS < midS) { |
| | | vec2 center = vec2(midS, 0.5); |
| | | float ptOnUpperLine = getPointOnLine(vec2(startPosition, 1.0), center, maskS); |
| | | float ptOnLowerLine = getPointOnLine(vec2(startPosition, 0.0), center, maskS); |
| | | |
| | | t *= 1.0 - step(ptOnUpperLine, maskT); |
| | | t *= step(ptOnLowerLine, maskT); |
| | | t = 1.0 - t; |
| | | } else { |
| | | vec2 center = vec2(endPosition, 0.5); |
| | | float ptOnUpperLine = getPointOnLine(vec2(midS, 1.0), center, maskS); |
| | | float ptOnLowerLine = getPointOnLine(vec2(midS, 0.0), center, maskS); |
| | | |
| | | t *= 1.0 - step(ptOnUpperLine, maskT); |
| | | t *= step(ptOnLowerLine, maskT); |
| | | } |
| | | |
| | | vec4 outsideColor = outColor; |
| | | vec4 currentColor = mix(outsideColor, directionColor, clamp(t, 0.0, 1.0)); |
| | | fragColor = currentColor; |
| | | } else { |
| | | fragColor = outColor; |
| | | } |
| | | |
| | | fragColor = czm_gammaCorrect(fragColor); |
| | | material.diffuse = fragColor.rgb; |
| | | material.alpha = fragColor.a; |
| | | return material; |
| | | }` |
| | | }, |
| | | translucent: true |
| | | }) |
| | | |
| | | class ArrowLineMaterialProperty extends MaterialProperty { |
| | | constructor(options = {}) { |
| | | super(options) |
| | | } |
| | | |
| | | getType (time) { |
| | | return arrowLineMaterialType |
| | | } |
| | | |
| | | getType (time) { |
| | | return arrowLineMaterialType |
| | | } |
| | | |
| | | getValue (time, result) { |
| | | if (!result) { |
| | | result = {} |
| | | } |
| | | |
| | | result.color = Cesium.Property.getValueOrUndefined(this._color, time) |
| | | result.directionColor = Cesium.Property.getValueOrUndefined(this._directionColor, time) |
| | | result.outlineColor = Cesium.Property.getValueOrUndefined(this._outlineColor, time) |
| | | result.outlineWidth = Cesium.Property.getValueOrUndefined(this._outlineWidth, time) |
| | | result.speed = Cesium.Property.getValueOrUndefined(this._speed, time) |
| | | |
| | | return result |
| | | } |
| | | |
| | | equals (other) { |
| | | return ( |
| | | this === other || |
| | | (other instanceof ArrowLineMaterialProperty && |
| | | Cesium.Property.equals(this._color, other._color) && |
| | | Cesium.Property.equals(this._directionColor, other._directionColor) && |
| | | Cesium.Property.equals(this._outlineColor, other._outlineColor) && |
| | | Cesium.Property.equals(this._outlineWidth, other._outlineWidth) && |
| | | Cesium.Property.equals(this._speed, other._speed)) |
| | | ) |
| | | } |
| | | } |
| | | |
| | | Object.defineProperties(ArrowLineMaterialProperty.prototype, { |
| | | color: Cesium.createPropertyDescriptor('color'), |
| | | directionColor: Cesium.createPropertyDescriptor('directionColor'), |
| | | outlineColor: Cesium.createPropertyDescriptor('outlineColor'), |
| | | outlineWidth: Cesium.createPropertyDescriptor('outlineWidth'), |
| | | speed: Cesium.createPropertyDescriptor('speed') |
| | | }) |
| | | |
| | | |
| | | // 轨迹线材质 |
| | | let pLG = "PolylineGlow" |
| | | Cesium.Material._materialCache.addMaterial(pLG, { |
| | | fabric: { |
| | | uniforms: { |
| | | color: new Cesium.Color(0, .5, 1, 1), |
| | | glowPower: .25, |
| | | taperPower: 1 |
| | | }, |
| | | |
| | | source: ` uniform vec4 color; |
| | | uniform float glowPower; |
| | | uniform float taperPower; |
| | | |
| | | czm_material czm_getMaterial(czm_materialInput materialInput) |
| | | { |
| | | czm_material material = czm_getDefaultMaterial(materialInput); |
| | | |
| | | vec2 st = materialInput.st; |
| | | float glow = glowPower / abs(st.t - 0.5) - (glowPower / 0.5); |
| | | |
| | | if (taperPower <= 0.99999) { |
| | | glow *= min(1.0, taperPower / (0.5 - st.s * 0.5) - (taperPower / 0.5)); |
| | | } |
| | | |
| | | vec4 fragColor; |
| | | fragColor.rgb = max(vec3(glow - 1.0 + color.rgb), color.rgb); |
| | | fragColor.a = clamp(0.0, 1.0, glow) * color.a; |
| | | fragColor = czm_gammaCorrect(fragColor); |
| | | |
| | | material.emission = fragColor.rgb; |
| | | material.alpha = fragColor.a; |
| | | |
| | | return material; |
| | | } |
| | | ` |
| | | }, |
| | | translucent: true |
| | | }) |
| | | class PolylineGlowMaterial extends MaterialProperty { |
| | | constructor(options = {}) { |
| | | super(options) |
| | | } |
| | | |
| | | getType (time) { |
| | | return pLG |
| | | } |
| | | |
| | | getValue (time, result) { |
| | | if (!result) { |
| | | result = {} |
| | | } |
| | | |
| | | result.color = Cesium.Property.getValueOrUndefined(this._color, time) |
| | | result.glowPower = Cesium.Property.getValueOrUndefined(this._glowPower, time) |
| | | result.taperPower = Cesium.Property.getValueOrUndefined(this._taperPower, time) |
| | | return result |
| | | } |
| | | |
| | | equals (other) { |
| | | return ( |
| | | this === other || |
| | | (other instanceof LineTrailMaterial && |
| | | Cesium.Property.equals(this._color, other._color) && |
| | | Cesium.Property.equals(this._glowPower, other._glowPower) && |
| | | Cesium.Property.equals(this._taperPower, other._taperPower)) |
| | | ) |
| | | } |
| | | } |
| | | |
| | | Object.defineProperties(PolylineGlowMaterial.prototype, { |
| | | color: Cesium.createPropertyDescriptor('color'), |
| | | glowPower: Cesium.createPropertyDescriptor('glowPower'), |
| | | taperPower: Cesium.createPropertyDescriptor('taperPower'), |
| | | }) |
| | | |
| | | |
| | | export { |
| | | PolyGradientMaterial, |
| | | LineTrailMaterial, |
| | | ArrowLineMaterialProperty, |
| | | PolylineGlowMaterial |
| | | } |
| | |
| | | * @returns {string} |
| | | */ |
| | | export const getSmallImg = url => { |
| | | if (!url) return '' |
| | | const lastDotIndex = url.lastIndexOf('.') |
| | | return `${url.substring(0, lastDotIndex)}_small${url.substring(lastDotIndex)}` |
| | | if (!url) return '' |
| | | const lastDotIndex = url.lastIndexOf('.') |
| | | return `${url.substring(0, lastDotIndex)}_small${url.substring(lastDotIndex)}` |
| | | } |
| | | /** |
| | | * 浏览器判断是否全屏 |
| | |
| | | // 设置默认范围 [上个月, 当前月] |
| | | return [new Date(lastMonthYear, lastMonth, 1), new Date(currentYear, currentMonth, 1)] |
| | | } |
| | | |
| | | // key驼峰转换为下划线 |
| | | export function camelToSnake (obj) { |
| | | if (typeof obj !== 'object' || obj === null) { |
| | | return obj |
| | | } |
| | | |
| | | if (Array.isArray(obj)) { |
| | | return obj.map(item => camelToSnake(item)) |
| | | } |
| | | |
| | | const newObj = {} |
| | | for (const key in obj) { |
| | | if (Object.prototype.hasOwnProperty.call(obj, key)) { |
| | | const newKey = key.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase() |
| | | newObj[newKey] = camelToSnake(obj[key]) |
| | | } |
| | | } |
| | | return newObj |
| | | } |