geojs 1.8.2 → 1.8.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geojs",
3
- "version": "1.8.2",
3
+ "version": "1.8.5",
4
4
  "description": "JavaScript Geo Visualization and Analysis Library",
5
5
  "homepage": "https://github.com/OpenGeoscience/geojs",
6
6
  "license": "Apache-2.0",
@@ -51,7 +51,7 @@
51
51
  "expose-loader": "^3.1.0",
52
52
  "express": "^4.17.2",
53
53
  "fs-extra": "^10.0.0",
54
- "glob": "^7.2.0",
54
+ "glob": "^8.0.1",
55
55
  "glslang-validator-prebuilt": "^0.0.7",
56
56
  "imports-loader": "^3.1.1",
57
57
  "jaguarjs-jsdoc": "^1.0.2",
@@ -65,11 +65,11 @@
65
65
  "karma-chrome-launcher": "^3.1.0",
66
66
  "karma-coverage": "^2.1.1",
67
67
  "karma-firefox-launcher": "^2.1.2",
68
- "karma-jasmine": "^4.0.1",
68
+ "karma-jasmine": "^5.0.0",
69
69
  "karma-jasmine-html-reporter": "^1.7.0",
70
70
  "karma-sinon": "^1.0.5",
71
71
  "karma-sourcemap-loader": "^0.3.8",
72
- "karma-spec-reporter": "^0.0.33",
72
+ "karma-spec-reporter": "^0.0.34",
73
73
  "karma-webpack": "^5.0.0",
74
74
  "nib": "^1.1.2",
75
75
  "npm-run-all": "^4.1.5",
@@ -82,17 +82,17 @@
82
82
  "semantic-release": "^19.0.2",
83
83
  "serve-index": "^1.9.1",
84
84
  "shader-loader": "^1.3.1",
85
- "sinon": "^13.0.1",
86
- "string-replace-webpack-plugin": "^0.1.3",
85
+ "sinon": "^14.0.0",
87
86
  "style-loader": "^3.3.1",
88
- "stylus": "^0.56.0",
87
+ "stylus": "^0.57.0",
89
88
  "stylus-loader": "^6.2.0",
90
89
  "terser-webpack-plugin": "^5.3.1",
91
90
  "touch-emulator": "^1.0.0",
92
91
  "typeface-lato": "^1.1.13",
93
92
  "webpack": "^5.68.0",
94
93
  "webpack-cli": "^4.9.1",
95
- "webpack-merge": "^5.8.0"
94
+ "webpack-merge": "^5.8.0",
95
+ "webpack-string-replacer": "^0.0.20"
96
96
  },
