geojs 1.6.3 → 1.7.0

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/README.md +14 -9
  3. package/geo.js +1101 -417
  4. package/geo.lean.js +1101 -417
  5. package/geo.lean.min.js +3 -3
  6. package/geo.min.js +5 -5
  7. package/package.json +6 -8
  8. package/src/annotation.js +11 -7
  9. package/src/annotationLayer.js +7 -7
  10. package/src/camera.js +5 -5
  11. package/src/canvas/pixelmapFeature.js +208 -0
  12. package/src/choroplethFeature.js +1 -1
  13. package/src/domRenderer.js +2 -1
  14. package/src/featureLayer.js +1 -1
  15. package/src/fileReader.js +2 -2
  16. package/src/imageTile.js +2 -1
  17. package/src/index.js +1 -0
  18. package/src/isolineFeature.js +1 -1
  19. package/src/layer.js +4 -2
  20. package/src/lineFeature.js +3 -3
  21. package/src/map.js +17 -15
  22. package/src/mapInteractor.js +17 -17
  23. package/src/markerFeature.js +2 -2
  24. package/src/meshFeature.js +1 -1
  25. package/src/osmLayer.js +2 -0
  26. package/src/pixelmapFeature.js +97 -249
  27. package/src/pixelmapLayer.js +145 -0
  28. package/src/pointFeature.js +1 -1
  29. package/src/polygonFeature.js +3 -3
  30. package/src/quadFeature.js +1 -1
  31. package/src/registry.js +2 -2
  32. package/src/svg/svgRenderer.js +3 -3
  33. package/src/tileCache.js +1 -1
  34. package/src/tileLayer.js +13 -12
  35. package/src/trackFeature.js +19 -19
  36. package/src/transform.js +8 -9
  37. package/src/typedef.js +2 -0
  38. package/src/ui/sliderWidget.js +1 -1
  39. package/src/util/clustering.js +3 -3
  40. package/src/util/color.js +1 -1
  41. package/src/util/common.js +7 -7
  42. package/src/util/throttle.js +1 -1
  43. package/src/webgl/index.js +2 -0
  44. package/src/webgl/lookupTable2D.js +122 -0
  45. package/src/webgl/markerFeature.js +1 -1
  46. package/src/webgl/pixelmapFeature.frag +47 -0
  47. package/src/webgl/pixelmapFeature.js +203 -0
  48. package/src/webgl/pointFeature.js +1 -1
  49. package/src/webgl/quadFeature.js +35 -2
  50. package/src/webgl/webglRenderer.js +1 -0
