# cesium-绘制点、线、面
# 介绍
在地图框架中,绘制点线面是最常见的功能,这里我们在cesium中实现它,让其可以在三维地形中贴地
# 实现效果
# 点

# 线

# 面

# 完整代码
这里使用vue实现具体功能
<template>
<div class="home">
<el-row type="flex" :gutter="20">
<el-col :span="24">
<div class="grid-content bg-purple">
<el-breadcrumb separator="/">
<el-breadcrumb-item>cesium</el-breadcrumb-item>
<el-breadcrumb-item>绘制功能</el-breadcrumb-item>
<el-breadcrumb-item>点、线、面</el-breadcrumb-item>
</el-breadcrumb>
</div>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="24">
<div class="grid-content bg-purple">
<cesiumComponent id="cesium" ref="refCesium"/>
</div>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="24">
<div class="grid-content bg-purple">
<el-button type="primary" @click="addDem()">复位</el-button>
<el-button type="primary" @click="draw('point')">绘制点</el-button>
<el-button type="primary" @click="draw('polyline')">绘制线</el-button>
<el-button type="primary" @click="draw('polygon')">绘制面</el-button>
<el-button type="primary" @click="clearDrawEntities">清空</el-button>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import cesiumComponent from '../cesium.vue'
export default {
name: "draw",
data() {
return {
_viewer: undefined,
tempEntities: [],
};
},
components: {
cesiumComponent
},
mounted() {
this.init();
},
methods: {
init() {
this.$refs.refCesium.initMap();
this._viewer = this.$refs.refCesium._viewer;
this.addDem();
},
addDem() {
let that = this;
that._viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
url: '../dem/ASTGTM_N29E087D'
});
that._viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(87.42919921875, 28.700224692776988, 67863.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-45.0),
roll: 0.0
}
});
},
/**
* 根据类型绘制对象
* @param type point、polyline、polygon
*/
draw(type) {
//绘制点
let that = this;
let viewer = this._viewer;
let tempEntities = this.tempEntities;
let position = [];
let tempPoints = [];
// 开启深度检测
viewer.scene.globe.depthTestAgainstTerrain = true;
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
switch (type) {
case 'point':
// 监听鼠标左键
handler.setInputAction(function (movement) {
// 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。
let ray = viewer.camera.getPickRay(movement.position);
// 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象
position = viewer.scene.globe.pick(ray, viewer.scene);
let point = that.drawPoint(position);
tempEntities.push(point);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 左键双击停止绘制
handler.setInputAction(function () {
handler.destroy();//关闭事件句柄
handler = null;
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
// 右击单击停止绘制
handler.setInputAction(function () {
handler.destroy();//关闭事件句柄
handler = null;
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
break;
case 'polyline':
//鼠标移动事件
handler.setInputAction(function (movement) {
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//左键点击操作
handler.setInputAction(function (click) {
//调用获取位置信息的接口
let ray = viewer.camera.getPickRay(click.position);
position = viewer.scene.globe.pick(ray, viewer.scene);
tempPoints.push(position);
let tempLength = tempPoints.length;
//调用绘制点的接口
let point = that.drawPoint(tempPoints[tempPoints.length - 1]);
tempEntities.push(point);
if (tempLength > 1) {
let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
tempEntities.push(pointline);
} else {
// tooltip.innerHTML = "请绘制下一个点,右键结束";
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//右键点击操作
handler.setInputAction(function (click) {
tempPoints = [];
handler.destroy();//关闭事件句柄
handler = null;
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
break;
case 'polygon':
//鼠标移动事件
handler.setInputAction(function (movement) {
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//左键点击操作
handler.setInputAction(function (click) {
//调用获取位置信息的接口
let ray = viewer.camera.getPickRay(click.position);
position = viewer.scene.globe.pick(ray, viewer.scene);
tempPoints.push(position);
let tempLength = tempPoints.length;
//调用绘制点的接口
let point = that.drawPoint(position);
tempEntities.push(point);
if (tempLength > 1) {
let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
tempEntities.push(pointline);
} else {
// tooltip.innerHTML = "请绘制下一个点,右键结束";
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//右键点击操作
handler.setInputAction(function (click) {
let cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid);
if (cartesian) {
let tempLength = tempPoints.length;
if (tempLength < 3) {
alert('请选择3个以上的点再执行闭合操作命令');
} else {
//闭合最后一条线
let pointline = that.drawPolyline([tempPoints[tempPoints.length - 1], tempPoints[0]]);
tempEntities.push(pointline);
that.drawPolygon(tempPoints);
tempEntities.push(tempPoints);
handler.destroy();//关闭事件句柄
handler = null;
}
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
break;
}
},
drawPoint(position, config) {
let viewer = this._viewer;
let config_ = config ? config : {};
return viewer.entities.add({
name: "点几何对象",
position: position,
point: {
color: Cesium.Color.SKYBLUE,
pixelSize: 10,
outlineColor: Cesium.Color.YELLOW,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
}
});
},
drawPolyline(positions, config_) {
let viewer = this._viewer;
if (positions.length < 1) return;
let config = config_ ? config_ : {};
return viewer.entities.add({
name: "线几何对象",
polyline: {
positions: positions,
width: config.width ? config.width : 5.0,
material: new Cesium.PolylineGlowMaterialProperty({
color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
}),
depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
}),
clampToGround: true,
}
});
},
drawPolygon(positions, config_) {
let viewer = this._viewer;
if (positions.length < 2) return;
let config = config_ ? config_ : {};
return viewer.entities.add({
name: "面几何对象",
polygon: {
hierarchy: positions,
material: config.color ? new Cesium.Color.fromCssColorString(config.color).withAlpha(.2) : new Cesium.Color.fromCssColorString("#FFD700").withAlpha(.2),
},
});
},
/**
* 清除实体
*/
clearDrawEntities() {
let viewer = this._viewer;
this.tempEntities = [];
// 清除之前的实体
const entitys = viewer.entities._entities._array;
let length = entitys.length
// 倒叙遍历防止实体减少之后entitys[f]不存在
for (let f = length - 1; f >= 0; f--) {
if (entitys[f]._name && (entitys[f]._name === '点几何对象' || entitys[f]._name === '线几何对象' || entitys[f]._name === '面几何对象')) {
viewer.entities.remove(entitys[f]);
}
}
},
},
created() {
},
}
</script>
<style scoped>
.home {
height: 100%;
margin: 0;
padding: 0;
overflow-y: auto;
overflow-x: hidden;
}
.el-breadcrumb {
margin: 10px;
font-size: 15px;
}
#cesium {
max-height: 600px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# 核心代码
这里实现思路是开启cesium的监听事件,左键开始绘制,右键完成绘制,具体监听事件代码如下:
/**
* 根据类型绘制对象
* @param type point、polyline、polygon
*/
draw(type) {
//绘制点
let that = this;
let viewer = this._viewer;
let tempEntities = this.tempEntities;
let position = [];
let tempPoints = [];
// 开启深度检测
viewer.scene.globe.depthTestAgainstTerrain = true;
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
switch (type) {
case 'point':
// 监听鼠标左键
handler.setInputAction(function (movement) {
// 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。
let ray = viewer.camera.getPickRay(movement.position);
// 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象
position = viewer.scene.globe.pick(ray, viewer.scene);
let point = that.drawPoint(position);
tempEntities.push(point);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 左键双击停止绘制
handler.setInputAction(function () {
handler.destroy();//关闭事件句柄
handler = null;
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
// 右击单击停止绘制
handler.setInputAction(function () {
handler.destroy();//关闭事件句柄
handler = null;
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
break;
case 'polyline':
//鼠标移动事件
handler.setInputAction(function (movement) {
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//左键点击操作
handler.setInputAction(function (click) {
//调用获取位置信息的接口
let ray = viewer.camera.getPickRay(click.position);
position = viewer.scene.globe.pick(ray, viewer.scene);
tempPoints.push(position);
let tempLength = tempPoints.length;
//调用绘制点的接口
let point = that.drawPoint(tempPoints[tempPoints.length - 1]);
tempEntities.push(point);
if (tempLength > 1) {
let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
tempEntities.push(pointline);
} else {
// tooltip.innerHTML = "请绘制下一个点,右键结束";
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//右键点击操作
handler.setInputAction(function (click) {
tempPoints = [];
handler.destroy();//关闭事件句柄
handler = null;
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
break;
case 'polygon':
//鼠标移动事件
handler.setInputAction(function (movement) {
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//左键点击操作
handler.setInputAction(function (click) {
//调用获取位置信息的接口
let ray = viewer.camera.getPickRay(click.position);
position = viewer.scene.globe.pick(ray, viewer.scene);
tempPoints.push(position);
let tempLength = tempPoints.length;
//调用绘制点的接口
let point = that.drawPoint(position);
tempEntities.push(point);
if (tempLength > 1) {
let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
tempEntities.push(pointline);
} else {
// tooltip.innerHTML = "请绘制下一个点,右键结束";
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//右键点击操作
handler.setInputAction(function (click) {
let cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid);
if (cartesian) {
let tempLength = tempPoints.length;
if (tempLength < 3) {
alert('请选择3个以上的点再执行闭合操作命令');
} else {
//闭合最后一条线
let pointline = that.drawPolyline([tempPoints[tempPoints.length - 1], tempPoints[0]]);
tempEntities.push(pointline);
that.drawPolygon(tempPoints);
tempEntities.push(tempPoints);
handler.destroy();//关闭事件句柄
handler = null;
}
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
break;
}
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
绘制点、线、面的代码:
drawPoint(position, config) {
let viewer = this._viewer;
let config_ = config ? config : {};
return viewer.entities.add({
name: "点几何对象",
position: position,
point: {
color: Cesium.Color.SKYBLUE,
pixelSize: 10,
outlineColor: Cesium.Color.YELLOW,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
}
});
},
drawPolyline(positions, config_) {
let viewer = this._viewer;
if (positions.length < 1) return;
let config = config_ ? config_ : {};
return viewer.entities.add({
name: "线几何对象",
polyline: {
positions: positions,
width: config.width ? config.width : 5.0,
material: new Cesium.PolylineGlowMaterialProperty({
color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
}),
depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
}),
clampToGround: true,
}
});
},
drawPolygon(positions, config_) {
let viewer = this._viewer;
if (positions.length < 2) return;
let config = config_ ? config_ : {};
return viewer.entities.add({
name: "面几何对象",
polygon: {
hierarchy: positions,
material: config.color ? new Cesium.Color.fromCssColorString(config.color).withAlpha(.2) : new Cesium.Color.fromCssColorString("#FFD700").withAlpha(.2),
},
});
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47