UNPKG

s2maps-gpu

Version:

S2 Maps GPU - An open source, high-performance, and GPU-accelerated map engine for rendering large-scale, interactive maps.

127 lines (126 loc) 4.56 kB
import { Color, interpolate } from './index.js'; /** * Build a color ramp given a string defined ramp style or ramp guide * @param ramp - string defined ramp style or ramp guide * @param lch - whether or not to use lch * @returns Uint8ClampedArray */ export function buildColorRamp(ramp, lch = false) { const { round } = Math; // create ramp image // (4) RGBA * (5) height (base color, protanopia, deuteranopia, tritanopia, greyscale) * (255) width const rampImage = new Uint8ClampedArray(4 * 5 * 256); // prep colors let getColor; if (typeof ramp === 'string') { if (ramp === 'sinebow') /** * Bbuild a sinebow Color array from an input ramp position * @param i - ramp position * @param cbAdjust - colorblind adjustment * @returns Color as [r, g, b, a] */ getColor = (i, cbAdjust) => Color.sinebow(i).getRGB(false, cbAdjust); else /** * Build a sinebow extended Color array from an input ramp position * @param i - ramp position * @param cbAdjust - colorblind adjustment * @returns Color as [r, g, b, a] */ getColor = (i, cbAdjust) => Color.sinebowExtended(i).getRGB(false, cbAdjust); } else { const colorRamp = []; const numberRamp = []; for (const { stop, color: c } of ramp) { numberRamp.push(stop); const color = new Color(c); colorRamp.push(lch ? color.toLCH() : color.toRGB()); } /** * setup color output function * @param t - ramp position * @param cbAdjust - colorblind adjustment * @returns Color as [r, g, b, a] */ getColor = (t, cbAdjust) => { let i = 0; while (t > numberRamp[i]) i++; if (t === numberRamp[i]) return lch ? colorRamp[i].getLCH() : colorRamp[i].getRGB(false, cbAdjust); return interpolate(colorRamp[i - 1], colorRamp[i], (t - numberRamp[i - 1]) / (numberRamp[i] - numberRamp[i - 1])).getRGB(false, cbAdjust); }; } // build the ramp for base color and each colorblindness const rampMap = [ undefined, 'protanopia', 'deuteranopia', 'tritanopia', 'greyscale', ]; for (let t = 0, tl = rampMap.length; t < tl; t++) { const type = rampMap[t]; const offset = t * 256 * 4; for (let i = 0; i < 256; i++) { const [r, g, b, a] = getColor(i / 256, type); const idx = (i << 2) + offset; rampImage[idx] = round(r * a); rampImage[idx + 1] = round(g * a); rampImage[idx + 2] = round(b * a); rampImage[idx + 3] = round(a * 255); } } return rampImage; } /** * Build a dash image * @param dasharray - dash array * @param devicePixelRatio - device pixel ratio * @returns the dash image */ export function buildDashImage(dasharray, devicePixelRatio) { const { round } = Math; // RGBA * 5 height (base color, protanopia, deuteranopia, tritanopia, grayscale) * found width const dashCount = dasharray.reduce((total, current) => total + current[0] * devicePixelRatio, 0); // increase length to be divisible by 256 const length = Math.ceil(dashCount / 256) * 256; const dashImage = new Uint8ClampedArray(4 * 5 * length); // convert all strings to colors const colorDashes = dasharray.map(([size, str]) => [ size * devicePixelRatio, new Color(str), ]); const rampMap = [ undefined, 'protanopia', 'deuteranopia', 'tritanopia', 'greyscale', ]; for (let t = 0, tl = rampMap.length; t < tl; t++) { const type = rampMap[t]; const offset = t * length * 4; let pos = 0; let dashPosition = 0; while (pos < length) { const [size, color] = colorDashes[dashPosition % colorDashes.length]; const [r, g, b, a] = color.getRGB(false, type); for (let i = 0; i < size; i++) { const idx = (pos++ << 2) + offset; dashImage[idx] = round(r * a); dashImage[idx + 1] = round(g * a); dashImage[idx + 2] = round(b * a); dashImage[idx + 3] = round(a * 255); } dashPosition++; } } return { length, dashCount, image: dashImage, }; }