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.
- package/CHANGELOG.md +31 -1
- package/README.md +14 -9
- package/geo.js +1101 -417
- package/geo.lean.js +1101 -417
- package/geo.lean.min.js +3 -3
- package/geo.min.js +5 -5
- package/package.json +6 -8
- package/src/annotation.js +11 -7
- package/src/annotationLayer.js +7 -7
- package/src/camera.js +5 -5
- package/src/canvas/pixelmapFeature.js +208 -0
- package/src/choroplethFeature.js +1 -1
- package/src/domRenderer.js +2 -1
- package/src/featureLayer.js +1 -1
- package/src/fileReader.js +2 -2
- package/src/imageTile.js +2 -1
- package/src/index.js +1 -0
- package/src/isolineFeature.js +1 -1
- package/src/layer.js +4 -2
- package/src/lineFeature.js +3 -3
- package/src/map.js +17 -15
- package/src/mapInteractor.js +17 -17
- package/src/markerFeature.js +2 -2
- package/src/meshFeature.js +1 -1
- package/src/osmLayer.js +2 -0
- package/src/pixelmapFeature.js +97 -249
- package/src/pixelmapLayer.js +145 -0
- package/src/pointFeature.js +1 -1
- package/src/polygonFeature.js +3 -3
- package/src/quadFeature.js +1 -1
- package/src/registry.js +2 -2
- package/src/svg/svgRenderer.js +3 -3
- package/src/tileCache.js +1 -1
- package/src/tileLayer.js +13 -12
- package/src/trackFeature.js +19 -19
- package/src/transform.js +8 -9
- package/src/typedef.js +2 -0
- package/src/ui/sliderWidget.js +1 -1
- package/src/util/clustering.js +3 -3
- package/src/util/color.js +1 -1
- package/src/util/common.js +7 -7
- package/src/util/throttle.js +1 -1
- package/src/webgl/index.js +2 -0
- package/src/webgl/lookupTable2D.js +122 -0
- package/src/webgl/markerFeature.js +1 -1
- package/src/webgl/pixelmapFeature.frag +47 -0
- package/src/webgl/pixelmapFeature.js +203 -0
- package/src/webgl/pointFeature.js +1 -1
- package/src/webgl/quadFeature.js +35 -2
- package/src/webgl/webglRenderer.js +1 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
var inherit = require('../inherit');
|
|
2
|
+
var registerFeature = require('../registry').registerFeature;
|
|
3
|
+
var pixelmapFeature = require('../pixelmapFeature');
|
|
4
|
+
var lookupTable2D = require('./lookupTable2D');
|
|
5
|
+
var util = require('../util');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create a new instance of class webgl.pixelmapFeature.
|
|
9
|
+
*
|
|
10
|
+
* @class
|
|
11
|
+
* @alias geo.webgl.pixelmapFeature
|
|
12
|
+
* @extends geo.pixelmapFeature
|
|
13
|
+
* @param {geo.pixelmapFeature.spec} arg
|
|
14
|
+
* @returns {geo.webgl.pixelmapFeature}
|
|
15
|
+
*/
|
|
16
|
+
var webgl_pixelmapFeature = function (arg) {
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
if (!(this instanceof webgl_pixelmapFeature)) {
|
|
20
|
+
return new webgl_pixelmapFeature(arg);
|
|
21
|
+
}
|
|
22
|
+
pixelmapFeature.call(this, arg);
|
|
23
|
+
|
|
24
|
+
var object = require('./object');
|
|
25
|
+
object.call(this);
|
|
26
|
+
|
|
27
|
+
const vgl = require('vgl');
|
|
28
|
+
const fragmentShader = require('./pixelmapFeature.frag');
|
|
29
|
+
|
|
30
|
+
var m_quadFeature,
|
|
31
|
+
m_quadFeatureInit,
|
|
32
|
+
s_exit = this._exit,
|
|
33
|
+
m_lookupTable,
|
|
34
|
+
m_this = this;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* If the specified coordinates are in the rendered quad, use the basis
|
|
38
|
+
* information from the quad to determine the pixelmap index value so that it
|
|
39
|
+
* can be included in the `found` results.
|
|
40
|
+
*
|
|
41
|
+
* @param {geo.geoPosition} geo Coordinate.
|
|
42
|
+
* @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use
|
|
43
|
+
* the interface gcs, `null` to use the map gcs, or any other transform.
|
|
44
|
+
* @returns {geo.feature.searchResult} An object with a list of features and
|
|
45
|
+
* feature indices that are located at the specified point.
|
|
46
|
+
*/
|
|
47
|
+
this.pointSearch = function (geo, gcs) {
|
|
48
|
+
if (m_quadFeature && m_this.m_info) {
|
|
49
|
+
let result = m_quadFeature.pointSearch(geo, gcs);
|
|
50
|
+
// use the last index by preference, since for tile layers, this is the
|
|
51
|
+
// topmosttile
|
|
52
|
+
let idxIdx = result.index.length - 1;
|
|
53
|
+
for (; idxIdx >= 0; idxIdx -= 1) {
|
|
54
|
+
if (result.extra[result.index[idxIdx]]._quad &&
|
|
55
|
+
result.extra[result.index[idxIdx]]._quad.image) {
|
|
56
|
+
const img = result.extra[result.index[idxIdx]]._quad.image;
|
|
57
|
+
const basis = result.extra[result.index[idxIdx]].basis;
|
|
58
|
+
const x = Math.floor(basis.x * img.width);
|
|
59
|
+
const y = Math.floor(basis.y * img.height);
|
|
60
|
+
const canvas = document.createElement('canvas');
|
|
61
|
+
canvas.width = canvas.height = 1;
|
|
62
|
+
const context = canvas.getContext('2d');
|
|
63
|
+
context.drawImage(img, x, y, 1, 1, 0, 0, 1, 1);
|
|
64
|
+
const pixel = context.getImageData(0, 0, 1, 1).data;
|
|
65
|
+
const idx = pixel[0] + pixel[1] * 256 + pixel[2] * 256 * 256;
|
|
66
|
+
result = {
|
|
67
|
+
index: [idx],
|
|
68
|
+
found: [m_this.data()[idx]]
|
|
69
|
+
};
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {index: [], found: []};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Given the loaded pixelmap image, create a texture for the colors and a
|
|
79
|
+
* quad that will use it.
|
|
80
|
+
*/
|
|
81
|
+
this._computePixelmap = function () {
|
|
82
|
+
var data = m_this.data() || [],
|
|
83
|
+
colorFunc = m_this.style.get('color');
|
|
84
|
+
|
|
85
|
+
let indexRange = m_this.indexModified(undefined, 'clear');
|
|
86
|
+
let fullUpdate = m_this.dataTime().timestamp() >= m_this.buildTime().timestamp() || indexRange === undefined;
|
|
87
|
+
if (!m_lookupTable) {
|
|
88
|
+
m_lookupTable = lookupTable2D();
|
|
89
|
+
m_lookupTable.setTextureUnit(1);
|
|
90
|
+
fullUpdate = true;
|
|
91
|
+
}
|
|
92
|
+
let clrLen = Math.max(1, data.length);
|
|
93
|
+
const maxWidth = m_lookupTable.maxWidth();
|
|
94
|
+
if (clrLen > maxWidth && clrLen % maxWidth) {
|
|
95
|
+
clrLen += maxWidth - (clrLen % maxWidth);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let colors;
|
|
99
|
+
if (!fullUpdate) {
|
|
100
|
+
colors = m_lookupTable.colorTable();
|
|
101
|
+
fullUpdate = colors.length !== clrLen * 4;
|
|
102
|
+
indexRange[0] = Math.max(0, indexRange[0]);
|
|
103
|
+
indexRange[1] = Math.min(data.length, indexRange[1] + 1);
|
|
104
|
+
}
|
|
105
|
+
if (fullUpdate) {
|
|
106
|
+
colors = new Uint8Array(clrLen * 4);
|
|
107
|
+
indexRange = [0, data.length];
|
|
108
|
+
}
|
|
109
|
+
for (let i = indexRange[0]; i < indexRange[1]; i += 1) {
|
|
110
|
+
const d = data[i];
|
|
111
|
+
const color = util.convertColor(colorFunc.call(m_this, d, i));
|
|
112
|
+
colors[i * 4] = color.r * 255;
|
|
113
|
+
colors[i * 4 + 1] = color.g * 255;
|
|
114
|
+
colors[i * 4 + 2] = color.b * 255;
|
|
115
|
+
colors[i * 4 + 3] = color.a === undefined ? 255 : (color.a * 255);
|
|
116
|
+
}
|
|
117
|
+
m_this.m_info = {colors: colors};
|
|
118
|
+
// check if colors haven't changed
|
|
119
|
+
var oldcolors = m_lookupTable.colorTable();
|
|
120
|
+
if (oldcolors && oldcolors.length === colors.length) {
|
|
121
|
+
let idx = indexRange[0] * 4;
|
|
122
|
+
for (; idx < indexRange[1] * 4; idx += 1) {
|
|
123
|
+
if (colors[idx] !== oldcolors[idx]) {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (idx === indexRange[1] * 4) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
m_lookupTable.colorTable(colors);
|
|
132
|
+
/* If we haven't made a quad feature, make one now */
|
|
133
|
+
if (!m_quadFeature) {
|
|
134
|
+
m_quadFeature = m_this.layer().createFeature('quad', {
|
|
135
|
+
selectionAPI: false,
|
|
136
|
+
gcs: m_this.gcs(),
|
|
137
|
+
visible: m_this.visible(undefined, true)
|
|
138
|
+
});
|
|
139
|
+
m_quadFeatureInit = false;
|
|
140
|
+
}
|
|
141
|
+
if (!m_quadFeatureInit) {
|
|
142
|
+
m_this.dependentFeatures([m_quadFeature]);
|
|
143
|
+
m_quadFeature.setShader('image_fragment', fragmentShader);
|
|
144
|
+
m_quadFeature._hookBuild = (prog) => {
|
|
145
|
+
const lutSampler = new vgl.uniform(vgl.GL.INT, 'lutSampler');
|
|
146
|
+
lutSampler.set(m_lookupTable.textureUnit());
|
|
147
|
+
prog.addUniform(lutSampler);
|
|
148
|
+
const lutWidth = new vgl.uniform(vgl.GL.INT, 'lutWidth');
|
|
149
|
+
lutWidth.set(m_lookupTable.width);
|
|
150
|
+
prog.addUniform(lutWidth);
|
|
151
|
+
const lutHeight = new vgl.uniform(vgl.GL.INT, 'lutHeight');
|
|
152
|
+
lutHeight.set(m_lookupTable.height);
|
|
153
|
+
prog.addUniform(lutHeight);
|
|
154
|
+
};
|
|
155
|
+
m_quadFeature._hookRenderImageQuads = (renderState, quads) => {
|
|
156
|
+
quads.forEach((quad) => {
|
|
157
|
+
if (quad.image && quad.texture && !quad.texture.nearestPixel()) {
|
|
158
|
+
quad.texture.setNearestPixel(true);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
m_lookupTable.bind(renderState, quads);
|
|
162
|
+
};
|
|
163
|
+
if (m_quadFeatureInit === false) {
|
|
164
|
+
m_quadFeature.style({
|
|
165
|
+
image: m_this.m_srcImage,
|
|
166
|
+
position: m_this.style.get('position')})
|
|
167
|
+
.data([{}])
|
|
168
|
+
.draw();
|
|
169
|
+
}
|
|
170
|
+
m_quadFeatureInit = true;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Destroy. Deletes the associated quadFeature.
|
|
176
|
+
*
|
|
177
|
+
* @returns {this}
|
|
178
|
+
*/
|
|
179
|
+
this._exit = function () {
|
|
180
|
+
if (m_quadFeature && m_this.layer()) {
|
|
181
|
+
m_this.layer().deleteFeature(m_quadFeature);
|
|
182
|
+
m_quadFeature = null;
|
|
183
|
+
m_this.dependentFeatures([]);
|
|
184
|
+
}
|
|
185
|
+
s_exit();
|
|
186
|
+
return m_this;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
if (arg.quadFeature) {
|
|
190
|
+
m_quadFeature = arg.quadFeature;
|
|
191
|
+
}
|
|
192
|
+
this._init(arg);
|
|
193
|
+
return this;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
inherit(webgl_pixelmapFeature, pixelmapFeature);
|
|
197
|
+
|
|
198
|
+
// Now register it
|
|
199
|
+
var capabilities = {};
|
|
200
|
+
capabilities[pixelmapFeature.capabilities.lookup] = true;
|
|
201
|
+
|
|
202
|
+
registerFeature('webgl', 'pixelmap', webgl_pixelmapFeature, capabilities);
|
|
203
|
+
module.exports = webgl_pixelmapFeature;
|
|
@@ -78,7 +78,7 @@ var webgl_pointFeature = function (arg) {
|
|
|
78
78
|
/**
|
|
79
79
|
* Create and style the data needed to render the points.
|
|
80
80
|
*
|
|
81
|
-
* @param {boolean} onlyStyle if true, use the existing geometry and just
|
|
81
|
+
* @param {boolean} [onlyStyle] if true, use the existing geometry and just
|
|
82
82
|
* recalculate the style.
|
|
83
83
|
*/
|
|
84
84
|
function createGLPoints(onlyStyle) {
|
package/src/webgl/quadFeature.js
CHANGED
|
@@ -158,7 +158,7 @@ var webgl_quadFeature = function (arg) {
|
|
|
158
158
|
* Build this feature.
|
|
159
159
|
*/
|
|
160
160
|
this._build = function () {
|
|
161
|
-
var mapper, mat, prog, srctex, unicrop, unicropsource, geom, context;
|
|
161
|
+
var mapper, mat, prog, srctex, unicrop, unicropsource, geom, context, sampler2d;
|
|
162
162
|
|
|
163
163
|
if (!m_this.position()) {
|
|
164
164
|
return;
|
|
@@ -183,6 +183,10 @@ var webgl_quadFeature = function (arg) {
|
|
|
183
183
|
prog.addUniform(new vgl.projectionUniform('projectionMatrix'));
|
|
184
184
|
prog.addUniform(new vgl.floatUniform('opacity', 1.0));
|
|
185
185
|
prog.addUniform(new vgl.floatUniform('zOffset', 0.0));
|
|
186
|
+
/* Use texture unit 0 */
|
|
187
|
+
sampler2d = new vgl.uniform(vgl.GL.INT, 'sampler2d');
|
|
188
|
+
sampler2d.set(0);
|
|
189
|
+
prog.addUniform(sampler2d);
|
|
186
190
|
context = m_this.renderer()._glContext();
|
|
187
191
|
unicrop = new vgl.uniform(context.FLOAT_VEC2, 'crop');
|
|
188
192
|
unicrop.set([1.0, 1.0]);
|
|
@@ -194,6 +198,9 @@ var webgl_quadFeature = function (arg) {
|
|
|
194
198
|
context.VERTEX_SHADER, context, vertexShaderImage));
|
|
195
199
|
prog.addShader(vgl.getCachedShader(
|
|
196
200
|
context.FRAGMENT_SHADER, context, fragmentShaderImage));
|
|
201
|
+
if (m_this._hookBuild) {
|
|
202
|
+
m_this._hookBuild(prog);
|
|
203
|
+
}
|
|
197
204
|
mat.addAttribute(prog);
|
|
198
205
|
mat.addAttribute(new vgl.blend());
|
|
199
206
|
/* This is similar to vgl.planeSource */
|
|
@@ -355,13 +362,18 @@ var webgl_quadFeature = function (arg) {
|
|
|
355
362
|
cropsrc = {x0: 0, y0: 0, x1: 1, y1: 1}, quadcropsrc,
|
|
356
363
|
w, h, quadw, quadh;
|
|
357
364
|
|
|
365
|
+
if (m_this._hookRenderImageQuads) {
|
|
366
|
+
m_this._hookRenderImageQuads(renderState, m_quads.imgQuads);
|
|
367
|
+
}
|
|
358
368
|
context.bindBuffer(context.ARRAY_BUFFER, m_glBuffers.imgQuadsPosition);
|
|
359
369
|
$.each(m_quads.imgQuads, function (idx, quad) {
|
|
360
370
|
if (!quad.image) {
|
|
361
371
|
return;
|
|
362
372
|
}
|
|
363
373
|
quad.texture.bind(renderState);
|
|
364
|
-
if
|
|
374
|
+
// only check if the context is out of memory when using modestly large
|
|
375
|
+
// textures. The check is slow.
|
|
376
|
+
if ((quad.image.width > 4096 || quad.image.height > 4096 || quad.image.width * quad.image.height > 4194304) && context.getError() === context.OUT_OF_MEMORY) {
|
|
365
377
|
console.log('Insufficient GPU memory for texture');
|
|
366
378
|
}
|
|
367
379
|
if (quad.opacity !== opacity) {
|
|
@@ -450,6 +462,27 @@ var webgl_quadFeature = function (arg) {
|
|
|
450
462
|
m_this.modified();
|
|
451
463
|
};
|
|
452
464
|
|
|
465
|
+
/**
|
|
466
|
+
* Set the image or color vertex or fragment shader.
|
|
467
|
+
*
|
|
468
|
+
* @param {string} shaderType One of `image_vertex`, `image_fragment`,
|
|
469
|
+
* `color_vertex`, or `color_fragment`.
|
|
470
|
+
* @param {string} shaderCode The shader program.
|
|
471
|
+
* @returns {this} The class instance on success, undefined in an unknown
|
|
472
|
+
* shaderType was specified.
|
|
473
|
+
*/
|
|
474
|
+
this.setShader = function (shaderType, shaderCode) {
|
|
475
|
+
switch (shaderType) {
|
|
476
|
+
case 'image_vertex': vertexShaderImage = shaderCode; break;
|
|
477
|
+
case 'image_fragment': fragmentShaderImage = shaderCode; break;
|
|
478
|
+
case 'color_vertex': vertexShaderColor = shaderCode; break;
|
|
479
|
+
case 'color_fragment': fragmentShaderColor = shaderCode; break;
|
|
480
|
+
default:
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
return m_this;
|
|
484
|
+
};
|
|
485
|
+
|
|
453
486
|
/**
|
|
454
487
|
* Destroy.
|
|
455
488
|
*/
|
|
@@ -319,6 +319,7 @@ webglRenderer.supported = function () {
|
|
|
319
319
|
var canvas, ctx, exts; // eslint-disable-line no-unused-vars
|
|
320
320
|
try {
|
|
321
321
|
canvas = document.createElement('canvas');
|
|
322
|
+
/** @type {WebGLRenderingContext} */
|
|
322
323
|
ctx = (canvas.getContext('webgl') ||
|
|
323
324
|
canvas.getContext('experimental-webgl'));
|
|
324
325
|
/* getSupportExtensions will throw an exception if the context isn't
|