geojs 1.6.5 → 1.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geojs",
3
- "version": "1.6.5",
3
+ "version": "1.6.6",
4
4
  "description": "JavaScript Geo Visualization and Analysis Library",
5
5
  "homepage": "https://github.com/OpenGeoscience/geojs",
6
6
  "license": "Apache-2.0",
@@ -1,6 +1,8 @@
1
1
  var inherit = require('../inherit');
2
2
  var registerFeature = require('../registry').registerFeature;
3
3
  var pixelmapFeature = require('../pixelmapFeature');
4
+ var geo_event = require('../event');
5
+ var util = require('../util');
4
6
 
5
7
  /**
6
8
  * Create a new instance of class pixelmapFeature.
@@ -22,6 +24,191 @@ var canvas_pixelmapFeature = function (arg) {
22
24
  var object = require('./object');
23
25
  object.call(this);
24
26
 
27
+ var m_quadFeature,
28
+ s_exit = this._exit,
29
+ m_this = this;
30
+
31
+ /**
32
+ * If the specified coordinates are in the rendered quad, use the basis
33
+ * information from the quad to determine the pixelmap index value so that it
34
+ * can be included in the `found` results.
35
+ *
36
+ * @param {geo.geoPosition} geo Coordinate.
37
+ * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use
38
+ * the interface gcs, `null` to use the map gcs, or any other transform.
39
+ * @returns {geo.feature.searchResult} An object with a list of features and
40
+ * feature indices that are located at the specified point.
41
+ */
42
+ this.pointSearch = function (geo, gcs) {
43
+ if (m_quadFeature && m_this.m_info) {
44
+ var result = m_quadFeature.pointSearch(geo, gcs);
45
+ if (result.index.length === 1 && result.extra && result.extra[result.index[0]].basis) {
46
+ var basis = result.extra[result.index[0]].basis, x, y, idx;
47
+ x = Math.floor(basis.x * m_this.m_info.width);
48
+ y = Math.floor(basis.y * m_this.m_info.height);
49
+ if (x >= 0 && x < m_this.m_info.width &&
50
+ y >= 0 && y < m_this.m_info.height) {
51
+ idx = m_this.m_info.indices[y * m_this.m_info.width + x];
52
+ result = {
53
+ index: [idx],
54
+ found: [m_this.data()[idx]]
55
+ };
56
+ return result;
57
+ }
58
+ }
59
+ }
60
+ return {index: [], found: []};
61
+ };
62
+
63
+ /**
64
+ * Compute information for this pixelmap image. It is wasteful to call this
65
+ * if the pixelmap has already been prepared (it is invalidated by a change
66
+ * in the image).
67
+ *
68
+ * @returns {geo.pixelmapFeature.info}
69
+ */
70
+ this._preparePixelmap = function () {
71
+ var i, idx, pixelData;
72
+
73
+ if (!util.isReadyImage(m_this.m_srcImage)) {
74
+ return;
75
+ }
76
+ m_this.m_info = {
77
+ width: m_this.m_srcImage.naturalWidth,
78
+ height: m_this.m_srcImage.naturalHeight,
79
+ canvas: document.createElement('canvas')
80
+ };
81
+
82
+ m_this.m_info.canvas.width = m_this.m_info.width;
83
+ m_this.m_info.canvas.height = m_this.m_info.height;
84
+ m_this.m_info.context = m_this.m_info.canvas.getContext('2d');
85
+
86
+ m_this.m_info.context.drawImage(m_this.m_srcImage, 0, 0);
87
+ m_this.m_info.imageData = m_this.m_info.context.getImageData(
88
+ 0, 0, m_this.m_info.canvas.width, m_this.m_info.canvas.height);
89
+ pixelData = m_this.m_info.imageData.data;
90
+ m_this.m_info.indices = new Array(pixelData.length / 4);
91
+ m_this.m_info.area = pixelData.length / 4;
92
+
93
+ m_this.m_info.mappedColors = {};
94
+ for (i = 0; i < pixelData.length; i += 4) {
95
+ idx = pixelData[i] + (pixelData[i + 1] << 8) + (pixelData[i + 2] << 16);
96
+ m_this.m_info.indices[i / 4] = idx;
97
+ if (!m_this.m_info.mappedColors[idx]) {
98
+ m_this.m_info.mappedColors[idx] = {first: i / 4};
99
+ }
100
+ m_this.m_info.mappedColors[idx].last = i / 4;
101
+ }
102
+ return m_this.m_info;
103
+ };
104
+
105
+ /**
106
+ * Given the loaded pixelmap image, create a canvas the size of the image.
107
+ * Compute a color for each distinct index and recolor the canvas based on
108
+ * these colors, then draw the resultant image as a quad.
109
+ *
110
+ * @fires geo.event.pixelmap.prepared
111
+ */
112
+ this._computePixelmap = function () {
113
+ var data = m_this.data() || [],
114
+ colorFunc = m_this.style.get('color'),
115
+ i, idx, lastidx, color, pixelData, indices, mappedColors,
116
+ updateFirst, updateLast = -1, update, prepared;
117
+
118
+ if (!m_this.m_info) {
119
+ if (!m_this._preparePixelmap()) {
120
+ return;
121
+ }
122
+ prepared = true;
123
+ }
124
+ mappedColors = m_this.m_info.mappedColors;
125
+ updateFirst = m_this.m_info.area;
126
+ for (idx in mappedColors) {
127
+ if (mappedColors.hasOwnProperty(idx)) {
128
+ color = colorFunc(data[idx], +idx) || {};
129
+ color = [
130
+ (color.r || 0) * 255,
131
+ (color.g || 0) * 255,
132
+ (color.b || 0) * 255,
133
+ color.a === undefined ? 255 : (color.a * 255)
134
+ ];
135
+ mappedColors[idx].update = (
136
+ !mappedColors[idx].color ||
137
+ mappedColors[idx].color[0] !== color[0] ||
138
+ mappedColors[idx].color[1] !== color[1] ||
139
+ mappedColors[idx].color[2] !== color[2] ||
140
+ mappedColors[idx].color[3] !== color[3]);
141
+ if (mappedColors[idx].update) {
142
+ mappedColors[idx].color = color;
143
+ updateFirst = Math.min(mappedColors[idx].first, updateFirst);
144
+ updateLast = Math.max(mappedColors[idx].last, updateLast);
145
+ }
146
+ }
147
+ }
148
+ /* If nothing was updated, we are done */
149
+ if (updateFirst >= updateLast) {
150
+ return;
151
+ }
152
+ /* Update only the extent that has changed */
153
+ pixelData = m_this.m_info.imageData.data;
154
+ indices = m_this.m_info.indices;
155
+ for (i = updateFirst; i <= updateLast; i += 1) {
156
+ idx = indices[i];
157
+ if (idx !== lastidx) {
158
+ lastidx = idx;
159
+ color = mappedColors[idx].color;
160
+ update = mappedColors[idx].update;
161
+ }
162
+ if (update) {
163
+ pixelData[i * 4] = color[0];
164
+ pixelData[i * 4 + 1] = color[1];
165
+ pixelData[i * 4 + 2] = color[2];
166
+ pixelData[i * 4 + 3] = color[3];
167
+ }
168
+ }
169
+ /* Place the updated area into the canvas */
170
+ m_this.m_info.context.putImageData(
171
+ m_this.m_info.imageData, 0, 0, 0, Math.floor(updateFirst / m_this.m_info.width),
172
+ m_this.m_info.width, Math.ceil((updateLast + 1) / m_this.m_info.width));
173
+
174
+ /* If we haven't made a quad feature, make one now. The quad feature needs
175
+ * to have the canvas capability. */
176
+ if (!m_quadFeature) {
177
+ m_quadFeature = m_this.layer().createFeature('quad', {
178
+ selectionAPI: false,
179
+ gcs: m_this.gcs(),
180
+ visible: m_this.visible(undefined, true)
181
+ });
182
+ m_this.dependentFeatures([m_quadFeature]);
183
+ m_quadFeature.style({
184
+ image: m_this.m_info.canvas,
185
+ position: m_this.style.get('position')})
186
+ .data([{}])
187
+ .draw();
188
+ }
189
+ /* If we prepared the pixelmap and rendered it, send a prepared event */
190
+ if (prepared) {
191
+ m_this.geoTrigger(geo_event.pixelmap.prepared, {
192
+ pixelmap: m_this
193
+ });
194
+ }
195
+ };
196
+
197
+ /**
198
+ * Destroy. Deletes the associated quadFeature.
199
+ *
200
+ * @returns {this}
201
+ */
202
+ this._exit = function () {
203
+ if (m_quadFeature && m_this.layer()) {
204
+ m_this.layer().deleteFeature(m_quadFeature);
205
+ m_quadFeature = null;
206
+ m_this.dependentFeatures([]);
207
+ }
208
+ s_exit();
209
+ return m_this;
210
+ };
211
+
25
212
  this._init(arg);
