forked from SuperMap/iClient-JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSUtil.js
More file actions
237 lines (210 loc) · 9 KB
/
SUtil.js
File metadata and controls
237 lines (210 loc) · 9 KB
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
/* Copyright© 2000 - 2018 SuperMap Software Co.Ltd. All rights reserved.
* This program are made available under the terms of the Apache License, Version 2.0
* which accompanies this distribution and is available at http://www.apache.org/licenses/LICENSE-2.0.html.*/
import {Area} from './Area';
import {Color} from './Color';
import {ComputeBoundingBox} from './ComputeBoundingBox';
import {Curve} from './Curve';
import {Env} from './Env';
import {Event} from './Event';
import {Http} from './Http';
import {Log} from './Log';
import {Math as SMath} from './Math';
import {Matrix} from './Matrix';
import {Util} from './Util';
import {Vector} from './Vector';
export class SUtil {
/**
* @function SuperMap.LevelRenderer.SUtil.SUtil_smoothBezier
* @description 贝塞尔平滑曲线。
* @private
* @param {Array} points - 线段顶点数组。
* @param {number} smooth - 平滑等级, 0-1。
* @param {boolean} isLoop - isLoop。
* @param {Array} constraint - 将计算出来的控制点约束在一个包围盒内,比如 [[0, 0], [100, 100]], 这个包围盒会与整个折线的包围盒做一个并集用来约束控制点。
* @param {Array} [originalPosition=[0, 0]] - 参考原点。
* @return {Array} 生成的平滑节点数组。
*/
static SUtil_smoothBezier(points, smooth, isLoop, constraint, originalPosition) {
if (!originalPosition || originalPosition !== 2) {
originalPosition = [0, 0];
}
var __OP = originalPosition;
var cps = [];
var v = [];
var v1 = [];
var v2 = [];
var hasConstraint = !!constraint;
var min, max;
if (hasConstraint) {
min = [Infinity, Infinity];
max = [-Infinity, -Infinity];
let len = points.length;
for (let i = 0; i < len; i++) {
SUtil.Util_vector.min(min, min, [points[i][0] + __OP[0], points[i][1] + __OP[1]]);
SUtil.Util_vector.max(max, max, [points[i][0] + __OP[0], points[i][1] + __OP[1]]);
}
// 与指定的包围盒做并集
SUtil.Util_vector.min(min, min, constraint[0]);
SUtil.Util_vector.max(max, max, constraint[1]);
}
let len = points.length;
for (let i = 0; i < len; i++) {
let point = [points[i][0] + __OP[0], points[i][1] + __OP[1]];
let prevPoint;
let nextPoint;
if (isLoop) {
prevPoint = [points[i ? i - 1 : len - 1][0] + __OP[0], points[i ? i - 1 : len - 1][1] + __OP[1]];
nextPoint = [points[(i + 1) % len][0] + __OP[0], points[(i + 1) % len][1] + __OP[1]];
} else {
if (i === 0 || i === len - 1) {
cps.push([points[i][0] + __OP[0], points[i][1] + __OP[1]]);
continue;
} else {
prevPoint = [points[i - 1][0] + __OP[0], points[i - 1][1] + __OP[1]];
nextPoint = [points[i + 1][0] + __OP[0], points[i + 1][1] + __OP[1]];
}
}
SUtil.Util_vector.sub(v, nextPoint, prevPoint);
// use degree to scale the handle length
SUtil.Util_vector.scale(v, v, smooth);
let d0 = SUtil.Util_vector.distance(point, prevPoint);
let d1 = SUtil.Util_vector.distance(point, nextPoint);
let sum = d0 + d1;
if (sum !== 0) {
d0 /= sum;
d1 /= sum;
}
SUtil.Util_vector.scale(v1, v, -d0);
SUtil.Util_vector.scale(v2, v, d1);
let cp0 = SUtil.Util_vector.add([], point, v1);
let cp1 = SUtil.Util_vector.add([], point, v2);
if (hasConstraint) {
SUtil.Util_vector.max(cp0, cp0, min);
SUtil.Util_vector.min(cp0, cp0, max);
SUtil.Util_vector.max(cp1, cp1, min);
SUtil.Util_vector.min(cp1, cp1, max);
}
cps.push(cp0);
cps.push(cp1);
}
if (isLoop) {
cps.push(cps.shift());
}
return cps;
}
/**
* @function SuperMap.LevelRenderer.SUtil.SUtil_smoothSpline
* @description 插值折线。
* @private
* @param {Array} points - 线段顶点数组。
* @param {boolean} isLoop - isLoop。
* @param {Array} constraint - 将计算出来的控制点约束在一个包围盒内,比如 [[0, 0], [100, 100]], 这个包围盒会与整个折线的包围盒做一个并集用来约束控制点。
* @param {Array} originalPosition - 参考原点。默认值:[0, 0]。
* @return {Array} 生成的平滑节点数组。
*/
static SUtil_smoothSpline(points, isLoop, constraint, originalPosition) {
if (!originalPosition || originalPosition !== 2) {
originalPosition = [0, 0];
}
var __OP = originalPosition;
var len = points.length;
var ret = [];
var distance = 0;
for (let i = 1; i < len; i++) {
distance += SUtil.Util_vector.distance([points[i - 1][0] + __OP[0], points[i - 1][1] + __OP[1]], [points[i][0] + __OP[0], points[i][1] + __OP[1]]);
}
var segs = distance / 5;
segs = segs < len ? len : segs;
for (let i = 0; i < segs; i++) {
let pos = i / (segs - 1) * (isLoop ? len : len - 1);
let idx = Math.floor(pos);
let w = pos - idx;
let p0;
let p1 = [points[idx % len][0] + __OP[0], points[idx % len][1] + __OP[1]];
let p2;
let p3;
if (!isLoop) {
p0 = [points[idx === 0 ? idx : idx - 1][0] + __OP[0], points[idx === 0 ? idx : idx - 1][1] + __OP[1]];
p2 = [points[idx > len - 2 ? len - 1 : idx + 1][0] + __OP[0], points[idx > len - 2 ? len - 1 : idx + 1][1] + __OP[1]];
p3 = [points[idx > len - 3 ? len - 1 : idx + 2][0] + __OP[0], points[idx > len - 3 ? len - 1 : idx + 2][1] + __OP[1]];
} else {
p0 = [points[(idx - 1 + len) % len][0] + __OP[0], points[(idx - 1 + len) % len][1] + __OP[1]];
p2 = [points[(idx + 1) % len][0] + __OP[0], points[(idx + 1) % len][1] + __OP[1]];
p3 = [points[(idx + 2) % len][0] + __OP[0], points[(idx + 2) % len][1] + __OP[1]];
}
let w2 = w * w;
let w3 = w * w2;
ret.push([
interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3),
interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3)
]);
}
return ret;
// inner Function
function interpolate(p0, p1, p2, p3, t, t2, t3) {
var v0 = (p2 - p0) * 0.5;
var v1 = (p3 - p1) * 0.5;
return (2 * (p1 - p2) + v0 + v1) * t3
+ (-3 * (p1 - p2) - 2 * v0 - v1) * t2
+ v0 * t + p1;
}
}
/**
* @function SuperMap.LevelRenderer.SUtil.SUtil_dashedLineTo
* @description 虚线 lineTo。
*/
static SUtil_dashedLineTo(ctx, x1, y1, x2, y2, dashLength, customDashPattern) {
// http://msdn.microsoft.com/en-us/library/ie/dn265063(v=vs.85).aspx
var dashPattern = [5, 5];
dashLength = typeof dashLength != 'number'
? 5
: dashLength;
if (ctx.setLineDash) {
dashPattern[0] = dashLength;
dashPattern[1] = dashLength;
if (customDashPattern && (customDashPattern instanceof Array)) {
ctx.setLineDash(customDashPattern);
} else {
ctx.setLineDash(dashPattern);
}
// ctx.setLineDash(dashPattern);
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
return;
}
var dx = x2 - x1;
var dy = y2 - y1;
var numDashes = Math.floor(
Math.sqrt(dx * dx + dy * dy) / dashLength
);
dx = dx / numDashes;
dy = dy / numDashes;
var flag = true;
for (var i = 0; i < numDashes; ++i) {
if (flag) {
ctx.moveTo(x1, y1);
} else {
ctx.lineTo(x1, y1);
}
flag = !flag;
x1 += dx;
y1 += dy;
}
ctx.lineTo(x2, y2);
}
}
// 把所有工具对象放到全局静态变量上,以便直接调用工具方法,
// 避免使用工具时频繁的创建工具对象带来的性能消耗。
SUtil.Util_area = new Area();
SUtil.Util_color = new Color();
SUtil.Util_computeBoundingBox = new ComputeBoundingBox();
SUtil.Util_curve = new Curve();
SUtil.Util_env = new Env();
SUtil.Util_event = new Event();
SUtil.Util_http = new Http();
SUtil.Util_log = new Log();
SUtil.Util_math = new SMath();
SUtil.Util_matrix = new Matrix();
SUtil.Util = new Util();
SUtil.Util_vector = new Vector();