package/geo.js CHANGED
@@ -221,7 +221,7 @@ var annotation = function annotation(type, args) {
221
221
  /**
222
222
  * Get or set the name of this annotation.
223
223
  *
224
- * @param {string|undefined} arg If `undefined`, return the name, otherwise
224
+ * @param {string|undefined} [arg] If `undefined`, return the name, otherwise
225
225
  * change it. When setting the name, the value is trimmed of
226
226
  * whitespace. The name will not be changed to an empty string.
227
227
  * @returns {this|string} The current name or this annotation.
@@ -398,7 +398,7 @@ var annotation = function annotation(type, args) {
398
398
  /**
399
399
  * Get or set the state of this annotation.
400
400
  *
401
- * @param {string|undefined} arg If `undefined`, return the state,
401
+ * @param {string|undefined} [arg] If `undefined`, return the state,
402
402
  * otherwise change it. This should be one of the
403
403
  * {@link geo.annotation.state} values.
404
404
  * @returns {this|string} The current state or this annotation.
@@ -466,7 +466,7 @@ var annotation = function annotation(type, args) {
466
466
  */
467
467
 
468
468
 
469
- this.processAction = function () {
469
+ this.processAction = function (evt) {
470
470
  return undefined;
471
471
  };
472
472
  /**
@@ -1309,8 +1309,8 @@ var annotation = function annotation(type, args) {
1309
1309
  *
1310
1310
  * @param {object} m_this The current annotation instance.
1311
1311
  * @param {function} s_actions The parent actions method.
1312
- * @param {string} [state] The state to return actions for. Defaults to
1313
- * the current state.
1312
+ * @param {string|undefined} state The state to return actions for. Defaults
1313
+ * to the current state.
1314
1314
  * @param {string} name The name of this annotation.
1315
1315
  * @param {Array} originalArgs arguments to original call
1316
1316
  * @returns {geo.actionRecord[]} A list of actions.
@@ -1365,7 +1365,7 @@ function continuousVerticesProcessAction(m_this, evt, name) {
1365
1365
  }
1366
1366
 
1367
1367
  var cpp = layer.options('continuousPointProximity');
1368
- var cpc = layer.options('continuousPointColinearity');
1368
+ var cpc = layer.options('continuousPointCollinearity');
1369
1369
  var ccp = layer.options('continuousCloseProximity');
1370
1370
 
1371
1371
  if (cpp || cpp === 0) {
@@ -1381,7 +1381,7 @@ function continuousVerticesProcessAction(m_this, evt, name) {
1381
1381
  var dist = layer.displayDistance(vertices[vertices.length - 2], null, evt.mouse.map, 'display');
1382
1382
 
1383
1383
  if (dist && dist > cpp) {
1384
- // combine nearly colinear points
1384
+ // combine nearly collinear points
1385
1385
  if (vertices.length >= (m_this._lastClickVertexCount || 1) + 3) {
1386
1386
  var d01 = layer.displayDistance(vertices[vertices.length - 3], null, vertices[vertices.length - 2], null),
1387
1387
  d12 = dist,
@@ -1429,6 +1429,11 @@ function continuousVerticesProcessAction(m_this, evt, name) {
1429
1429
  * rectangle in edit mode.
1430
1430
  */
1431
1431
 
1432
+ /*
1433
+ * @typedef {object} geo.rectangleAnnotation.subspec
1434
+ * @typedef {geo.annotation.spec | geo.rectangleAnnotation.subspec} geo.rectangleAnnotation.spec
1435
+ */
1436
+
1432
1437
  /**
1433
1438
  * Rectangle annotation class.
1434
1439
  *
@@ -2894,9 +2899,9 @@ var textFeature = __webpack_require__(9757);
2894
2899
  * @property {number} [continuousPointProximity=5] The minimum distance in
2895
2900
  * display coordinates (pixels) between two adjacent points when dragging
2896
2901
  * to create an annotation. `false` disables continuous drawing mode.
2897
- * @property {number} [continuousPointColinearity=1.0deg] The minimum angle
2902
+ * @property {number} [continuousPointCollinearity=1.0deg] The minimum angle
2898
2903
  * between a series of three points when dragging to not interpret them as
2899
- * colinear. Only applies if `continuousPointProximity` is not `false`.
2904
+ * collinear. Only applies if `continuousPointProximity` is not `false`.
2900
2905
  * @property {number} [continuousCloseProximity=10] The minimum distance in
2901
2906
  * display coordinates (pixels) to close a polygon or end drawing a line when
2902
2907
  * dragging to create an annotation. `false` never closes at the end of a
@@ -3048,8 +3053,8 @@ var annotationLayer = function annotationLayer(arg) {
3048
3053
  // continuous drawing modes.
3049
3054
  continuousPointProximity: 5,
3050
3055
  // in radians, minimum angle between continuous points to interpret them as
3051
- // being coliner
3052
- continuousPointColinearity: 1.0 * Math.PI / 180,
3056
+ // being collinear
3057
+ continuousPointCollinearity: 1.0 * Math.PI / 180,
3053
3058
  continuousCloseProximity: 10,
3054
3059
  // in pixels, 0 is exact
3055
3060
  finalPointProximity: 10,
@@ -3348,7 +3353,7 @@ var annotationLayer = function annotationLayer(arg) {
3348
3353
  * @param {geo.annotation} annotation The annotation to add.
3349
3354
  * @param {string|geo.transform|null} [gcs] `undefined` to use the interface
3350
3355
  * gcs, `null` to use the map gcs, or any other transform.
3351
- * @param {boolean} update If `false`, don't update the layer after adding
3356
+ * @param {boolean} [update] If `false`, don't update the layer after adding
3352
3357
  * the annotation.
3353
3358
  * @returns {this} The current layer.
3354
3359
  * @fires geo.event.annotation.add_before
@@ -3388,7 +3393,7 @@ var annotationLayer = function annotationLayer(arg) {
3388
3393
  * Remove an annotation from the layer.
3389
3394
  *
3390
3395
  * @param {geo.annotation} annotation The annotation to remove.
3391
- * @param {boolean} update If `false`, don't update the layer after removing
3396
+ * @param {boolean} [update] If `false`, don't update the layer after removing
3392
3397
  * the annotation.
3393
3398
  * @returns {boolean} `true` if an annotation was removed.
3394
3399
  * @fires geo.event.annotation.remove
@@ -3602,7 +3607,7 @@ var annotationLayer = function annotationLayer(arg) {
3602
3607
  * Return the current set of annotations as a geojson object. Alternately,
3603
3608
  * add a set of annotations from a geojson object.
3604
3609
  *
3605
- * @param {string|objectFile} [geojson] If present, add annotations based on
3610
+ * @param {string|object|File} [geojson] If present, add annotations based on
3606
3611
  * the given geojson object. If `undefined`, return the current
3607
3612
  * annotations as geojson. This may be a JSON string, a javascript
3608
3613
  * object, or a File object.
@@ -4830,7 +4835,7 @@ var camera = function camera(spec) {
4830
4835
  * Project a vector from world space into viewport (display) space. The
4831
4836
  * resulting vector always has the last component (`w`) equal to 1.
4832
4837
  *
4833
- * @param {vec2|vec3|vec4} point The point in world coordinates.
4838
+ * @param {vec3|vec4} point The point in world coordinates.
4834
4839
  * @returns {vec4} The point in display coordinates.
4835
4840
  */
4836
4841
 
@@ -4849,7 +4854,7 @@ var camera = function camera(spec) {
4849
4854
  * Project a vector from viewport (display) space into world space. The
4850
4855
  * resulting vector always has the last component (`w`) equal to 1.
4851
4856
  *
4852
- * @param {vec2|vec3|vec4} point The point in display coordinates.
4857
+ * @param {vec3|vec4} point The point in display coordinates.
4853
4858
  * @returns {vec4} The point in world space coordinates.
4854
4859
  */
4855
4860
 
@@ -5162,7 +5167,7 @@ var camera = function camera(spec) {
5162
5167
  /**
5163
5168
  * Represent a glmatrix as a pretty-printed string.
5164
5169
  * @param {mat4} mat A 4 x 4 matrix.
5165
- * @param {number} prec The number of decimal places.
5170
+ * @param {number} [prec] The number of decimal places.
5166
5171
  * @returns {string}
5167
5172
  */
5168
5173
 
@@ -5230,7 +5235,7 @@ var camera = function camera(spec) {
5230
5235
  };
5231
5236
  /**
5232
5237
  * Supported projection types.
5233
- * @enum
5238
+ * @enum {boolean}
5234
5239
  */
5235
5240
 
5236
5241
 
@@ -5241,7 +5246,7 @@ camera.projection = {
5241
5246
  /**
5242
5247
  * Default camera clipping bounds. Some features and renderers may rely on the
5243
5248
  * far clip value being more positive than the near clip value.
5244
- * @enum
5249
+ * @enum {number}
5245
5250
  */
5246
5251
 
5247
5252
  camera.clipbounds = {
@@ -6355,6 +6360,29 @@ var inherit = __webpack_require__(5699);
6355
6360
  var registerFeature = (__webpack_require__(4647).registerFeature);
6356
6361
 
6357
6362
  var pixelmapFeature = __webpack_require__(6374);
6363
+
6364
+ var geo_event = __webpack_require__(5108);
6365
+
6366
+ var util = __webpack_require__(4634);
6367
+ /**
6368
+ * Pixelmap feature information record.
6369
+ *
6370
+ * @typedef {object} geo.pixelmapFeature.info
6371
+ * @property {number} width The width of the source image.
6372
+ * @property {number} height The width of the source image.
6373
+ * @property {CanvasRenderingContext2D} context The HTMLCanvasElement context
6374
+ * used for handling the pixelmap.
6375
+ * @property {ImageData} imageData The context's image data.
6376
+ * @property {number[]} indices An array, one per pixel, of the index value in
6377
+ * the image. This decodes the pixel value to the corresponding integer.
6378
+ * @property number} area The number of pixels in the image. This is
6379
+ * `width * height`.
6380
+ * @property {object[]} mappedColors This has one entry for each distinct index
6381
+ * value. Each entry has `first` and `last` with the first and last pixel
6382
+ * locations where that index occurs. Note that last is the inclusive value
6383
+ * of the location (so its maximum possible value is `size - 1`).
6384
+ */
6385
+
6358
6386
  /**
6359
6387
  * Create a new instance of class pixelmapFeature.
6360
6388
  *
@@ -6378,6 +6406,219 @@ var canvas_pixelmapFeature = function canvas_pixelmapFeature(arg) {
6378
6406
  var object = __webpack_require__(3160);
6379
6407
 
6380
6408
  object.call(this);
6409
+ var m_quadFeature,
6410
+ s_exit = this._exit,
6411
+ m_this = this;
6412
+ /**
6413
+ * If the specified coordinates are in the rendered quad, use the basis
6414
+ * information from the quad to determine the pixelmap index value so that it
6415
+ * can be included in the `found` results.
6416
+ *
6417
+ * @param {geo.geoPosition} geo Coordinate.
6418
+ * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use
6419
+ * the interface gcs, `null` to use the map gcs, or any other transform.
6420
+ * @returns {geo.feature.searchResult} An object with a list of features and
6421
+ * feature indices that are located at the specified point.
6422
+ */
6423
+
6424
+ this.pointSearch = function (geo, gcs) {
6425
+ if (m_quadFeature && m_this.m_info) {
6426
+ var result = m_quadFeature.pointSearch(geo, gcs);
6427
+
6428
+ if (result.index.length === 1 && result.extra && result.extra[result.index[0]].basis) {
6429
+ var basis = result.extra[result.index[0]].basis,
6430
+ x,
6431
+ y,
6432
+ idx;
6433
+ x = Math.floor(basis.x * m_this.m_info.width);
6434
+ y = Math.floor(basis.y * m_this.m_info.height);
6435
+
6436
+ if (x >= 0 && x < m_this.m_info.width && y >= 0 && y < m_this.m_info.height) {
6437
+ idx = m_this.m_info.indices[y * m_this.m_info.width + x];
6438
+ result = {
6439
+ index: [idx],
6440
+ found: [m_this.data()[idx]]
6441
+ };
6442
+ return result;
6443
+ }
6444
+ }
6445
+ }
6446
+
6447
+ return {
6448
+ index: [],
6449
+ found: []
6450
+ };
6451
+ };
6452
+ /**
6453
+ * Compute information for this pixelmap image. It is wasteful to call this
6454
+ * if the pixelmap has already been prepared (it is invalidated by a change
6455
+ * in the image).
6456
+ *
6457
+ * @returns {geo.pixelmapFeature.info}
6458
+ */
6459
+
6460
+
6461
+ this._preparePixelmap = function () {
6462
+ var i, idx, pixelData;
6463
+
6464
+ if (!util.isReadyImage(m_this.m_srcImage)) {
6465
+ return;
6466
+ }
6467
+
6468
+ m_this.m_info = {
6469
+ width: m_this.m_srcImage.naturalWidth,
6470
+ height: m_this.m_srcImage.naturalHeight,
6471
+ canvas: document.createElement('canvas')
6472
+ };
6473
+ m_this.m_info.canvas.width = m_this.m_info.width;
6474
+ m_this.m_info.canvas.height = m_this.m_info.height;
6475
+ m_this.m_info.context = m_this.m_info.canvas.getContext('2d');
6476
+ m_this.m_info.context.drawImage(m_this.m_srcImage, 0, 0);
6477
+ m_this.m_info.imageData = m_this.m_info.context.getImageData(0, 0, m_this.m_info.canvas.width, m_this.m_info.canvas.height);
6478
+ pixelData = m_this.m_info.imageData.data;
6479
+ m_this.m_info.indices = new Array(pixelData.length / 4);
6480
+ m_this.m_info.area = pixelData.length / 4;
6481
+ m_this.m_info.mappedColors = {};
6482
+
6483
+ for (i = 0; i < pixelData.length; i += 4) {
6484
+ idx = pixelData[i] + (pixelData[i + 1] << 8) + (pixelData[i + 2] << 16);
6485
+ m_this.m_info.indices[i / 4] = idx;
6486
+
6487
+ if (!m_this.m_info.mappedColors[idx]) {
6488
+ m_this.m_info.mappedColors[idx] = {
6489
+ first: i / 4
6490
+ };
6491
+ }
6492
+
6493
+ m_this.m_info.mappedColors[idx].last = i / 4;
6494
+ }
6495
+
6496
+ return m_this.m_info;
6497
+ };
6498
+ /**
6499
+ * Given the loaded pixelmap image, create a canvas the size of the image.
6500
+ * Compute a color for each distinct index and recolor the canvas based on
6501
+ * these colors, then draw the resultant image as a quad.
6502
+ *
6503
+ * @fires geo.event.pixelmap.prepared
6504
+ */
6505
+
6506
+
6507
+ this._computePixelmap = function () {
6508
+ var data = m_this.data() || [],
6509
+ colorFunc = m_this.style.get('color'),
6510
+ i,
6511
+ idx,
6512
+ lastidx,
6513
+ color,
6514
+ pixelData,
6515
+ indices,
6516
+ mappedColors,
6517
+ updateFirst,
6518
+ updateLast = -1,
6519
+ update,
6520
+ prepared;
6521
+
6522
+ if (!m_this.m_info) {
6523
+ m_this.indexModified(undefined, 'clear');
6524
+
6525
+ if (!m_this._preparePixelmap()) {
6526
+ return;
6527
+ }
6528
+
6529
+ prepared = true;
6530
+ }
6531
+
6532
+ m_this.indexModified(undefined, 'clear');
6533
+ mappedColors = m_this.m_info.mappedColors;
6534
+ updateFirst = m_this.m_info.area;
6535
+
6536
+ for (idx in mappedColors) {
6537
+ if (mappedColors.hasOwnProperty(idx)) {
6538
+ color = colorFunc(data[idx], +idx) || {};
6539
+ color = [(color.r || 0) * 255, (color.g || 0) * 255, (color.b || 0) * 255, color.a === undefined ? 255 : color.a * 255];
6540
+ mappedColors[idx].update = !mappedColors[idx].color || mappedColors[idx].color[0] !== color[0] || mappedColors[idx].color[1] !== color[1] || mappedColors[idx].color[2] !== color[2] || mappedColors[idx].color[3] !== color[3];
6541
+
6542
+ if (mappedColors[idx].update) {
6543
+ mappedColors[idx].color = color;
6544
+ updateFirst = Math.min(mappedColors[idx].first, updateFirst);
6545
+ updateLast = Math.max(mappedColors[idx].last, updateLast);
6546
+ }
6547
+ }
6548
+ }
6549
+ /* If nothing was updated, we are done */
6550
+
6551
+
6552
+ if (updateFirst >= updateLast) {
6553
+ return;
6554
+ }
6555
+ /* Update only the extent that has changed */
6556
+
6557
+
6558
+ pixelData = m_this.m_info.imageData.data;
6559
+ indices = m_this.m_info.indices;
6560
+
6561
+ for (i = updateFirst; i <= updateLast; i += 1) {
6562
+ idx = indices[i];
6563
+
6564
+ if (idx !== lastidx) {
6565
+ lastidx = idx;
6566
+ color = mappedColors[idx].color;
6567
+ update = mappedColors[idx].update;
6568
+ }
6569
+
6570
+ if (update) {
6571
+ pixelData[i * 4] = color[0];
6572
+ pixelData[i * 4 + 1] = color[1];
6573
+ pixelData[i * 4 + 2] = color[2];
6574
+ pixelData[i * 4 + 3] = color[3];
6575
+ }
6576
+ }
6577
+ /* Place the updated area into the canvas */
6578
+
6579
+
6580
+ m_this.m_info.context.putImageData(m_this.m_info.imageData, 0, 0, 0, Math.floor(updateFirst / m_this.m_info.width), m_this.m_info.width, Math.ceil((updateLast + 1) / m_this.m_info.width));
6581
+ /* If we haven't made a quad feature, make one now. The quad feature needs
6582
+ * to have the canvas capability. */
6583
+
6584
+ if (!m_quadFeature) {
6585
+ m_quadFeature = m_this.layer().createFeature('quad', {
6586
+ selectionAPI: false,
6587
+ gcs: m_this.gcs(),
6588
+ visible: m_this.visible(undefined, true)
6589
+ });
6590
+ m_this.dependentFeatures([m_quadFeature]);
6591
+ m_quadFeature.style({
6592
+ image: m_this.m_info.canvas,
6593
+ position: m_this.style.get('position')
6594
+ }).data([{}]).draw();
6595
+ }
6596
+ /* If we prepared the pixelmap and rendered it, send a prepared event */
6597
+
6598
+
6599
+ if (prepared) {
6600
+ m_this.geoTrigger(geo_event.pixelmap.prepared, {
6601
+ pixelmap: m_this
6602
+ });
6603
+ }
6604
+ };
6605
+ /**
6606
+ * Destroy. Deletes the associated quadFeature.
6607
+ *
6608
+ * @returns {this}
6609
+ */
6610
+
6611
+
6612
+ this._exit = function () {
6613
+ if (m_quadFeature && m_this.layer()) {
6614
+ m_this.layer().deleteFeature(m_quadFeature);
6615
+ m_quadFeature = null;
6616
+ m_this.dependentFeatures([]);
6617
+ }
6618
+
6619
+ s_exit();
6620
+ return m_this;
6621
+ };
6381
6622
 
6382
6623
  this._init(arg);
6383
6624
 
@@ -7400,7 +7641,7 @@ var choroplethFeature = function choroplethFeature(arg) {
7400
7641
  /**
7401
7642
  * Add a geojson polygon feature to the current layer.
7402
7643
  *
7403
- * @param {geojsonFeature} feature A geojson parsed feature.
7644
+ * @param {geo.geojsonFeature} feature A geojson parsed feature.
7404
7645
  * @param {geo.geoColor} fillColor The fill color for the feature.
7405
7646
  * @returns {geo.polygonFeature}
7406
7647
  */
@@ -7814,11 +8055,12 @@ var domRenderer = function domRenderer(arg) {
7814
8055
  /**
7815
8056
  * Initialize.
7816
8057
  *
8058
+ * @param {object} [arg] Optional arguments.
7817
8059
  * @returns {this}
7818
8060
  */
7819
8061
 
7820
8062
 
7821
- this._init = function () {
8063
+ this._init = function (arg) {
7822
8064
  var layer = m_this.layer().node();
7823
8065
 
7824
8066
  if (!m_this.canvas() && layer && layer.length) {
@@ -9767,7 +10009,7 @@ var featureLayer = function featureLayer(arg) {
9767
10009
  /**
9768
10010
  * Get/Set drawables.
9769
10011
  *
9770
- * @param {geo.feature[]} val A list of features, or unspecified to return
10012
+ * @param {geo.feature[]} [val] A list of features, or unspecified to return
9771
10013
  * the current feature list. If a list is provided, features are added or
9772
10014
  * removed as needed.
9773
10015
  * @returns {geo.feature[]|this} The current features associated with the
@@ -10351,7 +10593,7 @@ var object = __webpack_require__(3737);
10351
10593
  * Object specification for a fileReader.
10352
10594
  *
10353
10595
  * @typedef {object} geo.fileReader.spec
10354
- * @property {geo.featureLayer} layer The target feature layer.
10596
+ * @property {geo.featureLayer} [layer] The target feature layer.
10355
10597
  */
10356
10598
 
10357
10599
  /**
@@ -10360,7 +10602,7 @@ var object = __webpack_require__(3737);
10360
10602
  * @class
10361
10603
  * @alias geo.fileReader
10362
10604
  * @extends geo.object
10363
- * @param {geo.fileReader.spec} arg
10605
+ * @param {geo.fileReader.spec} [arg]
10364
10606
  * @returns {geo.fileReader}
10365
10607
  */
10366
10608
 
@@ -11838,7 +12080,8 @@ var tile = __webpack_require__(8418);
11838
12080
  * @property {object} [size] The size of each tile.
11839
12081
  * @property {number} [size.x=256] Width in pixels.
11840
12082
  * @property {number} [size.y=256] Height in pixels.
11841
- * @property {string} [crossDomain='anonymous'] Image CORS attribute.
12083
+ * @property {string} [crossDomain='anonymous'] Image CORS attribute. This is
12084
+ * used for the `crossorigin` property when loading images.
11842
12085
  */
11843
12086
 
11844
12087
  /**
@@ -12031,6 +12274,7 @@ module.exports = $.extend({
12031
12274
  polygonFeature: __webpack_require__(4343),
12032
12275
  quadFeature: __webpack_require__(5017),
12033
12276
  pixelmapFeature: __webpack_require__(6374),
12277
+ pixelmapLayer: __webpack_require__(809),
12034
12278
  renderer: __webpack_require__(3234),
12035
12279
  sceneObject: __webpack_require__(5358),
12036
12280
  textFeature: __webpack_require__(9757),
@@ -13002,7 +13246,7 @@ var isolineFeature = function isolineFeature(arg) {
13002
13246
  * the generated labels. The viewport calculation is conservative, as the
13003
13247
  * map could be rotated, changed size, or have other modifications.
13004
13248
  *
13005
- * @returns {exit}
13249
+ * @returns {this}
13006
13250
  */
13007
13251
 
13008
13252
 
@@ -13610,7 +13854,7 @@ var layer = function layer(arg) {
13610
13854
  /**
13611
13855
  * Get root node of the layer.
13612
13856
  *
13613
- * @returns {div}
13857
+ * @returns {HTMLDivElement}
13614
13858
  */
13615
13859
 
13616
13860
 
@@ -13938,11 +14182,13 @@ var layer = function layer(arg) {
13938
14182
  * Update layer.
13939
14183
  *
13940
14184
  * This is a stub that should be subclassed.
14185
+ *
14186
+ * @param {object} [arg] An object, possibly with an ``event`` key and value.
13941
14187
  * @returns {this}
13942
14188
  */
13943
14189
 
13944
14190
 
13945
- this._update = function () {
14191
+ this._update = function (arg) {
13946
14192
  return m_this;
13947
14193
  };
13948
14194
  /**
@@ -14617,9 +14863,9 @@ var lineFeature = function lineFeature(arg) {
14617
14863
  *
14618
14864
  * @param {array} data A new data array.
14619
14865
  * @param {number} [tolerance] The maximum variation allowed in map.gcs
14620
- * units. A value of zero will only remove perfectly colinear points. If
14621
- * not specified, this is set to a half display pixel at the map's current
14622
- * zoom level.
14866
+ * units. A value of zero will only remove perfectly collinear points.
14867
+ * If not specified, this is set to a half display pixel at the map's
14868
+ * current zoom level.
14623
14869
  * @param {function} [posFunc=this.style.get('position')] The function to
14624
14870
  * get the position of each vertex.
14625
14871
  * @param {function} [lineFunc=this.style.get('line')] The function to get
@@ -15357,7 +15603,7 @@ var map = function map(arg) {
15357
15603
  * view center. Rotation mostly ignores `clampBoundsX`, as the behavior
15358
15604
  * feels peculiar otherwise.
15359
15605
  *
15360
- * @param {number} rotation Absolute angle in radians (positive is
15606
+ * @param {number} [rotation] Absolute angle in radians (positive is
15361
15607
  * clockwise).
15362
15608
  * @param {object} [origin] If specified, rotate about this origin.
15363
15609
  * @param {geo.geoPosition} origin.geo The gcs coordinates of the
@@ -15715,7 +15961,7 @@ var map = function map(arg) {
15715
15961
  * coordinate to convert.
15716
15962
  * @param {string|geo.transform|null} [gcs] Output gcs. `undefined` to use
15717
15963
  * the interface gcs, `null` to use the map gcs, or any other transform.
15718
- * @returns {geo.geoPosition|geoPosition[]} GCS space coordinates.
15964
+ * @returns {geo.geoPosition|geo.geoPosition[]} GCS space coordinates.
15719
15965
  */
15720
15966
 
15721
15967
 
@@ -15857,11 +16103,12 @@ var map = function map(arg) {
15857
16103
  /**
15858
16104
  * Initialize the map.
15859
16105
  *
16106
+ * @param {object} [arg] Optional arguments.
15860
16107
  * @returns {this} The map object.
15861
16108
  */
15862
16109
 
15863
16110
 
15864
- this._init = function () {
16111
+ this._init = function (arg) {
15865
16112
  if (m_node === undefined || m_node === null) {
15866
16113
  throw new Error('Map require DIV node');
15867
16114
  }
@@ -16228,7 +16475,7 @@ var map = function map(arg) {
16228
16475
  m_center = m_this.gcsToWorld({
16229
16476
  x: p[0],
16230
16477
  y: p[1]
16231
- }, null, true, true);
16478
+ }, null);
16232
16479
  m_this.zoom(p[2], m_transition.zoomOrigin, true);
16233
16480
  }
16234
16481
 
@@ -16468,7 +16715,7 @@ var map = function map(arg) {
16468
16715
  * @param {number} rotation The requested rotation in clockwise radians.
16469
16716
  * @param {string|geo.transform|null} [gcs] `undefined` to use the interface
16470
16717
  * gcs, `null` to use the map gcs, or any other transform.
16471
- * @param {boolean} ignoreDiscreteZoom If `true`, ignore the `discreteZoom`
16718
+ * @param {boolean} [ignoreDiscreteZoom] If `true`, ignore the `discreteZoom`
16472
16719
  * option when determining the new view.
16473
16720
  * @param {boolean} [ignoreClampBounds] If `true` and `clampBoundsX` or
16474
16721
  * `clampBoundsY` is set, allow the bounds to be less clamped.
@@ -16720,11 +16967,11 @@ var map = function map(arg) {
16720
16967
  * @param {boolean|null} [opts.attribution=null] If `null` or unspecified,
16721
16968
  * include the attribution only if all layers are used. If false, never
16722
16969
  * include the attribution. If `true`, always include it.
16723
- * @param {HTMLObject[]|string[]} [opts.html] A list of additional HTML
16970
+ * @param {HTMLElement[]|string[]} [opts.html] A list of additional HTML
16724
16971
  * elements, selectors, or jQuery elements to render on top of the map.
16725
16972
  * These are rendered in order, with the last one topmost.
16726
- * @returns {deferred} A jQuery Deferred object. The done function receives
16727
- * either a data URL or an `HTMLCanvasElement` with the result.
16973
+ * @returns {jQueryDeferred} A jQuery Deferred object. The done function
16974
+ * receives either a data URL or an `HTMLCanvasElement` with the result.
16728
16975
  * @fires geo.event.screenshot.ready
16729
16976
  */
16730
16977
 
@@ -16933,7 +17180,7 @@ var map = function map(arg) {
16933
17180
  /**
16934
17181
  * Return the nearest valid zoom level to the requested zoom.
16935
17182
  * @param {number} zoom A zoom level to adjust to current settings
16936
- * @param {boolean} ignoreDiscreteZoom If `true`, ignore the `discreteZoom`
17183
+ * @param {boolean} [ignoreDiscreteZoom] If `true`, ignore the `discreteZoom`
16937
17184
  * option when determining the new view.
16938
17185
  * @returns {number} The zoom level clamped to the allowed zoom range and
16939
17186
  * with other settings applied.
@@ -16977,10 +17224,11 @@ var map = function map(arg) {
16977
17224
  * Draw a layer image to a canvas context. The layer's opacity and transform
16978
17225
  * are applied. This is used as part of making a screenshot.
16979
17226
  *
16980
- * @param {context} context The 2d canvas context to draw into.
17227
+ * @param {CanvasRenderingContext2D} context The 2d canvas context to draw
17228
+ * into.
16981
17229
  * @param {number} opacity The opacity in the range [0, 1].
16982
17230
  * @param {object} elem A jQuery element that might have a transform.
16983
- * @param {HTMLImageObject} img The image or canvas to draw to the canvas.
17231
+ * @param {HTMLImageElement} img The image or canvas to draw to the canvas.
16984
17232
  * @param {string} [mixBlendMode] the mix-blend-mode used to add this layer.
16985
17233
  * @private
16986
17234
  */
@@ -17188,12 +17436,12 @@ var map = function map(arg) {
17188
17436
  * Return a valid rotation angle.
17189
17437
  *
17190
17438
  * @param {number} rotation Proposed rotation.
17191
- * @param {boolean} ignoreRotationFunc If truthy and rotations are allowed,
17439
+ * @param {boolean} [ignoreRotationFunc] If truthy and rotations are allowed,
17192
17440
  * allow any rotation. Otherwise, the rotation is passed through the
17193
17441
  * `allowRotation` function.
17194
- * @param {boolean} noRangeLimit If falsy, ensure that the rotation is in the
17195
- * range [0, 2*PI). If it is very close to zero, it is snapped to zero.
17196
- * If true, the rotation can have any value.
17442
+ * @param {boolean} [noRangeLimit] If falsy, ensure that the rotation is in
17443
+ * the range [0, 2*PI). If it is very close to zero, it is snapped to
17444
+ * zero. If true, the rotation can have any value.
17197
17445
  * @returns {number} the validated rotation
17198
17446
  * @private
17199
17447
  */
@@ -19851,26 +20099,26 @@ var mapInteractor = function mapInteractor(args) {
19851
20099
  * map in pixels relative to the map's div.
19852
20100
  * @param {geo.screenPosition} [options.center] The position of a touch
19853
20101
  * event center relative to the window.
19854
- * @param {string} [button] One of `left`, `middle`, or `right` for mouse
19855
- * events.
19856
- * @param {string} [modifiers] A space-separated list of metakeys that are
19857
- * down on mouse events.
19858
- * @param {geo.screenPosition} [wheelDelta] The amount the wheel moved in
19859
- * both directions for wheel events. One step is often 20 units of
19860
- * vement.
19861
- * @param {number} [wheelMode] The wheel delta mode. See
20102
+ * @param {string} [options.button] One of `left`, `middle`, or `right` for
20103
+ * mouse events.
20104
+ * @param {string} [options.modifiers] A space-separated list of metakeys
20105
+ * that are down on mouse events.
20106
+ * @param {geo.screenPosition} [options.wheelDelta] The amount the wheel
20107
+ * moved in both directions for wheel events. One step is often 20 units
20108
+ * of movement.
20109
+ * @param {number} [options.wheelMode] The wheel delta mode. See
19862
20110
  * https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent .
19863
- * @param {boolean} [touch] `truthy` if this is a touch event.
19864
- * @param {number} [rotation] Touch event rotation in degrees.
19865
- * @param {number} [scale] Touch event scale. Initial events should have a
19866
- * scale of 1; subsequent events should increase or decrease this to
19867
- * simulate spread and pinch actions.
19868
- * @param {number[]} [pointers] A list of pointer numbers involved in a
19869
- * touch event. Pointers are number from one up, so `[1]` is the first
20111
+ * @param {boolean} [options.touch] `truthy` if this is a touch event.
20112
+ * @param {number} [options.rotation] Touch event rotation in degrees.
20113
+ * @param {number} [options.scale] Touch event scale. Initial events should
20114
+ * have a scale of 1; subsequent events should increase or decrease this
20115
+ * to simulate spread and pinch actions.
20116
+ * @param {number[]} [options.pointers] A list of pointer numbers involved in
20117
+ * a touch event. Pointers are number from one up, so `[1]` is the first
19870
20118
  * touch point, `[1, 2]` are two touch points, and `[2]` is when the first
19871
20119
  * point was released but the second is still touching.
19872
- * @param {string} [pointerType] `mouse` if this is a mouse action rather
19873
- * than a touch action.
20120
+ * @param {string} [options.pointerType] `mouse` if this is a mouse action
20121
+ * rather than a touch action.
19874
20122
  * @returns {mapInteractor}
19875
20123
  */
19876
20124
 
@@ -20505,7 +20753,7 @@ markerFeature.capabilities = {
20505
20753
  markerFeature.primitiveShapes = pointFeature.primitiveShapes;
20506
20754
  /**
20507
20755
  * Marker symbols
20508
- * @enum
20756
+ * @enum {number}
20509
20757
  */
20510
20758
 
20511
20759
  markerFeature.symbols = {
@@ -20562,7 +20810,7 @@ markerFeature.symbols = {
20562
20810
  });
20563
20811
  /**
20564
20812
  * Marker scale modes
20565
- * @enum
20813
+ * @enum {number}
20566
20814
  */
20567
20815
 
20568
20816
  markerFeature.scaleMode = {
@@ -20602,7 +20850,7 @@ var feature = __webpack_require__(6837);
20602
20850
  * of these properties can be functions, which get passed `data`.
20603
20851
  *
20604
20852
  * @typedef {object} geo.meshFeature.meshSpec
20605
- * @property {number[]|array.<number[]>} [elements] If specified, a list of
20853
+ * @property {number[]|Array.<number[]>} [elements] If specified, a list of
20606
20854
  * indices into the data array that form elements. If this is an array of
20607
20855
  * arrays, each subarray must have at least either 3 values for triangular
20608
20856
  * elements or 4 values for square elements. If this is a single array,
@@ -21600,6 +21848,8 @@ var quadFeature = __webpack_require__(5017);
21600
21848
  * specified, use this as the layer opacity.
21601
21849
  * @property {string} [source] If specified, use the predefined tile source
21602
21850
  * (see {@link geo.osmLayer.tileSources}).
21851
+ * @property {string} [crossDomain='anonymous'] Image CORS attribute. This is
21852
+ * used for the `crossorigin` property when loading images.
21603
21853
  */
21604
21854
 
21605
21855
  /**
@@ -21973,8 +22223,6 @@ var inherit = __webpack_require__(5699);
21973
22223
 
21974
22224
  var feature = __webpack_require__(6837);
21975
22225
 
21976
- var geo_event = __webpack_require__(5108);
21977
-
21978
22226
  var util = __webpack_require__(4634);
21979
22227
  /**
21980
22228
  * Pixelmap feature specification.
@@ -22003,25 +22251,6 @@ var util = __webpack_require__(4634);
22003
22251
  * transformations for those two triangles.
22004
22252
  */
22005
22253
 
22006
- /**
22007
- * Pixelmap feature information record.
22008
- *
22009
- * @typedef {object} geo.pixelmapFeature.info
22010
- * @property {number} width The width of the source image.
22011
- * @property {number} height The width of the source image.
22012
- * @property {context} context The HTMLCanvasElement context used for handling
22013
- * the pixelmap.
22014
- * @property {ImageData} imageData The context's image data.
22015
- * @property {number[]} indices An array, one per pixel, of the index value in
22016
- * the image. This decodes the pixel value to the corresponding integer.
22017
- * @property number} area The number of pixels in the image. This is
22018
- * `width * height`.
22019
- * @property {object[]} mappedColors This has one entry for each distinct index
22020
- * value. Each entry has `first` and `last` with the first and last pixel
22021
- * locations where that index occurs. Note that last is the inclusive value
22022
- * of the location (so its maximum possible value is `size - 1`).
22023
- */
22024
-
22025
22254
  /**
22026
22255
  * Create a new instance of class pixelmapFeature
22027
22256
  *
@@ -22047,12 +22276,9 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22047
22276
  */
22048
22277
 
22049
22278
  var m_this = this,
22050
- m_quadFeature,
22051
- m_srcImage,
22052
- m_info,
22053
22279
  s_update = this._update,
22054
- s_init = this._init,
22055
- s_exit = this._exit;
22280
+ m_modifiedIndexRange,
22281
+ s_init = this._init;
22056
22282
  this.featureType = 'pixelmap';
22057
22283
  /**
22058
22284
  * Get/Set position accessor.
@@ -22089,7 +22315,7 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22089
22315
  if (val === undefined) {
22090
22316
  return m_this.style('url');
22091
22317
  } else if (val !== m_this.style('url')) {
22092
- m_srcImage = m_info = undefined;
22318
+ m_this.m_srcImage = m_this.m_info = undefined;
22093
22319
  m_this.style('url', val);
22094
22320
  m_this.dataTime().modified();
22095
22321
  m_this.modified();
@@ -22097,31 +22323,6 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22097
22323
 
22098
22324
  return m_this;
22099
22325
  };
22100
- /**
22101
- * Get the maximum index value from the pixelmap. This is a value present in
22102
- * the pixelmap.
22103
- *
22104
- * @returns {number} The maximum index value.
22105
- */
22106
-
22107
-
22108
- this.maxIndex = function () {
22109
- if (m_info) {
22110
- /* This isn't just m_info.mappedColors.length - 1, since there
22111
- * may be more data than actual indices. */
22112
- if (m_info.maxIndex === undefined) {
22113
- m_info.maxIndex = 0;
22114
-
22115
- for (var idx in m_info.mappedColors) {
22116
- if (m_info.mappedColors.hasOwnProperty(idx)) {
22117
- m_info.maxIndex = Math.max(m_info.maxIndex, idx);
22118
- }
22119
- }
22120
- }
22121
-
22122
- return m_info.maxIndex;
22123
- }
22124
- };
22125
22326
  /**
22126
22327
  * Get/Set color accessor.
22127
22328
  *
@@ -22143,46 +22344,101 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22143
22344
  return m_this;
22144
22345
  };
22145
22346
  /**
22146
- * If the specified coordinates are in the rendered quad, use the basis
22147
- * information from the quad to determine the pixelmap index value so that it
22148
- * can be included in the `found` results.
22347
+ * Mark that an index's data value (and hence its color) has changed without
22348
+ * marking all of the data array as changed. If this function is called
22349
+ * without any parameters, it clears the tracked changes.
22149
22350
  *
22150
- * @param {geo.geoPosition} geo Coordinate.
22151
- * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use
22152
- * the interface gcs, `null` to use the map gcs, or any other transform.
22153
- * @returns {geo.feature.searchResult} An object with a list of features and
22154
- * feature indices that are located at the specified point.
22351
+ * @param {number} [idx] The lowest data index that has changed. If
22352
+ * `undefined`, return the current tracked changed range.
22353
+ * @param {number|'clear'} [idx2] If an index was specified in `idx` and
22354
+ * this is specified, the highest index (inclusive) that has changed. If
22355
+ * returning the tracked changed range and this is `clear`, clear the
22356
+ * tracked range.
22357
+ * @returns {this|number[]} When returning a range, this is the lowest and
22358
+ * highest index values that have changed (inclusive), so their range is
22359
+ * `[0, data.length)`.
22155
22360
  */
22156
22361
 
22157
22362
 
22158
- this.pointSearch = function (geo, gcs) {
22159
- if (m_quadFeature && m_info) {
22160
- var result = m_quadFeature.pointSearch(geo, gcs);
22363
+ this.indexModified = function (idx, idx2) {
22364
+ if (idx === undefined) {
22365
+ var range = m_modifiedIndexRange;
22161
22366
 
22162
- if (result.index.length === 1 && result.extra && result.extra[result.index[0]].basis) {
22163
- var basis = result.extra[result.index[0]].basis,
22164
- x,
22165
- y,
22166
- idx;
22167
- x = Math.floor(basis.x * m_info.width);
22168
- y = Math.floor(basis.y * m_info.height);
22367
+ if (idx2 === 'clear') {
22368
+ m_modifiedIndexRange = undefined;
22369
+ }
22169
22370
 
22170
- if (x >= 0 && x < m_info.width && y >= 0 && y < m_info.height) {
22171
- idx = m_info.indices[y * m_info.width + x];
22172
- result = {
22173
- index: [idx],
22174
- found: [m_this.data()[idx]]
22175
- };
22176
- return result;
22371
+ return range;
22372
+ }
22373
+
22374
+ m_this.modified();
22375
+
22376
+ if (m_modifiedIndexRange === undefined) {
22377
+ m_modifiedIndexRange = [idx, idx];
22378
+ }
22379
+
22380
+ if (idx < m_modifiedIndexRange[0]) {
22381
+ m_modifiedIndexRange[0] = idx;
22382
+ }
22383
+
22384
+ if ((idx2 || idx) > m_modifiedIndexRange[1]) {
22385
+ m_modifiedIndexRange[1] = idx2 || idx;
22386
+ }
22387
+
22388
+ return m_this;
22389
+ };
22390
+ /**
22391
+ * Update.
22392
+ *
22393
+ * @returns {this}
22394
+ */
22395
+
22396
+
22397
+ this._update = function () {
22398
+ s_update.call(m_this);
22399
+
22400
+ if (m_this.buildTime().timestamp() <= m_this.dataTime().timestamp() || m_this.updateTime().timestamp() < m_this.timestamp()) {
22401
+ m_this._build();
22402
+ }
22403
+
22404
+ m_this.updateTime().modified();
22405
+ return m_this;
22406
+ };
22407
+ /**
22408
+ * Get the maximum index value from the pixelmap. This is a value present in
22409
+ * the pixelmap.
22410
+ *
22411
+ * @returns {number} The maximum index value.
22412
+ */
22413
+
22414
+
22415
+ this.maxIndex = function () {
22416
+ if (m_this.m_info) {
22417
+ /* This isn't just m_info.mappedColors.length - 1, since there
22418
+ * may be more data than actual indices. */
22419
+ if (m_this.m_info.maxIndex === undefined) {
22420
+ m_this.m_info.maxIndex = 0;
22421
+
22422
+ for (var idx in m_this.m_info.mappedColors) {
22423
+ if (m_this.m_info.mappedColors.hasOwnProperty(idx)) {
22424
+ m_this.m_info.maxIndex = Math.max(m_this.m_info.maxIndex, idx);
22425
+ }
22177
22426
  }
22178
22427
  }
22179
- }
22180
22428
 
22181
- return {
22182
- index: [],
22183
- found: []
22184
- };
22429
+ return m_this.m_info.maxIndex;
22430
+ }
22185
22431
  };
22432
+ /**
22433
+ * Given the loaded pixelmap image, create a canvas the size of the image.
22434
+ * Compute a color for each distinct index and recolor the canvas based on
22435
+ * these colors, then draw the resultant image as a quad.
22436
+ *
22437
+ * @fires geo.event.pixelmap.prepared
22438
+ */
22439
+
22440
+
22441
+ this._computePixelmap = function () {};
22186
22442
  /**
22187
22443
  * Build. Fetches the image if necessary.
22188
22444
  *
@@ -22195,14 +22451,12 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22195
22451
  * drawing a quad, which can trigger a full layer update, which in turn
22196
22452
  * checks if this feature is built. Setting the build time avoids calling
22197
22453
  * this a second time. */
22198
- m_this.buildTime().modified();
22199
-
22200
- if (!m_srcImage) {
22454
+ if (!m_this.m_srcImage) {
22201
22455
  var src = m_this.style.get('url')();
22202
22456
 
22203
22457
  if (util.isReadyImage(src)) {
22204
22458
  /* we have an already loaded image, so we can just use it. */
22205
- m_srcImage = src;
22459
+ m_this.m_srcImage = src;
22206
22460
 
22207
22461
  m_this._computePixelmap();
22208
22462
  } else if (src) {
@@ -22213,19 +22467,19 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22213
22467
  if (src instanceof Image) {
22214
22468
  /* we have an unloaded image. Hook to the load and error callbacks
22215
22469
  * so that when it is loaded we can use it. */
22216
- m_srcImage = src;
22470
+ m_this.m_srcImage = src;
22217
22471
  prev_onload = src.onload;
22218
22472
  prev_onerror = src.onerror;
22219
22473
  } else {
22220
22474
  /* we were given a url, so construct a new image */
22221
- m_srcImage = new Image(); // Only set the crossOrigin parameter if this is going across origins.
22475
+ m_this.m_srcImage = new Image(); // Only set the crossOrigin parameter if this is going across origins.
22222
22476
 
22223
22477
  if (src.indexOf(':') >= 0 && src.indexOf('/') === src.indexOf(':') + 1) {
22224
- m_srcImage.crossOrigin = m_this.style.get('crossDomain')() || 'anonymous';
22478
+ m_this.m_srcImage.crossOrigin = m_this.style.get('crossDomain')() || 'anonymous';
22225
22479
  }
22226
22480
  }
22227
22481
 
22228
- m_srcImage.onload = function () {
22482
+ m_this.m_srcImage.onload = function () {
22229
22483
  if (prev_onload) {
22230
22484
  prev_onload.apply(m_this, arguments);
22231
22485
  }
@@ -22234,7 +22488,7 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22234
22488
 
22235
22489
 
22236
22490
  if (m_this.style.get('url')() === src) {
22237
- m_info = undefined;
22491
+ m_this.m_info = undefined;
22238
22492
 
22239
22493
  m_this._computePixelmap();
22240
22494
  }
@@ -22242,7 +22496,7 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22242
22496
  defer.resolve();
22243
22497
  };
22244
22498
 
22245
- m_srcImage.onerror = function () {
22499
+ m_this.m_srcImage.onerror = function () {
22246
22500
  if (prev_onerror) {
22247
22501
  prev_onerror.apply(m_this, arguments);
22248
22502
  }
@@ -22254,197 +22508,14 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22254
22508
  m_this.layer().addPromise(m_this);
22255
22509
 
22256
22510
  if (!(src instanceof Image)) {
22257
- m_srcImage.src = src;
22511
+ m_this.m_srcImage.src = src;
22258
22512
  }
22259
22513
  }
22260
- } else if (m_info) {
22514
+ } else if (m_this.m_info) {
22261
22515
  m_this._computePixelmap();
22262
22516
  }
22263
22517
 
22264
- return m_this;
22265
- };
22266
- /**
22267
- * Compute information for this pixelmap image. It is wasteful to call this
22268
- * if the pixelmap has already been prepared (it is invalidated by a change
22269
- * in the image).
22270
- *
22271
- * @returns {geo.pixelmapFeature.info}
22272
- */
22273
-
22274
-
22275
- this._preparePixelmap = function () {
22276
- var i, idx, pixelData;
22277
-
22278
- if (!util.isReadyImage(m_srcImage)) {
22279
- return;
22280
- }
22281
-
22282
- m_info = {
22283
- width: m_srcImage.naturalWidth,
22284
- height: m_srcImage.naturalHeight,
22285
- canvas: document.createElement('canvas')
22286
- };
22287
- m_info.canvas.width = m_info.width;
22288
- m_info.canvas.height = m_info.height;
22289
- m_info.context = m_info.canvas.getContext('2d');
22290
- m_info.context.drawImage(m_srcImage, 0, 0);
22291
- m_info.imageData = m_info.context.getImageData(0, 0, m_info.canvas.width, m_info.canvas.height);
22292
- pixelData = m_info.imageData.data;
22293
- m_info.indices = new Array(pixelData.length / 4);
22294
- m_info.area = pixelData.length / 4;
22295
- m_info.mappedColors = {};
22296
-
22297
- for (i = 0; i < pixelData.length; i += 4) {
22298
- idx = pixelData[i] + (pixelData[i + 1] << 8) + (pixelData[i + 2] << 16);
22299
- m_info.indices[i / 4] = idx;
22300
-
22301
- if (!m_info.mappedColors[idx]) {
22302
- m_info.mappedColors[idx] = {
22303
- first: i / 4
22304
- };
22305
- }
22306
-
22307
- m_info.mappedColors[idx].last = i / 4;
22308
- }
22309
-
22310
- return m_info;
22311
- };
22312
- /**
22313
- * Given the loaded pixelmap image, create a canvas the size of the image.
22314
- * Compute a color for each distinct index and recolor the canvas based on
22315
- * these colors, then draw the resultant image as a quad.
22316
- *
22317
- * @fires geo.event.pixelmap.prepared
22318
- */
22319
-
22320
-
22321
- this._computePixelmap = function () {
22322
- var data = m_this.data() || [],
22323
- colorFunc = m_this.style.get('color'),
22324
- i,
22325
- idx,
22326
- lastidx,
22327
- color,
22328
- pixelData,
22329
- indices,
22330
- mappedColors,
22331
- updateFirst,
22332
- updateLast = -1,
22333
- update,
22334
- prepared;
22335
-
22336
- if (!m_info) {
22337
- if (!m_this._preparePixelmap()) {
22338
- return;
22339
- }
22340
-
22341
- prepared = true;
22342
- }
22343
-
22344
- mappedColors = m_info.mappedColors;
22345
- updateFirst = m_info.area;
22346
-
22347
- for (idx in mappedColors) {
22348
- if (mappedColors.hasOwnProperty(idx)) {
22349
- color = colorFunc(data[idx], +idx) || {};
22350
- color = [(color.r || 0) * 255, (color.g || 0) * 255, (color.b || 0) * 255, color.a === undefined ? 255 : color.a * 255];
22351
- mappedColors[idx].update = !mappedColors[idx].color || mappedColors[idx].color[0] !== color[0] || mappedColors[idx].color[1] !== color[1] || mappedColors[idx].color[2] !== color[2] || mappedColors[idx].color[3] !== color[3];
22352
-
22353
- if (mappedColors[idx].update) {
22354
- mappedColors[idx].color = color;
22355
- updateFirst = Math.min(mappedColors[idx].first, updateFirst);
22356
- updateLast = Math.max(mappedColors[idx].last, updateLast);
22357
- }
22358
- }
22359
- }
22360
- /* If nothing was updated, we are done */
22361
-
22362
-
22363
- if (updateFirst >= updateLast) {
22364
- return;
22365
- }
22366
- /* Update only the extent that has changed */
22367
-
22368
-
22369
- pixelData = m_info.imageData.data;
22370
- indices = m_info.indices;
22371
-
22372
- for (i = updateFirst; i <= updateLast; i += 1) {
22373
- idx = indices[i];
22374
-
22375
- if (idx !== lastidx) {
22376
- lastidx = idx;
22377
- color = mappedColors[idx].color;
22378
- update = mappedColors[idx].update;
22379
- }
22380
-
22381
- if (update) {
22382
- pixelData[i * 4] = color[0];
22383
- pixelData[i * 4 + 1] = color[1];
22384
- pixelData[i * 4 + 2] = color[2];
22385
- pixelData[i * 4 + 3] = color[3];
22386
- }
22387
- }
22388
- /* Place the updated area into the canvas */
22389
-
22390
-
22391
- m_info.context.putImageData(m_info.imageData, 0, 0, 0, Math.floor(updateFirst / m_info.width), m_info.width, Math.ceil((updateLast + 1) / m_info.width));
22392
- /* If we haven't made a quad feature, make one now. The quad feature needs
22393
- * to have the canvas capability. */
22394
-
22395
- if (!m_quadFeature) {
22396
- m_quadFeature = m_this.layer().createFeature('quad', {
22397
- selectionAPI: false,
22398
- gcs: m_this.gcs(),
22399
- visible: m_this.visible(undefined, true)
22400
- });
22401
- m_this.dependentFeatures([m_quadFeature]);
22402
- m_quadFeature.style({
22403
- image: m_info.canvas,
22404
- position: m_this.style.get('position')
22405
- }).data([{}]).draw();
22406
- }
22407
- /* If we prepared the pixelmap and rendered it, send a prepared event */
22408
-
22409
-
22410
- if (prepared) {
22411
- m_this.geoTrigger(geo_event.pixelmap.prepared, {
22412
- pixelmap: m_this
22413
- });
22414
- }
22415
- };
22416
- /**
22417
- * Update.
22418
- *
22419
- * @returns {this}
22420
- */
22421
-
22422
-
22423
- this._update = function () {
22424
- s_update.call(m_this);
22425
-
22426
- if (m_this.buildTime().timestamp() <= m_this.dataTime().timestamp() || m_this.updateTime().timestamp() < m_this.timestamp()) {
22427
- m_this._build();
22428
- }
22429
-
22430
- m_this.updateTime().modified();
22431
- return m_this;
22432
- };
22433
- /**
22434
- * Destroy. Deletes the associated quadFeature.
22435
- *
22436
- * @returns {this}
22437
- */
22438
-
22439
-
22440
- this._exit = function () {
22441
- if (m_quadFeature && m_this.layer()) {
22442
- m_this.layer().deleteFeature(m_quadFeature);
22443
- m_quadFeature = null;
22444
- m_this.dependentFeatures([]);
22445
- }
22446
-
22447
- s_exit();
22518
+ m_this.buildTime().modified();
22448
22519
  return m_this;
22449
22520
  };
22450
22521
  /**
@@ -22486,6 +22557,13 @@ var pixelmapFeature = function pixelmapFeature(arg) {
22486
22557
 
22487
22558
  m_this.style(style);
22488
22559
  m_this.dataTime().modified();
22560
+
22561
+ if (arg.quadFeature) {
22562
+ m_this.m_srcImage = true;
22563
+
22564
+ m_this._computePixelmap();
22565
+ }
22566
+
22489
22567
  return m_this;
22490
22568
  };
22491
22569
 
@@ -22511,13 +22589,182 @@ pixelmapFeature.create = function (layer, spec) {
22511
22589
 
22512
22590
  pixelmapFeature.capabilities = {
22513
22591
  /* core feature name -- support in any manner */
22514
- feature: 'pixelmap'
22592
+ feature: 'pixelmap',
22593
+
22594
+ /* support for image-based lookup */
22595
+ lookup: 'pixelmap.lookup'
22515
22596
  };
22516
22597
  inherit(pixelmapFeature, feature);
22517
22598
  module.exports = pixelmapFeature;
22518
22599
 
22519
22600
  /***/ }),
22520
22601
 
22602
+ /***/ 809:
22603
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
22604
+
22605
+ var $ = __webpack_require__(5638);
22606
+
22607
+ var inherit = __webpack_require__(5699);
22608
+
22609
+ var tileLayer = __webpack_require__(1940);
22610
+
22611
+ var registry = __webpack_require__(4647);
22612
+
22613
+ var quadFeature = __webpack_require__(5017);
22614
+
22615
+ var pixelmapFeature = __webpack_require__(6374);
22616
+ /**
22617
+ * Object specification for a pixelmap layer.
22618
+ *
22619
+ * @typedef {geo.tileLayer.spec} geo.pixelmapLayer.spec
22620
+ * @extends {geo.tileLayer.spec}
22621
+ * @property {geo.geoColor|function} [color] The color that should be used
22622
+ * for each data element. Data elements correspond to the indices in the
22623
+ * pixel map. If an index is larger than the number of data elements, it will
22624
+ * be transparent. If there is more data than there are indices, it is
22625
+ * ignored.
22626
+ * @property {object} [style] An optional style object that could contain
22627
+ * `color` or other style values.
22628
+ * @property {array} [data] A new data array.
22629
+ * @property {string} [crossDomain='anonymous'] Image CORS attribute. This is
22630
+ * used for the `crossorigin` property when loading images.
22631
+ */
22632
+
22633
+ /**
22634
+ * Create a new instance of pixelmapLayer. This is a {@link geo.tileLayer} with
22635
+ * an OSM url and attribution defaults and with the tiles centered on the
22636
+ * origin.
22637
+ *
22638
+ * @class
22639
+ * @alias geo.pixelmapLayer
22640
+ * @extends geo.tileLayer
22641
+ *
22642
+ * @param {geo.pixelmapLayer.spec} [arg] Specification for the layer.
22643
+ */
22644
+
22645
+
22646
+ var pixelmapLayer = function pixelmapLayer(arg) {
22647
+ var imageTile = __webpack_require__(4665);
22648
+
22649
+ if (!(this instanceof pixelmapLayer)) {
22650
+ return new pixelmapLayer(arg);
22651
+ }
22652
+
22653
+ arg = arg || {};
22654
+ arg = $.extend(true, {}, this.constructor.defaults, arg);
22655
+ tileLayer.call(this, arg);
22656
+ var s_init = this._init,
22657
+ m_pixelmapFeature,
22658
+ m_this = this;
22659
+ /**
22660
+ * Returns an instantiated imageTile object with the given indices. This
22661
+ * method always returns a new tile object. Use `_getTileCached` to use
22662
+ * the caching layer.
22663
+ *
22664
+ * @param {object} index The tile index.
22665
+ * @param {number} index.x
22666
+ * @param {number} index.y
22667
+ * @param {number} index.level
22668
+ * @param {object} source The tile index used for constructing the url.
22669
+ * @param {number} source.x
22670
+ * @param {number} source.y
22671
+ * @param {number} source.level
22672
+ * @returns {geo.tile}
22673
+ */
22674
+
22675
+ this._getTile = function (index, source) {
22676
+ var urlParams = source || index;
22677
+ return imageTile({
22678
+ index: index,
22679
+ size: {
22680
+ x: m_this._options.tileWidth,
22681
+ y: m_this._options.tileHeight
22682
+ },
22683
+ queue: m_this._queue,
22684
+ overlap: m_this._options.tileOverlap,
22685
+ scale: m_this._options.tileScale,
22686
+ url: m_this._options.url.call(m_this, urlParams.x, urlParams.y, urlParams.level || 0, m_this._options.subdomains),
22687
+ crossDomain: m_this._options.crossDomain
22688
+ });
22689
+ };
22690
+ /**
22691
+ * Initialize.
22692
+ *
22693
+ * @returns {this} The current layer.
22694
+ */
22695
+
22696
+
22697
+ this._init = function () {
22698
+ // Call super class init
22699
+ s_init.apply(m_this, arguments);
22700
+ var pixelmapArgs = {
22701
+ quadFeature: m_this.features()[0]
22702
+ };
22703
+
22704
+ if (arg.style) {
22705
+ pixelmapArgs.style = arg.style;
22706
+ }
22707
+
22708
+ if (arg.color) {
22709
+ pixelmapArgs.color = arg.color;
22710
+ }
22711
+
22712
+ m_pixelmapFeature = m_this.createFeature('pixelmap', pixelmapArgs);
22713
+
22714
+ if (arg.data) {
22715
+ m_pixelmapFeature.data(arg.data);
22716
+ }
22717
+
22718
+ m_this.style = m_pixelmapFeature.style;
22719
+ m_this.data = m_pixelmapFeature.data;
22720
+ m_this.indexModified = m_pixelmapFeature.indexModified;
22721
+ var s_dataTimeModified = m_this.dataTime().modified;
22722
+
22723
+ m_this.dataTime().modified = function () {
22724
+ m_pixelmapFeature.dataTime().modified();
22725
+ return s_dataTimeModified();
22726
+ };
22727
+
22728
+ ['modified', 'geoOn', 'geoOff', 'geoOnce'].forEach(function (funcName) {
22729
+ var superFunc = m_this[funcName];
22730
+
22731
+ m_this[funcName] = function () {
22732
+ m_pixelmapFeature[funcName].apply(this, arguments);
22733
+ return superFunc.apply(this, arguments);
22734
+ };
22735
+ });
22736
+ return m_this;
22737
+ };
22738
+
22739
+ return m_this;
22740
+ };
22741
+ /**
22742
+ * This object contains the default options used to initialize the
22743
+ * pixelmapLayer.
22744
+ */
22745
+
22746
+
22747
+ pixelmapLayer.defaults = $.extend({}, tileLayer.defaults, {
22748
+ features: [quadFeature.capabilities.image, pixelmapFeature.capabilities.lookup],
22749
+ tileOffset: function tileOffset(level) {
22750
+ var s = Math.pow(2, level - 1) * 256;
22751
+ return {
22752
+ x: s,
22753
+ y: s
22754
+ };
22755
+ },
22756
+ url: ''
22757
+ });
22758
+ inherit(pixelmapLayer, tileLayer);
22759
+ /* By default, ask to support image quads. If the user needs full
22760
+ * reprojection, they will need to require the
22761
+ * quadFeature.capabilities.imageFull feature */
22762
+
22763
+ registry.registerLayer('pixelmap', pixelmapLayer, [quadFeature.capabilities.image]);
22764
+ module.exports = pixelmapLayer;
22765
+
22766
+ /***/ }),
22767
+
22521
22768
  /***/ 2557:
22522
22769
  /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
22523
22770
 
@@ -23177,7 +23424,7 @@ pointFeature.capabilities = {
23177
23424
  };
23178
23425
  /**
23179
23426
  * Support primitive shapes
23180
- * @enum
23427
+ * @enum {string}
23181
23428
  */
23182
23429
 
23183
23430
  pointFeature.primitiveShapes = {
@@ -23903,9 +24150,9 @@ var polygonFeature = function polygonFeature(arg) {
23903
24150
  *
23904
24151
  * @param {array} data A new data array.
23905
24152
  * @param {number} [tolerance] The maximum variation allowed in map.gcs
23906
- * units. A value of zero will only remove perfectly colinear points. If
23907
- * not specified, this is set to a half display pixel at the map's current
23908
- * zoom level.
24153
+ * units. A value of zero will only remove perfectly collinear points.
24154
+ * If not specified, this is set to a half display pixel at the map's
24155
+ * current zoom level.
23909
24156
  * @param {function} [posFunc=this.style.get('position')] The function to
23910
24157
  * get the position of each vertex.
23911
24158
  * @param {function} [polyFunc=this.style.get('polygon')] The function to
@@ -24406,7 +24653,8 @@ var quadFeature = function quadFeature(arg) {
24406
24653
 
24407
24654
  if (coordbasis) {
24408
24655
  extra[quad.idx] = {
24409
- basis: coordbasis
24656
+ basis: coordbasis,
24657
+ _quad: quad
24410
24658
  };
24411
24659
  }
24412
24660
  }
@@ -25099,7 +25347,7 @@ util.registerRenderer = function (name, func) {
25099
25347
  * @param {geo.layer} layer The layer associated with the renderer.
25100
25348
  * @param {HTMLCanvasElement} [canvas] A canvas object to share between
25101
25349
  * renderers.
25102
- * @param {object} options Options for the new renderer.
25350
+ * @param {object} [options] Options for the new renderer.
25103
25351
  * @returns {geo.renderer|null} The new renderer or null if no such name is
25104
25352
  * registered.
25105
25353
  */
@@ -25128,7 +25376,7 @@ util.createRenderer = function (name, layer, canvas, options) {
25128
25376
  *
25129
25377
  * @alias geo.checkRenderer
25130
25378
  * @param {string|null} name Name of the desired renderer.
25131
- * @param {boolean} noFallback If truthy, don't recommend a fallback.
25379
+ * @param {boolean} [noFallback] If truthy, don't recommend a fallback.
25132
25380
  * @returns {string|null|false} The name of the renderer that should be used
25133
25381
  * or false if no valid renderer can be determined.
25134
25382
  */
@@ -26004,7 +26252,7 @@ module.exports = sceneObject;
26004
26252
  * @constant
26005
26253
  * @type {string}
26006
26254
  */
26007
- module.exports = "4c7a5260c6c4756f2cf461d00c9be82abaea01a7";
26255
+ module.exports = "1d12f116c34ea5a1423ecb767df24b2291e53b06";
26008
26256
 
26009
26257
  /***/ }),
26010
26258
 
@@ -27385,10 +27633,10 @@ var svgRenderer = function svgRenderer(arg) {
27385
27633
  * Create a new feature element from an object that describes the feature
27386
27634
  * attributes. To be called from feature classes only.
27387
27635
  *
27388
- * @param {object} arg Options for the features.
27636
+ * @param {object} arg
27389
27637
  * @param {string} arg.id A unique string identifying the feature.
27390
27638
  * @param {array} arg.data Array of data objects used in a d3 data method.
27391
- * @param {function} [aeg.dataIndex] A function that returns a unique id for
27639
+ * @param {function} [arg.dataIndex] A function that returns a unique id for
27392
27640
  * each data element. This is passed to the data access function.
27393
27641
  * @param {object} arg.style An object with style values or functions.
27394
27642
  * @param {object} arg.attributes An object containing element attributes.
@@ -27401,7 +27649,7 @@ var svgRenderer = function svgRenderer(arg) {
27401
27649
  * attributes and styles set when new. If falsy, features always have
27402
27650
  * attributes and styles updated.
27403
27651
  * @param {boolean} [arg.sortByZ] If truthy, sort features by the `d.zIndex`.
27404
- * @param {string} [parentId] If set, the group ID of the parent element.
27652
+ * @param {string} [arg.parentId] If set, the group ID of the parent element.
27405
27653
  * @returns {this}
27406
27654
  */
27407
27655
 
@@ -28714,7 +28962,7 @@ var tileCache = function tileCache(options) {
28714
28962
  * Remove a tile from the cache.
28715
28963
  *
28716
28964
  * @param {string|geo.tile} tile The tile or its hash.
28717
- * @returns {booliean} `true` if a tile was removed.
28965
+ * @returns {boolean} `true` if a tile was removed.
28718
28966
  */
28719
28967
 
28720
28968
 
@@ -29409,7 +29657,7 @@ var tileLayer = function tileLayer(arg) {
29409
29657
  /**
29410
29658
  * Returns a tile's bounds in a gcs.
29411
29659
  *
29412
- * @param {object|tile} indexOrTile Either a tile or an object with
29660
+ * @param {object|geo.tile} indexOrTile Either a tile or an object with
29413
29661
  * {x, y, level}` specifying a tile.
29414
29662
  * @param {string|geo.transform|null} [gcs] `undefined` to use the
29415
29663
  * interface gcs, `null` to use the map gcs, or any other transform.
@@ -29578,7 +29826,7 @@ var tileLayer = function tileLayer(arg) {
29578
29826
  * @param {number} maxLevel The zoom level
29579
29827
  * @param {geo.geoBounds} bounds The map bounds
29580
29828
  * @param {boolean} sorted Return a sorted list
29581
- * @param {boolean} onlyIfChanged If the set of tiles have not changed
29829
+ * @param {boolean} [onlyIfChanged] If the set of tiles have not changed
29582
29830
  * (even if their desired order has), return undefined instead of an
29583
29831
  * array of tiles.
29584
29832
  * @returns {geo.tile[]} An array of tile objects
@@ -29599,7 +29847,7 @@ var tileLayer = function tileLayer(arg) {
29599
29847
  changed = false,
29600
29848
  old,
29601
29849
  level,
29602
- minLevel = m_this._options.keepLower ? m_this._options.minLevel : maxLevel;
29850
+ minLevel = m_this._options.keepLower ? m_this._options.minLevel : Math.max(maxLevel, m_this._options.minLevel);
29603
29851
 
29604
29852
  if (maxLevel < minLevel) {
29605
29853
  maxLevel = minLevel;
@@ -30112,7 +30360,7 @@ var tileLayer = function tileLayer(arg) {
30112
30360
  * origin.
30113
30361
  *
30114
30362
  * @param {object} pt A point in world space coordinates with `x` and `y`.
30115
- * @param {number|undefined} zoom If unspecified, use the map zoom.
30363
+ * @param {number} [zoom] If unspecified, use the map zoom.
30116
30364
  * @returns {object} Local coordinates with `x` and `y`.
30117
30365
  */
30118
30366
 
@@ -30161,7 +30409,7 @@ var tileLayer = function tileLayer(arg) {
30161
30409
  * create the element if it doesn't already exist.
30162
30410
  *
30163
30411
  * @param {number} level The zoom level of the layer to fetch.
30164
- * @returns {DOM} The layer's DOM element.
30412
+ * @returns {HTMLElement} The layer's DOM element.
30165
30413
  */
30166
30414
 
30167
30415
 
@@ -30518,8 +30766,8 @@ var tileLayer = function tileLayer(arg) {
30518
30766
  * @param {geo.geoBounds} [bounds] The view bounds (if unspecified, assume
30519
30767
  * global bounds)
30520
30768
  * @param {number} bounds.level The zoom level the bounds are given as.
30521
- * @param {number} zoom Keep in bound tile at this zoom level.
30522
- * @param {boolean} doneLoading If true, allow purging additional tiles.
30769
+ * @param {number} [zoom] Keep in bound tile at this zoom level.
30770
+ * @param {boolean} [doneLoading] If true, allow purging additional tiles.
30523
30771
  * @returns {boolean}
30524
30772
  */
30525
30773
 
@@ -30539,7 +30787,7 @@ var tileLayer = function tileLayer(arg) {
30539
30787
  /* For tile layers that should only keep one layer, if loading is
30540
30788
  * finished, purge all but the current layer. This is important for
30541
30789
  * semi-transparent layers. */
30542
- if ((doneLoading || m_this._isCovered(tile)) && zoom !== tile.index.level) {
30790
+ if ((doneLoading || m_this._isCovered(tile)) && zoom !== tile.index.level && (zoom >= m_this._options.minLevel || tile.index.level !== m_this._options.minLevel)) {
30543
30791
  return true;
30544
30792
  }
30545
30793
  }
@@ -30632,9 +30880,9 @@ var tileLayer = function tileLayer(arg) {
30632
30880
  /**
30633
30881
  * Get or set the subdomains used for templating.
30634
30882
  *
30635
- * @param {string|list} [subdomains] A comma-separated list, a string of
30883
+ * @param {string|string[]} [subdomains] A comma-separated list, a string of
30636
30884
  * single character subdomains, or a list.
30637
- * @returns {string|list|this}
30885
+ * @returns {string|string[]|this}
30638
30886
  */
30639
30887
 
30640
30888
 
@@ -30678,8 +30926,8 @@ var tileLayer = function tileLayer(arg) {
30678
30926
  /**
30679
30927
  * Get/Set visibility of the layer.
30680
30928
  *
30681
- * @param {boolean|undefined} val If unspecified, return the visibility,
30682
- * otherwise set it.
30929
+ * @param {boolean} [val] If unspecified, return the visibility, otherwise
30930
+ * set it.
30683
30931
  * @returns {boolean|this} Either the visibility (if getting) or the layer
30684
30932
  * (if setting).
30685
30933
  */
@@ -30896,24 +31144,24 @@ var util = __webpack_require__(4634);
30896
31144
  * @extends geo.feature.spec
30897
31145
  * @property {geo.geoPosition|function} [position] Position of the data.
30898
31146
  * Default is (data).
30899
- * @property {float|function} [time] Time of the data. Default is `(data).t`.
31147
+ * @property {number|function} [time] Time of the data. Default is `(data).t`.
30900
31148
  * @property {object|function} [track] Tracks from the data. Default is
30901
31149
  * (data). Typically, the data is an array of tracks, each of which is an
30902
31150
  * array of points, each of which has a position and time. The position and
30903
31151
  * time functions are called for each point as `position(trackPoint,
30904
31152
  * pointIndex, trackEntry, trackEntryIndex)`.
30905
- * @property {float|null} [startTime=null] Start time. Used for styling. If
31153
+ * @property {number|null} [startTime=null] Start time. Used for styling. If
30906
31154
  * `null`, this is the duration before the end time if `duration` is not
30907
31155
  * `null` and the minimum time in any track if `duration` is `null`.
30908
- * @property {float} [endTime=null] End time. Used for styling and position of
30909
- * the track head. If `null` and either of `startTime` or `duration` are
31156
+ * @property {number} [endTime=null] End time. Used for styling and position
31157
+ * of the track head. If `null` and either of `startTime` or `duration` are
30910
31158
  * `null`, this is the maximum time in any track.
30911
- * @property {float} [duration=null] Duration between start and end times.
31159
+ * @property {number} [duration=null] Duration between start and end times.
30912
31160
  * Ignored if both start and end times are specified.
30913
- * @property {float|function} [text] Text to use for the head of the track. If
30914
- * specified, the track head is rendered as text. If `undefined` a marker is
30915
- * used instead. If `null` or an empty string (`''`), neither a marker nor
30916
- * text is used.
31161
+ * @property {number|function} [text] Text to use for the head of the track.
31162
+ * If specified, the track head is rendered as text. If `undefined` a marker
31163
+ * is used instead. If `null` or an empty string (`''`), neither a marker
31164
+ * nor text is used.
30917
31165
  * @property {geo.trackFeature.styleSpec} [style] Style object with default
30918
31166
  * style options.
30919
31167
  * @property {geo.lineFeature.styleSpec} [pastStyle] Style object with
@@ -31061,7 +31309,7 @@ var trackFeature = function trackFeature(arg) {
31061
31309
  * Calculate an interpolated position given a time. If the time is outside
31062
31310
  * the range of a track, the first or last point is returned.
31063
31311
  *
31064
- * @param {float} time The time to compute a position array for.
31312
+ * @param {number} time The time to compute a position array for.
31065
31313
  * @param {string|geo.transform|null} [gcs] `undefined` to use the feature
31066
31314
  * gcs, `null` to use the map gcs, or any other transform. This transform
31067
31315
  * is used for the interpolation; the results are still in feature gcs.
@@ -31226,7 +31474,7 @@ var trackFeature = function trackFeature(arg) {
31226
31474
  m_tracks.trackFunc = m_this.style.get('track');
31227
31475
  m_tracks.textFunc = m_this.style.get('text');
31228
31476
  ['past', 'current', 'future'].forEach(function (key) {
31229
- m_lineFeatures[key].style(m_this[key + 'Style']()).style(m_this.style()).line(m_this.style('track')).gcs(m_this.gcs()).data(data).position(m_this._linePosition(key));
31477
+ m_lineFeatures[key].style(m_this.style()).style(m_this[key + 'Style']()).line(m_this.style('track')).gcs(m_this.gcs()).data(data).position(m_this._linePosition(key));
31230
31478
  });
31231
31479
  var timeExtents = {};
31232
31480
  data.forEach(function (d, i) {
@@ -31562,11 +31810,11 @@ var trackFeature = function trackFeature(arg) {
31562
31810
  /**
31563
31811
  * Get/Set time accessor.
31564
31812
  *
31565
- * @param {float} [val] If not specified, return the current time accessor.
31813
+ * @param {number} [val] If not specified, return the current time accessor.
31566
31814
  * If specified, use this for the time accessor and return `this`. If a
31567
31815
  * function is given, this is called with `(vertexElement, vertexIndex,
31568
31816
  * dataElement, dataIndex)`.
31569
- * @returns {float|function|this} The current time or this feature.
31817
+ * @returns {number|function|this} The current time or this feature.
31570
31818
  */
31571
31819
 
31572
31820
 
@@ -31636,8 +31884,8 @@ var trackFeature = function trackFeature(arg) {
31636
31884
  /**
31637
31885
  * Get or set the start time.
31638
31886
  *
31639
- * @param {float|null} [val] If specified, the new start time.
31640
- * @returns {float|null|this} If set, the instance. Otherwise, the current
31887
+ * @param {number|null} [val] If specified, the new start time.
31888
+ * @returns {number|null|this} If set, the instance. Otherwise, the current
31641
31889
  * start time value.
31642
31890
  */
31643
31891
 
@@ -31658,8 +31906,8 @@ var trackFeature = function trackFeature(arg) {
31658
31906
  /**
31659
31907
  * Get or set the end time.
31660
31908
  *
31661
- * @param {float|null} [val] If specified, the new end time.
31662
- * @returns {float|null|this} If set, the instance. Otherwise, the current
31909
+ * @param {number|null} [val] If specified, the new end time.
31910
+ * @returns {number|null|this} If set, the instance. Otherwise, the current
31663
31911
  * end time value.
31664
31912
  */
31665
31913
 
@@ -31680,8 +31928,8 @@ var trackFeature = function trackFeature(arg) {
31680
31928
  /**
31681
31929
  * Get or set the duration.
31682
31930
  *
31683
- * @param {float|null} [val] If specified, the new duration.
31684
- * @returns {float|null|this} If set, the instance. Otherwise, the current
31931
+ * @param {number|null} [val] If specified, the new duration.
31932
+ * @returns {number|null|this} If set, the instance. Otherwise, the current
31685
31933
  * duration.
31686
31934
  */
31687
31935
 
@@ -32305,11 +32553,12 @@ transform.lookup = function (projection) {
32305
32553
  *
32306
32554
  * @param {string} srcPrj The source projection.
32307
32555
  * @param {string} tgtPrj The destination projection.
32308
- * @param {geoPosition|geoPosition[]|number[]} coordinates An array of
32309
- * coordinate objects. These may be in object or array form, or a flat
32310
- * array.
32311
- * @param {number} numberOfComponents For flat arrays, either 2 or 3.
32312
- * @returns {geoPosition|geoPosition[]|number[]} The transformed coordinates.
32556
+ * @param {geo.geoPosition|geo.geoPosition[]|number[]} coordinates An array of
32557
+ * coordinate objects. These may be in object or array form, or a flat
32558
+ * array.
32559
+ * @param {number} [numberOfComponents] For flat arrays, either 2 or 3.
32560
+ * @returns {geo.geoPosition|geo.geoPosition[]|number[]} The transformed
32561
+ * coordinates.
32313
32562
  */
32314
32563
 
32315
32564
 
@@ -32398,10 +32647,10 @@ transform.transformCoordinates = function (srcPrj, tgtPrj, coordinates, numberOf
32398
32647
  * components per coordinate. The array is modified in place.
32399
32648
  *
32400
32649
  * @param {transform} trans The transformation object.
32401
- * @param {geoPosition[]|number[]} coordinates An array of coordinate
32650
+ * @param {geo.geoPosition[]|number[]} coordinates An array of coordinate
32402
32651
  * objects or a flat array.
32403
32652
  * @param {number} numberOfComponents For flat arrays, either 2 or 3.
32404
- * @returns {geoPosition[]|number[]} The transformed coordinates
32653
+ * @returns {geo.geoPosition[]|number[]} The transformed coordinates
32405
32654
  */
32406
32655
 
32407
32656
 
@@ -32723,8 +32972,6 @@ transform.affineInverse = function (def, coords) {
32723
32972
  * @param {object} [ellipsoid=proj4.WGS84] An object with at least `a` and one
32724
32973
  * of `b`, `f`, or `rf` (1 / `f`) -- this works with proj4 ellipsoid
32725
32974
  * definitions.
32726
- * @param {number} [maxIterations=100] Maximum number of iterations to use
32727
- * to test convergence.
32728
32975
  * @returns {number} The distance in meters (or whatever units the ellipsoid
32729
32976
  * was specified in.
32730
32977
  */
@@ -32862,7 +33109,7 @@ module.exports = transform;
32862
33109
  /***/ }),
32863
33110
 
32864
33111
  /***/ 3762:
32865
- /***/ (function() {
33112
+ /***/ (function(module) {
32866
33113
 
32867
33114
  /*
32868
33115
  * Type definitions for jsdoc.
@@ -33100,6 +33347,7 @@ module.exports = transform;
33100
33347
  *
33101
33348
  * @typedef {geo.polygonFlat|geo.polygonObject} geo.polygon
33102
33349
  */
33350
+ module.exports = {};
33103
33351
 
33104
33352
  /***/ }),
33105
33353
 
@@ -34655,7 +34903,7 @@ var sliderWidget = function sliderWidget(arg) {
34655
34903
  * Respond to a mouse event on the widget.
34656
34904
  *
34657
34905
  * @param {d3Event} evt The event on the widget.
34658
- * @param {boolean} trans Truthy for an animated transition.
34906
+ * @param {boolean} [trans] Truthy for an animated transition.
34659
34907
  */
34660
34908
 
34661
34909
  function respond(evt, trans) {
@@ -35276,7 +35524,7 @@ var $ = __webpack_require__(5638);
35276
35524
  *
35277
35525
  * @param {geo.util.ClusterGroup} group The source cluster group
35278
35526
  * @param {number} zoom The zoom level of the current node
35279
- * @param {object[]} children An array of ClusterTrees or point objects
35527
+ * @param {object[]} [children] An array of ClusterTrees or point objects
35280
35528
  */
35281
35529
 
35282
35530
 
@@ -35410,8 +35658,8 @@ ClusterTree.prototype.coords = function () {
35410
35658
  * @class
35411
35659
  * @alias geo.util.ClusterGroup
35412
35660
  * @param {object} opts An options object
35413
- * @param {number} maxZoom The maximum zoom level to calculate.
35414
- * @param {number} radius Size of clustering at zoom 0 in point gcs.
35661
+ * @param {number} [opts.maxZoom] The maximum zoom level to calculate.
35662
+ * @param {number} [opts.radius] Size of clustering at zoom 0 in point gcs.
35415
35663
  */
35416
35664
 
35417
35665
 
@@ -35613,7 +35861,7 @@ var colorName = __webpack_require__(9552);
35613
35861
  /**
35614
35862
  * @typedef {object} geo.util.cssColorConversionRecord
35615
35863
  * @property {string} name The name of the color conversion.
35616
- * @property {RegEx} regex A regex that, if it matches the color string, will
35864
+ * @property {RegExp} regex A regex that, if it matches the color string, will
35617
35865
  * cause the process function to be invoked.
35618
35866
  * @property {function} process A function that takes (`color`, `match`) with
35619
35867
  * the original color string and the results of matching the regex using
@@ -36073,7 +36321,7 @@ var util = {
36073
36321
  * Check if an object an HTMLVideoElement element that is loaded.
36074
36322
  *
36075
36323
  * @param {object} vid An object that might be an HTMLVideoElement.
36076
- * @param {boolean} [allowFailedVideo] If `true`, an viedo element that has
36324
+ * @param {boolean} [allowFailedVideo] If `true`, an video element that has
36077
36325
  * a source and has failed to load is also considered 'ready' in the
36078
36326
  * sense that it isn't expected to change to a better state.
36079
36327
  * @returns {boolean} `true` if this is a video that is ready.
@@ -36463,7 +36711,7 @@ var util = {
36463
36711
  * var map = geo.map($.extend(results.map, {clampZoom: false}));
36464
36712
  * map.createLayer('osm', results.layer);
36465
36713
  *
36466
- * @param {string} [node] DOM selector for the map container.
36714
+ * @param {string?} node DOM selector for the map container.
36467
36715
  * @param {number} width Width of the whole map contents in pixels.
36468
36716
  * @param {number} height Height of the whole map contents in pixels.
36469
36717
  * @param {number} [tileWidth] If an osm or tile layer is going to be used,
@@ -36737,7 +36985,7 @@ var util = {
36737
36985
  /**
36738
36986
  * Determine if two line segments cross. They are not considered crossing if
36739
36987
  * they share a vertex. They are crossing if either of one segment's
36740
- * vertices are colinear with the other segment.
36988
+ * vertices are collinear with the other segment.
36741
36989
  *
36742
36990
  * @param {geo.geoPosition} seg1pt1 One endpoint of the first segment.
36743
36991
  * @param {geo.geoPosition} seg1pt2 The other endpoint of the first segment.
@@ -36759,7 +37007,7 @@ var util = {
36759
37007
  }
36760
37008
  /* If the lines cross, the signed area of the triangles formed between one
36761
37009
  * segment and the other's vertices will have different signs. By using
36762
- * > 0, colinear points are crossing. */
37010
+ * > 0, collinear points are crossing. */
36763
37011
 
36764
37012
 
36765
37013
  if (util.triangleTwiceSignedArea2d(seg1pt1, seg1pt2, seg2pt1) * util.triangleTwiceSignedArea2d(seg1pt1, seg1pt2, seg2pt2) > 0 || util.triangleTwiceSignedArea2d(seg2pt1, seg2pt2, seg1pt1) * util.triangleTwiceSignedArea2d(seg2pt1, seg2pt2, seg1pt2) > 0) {
@@ -36806,7 +37054,7 @@ var util = {
36806
37054
  * @param {geo.geoPosition[]} pts A list of points forming the line or
36807
37055
  * polygon.
36808
37056
  * @param {number} tolerance The maximum variation allowed. A value of zero
36809
- * will only remove perfectly colinear points.
37057
+ * will only remove perfectly collinear points.
36810
37058
  * @param {boolean} [closed] If true, this is a polygon rather than an open
36811
37059
  * line. In this case, it is possible to get back a single point.
36812
37060
  * @param {Array.<geo.geoPosition[]>?} [noCrossLines] A falsy value to allow
@@ -36966,7 +37214,7 @@ var util = {
36966
37214
  */
36967
37215
  escapeUnicodeHTML: function escapeUnicodeHTML(text) {
36968
37216
  return text.replace(/./g, function (k) {
36969
- var code = k.charCodeAt();
37217
+ var code = k.charCodeAt(0);
36970
37218
 
36971
37219
  if (code < 127) {
36972
37220
  return k;
@@ -37033,7 +37281,7 @@ var util = {
37033
37281
  * stored as local base64 urls.
37034
37282
  *
37035
37283
  * @param {string} css The css to parse for urls.
37036
- * @param {jQuery.selector|DOMElement} styleElem The element that receivs
37284
+ * @param {jQuery.selector|HTMLElement} styleElem The element that receives
37037
37285
  * the css text after dereferencing or the DOM element that has style
37038
37286
  * that will be updated.
37039
37287
  * @param {jQuery.Deferred} styleDefer A Deferred to resolve once
@@ -38140,7 +38388,7 @@ module.exports.restoreWebglRenderer = function () {
38140
38388
  * unspecified, callback will be executed one final time after the last
38141
38389
  * throttled-function call. (After the throttled-function has not been
38142
38390
  * called for `delay` milliseconds, the internal counter is reset)
38143
- * @param {function} callback A function to be executed after `delay`
38391
+ * @param {function} [callback] A function to be executed after `delay`
38144
38392
  * milliseconds. The `this` context and all arguments are passed through,
38145
38393
  * as-is, to `callback` when the throttled-function is executed.
38146
38394
  * @param {function} [accumulator] A function to be executed (synchronously)
@@ -38468,7 +38716,7 @@ module.exports = vectorFeature;
38468
38716
  * @constant
38469
38717
  * @type {string}
38470
38718
  */
38471
- module.exports = "1.6.3";
38719
+ module.exports = "1.7.0";
38472
38720
 
38473
38721
  /***/ }),
38474
38722
 
@@ -39231,8 +39479,10 @@ module.exports = {
39231
39479
  isolineFeature: __webpack_require__(9752),
39232
39480
  layer: __webpack_require__(5389),
39233
39481
  lineFeature: __webpack_require__(7390),
39482
+ lookupTable2D: __webpack_require__(8672),
39234
39483
  markerFeature: __webpack_require__(1848),
39235
39484
  meshColored: __webpack_require__(5651),
39485
+ pixelmapFeature: __webpack_require__(9685),
39236
39486
  pointFeature: __webpack_require__(5675),
39237
39487
  polygonFeature: __webpack_require__(2890),
39238
39488
  quadFeature: __webpack_require__(2182),
@@ -40182,6 +40432,139 @@ module.exports = webgl_lineFeature;
40182
40432
 
40183
40433
  /***/ }),
40184
40434
 
40435
+ /***/ 8672:
40436
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
40437
+
40438
+ var inherit = __webpack_require__(5699);
40439
+
40440
+ var timestamp = __webpack_require__(6618);
40441
+
40442
+ var vgl = __webpack_require__(320);
40443
+ /**
40444
+ * Switch to a specific texture unit.
40445
+ *
40446
+ * @param {vgl.renderState} renderState An object that contains the context
40447
+ * used for drawing.
40448
+ * @param {number} textureUnit The number of the texture unit [0-15].
40449
+ */
40450
+
40451
+
40452
+ function activateTextureUnit(renderState, textureUnit) {
40453
+ if (textureUnit >= 0 && textureUnit <= 31) {
40454
+ renderState.m_context.activeTexture(vgl.GL.TEXTURE0 + textureUnit);
40455
+ } else {
40456
+ throw Error('[error] Texture unit ' + textureUnit + ' is not supported');
40457
+ }
40458
+ }
40459
+ /**
40460
+ * Create a new instance of class webgl_lookupTable2D.
40461
+ *
40462
+ * @class
40463
+ * @alias geo.webgl.lookupTable2D
40464
+ * @param {object} arg Options object.
40465
+ * @param {number} [arg.maxWidth] Maximum width to use for the texture. If the
40466
+ * number of colors set is less than this, the texture is 1D. If greater, it
40467
+ * will be a rectangle of maxWidth x whatever height is necessary.
40468
+ * @param {number[]} [arg.colorTable] Initial color table for the texture.
40469
+ * This is of the form RGBARGBA... where each value is an integer on the
40470
+ * scale [0,255].
40471
+ * @extends vgl.texture
40472
+ * @returns {geo.webgl.lookupTable2D}
40473
+ */
40474
+
40475
+
40476
+ var webgl_lookupTable2D = function webgl_lookupTable2D(arg) {
40477
+ 'use strict';
40478
+
40479
+ if (!(this instanceof webgl_lookupTable2D)) {
40480
+ return new webgl_lookupTable2D(arg);
40481
+ }
40482
+
40483
+ arg = arg || {};
40484
+ vgl.texture.call(this);
40485
+ var m_setupTimestamp = timestamp(),
40486
+ m_maxWidth = arg.maxWidth || 4096,
40487
+ m_colorTable = new Uint8Array([0, 0, 0, 0]),
40488
+ m_colorTableOrig,
40489
+ m_this = this;
40490
+ /**
40491
+ * Create lookup table, initialize parameters, and bind data to it.
40492
+ *
40493
+ * @param {vgl.renderState} renderState An object that contains the context
40494
+ * used for drawing.
40495
+ */
40496
+
40497
+ this.setup = function (renderState) {
40498
+ activateTextureUnit(renderState, m_this.textureUnit());
40499
+ renderState.m_context.deleteTexture(m_this.m_textureHandle);
40500
+ m_this.m_textureHandle = renderState.m_context.createTexture();
40501
+ renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, m_this.m_textureHandle);
40502
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_MIN_FILTER, vgl.GL.NEAREST);
40503
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_MAG_FILTER, vgl.GL.NEAREST);
40504
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_WRAP_S, vgl.GL.CLAMP_TO_EDGE);
40505
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_WRAP_T, vgl.GL.CLAMP_TO_EDGE);
40506
+ renderState.m_context.pixelStorei(vgl.GL.UNPACK_ALIGNMENT, 1);
40507
+ renderState.m_context.pixelStorei(vgl.GL.UNPACK_FLIP_Y_WEBGL, true);
40508
+ renderState.m_context.texImage2D(vgl.GL.TEXTURE_2D, 0, vgl.GL.RGBA, m_this.width, m_this.height, 0, vgl.GL.RGBA, vgl.GL.UNSIGNED_BYTE, m_colorTable);
40509
+ renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, null);
40510
+ m_setupTimestamp.modified();
40511
+ };
40512
+ /**
40513
+ * Get/set color table.
40514
+ *
40515
+ * @param {number[]} [val] An array of RGBARGBA... integers on a scale
40516
+ * of [0, 255]. `undefined` to get the current value.
40517
+ * @returns {number[]|this}
40518
+ */
40519
+
40520
+
40521
+ this.colorTable = function (val) {
40522
+ if (val === undefined) {
40523
+ return m_colorTableOrig;
40524
+ }
40525
+
40526
+ m_colorTableOrig = val;
40527
+
40528
+ if (val.length < 4) {
40529
+ val = [0, 0, 0, 0];
40530
+ }
40531
+
40532
+ m_this.width = Math.min(m_maxWidth, val.length / 4);
40533
+ m_this.height = Math.ceil(val.length / 4 / m_maxWidth);
40534
+
40535
+ if (!(val instanceof Uint8Array) || val.length !== m_this.width * m_this.height * 4) {
40536
+ if (val.length < m_this.width * m_this.height * 4) {
40537
+ val = val.concat(new Array(m_this.width * m_this.height * 4 - val.length).fill(0));
40538
+ }
40539
+
40540
+ m_colorTable = new Uint8Array(val);
40541
+ } else {
40542
+ m_colorTable = val;
40543
+ }
40544
+
40545
+ m_this.modified();
40546
+ return m_this;
40547
+ };
40548
+ /**
40549
+ * Get maxWidth value.
40550
+ *
40551
+ * @returns {number} The maxWidth of the texture used.
40552
+ */
40553
+
40554
+
40555
+ this.maxWidth = function () {
40556
+ return m_maxWidth;
40557
+ };
40558
+
40559
+ this.colorTable(arg.colorTable || []);
40560
+ return this;
40561
+ };
40562
+
40563
+ inherit(webgl_lookupTable2D, vgl.texture);
40564
+ module.exports = webgl_lookupTable2D;
40565
+
40566
+ /***/ }),
40567
+
40185
40568
  /***/ 1848:
40186
40569
  /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
40187
40570
 
@@ -40296,7 +40679,7 @@ var webgl_markerFeature = function webgl_markerFeature(arg) {
40296
40679
  /**
40297
40680
  * Create and style the data needed to render the markers.
40298
40681
  *
40299
- @param {boolean} onlyStyle if true, use the existing geometry and just
40682
+ @param {boolean} [onlyStyle] if true, use the existing geometry and just
40300
40683
  * recalculate the style.
40301
40684
  */
40302
40685
 
@@ -41121,6 +41504,247 @@ module.exports = webgl_object;
41121
41504
 
41122
41505
  /***/ }),
41123
41506
 
41507
+ /***/ 9685:
41508
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
41509
+
41510
+ var inherit = __webpack_require__(5699);
41511
+
41512
+ var registerFeature = (__webpack_require__(4647).registerFeature);
41513
+
41514
+ var pixelmapFeature = __webpack_require__(6374);
41515
+
41516
+ var lookupTable2D = __webpack_require__(8672);
41517
+
41518
+ var util = __webpack_require__(4634);
41519
+ /**
41520
+ * Create a new instance of class webgl.pixelmapFeature.
41521
+ *
41522
+ * @class
41523
+ * @alias geo.webgl.pixelmapFeature
41524
+ * @extends geo.pixelmapFeature
41525
+ * @param {geo.pixelmapFeature.spec} arg
41526
+ * @returns {geo.webgl.pixelmapFeature}
41527
+ */
41528
+
41529
+
41530
+ var webgl_pixelmapFeature = function webgl_pixelmapFeature(arg) {
41531
+ 'use strict';
41532
+
41533
+ if (!(this instanceof webgl_pixelmapFeature)) {
41534
+ return new webgl_pixelmapFeature(arg);
41535
+ }
41536
+
41537
+ pixelmapFeature.call(this, arg);
41538
+
41539
+ var object = __webpack_require__(7719);
41540
+
41541
+ object.call(this);
41542
+
41543
+ var vgl = __webpack_require__(320);
41544
+
41545
+ var fragmentShader = __webpack_require__(3953);
41546
+
41547
+ var m_quadFeature,
41548
+ m_quadFeatureInit,
41549
+ s_exit = this._exit,
41550
+ m_lookupTable,
41551
+ m_this = this;
41552
+ /**
41553
+ * If the specified coordinates are in the rendered quad, use the basis
41554
+ * information from the quad to determine the pixelmap index value so that it
41555
+ * can be included in the `found` results.
41556
+ *
41557
+ * @param {geo.geoPosition} geo Coordinate.
41558
+ * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use
41559
+ * the interface gcs, `null` to use the map gcs, or any other transform.
41560
+ * @returns {geo.feature.searchResult} An object with a list of features and
41561
+ * feature indices that are located at the specified point.
41562
+ */
41563
+
41564
+ this.pointSearch = function (geo, gcs) {
41565
+ if (m_quadFeature && m_this.m_info) {
41566
+ var result = m_quadFeature.pointSearch(geo, gcs); // use the last index by preference, since for tile layers, this is the
41567
+ // topmosttile
41568
+
41569
+ var idxIdx = result.index.length - 1;
41570
+
41571
+ for (; idxIdx >= 0; idxIdx -= 1) {
41572
+ if (result.extra[result.index[idxIdx]]._quad && result.extra[result.index[idxIdx]]._quad.image) {
41573
+ var img = result.extra[result.index[idxIdx]]._quad.image;
41574
+ var basis = result.extra[result.index[idxIdx]].basis;
41575
+ var x = Math.floor(basis.x * img.width);
41576
+ var y = Math.floor(basis.y * img.height);
41577
+ var canvas = document.createElement('canvas');
41578
+ canvas.width = canvas.height = 1;
41579
+ var context = canvas.getContext('2d');
41580
+ context.drawImage(img, x, y, 1, 1, 0, 0, 1, 1);
41581
+ var pixel = context.getImageData(0, 0, 1, 1).data;
41582
+ var idx = pixel[0] + pixel[1] * 256 + pixel[2] * 256 * 256;
41583
+ result = {
41584
+ index: [idx],
41585
+ found: [m_this.data()[idx]]
41586
+ };
41587
+ return result;
41588
+ }
41589
+ }
41590
+ }
41591
+
41592
+ return {
41593
+ index: [],
41594
+ found: []
41595
+ };
41596
+ };
41597
+ /**
41598
+ * Given the loaded pixelmap image, create a texture for the colors and a
41599
+ * quad that will use it.
41600
+ */
41601
+
41602
+
41603
+ this._computePixelmap = function () {
41604
+ var data = m_this.data() || [],
41605
+ colorFunc = m_this.style.get('color');
41606
+ var indexRange = m_this.indexModified(undefined, 'clear');
41607
+ var fullUpdate = m_this.dataTime().timestamp() >= m_this.buildTime().timestamp() || indexRange === undefined;
41608
+
41609
+ if (!m_lookupTable) {
41610
+ m_lookupTable = lookupTable2D();
41611
+ m_lookupTable.setTextureUnit(1);
41612
+ fullUpdate = true;
41613
+ }
41614
+
41615
+ var clrLen = Math.max(1, data.length);
41616
+ var maxWidth = m_lookupTable.maxWidth();
41617
+
41618
+ if (clrLen > maxWidth && clrLen % maxWidth) {
41619
+ clrLen += maxWidth - clrLen % maxWidth;
41620
+ }
41621
+
41622
+ var colors;
41623
+
41624
+ if (!fullUpdate) {
41625
+ colors = m_lookupTable.colorTable();
41626
+ fullUpdate = colors.length !== clrLen * 4;
41627
+ indexRange[0] = Math.max(0, indexRange[0]);
41628
+ indexRange[1] = Math.min(data.length, indexRange[1] + 1);
41629
+ }
41630
+
41631
+ if (fullUpdate) {
41632
+ colors = new Uint8Array(clrLen * 4);
41633
+ indexRange = [0, data.length];
41634
+ }
41635
+
41636
+ for (var i = indexRange[0]; i < indexRange[1]; i += 1) {
41637
+ var d = data[i];
41638
+ var color = util.convertColor(colorFunc.call(m_this, d, i));
41639
+ colors[i * 4] = color.r * 255;
41640
+ colors[i * 4 + 1] = color.g * 255;
41641
+ colors[i * 4 + 2] = color.b * 255;
41642
+ colors[i * 4 + 3] = color.a === undefined ? 255 : color.a * 255;
41643
+ }
41644
+
41645
+ m_this.m_info = {
41646
+ colors: colors
41647
+ }; // check if colors haven't changed
41648
+
41649
+ var oldcolors = m_lookupTable.colorTable();
41650
+
41651
+ if (oldcolors && oldcolors.length === colors.length) {
41652
+ var idx = indexRange[0] * 4;
41653
+
41654
+ for (; idx < indexRange[1] * 4; idx += 1) {
41655
+ if (colors[idx] !== oldcolors[idx]) {
41656
+ break;
41657
+ }
41658
+ }
41659
+
41660
+ if (idx === indexRange[1] * 4) {
41661
+ return;
41662
+ }
41663
+ }
41664
+
41665
+ m_lookupTable.colorTable(colors);
41666
+ /* If we haven't made a quad feature, make one now */
41667
+
41668
+ if (!m_quadFeature) {
41669
+ m_quadFeature = m_this.layer().createFeature('quad', {
41670
+ selectionAPI: false,
41671
+ gcs: m_this.gcs(),
41672
+ visible: m_this.visible(undefined, true)
41673
+ });
41674
+ m_quadFeatureInit = false;
41675
+ }
41676
+
41677
+ if (!m_quadFeatureInit) {
41678
+ m_this.dependentFeatures([m_quadFeature]);
41679
+ m_quadFeature.setShader('image_fragment', fragmentShader);
41680
+
41681
+ m_quadFeature._hookBuild = function (prog) {
41682
+ var lutSampler = new vgl.uniform(vgl.GL.INT, 'lutSampler');
41683
+ lutSampler.set(m_lookupTable.textureUnit());
41684
+ prog.addUniform(lutSampler);
41685
+ var lutWidth = new vgl.uniform(vgl.GL.INT, 'lutWidth');
41686
+ lutWidth.set(m_lookupTable.width);
41687
+ prog.addUniform(lutWidth);
41688
+ var lutHeight = new vgl.uniform(vgl.GL.INT, 'lutHeight');
41689
+ lutHeight.set(m_lookupTable.height);
41690
+ prog.addUniform(lutHeight);
41691
+ };
41692
+
41693
+ m_quadFeature._hookRenderImageQuads = function (renderState, quads) {
41694
+ quads.forEach(function (quad) {
41695
+ if (quad.image && quad.texture && !quad.texture.nearestPixel()) {
41696
+ quad.texture.setNearestPixel(true);
41697
+ }
41698
+ });
41699
+ m_lookupTable.bind(renderState, quads);
41700
+ };
41701
+
41702
+ if (m_quadFeatureInit === false) {
41703
+ m_quadFeature.style({
41704
+ image: m_this.m_srcImage,
41705
+ position: m_this.style.get('position')
41706
+ }).data([{}]).draw();
41707
+ }
41708
+
41709
+ m_quadFeatureInit = true;
41710
+ }
41711
+ };
41712
+ /**
41713
+ * Destroy. Deletes the associated quadFeature.
41714
+ *
41715
+ * @returns {this}
41716
+ */
41717
+
41718
+
41719
+ this._exit = function () {
41720
+ if (m_quadFeature && m_this.layer()) {
41721
+ m_this.layer().deleteFeature(m_quadFeature);
41722
+ m_quadFeature = null;
41723
+ m_this.dependentFeatures([]);
41724
+ }
41725
+
41726
+ s_exit();
41727
+ return m_this;
41728
+ };
41729
+
41730
+ if (arg.quadFeature) {
41731
+ m_quadFeature = arg.quadFeature;
41732
+ }
41733
+
41734
+ this._init(arg);
41735
+
41736
+ return this;
41737
+ };
41738
+
41739
+ inherit(webgl_pixelmapFeature, pixelmapFeature); // Now register it
41740
+
41741
+ var capabilities = {};
41742
+ capabilities[pixelmapFeature.capabilities.lookup] = true;
41743
+ registerFeature('webgl', 'pixelmap', webgl_pixelmapFeature, capabilities);
41744
+ module.exports = webgl_pixelmapFeature;
41745
+
41746
+ /***/ }),
41747
+
41124
41748
  /***/ 5675:
41125
41749
  /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
41126
41750
 
@@ -41216,7 +41840,7 @@ var webgl_pointFeature = function webgl_pointFeature(arg) {
41216
41840
  /**
41217
41841
  * Create and style the data needed to render the points.
41218
41842
  *
41219
- * @param {boolean} onlyStyle if true, use the existing geometry and just
41843
+ * @param {boolean} [onlyStyle] if true, use the existing geometry and just
41220
41844
  * recalculate the style.
41221
41845
  */
41222
41846
 
@@ -42485,7 +43109,7 @@ var webgl_quadFeature = function webgl_quadFeature(arg) {
42485
43109
 
42486
43110
 
42487
43111
  this._build = function () {
42488
- var mapper, mat, prog, srctex, unicrop, unicropsource, geom, context;
43112
+ var mapper, mat, prog, srctex, unicrop, unicropsource, geom, context, sampler2d;
42489
43113
 
42490
43114
  if (!m_this.position()) {
42491
43115
  return;
@@ -42510,6 +43134,11 @@ var webgl_quadFeature = function webgl_quadFeature(arg) {
42510
43134
  prog.addUniform(new vgl.projectionUniform('projectionMatrix'));
42511
43135
  prog.addUniform(new vgl.floatUniform('opacity', 1.0));
42512
43136
  prog.addUniform(new vgl.floatUniform('zOffset', 0.0));
43137
+ /* Use texture unit 0 */
43138
+
43139
+ sampler2d = new vgl.uniform(vgl.GL.INT, 'sampler2d');
43140
+ sampler2d.set(0);
43141
+ prog.addUniform(sampler2d);
42513
43142
  context = m_this.renderer()._glContext();
42514
43143
  unicrop = new vgl.uniform(context.FLOAT_VEC2, 'crop');
42515
43144
  unicrop.set([1.0, 1.0]);
@@ -42519,6 +43148,11 @@ var webgl_quadFeature = function webgl_quadFeature(arg) {
42519
43148
  prog.addUniform(unicropsource);
42520
43149
  prog.addShader(vgl.getCachedShader(context.VERTEX_SHADER, context, vertexShaderImage));
42521
43150
  prog.addShader(vgl.getCachedShader(context.FRAGMENT_SHADER, context, fragmentShaderImage));
43151
+
43152
+ if (m_this._hookBuild) {
43153
+ m_this._hookBuild(prog);
43154
+ }
43155
+
42522
43156
  mat.addAttribute(prog);
42523
43157
  mat.addAttribute(new vgl.blend());
42524
43158
  /* This is similar to vgl.planeSource */
@@ -42695,15 +43329,21 @@ var webgl_quadFeature = function webgl_quadFeature(arg) {
42695
43329
  h,
42696
43330
  quadw,
42697
43331
  quadh;
43332
+
43333
+ if (m_this._hookRenderImageQuads) {
43334
+ m_this._hookRenderImageQuads(renderState, m_quads.imgQuads);
43335
+ }
43336
+
42698
43337
  context.bindBuffer(context.ARRAY_BUFFER, m_glBuffers.imgQuadsPosition);
42699
43338
  $.each(m_quads.imgQuads, function (idx, quad) {
42700
43339
  if (!quad.image) {
42701
43340
  return;
42702
43341
  }
42703
43342
 
42704
- quad.texture.bind(renderState);
43343
+ quad.texture.bind(renderState); // only check if the context is out of memory when using modestly large
43344
+ // textures. The check is slow.
42705
43345
 
42706
- if (context.getError() === context.OUT_OF_MEMORY) {
43346
+ if ((quad.image.width > 4096 || quad.image.height > 4096 || quad.image.width * quad.image.height > 4194304) && context.getError() === context.OUT_OF_MEMORY) {
42707
43347
  console.log('Insufficient GPU memory for texture');
42708
43348
  }
42709
43349
 
@@ -42811,6 +43451,41 @@ var webgl_quadFeature = function webgl_quadFeature(arg) {
42811
43451
 
42812
43452
  m_this.modified();
42813
43453
  };
43454
+ /**
43455
+ * Set the image or color vertex or fragment shader.
43456
+ *
43457
+ * @param {string} shaderType One of `image_vertex`, `image_fragment`,
43458
+ * `color_vertex`, or `color_fragment`.
43459
+ * @param {string} shaderCode The shader program.
43460
+ * @returns {this} The class instance on success, undefined in an unknown
43461
+ * shaderType was specified.
43462
+ */
43463
+
43464
+
43465
+ this.setShader = function (shaderType, shaderCode) {
43466
+ switch (shaderType) {
43467
+ case 'image_vertex':
43468
+ vertexShaderImage = shaderCode;
43469
+ break;
43470
+
43471
+ case 'image_fragment':
43472
+ fragmentShaderImage = shaderCode;
43473
+ break;
43474
+
43475
+ case 'color_vertex':
43476
+ vertexShaderColor = shaderCode;
43477
+ break;
43478
+
43479
+ case 'color_fragment':
43480
+ fragmentShaderColor = shaderCode;
43481
+ break;
43482
+
43483
+ default:
43484
+ return;
43485
+ }
43486
+
43487
+ return m_this;
43488
+ };
42814
43489
  /**
42815
43490
  * Destroy.
42816
43491
  */
@@ -43524,6 +44199,8 @@ webglRenderer.supported = function () {
43524
44199
 
43525
44200
  try {
43526
44201
  canvas = document.createElement('canvas');
44202
+ /** @type {WebGLRenderingContext} */
44203
+
43527
44204
  ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
43528
44205
  /* getSupportExtensions will throw an exception if the context isn't
43529
44206
  * really supported. */
@@ -93891,6 +94568,13 @@ module.exports = "/* contourFeature vertex shader */\n\n#ifdef GL_ES\n precisio
93891
94568
 
93892
94569
  /***/ }),
93893
94570
 
94571
+ /***/ 3953:
94572
+ /***/ (function(module) {
94573
+
94574
+ module.exports = "/* pixelmapFeature fragment shader */\n\nvarying highp vec2 iTextureCoord;\nuniform sampler2D sampler2d;\nuniform sampler2D lutSampler;\nuniform int lutWidth;\nuniform int lutHeight;\nuniform mediump float opacity;\nuniform highp vec2 crop;\n\nvoid main(void) {\n if ((crop.s < 1.0 && iTextureCoord.s > crop.s) || (crop.t < 1.0 && 1.0 - iTextureCoord.t > crop.t)) {\n discard;\n }\n // to add anti-aliasing, we would need to know the current pixel size\n // (probably computed in the vertex shader) and then sample the base image at\n // multiple points, then average the output color.\n highp vec4 lutValue = texture2D(sampler2d, iTextureCoord);\n highp vec2 lutCoord;\n lutCoord.s = (\n mod(\n // add 0.5 to handle float imprecision\n floor(lutValue.r * 255.0 + 0.5) +\n floor(lutValue.g * 255.0 + 0.5) * 256.0,\n float(lutWidth)\n // center in pixel\n ) + 0.5) / float(lutWidth);\n // Our image is top-down, so invert the coordinate\n lutCoord.t = 1.0 - (\n floor(\n (\n // add 0.5 to handle float imprecision\n floor(lutValue.r * 255.0 + 0.5) +\n floor(lutValue.g * 255.0 + 0.5) * 256.0 +\n floor(lutValue.b * 255.0 + 0.5) * 256.0 * 256.0\n // We may want an option to use the alpha channel to allow more indices\n ) / float(lutWidth)\n // center in pixel\n ) + 0.5) / float(lutHeight);\n if (lutCoord.t < 0.0) {\n discard;\n }\n mediump vec4 color = texture2D(lutSampler, lutCoord);\n\n color.a *= opacity;\n gl_FragColor = color;\n}\n"
94575
+
94576
+ /***/ }),
94577
+
93894
94578
  /***/ 1815:
93895
94579
  /***/ (function(module) {
93896
94580