feat: Support tiled pixelmaps.
This creates a pixelmapLayer that is much like an osmLayer mixed with a
pixelmap feature.
MODIFY
scripts/datastore.js
scripts/datastore.js
@@ -19,6 +19,11 @@ var registry = {
'oahu-dense.json': '692a44ec4a18b16d1530403a9a2bf286ff2ef7d45fa58f555c278f91a0fa708b5626a3f38955e06a11cdc06a1009e859328687c1f32a2169e0c8ef1b518418c1',
'oahu.json': 'e44282c44fa95f0b40c2135ee94ff40a755771f3b4bf9acda0eef0048cd0fb29b3a71352e2eecdca6cfc35fafde96ffb1a9658c9fee2346071808a9123c26cb5',
'oahu-medium.json': '83375c5c2678b11d8de7f59fd8e2f9b889d3ec20f4a81279d996711bfc0942bd9dcdce149cbca995930459c26b3bf58be60569687085adf361ff805436b75aab',
+ 'pixelmap_0_0_0.png': 'c9be347bb323dca21a8ec4708b2c4343d7861546606f7d531b305d22d7b5be1e3bc7754cc407d117eda7ec3e31e2e0197d296cd80d40f0b32c17db0ad4db4292',
+ 'pixelmap_1_0_0.png': '41ca6c789bd410b0ea4dd814c92eb6047c098fcc6a8f77c200604e2bff7b7847f6c740e3a411a957a03edc0dfe6ee1383f38c34dceacdfa3e9f6408b7187ee25',
+ 'pixelmap_1_0_1.png': 'a27aa667e482cd7a7800cbe9c2401b9fbf387bdc67a49b17be04f7aa2846e522aa64383383fb3413d9dc7206e3b90910ccc8d4454ac1b08ebcedc68182c49e99',
+ 'pixelmap_1_1_0.png': 'b3f020355093ca6fa450550fe9680f549a6dc327a568d439d59e620ee3f9a43b6c88913e5d9344e65bd896cce5494b864051359faaaa4704433d5d0c41da2a43',
+ 'pixelmap_1_1_1.png': '31060e137ea25029dc977c66af62becf5ab685a3ac254fd8a9953eaa71c9b20efe97cd2d9ba03389e0d5c90c2c6bbe46a43a99c4aef10159b0d3515ee80cf459',
'red.jpg': '70884f5c3d1747633412dcf64d4886d985b49f508b68eb9f3874b2fdcfad38e7623f4a7c7355baa1656503f46e2e091576a19ded9fad7c7c65387c313206d2e6',
'roads.json': 'ae8d8b99c3fab73798ddcc246ea53b1bc8d598414d00df4ce697373a343fbf7ffed4dbae5f07a997ac7731b5f86140686b8425b99bd5818b8c9ec68e7c4d3315',
'sample.json': '5d4b00559f17fac607eafe4a9bb933386ebd572fbe545e6138b8eafbbf510074a8ae398c7df0420a017218af83b18cc322633b77007b63a27dfea7a50db70244',

MODIFY
src/index.js
src/index.js
@@ -77,6 +77,7 @@ module.exports = $.extend({
polygonFeature: require('./polygonFeature'),
quadFeature: require('./quadFeature'),
pixelmapFeature: require('./pixelmapFeature'),
+ pixelmapLayer: require('./pixelmapLayer'),
renderer: require('./renderer'),
sceneObject: require('./sceneObject'),
textFeature: require('./textFeature'),

MODIFY
src/pixelmapFeature.js
src/pixelmapFeature.js
@@ -282,6 +282,10 @@ var pixelmapFeature = function (arg) {
}
m_this.style(style);
m_this.dataTime().modified();
+ if (arg.quadFeature) {
+ m_this.m_srcImage = true;
+ m_this._computePixelmap();
+ }
return m_this;
};
@@ -307,7 +311,9 @@ pixelmapFeature.create = function (layer, spec) {
pixelmapFeature.capabilities = {
/* core feature name -- support in any manner */
- feature: 'pixelmap'
+ feature: 'pixelmap',
+ /* support for image-based lookup */
+ lookup: 'pixelmap.lookup'
};
inherit(pixelmapFeature, feature);

ADD
src/pixelmapLayer.js
+var $ = require('jquery');
+var inherit = require('./inherit');
+var tileLayer = require('./tileLayer');
+var registry = require('./registry');
+var quadFeature = require('./quadFeature');
+var pixelmapFeature = require('./pixelmapFeature');
+
+/**
+ * Object specification for a pixelmap layer.
+ *
+ * @typedef {geo.tileLayer.spec} geo.pixelmapLayer.spec
+ * @extends {geo.tileLayer.spec}
+ * @property {geo.geoColor|function} [color] The color that should be used
+ * for each data element. Data elements correspond to the indices in the
+ * pixel map. If an index is larger than the number of data elements, it will
+ * be transparent. If there is more data than there are indices, it is
+ * ignored.
+ */
+
+/**
+ * Create a new instance of pixelmapLayer. This is a {@link geo.tileLayer} with
+ * an OSM url and attribution defaults and with the tiles centered on the
+ * origin.
+ *
+ * @class
+ * @alias geo.pixelmapLayer
+ * @extends geo.tileLayer
+ *
+ * @param {geo.tileLayer.spec} [arg] Specification for the layer.
+ */
+var pixelmapLayer = function (arg) {
+
+ var imageTile = require('./imageTile');
+
+ if (!(this instanceof pixelmapLayer)) {
+ return new pixelmapLayer(arg);
+ }
+ arg = arg || {};
+ arg = $.extend(
+ true,
+ {},
+ this.constructor.defaults,
+ arg);
+ tileLayer.call(this, arg);
+
+ var s_init = this._init,
+ m_pixelmapFeature,
+ m_this = this;
+
+ /**
+ * Returns an instantiated imageTile object with the given indices. This
+ * method always returns a new tile object. Use `_getTileCached` to use
+ * the caching layer.
+ *
+ * @param {object} index The tile index.
+ * @param {number} index.x
+ * @param {number} index.y
+ * @param {number} index.level
+ * @param {object} source The tile index used for constructing the url.
+ * @param {number} source.x
+ * @param {number} source.y
+ * @param {number} source.level
+ * @returns {geo.tile}
+ */
+ this._getTile = function (index, source) {
+ var urlParams = source || index;
+ return imageTile({
+ index: index,
+ size: {x: m_this._options.tileWidth, y: m_this._options.tileHeight},
+ queue: m_this._queue,
+ overlap: m_this._options.tileOverlap,
+ scale: m_this._options.tileScale,
+ url: m_this._options.url.call(
+ m_this, urlParams.x, urlParams.y, urlParams.level || 0,
+ m_this._options.subdomains),
+ crossDomain: m_this._options.crossDomain
+ });
+ };
+
+ /**
+ * Initialize.
+ *
+ * @returns {this} The current layer.
+ */
+ this._init = function () {
+ // Call super class init
+ s_init.apply(m_this, arguments);
+
+ const pixelmapArgs = {quadFeature: m_this.features()[0]};
+ if (arg.style) {
+ pixelmapArgs.style = arg.style;
+ }
+ if (arg.color) {
+ pixelmapArgs.color = arg.color;
+ }
+ m_pixelmapFeature = m_this.createFeature('pixelmap', pixelmapArgs);
+ if (arg.data) {
+ m_pixelmapFeature.data(arg.data);
+ }
+ m_this.style = m_pixelmapFeature.style;
+ m_this.data = m_pixelmapFeature.data;
+ const s_dataTimeModified = m_this.dataTime().modified;
+ m_this.dataTime().modified = () => {
+ m_pixelmapFeature.dataTime().modified();
+ return s_dataTimeModified();
+ };
+ const s_modified = m_this.modified;
+ m_this.modified = () => {
+ m_pixelmapFeature.modified();
+ return s_modified();
+ };
+ const s_geoOn = m_this.geoOn;
+ const s_geoOff = m_this.geoOff;
+ m_this.geoOn = (event, handler) => {
+ m_pixelmapFeature.geoOn(event, handler);
+ return s_geoOn(event, handler);
+ };
+ m_this.geoOff = (event, handler) => {
+ m_pixelmapFeature.geoOff(event, handler);
+ return s_geoOff(event, handler);
+ };
+ return m_this;
+ };
+
+ return m_this;
+};
+
+/**
+ * This object contains the default options used to initialize the
+ * pixelmapLayer.
+ */
+pixelmapLayer.defaults = $.extend({}, tileLayer.defaults, {
+ features: [quadFeature.capabilities.image, pixelmapFeature.capabilities.lookup],
+ tileOffset : function (level) {
+ var s = Math.pow(2, level - 1) * 256;
+ return {x: s, y: s};
+ },
+ url: ''
+});
+
+inherit(pixelmapLayer, tileLayer);
+/* By default, ask to support image quads. If the user needs full
+ * reprojection, they will need to require the
+ * quadFeature.capabilities.imageFull feature */
+registry.registerLayer('pixelmap', pixelmapLayer, [quadFeature.capabilities.image]);
+
+module.exports = pixelmapLayer;

MODIFY
src/webgl/pixelmapFeature.js
src/webgl/pixelmapFeature.js
@@ -28,6 +28,7 @@ var webgl_pixelmapFeature = function (arg) {
const fragmentShader = require('./pixelmapFeature.frag');
var m_quadFeature,
+ m_quadFeatureInit,
s_exit = this._exit,
m_lookupTable,
m_this = this;
@@ -117,6 +118,9 @@ var webgl_pixelmapFeature = function (arg) {
gcs: m_this.gcs(),
visible: m_this.visible(undefined, true)
});
+ m_quadFeatureInit = false;
+ }
+ if (!m_quadFeatureInit) {
m_this.dependentFeatures([m_quadFeature]);
m_quadFeature.setShader('image_fragment', fragmentShader);
m_quadFeature._hookBuild = (prog) => {
@@ -138,12 +142,15 @@ var webgl_pixelmapFeature = function (arg) {
});
m_lookupTable.bind(renderState, quads);
};
+ if (m_quadFeatureInit === false) {
m_quadFeature.style({
image: m_this.m_srcImage,
position: m_this.style.get('position')})
.data([{}])
.draw();
}
+ m_quadFeatureInit = true;
+ }
};
/**
@@ -161,6 +168,9 @@ var webgl_pixelmapFeature = function (arg) {
return m_this;
};
+ if (arg.quadFeature) {
+ m_quadFeature = arg.quadFeature;
+ }
this._init(arg);
return this;
};
@@ -168,5 +178,8 @@ var webgl_pixelmapFeature = function (arg) {
inherit(webgl_pixelmapFeature, pixelmapFeature);
// Now register it
-registerFeature('webgl', 'pixelmap', webgl_pixelmapFeature);
+var capabilities = {};
+capabilities[pixelmapFeature.capabilities.lookup] = true;
+
+registerFeature('webgl', 'pixelmap', webgl_pixelmapFeature, capabilities);
module.exports = webgl_pixelmapFeature;

feat: Support tiled pixelmaps.

This creates a pixelmapLayer that is much like an osmLayer mixed with a
pixelmap feature.