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
@@ -565,9 +565,9 @@ var polygonFeature = function (arg) {
565
565
  *
566
566
  * @param {array} data A new data array.
567
567
  * @param {number} [tolerance] The maximum variation allowed in map.gcs
568
- * units. A value of zero will only remove perfectly colinear points. If
569
- * not specified, this is set to a half display pixel at the map's current
570
- * zoom level.
568
+ * units. A value of zero will only remove perfectly collinear points.
569
+ * If not specified, this is set to a half display pixel at the map's
570
+ * current zoom level.
571
571
  * @param {function} [posFunc=this.style.get('position')] The function to
572
572
  * get the position of each vertex.
573
573
  * @param {function} [polyFunc=this.style.get('polygon')] The function to
@@ -232,7 +232,7 @@ var quadFeature = function (arg) {
232
232
  coordbasis.y = 1 - coordbasis.y;
233
233
  }
234
234
  if (coordbasis) {
235
- extra[quad.idx] = {basis: coordbasis};
235
+ extra[quad.idx] = {basis: coordbasis, _quad: quad};
236
236
  }
237
237
  }
238
238
  });
package/src/registry.js CHANGED
@@ -60,7 +60,7 @@ util.registerRenderer = function (name, func) {
60
60
  * @param {geo.layer} layer The layer associated with the renderer.
61
61
  * @param {HTMLCanvasElement} [canvas] A canvas object to share between
62
62
  * renderers.
63
- * @param {object} options Options for the new renderer.
63
+ * @param {object} [options] Options for the new renderer.
64
64
  * @returns {geo.renderer|null} The new renderer or null if no such name is
65
65
  * registered.
66
66
  */
@@ -83,7 +83,7 @@ util.createRenderer = function (name, layer, canvas, options) {
83
83
  *
84
84
  * @alias geo.checkRenderer
85
85
  * @param {string|null} name Name of the desired renderer.
86
- * @param {boolean} noFallback If truthy, don't recommend a fallback.
86
+ * @param {boolean} [noFallback] If truthy, don't recommend a fallback.
87
87
  * @returns {string|null|false} The name of the renderer that should be used
88
88
  * or false if no valid renderer can be determined.
89
89
  */
@@ -484,10 +484,10 @@ var svgRenderer = function (arg) {
484
484
  * Create a new feature element from an object that describes the feature
485
485
  * attributes. To be called from feature classes only.
486
486
  *
487
- * @param {object} arg Options for the features.
487
+ * @param {object} arg
488
488
  * @param {string} arg.id A unique string identifying the feature.
489
489
  * @param {array} arg.data Array of data objects used in a d3 data method.
490
- * @param {function} [aeg.dataIndex] A function that returns a unique id for
490
+ * @param {function} [arg.dataIndex] A function that returns a unique id for
491
491
  * each data element. This is passed to the data access function.
492
492
  * @param {object} arg.style An object with style values or functions.
493
493
  * @param {object} arg.attributes An object containing element attributes.
@@ -500,7 +500,7 @@ var svgRenderer = function (arg) {
500
500
  * attributes and styles set when new. If falsy, features always have
501
501
  * attributes and styles updated.
502
502
  * @param {boolean} [arg.sortByZ] If truthy, sort features by the `d.zIndex`.
503
- * @param {string} [parentId] If set, the group ID of the parent element.
503
+ * @param {string} [arg.parentId] If set, the group ID of the parent element.
504
504
  * @returns {this}
505
505
  */
506
506
  this._drawFeatures = function (arg) {
package/src/tileCache.js CHANGED
@@ -55,7 +55,7 @@ var tileCache = function (options) {
55
55
  * Remove a tile from the cache.
56
56
  *
57
57
  * @param {string|geo.tile} tile The tile or its hash.
58
- * @returns {booliean} `true` if a tile was removed.
58
+ * @returns {boolean} `true` if a tile was removed.
59
59
  */
60
60
  this.remove = function (tile) {
61
61
  var hash = typeof tile === 'string' ? tile : tile.toString();
package/src/tileLayer.js CHANGED
@@ -525,7 +525,7 @@ var tileLayer = function (arg) {
525
525
  /**
526
526
  * Returns a tile's bounds in a gcs.
527
527
  *
528
- * @param {object|tile} indexOrTile Either a tile or an object with
528
+ * @param {object|geo.tile} indexOrTile Either a tile or an object with
529
529
  * {x, y, level}` specifying a tile.
530
530
  * @param {string|geo.transform|null} [gcs] `undefined` to use the
531
531
  * interface gcs, `null` to use the map gcs, or any other transform.
@@ -668,7 +668,7 @@ var tileLayer = function (arg) {
668
668
  * @param {number} maxLevel The zoom level
669
669
  * @param {geo.geoBounds} bounds The map bounds
670
670
  * @param {boolean} sorted Return a sorted list
671
- * @param {boolean} onlyIfChanged If the set of tiles have not changed
671
+ * @param {boolean} [onlyIfChanged] If the set of tiles have not changed
672
672
  * (even if their desired order has), return undefined instead of an
673
673
  * array of tiles.
674
674
  * @returns {geo.tile[]} An array of tile objects
@@ -676,7 +676,7 @@ var tileLayer = function (arg) {
676
676
  this._getTiles = function (maxLevel, bounds, sorted, onlyIfChanged) {
677
677
  var i, j, tiles = [], index, nTilesLevel,
678
678
  start, end, indexRange, source, center, changed = false, old, level,
679
- minLevel = (m_this._options.keepLower ? m_this._options.minLevel : maxLevel);
679
+ minLevel = (m_this._options.keepLower ? m_this._options.minLevel : Math.max(maxLevel, m_this._options.minLevel));
680
680
  if (maxLevel < minLevel) {
681
681
  maxLevel = minLevel;
682
682
  }
@@ -1134,7 +1134,7 @@ var tileLayer = function (arg) {
1134
1134
  * origin.
1135
1135
  *
1136
1136
  * @param {object} pt A point in world space coordinates with `x` and `y`.
1137
- * @param {number|undefined} zoom If unspecified, use the map zoom.
1137
+ * @param {number} [zoom] If unspecified, use the map zoom.
1138
1138
  * @returns {object} Local coordinates with `x` and `y`.
1139
1139
  */
1140
1140
  this.toLocal = function (pt, zoom) {
@@ -1180,7 +1180,7 @@ var tileLayer = function (arg) {
1180
1180
  * create the element if it doesn't already exist.
1181
1181
  *
1182
1182
  * @param {number} level The zoom level of the layer to fetch.
1183
- * @returns {DOM} The layer's DOM element.
1183
+ * @returns {HTMLElement} The layer's DOM element.
1184
1184
  */
1185
1185
  this._getSubLayer = function (level) {
1186
1186
  if (!m_this.canvas()) {
@@ -1512,8 +1512,8 @@ var tileLayer = function (arg) {
1512
1512
  * @param {geo.geoBounds} [bounds] The view bounds (if unspecified, assume
1513
1513
  * global bounds)
1514
1514
  * @param {number} bounds.level The zoom level the bounds are given as.
1515
- * @param {number} zoom Keep in bound tile at this zoom level.
1516
- * @param {boolean} doneLoading If true, allow purging additional tiles.
1515
+ * @param {number} [zoom] Keep in bound tile at this zoom level.
1516
+ * @param {boolean} [doneLoading] If true, allow purging additional tiles.
1517
1517
  * @returns {boolean}
1518
1518
  */
1519
1519
  this._canPurge = function (tile, bounds, zoom, doneLoading) {
@@ -1532,7 +1532,8 @@ var tileLayer = function (arg) {
1532
1532
  * finished, purge all but the current layer. This is important for
1533
1533
  * semi-transparent layers. */
1534
1534
  if ((doneLoading || m_this._isCovered(tile)) &&
1535
- zoom !== tile.index.level) {
1535
+ zoom !== tile.index.level &&
1536
+ (zoom >= m_this._options.minLevel || tile.index.level !== m_this._options.minLevel)) {
1536
1537
  return true;
1537
1538
  }
1538
1539
  }
@@ -1604,9 +1605,9 @@ var tileLayer = function (arg) {
1604
1605
  /**
1605
1606
  * Get or set the subdomains used for templating.
1606
1607
  *
1607
- * @param {string|list} [subdomains] A comma-separated list, a string of
1608
+ * @param {string|string[]} [subdomains] A comma-separated list, a string of
1608
1609
  * single character subdomains, or a list.
1609
- * @returns {string|list|this}
1610
+ * @returns {string|string[]|this}
1610
1611
  */
1611
1612
  this.subdomains = function (subdomains) {
1612
1613
  if (subdomains === undefined) {
@@ -1644,8 +1645,8 @@ var tileLayer = function (arg) {
1644
1645
  /**
1645
1646
  * Get/Set visibility of the layer.
1646
1647
  *
1647
- * @param {boolean|undefined} val If unspecified, return the visibility,
1648
- * otherwise set it.
1648
+ * @param {boolean} [val] If unspecified, return the visibility, otherwise
1649
+ * set it.
1649
1650
  * @returns {boolean|this} Either the visibility (if getting) or the layer
1650
1651
  * (if setting).
1651
1652
  */
@@ -10,24 +10,24 @@ var util = require('./util');
10
10
  * @extends geo.feature.spec
11
11
  * @property {geo.geoPosition|function} [position] Position of the data.
12
12
  * Default is (data).
13
- * @property {float|function} [time] Time of the data. Default is `(data).t`.
13
+ * @property {number|function} [time] Time of the data. Default is `(data).t`.
14
14
  * @property {object|function} [track] Tracks from the data. Default is
15
15
  * (data). Typically, the data is an array of tracks, each of which is an
16
16
  * array of points, each of which has a position and time. The position and
17
17
  * time functions are called for each point as `position(trackPoint,
18
18
  * pointIndex, trackEntry, trackEntryIndex)`.
19
- * @property {float|null} [startTime=null] Start time. Used for styling. If
19
+ * @property {number|null} [startTime=null] Start time. Used for styling. If
20
20
  * `null`, this is the duration before the end time if `duration` is not
21
21
  * `null` and the minimum time in any track if `duration` is `null`.
22
- * @property {float} [endTime=null] End time. Used for styling and position of
23
- * the track head. If `null` and either of `startTime` or `duration` are
22
+ * @property {number} [endTime=null] End time. Used for styling and position
23
+ * of the track head. If `null` and either of `startTime` or `duration` are
24
24
  * `null`, this is the maximum time in any track.
25
- * @property {float} [duration=null] Duration between start and end times.
25
+ * @property {number} [duration=null] Duration between start and end times.
26
26
  * Ignored if both start and end times are specified.
27
- * @property {float|function} [text] Text to use for the head of the track. If
28
- * specified, the track head is rendered as text. If `undefined` a marker is
29
- * used instead. If `null` or an empty string (`''`), neither a marker nor
30
- * text is used.
27
+ * @property {number|function} [text] Text to use for the head of the track.
28
+ * If specified, the track head is rendered as text. If `undefined` a marker
29
+ * is used instead. If `null` or an empty string (`''`), neither a marker
30
+ * nor text is used.
31
31
  * @property {geo.trackFeature.styleSpec} [style] Style object with default
32
32
  * style options.
33
33
  * @property {geo.lineFeature.styleSpec} [pastStyle] Style object with
@@ -168,7 +168,7 @@ var trackFeature = function (arg) {
168
168
  * Calculate an interpolated position given a time. If the time is outside
169
169
  * the range of a track, the first or last point is returned.
170
170
  *
171
- * @param {float} time The time to compute a position array for.
171
+ * @param {number} time The time to compute a position array for.
172
172
  * @param {string|geo.transform|null} [gcs] `undefined` to use the feature
173
173
  * gcs, `null` to use the map gcs, or any other transform. This transform
174
174
  * is used for the interpolation; the results are still in feature gcs.
@@ -275,8 +275,8 @@ var trackFeature = function (arg) {
275
275
  m_tracks.textFunc = m_this.style.get('text');
276
276
  ['past', 'current', 'future'].forEach(key => {
277
277
  m_lineFeatures[key]
278
- .style(m_this[key + 'Style']())
279
278
  .style(m_this.style())
279
+ .style(m_this[key + 'Style']())
280
280
  .line(m_this.style('track'))
281
281
  .gcs(m_this.gcs())
282
282
  .data(data)
@@ -571,11 +571,11 @@ var trackFeature = function (arg) {
571
571
  /**
572
572
  * Get/Set time accessor.
573
573
  *
574
- * @param {float} [val] If not specified, return the current time accessor.
574
+ * @param {number} [val] If not specified, return the current time accessor.
575
575
  * If specified, use this for the time accessor and return `this`. If a
576
576
  * function is given, this is called with `(vertexElement, vertexIndex,
577
577
  * dataElement, dataIndex)`.
578
- * @returns {float|function|this} The current time or this feature.
578
+ * @returns {number|function|this} The current time or this feature.
579
579
  */
580
580
  this.time = function (val) {
581
581
  if (val === undefined) {
@@ -636,8 +636,8 @@ var trackFeature = function (arg) {
636
636
  /**
637
637
  * Get or set the start time.
638
638
  *
639
- * @param {float|null} [val] If specified, the new start time.
640
- * @returns {float|null|this} If set, the instance. Otherwise, the current
639
+ * @param {number|null} [val] If specified, the new start time.
640
+ * @returns {number|null|this} If set, the instance. Otherwise, the current
641
641
  * start time value.
642
642
  */
643
643
  this.startTime = function (val) {
@@ -654,8 +654,8 @@ var trackFeature = function (arg) {
654
654
  /**
655
655
  * Get or set the end time.
656
656
  *
657
- * @param {float|null} [val] If specified, the new end time.
658
- * @returns {float|null|this} If set, the instance. Otherwise, the current
657
+ * @param {number|null} [val] If specified, the new end time.
658
+ * @returns {number|null|this} If set, the instance. Otherwise, the current
659
659
  * end time value.
660
660
  */
661
661
  this.endTime = function (val) {
@@ -672,8 +672,8 @@ var trackFeature = function (arg) {
672
672
  /**
673
673
  * Get or set the duration.
674
674
  *
675
- * @param {float|null} [val] If specified, the new duration.
676
- * @returns {float|null|this} If set, the instance. Otherwise, the current
675
+ * @param {number|null} [val] If specified, the new duration.
676
+ * @returns {number|null|this} If set, the instance. Otherwise, the current
677
677
  * duration.
678
678
  */
679
679
  this.duration = function (val) {
package/src/transform.js CHANGED
@@ -330,11 +330,12 @@ transform.lookup = function (projection) {
330
330
  *
331
331
  * @param {string} srcPrj The source projection.
332
332
  * @param {string} tgtPrj The destination projection.
333
- * @param {geoPosition|geoPosition[]|number[]} coordinates An array of
334
- * coordinate objects. These may be in object or array form, or a flat
335
- * array.
336
- * @param {number} numberOfComponents For flat arrays, either 2 or 3.
337
- * @returns {geoPosition|geoPosition[]|number[]} The transformed coordinates.
333
+ * @param {geo.geoPosition|geo.geoPosition[]|number[]} coordinates An array of
334
+ * coordinate objects. These may be in object or array form, or a flat
335
+ * array.
336
+ * @param {number} [numberOfComponents] For flat arrays, either 2 or 3.
337
+ * @returns {geo.geoPosition|geo.geoPosition[]|number[]} The transformed
338
+ * coordinates.
338
339
  */
339
340
  transform.transformCoordinates = function (srcPrj, tgtPrj, coordinates, numberOfComponents) {
340
341
  'use strict';
@@ -385,10 +386,10 @@ transform.transformCoordinates = function (srcPrj, tgtPrj, coordinates, numberOf
385
386
  * components per coordinate. The array is modified in place.
386
387
  *
387
388
  * @param {transform} trans The transformation object.
388
- * @param {geoPosition[]|number[]} coordinates An array of coordinate
389
+ * @param {geo.geoPosition[]|number[]} coordinates An array of coordinate
389
390
  * objects or a flat array.
390
391
  * @param {number} numberOfComponents For flat arrays, either 2 or 3.
391
- * @returns {geoPosition[]|number[]} The transformed coordinates
392
+ * @returns {geo.geoPosition[]|number[]} The transformed coordinates
392
393
  */
393
394
  transform.transformCoordinatesArray = function (trans, coordinates, numberOfComponents) {
394
395
  var i, count, offset, xAcc, yAcc, zAcc, writer, output, projPoint,
@@ -654,8 +655,6 @@ transform.affineInverse = function (def, coords) {
654
655
  * @param {object} [ellipsoid=proj4.WGS84] An object with at least `a` and one
655
656
  * of `b`, `f`, or `rf` (1 / `f`) -- this works with proj4 ellipsoid
656
657
  * definitions.
657
- * @param {number} [maxIterations=100] Maximum number of iterations to use
658
- * to test convergence.
659
658
  * @returns {number} The distance in meters (or whatever units the ellipsoid
660
659
  * was specified in.
661
660
  */
package/src/typedef.js CHANGED
@@ -234,3 +234,5 @@
234
234
  *
235
235
  * @typedef {geo.polygonFlat|geo.polygonObject} geo.polygon
236
236
  */
237
+
238
+ module.exports = {};
@@ -203,7 +203,7 @@ var sliderWidget = function (arg) {
203
203
  * Respond to a mouse event on the widget.
204
204
  *
205
205
  * @param {d3Event} evt The event on the widget.
206
- * @param {boolean} trans Truthy for an animated transition.
206
+ * @param {boolean} [trans] Truthy for an animated transition.
207
207
  */
208
208
  function respond(evt, trans) {
209
209
  var z = m_yscale.invert(d3.mouse(svg.node())[1]),
@@ -18,7 +18,7 @@ var $ = require('jquery');
18
18
  *
19
19
  * @param {geo.util.ClusterGroup} group The source cluster group
20
20
  * @param {number} zoom The zoom level of the current node
21
- * @param {object[]} children An array of ClusterTrees or point objects
21
+ * @param {object[]} [children] An array of ClusterTrees or point objects
22
22
  */
23
23
  function ClusterTree(group, zoom, children) {
24
24
  this._group = group;
@@ -136,8 +136,8 @@ ClusterTree.prototype.coords = function () {
136
136
  * @class
137
137
  * @alias geo.util.ClusterGroup
138
138
  * @param {object} opts An options object
139
- * @param {number} maxZoom The maximum zoom level to calculate.
140
- * @param {number} radius Size of clustering at zoom 0 in point gcs.
139
+ * @param {number} [opts.maxZoom] The maximum zoom level to calculate.
140
+ * @param {number} [opts.radius] Size of clustering at zoom 0 in point gcs.
141
141
  */
142
142
  function C(opts) {
143
143
 
package/src/util/color.js CHANGED
@@ -59,7 +59,7 @@ var colorName = require('color-name');
59
59
  /**
60
60
  * @typedef {object} geo.util.cssColorConversionRecord
61
61
  * @property {string} name The name of the color conversion.
62
- * @property {RegEx} regex A regex that, if it matches the color string, will
62
+ * @property {RegExp} regex A regex that, if it matches the color string, will
63
63
  * cause the process function to be invoked.
64
64
  * @property {function} process A function that takes (`color`, `match`) with
65
65
  * the original color string and the results of matching the regex using
@@ -128,7 +128,7 @@ var util = {
128
128
  * Check if an object an HTMLVideoElement element that is loaded.
129
129
  *
130
130
  * @param {object} vid An object that might be an HTMLVideoElement.
131
- * @param {boolean} [allowFailedVideo] If `true`, an viedo element that has
131
+ * @param {boolean} [allowFailedVideo] If `true`, an video element that has
132
132
  * a source and has failed to load is also considered 'ready' in the
133
133
  * sense that it isn't expected to change to a better state.
134
134
  * @returns {boolean} `true` if this is a video that is ready.
@@ -525,7 +525,7 @@ var util = {
525
525
  * var map = geo.map($.extend(results.map, {clampZoom: false}));
526
526
  * map.createLayer('osm', results.layer);
527
527
  *
528
- * @param {string} [node] DOM selector for the map container.
528
+ * @param {string?} node DOM selector for the map container.
529
529
  * @param {number} width Width of the whole map contents in pixels.
530
530
  * @param {number} height Height of the whole map contents in pixels.
531
531
  * @param {number} [tileWidth] If an osm or tile layer is going to be used,
@@ -758,7 +758,7 @@ var util = {
758
758
  /**
759
759
  * Determine if two line segments cross. They are not considered crossing if
760
760
  * they share a vertex. They are crossing if either of one segment's
761
- * vertices are colinear with the other segment.
761
+ * vertices are collinear with the other segment.
762
762
  *
763
763
  * @param {geo.geoPosition} seg1pt1 One endpoint of the first segment.
764
764
  * @param {geo.geoPosition} seg1pt2 The other endpoint of the first segment.
@@ -788,7 +788,7 @@ var util = {
788
788
  }
789
789
  /* If the lines cross, the signed area of the triangles formed between one
790
790
  * segment and the other's vertices will have different signs. By using
791
- * > 0, colinear points are crossing. */
791
+ * > 0, collinear points are crossing. */
792
792
  if (util.triangleTwiceSignedArea2d(seg1pt1, seg1pt2, seg2pt1) *
793
793
  util.triangleTwiceSignedArea2d(seg1pt1, seg1pt2, seg2pt2) > 0 ||
794
794
  util.triangleTwiceSignedArea2d(seg2pt1, seg2pt2, seg1pt1) *
@@ -834,7 +834,7 @@ var util = {
834
834
  * @param {geo.geoPosition[]} pts A list of points forming the line or
835
835
  * polygon.
836
836
  * @param {number} tolerance The maximum variation allowed. A value of zero
837
- * will only remove perfectly colinear points.
837
+ * will only remove perfectly collinear points.
838
838
  * @param {boolean} [closed] If true, this is a polygon rather than an open
839
839
  * line. In this case, it is possible to get back a single point.
840
840
  * @param {Array.<geo.geoPosition[]>?} [noCrossLines] A falsy value to allow
@@ -967,7 +967,7 @@ var util = {
967
967
  */
968
968
  escapeUnicodeHTML: function (text) {
969
969
  return text.replace(/./g, function (k) {
970
- var code = k.charCodeAt();
970
+ var code = k.charCodeAt(0);
971
971
  if (code < 127) {
972
972
  return k;
973
973
  }
@@ -1026,7 +1026,7 @@ var util = {
1026
1026
  * stored as local base64 urls.
1027
1027
  *
1028
1028
  * @param {string} css The css to parse for urls.
1029
- * @param {jQuery.selector|DOMElement} styleElem The element that receivs
1029
+ * @param {jQuery.selector|HTMLElement} styleElem The element that receives
1030
1030
  * the css text after dereferencing or the DOM element that has style
1031
1031
  * that will be updated.
1032
1032
  * @param {jQuery.Deferred} styleDefer A Deferred to resolve once
@@ -43,7 +43,7 @@
43
43
  * unspecified, callback will be executed one final time after the last
44
44
  * throttled-function call. (After the throttled-function has not been
45
45
  * called for `delay` milliseconds, the internal counter is reset)
46
- * @param {function} callback A function to be executed after `delay`
46
+ * @param {function} [callback] A function to be executed after `delay`
47
47
  * milliseconds. The `this` context and all arguments are passed through,
48
48
  * as-is, to `callback` when the throttled-function is executed.
49
49
  * @param {function} [accumulator] A function to be executed (synchronously)
@@ -8,8 +8,10 @@ module.exports = {
8
8
  isolineFeature: require('./isolineFeature'),
9
9
  layer: require('./layer'),
10
10
  lineFeature: require('./lineFeature'),
11
+ lookupTable2D: require('./lookupTable2D'),
11
12
  markerFeature: require('./markerFeature'),
12
13
  meshColored: require('./meshColored'),
14
+ pixelmapFeature: require('./pixelmapFeature'),
13
15
  pointFeature: require('./pointFeature'),
14
16
  polygonFeature: require('./polygonFeature'),
15
17
  quadFeature: require('./quadFeature'),
@@ -0,0 +1,122 @@
1
+ var inherit = require('../inherit');
2
+ var timestamp = require('../timestamp');
3
+ var vgl = require('vgl');
4
+
5
+ /**
6
+ * Switch to a specific texture unit.
7
+ *
8
+ * @param {vgl.renderState} renderState An object that contains the context
9
+ * used for drawing.
10
+ * @param {number} textureUnit The number of the texture unit [0-15].
11
+ */
12
+ function activateTextureUnit(renderState, textureUnit) {
13
+ if (textureUnit >= 0 && textureUnit <= 31) {
14
+ renderState.m_context.activeTexture(vgl.GL.TEXTURE0 + textureUnit);
15
+ } else {
16
+ throw Error('[error] Texture unit ' + textureUnit + ' is not supported');
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Create a new instance of class webgl_lookupTable2D.
22
+ *
23
+ * @class
24
+ * @alias geo.webgl.lookupTable2D
25
+ * @param {object} arg Options object.
26
+ * @param {number} [arg.maxWidth] Maximum width to use for the texture. If the
27
+ * number of colors set is less than this, the texture is 1D. If greater, it
28
+ * will be a rectangle of maxWidth x whatever height is necessary.
29
+ * @param {number[]} [arg.colorTable] Initial color table for the texture.
30
+ * This is of the form RGBARGBA... where each value is an integer on the
31
+ * scale [0,255].
32
+ * @extends vgl.texture
33
+ * @returns {geo.webgl.lookupTable2D}
34
+ */
35
+ var webgl_lookupTable2D = function (arg) {
36
+ 'use strict';
37
+
38
+ if (!(this instanceof webgl_lookupTable2D)) {
39
+ return new webgl_lookupTable2D(arg);
40
+ }
41
+ arg = arg || {};
42
+ vgl.texture.call(this);
43
+
44
+ var m_setupTimestamp = timestamp(),
45
+ m_maxWidth = arg.maxWidth || 4096,
46
+ m_colorTable = new Uint8Array([0, 0, 0, 0]),
47
+ m_colorTableOrig,
48
+ m_this = this;
49
+
50
+ /**
51
+ * Create lookup table, initialize parameters, and bind data to it.
52
+ *
53
+ * @param {vgl.renderState} renderState An object that contains the context
54
+ * used for drawing.
55
+ */
56
+ this.setup = function (renderState) {
57
+ activateTextureUnit(renderState, m_this.textureUnit());
58
+
59
+ renderState.m_context.deleteTexture(m_this.m_textureHandle);
60
+ m_this.m_textureHandle = renderState.m_context.createTexture();
61
+ renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, m_this.m_textureHandle);
62
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_MIN_FILTER, vgl.GL.NEAREST);
63
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_MAG_FILTER, vgl.GL.NEAREST);
64
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_WRAP_S, vgl.GL.CLAMP_TO_EDGE);
65
+ renderState.m_context.texParameteri(vgl.GL.TEXTURE_2D, vgl.GL.TEXTURE_WRAP_T, vgl.GL.CLAMP_TO_EDGE);
66
+ renderState.m_context.pixelStorei(vgl.GL.UNPACK_ALIGNMENT, 1);
67
+ renderState.m_context.pixelStorei(vgl.GL.UNPACK_FLIP_Y_WEBGL, true);
68
+
69
+ renderState.m_context.texImage2D(
70
+ vgl.GL.TEXTURE_2D, 0, vgl.GL.RGBA, m_this.width, m_this.height, 0,
71
+ vgl.GL.RGBA, vgl.GL.UNSIGNED_BYTE, m_colorTable);
72
+
73
+ renderState.m_context.bindTexture(vgl.GL.TEXTURE_2D, null);
74
+ m_setupTimestamp.modified();
75
+ };
76
+
77
+ /**
78
+ * Get/set color table.
79
+ *
80
+ * @param {number[]} [val] An array of RGBARGBA... integers on a scale
81
+ * of [0, 255]. `undefined` to get the current value.
82
+ * @returns {number[]|this}
83
+ */
84
+ this.colorTable = function (val) {
85
+ if (val === undefined) {
86
+ return m_colorTableOrig;
87
+ }
88
+ m_colorTableOrig = val;
89
+ if (val.length < 4) {
90
+ val = [0, 0, 0, 0];
91
+ }
92
+ m_this.width = Math.min(m_maxWidth, val.length / 4);
93
+ m_this.height = Math.ceil(val.length / 4 / m_maxWidth);
94
+ if (!(val instanceof Uint8Array) || val.length !== m_this.width * m_this.height * 4) {
95
+ if (val.length < m_this.width * m_this.height * 4) {
96
+ val = val.concat(new Array(m_this.width * m_this.height * 4 - val.length).fill(0));
97
+ }
98
+ m_colorTable = new Uint8Array(val);
99
+ } else {
100
+ m_colorTable = val;
101
+ }
102
+ m_this.modified();
103
+ return m_this;
104
+ };
105
+
106
+ /**
107
+ * Get maxWidth value.
108
+ *
109
+ * @returns {number} The maxWidth of the texture used.
110
+ */
111
+ this.maxWidth = function () {
112
+ return m_maxWidth;
113
+ };
114
+
115
+ this.colorTable(arg.colorTable || []);
116
+
117
+ return this;
118
+ };
119
+
120
+ inherit(webgl_lookupTable2D, vgl.texture);
121
+
122
+ module.exports = webgl_lookupTable2D;
@@ -98,7 +98,7 @@ var webgl_markerFeature = function (arg) {
98
98
  /**
99
99
  * Create and style the data needed to render the markers.
100
100
  *
101
- @param {boolean} onlyStyle if true, use the existing geometry and just
101
+ @param {boolean} [onlyStyle] if true, use the existing geometry and just
102
102
  * recalculate the style.
103
103
  */
104
104
  function createGLMarkers(onlyStyle) {
@@ -0,0 +1,47 @@
1
+ /* pixelmapFeature fragment shader */
2
+
3
+ varying highp vec2 iTextureCoord;
4
+ uniform sampler2D sampler2d;
5
+ uniform sampler2D lutSampler;
6
+ uniform int lutWidth;
7
+ uniform int lutHeight;
8
+ uniform mediump float opacity;
9
+ uniform highp vec2 crop;
10
+
11
+ void main(void) {
12
+ if ((crop.s < 1.0 && iTextureCoord.s > crop.s) || (crop.t < 1.0 && 1.0 - iTextureCoord.t > crop.t)) {
13
+ discard;
14
+ }
15
+ // to add anti-aliasing, we would need to know the current pixel size
16
+ // (probably computed in the vertex shader) and then sample the base image at
17
+ // multiple points, then average the output color.
18
+ highp vec4 lutValue = texture2D(sampler2d, iTextureCoord);
19
+ highp vec2 lutCoord;
20
+ lutCoord.s = (
21
+ mod(
22
+ // add 0.5 to handle float imprecision
23
+ floor(lutValue.r * 255.0 + 0.5) +
24
+ floor(lutValue.g * 255.0 + 0.5) * 256.0,
25
+ float(lutWidth)
26
+ // center in pixel
27
+ ) + 0.5) / float(lutWidth);
28
+ // Our image is top-down, so invert the coordinate
29
+ lutCoord.t = 1.0 - (
30
+ floor(
31
+ (
32
+ // add 0.5 to handle float imprecision
33
+ floor(lutValue.r * 255.0 + 0.5) +
34
+ floor(lutValue.g * 255.0 + 0.5) * 256.0 +
35
+ floor(lutValue.b * 255.0 + 0.5) * 256.0 * 256.0
36
+ // We may want an option to use the alpha channel to allow more indices
37
+ ) / float(lutWidth)
38
+ // center in pixel
39
+ ) + 0.5) / float(lutHeight);
40
+ if (lutCoord.t < 0.0) {
41
+ discard;
42
+ }
43
+ mediump vec4 color = texture2D(lutSampler, lutCoord);
44
+
45
+ color.a *= opacity;
46
+ gl_FragColor = color;
47
+ }