raster.d.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. import type {ChannelValueSpec} from "../channel.js";
  2. import type {Data, MarkOptions, RenderableMark} from "../mark.js";
  3. /**
  4. * The built-in spatial interpolation methods; one of:
  5. *
  6. * - *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)
  7. * - *barycentric* - apply barycentric interpolation over the Delaunay triangulation
  8. * - *random-walk* - apply a random walk from each pixel, stopping when near a sample
  9. */
  10. export type RasterInterpolateName = "nearest" | "barycentric" | "random-walk";
  11. /**
  12. * A spatial interpolation implementation function that receives samples’
  13. * positions and values and returns a flat array of *width*×*height* values.
  14. * *x*[*index*[0]] represents the *x*-position of the first sample,
  15. * *y*[*index*[0]] its *y*-position, and *value*[*index*[0]] its value (*e.g.*,
  16. * the observed height for a topographic map).
  17. */
  18. export type RasterInterpolateFunction = (
  19. /** An array of numeric indexes into the channels *x*, *y*, *value*. */
  20. index: number[],
  21. /** The width of the raster grid in pixels; a positive integer. */
  22. width: number,
  23. /** The height of the raster grid in pixels; a positive integer. */
  24. height: number,
  25. /** An array of values representing the *x*-position of samples. */
  26. x: number[],
  27. /** An array of values representing the *y*-position of samples. */
  28. y: number[],
  29. /** An array of values representing the sample’s observed value. */
  30. values: any[]
  31. ) => any[];
  32. /**
  33. * A spatial interpolation method; either a named built-in interpolation method,
  34. * or a custom interpolation function.
  35. */
  36. export type RasterInterpolate = RasterInterpolateName | RasterInterpolateFunction;
  37. /**
  38. * A source of pseudo-random numbers in [0, 1). The default source is seeded to
  39. * ensure reproducibility.
  40. */
  41. export type RandomSource = () => number;
  42. /**
  43. * A sampler function, which returns a value for the given *x* and *y* values in
  44. * the current *facet*.
  45. */
  46. export type RasterSampler = (
  47. /** The horizontal position. */
  48. x: number,
  49. /** The vertical position. */
  50. y: number,
  51. /** The current facet index, and corresponding *fx* and *fy* value. */
  52. facet: number[] & {fx: any; fy: any}
  53. ) => any;
  54. /** Options for the raster mark. */
  55. export interface RasterOptions extends Omit<MarkOptions, "fill" | "fillOpacity"> {
  56. /** The horizontal position channel, typically bound to the *x* scale. */
  57. x?: ChannelValueSpec;
  58. /** The vertical position channel, typically bound to the *y* scale. */
  59. y?: ChannelValueSpec;
  60. /**
  61. * The starting horizontal position (typically the left edge) of the raster
  62. * domain; the lower bound of the *x* scale.
  63. *
  64. * If **width** is specified, defaults to 0; otherwise, if *data* is
  65. * specified, defaults to the frame’s left coordinate in *x*. If *data* is not
  66. * specified (as when **value** is a function of *x* and *y*), you must
  67. * specify **x1** explicitly.
  68. */
  69. x1?: number;
  70. /**
  71. * The ending horizontal position (typically the right edge) of the raster
  72. * domain; the upper bound of the *x* scale.
  73. *
  74. * If **width** is specified, defaults to **width**; otherwise, if *data* is
  75. * specified, defaults to the frame’s right coordinate in *x*. If *data* is
  76. * not specified (as when **value** is a function of *x* and *y*), you must
  77. * specify **x2** explicitly.
  78. */
  79. x2?: number;
  80. /**
  81. * The starting vertical position (typically the bottom edge) of the raster
  82. * domain; the lower bound of the *y* scale.
  83. *
  84. * If **height** is specified, defaults to 0; otherwise, if *data* is
  85. * specified, defaults to the frame’s top coordinate in *y*. If *data* is not
  86. * specified (as when **value** is a function of *x* and *y*), you must
  87. * specify **y1** explicitly.
  88. */
  89. y1?: number;
  90. /**
  91. * The ending vertical position (typically the bottom edge) of the raster
  92. * domain; the lower bound of the *y* scale.
  93. *
  94. * If **height** is specified, defaults to **height**; otherwise, if *data* is
  95. * specified, defaults to the frame’s bottom coordinate in *y*. If *data* is
  96. * not specified (as when **value** is a function of *x* and *y*), you must
  97. * specify **y2** explicitly.
  98. */
  99. y2?: number;
  100. /** The width (number of columns) of the raster grid, in actual pixels. */
  101. width?: number;
  102. /** The height (number of rows) of the raster grid, in actual pixels. */
  103. height?: number;
  104. /**
  105. * The effective screen size of a raster pixel, used to determine the height
  106. * and width of the raster from the frame’s dimensions; defaults to 1.
  107. */
  108. pixelSize?: number;
  109. /**
  110. * A non-negative pixel radius for smoothing; defaults to 0. Note that
  111. * blurring is applied on the values (before the color scale is applied) if
  112. * quantitative, and after (on the materialized pixels), if ordinal.
  113. */
  114. blur?: number;
  115. /**
  116. * The spatial interpolation method, when using *data* samples. One of:
  117. *
  118. * - *none* (or null, default) - assign each sample to the containing pixel
  119. * - a named interpolation method, such as *nearest*, *barycentric*, or *random-walk*
  120. * - a custom interpolation function
  121. */
  122. interpolate?: RasterInterpolate | "none" | null;
  123. /**
  124. * The [image-rendering attribute][1]; defaults to *auto* (bilinear). The
  125. * option may be set to *pixelated* to disable bilinear interpolation for a
  126. * sharper image; however, note that this is not supported in WebKit.
  127. *
  128. * [1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering
  129. */
  130. imageRendering?: string;
  131. /**
  132. * The fill, typically bound to the *color* scale. Can be specified as a
  133. * constant, a channel based on the sample *data*, or as a function *f*(*x*,
  134. * *y*) to be evaluated at each pixel if the *data* is not provided.
  135. */
  136. fill?: ChannelValueSpec | RasterSampler;
  137. /**
  138. * The opacity, typically bound to the *opacity* scale. Can be specified as a
  139. * constant, a channel based on the sample *data*, or as a function *f*(*x*,
  140. * *y*) to be evaluated at each pixel if the *data* is not provided.
  141. */
  142. fillOpacity?: ChannelValueSpec | RasterSampler;
  143. }
  144. /**
  145. * Returns a raster mark which renders a raster image from spatial samples. If
  146. * *data* is provided, it represents discrete samples in abstract coordinates
  147. * **x** and **y**; the **fill** and **fillOpacity** channels specify further
  148. * abstract values (_e.g._, height in a topographic map) to be spatially
  149. * interpolated to produce an image.
  150. *
  151. * ```js
  152. * Plot.raster(volcano.values, {width: volcano.width, height: volcano.height})
  153. * ```
  154. *
  155. * The **fill** and **fillOpacity** channels may alternatively be specified as
  156. * functions *f*(*x*, *y*) to be evaluated at each pixel centroid of the raster
  157. * grid (without interpolation).
  158. *
  159. * ```js
  160. * Plot.raster({x1: -1, x2: 1, y1: -1, y2: 1, fill: (x, y) => Math.atan2(y, x)})
  161. * ```
  162. *
  163. * If **width** is specified, **x1** defaults to 0 and **x2** defaults to
  164. * **width**; likewise, if **height** is specified, **y1** defaults to 0 and
  165. * **y2** defaults to **height**. Otherwise, if *data* is specified, **x1**,
  166. * **y1**, **x2**, and **y2** respectively default to the frame’s left, top,
  167. * right, and bottom coordinates. Lastly, if *data* is not specified (as when
  168. * **value** is a function of *x* and *y*), you must specify all of **x1**,
  169. * **x2**, **y1**, and **y2** to define the raster domain.
  170. */
  171. export function raster(data?: Data, options?: RasterOptions): Raster;
  172. export function raster(options?: RasterOptions): Raster;
  173. /**
  174. * Applies a simple forward mapping of samples, binning them into pixels in the
  175. * raster grid without any blending or interpolation. If multiple samples map to
  176. * the same pixel, the last one wins; this can introduce bias if the points are
  177. * not in random order, so use Plot.shuffle to randomize the input if needed.
  178. */
  179. export const interpolateNone: RasterInterpolateFunction;
  180. /**
  181. * Constructs a Delaunay triangulation of the samples, and then for each pixel
  182. * in the raster grid, determines the triangle that covers the pixel’s centroid
  183. * and interpolates the values associated with the triangle’s vertices using
  184. * [barycentric coordinates][1]. If the interpolated values are ordinal or
  185. * categorical (_i.e._, anything other than numbers or dates), then one of the
  186. * three values will be picked randomly weighted by the barycentric coordinates;
  187. * the given *random* number generator will be used, which defaults to a [linear
  188. * congruential generator][2] with a fixed seed (for deterministic results).
  189. *
  190. * [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system
  191. * [2]: https://d3js.org/d3-random#randomLcg
  192. */
  193. export function interpolatorBarycentric(options?: {random?: RandomSource}): RasterInterpolateFunction;
  194. /**
  195. * Assigns each pixel in the raster grid the value of the closest sample;
  196. * effectively a Voronoi diagram.
  197. */
  198. export const interpolateNearest: RasterInterpolateFunction;
  199. /**
  200. * For each pixel in the raster grid, initiates a random walk, stopping when
  201. * either the walk is within a given distance (**minDistance**) of a sample or
  202. * the maximum allowable number of steps (**maxSteps**) have been taken, and
  203. * then assigning the current pixel the closest sample’s value. The random walk
  204. * uses the “walk on spheres” algorithm in two dimensions described by [Sawhney
  205. * and Crane][1], SIGGRAPH 2020.
  206. *
  207. * [1]: https://www.cs.cmu.edu/~kmcrane/Projects/MonteCarloGeometryProcessing/index.html
  208. */
  209. export function interpolatorRandomWalk(options?: {
  210. /**
  211. * An optional source of pseudo-random numbers in [0, 1). Called at each step
  212. * of the random walk algorithm with arguments *x*, *y*, and *step*. If not
  213. * specified, defaults to a seeded random number generator.
  214. */
  215. random?: RandomSource;
  216. /**
  217. * The random walk ends by “snapping” to the closest sample if closer than
  218. * this distance (in pixels).
  219. */
  220. minDistance?: number;
  221. /**
  222. * After this number of steps, which defaults to 3, lift the **minDistance**
  223. * requirement and snap to the closest sample.
  224. */
  225. maxSteps?: number;
  226. }): RasterInterpolateFunction;
  227. /** The raster mark. */
  228. export class Raster extends RenderableMark {}