mapping-component-package-jp 0.0.2
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/README.md +70 -0
- package/dist/index.d.ts +264 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +54 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +48 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +43 -0
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +25 -0
- package/public/robots.txt +3 -0
- package/rollup.config.js +48 -0
- package/src/components/FabControl.tsx +63 -0
- package/src/components/GoogleSearchBar.tsx +182 -0
- package/src/components/Icons.tsx +20 -0
- package/src/components/JPMapComponent.tsx +96 -0
- package/src/components/SpeedDialTool.tsx +97 -0
- package/src/components/index.ts +22 -0
- package/src/hooks/useMapManager.ts +48 -0
- package/src/interfaces/AgnifyMapComponentProps.ts +18 -0
- package/src/interfaces/CustomMapOptions.ts +14 -0
- package/src/interfaces/Data/EnterpriseRegion.ts +12 -0
- package/src/interfaces/Data/Farm.ts +10 -0
- package/src/interfaces/Data/Field.ts +19 -0
- package/src/interfaces/Data/LocationData.ts +9 -0
- package/src/interfaces/Data/MapLocationFeature.ts +8 -0
- package/src/interfaces/Data/NDVI.ts +14 -0
- package/src/interfaces/GoogleMapsOptions.ts +39 -0
- package/src/interfaces/Message.ts +13 -0
- package/src/interfaces/Mode.ts +54 -0
- package/src/interfaces/Properties.ts +16 -0
- package/src/js/fieldEncapsulation/iql.field.js +8 -0
- package/src/js/fieldEncapsulation/iql.fieldupload.js +158 -0
- package/src/js/fieldEncapsulation/iql.fieldvalidator.js +574 -0
- package/src/js/mapEncapsulation/circle.functions.js +30 -0
- package/src/js/mapEncapsulation/field.geolocation.js +19 -0
- package/src/js/mapEncapsulation/map.common.js +96 -0
- package/src/js/mapEncapsulation/mapOverlayManager.d.ts +64 -0
- package/src/js/mapEncapsulation/mapOverlayManager.js +2753 -0
- package/src/js/mapEncapsulation/shapes/circle.full.js +789 -0
- package/src/js/mapEncapsulation/shapes/circle.sector.js +1099 -0
- package/src/js/mapEncapsulation/shapes/circle.segment.js +1109 -0
- package/src/js/mapEncapsulation/shapes/polygon.customedit.js +393 -0
- package/src/js/mapEncapsulation/shapes/polyline.customedit.js +478 -0
- package/src/utils/commonUtils.ts +5 -0
- package/src/utils/iconUtils.js +52 -0
- package/src/utils/mapUtils.ts +88 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Field Validator Object
|
|
3
|
+
*/
|
|
4
|
+
import polyline from 'polyline';
|
|
5
|
+
|
|
6
|
+
export class FieldValidator {
|
|
7
|
+
static geoJSON2GoogleLatLng(boundaries) {
|
|
8
|
+
return boundaries.map(point => new google.maps.LatLng(point[1], point[0]));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static calcIntersection(polyOne, polyTwo) {
|
|
12
|
+
const polygon1 = new google.maps.Polygon({
|
|
13
|
+
paths: polyOne.map(p => new google.maps.LatLng(p[1], p[0]))
|
|
14
|
+
});
|
|
15
|
+
const polygon2 = new google.maps.Polygon({
|
|
16
|
+
paths: polyTwo.map(p => new google.maps.LatLng(p[1], p[0]))
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Check if any point of polygon2 is inside polygon1
|
|
20
|
+
for (let i = 0; i < polyTwo.length; i++) {
|
|
21
|
+
const point = new google.maps.LatLng(polyTwo[i][1], polyTwo[i][0]);
|
|
22
|
+
if (google.maps.geometry.poly.containsLocation(point, polygon1)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check if any point of polygon1 is inside polygon2
|
|
28
|
+
for (let i = 0; i < polyOne.length; i++) {
|
|
29
|
+
const point = new google.maps.LatLng(polyOne[i][1], polyOne[i][0]);
|
|
30
|
+
if (google.maps.geometry.poly.containsLocation(point, polygon2)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static findSelfIntersects(geoJsonPolygon) {
|
|
39
|
+
const path = geoJsonPolygon.map(point => new google.maps.LatLng(point[1], point[0]));
|
|
40
|
+
const polygon = new google.maps.Polygon({ paths: path });
|
|
41
|
+
|
|
42
|
+
// Check for self-intersections by comparing segments
|
|
43
|
+
const intersectionPoints = [];
|
|
44
|
+
|
|
45
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
46
|
+
for (let j = i + 2; j < path.length - 1; j++) {
|
|
47
|
+
// Skip adjacent segments
|
|
48
|
+
if (i === 0 && j === path.length - 2) continue;
|
|
49
|
+
|
|
50
|
+
const seg1 = [path[i], path[i + 1]];
|
|
51
|
+
const seg2 = [path[j], path[j + 1]];
|
|
52
|
+
|
|
53
|
+
if (this.segmentsIntersect(
|
|
54
|
+
seg1[0].lat(), seg1[0].lng(),
|
|
55
|
+
seg1[1].lat(), seg1[1].lng(),
|
|
56
|
+
seg2[0].lat(), seg2[0].lng(),
|
|
57
|
+
seg2[1].lat(), seg2[1].lng()
|
|
58
|
+
)) {
|
|
59
|
+
// Calculate intersection point (approximate)
|
|
60
|
+
const midPoint = new google.maps.LatLng(
|
|
61
|
+
(seg1[0].lat() + seg1[1].lat()) / 2,
|
|
62
|
+
(seg1[0].lng() + seg1[1].lng()) / 2
|
|
63
|
+
);
|
|
64
|
+
intersectionPoints.push([midPoint.lng(), midPoint.lat()]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return intersectionPoints;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4) {
|
|
73
|
+
const ccw = (x1, y1, x2, y2, x3, y3) => {
|
|
74
|
+
return (y3 - y1) * (x2 - x1) > (y2 - y1) * (x3 - x1);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (ccw(x1, y1, x3, y3, x4, y4) !== ccw(x2, y2, x3, y3, x4, y4)) &&
|
|
78
|
+
(ccw(x1, y1, x2, y2, x3, y3) !== ccw(x1, y1, x2, y2, x4, y4));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Completes the shape path start point equals to end point
|
|
82
|
+
static path_convert(shape) {
|
|
83
|
+
var newShape = shape;
|
|
84
|
+
if (newShape[shape.length-1] !== newShape[0]) {
|
|
85
|
+
newShape[shape.length] = newShape[0];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return (newShape);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Checks if google geometnry API is available
|
|
92
|
+
static checkGoogleAPI() {
|
|
93
|
+
try {
|
|
94
|
+
google.maps.geometry;
|
|
95
|
+
} catch (e) {
|
|
96
|
+
throw new Error('Google Maps API is Required');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Decode shape coordinates
|
|
101
|
+
static decodeShapes_get(encodedShapes) {
|
|
102
|
+
var shapes_splited = [];
|
|
103
|
+
|
|
104
|
+
encodedShapes.forEach(function (shape, polyindex) {
|
|
105
|
+
shapes_splited.push(shape.path);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
var shapesPath = [];
|
|
109
|
+
var path = [];
|
|
110
|
+
|
|
111
|
+
shapes_splited.forEach(function (poly, pIndex) {
|
|
112
|
+
path = polyline.decode(poly);
|
|
113
|
+
shapesPath.push(path);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return (shapesPath);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Convert array of point into google LatLng
|
|
120
|
+
static pathToGoogleLatLng_get(shapesPath) {
|
|
121
|
+
var paths_googleLatLng = [];
|
|
122
|
+
var path_googleLatLng = [];
|
|
123
|
+
|
|
124
|
+
shapesPath.forEach(function (poly, polyindex) {
|
|
125
|
+
path_googleLatLng = [];
|
|
126
|
+
|
|
127
|
+
poly.forEach(function (c, cindex) {
|
|
128
|
+
path_googleLatLng.push(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])));
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
paths_googleLatLng.push(path_googleLatLng);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return (paths_googleLatLng);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Checks if all the holes inside the outershape
|
|
138
|
+
static holesOutsideOuterShape_check(shapesPath, paths_googleLatLng) {
|
|
139
|
+
var outerPoly = new google.maps.Polygon({
|
|
140
|
+
path: paths_googleLatLng[0]
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
var pointsNotInside_count = 0;
|
|
144
|
+
var shapesOutside = 0;
|
|
145
|
+
|
|
146
|
+
shapesPath.forEach(function (poly, polyindex) {
|
|
147
|
+
if (polyindex > 0) {
|
|
148
|
+
poly.forEach(function (c, cindex) {
|
|
149
|
+
if (!google.maps.geometry.poly.containsLocation(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])), outerPoly)) {
|
|
150
|
+
pointsNotInside_count++;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
if (pointsNotInside_count == poly.length) {
|
|
154
|
+
shapesOutside++;
|
|
155
|
+
}
|
|
156
|
+
pointsNotInside_count = 0;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return (shapesOutside > 0);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Returns true if one of the shapes path has a self intersection.
|
|
164
|
+
static selfInterceptionShape_check(shapesPath) {
|
|
165
|
+
var invalidPoints = 0;
|
|
166
|
+
var selfInterceptionCount = 0;
|
|
167
|
+
|
|
168
|
+
shapesPath.forEach(function (poly, polyindex) {
|
|
169
|
+
// check self-intersection
|
|
170
|
+
|
|
171
|
+
invalidPoints = FieldValidator.findSelfIntersects(FieldValidator.path_convert(poly));
|
|
172
|
+
selfInterceptionCount += invalidPoints.length;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return (selfInterceptionCount > 0)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Check if all the all the holes are inside the outer polygon
|
|
179
|
+
static holesInterceptOuterShape_check(shapesPath, paths_googleLatLng) {
|
|
180
|
+
// check if holes are inside outer polygon
|
|
181
|
+
var outerPoly = new google.maps.Polygon({
|
|
182
|
+
path: paths_googleLatLng[0]
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
var notInsideCount = 0;
|
|
186
|
+
var shapesInterceptOutside = 0;
|
|
187
|
+
|
|
188
|
+
shapesPath.forEach(function (poly, polyindex) {
|
|
189
|
+
if (polyindex > 0) {
|
|
190
|
+
poly.forEach(function (c, cindex) {
|
|
191
|
+
if (!google.maps.geometry.poly.containsLocation(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])), outerPoly)) {
|
|
192
|
+
notInsideCount++;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
if (notInsideCount > 0 && notInsideCount < poly.length) {
|
|
196
|
+
shapesInterceptOutside++;
|
|
197
|
+
}
|
|
198
|
+
notInsideCount = 0;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
return (shapesInterceptOutside == 0);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Check if holes intersect between each other
|
|
206
|
+
static holesIntercept_check(shapesPath, paths_googleLatLng) {
|
|
207
|
+
var holeIntersectCount = 0;
|
|
208
|
+
|
|
209
|
+
for (var i = 1; i < paths_googleLatLng.length - 1; i++) {
|
|
210
|
+
for (var j = i + 1; j < paths_googleLatLng.length; j++) {
|
|
211
|
+
if (FieldValidator.calcIntersection(FieldValidator.path_convert(shapesPath[i]), FieldValidator.path_convert(shapesPath[j]))) {
|
|
212
|
+
holeIntersectCount++;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return (holeIntersectCount > 0);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Validates coordinates
|
|
221
|
+
static coordinatesValidate(coordinates, polygonType) {
|
|
222
|
+
|
|
223
|
+
FieldValidator.checkGoogleAPI();
|
|
224
|
+
|
|
225
|
+
var isValid = false;
|
|
226
|
+
var errorMessage = '';
|
|
227
|
+
var encodedField = '';
|
|
228
|
+
|
|
229
|
+
if (polygonType == 'Polygon') {
|
|
230
|
+
if (coordinates.length > 0) {
|
|
231
|
+
polycoords = coordinates;
|
|
232
|
+
// check if any of the shapes has less then three vertices (four coordinates)
|
|
233
|
+
invalidVerticesCount = 0;
|
|
234
|
+
|
|
235
|
+
polycoords.forEach(poly => {
|
|
236
|
+
if (poly.length < 4) {
|
|
237
|
+
invalidVerticesCount++;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
if (invalidVerticesCount == 0) {
|
|
242
|
+
// check if first and last coordinate are the same
|
|
243
|
+
invalidStartEndCount = 0;
|
|
244
|
+
|
|
245
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
246
|
+
if (poly[0][0] != poly[poly.length - 1][0] || poly[0][1] != poly[poly.length - 1][1]) {
|
|
247
|
+
invalidStartEndCount++;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
if (invalidStartEndCount == 0) {
|
|
252
|
+
selfIntersectionCount = 0;
|
|
253
|
+
|
|
254
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
255
|
+
// check self-intersection
|
|
256
|
+
invalidPoints = FieldValidator.findSelfIntersects(poly);
|
|
257
|
+
selfIntersectionCount += invalidPoints.length;
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
if (selfIntersectionCount == 0) {
|
|
261
|
+
paths = [];
|
|
262
|
+
// check orientation of outer and inner polygons using signed area
|
|
263
|
+
invalidOrientationCount = 0;
|
|
264
|
+
|
|
265
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
266
|
+
path = [];
|
|
267
|
+
|
|
268
|
+
poly.forEach(function (c, cindex) {
|
|
269
|
+
path.push(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])));
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
signedArea = google.maps.geometry.spherical.computeSignedArea(path);
|
|
273
|
+
console.log('signedArea before: '+signedArea);
|
|
274
|
+
|
|
275
|
+
if (polyindex == 0 && signedArea > 0) {
|
|
276
|
+
path.reverse();
|
|
277
|
+
//invalidOrientationCount++;
|
|
278
|
+
//path.reverse();
|
|
279
|
+
//invalidOrientationCount--;
|
|
280
|
+
}
|
|
281
|
+
if (polyindex > 0 && signedArea < 0) {
|
|
282
|
+
//invalidOrientationCount++;
|
|
283
|
+
path.reverse();
|
|
284
|
+
//invalidOrientationCount--;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
signedArea = google.maps.geometry.spherical.computeSignedArea(path);
|
|
288
|
+
console.log('signedArea after: '+signedArea);
|
|
289
|
+
if (polyindex == 0 && signedArea > 0) {
|
|
290
|
+
invalidOrientationCount++;
|
|
291
|
+
}
|
|
292
|
+
if (polyindex > 0 && signedArea < 0) {
|
|
293
|
+
invalidOrientationCount++;
|
|
294
|
+
}
|
|
295
|
+
paths.push(path);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
if (invalidOrientationCount == 0) {
|
|
299
|
+
if (paths.length == 1) {
|
|
300
|
+
encodedField = google.maps.geometry.encoding.encodePath(paths[0]);
|
|
301
|
+
isValid = true;
|
|
302
|
+
}
|
|
303
|
+
else if (paths.length > 1) {
|
|
304
|
+
// check if holes are inside outer polygon
|
|
305
|
+
outerPoly = new google.maps.Polygon({
|
|
306
|
+
path: paths[0]
|
|
307
|
+
});
|
|
308
|
+
notInsideCount = 0;
|
|
309
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
310
|
+
if (polyindex > 0) {
|
|
311
|
+
poly.forEach(function (c, cindex) {
|
|
312
|
+
if (!google.maps.geometry.poly.containsLocation(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])), outerPoly)) {
|
|
313
|
+
notInsideCount++;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
//console.log('Polygon notInsideCount: '+notInsideCount);
|
|
319
|
+
|
|
320
|
+
if (notInsideCount == 0) {
|
|
321
|
+
console.log('Polygon paths.length: ' + paths.length);
|
|
322
|
+
if (paths.length == 2) {
|
|
323
|
+
encodedPath = '';
|
|
324
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
325
|
+
path = [];
|
|
326
|
+
poly.forEach(function (c, cindex) {
|
|
327
|
+
path.push(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])));
|
|
328
|
+
});
|
|
329
|
+
encodedPath += google.maps.geometry.encoding.encodePath(path) + ',';
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
encodedField = encodedPath.substr(0, encodedPath.length - 1);
|
|
333
|
+
isValid = true;
|
|
334
|
+
|
|
335
|
+
}
|
|
336
|
+
else if (paths.length > 2) {
|
|
337
|
+
// check if holes don't intersect each other if there is more than one hole
|
|
338
|
+
holeIntersectCount = 0;
|
|
339
|
+
//var combis = [];
|
|
340
|
+
|
|
341
|
+
for (var i = 1; i < paths.length - 1; i++) {
|
|
342
|
+
for (var j = i + 1; j < paths.length; j++) {
|
|
343
|
+
if (FieldValidator.calcIntersection(polycoords[i], polycoords[j])) {
|
|
344
|
+
holeIntersectCount++;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (holeIntersectCount == 0) {
|
|
350
|
+
encodedPath = '';
|
|
351
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
352
|
+
path = [];
|
|
353
|
+
poly.forEach(function (c, cindex) {
|
|
354
|
+
path.push(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])));
|
|
355
|
+
});
|
|
356
|
+
encodedPath += google.maps.geometry.encoding.encodePath(path) + ',';
|
|
357
|
+
});
|
|
358
|
+
isValid = true;
|
|
359
|
+
encodedField = encodedPath.substr(0, encodedPath.length - 1);
|
|
360
|
+
|
|
361
|
+
} else {
|
|
362
|
+
errorMessage = 'At least two holes intersect';
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
errorMessage = 'At least one hole intersects with the outer polygon';
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
} else {
|
|
370
|
+
errorMessage = 'The uploaded polygon(s) have an invalid orientation';
|
|
371
|
+
}
|
|
372
|
+
} else {
|
|
373
|
+
errorMessage = 'There is self-intersection in the uploaded polygon(s)';
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
errorMessage = 'The path of the uploaded polygon(s) is not complete';
|
|
377
|
+
}
|
|
378
|
+
} else {
|
|
379
|
+
errorMessage = 'There is an insufficient amount of vertices in at least one of the uploaded polygon(s)';
|
|
380
|
+
}
|
|
381
|
+
} else {
|
|
382
|
+
errorMessage = 'There are no coordinates for the uploaded polygon';
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else if (polygonType == 'MultiPolygon') {
|
|
386
|
+
if (coordinates.length > 1) {
|
|
387
|
+
errorMessage = 'There is more than one outer polygon';
|
|
388
|
+
} else if (coordinates.length == 1) {
|
|
389
|
+
if (coordinates[0].length > 0) {
|
|
390
|
+
polycoords = coordinates[0];
|
|
391
|
+
// check if any of the shapes has less then three vertices (four coordinates)
|
|
392
|
+
invalidVerticesCount = 0;
|
|
393
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
394
|
+
console.log('MP polyindex: ' + polyindex);
|
|
395
|
+
console.log('MP poly.length: ' + poly.length);
|
|
396
|
+
if (poly.length < 4) {
|
|
397
|
+
invalidVerticesCount++;
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
if (invalidVerticesCount == 0) {
|
|
402
|
+
// check if first and last coordinate are the same
|
|
403
|
+
invalidStartEndCount = 0;
|
|
404
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
405
|
+
if (poly[0][0] != poly[poly.length - 1][0] || poly[0][1] != poly[poly.length - 1][1]) {
|
|
406
|
+
invalidStartEndCount++;
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
if (invalidStartEndCount == 0) {
|
|
410
|
+
selfIntersectionCount = 0;
|
|
411
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
412
|
+
// check self-intersection
|
|
413
|
+
invalidPoints = FieldValidator.findSelfIntersects(poly);
|
|
414
|
+
selfIntersectionCount += invalidPoints.length;
|
|
415
|
+
});
|
|
416
|
+
if (selfIntersectionCount == 0) {
|
|
417
|
+
paths = [];
|
|
418
|
+
// check orientation of outer and inner polygons using signed area
|
|
419
|
+
invalidOrientationCount = 0;
|
|
420
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
421
|
+
path = [];
|
|
422
|
+
poly.forEach(function (c, cindex) {
|
|
423
|
+
path.push(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])));
|
|
424
|
+
});
|
|
425
|
+
signedArea = google.maps.geometry.spherical.computeSignedArea(path);
|
|
426
|
+
if (polyindex == 0 && signedArea > 0) {
|
|
427
|
+
path.reverse();
|
|
428
|
+
}
|
|
429
|
+
if (polyindex > 0 && signedArea < 0) {
|
|
430
|
+
path.reverse();
|
|
431
|
+
}
|
|
432
|
+
signedArea = google.maps.geometry.spherical.computeSignedArea(path);
|
|
433
|
+
if (polyindex == 0 && signedArea > 0) {
|
|
434
|
+
invalidOrientationCount++;
|
|
435
|
+
}
|
|
436
|
+
if (polyindex > 0 && signedArea < 0) {
|
|
437
|
+
invalidOrientationCount++;
|
|
438
|
+
}
|
|
439
|
+
paths.push(path);
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
if (invalidOrientationCount == 0) {
|
|
443
|
+
if (paths.length == 1) {
|
|
444
|
+
encodedField = google.maps.geometry.encoding.encodePath(paths[0]);
|
|
445
|
+
isValid = true;
|
|
446
|
+
} else if (paths.length > 1) {
|
|
447
|
+
// check if holes are inside outer polygon
|
|
448
|
+
outerPoly = new google.maps.Polygon({
|
|
449
|
+
path: paths[0]
|
|
450
|
+
});
|
|
451
|
+
notInsideCount = 0;
|
|
452
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
453
|
+
if (polyindex > 0) {
|
|
454
|
+
poly.forEach(function (c, cindex) {
|
|
455
|
+
if (!google.maps.geometry.poly.containsLocation(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])), outerPoly)) {
|
|
456
|
+
notInsideCount++;
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
//console.log('Polygon notInsideCount: '+notInsideCount);
|
|
462
|
+
|
|
463
|
+
if (notInsideCount == 0) {
|
|
464
|
+
console.log('Polygon paths.length: ' + paths.length);
|
|
465
|
+
if (paths.length == 2) {
|
|
466
|
+
encodedPath = '';
|
|
467
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
468
|
+
path = [];
|
|
469
|
+
poly.forEach(function (c, cindex) {
|
|
470
|
+
path.push(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])));
|
|
471
|
+
});
|
|
472
|
+
encodedPath += google.maps.geometry.encoding.encodePath(path) + ',';
|
|
473
|
+
});
|
|
474
|
+
encodedField = encodedPath.substr(0, encodedPath.length - 1);
|
|
475
|
+
isValid = true;
|
|
476
|
+
|
|
477
|
+
} else if (paths.length > 2) {
|
|
478
|
+
// check if holes don't intersect each other if there is more than one hole
|
|
479
|
+
holeIntersectCount = 0;
|
|
480
|
+
//var combis = [];
|
|
481
|
+
for (var i = 1; i < paths.length - 1; i++) {
|
|
482
|
+
for (var j = i + 1; j < paths.length; j++) {
|
|
483
|
+
if (calcIntersection(polycoords[i], polycoords[j])) {
|
|
484
|
+
holeIntersectCount++;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (holeIntersectCount == 0) {
|
|
489
|
+
encodedPath = '';
|
|
490
|
+
polycoords.forEach(function (poly, polyindex) {
|
|
491
|
+
path = [];
|
|
492
|
+
poly.forEach(function (c, cindex) {
|
|
493
|
+
path.push(new google.maps.LatLng(parseFloat(c[1]), parseFloat(c[0])));
|
|
494
|
+
});
|
|
495
|
+
encodedPath += google.maps.geometry.encoding.encodePath(path) + ',';
|
|
496
|
+
});
|
|
497
|
+
encodedField = encodedPath.substr(0, encodedPath.length - 1);
|
|
498
|
+
isValid = true
|
|
499
|
+
|
|
500
|
+
} else {
|
|
501
|
+
errorMessage = 'At least two holes intersect';
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
} else {
|
|
505
|
+
errorMessage = 'At least one hole intersects with the outer polygon';
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
} else {
|
|
509
|
+
errorMessage = 'The uploaded polygon(s) have an invalid orientation';
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
errorMessage = 'There is self-intersection in the uploaded polygon(s)';
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
errorMessage = 'The path of the uploaded polygon(s) is not complete';
|
|
516
|
+
}
|
|
517
|
+
} else {
|
|
518
|
+
errorMessage = 'There is an insufficient amount of vertices in at least one of the uploaded polygon(s)';
|
|
519
|
+
}
|
|
520
|
+
} else {
|
|
521
|
+
errorMessage = 'There are no coordinates for the uploaded polygon(s)';
|
|
522
|
+
}
|
|
523
|
+
} else {
|
|
524
|
+
errorMessage = 'There are no coordinates for the uploaded polygon(s)';
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
return {
|
|
530
|
+
'isValid': isValid,
|
|
531
|
+
'errorMessage': errorMessage,
|
|
532
|
+
'encodedField': encodedField
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Validates field
|
|
537
|
+
static mapFieldsValidate(encodedShapes) {
|
|
538
|
+
|
|
539
|
+
FieldValidator.checkGoogleAPI();
|
|
540
|
+
var errorMessage = '';
|
|
541
|
+
|
|
542
|
+
// Decoded shapes
|
|
543
|
+
var shapesPath = FieldValidator.decodeShapes_get(encodedShapes);
|
|
544
|
+
|
|
545
|
+
var paths_googleLatLng = FieldValidator.pathToGoogleLatLng_get(shapesPath);
|
|
546
|
+
|
|
547
|
+
if (shapesPath.length > 0 ) {
|
|
548
|
+
// Checks if any of the listed shapes has a selfintersection
|
|
549
|
+
if (!FieldValidator.selfInterceptionShape_check(shapesPath)) {
|
|
550
|
+
// Checks if every hole is outside the outer shape
|
|
551
|
+
if (!FieldValidator.holesOutsideOuterShape_check(shapesPath, paths_googleLatLng)) {
|
|
552
|
+
// Checks if every hole is inside the outer shape
|
|
553
|
+
if (FieldValidator.holesInterceptOuterShape_check(shapesPath, paths_googleLatLng)) {
|
|
554
|
+
if (paths_googleLatLng.length > 2) {
|
|
555
|
+
// Check if holes don't intersect each other if there is more than one hole
|
|
556
|
+
if (!FieldValidator.holesIntercept_check(shapesPath, paths_googleLatLng)) {
|
|
557
|
+
} else {
|
|
558
|
+
errorMessage = 'ShapeInterceptingShape';
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
} else {
|
|
562
|
+
errorMessage = 'ShapeOutsideOutterShape';
|
|
563
|
+
}
|
|
564
|
+
} else {
|
|
565
|
+
errorMessage = 'ShapeOutsideOutterShape';
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
} else {
|
|
569
|
+
errorMessage = 'InterceptShapes';
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return (errorMessage);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function toRadians(angleInDegrees) {
|
|
2
|
+
return (angleInDegrees * Math.PI) / 180;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function toDegrees(angleInRadians) {
|
|
6
|
+
return (angleInRadians * 180) / Math.PI;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function offset(c1, distance, bearing) {
|
|
10
|
+
var lat1 = toRadians(c1[1]);
|
|
11
|
+
var lon1 = toRadians(c1[0]);
|
|
12
|
+
var dByR = distance / 6378137;
|
|
13
|
+
var lat = Math.asin(Math.sin(lat1) * Math.cos(dByR) + Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));
|
|
14
|
+
var lon = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1), Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));
|
|
15
|
+
return new google.maps.LatLng({ lat: toDegrees(lat), lng: toDegrees(lon) });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function circleToPolygon(center, radius, numberOfWaypoints, isHole) {
|
|
19
|
+
var coordinates = [];
|
|
20
|
+
for (var i = 0; i < numberOfWaypoints; ++i) {
|
|
21
|
+
coordinates.push(offset(center, radius, (2 * Math.PI * - i) / numberOfWaypoints));
|
|
22
|
+
}
|
|
23
|
+
if (isHole) {
|
|
24
|
+
return coordinates;
|
|
25
|
+
} else {
|
|
26
|
+
return coordinates.reverse();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { toRadians, toDegrees, offset, circleToPolygon };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class IQLFieldGeoLocation {
|
|
2
|
+
|
|
3
|
+
IsValid = '';
|
|
4
|
+
Poly = '';
|
|
5
|
+
Area = 0;
|
|
6
|
+
Perimeter = 0;
|
|
7
|
+
Latitude = 0;
|
|
8
|
+
Longitude = 0;
|
|
9
|
+
|
|
10
|
+
constructor(path, area, perimeter, latitude, longitude, IsValid) {
|
|
11
|
+
this.Poly = path;
|
|
12
|
+
this.Area = area;
|
|
13
|
+
this.Perimeter = perimeter;
|
|
14
|
+
this.Latitude = latitude;
|
|
15
|
+
this.Longitude = longitude;
|
|
16
|
+
this.IsValid = IsValid;
|
|
17
|
+
this.GeoJSON = undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|