/** * 等高线 */ import Dialog from "../../Obj/Element/Dialog"; import Tools from "../../Tools"; let _DialogObject = null; let material = null; let handler = null; let activeHeightElm = null; let tools activeHeightElm = document.createElement('div') activeHeightElm.className = 'YJ-customize-active-height-elm' activeHeightElm.style.position = 'absolute' activeHeightElm.style.left = '10px' activeHeightElm.style.top = '10px' activeHeightElm.style.width = '100px' // activeHeightElm.style.backgroundColor = 'rgba(0, 0, 0, 0.5)' activeHeightElm.style.textAlign = 'center' activeHeightElm.style.pointerEvents = 'none' activeHeightElm.style.color = '#ff0000' activeHeightElm.style.display = 'none' async function dialog(sdk) { if (!sdk || _DialogObject) { return } if (!material) { createMaterial() } if (!tools) { tools = new Tools() } _DialogObject = await new Dialog(sdk, {}, { title: "等高线", left: '180px', top: '100px', confirmCallBack: options => { }, closeCallBack: () => { _DialogObject = null } }); _DialogObject._element.body.className = _DialogObject._element.body.className + ' contour' let contentElm = document.createElement('div') contentElm.innerHTML = `
高差
m
主线颜色
次线条数
次线颜色
开关
` contentElm.innerHTML = `
开关
` _DialogObject.contentAppChild(contentElm) contentElm.getElementsByClassName('btn-switch')[0].addEventListener('change', (e) => { if (e.target.checked) { if (handler) { handler.destroy() } if (!sdk.viewer.container.getElementsByClassName('YJ-customize-active-height-elm')[0]) { sdk.viewer.container.appendChild(activeHeightElm) } handler = new Cesium.ScreenSpaceEventHandler( sdk.viewer.canvas ) handler.setInputAction((movement) => { let cartesian = sdk.viewer.scene.pickPosition(movement.endPosition) if (cartesian) { let top = 0 let left = 0 if (sdk.viewer && sdk.viewer._element) { let element = sdk.viewer._element.getElementsByClassName('cesium-widget')[0].getElementsByTagName('canvas')[0] top = element.getBoundingClientRect().top + window.scrollY left = element.getBoundingClientRect().left + window.scrollX } activeHeightElm.style.left = movement.endPosition.x - 50 + left + 'px' activeHeightElm.style.top = movement.endPosition.y - 40 + top + 'px' activeHeightElm.style.display = 'block' let pos84 = tools.cartesian3Towgs84(cartesian, sdk.viewer) let mainContourHeight = Math.floor(pos84.alt / material.uniforms.spacing) * material.uniforms.spacing let gap = pos84.alt - mainContourHeight let gap2 = material.uniforms.spacing / (material.uniforms.secondaryLinesCount + 1) let activeHeight = Math.floor(gap / gap2) * gap2 + mainContourHeight if ((pos84.alt - activeHeight) > gap2 / 2) { activeHeight = activeHeight + gap2 } material.uniforms.mouseHeight = pos84.alt material.uniforms.mousePosition = cartesian activeHeightElm.innerHTML = `${activeHeight.toFixed(0)}` } else { activeHeightElm.style.display = 'none' } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) sdk.viewer.scene.globe.material = material; } else { if (handler) { handler.destroy() handler = null } if (sdk.viewer.container.getElementsByClassName('YJ-customize-active-height-elm')[0]) { activeHeightElm.style.display = 'none' sdk.viewer.container.removeChild(activeHeightElm) } sdk.viewer.scene.globe.material = null; } }) } function createMaterial() { Cesium.Material._materialCache._materials.ElevationContour.fabric.source = ` uniform vec4 color; uniform vec4 secondaryLinesColor; uniform float spacing; uniform float width; uniform float secondaryLinesWidth; uniform float mouseHeight; uniform float secondaryLinesCount; // 0=无次线, 1=1条次线, 2=2条次线... czm_material czm_getMaterial(czm_materialInput materialInput) { czm_material material = czm_getDefaultMaterial(materialInput); // 主等高线计算 float distanceToMainContour = mod(materialInput.height, spacing); // 抗锯齿计算 #if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives)) float dxc = abs(dFdx(materialInput.height)); float dyc = abs(dFdy(materialInput.height)); float dFMain = max(dxc, dyc) * czm_pixelRatio * width; #else float dFMain = czm_pixelRatio * width; #endif bool isMainContour = distanceToMainContour < dFMain; bool isSecondaryContour = false; float dFSecondary = 0.0; float secondarySpacing = 0.0; // 只有当存在次线时才计算次线 if(secondaryLinesCount > 0.0) { secondarySpacing = spacing / (secondaryLinesCount + 1.0); float distanceToSecondaryContour = mod(materialInput.height, secondarySpacing); // 确保次线不会与主线重叠 float minDistanceToMain = min(distanceToMainContour, spacing - distanceToMainContour); bool notCloseToMain = minDistanceToMain > dFMain * 2.0; // 2倍线宽缓冲 #if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives)) dFSecondary = max(dxc, dyc) * czm_pixelRatio * secondaryLinesWidth; #else dFSecondary = czm_pixelRatio * secondaryLinesWidth; #endif isSecondaryContour = (distanceToSecondaryContour < dFSecondary) && notCloseToMain; } // 计算当前高度所属的等高线高度 float mainContourHeight = floor(materialInput.height / spacing) * spacing; float secondaryContourHeight = floor(materialInput.height / spacing * (secondaryLinesCount + 1.0)) * spacing / (secondaryLinesCount + 1.0); // 高亮判断 bool shouldHighlight = false; if(isMainContour && abs(mainContourHeight - mouseHeight) < 0.5 * (spacing/(secondaryLinesCount+1.0))) { shouldHighlight = true; } else if(isSecondaryContour && abs(secondaryContourHeight - mouseHeight) < 0.5 * (spacing/(secondaryLinesCount+1.0))) { shouldHighlight = true; } // 颜色输出 vec4 outColor; if(shouldHighlight) { outColor = vec4(1.0, 0.0, 0.0, 1.0); } else if(isMainContour) { outColor = czm_gammaCorrect(vec4(color.rgb, color.a)); } else if(isSecondaryContour) { outColor = czm_gammaCorrect(vec4(secondaryLinesColor.rgb, secondaryLinesColor.a)); } else { outColor = vec4(0.0); } material.diffuse = outColor.rgb; material.alpha = outColor.a; return material; } ` material = new Cesium.Material({ fabric: { type: "ElevationContour", uniforms: { width: 2, secondaryLinesWidth: 1, // 次级线宽度 spacing: 200, color: Cesium.Color.fromCssColorString('#ffd000'), secondaryLinesColor: Cesium.Color.fromCssColorString('#0dff00').withAlpha(0.5), mouseHeight: -100000, mousePosition: new Cesium.Cartesian3(0, 0, 0), secondaryLinesCount: 3 }, } }); } export { dialog }