-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathThinning.ts
217 lines (185 loc) · 5.94 KB
/
Thinning.ts
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
import { Cartesian2, defined, EllipsoidGeodesic, Entity, JulianDate, ScreenSpaceEventType, Viewer } from "cesium";
import { FeatureBase } from "..";
/**
* 抽稀
*
* @export
* @class Thinning
* @extends {FeatureBase}
*/
export default class Thinning extends FeatureBase {
/**
* 获取点函数
*
* @private
* @memberof Thinning
*/
private pointsFunc: ((viewer: Viewer) => Array<Entity>) | undefined;
/**
* x方向 (东方向) 抽稀系数
*
* @private
* @type {number}
* @memberof Thinning
*/
private x: number = 0;
/**
* y方向 (西方向) 抽稀系数
*
* @private
* @type {number}
* @memberof Thinning
*/
private y: number = 0;
constructor(viewer: Viewer) {
super(viewer);
}
/**
* 设置抽稀点获取函数
*
* @param {(viewer: Viewer) => Array<Entity>} pointsFunc
* @return {*}
* @memberof Thinning
*/
setPointsFunc(pointsFunc: (viewer: Viewer) => Array<Entity>): Thinning {
this.pointsFunc = pointsFunc;
return this;
}
/**
* 设置xy抽稀系数
*
* @param {number} x
* @param {number} y
* @return {*}
* @memberof Thinning
*/
setLimitXY(x: number, y: number): Thinning {
this.x = x;
this.y = y;
return this;
}
/**
* 运行抽稀
*
* @memberof Thinning
*/
start() {
this.calThinning();
this.viewer.screenSpaceEventHandler.setInputAction(e => {
this.calThinning();
}, ScreenSpaceEventType.WHEEL)
}
/**
* 停止抽稀
*
* @memberof Thinning
*/
clear(): void {
if (this.pointsFunc)
this.pointsFunc(this.viewer).forEach(entity => entity.show = true);
this.viewer.screenSpaceEventHandler.removeInputAction(ScreenSpaceEventType.WHEEL);
if (this.pointsFunc)
this.pointsFunc = undefined;
this.x = 0;
this.y = 0;
}
private calThinning() {
// 获取抽稀点
if (this.pointsFunc === undefined) return;
let points = this.pointsFunc(this.viewer);
// 获取空间屏幕分辨率
let geoRES = this.calGeoRES();
if (geoRES === null) return;
//获取点范围
let extent = this.calExtent(points);
if (extent === null) return;
let xGES = geoRES * this.x;
let yGES = geoRES * this.y;
const { xMin, yMin, xMax, yMax } = extent;
let hitMap = new Array<Array<Entity>>();
/* xGES (xmax,ymax)
+ + + + + + + + + + + + +
yGES + + p5 + + p4 +
+ + + + +
+ + + + + + + + + + + + +
+ p9 + + p2 + +
+ + + p7(out)+ +
+ + + + + + + + + + + + +
+ + p1 + + p3 +
+ +p10(out)+ + +
+ + + + + + + + + + + + +
+ p6 + + p8 + +
+ + + + +
+ + + + + + + + + + + + +
(xmin,ymin)
*/
points.forEach(point => {
if (point.position) {
let xy = point.position.getValue(JulianDate.now());
let i = Math.round((xy.x - xMin) / xGES);
let j = Math.round((xy.y - yMin) / yGES);
if (hitMap[i] == undefined)
hitMap[i] = new Array<Entity>();
if (hitMap[i][j])
point.show = false;
else {
hitMap[i][j] = point;
point.show = true;
}
}
})
}
/**
* 计算地理分辨率 当前相机层级1px代表的地理长度
*
* @private
* @return {*}
* @memberof Thinning
*/
private calGeoRES(): number | null {
let scene = this.viewer.scene;
// 获取画布的大小
let width = scene.canvas.clientWidth;
let height = scene.canvas.clientHeight;
//获取画布中心两个像素的坐标(默认地图渲染在画布中心位置)
let left = scene.camera.getPickRay(new Cartesian2((width / 2) | 0, (height - 1) / 2));
let right = scene.camera.getPickRay(new Cartesian2(1 + (width / 2) | 0, (height - 1) / 2));
let globe = scene.globe;
let leftPosition = globe.pick(left, scene);
let rightPosition = globe.pick(right, scene);
if (!defined(leftPosition) || !defined(rightPosition) || !leftPosition || !rightPosition) {
return null;
}
let leftCartographic = globe.ellipsoid.cartesianToCartographic(leftPosition);
let rightCartographic = globe.ellipsoid.cartesianToCartographic(rightPosition);
let geodesic = new EllipsoidGeodesic();
geodesic.setEndPoints(leftCartographic, rightCartographic);
return geodesic.surfaceDistance;//分辨率
}
/**
* 计算当前点范围
*
* @private
* @param {Array<Entity>} points
* @return {*}
* @memberof Thinning
*/
private calExtent(points: Array<Entity>): { xMin: number, yMin: number, xMax: number, yMax: number } | null {
if (!points || points.length < 1)
return null;
let xMin = Number.MAX_VALUE;
let yMin = Number.MAX_VALUE;
let xMax = Number.MIN_VALUE;
let yMax = Number.MIN_VALUE;
points.forEach(point => {
if (point.position) {
let xy = point.position.getValue(JulianDate.now());
xMin = Math.min(xMin, xy.x);
yMin = Math.min(yMin, xy.y);
xMax = Math.max(xMax, xy.x);
yMax = Math.max(yMax, xy.y);
}
})
return { xMin, yMin, xMax, yMax };
}
}