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/geo.js +667 -261
- package/geo.lean.js +667 -261
- package/geo.lean.min.js +3 -3
- package/geo.min.js +5 -5
- package/package.json +1 -1
- package/src/canvas/pixelmapFeature.js +187 -0
- package/src/pixelmapFeature.js +52 -228
- package/src/quadFeature.js +1 -1
- package/src/webgl/index.js +2 -0
- package/src/webgl/lookupTable2D.js +122 -0
- package/src/webgl/pixelmapFeature.frag +47 -0
- package/src/webgl/pixelmapFeature.js +172 -0
- package/src/webgl/quadFeature.js +32 -1
package/package.json
CHANGED
|
@@ -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
|
};
|
package/src/pixelmapFeature.js
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
* @
|
|
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.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
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
|
*
|
package/src/quadFeature.js
CHANGED
package/src/webgl/index.js
CHANGED
|
@@ -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'),
|