transfer-function.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { TextureImage } from 'mol-gl/renderable/util';
  7. import { spline } from 'mol-math/interpolate';
  8. import { ColorScale, Color } from 'mol-util/color';
  9. import { ValueCell } from 'mol-util';
  10. import { Vec2 } from 'mol-math/linear-algebra';
  11. import { ColorListName } from 'mol-util/color/scale';
  12. export interface ControlPoint { x: number, alpha: number }
  13. export function getControlPointsFromString(s: string): ControlPoint[] {
  14. return s.split(/\s*,\s*/).map(p => {
  15. const ps = p.split(/\s*:\s*/)
  16. return { x: parseFloat(ps[0]), alpha: parseFloat(ps[1]) }
  17. })
  18. }
  19. export function getControlPointsFromVec2Array(array: Vec2[]): ControlPoint[] {
  20. return array.map(v => ({ x: v[0], alpha: v[1] }))
  21. }
  22. export function createTransferFunctionTexture(controlPoints: ControlPoint[], listOrName: Color[] | ColorListName, texture?: ValueCell<TextureImage<Uint8Array>>): ValueCell<TextureImage<Uint8Array>> {
  23. const cp = [
  24. { x: 0, alpha: 0 },
  25. { x: 0, alpha: 0 },
  26. ...controlPoints,
  27. { x: 1, alpha: 0 },
  28. { x: 1, alpha: 0 },
  29. ]
  30. const scale = ColorScale.create({ domain: [0, 1], listOrName })
  31. const n = 256
  32. const array = texture ? texture.ref.value.array : new Uint8Array(n * 4)
  33. let k = 0
  34. let x1: number, x2: number
  35. let a0: number, a1: number, a2: number, a3: number
  36. const il = controlPoints.length + 1
  37. for (let i = 0; i < il; ++i) {
  38. x1 = cp[i + 1].x
  39. x2 = cp[i + 2].x
  40. a0 = cp[i].alpha
  41. a1 = cp[i + 1].alpha
  42. a2 = cp[i + 2].alpha
  43. a3 = cp[i + 3].alpha
  44. const jl = Math.round((x2 - x1) * n)
  45. for (let j = 0; j < jl; ++j) {
  46. const t = j / jl
  47. array[k * 4 + 3] = Math.max(0, spline(a0, a1, a2, a3, t, 0.5) * 255)
  48. scale.colorToArray(k / 255, array, k * 4)
  49. ++k
  50. }
  51. }
  52. const textureImage = { array, width: 256, height: 1 }
  53. if (texture) {
  54. ValueCell.update(texture, textureImage)
  55. return texture
  56. } else {
  57. return ValueCell.create(textureImage)
  58. }
  59. }