97
97
  "release": {
98
98
  "plugins": [
package/src/annotation.js CHANGED
@@ -215,7 +215,7 @@ var annotation = function (type, args) {
215
215
  */
216
216
  this._rotateHandlePosition = function (offset, rotation) {
217
217
  var map = m_this.layer().map(),
218
- coor = m_this._coordinates(),
218
+ coord = m_this._coordinates(),
219
219
  center = util.centerFromPerimeter(m_this._coordinates()),
220
220
  dispCenter = center ? map.gcsToDisplay(center, null) : undefined,
221
221
  i, pos, maxr2 = 0, r;
@@ -224,8 +224,9 @@ var annotation = function (type, args) {
224
224
  }
225
225
  offset = offset || 0;
226
226
  rotation = rotation || 0;
227
- for (i = 0; i < coor.length; i += 1) {
228
- pos = map.gcsToDisplay(coor[i], null);
227
+ coord = coord.outer ? coord.outer : coord;
228
+ for (i = 0; i < coord.length; i += 1) {
229
+ pos = map.gcsToDisplay(coord[i], null);
229
230
  maxr2 = Math.max(maxr2, Math.pow(pos.x - dispCenter.x, 2) + Math.pow(pos.y - dispCenter.y, 2));
230
231
  }
231
232
  r = Math.sqrt(maxr2) + offset;
@@ -390,6 +391,22 @@ var annotation = function (type, args) {
390
391
  }
391
392
  };
392
393
 
394
+ /**
395
+ * Return a copy of the _coordinates or a geo.polygon record so that it
396
+ * doesn't share memory with the original.
397
+ *
398
+ * @param {geo.polygon} [coord] if specified, return a copy of this object.
399
+ * Otherwise, return a copy of this._coordinates.
400
+ * @returns {geo.polygon}
401
+ */
402
+ this._copyOfCoordinates = function (coord) {
403
+ coord = coord || m_this._coordinates();
404
+ if (!coord.outer) {
405
+ return coord.slice();
406
+ }
407
+ return {outer: coord.outer.slice(), inner: (coord.inner || []).map((h) => h.slice())};
408
+ };
409
+
393
410
  /**
394
411
  * When an edit handle is selected or deselected (for instance, by moving the
395
412
  * mouse on or off of it), mark if it is selected and record the current
@@ -409,7 +426,7 @@ var annotation = function (type, args) {
409
426
  var amountRotated = (m_this._editHandle || {}).amountRotated || 0;
410
427
  m_this._editHandle = {
411
428
  handle: handle,
412
- startCoordinates: m_this._coordinates().slice(),
429
+ startCoordinates: m_this._copyOfCoordinates(),
413
430
  center: util.centerFromPerimeter(m_this._coordinates()),
414
431
  rotatePosition: m_this._rotateHandlePosition(
415
432
  handle.style.rotateHandleOffset, handle.style.rotateHandleRotation + amountRotated),
@@ -465,9 +482,9 @@ var annotation = function (type, args) {
465
482
  m_options[arg1] = arg2;
466
483
  }
467
484
  if (m_options.coordinates) {
468
- var coor = m_options.coordinates;
485
+ var coord = m_options.coordinates;
469
486
  delete m_options.coordinates;
470
- m_this._coordinates(coor);
487
+ m_this._coordinates(coord);
471
488
  }
472
489
  if (m_options.name !== undefined) {
473
490
  var name = m_options.name;
@@ -676,7 +693,7 @@ var annotation = function (type, args) {
676
693
  gcs = (gcs === null ? map.gcs() : (
677
694
  gcs === undefined ? map.ingcs() : gcs));
678
695
  if (gcs !== map.gcs()) {
679
- coord = transform.transformCoordinates(map.gcs(), gcs, coord);
696
+ coord = m_this._convertCoordinates(map.gcs(), gcs, coord);
680
697
  }
681
698
  }
682
699
  return coord;
@@ -752,20 +769,20 @@ var annotation = function (type, args) {
752
769
  * should not be represented (for instance, while it is being created).
753
770
  */
754
771
  this.geojson = function (gcs, includeCrs) {
755
- var coor = m_this._geojsonCoordinates(gcs),
772
+ var coord = m_this._geojsonCoordinates(gcs),
756
773
  geotype = m_this._geojsonGeometryType(),
757
774
  styles = m_this._geojsonStyles(),
758
775
  objStyle = m_this.options('style') || {},
759
776
  objLabelStyle = m_this.labelStyle() || {},
760
777
  i, key, value;
761
- if (!coor || !coor.length || !geotype) {
778
+ if (!coord || !coord.length || !geotype) {
762
779
  return;
763
780
  }
764
781
  var obj = {
765
782
  type: 'Feature',
766
783
  geometry: {
767
784
  type: geotype,
768
- coordinates: coor
785
+ coordinates: coord
769
786
  },
770
787
  properties: {
771
788
  annotationType: m_type,
@@ -850,22 +867,25 @@ var annotation = function (type, args) {
850
867
  features[editHandleFeatureLevel] = {point: []};
851
868
  }
852
869
  editPoints = features[editHandleFeatureLevel].point;
853
- vertices.forEach(function (pt, idx) {
854
- if (opts.vertex !== false) {
855
- editPoints.push($.extend({}, pt, {type: 'vertex', index: idx, style: style, editHandle: true}));
856
- }
857
- if (opts.edge !== false && idx !== vertices.length - 1 && (pt.x !== vertices[idx + 1].x || pt.y !== vertices[idx + 1].y)) {
858
- editPoints.push($.extend({
859
- x: (pt.x + vertices[idx + 1].x) / 2,
860
- y: (pt.y + vertices[idx + 1].y) / 2
861
- }, {type: 'edge', index: idx, style: style, editHandle: true}));
862
- }
863
- if (opts.edge !== false && !isOpen && idx === vertices.length - 1 && (pt.x !== vertices[0].x || pt.y !== vertices[0].y)) {
864
- editPoints.push($.extend({
865
- x: (pt.x + vertices[0].x) / 2,
866
- y: (pt.y + vertices[0].y) / 2
867
- }, {type: 'edge', index: idx, style: style, editHandle: true}));
868
- }
870
+ const vertexList = vertices.outer ? [vertices.outer].concat(vertices.inner || []) : [vertices];
871
+ vertexList.forEach((vert, vidx) => {
872
+ vert.forEach(function (pt, idx) {
873
+ if (opts.vertex !== false) {
874
+ editPoints.push($.extend({}, pt, {type: 'vertex', index: idx, vindex: vidx, style: style, editHandle: true}));
875
+ }
876
+ if (opts.edge !== false && idx !== vert.length - 1 && (pt.x !== vert[idx + 1].x || pt.y !== vert[idx + 1].y)) {
877
+ editPoints.push($.extend({
878
+ x: (pt.x + vert[idx + 1].x) / 2,
879
+ y: (pt.y + vert[idx + 1].y) / 2
880
+ }, {type: 'edge', index: idx, vindex: vidx, style: style, editHandle: true}));
881
+ }
882
+ if (opts.edge !== false && !isOpen && idx === vert.length - 1 && (pt.x !== vert[0].x || pt.y !== vert[0].y)) {
883
+ editPoints.push($.extend({
884
+ x: (pt.x + vert[0].x) / 2,
885
+ y: (pt.y + vert[0].y) / 2
886
+ }, {type: 'edge', index: idx, vindex: vidx, style: style, editHandle: true}));
887
+ }
888
+ });
869
889
  });
870
890
  if (opts.center !== false) {
871
891
  editPoints.push($.extend({}, util.centerFromPerimeter(m_this._coordinates()), {type: 'center', style: style, editHandle: true}));
@@ -887,13 +907,43 @@ var annotation = function (type, args) {
887
907
  }
888
908
  if (selected) {
889
909
  editPoints.forEach(function (pt) {
890
- if (pt.type === selected.type && pt.index === selected.index) {
910
+ if (pt.type === selected.type && pt.index === selected.index && pt.vindex === selected.vindex) {
891
911
  pt.selected = true;
892
912
  }
893
913
  });
894
914
  }
895
915
  };
896
916
 
917
+ /**
918
+ * Apply a map function of a geo.polygon.
919
+ *
920
+ * @param {geo.polygon} coord The polygon to apply the function to.
921
+ * @param {function} func The function to apply.
922
+ * @returns {array} The map results.
923
+ */
924
+ this._coordinatesMapFunc = function (coord, func) {
925
+ if (!coord.outer) {
926
+ return coord.map(func);
927
+ }
928
+ return {
929
+ outer: coord.outer.map(func),
930
+ inner: (coord.inner || []).map((h) => h.map(func))
931
+ };
932
+ };
933
+
934
+ /**
935
+ * Check if two geo.polygons differ in their first point.
936
+ *
937
+ * @param {geo.polygon} coord1 One polygon to compare.
938
+ * @param {geo.polygon} coord2 A second polygon to compare.
939
+ * @returns {boolean} true if the first point matches.
940
+ */
941
+ this._firstPointDifferent = function (coord1, coord2) {
942
+ coord1 = coord1.outer ? coord1.outer : coord1;
943
+ coord2 = coord2.outer ? coord2.outer : coord2;
944
+ return (coord1[0].x !== coord2[0].x || coord1[0].y !== coord2[0].y);
945
+ };
946
+
897
947
  /**
898
948
  * Process the edit center action for a general annotation.
899
949
  *
@@ -908,10 +958,10 @@ var annotation = function (type, args) {
908
958
  y: evt.mouse.mapgcs.y - evt.state.origin.mapgcs.y
909
959
  },
910
960
  curPts = m_this._coordinates();
911
- var pts = start.map(function (elem) {
961
+ var pts = m_this._coordinatesMapFunc(start, function (elem) {
912
962
  return {x: elem.x + delta.x, y: elem.y + delta.y};
913
963
  });
914
- if (pts[0].x !== curPts[0].x || pts[0].y !== curPts[0].y) {
964
+ if (m_this._firstPointDifferent(pts, curPts)) {
915
965
  m_this._coordinates(pts);
916
966
  return true;
917
967
  }
@@ -940,14 +990,14 @@ var annotation = function (type, args) {
940
990
  handle.rotatePosition.x + delta.x - handle.center.x),
941
991
  ang = ang2 - ang1,
942
992
  curPts = m_this._coordinates();
943
- var pts = start.map(function (elem) {
993
+ var pts = m_this._coordinatesMapFunc(start, function (elem) {
944
994
  var delta = {x: elem.x - handle.center.x, y: elem.y - handle.center.y};
945
995
  return {
946
996
  x: delta.x * Math.cos(ang) - delta.y * Math.sin(ang) + handle.center.x,
947
997
  y: delta.x * Math.sin(ang) + delta.y * Math.cos(ang) + handle.center.y
948
998
  };
949
999
  });
950
- if (pts[0].x !== curPts[0].x || pts[0].y !== curPts[0].y) {
1000
+ if (m_this._firstPointDifferent(pts, curPts)) {
951
1001
  m_this._coordinates(pts);
952
1002
  handle.amountRotated = handle.startAmountRotated + ang;
953
1003
  return true;
@@ -985,13 +1035,13 @@ var annotation = function (type, args) {
985
1035
  curPts = m_this._coordinates();
986
1036
  if (d02 && d01) {
987
1037
  var scale = d02 / d01;
988
- var pts = start.map(function (elem) {
1038
+ var pts = m_this._coordinatesMapFunc(start, function (elem) {
989
1039
  return {
990
1040
  x: (elem.x - handle.center.x) * scale + handle.center.x,
991
1041
  y: (elem.y - handle.center.y) * scale + handle.center.y
992
1042
  };
993
1043
  });
994
- if (pts[0].x !== curPts[0].x || pts[0].y !== curPts[0].y) {
1044
+ if (m_this._firstPointDifferent(pts, curPts)) {
995
1045
  m_this._coordinates(pts);
996
1046
  return true;
997
1047
  }
@@ -1009,11 +1059,17 @@ var annotation = function (type, args) {
1009
1059
  this._processEditActionEdge = function (evt) {
1010
1060
  var handle = m_this._editHandle,
1011
1061
  index = handle.handle.index,
1062
+ vindex = handle.handle.vindex,
1012
1063
  curPts = m_this._coordinates();
1013
- curPts.splice(index + 1, 0, {x: handle.handle.x, y: handle.handle.y});
1064
+ if (!curPts.outer) {
1065
+ curPts.splice(index + 1, 0, {x: handle.handle.x, y: handle.handle.y});
1066
+ } else {
1067
+ const loop = vindex ? curPts.inner[vindex - 1] : curPts.outer;
1068
+ loop.splice(index + 1, 0, {x: handle.handle.x, y: handle.handle.y});
1069
+ }
1014
1070
  handle.handle.type = 'vertex';
1015
1071
  handle.handle.index += 1;
1016
- handle.startCoordinates = curPts.slice();
1072
+ handle.startCoordinates = m_this._copyOfCoordinates(curPts);
1017
1073
  m_this.modified();
1018
1074
  return true;
1019
1075
  };
@@ -1031,8 +1087,10 @@ var annotation = function (type, args) {
1031
1087
  this._processEditActionVertex = function (evt, canClose) {
1032
1088
  var handle = m_this._editHandle,
1033
1089
  index = handle.handle.index,
1090
+ vindex = handle.handle.vindex,
1034
1091
  start = handle.startCoordinates,
1035
- curPts = m_this._coordinates(),
1092
+ ptsRef = m_this._coordinates(),
1093
+ curPts = ptsRef.outer ? (vindex ? ptsRef.inner[vindex - 1] : ptsRef.outer) : ptsRef,
1036
1094
  origLen = curPts.length,
1037
1095
  origPt = curPts[index],
1038
1096
  delta = {
@@ -1043,6 +1101,9 @@ var annotation = function (type, args) {
1043
1101
  aPP = layer.options('adjacentPointProximity'),
1044
1102
  near, atEnd;
1045
1103
 
1104
+ if (start.outer) {
1105
+ start = vindex ? start.inner[vindex - 1] : start.outer;
1106
+ }
1046
1107
  curPts[index] = {
1047
1108
  x: start[index].x + delta.x,
1048
1109
  y: start[index].y + delta.y
@@ -1078,9 +1139,37 @@ var annotation = function (type, args) {
1078
1139
  curPts[index].x === origPt.x && curPts[index].y === origPt.y) {
1079
1140
  return false;
1080
1141
  }
1081
- m_this._coordinates(curPts);
1142
+
1143
+ m_this._coordinates(ptsRef);
1082
1144
  return true;
1083
1145
  };
1146
+
1147
+ /**
1148
+ * Transform the annotations coordinates from one gcs to another.
1149
+ *
1150
+ * @param {string|geo.transform} oldgcs The current gcs.
1151
+ * @param {string|geo.transform} newgcs The new gcs.
1152
+ * @param {geo.polygon} [coord] If not specified, convert the coordinates in
1153
+ * place. If specified, convert these coordinates and return them (don't
1154
+ * alter the existing values).
1155
+ * @returns {geo.polygon}
1156
+ */
1157
+ this._convertCoordinates = function (oldgcs, newgcs, coord) {
1158
+ const store = !coord;
1159
+ coord = coord || m_this._coordinates();
1160
+ if (!coord.outer) {
1161
+ coord = transform.transformCoordinates(oldgcs, newgcs, coord);
1162
+ } else {
1163
+ coord = {
1164
+ outer: transform.transformCoordinates(oldgcs, newgcs, coord.outer),
1165
+ inner: (coord.inner || []).map((h) => transform.transformCoordinates(oldgcs, newgcs, h))
1166
+ };
1167
+ }
1168
+ if (store) {
1169
+ m_this._coordinates(coord);
1170
+ }
1171
+ return coord;
1172
+ };
1084
1173
  };
1085
1174
 
1086
1175
  /* Functions used by multiple annotations */
@@ -1368,12 +1457,12 @@ var rectangleAnnotation = function (args, annotationName) {
1368
1457
  if (!src || m_this.state() === annotationState.create || src.length < 4) {
1369
1458
  return;
1370
1459
  }
1371
- var coor = [];
1460
+ var coord = [];
1372
1461
  for (var i = 0; i < 4; i += 1) {
1373
- coor.push([src[i].x, src[i].y]);
1462
+ coord.push([src[i].x, src[i].y]);
1374
1463
  }
1375
- coor.push([src[0].x, src[0].y]);
1376
- return [coor];
1464
+ coord.push([src[0].x, src[0].y]);
1465
+ return [coord];
1377
1466
  };
1378
1467
 
1379
1468
  /**
@@ -1745,12 +1834,16 @@ var polygonAnnotation = function (args) {
1745
1834
  fillColor: {r: 0.3, g: 0.3, b: 0.3},
1746
1835
  fillOpacity: 0.25,
1747
1836
  line: function (d) {
1837
+ const coord = m_this._coordinates();
1748
1838
  /* Return an array that has the same number of items as we have
1749
1839
  * vertices. */
1750
- return Array.apply(null, Array(m_this.options('vertices').length)).map(
1840
+ return Array.apply(null, Array((coord.outer || coord).length)).map(
1751
1841
  function () { return d; });
1752
1842
  },
1753
1843
  position: function (d, i) {
1844
+ if (d.x !== undefined) {
1845
+ return d.x;
1846
+ }
1754
1847
  return m_this.options('vertices')[i];
1755
1848
  },
1756
1849
  stroke: false,
@@ -1779,7 +1872,7 @@ var polygonAnnotation = function (args) {
1779
1872
  switch (state) {
1780
1873
  case annotationState.create:
1781
1874
  features = [];
1782
- if (opt.vertices && opt.vertices.length >= 3) {
1875
+ if (opt.vertices && (opt.vertices.outer || opt.vertices.length >= 3)) {
1783
1876
  features[1] = {
1784
1877
  polygon: {
1785
1878
  polygon: opt.vertices,
@@ -1939,15 +2032,23 @@ var polygonAnnotation = function (args) {
1939
2032
  */
1940
2033
  this._geojsonCoordinates = function (gcs) {
1941
2034
  var src = m_this.coordinates(gcs);
1942
- if (!src || src.length < 3 || m_this.state() === annotationState.create) {
2035
+ if (!src || (!src.outer && src.length < 3) || m_this.state() === annotationState.create) {
1943
2036
  return;
1944
2037
  }
1945
- var coor = [];
1946
- for (var i = 0; i < src.length; i += 1) {
1947
- coor.push([src[i].x, src[i].y]);
2038
+ var coord = [];
2039
+ if (!src.outer) {
2040
+ coord = [src.map((pt) => [pt.x, pt.y])];
2041
+ coord[0].push(coord[0][0].slice());
2042
+ } else {
2043
+ coord = [src.outer.map((pt) => [pt.x, pt.y])];
2044
+ coord[0].push(coord[0][0].slice());
2045
+ (src.inner || []).forEach((h) => {
2046
+ const poly = h.map((pt) => [pt.x, pt.y]);
2047
+ poly.push(poly[0].slice());
2048
+ coord.push(poly);
2049
+ });
1948
2050
  }
1949
- coor.push([src[0].x, src[0].y]);
1950
- return [coor];
2051
+ return coord;
1951
2052
  };
1952
2053
 
1953
2054
  /**
@@ -2220,11 +2321,11 @@ var lineAnnotation = function (args) {
2220
2321
  if (!src || src.length < 2 || m_this.state() === annotationState.create) {
2221
2322
  return;
2222
2323
  }
2223
- var coor = [];
2324
+ var coord = [];
2224
2325
  for (var i = 0; i < src.length; i += 1) {
2225
- coor.push([src[i].x, src[i].y]);
2326
+ coord.push([src[i].x, src[i].y]);
2226
2327
  }
2227
- return coor;
2328
+ return coord;
2228
2329
  };
2229
2330
 
2230
2331
  /**
@@ -417,8 +417,7 @@ var annotationLayer = function (arg) {
417
417
  gcs = (gcs === null ? map.gcs() : (
418
418
  gcs === undefined ? map.ingcs() : gcs));
419
419
  if (gcs !== map.gcs()) {
420
- annotation._coordinates(transform.transformCoordinates(
421
- gcs, map.gcs(), annotation._coordinates()));
420
+ annotation._convertCoordinates(gcs, map.gcs());
422
421
  }
423
422
  if (update !== false) {
424
423
  m_this.modified();
@@ -707,14 +706,25 @@ var annotationLayer = function (arg) {
707
706
  return;
708
707
  }
709
708
  // make a copy of the position array to avoid mutating the original.
710
- position = position.outer.slice();
711
- if (position[position.length - 1][0] === position[0][0] &&
712
- position[position.length - 1][1] === position[0][1]) {
713
- position.splice(position.length - 1, 1);
714
- if (position.length < 3) {
709
+ position = {
710
+ outer: position.outer.slice(),
711
+ inner: (position.inner || []).map((h) => h.slice())
712
+ };
713
+ if (position.outer[position.outer.length - 1][0] === position.outer[0][0] &&
714
+ position.outer[position.outer.length - 1][1] === position.outer[0][1]) {
715
+ position.outer.splice(position.outer.length - 1, 1);
716
+ if (position.outer.length < 3) {
715
717
  return;
716
718
  }
717
719
  }
720
+ position.inner.forEach((h) => {
721
+ if (h.length > 3 && h[h.length - 1][0] === h[0][0] && h[h.length - 1][1] === h[0][1]) {
722
+ h.splice(h.length - 1, 1);
723
+ }
724
+ });
725
+ if (!position.inner || !position.inner.length) {
726
+ position = position.outer;
727
+ }
718
728
  break;
719
729
  case 'marker':
720
730
  position = data.geometry.coordinates[0].slice(0, 4);
@@ -723,15 +733,20 @@ var annotationLayer = function (arg) {
723
733
  position = [feature.position()(data, data_idx)];
724
734
  break;
725
735
  }
726
- for (i = 0; i < position.length; i += 1) {
727
- position[i] = util.normalizeCoordinates(position[i]);
728
- }
729
736
  datagcs = ((data.crs && data.crs.type === 'name' && data.crs.properties &&
730
737
  data.crs.properties.type === 'proj4' &&
731
738
  data.crs.properties.name) ? data.crs.properties.name : gcs);
732
- if (datagcs !== map.gcs()) {
733
- position = transform.transformCoordinates(datagcs, map.gcs(), position);
734
- }
739
+ [position.outer || position].concat(position.inner || []).forEach((poslist) => {
740
+ for (i = 0; i < poslist.length; i += 1) {
741
+ poslist[i] = util.normalizeCoordinates(poslist[i]);
742
+ }
743
+ if (datagcs !== map.gcs()) {
744
+ const transposlist = transform.transformCoordinates(datagcs, map.gcs(), poslist);
745
+ for (i = 0; i < poslist.length; i += 1) {
746
+ poslist[i] = transposlist[i];
747
+ }
748
+ }
749
+ });
735
750
  options.coordinates = position;
736
751
  /* For each style listed in the geojsonStyleProperties object, check if
737
752
  * is given under any of the variety of keys as a valid instance of the
package/src/fetchQueue.js CHANGED
@@ -40,6 +40,7 @@ var fetchQueue = function (options) {
40
40
  this._size = options.size || 6;
41
41
  this._initialSize = options.initialSize || 0;
42
42
  this._track = options.track || 600;
43
+ this._initialTrack = this._track;
43
44
  this._needed = options.needed || null;
44
45
  this._batch = false;
45
46
 
@@ -76,6 +77,30 @@ var fetchQueue = function (options) {
76
77
  }
77
78
  });
78
79
 
80
+ /**
81
+ * Get/set the track size. This is used to determine when to check if
82
+ * entries can be discarded.
83
+ * @property {number} track The number of entries to track without checking
84
+ * for discards.
85
+ * @name geo.fetchQueue#track
86
+ */
87
+ Object.defineProperty(this, 'track', {
88
+ get: function () { return m_this._track; },
89
+ set: function (n) { m_this._track = n; }
90
+ });
91
+
92
+ /**
93
+ * Get/set the initial track size. Unless changed, this is the value used
94
+ * for track on class initialization.
95
+ * @property {number} initialTrack The number of entries to track without
96
+ * checking for discards.
97
+ * @name geo.fetchQueue#intitialTrack
98
+ */
99
+ Object.defineProperty(this, 'initialTrack', {
100
+ get: function () { return m_this._initialTrack; },
101
+ set: function (n) { m_this._initialTrack = n; }
102
+ });
103
+
79
104
  /**
80
105
  * Get the current queue size. Read only.
81
106
  * @property {number} length The current queue size.
@@ -121,8 +146,8 @@ var fetchQueue = function (options) {
121
146
  if (defer.__fetchQueue) {
122
147
  var pos = $.inArray(defer, m_this._queue);
123
148
  if (pos >= 0) {
124
- m_this._queue.splice(pos, 1);
125
- m_this._addToQueue(defer, atEnd);
149
+ // m_this._queue.splice(pos, 1);
150
+ m_this._addToQueue(defer, atEnd, pos);
126
151
  return defer;
127
152
  }
128
153
  }
@@ -152,20 +177,34 @@ var fetchQueue = function (options) {
152
177
  * @param {boolean} atEnd If falsy, add the item to the front of the queue
153
178
  * if batching is turned off or at the end of the current batch if it is
154
179
  * turned on. If truthy, always add the item to the end of the queue.
180
+ * @param {number} [pos] If specified, the current location in the queue of
181
+ * the object being added. This avoids having to splice, push, or unshift
182
+ * the queue.
155
183
  */
156
- this._addToQueue = function (defer, atEnd) {
184
+ this._addToQueue = function (defer, atEnd, pos) {
185
+ let move = atEnd ? m_this._queue.length - 1 : 0;
157
186
  defer.__fetchQueue._batch = m_this._batch;
158
- if (atEnd) {
159
- m_this._queue.push(defer);
160
- } else if (!this._batch) {
161
- m_this._queue.unshift(defer);
162
- } else {
163
- for (var i = 0; i < m_this._queue.length; i += 1) {
164
- if (m_this._queue[i].__fetchQueue._batch !== m_this._batch) {
187
+ if (!atEnd && m_this._batch) {
188
+ for (move = 0; move < m_this._queue.length - (pos === undefined ? 0 : 1); move += 1) {
189
+ if (m_this._queue[move].__fetchQueue._batch !== m_this._batch) {
165
190
  break;
166
191
  }
167
192
  }
168
- m_this._queue.splice(i, 0, defer);
193
+ }
194
+ if (pos === undefined) {
195
+ if (atEnd) {
196
+ m_this._queue.push(defer);
197
+ } else if (!move) {
198
+ m_this._queue.unshift(defer);
199
+ } else {
200
+ m_this._queue.splice(move, 0, defer);
201
+ }
202
+ } else if (pos !== move) {
203
+ const dir = pos < move ? 1 : -1;
204
+ for (let i = pos; i !== move; i += dir) {
205
+ m_this._queue[i] = m_this._queue[i + dir];
206
+ }
207
+ m_this._queue[move] = defer;
169
208
  }
170
209
  };
171
210
 
package/src/tileLayer.js CHANGED
@@ -16,7 +16,7 @@ var featureLayer = require('./featureLayer');
16
16
  * @property {function} [tilesAtZoom=null] A function that is given a zoom
17
17
  * level and returns `{x: (num), y: (num)}` with the number of tiles at that
18
18
  * zoom level.
19
- * @property {number} [cacheSize=400] The maximum number of tiles to cache.
19
+ * @property {number} [cacheSize=600] The maximum number of tiles to cache.
20
20
  * The default is 200 if keepLower is false.
21
21
  * @property {geo.fetchQueue} [queue] A fetch queue to use. If unspecified, a
22
22
  * new queue is created.
@@ -193,6 +193,10 @@ var tileLayer = function (arg) {
193
193
  arg = $.extend(true, {}, this.constructor.defaults, arg || {});
194
194
  if (!arg.cacheSize) {
195
195
  // this size should be sufficient for a 4k display
196
+ // where display size is (w, h), minimum tile dimension is ts, and total
197
+ // number of levels is ml, this is roughly
198
+ // sum([(math.ceil((w**2+h**2)**0.5 / (ts*2**l)) + 1) *
199
+ // (math.ceil(min(w, h) / (ts*2**l)) + 1) for l in range(ml)])
196
200
  arg.cacheSize = arg.keepLower ? 600 : 200;
197
201
  }
198
202
  if ($.type(arg.subdomains) === 'string') {
@@ -261,6 +265,9 @@ var tileLayer = function (arg) {
261
265
  });
262
266
  this._queue._tileLayers = this._queue._tileLayers || [];
263
267
  this._queue._tileLayers.push(m_this);
268
+ if (this._queue.initialTrack && this._queue.track) {
269
+ this._queue.track = this._queue.initialTrack * this._queue._tileLayers.length;
270
+ }
264
271
 
265
272
  var m_tileOffsetValues = {};
266
273
 
@@ -310,10 +317,16 @@ var tileLayer = function (arg) {
310
317
  if (m_this._queue !== queue) {
311
318
  if (this._queue && this._queue._tileLayers && this._queue._tileLayers.indexOf(m_this) >= 0) {
312
319
  this._queue._tileLayers.splice(this._queue._tileLayers.indexOf(m_this), 1);
320
+ if (this._queue.initialTrack && this._queue.track && this._queue._tileLayers.length) {
321
+ this._queue.track = this._queue.initialTrack * this._queue._tileLayers.length;
322
+ }
313
323
  }
314
324
  m_this._queue = queue;
315
325
  m_this._queue._tileLayers = m_this._queue._tileLayers || [];
316
326
  m_this._queue._tileLayers.push(m_this);
327
+ if (m_this._queue.initialTrack && m_this._queue.track) {
328
+ m_this._queue.track = m_this._queue.initialTrack * m_this._queue._tileLayers.length;
329
+ }
317
330
  }
318
331
  }
319
332
  });
@@ -1736,6 +1749,9 @@ var tileLayer = function (arg) {
1736
1749
  m_exited = true;
1737
1750
  if (this._queue && this._queue._tileLayers && this._queue._tileLayers.indexOf(m_this) >= 0) {
1738
1751
  this._queue._tileLayers.splice(this._queue._tileLayers.indexOf(m_this), 1);
1752
+ if (this._queue.initialTrack && this._queue.track && this._queue._tileLayers.length) {
1753
+ this._queue.track = this._queue.initialTrack * this._queue._tileLayers.length;
1754
+ }
1739
1755
  }
1740
1756
  return m_this;
1741
1757
  };
@@ -1765,7 +1781,7 @@ tileLayer.defaults = {
1765
1781
  topDown: false,
1766
1782
  keepLower: true,
1767
1783
  idleAfter: 'view',
1768
- // cacheSize: 400, // set depending on keepLower
1784
+ // cacheSize: 600, // set depending on keepLower
1769
1785
  tileRounding: Math.round,
1770
1786
  attribution: '',
1771
1787
  animationDuration: 0