egovamap 0.35.20 → 0.35.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.md +16 -16
- package/egovamap/EGovaScene.js +195 -195
- package/egovamap/GeometryTrans.js +96 -96
- package/egovamap/RingsConvert.js +181 -181
- package/egovamap/coordconvert/CoordConvConfig.js +7 -7
- package/egovamap/egovagisviewer.js +8 -0
- package/egovamap/egovamap.css +97 -97
- package/egovamap/egovamap.js +14 -0
- package/egovamap/egovamms.js +566 -566
- package/egovamap/globe.html +34 -34
- package/egovamap/globe.jsp +17 -17
- package/egovamap/map.html +47 -47
- package/egovamap/map.jsp +58 -58
- package/egovamap/mapUtils.js +543 -543
- package/egovamap/mapswich.css +157 -157
- package/egovamap/mapswich.js +165 -165
- package/egovamap/mms.jsp +71 -71
- package/index.js +2 -2
- package/map.html +72 -72
- package/package.json +1 -1
package/egovamap/mapUtils.js
CHANGED
|
@@ -1,543 +1,543 @@
|
|
|
1
|
-
import CoordConvConfig from "./coordconvert/CoordConvConfig";
|
|
2
|
-
import * as coordConvert from "egovacoordconvert/build/dist/coordconvert";
|
|
3
|
-
|
|
4
|
-
var MapUtils = {
|
|
5
|
-
type: function (obj) {
|
|
6
|
-
var result = Array.isArray(obj) ? "array" : typeof obj;
|
|
7
|
-
return result;
|
|
8
|
-
},
|
|
9
|
-
deepClones: function () {
|
|
10
|
-
var options,
|
|
11
|
-
name,
|
|
12
|
-
src,
|
|
13
|
-
copy,
|
|
14
|
-
copyIsArray,
|
|
15
|
-
clone,
|
|
16
|
-
target = arguments[0] || {},
|
|
17
|
-
i = 1,
|
|
18
|
-
length = arguments.length,
|
|
19
|
-
deep = false;
|
|
20
|
-
|
|
21
|
-
// Handle a deep copy situation
|
|
22
|
-
if (typeof target === "boolean") {
|
|
23
|
-
deep = target;
|
|
24
|
-
|
|
25
|
-
// Skip the boolean and the target
|
|
26
|
-
target = arguments[i] || {};
|
|
27
|
-
i++;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Handle case when target is a string or something (possible in deep copy)
|
|
31
|
-
if (
|
|
32
|
-
this.type(target) !== "object" &&
|
|
33
|
-
this.type(target) !== "function" &&
|
|
34
|
-
this.type(target) !== "array"
|
|
35
|
-
) {
|
|
36
|
-
target = {};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Extend jQuery itself if only one argument is passed
|
|
40
|
-
if (i === length) {
|
|
41
|
-
target = this;
|
|
42
|
-
i--;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
for (; i < length; i++) {
|
|
46
|
-
// Only deal with non-null/undefined values
|
|
47
|
-
if ((options = arguments[i]) != null) {
|
|
48
|
-
// Extend the base object
|
|
49
|
-
for (name in options) {
|
|
50
|
-
src = target[name];
|
|
51
|
-
copy = options[name];
|
|
52
|
-
|
|
53
|
-
// Prevent never-ending loop
|
|
54
|
-
if (target === copy) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Recurse if we're merging plain objects or arrays
|
|
59
|
-
if (
|
|
60
|
-
deep &&
|
|
61
|
-
copy &&
|
|
62
|
-
(this.type(copy) === "object" ||
|
|
63
|
-
(copyIsArray = this.type(copy) === "array"))
|
|
64
|
-
) {
|
|
65
|
-
if (copyIsArray) {
|
|
66
|
-
copyIsArray = false;
|
|
67
|
-
clone =
|
|
68
|
-
src && this.type(copy) === "array" ? src : [];
|
|
69
|
-
} else {
|
|
70
|
-
clone =
|
|
71
|
-
src && this.type(copy) === "object" ? src : {};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Never move original objects, clone them
|
|
75
|
-
target[name] = this.deepClones(deep, clone, copy);
|
|
76
|
-
|
|
77
|
-
// Don't bring in undefined values
|
|
78
|
-
} else if (copy !== undefined) {
|
|
79
|
-
target[name] = copy;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
// Return the modified object
|
|
85
|
-
return target;
|
|
86
|
-
},
|
|
87
|
-
//初始化
|
|
88
|
-
init: function (context) {
|
|
89
|
-
var coordConvertType = context.coordConvertType;
|
|
90
|
-
var coordParam = context.coordConvertParam;
|
|
91
|
-
var nullParamTypes = [
|
|
92
|
-
"BJCG",
|
|
93
|
-
"GPS",
|
|
94
|
-
"MKT",
|
|
95
|
-
"84ll2bdll",
|
|
96
|
-
"84ll2gcjll",
|
|
97
|
-
"84ll2bdmc",
|
|
98
|
-
"GD",
|
|
99
|
-
];
|
|
100
|
-
if (coordConvertType) {
|
|
101
|
-
if (nullParamTypes.toString().indexOf(coordConvertType) != -1) {
|
|
102
|
-
this.convertType = coordConvertType; //正转类型
|
|
103
|
-
this.coordParam = "";
|
|
104
|
-
this.unCoordParam = "";
|
|
105
|
-
if (coordConvertType == "BJCG")
|
|
106
|
-
this.unConvertType = "unBJCG2WGS84"; //北京城管转84经纬度
|
|
107
|
-
if (coordConvertType == "GPS") this.unConvertType = "GPS";
|
|
108
|
-
if (coordConvertType == "MKT") this.unConvertType = "84mc284ll";
|
|
109
|
-
if (coordConvertType == "84ll2bdll")
|
|
110
|
-
this.unConvertType = "bdll284ll";
|
|
111
|
-
if (coordConvertType == "84ll2gcjll")
|
|
112
|
-
this.unConvertType = "gcjll284ll";
|
|
113
|
-
if (coordConvertType == "84ll2bdmc")
|
|
114
|
-
this.unConvertType = "bdmc2bdll,bdll284ll"; //先转百度经纬度再转84经纬度
|
|
115
|
-
if (coordConvertType == "GD")
|
|
116
|
-
this.unConvertType = "gcjmc2gcjll,gcjll284ll"; //先转高德经纬度再转84经纬度
|
|
117
|
-
} else {
|
|
118
|
-
this.convertType = "YDCL";
|
|
119
|
-
this.unConvertType = "xy284ll";
|
|
120
|
-
this.coordParam =
|
|
121
|
-
coordParam || CoordConvConfig.coordConvert4Params;
|
|
122
|
-
this.unCoordParam =
|
|
123
|
-
context.unCoordConvertParam ||
|
|
124
|
-
CoordConvConfig.coordConvert4ParamsReverse; //反转参数
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
this.convertType = "GPS"; //没有提供类型不做转换
|
|
128
|
-
this.unConvertType = "GPS";
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
//限制经纬度坐标在一个正确范围
|
|
133
|
-
limitLon: function (x) {
|
|
134
|
-
x = x > 180 ? 180 : x;
|
|
135
|
-
x = x < -180 ? -180 : x;
|
|
136
|
-
return x;
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
//限制经纬度坐标在一个正确范围
|
|
140
|
-
limitLat: function (y) {
|
|
141
|
-
y = y > 90 ? 90 : y;
|
|
142
|
-
y = y < -90 ? -90 : y;
|
|
143
|
-
return y;
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
//限制经纬度坐标在一个正确范围
|
|
147
|
-
limitLonLatArray: function (arrPnts) {
|
|
148
|
-
var result = [];
|
|
149
|
-
var length = arrPnts.length;
|
|
150
|
-
for (var k = 0; k < length; ++k) {
|
|
151
|
-
result.push([
|
|
152
|
-
this.limitLon(arrPnts[k][0]),
|
|
153
|
-
this.limitLat(arrPnts[k][1]),
|
|
154
|
-
]);
|
|
155
|
-
}
|
|
156
|
-
return result;
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
//坐标变换,本地转经纬度,返回 {x, y}格式
|
|
160
|
-
toLonLat: function (x, y) {
|
|
161
|
-
if (this.unConvertType == "GPS") {
|
|
162
|
-
var resultPoint = {
|
|
163
|
-
x: x,
|
|
164
|
-
y: y,
|
|
165
|
-
};
|
|
166
|
-
return resultPoint;
|
|
167
|
-
}
|
|
168
|
-
if (this.unConvertType && this.unConvertType.split(",").length == 1) {
|
|
169
|
-
var factory = coordConvert.getConvertFactory(
|
|
170
|
-
this.unConvertType,
|
|
171
|
-
this.unCoordParam
|
|
172
|
-
);
|
|
173
|
-
var result = factory.convert(x, y);
|
|
174
|
-
var resultPoint = {
|
|
175
|
-
x: this.limitLon(result[0]),
|
|
176
|
-
y: this.limitLat(result[1]),
|
|
177
|
-
};
|
|
178
|
-
} else if (
|
|
179
|
-
this.unConvertType &&
|
|
180
|
-
this.unConvertType.split(",").length > 1
|
|
181
|
-
) {
|
|
182
|
-
//需要两次转换
|
|
183
|
-
var unConvertTps = this.unConvertType.split(",");
|
|
184
|
-
var factory = coordConvert.getConvertFactory(
|
|
185
|
-
unConvertTps[0],
|
|
186
|
-
this.unCoordParam
|
|
187
|
-
);
|
|
188
|
-
var result = factory.convert(x, y);
|
|
189
|
-
var factory2 = coordConvert.getConvertFactory(
|
|
190
|
-
unConvertTps[1],
|
|
191
|
-
this.unCoordParam
|
|
192
|
-
);
|
|
193
|
-
result = factory2.convert(result[0], result[1]);
|
|
194
|
-
var resultPoint = {
|
|
195
|
-
x: this.limitLon(result[0]),
|
|
196
|
-
y: this.limitLat(result[1]),
|
|
197
|
-
};
|
|
198
|
-
} else
|
|
199
|
-
var resultPoint = {
|
|
200
|
-
x: x,
|
|
201
|
-
y: y,
|
|
202
|
-
};
|
|
203
|
-
return resultPoint;
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
//批量坐标变换,本地转经纬度,返回坐标点对数组,传入形式[[100.0, 0.0], [101.0, 1.0]]传出形式相同
|
|
207
|
-
toLonLatArray: function (arrPnts) {
|
|
208
|
-
if (arrPnts.length == 0) {
|
|
209
|
-
return arrPnts;
|
|
210
|
-
}
|
|
211
|
-
if (this.unConvertType == "GPS") return arrPnts;
|
|
212
|
-
if (this.unConvertType && this.unConvertType.split(",").length == 1) {
|
|
213
|
-
var factory = coordConvert.getConvertFactory(
|
|
214
|
-
this.unConvertType,
|
|
215
|
-
this.unCoordParam
|
|
216
|
-
);
|
|
217
|
-
} else if (
|
|
218
|
-
this.unConvertType &&
|
|
219
|
-
this.unConvertType.split(",").length > 1
|
|
220
|
-
) {
|
|
221
|
-
//需要两次转换
|
|
222
|
-
var unConvertTps = this.unConvertType.split(",");
|
|
223
|
-
var factory = coordConvert.getConvertFactory(
|
|
224
|
-
unConvertTps[0],
|
|
225
|
-
this.unCoordParam
|
|
226
|
-
);
|
|
227
|
-
var factory2 = coordConvert.getConvertFactory(
|
|
228
|
-
unConvertTps[1],
|
|
229
|
-
this.unCoordParam
|
|
230
|
-
);
|
|
231
|
-
} else return arrPnts;
|
|
232
|
-
var resultPoints = [];
|
|
233
|
-
for (var i = 0; i < arrPnts.length; i++) {
|
|
234
|
-
var pnt = arrPnts[i];
|
|
235
|
-
var temp = factory.convert(pnt[0], pnt[1]);
|
|
236
|
-
if (factory2) {
|
|
237
|
-
var temp2 = factory2.convert(temp[0], temp[1]);
|
|
238
|
-
} else var temp2 = temp;
|
|
239
|
-
resultPoints.push([
|
|
240
|
-
this.limitLon(temp2[0]),
|
|
241
|
-
this.limitLat(temp2[1]),
|
|
242
|
-
]);
|
|
243
|
-
}
|
|
244
|
-
return resultPoints;
|
|
245
|
-
},
|
|
246
|
-
|
|
247
|
-
//坐标变换,经纬度转本地,返回 {x, y}格式
|
|
248
|
-
toLocal: function (x, y) {
|
|
249
|
-
if (this.convertType) {
|
|
250
|
-
var factory = coordConvert.getConvertFactory(
|
|
251
|
-
this.convertType,
|
|
252
|
-
this.coordParam
|
|
253
|
-
);
|
|
254
|
-
var result = factory.convert(x, y);
|
|
255
|
-
var resultPoint = {
|
|
256
|
-
x: result[0],
|
|
257
|
-
y: result[1],
|
|
258
|
-
};
|
|
259
|
-
} else
|
|
260
|
-
var resultPoint = {
|
|
261
|
-
x: x,
|
|
262
|
-
y: y,
|
|
263
|
-
};
|
|
264
|
-
return resultPoint;
|
|
265
|
-
},
|
|
266
|
-
|
|
267
|
-
//批量坐标变换,经纬度转本地,返回坐标点对数组,输入形式 [[100.0, 0.0], [101.0, 1.0]],输出形式相同
|
|
268
|
-
toLocalArray: function (arrPnts) {
|
|
269
|
-
if (arrPnts.length == 0) {
|
|
270
|
-
return arrPnts;
|
|
271
|
-
}
|
|
272
|
-
if (this.convertType) {
|
|
273
|
-
var factory = coordConvert.getConvertFactory(
|
|
274
|
-
this.convertType,
|
|
275
|
-
this.coordParam
|
|
276
|
-
);
|
|
277
|
-
} else return arrPnts;
|
|
278
|
-
var resultPoints = [];
|
|
279
|
-
for (var i = 0; i < arrPnts.length; i++) {
|
|
280
|
-
var pnt = arrPnts[i];
|
|
281
|
-
var temp = factory.convert(pnt[0], pnt[1]);
|
|
282
|
-
resultPoints.push([temp[0], temp[1]]);
|
|
283
|
-
}
|
|
284
|
-
return resultPoints;
|
|
285
|
-
},
|
|
286
|
-
|
|
287
|
-
//二维地图范围转成三维经纬度地图范围
|
|
288
|
-
toLonLatExtent: function (extent) {
|
|
289
|
-
var lowerleft = this.toLonLat(extent.xmin, extent.ymin);
|
|
290
|
-
var upperright = this.toLonLat(extent.xmax, extent.ymax);
|
|
291
|
-
if (lowerleft && upperright) {
|
|
292
|
-
return {
|
|
293
|
-
xmin: lowerleft.x,
|
|
294
|
-
ymin: lowerleft.y,
|
|
295
|
-
xmax: upperright.x,
|
|
296
|
-
ymax: upperright.y,
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
|
|
301
|
-
//三维经纬度地图范围转成二维地图范围
|
|
302
|
-
toLocalExtent: function (extent) {
|
|
303
|
-
var lowerleft = this.toLocal(
|
|
304
|
-
extent.west || extent.xmin,
|
|
305
|
-
extent.south || extent.ymin
|
|
306
|
-
);
|
|
307
|
-
var upperright = this.toLocal(
|
|
308
|
-
extent.east || extent.xmax,
|
|
309
|
-
extent.north || extent.ymax
|
|
310
|
-
);
|
|
311
|
-
if (lowerleft && upperright) {
|
|
312
|
-
return {
|
|
313
|
-
xmin: lowerleft.x,
|
|
314
|
-
ymin: lowerleft.y,
|
|
315
|
-
xmax: upperright.x,
|
|
316
|
-
ymax: upperright.y,
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
},
|
|
320
|
-
//其它坐标转换 坐标形式coord=[116.9,40.12]
|
|
321
|
-
commonConvert: function (type, param, coord) {
|
|
322
|
-
var factory = coordConvert.getConvertFactory(type, param);
|
|
323
|
-
var result = factory.convert(coord[0], coord[1]);
|
|
324
|
-
return result;
|
|
325
|
-
},
|
|
326
|
-
|
|
327
|
-
//转换geoserver面数据转为geojson
|
|
328
|
-
convertRingsToGeoJSON: function (rings) {
|
|
329
|
-
function isNumber(n) {
|
|
330
|
-
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function ringIsClockwise(ringToTest) {
|
|
334
|
-
var total = 0,
|
|
335
|
-
i = 0;
|
|
336
|
-
var rLength = ringToTest.length;
|
|
337
|
-
var pt1 = ringToTest[i];
|
|
338
|
-
var pt2;
|
|
339
|
-
for (i; i < rLength - 1; i++) {
|
|
340
|
-
pt2 = ringToTest[i + 1];
|
|
341
|
-
total += (pt2[0] - pt1[0]) * (pt2[1] + pt1[1]);
|
|
342
|
-
pt1 = pt2;
|
|
343
|
-
}
|
|
344
|
-
return total >= 0;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function closeRing(coordinates) {
|
|
348
|
-
if (
|
|
349
|
-
!pointsEqual(
|
|
350
|
-
coordinates[0],
|
|
351
|
-
coordinates[coordinates.length - 1]
|
|
352
|
-
)
|
|
353
|
-
) {
|
|
354
|
-
coordinates.push(coordinates[0]);
|
|
355
|
-
}
|
|
356
|
-
return coordinates;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// checks if 2 x,y points are equal
|
|
360
|
-
function pointsEqual(a, b) {
|
|
361
|
-
for (var i = 0; i < a.length; i++) {
|
|
362
|
-
if (a[i] !== b[i]) {
|
|
363
|
-
return false;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function coordinatesContainPoint(coordinates, point) {
|
|
370
|
-
var contains = false;
|
|
371
|
-
for (
|
|
372
|
-
var i = -1, l = coordinates.length, j = l - 1;
|
|
373
|
-
++i < l;
|
|
374
|
-
j = i
|
|
375
|
-
) {
|
|
376
|
-
if (
|
|
377
|
-
((coordinates[i][1] <= point[1] &&
|
|
378
|
-
point[1] < coordinates[j][1]) ||
|
|
379
|
-
(coordinates[j][1] <= point[1] &&
|
|
380
|
-
point[1] < coordinates[i][1])) &&
|
|
381
|
-
point[0] <
|
|
382
|
-
((coordinates[j][0] - coordinates[i][0]) *
|
|
383
|
-
(point[1] - coordinates[i][1])) /
|
|
384
|
-
(coordinates[j][1] - coordinates[i][1]) +
|
|
385
|
-
coordinates[i][0]
|
|
386
|
-
) {
|
|
387
|
-
contains = !contains;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
return contains;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
function edgeIntersectsEdge(a1, a2, b1, b2) {
|
|
394
|
-
var ua_t =
|
|
395
|
-
(b2[0] - b1[0]) * (a1[1] - b1[1]) -
|
|
396
|
-
(b2[1] - b1[1]) * (a1[0] - b1[0]);
|
|
397
|
-
var ub_t =
|
|
398
|
-
(a2[0] - a1[0]) * (a1[1] - b1[1]) -
|
|
399
|
-
(a2[1] - a1[1]) * (a1[0] - b1[0]);
|
|
400
|
-
var u_b =
|
|
401
|
-
(b2[1] - b1[1]) * (a2[0] - a1[0]) -
|
|
402
|
-
(b2[0] - b1[0]) * (a2[1] - a1[1]);
|
|
403
|
-
|
|
404
|
-
if (u_b !== 0) {
|
|
405
|
-
var ua = ua_t / u_b;
|
|
406
|
-
var ub = ub_t / u_b;
|
|
407
|
-
|
|
408
|
-
if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
|
|
409
|
-
return true;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return false;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function arraysIntersectArrays(a, b) {
|
|
417
|
-
if (isNumber(a[0][0])) {
|
|
418
|
-
if (isNumber(b[0][0])) {
|
|
419
|
-
for (var i = 0; i < a.length - 1; i++) {
|
|
420
|
-
for (var j = 0; j < b.length - 1; j++) {
|
|
421
|
-
if (
|
|
422
|
-
edgeIntersectsEdge(
|
|
423
|
-
a[i],
|
|
424
|
-
a[i + 1],
|
|
425
|
-
b[j],
|
|
426
|
-
b[j + 1]
|
|
427
|
-
)
|
|
428
|
-
) {
|
|
429
|
-
return true;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
} else {
|
|
434
|
-
for (var k = 0; k < b.length; k++) {
|
|
435
|
-
if (arraysIntersectArrays(a, b[k])) {
|
|
436
|
-
return true;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
} else {
|
|
441
|
-
for (var l = 0; l < a.length; l++) {
|
|
442
|
-
if (arraysIntersectArrays(a[l], b)) {
|
|
443
|
-
return true;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
return false;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
function coordinatesContainCoordinates(outer, inner) {
|
|
451
|
-
var intersects = arraysIntersectArrays(outer, inner);
|
|
452
|
-
var contains = coordinatesContainPoint(outer, inner[0]);
|
|
453
|
-
if (!intersects && contains) {
|
|
454
|
-
return true;
|
|
455
|
-
}
|
|
456
|
-
return false;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
var outerRings = [];
|
|
460
|
-
var holes = [];
|
|
461
|
-
var x; // iterator
|
|
462
|
-
var outerRing; // current outer ring being evaluated
|
|
463
|
-
var hole; // current hole being evaluated
|
|
464
|
-
|
|
465
|
-
// for each ring
|
|
466
|
-
for (var r = 0; r < rings.length; r++) {
|
|
467
|
-
var ring = closeRing(rings[r].slice(0));
|
|
468
|
-
if (ring.length < 4) {
|
|
469
|
-
continue;
|
|
470
|
-
}
|
|
471
|
-
// is this ring an outer ring? is it clockwise?
|
|
472
|
-
if (ringIsClockwise(ring)) {
|
|
473
|
-
var polygon = [ring.slice().reverse()]; // wind outer rings counterclockwise for RFC 7946 compliance
|
|
474
|
-
outerRings.push(polygon); // push to outer rings
|
|
475
|
-
} else {
|
|
476
|
-
holes.push(ring.slice().reverse()); // wind inner rings clockwise for RFC 7946 compliance
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
var uncontainedHoles = [];
|
|
481
|
-
|
|
482
|
-
// while there are holes left...
|
|
483
|
-
while (holes.length) {
|
|
484
|
-
// pop a hole off out stack
|
|
485
|
-
hole = holes.pop();
|
|
486
|
-
|
|
487
|
-
// loop over all outer rings and see if they contain our hole.
|
|
488
|
-
var contained = false;
|
|
489
|
-
for (x = outerRings.length - 1; x >= 0; x--) {
|
|
490
|
-
outerRing = outerRings[x][0];
|
|
491
|
-
if (coordinatesContainCoordinates(outerRing, hole)) {
|
|
492
|
-
// the hole is contained push it into our polygon
|
|
493
|
-
outerRings[x].push(hole);
|
|
494
|
-
contained = true;
|
|
495
|
-
break;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// ring is not contained in any outer ring
|
|
500
|
-
// sometimes this happens https://github.com/Esri/esri-leaflet/issues/320
|
|
501
|
-
if (!contained) {
|
|
502
|
-
uncontainedHoles.push(hole);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// if we couldn't match any holes using contains we can now try intersects...
|
|
507
|
-
while (uncontainedHoles.length) {
|
|
508
|
-
// pop a hole off out stack
|
|
509
|
-
hole = uncontainedHoles.pop();
|
|
510
|
-
|
|
511
|
-
// loop over all outer rings and see if any intersect our hole.
|
|
512
|
-
var intersects = false;
|
|
513
|
-
for (x = outerRings.length - 1; x >= 0; x--) {
|
|
514
|
-
outerRing = outerRings[x][0];
|
|
515
|
-
if (arraysIntersectArrays(outerRing, hole)) {
|
|
516
|
-
// the hole intersects the outer ring push it into our polygon
|
|
517
|
-
outerRings[x].push(hole);
|
|
518
|
-
intersects = true;
|
|
519
|
-
break;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// hole does not intersect ANY outer ring at this point
|
|
524
|
-
// make it an outer ring.
|
|
525
|
-
if (!intersects) {
|
|
526
|
-
outerRings.push([hole.reverse()]);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
if (outerRings.length === 1) {
|
|
531
|
-
return {
|
|
532
|
-
type: "Polygon",
|
|
533
|
-
coordinates: outerRings[0],
|
|
534
|
-
};
|
|
535
|
-
} else {
|
|
536
|
-
return {
|
|
537
|
-
type: "MultiPolygon",
|
|
538
|
-
coordinates: outerRings,
|
|
539
|
-
};
|
|
540
|
-
}
|
|
541
|
-
},
|
|
542
|
-
};
|
|
543
|
-
export default MapUtils;
|
|
1
|
+
import CoordConvConfig from "./coordconvert/CoordConvConfig";
|
|
2
|
+
import * as coordConvert from "egovacoordconvert/build/dist/coordconvert";
|
|
3
|
+
|
|
4
|
+
var MapUtils = {
|
|
5
|
+
type: function (obj) {
|
|
6
|
+
var result = Array.isArray(obj) ? "array" : typeof obj;
|
|
7
|
+
return result;
|
|
8
|
+
},
|
|
9
|
+
deepClones: function () {
|
|
10
|
+
var options,
|
|
11
|
+
name,
|
|
12
|
+
src,
|
|
13
|
+
copy,
|
|
14
|
+
copyIsArray,
|
|
15
|
+
clone,
|
|
16
|
+
target = arguments[0] || {},
|
|
17
|
+
i = 1,
|
|
18
|
+
length = arguments.length,
|
|
19
|
+
deep = false;
|
|
20
|
+
|
|
21
|
+
// Handle a deep copy situation
|
|
22
|
+
if (typeof target === "boolean") {
|
|
23
|
+
deep = target;
|
|
24
|
+
|
|
25
|
+
// Skip the boolean and the target
|
|
26
|
+
target = arguments[i] || {};
|
|
27
|
+
i++;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Handle case when target is a string or something (possible in deep copy)
|
|
31
|
+
if (
|
|
32
|
+
this.type(target) !== "object" &&
|
|
33
|
+
this.type(target) !== "function" &&
|
|
34
|
+
this.type(target) !== "array"
|
|
35
|
+
) {
|
|
36
|
+
target = {};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Extend jQuery itself if only one argument is passed
|
|
40
|
+
if (i === length) {
|
|
41
|
+
target = this;
|
|
42
|
+
i--;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (; i < length; i++) {
|
|
46
|
+
// Only deal with non-null/undefined values
|
|
47
|
+
if ((options = arguments[i]) != null) {
|
|
48
|
+
// Extend the base object
|
|
49
|
+
for (name in options) {
|
|
50
|
+
src = target[name];
|
|
51
|
+
copy = options[name];
|
|
52
|
+
|
|
53
|
+
// Prevent never-ending loop
|
|
54
|
+
if (target === copy) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Recurse if we're merging plain objects or arrays
|
|
59
|
+
if (
|
|
60
|
+
deep &&
|
|
61
|
+
copy &&
|
|
62
|
+
(this.type(copy) === "object" ||
|
|
63
|
+
(copyIsArray = this.type(copy) === "array"))
|
|
64
|
+
) {
|
|
65
|
+
if (copyIsArray) {
|
|
66
|
+
copyIsArray = false;
|
|
67
|
+
clone =
|
|
68
|
+
src && this.type(copy) === "array" ? src : [];
|
|
69
|
+
} else {
|
|
70
|
+
clone =
|
|
71
|
+
src && this.type(copy) === "object" ? src : {};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Never move original objects, clone them
|
|
75
|
+
target[name] = this.deepClones(deep, clone, copy);
|
|
76
|
+
|
|
77
|
+
// Don't bring in undefined values
|
|
78
|
+
} else if (copy !== undefined) {
|
|
79
|
+
target[name] = copy;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Return the modified object
|
|
85
|
+
return target;
|
|
86
|
+
},
|
|
87
|
+
//初始化
|
|
88
|
+
init: function (context) {
|
|
89
|
+
var coordConvertType = context.coordConvertType;
|
|
90
|
+
var coordParam = context.coordConvertParam;
|
|
91
|
+
var nullParamTypes = [
|
|
92
|
+
"BJCG",
|
|
93
|
+
"GPS",
|
|
94
|
+
"MKT",
|
|
95
|
+
"84ll2bdll",
|
|
96
|
+
"84ll2gcjll",
|
|
97
|
+
"84ll2bdmc",
|
|
98
|
+
"GD",
|
|
99
|
+
];
|
|
100
|
+
if (coordConvertType) {
|
|
101
|
+
if (nullParamTypes.toString().indexOf(coordConvertType) != -1) {
|
|
102
|
+
this.convertType = coordConvertType; //正转类型
|
|
103
|
+
this.coordParam = "";
|
|
104
|
+
this.unCoordParam = "";
|
|
105
|
+
if (coordConvertType == "BJCG")
|
|
106
|
+
this.unConvertType = "unBJCG2WGS84"; //北京城管转84经纬度
|
|
107
|
+
if (coordConvertType == "GPS") this.unConvertType = "GPS";
|
|
108
|
+
if (coordConvertType == "MKT") this.unConvertType = "84mc284ll";
|
|
109
|
+
if (coordConvertType == "84ll2bdll")
|
|
110
|
+
this.unConvertType = "bdll284ll";
|
|
111
|
+
if (coordConvertType == "84ll2gcjll")
|
|
112
|
+
this.unConvertType = "gcjll284ll";
|
|
113
|
+
if (coordConvertType == "84ll2bdmc")
|
|
114
|
+
this.unConvertType = "bdmc2bdll,bdll284ll"; //先转百度经纬度再转84经纬度
|
|
115
|
+
if (coordConvertType == "GD")
|
|
116
|
+
this.unConvertType = "gcjmc2gcjll,gcjll284ll"; //先转高德经纬度再转84经纬度
|
|
117
|
+
} else {
|
|
118
|
+
this.convertType = "YDCL";
|
|
119
|
+
this.unConvertType = "xy284ll";
|
|
120
|
+
this.coordParam =
|
|
121
|
+
coordParam || CoordConvConfig.coordConvert4Params;
|
|
122
|
+
this.unCoordParam =
|
|
123
|
+
context.unCoordConvertParam ||
|
|
124
|
+
CoordConvConfig.coordConvert4ParamsReverse; //反转参数
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
this.convertType = "GPS"; //没有提供类型不做转换
|
|
128
|
+
this.unConvertType = "GPS";
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
//限制经纬度坐标在一个正确范围
|
|
133
|
+
limitLon: function (x) {
|
|
134
|
+
x = x > 180 ? 180 : x;
|
|
135
|
+
x = x < -180 ? -180 : x;
|
|
136
|
+
return x;
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
//限制经纬度坐标在一个正确范围
|
|
140
|
+
limitLat: function (y) {
|
|
141
|
+
y = y > 90 ? 90 : y;
|
|
142
|
+
y = y < -90 ? -90 : y;
|
|
143
|
+
return y;
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
//限制经纬度坐标在一个正确范围
|
|
147
|
+
limitLonLatArray: function (arrPnts) {
|
|
148
|
+
var result = [];
|
|
149
|
+
var length = arrPnts.length;
|
|
150
|
+
for (var k = 0; k < length; ++k) {
|
|
151
|
+
result.push([
|
|
152
|
+
this.limitLon(arrPnts[k][0]),
|
|
153
|
+
this.limitLat(arrPnts[k][1]),
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
//坐标变换,本地转经纬度,返回 {x, y}格式
|
|
160
|
+
toLonLat: function (x, y) {
|
|
161
|
+
if (this.unConvertType == "GPS") {
|
|
162
|
+
var resultPoint = {
|
|
163
|
+
x: x,
|
|
164
|
+
y: y,
|
|
165
|
+
};
|
|
166
|
+
return resultPoint;
|
|
167
|
+
}
|
|
168
|
+
if (this.unConvertType && this.unConvertType.split(",").length == 1) {
|
|
169
|
+
var factory = coordConvert.getConvertFactory(
|
|
170
|
+
this.unConvertType,
|
|
171
|
+
this.unCoordParam
|
|
172
|
+
);
|
|
173
|
+
var result = factory.convert(x, y);
|
|
174
|
+
var resultPoint = {
|
|
175
|
+
x: this.limitLon(result[0]),
|
|
176
|
+
y: this.limitLat(result[1]),
|
|
177
|
+
};
|
|
178
|
+
} else if (
|
|
179
|
+
this.unConvertType &&
|
|
180
|
+
this.unConvertType.split(",").length > 1
|
|
181
|
+
) {
|
|
182
|
+
//需要两次转换
|
|
183
|
+
var unConvertTps = this.unConvertType.split(",");
|
|
184
|
+
var factory = coordConvert.getConvertFactory(
|
|
185
|
+
unConvertTps[0],
|
|
186
|
+
this.unCoordParam
|
|
187
|
+
);
|
|
188
|
+
var result = factory.convert(x, y);
|
|
189
|
+
var factory2 = coordConvert.getConvertFactory(
|
|
190
|
+
unConvertTps[1],
|
|
191
|
+
this.unCoordParam
|
|
192
|
+
);
|
|
193
|
+
result = factory2.convert(result[0], result[1]);
|
|
194
|
+
var resultPoint = {
|
|
195
|
+
x: this.limitLon(result[0]),
|
|
196
|
+
y: this.limitLat(result[1]),
|
|
197
|
+
};
|
|
198
|
+
} else
|
|
199
|
+
var resultPoint = {
|
|
200
|
+
x: x,
|
|
201
|
+
y: y,
|
|
202
|
+
};
|
|
203
|
+
return resultPoint;
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
//批量坐标变换,本地转经纬度,返回坐标点对数组,传入形式[[100.0, 0.0], [101.0, 1.0]]传出形式相同
|
|
207
|
+
toLonLatArray: function (arrPnts) {
|
|
208
|
+
if (arrPnts.length == 0) {
|
|
209
|
+
return arrPnts;
|
|
210
|
+
}
|
|
211
|
+
if (this.unConvertType == "GPS") return arrPnts;
|
|
212
|
+
if (this.unConvertType && this.unConvertType.split(",").length == 1) {
|
|
213
|
+
var factory = coordConvert.getConvertFactory(
|
|
214
|
+
this.unConvertType,
|
|
215
|
+
this.unCoordParam
|
|
216
|
+
);
|
|
217
|
+
} else if (
|
|
218
|
+
this.unConvertType &&
|
|
219
|
+
this.unConvertType.split(",").length > 1
|
|
220
|
+
) {
|
|
221
|
+
//需要两次转换
|
|
222
|
+
var unConvertTps = this.unConvertType.split(",");
|
|
223
|
+
var factory = coordConvert.getConvertFactory(
|
|
224
|
+
unConvertTps[0],
|
|
225
|
+
this.unCoordParam
|
|
226
|
+
);
|
|
227
|
+
var factory2 = coordConvert.getConvertFactory(
|
|
228
|
+
unConvertTps[1],
|
|
229
|
+
this.unCoordParam
|
|
230
|
+
);
|
|
231
|
+
} else return arrPnts;
|
|
232
|
+
var resultPoints = [];
|
|
233
|
+
for (var i = 0; i < arrPnts.length; i++) {
|
|
234
|
+
var pnt = arrPnts[i];
|
|
235
|
+
var temp = factory.convert(pnt[0], pnt[1]);
|
|
236
|
+
if (factory2) {
|
|
237
|
+
var temp2 = factory2.convert(temp[0], temp[1]);
|
|
238
|
+
} else var temp2 = temp;
|
|
239
|
+
resultPoints.push([
|
|
240
|
+
this.limitLon(temp2[0]),
|
|
241
|
+
this.limitLat(temp2[1]),
|
|
242
|
+
]);
|
|
243
|
+
}
|
|
244
|
+
return resultPoints;
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
//坐标变换,经纬度转本地,返回 {x, y}格式
|
|
248
|
+
toLocal: function (x, y) {
|
|
249
|
+
if (this.convertType) {
|
|
250
|
+
var factory = coordConvert.getConvertFactory(
|
|
251
|
+
this.convertType,
|
|
252
|
+
this.coordParam
|
|
253
|
+
);
|
|
254
|
+
var result = factory.convert(x, y);
|
|
255
|
+
var resultPoint = {
|
|
256
|
+
x: result[0],
|
|
257
|
+
y: result[1],
|
|
258
|
+
};
|
|
259
|
+
} else
|
|
260
|
+
var resultPoint = {
|
|
261
|
+
x: x,
|
|
262
|
+
y: y,
|
|
263
|
+
};
|
|
264
|
+
return resultPoint;
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
//批量坐标变换,经纬度转本地,返回坐标点对数组,输入形式 [[100.0, 0.0], [101.0, 1.0]],输出形式相同
|
|
268
|
+
toLocalArray: function (arrPnts) {
|
|
269
|
+
if (arrPnts.length == 0) {
|
|
270
|
+
return arrPnts;
|
|
271
|
+
}
|
|
272
|
+
if (this.convertType) {
|
|
273
|
+
var factory = coordConvert.getConvertFactory(
|
|
274
|
+
this.convertType,
|
|
275
|
+
this.coordParam
|
|
276
|
+
);
|
|
277
|
+
} else return arrPnts;
|
|
278
|
+
var resultPoints = [];
|
|
279
|
+
for (var i = 0; i < arrPnts.length; i++) {
|
|
280
|
+
var pnt = arrPnts[i];
|
|
281
|
+
var temp = factory.convert(pnt[0], pnt[1]);
|
|
282
|
+
resultPoints.push([temp[0], temp[1]]);
|
|
283
|
+
}
|
|
284
|
+
return resultPoints;
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
//二维地图范围转成三维经纬度地图范围
|
|
288
|
+
toLonLatExtent: function (extent) {
|
|
289
|
+
var lowerleft = this.toLonLat(extent.xmin, extent.ymin);
|
|
290
|
+
var upperright = this.toLonLat(extent.xmax, extent.ymax);
|
|
291
|
+
if (lowerleft && upperright) {
|
|
292
|
+
return {
|
|
293
|
+
xmin: lowerleft.x,
|
|
294
|
+
ymin: lowerleft.y,
|
|
295
|
+
xmax: upperright.x,
|
|
296
|
+
ymax: upperright.y,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
//三维经纬度地图范围转成二维地图范围
|
|
302
|
+
toLocalExtent: function (extent) {
|
|
303
|
+
var lowerleft = this.toLocal(
|
|
304
|
+
extent.west || extent.xmin,
|
|
305
|
+
extent.south || extent.ymin
|
|
306
|
+
);
|
|
307
|
+
var upperright = this.toLocal(
|
|
308
|
+
extent.east || extent.xmax,
|
|
309
|
+
extent.north || extent.ymax
|
|
310
|
+
);
|
|
311
|
+
if (lowerleft && upperright) {
|
|
312
|
+
return {
|
|
313
|
+
xmin: lowerleft.x,
|
|
314
|
+
ymin: lowerleft.y,
|
|
315
|
+
xmax: upperright.x,
|
|
316
|
+
ymax: upperright.y,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
//其它坐标转换 坐标形式coord=[116.9,40.12]
|
|
321
|
+
commonConvert: function (type, param, coord) {
|
|
322
|
+
var factory = coordConvert.getConvertFactory(type, param);
|
|
323
|
+
var result = factory.convert(coord[0], coord[1]);
|
|
324
|
+
return result;
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
//转换geoserver面数据转为geojson
|
|
328
|
+
convertRingsToGeoJSON: function (rings) {
|
|
329
|
+
function isNumber(n) {
|
|
330
|
+
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function ringIsClockwise(ringToTest) {
|
|
334
|
+
var total = 0,
|
|
335
|
+
i = 0;
|
|
336
|
+
var rLength = ringToTest.length;
|
|
337
|
+
var pt1 = ringToTest[i];
|
|
338
|
+
var pt2;
|
|
339
|
+
for (i; i < rLength - 1; i++) {
|
|
340
|
+
pt2 = ringToTest[i + 1];
|
|
341
|
+
total += (pt2[0] - pt1[0]) * (pt2[1] + pt1[1]);
|
|
342
|
+
pt1 = pt2;
|
|
343
|
+
}
|
|
344
|
+
return total >= 0;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function closeRing(coordinates) {
|
|
348
|
+
if (
|
|
349
|
+
!pointsEqual(
|
|
350
|
+
coordinates[0],
|
|
351
|
+
coordinates[coordinates.length - 1]
|
|
352
|
+
)
|
|
353
|
+
) {
|
|
354
|
+
coordinates.push(coordinates[0]);
|
|
355
|
+
}
|
|
356
|
+
return coordinates;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// checks if 2 x,y points are equal
|
|
360
|
+
function pointsEqual(a, b) {
|
|
361
|
+
for (var i = 0; i < a.length; i++) {
|
|
362
|
+
if (a[i] !== b[i]) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function coordinatesContainPoint(coordinates, point) {
|
|
370
|
+
var contains = false;
|
|
371
|
+
for (
|
|
372
|
+
var i = -1, l = coordinates.length, j = l - 1;
|
|
373
|
+
++i < l;
|
|
374
|
+
j = i
|
|
375
|
+
) {
|
|
376
|
+
if (
|
|
377
|
+
((coordinates[i][1] <= point[1] &&
|
|
378
|
+
point[1] < coordinates[j][1]) ||
|
|
379
|
+
(coordinates[j][1] <= point[1] &&
|
|
380
|
+
point[1] < coordinates[i][1])) &&
|
|
381
|
+
point[0] <
|
|
382
|
+
((coordinates[j][0] - coordinates[i][0]) *
|
|
383
|
+
(point[1] - coordinates[i][1])) /
|
|
384
|
+
(coordinates[j][1] - coordinates[i][1]) +
|
|
385
|
+
coordinates[i][0]
|
|
386
|
+
) {
|
|
387
|
+
contains = !contains;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return contains;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function edgeIntersectsEdge(a1, a2, b1, b2) {
|
|
394
|
+
var ua_t =
|
|
395
|
+
(b2[0] - b1[0]) * (a1[1] - b1[1]) -
|
|
396
|
+
(b2[1] - b1[1]) * (a1[0] - b1[0]);
|
|
397
|
+
var ub_t =
|
|
398
|
+
(a2[0] - a1[0]) * (a1[1] - b1[1]) -
|
|
399
|
+
(a2[1] - a1[1]) * (a1[0] - b1[0]);
|
|
400
|
+
var u_b =
|
|
401
|
+
(b2[1] - b1[1]) * (a2[0] - a1[0]) -
|
|
402
|
+
(b2[0] - b1[0]) * (a2[1] - a1[1]);
|
|
403
|
+
|
|
404
|
+
if (u_b !== 0) {
|
|
405
|
+
var ua = ua_t / u_b;
|
|
406
|
+
var ub = ub_t / u_b;
|
|
407
|
+
|
|
408
|
+
if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function arraysIntersectArrays(a, b) {
|
|
417
|
+
if (isNumber(a[0][0])) {
|
|
418
|
+
if (isNumber(b[0][0])) {
|
|
419
|
+
for (var i = 0; i < a.length - 1; i++) {
|
|
420
|
+
for (var j = 0; j < b.length - 1; j++) {
|
|
421
|
+
if (
|
|
422
|
+
edgeIntersectsEdge(
|
|
423
|
+
a[i],
|
|
424
|
+
a[i + 1],
|
|
425
|
+
b[j],
|
|
426
|
+
b[j + 1]
|
|
427
|
+
)
|
|
428
|
+
) {
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
for (var k = 0; k < b.length; k++) {
|
|
435
|
+
if (arraysIntersectArrays(a, b[k])) {
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
} else {
|
|
441
|
+
for (var l = 0; l < a.length; l++) {
|
|
442
|
+
if (arraysIntersectArrays(a[l], b)) {
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function coordinatesContainCoordinates(outer, inner) {
|
|
451
|
+
var intersects = arraysIntersectArrays(outer, inner);
|
|
452
|
+
var contains = coordinatesContainPoint(outer, inner[0]);
|
|
453
|
+
if (!intersects && contains) {
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
var outerRings = [];
|
|
460
|
+
var holes = [];
|
|
461
|
+
var x; // iterator
|
|
462
|
+
var outerRing; // current outer ring being evaluated
|
|
463
|
+
var hole; // current hole being evaluated
|
|
464
|
+
|
|
465
|
+
// for each ring
|
|
466
|
+
for (var r = 0; r < rings.length; r++) {
|
|
467
|
+
var ring = closeRing(rings[r].slice(0));
|
|
468
|
+
if (ring.length < 4) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
// is this ring an outer ring? is it clockwise?
|
|
472
|
+
if (ringIsClockwise(ring)) {
|
|
473
|
+
var polygon = [ring.slice().reverse()]; // wind outer rings counterclockwise for RFC 7946 compliance
|
|
474
|
+
outerRings.push(polygon); // push to outer rings
|
|
475
|
+
} else {
|
|
476
|
+
holes.push(ring.slice().reverse()); // wind inner rings clockwise for RFC 7946 compliance
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
var uncontainedHoles = [];
|
|
481
|
+
|
|
482
|
+
// while there are holes left...
|
|
483
|
+
while (holes.length) {
|
|
484
|
+
// pop a hole off out stack
|
|
485
|
+
hole = holes.pop();
|
|
486
|
+
|
|
487
|
+
// loop over all outer rings and see if they contain our hole.
|
|
488
|
+
var contained = false;
|
|
489
|
+
for (x = outerRings.length - 1; x >= 0; x--) {
|
|
490
|
+
outerRing = outerRings[x][0];
|
|
491
|
+
if (coordinatesContainCoordinates(outerRing, hole)) {
|
|
492
|
+
// the hole is contained push it into our polygon
|
|
493
|
+
outerRings[x].push(hole);
|
|
494
|
+
contained = true;
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// ring is not contained in any outer ring
|
|
500
|
+
// sometimes this happens https://github.com/Esri/esri-leaflet/issues/320
|
|
501
|
+
if (!contained) {
|
|
502
|
+
uncontainedHoles.push(hole);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// if we couldn't match any holes using contains we can now try intersects...
|
|
507
|
+
while (uncontainedHoles.length) {
|
|
508
|
+
// pop a hole off out stack
|
|
509
|
+
hole = uncontainedHoles.pop();
|
|
510
|
+
|
|
511
|
+
// loop over all outer rings and see if any intersect our hole.
|
|
512
|
+
var intersects = false;
|
|
513
|
+
for (x = outerRings.length - 1; x >= 0; x--) {
|
|
514
|
+
outerRing = outerRings[x][0];
|
|
515
|
+
if (arraysIntersectArrays(outerRing, hole)) {
|
|
516
|
+
// the hole intersects the outer ring push it into our polygon
|
|
517
|
+
outerRings[x].push(hole);
|
|
518
|
+
intersects = true;
|
|
519
|
+
break;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// hole does not intersect ANY outer ring at this point
|
|
524
|
+
// make it an outer ring.
|
|
525
|
+
if (!intersects) {
|
|
526
|
+
outerRings.push([hole.reverse()]);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (outerRings.length === 1) {
|
|
531
|
+
return {
|
|
532
|
+
type: "Polygon",
|
|
533
|
+
coordinates: outerRings[0],
|
|
534
|
+
};
|
|
535
|
+
} else {
|
|
536
|
+
return {
|
|
537
|
+
type: "MultiPolygon",
|
|
538
|
+
coordinates: outerRings,
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
};
|
|
543
|
+
export default MapUtils;
|