26
213
  return this;
27
214
  };
@@ -1,7 +1,6 @@
1
1
  var $ = require('jquery');
2
2
  var inherit = require('./inherit');
3
3
  var feature = require('./feature');
4
- var geo_event = require('./event');
5
4
  var util = require('./util');
6
5
 
7
6
  /**
@@ -72,12 +71,8 @@ var pixelmapFeature = function (arg) {
72
71
  * @private
73
72
  */
74
73
  var m_this = this,
75
- m_quadFeature,
76
- m_srcImage,
77
- m_info,
78
74
  s_update = this._update,
79
- s_init = this._init,
80
- s_exit = this._exit;
75
+ s_init = this._init;
81
76
 
82
77
  this.featureType = 'pixelmap';
83
78
 
@@ -113,7 +108,7 @@ var pixelmapFeature = function (arg) {
113
108
  if (val === undefined) {
114
109
  return m_this.style('url');
115
110
  } else if (val !== m_this.style('url')) {
116
- m_srcImage = m_info = undefined;
111
+ m_this.m_srcImage = m_this.m_info = undefined;
117
112
  m_this.style('url', val);
118
113
  m_this.dataTime().modified();
119
114
  m_this.modified();
@@ -121,28 +116,6 @@ var pixelmapFeature = function (arg) {
121
116
  return m_this;
122
117
  };
123
118
 
124
- /**
125
- * Get the maximum index value from the pixelmap. This is a value present in
126
- * the pixelmap.
127
- *
128
- * @returns {number} The maximum index value.
129
- */
130
- this.maxIndex = function () {
131
- if (m_info) {
132
- /* This isn't just m_info.mappedColors.length - 1, since there
133
- * may be more data than actual indices. */
134
- if (m_info.maxIndex === undefined) {
135
- m_info.maxIndex = 0;
136
- for (var idx in m_info.mappedColors) {
137
- if (m_info.mappedColors.hasOwnProperty(idx)) {
138
- m_info.maxIndex = Math.max(m_info.maxIndex, idx);
139
- }
140
- }
141
- }
142
- return m_info.maxIndex;
143
- }
144
- };
145
-
146
119
  /**
147
120
  * Get/Set color accessor.
148
121
  *
@@ -162,35 +135,51 @@ var pixelmapFeature = function (arg) {
162
135
  };
163
136
 
164
137
  /**
165
- * If the specified coordinates are in the rendered quad, use the basis
166
- * information from the quad to determine the pixelmap index value so that it
167
- * can be included in the `found` results.
138
+ * Update.
168
139
  *
169
- * @param {geo.geoPosition} geo Coordinate.
170
- * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use
171
- * the interface gcs, `null` to use the map gcs, or any other transform.
172
- * @returns {geo.feature.searchResult} An object with a list of features and
173
- * feature indices that are located at the specified point.
140
+ * @returns {this}
174
141
  */
175
- this.pointSearch = function (geo, gcs) {
176
- if (m_quadFeature && m_info) {
177
- var result = m_quadFeature.pointSearch(geo, gcs);
178
- if (result.index.length === 1 && result.extra && result.extra[result.index[0]].basis) {
179
- var basis = result.extra[result.index[0]].basis, x, y, idx;
180
- x = Math.floor(basis.x * m_info.width);
181
- y = Math.floor(basis.y * m_info.height);
182
- if (x >= 0 && x < m_info.width &&
183
- y >= 0 && y < m_info.height) {
184
- idx = m_info.indices[y * m_info.width + x];
185
- result = {
186
- index: [idx],
187
- found: [m_this.data()[idx]]
188
- };
189
- return result;
142
+ this._update = function () {
143
+ s_update.call(m_this);
144
+ if (m_this.buildTime().timestamp() <= m_this.dataTime().timestamp() ||
145
+ m_this.updateTime().timestamp() < m_this.timestamp()) {
146
+ m_this._build();
147
+ }
148
+
149
+ m_this.updateTime().modified();
150
+ return m_this;
151
+ };
152
+
153
+ /**
154
+ * Get the maximum index value from the pixelmap. This is a value present in
155
+ * the pixelmap.
156
+ *
157
+ * @returns {number} The maximum index value.
158
+ */
159
+ this.maxIndex = function () {
160
+ if (m_this.m_info) {
161
+ /* This isn't just m_info.mappedColors.length - 1, since there
162
+ * may be more data than actual indices. */
163
+ if (m_this.m_info.maxIndex === undefined) {
164
+ m_this.m_info.maxIndex = 0;
165
+ for (var idx in m_this.m_info.mappedColors) {
166
+ if (m_this.m_info.mappedColors.hasOwnProperty(idx)) {
167
+ m_this.m_info.maxIndex = Math.max(m_this.m_info.maxIndex, idx);
168
+ }
190
169
  }
191
170
  }
171
+ return m_this.m_info.maxIndex;
192
172
  }
193
- return {index: [], found: []};
173
+ };
174
+
175
+ /**
176
+ * Given the loaded pixelmap image, create a canvas the size of the image.
177
+ * Compute a color for each distinct index and recolor the canvas based on
178
+ * these colors, then draw the resultant image as a quad.
179
+ *
180
+ * @fires geo.event.pixelmap.prepared
181
+ */
182
+ this._computePixelmap = function () {
194
183
  };
195
184
 
196
185
  /**
@@ -204,42 +193,42 @@ var pixelmapFeature = function (arg) {
204
193
  * checks if this feature is built. Setting the build time avoids calling
205
194
  * this a second time. */
206
195
  m_this.buildTime().modified();
207
- if (!m_srcImage) {
196
+ if (!m_this.m_srcImage) {
208
197
  var src = m_this.style.get('url')();
209
198
  if (util.isReadyImage(src)) {
210
199
  /* we have an already loaded image, so we can just use it. */
211
- m_srcImage = src;
200
+ m_this.m_srcImage = src;
212
201
  m_this._computePixelmap();
213
202
  } else if (src) {
214
203
  var defer = $.Deferred(), prev_onload, prev_onerror;
215
204
  if (src instanceof Image) {
216
205
  /* we have an unloaded image. Hook to the load and error callbacks
217
206
  * so that when it is loaded we can use it. */
218
- m_srcImage = src;
207
+ m_this.m_srcImage = src;
219
208
  prev_onload = src.onload;
220
209
  prev_onerror = src.onerror;
221
210
  } else {
222
211
  /* we were given a url, so construct a new image */
223
- m_srcImage = new Image();
212
+ m_this.m_srcImage = new Image();
224
213
  // Only set the crossOrigin parameter if this is going across origins.
225
214
  if (src.indexOf(':') >= 0 &&
226
215
  src.indexOf('/') === src.indexOf(':') + 1) {
227
- m_srcImage.crossOrigin = m_this.style.get('crossDomain')() || 'anonymous';
216
+ m_this.m_srcImage.crossOrigin = m_this.style.get('crossDomain')() || 'anonymous';
228
217
  }
229
218
  }
230
- m_srcImage.onload = function () {
219
+ m_this.m_srcImage.onload = function () {
231
220
  if (prev_onload) {
232
221
  prev_onload.apply(m_this, arguments);
233
222
  }
234
223
  /* Only use this image if our pixelmap hasn't changed since we
235
224
  * attached our handler */
236
225
  if (m_this.style.get('url')() === src) {
237
- m_info = undefined;
226
+ m_this.m_info = undefined;
238
227
  m_this._computePixelmap();
239
228
  }
240
229
  defer.resolve();
241
230
  };
242
- m_srcImage.onerror = function () {
231
+ m_this.m_srcImage.onerror = function () {
243
232
  if (prev_onerror) {
244
233
  prev_onerror.apply(m_this, arguments);
245
234
  }
@@ -248,180 +237,15 @@ var pixelmapFeature = function (arg) {
248
237
  defer.promise(m_this);
249
238
  m_this.layer().addPromise(m_this);
250
239
  if (!(src instanceof Image)) {
251
- m_srcImage.src = src;
240
+ m_this.m_srcImage.src = src;
252
241
  }
253
242
  }
254
- } else if (m_info) {
243
+ } else if (m_this.m_info) {
255
244
  m_this._computePixelmap();
256
245
  }
257
246
  return m_this;
258
247
  };
259
248
 
260
- /**
261
- * Compute information for this pixelmap image. It is wasteful to call this
262
- * if the pixelmap has already been prepared (it is invalidated by a change
263
- * in the image).
264
- *
265
- * @returns {geo.pixelmapFeature.info}
266
- */
267
- this._preparePixelmap = function () {
268
- var i, idx, pixelData;
269
-
270
- if (!util.isReadyImage(m_srcImage)) {
271
- return;
272
- }
273
- m_info = {
274
- width: m_srcImage.naturalWidth,
275
- height: m_srcImage.naturalHeight,
276
- canvas: document.createElement('canvas')
277
- };
278
-
279
- m_info.canvas.width = m_info.width;
280
- m_info.canvas.height = m_info.height;
281
- m_info.context = m_info.canvas.getContext('2d');
282
-
283
- m_info.context.drawImage(m_srcImage, 0, 0);
284
- m_info.imageData = m_info.context.getImageData(
285
- 0, 0, m_info.canvas.width, m_info.canvas.height);
286
- pixelData = m_info.imageData.data;
287
- m_info.indices = new Array(pixelData.length / 4);
288
- m_info.area = pixelData.length / 4;
289
-
290
- m_info.mappedColors = {};
291
- for (i = 0; i < pixelData.length; i += 4) {
292
- idx = pixelData[i] + (pixelData[i + 1] << 8) + (pixelData[i + 2] << 16);
293
- m_info.indices[i / 4] = idx;
294
- if (!m_info.mappedColors[idx]) {
295
- m_info.mappedColors[idx] = {first: i / 4};
296
- }
297
- m_info.mappedColors[idx].last = i / 4;
298
- }
299
- return m_info;
300
- };
301
-
302
- /**
303
- * Given the loaded pixelmap image, create a canvas the size of the image.
304
- * Compute a color for each distinct index and recolor the canvas based on
305
- * these colors, then draw the resultant image as a quad.
306
- *
307
- * @fires geo.event.pixelmap.prepared
308
- */
309
- this._computePixelmap = function () {
310
- var data = m_this.data() || [],
311
- colorFunc = m_this.style.get('color'),
312
- i, idx, lastidx, color, pixelData, indices, mappedColors,
313
- updateFirst, updateLast = -1, update, prepared;
314
-
315
- if (!m_info) {
316
- if (!m_this._preparePixelmap()) {
317
- return;
318
- }
319
- prepared = true;
320
- }
321
- mappedColors = m_info.mappedColors;
322
- updateFirst = m_info.area;
323
- for (idx in mappedColors) {
324
- if (mappedColors.hasOwnProperty(idx)) {
325
- color = colorFunc(data[idx], +idx) || {};
326
- color = [
327
- (color.r || 0) * 255,
328
- (color.g || 0) * 255,
329
- (color.b || 0) * 255,
330
- color.a === undefined ? 255 : (color.a * 255)
331
- ];
332
- mappedColors[idx].update = (
333
- !mappedColors[idx].color ||
334
- mappedColors[idx].color[0] !== color[0] ||
335
- mappedColors[idx].color[1] !== color[1] ||
336
- mappedColors[idx].color[2] !== color[2] ||
337
- mappedColors[idx].color[3] !== color[3]);
338
- if (mappedColors[idx].update) {
339
- mappedColors[idx].color = color;
340
- updateFirst = Math.min(mappedColors[idx].first, updateFirst);
341
- updateLast = Math.max(mappedColors[idx].last, updateLast);
342
- }
343
- }
344
- }
345
- /* If nothing was updated, we are done */
346
- if (updateFirst >= updateLast) {
347
- return;
348
- }
349
- /* Update only the extent that has changed */
350
- pixelData = m_info.imageData.data;
351
- indices = m_info.indices;
352
- for (i = updateFirst; i <= updateLast; i += 1) {
353
- idx = indices[i];
354
- if (idx !== lastidx) {
355
- lastidx = idx;
356
- color = mappedColors[idx].color;
357
- update = mappedColors[idx].update;
358
- }
359
- if (update) {
360
- pixelData[i * 4] = color[0];
361
- pixelData[i * 4 + 1] = color[1];
362
- pixelData[i * 4 + 2] = color[2];
363
- pixelData[i * 4 + 3] = color[3];
364
- }
365
- }
366
- /* Place the updated area into the canvas */
367
- m_info.context.putImageData(
368
- m_info.imageData, 0, 0, 0, Math.floor(updateFirst / m_info.width),
369
- m_info.width, Math.ceil((updateLast + 1) / m_info.width));
370
-
371
- /* If we haven't made a quad feature, make one now. The quad feature needs
372
- * to have the canvas capability. */
373
- if (!m_quadFeature) {
374
- m_quadFeature = m_this.layer().createFeature('quad', {
375
- selectionAPI: false,
376
- gcs: m_this.gcs(),
377
- visible: m_this.visible(undefined, true)
378
- });
379
- m_this.dependentFeatures([m_quadFeature]);
380
- m_quadFeature.style({
381
- image: m_info.canvas,
382
- position: m_this.style.get('position')})
383
- .data([{}])
384
- .draw();
385
- }
386
- /* If we prepared the pixelmap and rendered it, send a prepared event */
387
- if (prepared) {
388
- m_this.geoTrigger(geo_event.pixelmap.prepared, {
389
- pixelmap: m_this
390
- });
391
- }
392
- };
393
-
394
- /**
395
- * Update.
396
- *
397
- * @returns {this}
398
- */
399
- this._update = function () {
400
- s_update.call(m_this);
401
- if (m_this.buildTime().timestamp() <= m_this.dataTime().timestamp() ||
402
- m_this.updateTime().timestamp() < m_this.timestamp()) {
403
- m_this._build();
404
- }
405
-
406
- m_this.updateTime().modified();
407
- return m_this;
408
- };
409
-
410
- /**
411
- * Destroy. Deletes the associated quadFeature.
412
- *
413
- * @returns {this}
414
- */
415
- this._exit = function () {
416
- if (m_quadFeature && m_this.layer()) {
417
- m_this.layer().deleteFeature(m_quadFeature);
418
- m_quadFeature = null;
419
- m_this.dependentFeatures([]);
420
- }
421
- s_exit();
422
- return m_this;
423
- };
424
-
425
249
  /**
426
250
  * Initialize.
427
251
  *
@@ -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
  });
@@ -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'),