Files
sdk4.0/src/Global/Contour/index.js

254 lines
8.9 KiB
JavaScript
Raw Normal View History

2025-07-03 13:54:01 +08:00
/**
* 等高线
*/
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 = `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col input-select-unit-box">
<span class="label">高差</span>
<div class="input-number input-number-unit-1">
<input class="input gap" type="number" title="" min="0" max="1000">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col input-select-unit-box" style="flex: 0 0 120px;">
<span class="label">主线颜色</span>
<div class="primary-lice-color"></div>
</div>
</div>
<div class="row">
<div class="col input-select-unit-box">
<span class="label">次线条数</span>
<div class="input-number input-number-unit-1">
<input class="input gap2" type="number" title="" min="0" max="10">
<span class="unit"></span>
<span class="arrow"></span>
</div>
</div>
<div class="col input-select-unit-box" style="flex: 0 0 120px;">
<span class="label">次线颜色</span>
<div class="secondary-lice-color"></div>
</div>
</div>
<div class="row" style="align-items: flex-start;">
<div class="col">
</div>
<div class="col" style="flex: 0 0 120px;">
<span class="label">开关</span>
<input class="btn-switch" type="checkbox">
</div>
</div>
</div>
<span class="custom-divider"></span>
`
contentElm.innerHTML = `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col" style="flex: 0 0 120px;">
<span class="label">开关</span>
<input class="btn-switch" type="checkbox">
</div>
</div>
</div>
`
_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 }