可视域分析示例
这个示例演示如何使用 DMap3D SDK 进行可视域分析,判断观察点能够看到的区域。
效果预览
用户在场景中点击设置观察点,可视区域显示为绿色,不可视区域显示为红色。
完整代码
src/components/ViewshedAnalysis.tsx
import { useEffect, useRef, useState } from 'react'
import * as Cesium from 'cesium'
import DMap3D from 'dmap3d'
import './ViewshedAnalysis.css'
function ViewshedAnalysis() {
const containerRef = useRef<HTMLDivElement>(null)
const viewerRef = useRef<Cesium.Viewer | null>(null)
const toolRef = useRef<any>(null)
const [isActive, setIsActive] = useState(false)
useEffect(() => {
if (!containerRef.current) return
Cesium.Ion.defaultAccessToken = 'your-cesium-ion-token'
const viewer = new Cesium.Viewer(containerRef.current, {
animation: false,
fullscreenButton: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
selectionIndicator: false,
timeline: false,
navigationHelpButton: false,
infoBox: false,
baseLayerPicker: false,
terrain: Cesium.Terrain.fromWorldTerrain(),
})
viewerRef.current = viewer
// 加载 3DTiles 模型(可视域分析需要遮挡物)
const loadTileset = async () => {
const tileset = await Cesium.Cesium3DTileset.fromUrl(
'/3DTiles/model/tileset.json'
)
viewer.scene.primitives.add(tileset)
viewer.zoomTo(tileset)
}
loadTileset()
// 创建可视域分析工具
const tool = new DMap3D.analysis.viewshed(viewer, {
visibleLineColor: '#00ff00', // 可视区域颜色(绿色)
invisibleLineColor: '#ff0000', // 不可视区域颜色(红色)
})
toolRef.current = tool
// 监听分析完成
tool.onAnalysisEnd(() => {
setIsActive(false)
})
return () => {
tool.destroy()
viewer.destroy()
}
}, [])
const handleStart = () => {
const tool = toolRef.current
if (!tool) return
tool.activate()
setIsActive(true)
}
const handleStop = () => {
const tool = toolRef.current
if (!tool) return
tool.deactivate()
setIsActive(false)
}
const handleClear = () => {
const tool = toolRef.current
if (!tool) return
tool.clear()
setIsActive(false)
}
return (
<div className="viewshed-analysis">
<div ref={containerRef} className="cesium-container" />
<div className="control-panel">
<h3>可视域分析</h3>
<p>点击设置观察点,拖动调整方向和范围</p>
<div className="buttons">
<button onClick={handleStart} disabled={isActive}>
{isActive ? '分析中...' : '开始分析'}
</button>
<button onClick={handleStop} disabled={!isActive}>停止</button>
<button onClick={handleClear}>清除</button>
</div>
<div className="legend">
<h4>图例</h4>
<div className="legend-item">
<span className="color-box visible"></span>
<span>可视区域</span>
</div>
<div className="legend-item">
<span className="color-box invisible"></span>
<span>不可视区域</span>
</div>
</div>
<div className="tip">
<h4>操作说明</h4>
<ol>
<li>点击场景设置观察点位置</li>
<li>移动鼠标调整观察方向</li>
<li>再次点击确认分析范围</li>
</ol>
</div>
</div>
</div>
)
}
export default ViewshedAnalysis
样式文件
src/components/ViewshedAnalysis.css
.viewshed-analysis {
position: relative;
width: 100%;
height: 100vh;
}
.cesium-container {
width: 100%;
height: 100%;
}
.control-panel {
position: absolute;
top: 20px;
right: 20px;
background: rgba(255, 255, 255, 0.95);
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
min-width: 250px;
}
.control-panel h3 {
margin: 0 0 10px 0;
font-size: 18px;
}
.control-panel p {
margin: 0 0 15px 0;
color: #666;
font-size: 14px;
}
.buttons {
display: flex;
gap: 8px;
margin-bottom: 15px;
}
.buttons button {
flex: 1;
padding: 8px 12px;
border: none;
border-radius: 4px;
background: #1890ff;
color: white;
cursor: pointer;
font-size: 14px;
}
.buttons button:hover {
background: #40a9ff;
}
.buttons button:disabled {
background: #d9d9d9;
cursor: not-allowed;
}
.legend {
border-top: 1px solid #e8e8e8;
padding-top: 15px;
margin-bottom: 15px;
}
.legend h4 {
margin: 0 0 8px 0;
font-size: 14px;
color: #666;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
margin: 6px 0;
font-size: 14px;
}
.color-box {
width: 20px;
height: 12px;
border-radius: 2px;
}
.color-box.visible {
background: #00ff00;
}
.color-box.invisible {
background: #ff0000;
}
.tip {
border-top: 1px solid #e8e8e8;
padding-top: 15px;
}
.tip h4 {
margin: 0 0 8px 0;
font-size: 14px;
color: #666;
}
.tip ol {
padding-left: 20px;
margin: 0;
}
.tip li {
font-size: 13px;
margin: 4px 0;
color: #666;
}
关键代码说明
1. 加载 3DTiles 模型
const tileset = await Cesium.Cesium3DTileset.fromUrl('/3DTiles/model/tileset.json')
viewer.scene.primitives.add(tileset)
viewer.zoomTo(tileset)
可视域分析需要有遮挡物(建筑、地形等),因此通常需要加载 3DTiles 模型。
2. 创建可视域分析工具
const tool = new DMap3D.analysis.viewshed(viewer, {
visibleLineColor: '#00ff00', // 可视区域颜色
invisibleLineColor: '#ff0000', // 不可视区域颜色
})
3. 分析流程
// 激活分析工具,进入交互模式
tool.activate()
// 用户操作:
// 1. 左键点击设置观察点
// 2. 移动鼠标确定观察方向
// 3. 再次点击完成分析
// 停用分析
tool.deactivate()
// 清除分析结果
tool.clear()
扩展功能
- 参数调节 - 动态调整可视域方向角、俯仰角、距离
- 多观察点 - 同时设置多个观察点进行综合分析
- 区域可视域 - 使用
DMap3D.analysis.viewshedArea进行区域可视域分析 - 结果导出 - 导出可视域分析结果