From 8145b358c0045a9ab18d8f3913d7372fd1065c9a Mon Sep 17 00:00:00 2001 From: Olivier Guyot Date: Sun, 19 May 2019 11:55:54 +0200 Subject: [PATCH] Webgl renderer / add id encode/decode utils --- src/ol/renderer/webgl/Layer.js | 36 +++++++++++++++++++++++ test/spec/ol/renderer/webgl/layer.test.js | 33 +++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/ol/renderer/webgl/Layer.js b/src/ol/renderer/webgl/Layer.js index b50b54d1b2..60b6344a34 100644 --- a/src/ol/renderer/webgl/Layer.js +++ b/src/ol/renderer/webgl/Layer.js @@ -238,4 +238,40 @@ export function getBlankTexture() { return image; } +/** + * Generates a color array based on a numerical id + * Note: the range for each component is 0 to 1 with 256 steps + * @param {number} id Id + * @param {Array} [opt_array] Reusable array + * @return {Array} Color array containing the encoded id + */ +export function colorEncodeId(id, opt_array) { + const array = opt_array || []; + const radix = 256; + const divide = radix - 1; + array[0] = Math.floor(id / radix / radix / radix) / divide; + array[1] = (Math.floor(id / radix / radix) % radix) / divide; + array[2] = (Math.floor(id / radix) % radix) / divide; + array[3] = (id % radix) / divide; + return array; +} + + +/** + * Reads an id from a color-encoded array + * Note: the expected range for each component is 0 to 1 with 256 steps. + * @param {Array} color Color array containing the encoded id + * @return {number} Decoded id + */ +export function colorDecodeId(color) { + let id = 0; + const radix = 256; + const mult = radix - 1; + id += Math.round(color[0] * radix * radix * radix * mult); + id += Math.round(color[1] * radix * radix * mult); + id += Math.round(color[2] * radix * mult); + id += Math.round(color[3] * mult); + return id; +} + export default WebGLLayerRenderer; diff --git a/test/spec/ol/renderer/webgl/layer.test.js b/test/spec/ol/renderer/webgl/layer.test.js index cb9f30f3c1..fdde057f6b 100644 --- a/test/spec/ol/renderer/webgl/layer.test.js +++ b/test/spec/ol/renderer/webgl/layer.test.js @@ -1,4 +1,6 @@ import WebGLLayerRenderer, { + colorDecodeId, + colorEncodeId, getBlankTexture, POINT_INSTRUCTIONS_COUNT, POINT_VERTEX_STRIDE, writePointFeatureInstructions, writePointFeatureToBuffers } from '../../../../../src/ol/renderer/webgl/Layer.js'; @@ -249,4 +251,35 @@ describe('ol.renderer.webgl.Layer', function() { }); }); + describe('colorEncodeId and colorDecodeId', function() { + it('correctly encodes and decodes ids', function() { + expect(colorDecodeId(colorEncodeId(0))).to.eql(0); + expect(colorDecodeId(colorEncodeId(1))).to.eql(1); + expect(colorDecodeId(colorEncodeId(123))).to.eql(123); + expect(colorDecodeId(colorEncodeId(12345))).to.eql(12345); + expect(colorDecodeId(colorEncodeId(123456))).to.eql(123456); + expect(colorDecodeId(colorEncodeId(91612))).to.eql(91612); + expect(colorDecodeId(colorEncodeId(1234567890))).to.eql(1234567890); + }); + + it('correctly reuses array', function() { + const arr = []; + expect(colorEncodeId(123, arr)).to.be(arr); + }); + + it('is compatible with Uint8Array storage', function() { + const encoded = colorEncodeId(91612); + const typed = Uint8Array.of(encoded[0] * 255, encoded[1] * 255, + encoded[2] * 255, encoded[3] * 255); + const arr = [ + typed[0] / 255, + typed[1] / 255, + typed[2] / 255, + typed[3] / 255 + ]; + const decoded = colorDecodeId(arr); + expect(decoded).to.eql(91612); + }); + }); + });