halton2DSequence.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /**
  2. * Class for generating 2D Halton sequences.
  3. * From https://observablehq.com/@jrus/halton
  4. */
  5. export class Halton2DSequence {
  6. /**
  7. * Creates a new Halton2DSequence.
  8. * @param numSamples Number of samples in the sequence.
  9. * @param baseX The base for the x coordinate (default: 2).
  10. * @param baseY The base for the y coordinate (default: 3).
  11. * @param width Factor to scale the x coordinate by (default: 1). The scaling factor is 1/width.
  12. * @param height Factor to scale the y coordinate by (default: 1). The scaling factor is 1/height.
  13. */
  14. constructor(numSamples, baseX = 2, baseY = 3, width = 1, height = 1) {
  15. this._curIndex = 0;
  16. this._sequence = [];
  17. this._numSamples = 0;
  18. /**
  19. * The x coordinate of the current sample.
  20. */
  21. this.x = 0;
  22. /**
  23. * The y coordinate of the current sample.
  24. */
  25. this.y = 0;
  26. this._width = width;
  27. this._height = height;
  28. this._baseX = baseX;
  29. this._baseY = baseY;
  30. this._generateSequence(numSamples);
  31. this.next();
  32. }
  33. /**
  34. * Regenerates the sequence with a new number of samples.
  35. * @param numSamples Number of samples in the sequence.
  36. */
  37. regenerate(numSamples) {
  38. this._generateSequence(numSamples);
  39. this.next();
  40. }
  41. /**
  42. * Sets the dimensions of the sequence.
  43. * @param width Factor to scale the x coordinate by. The scaling factor is 1/width.
  44. * @param height Factor to scale the y coordinate by. The scaling factor is 1/height.
  45. */
  46. setDimensions(width, height) {
  47. this._width = width;
  48. this._height = height;
  49. }
  50. /**
  51. * Advances to the next sample in the sequence.
  52. */
  53. next() {
  54. this.x = this._sequence[this._curIndex] / this._width;
  55. this.y = this._sequence[this._curIndex + 1] / this._height;
  56. this._curIndex += 2;
  57. if (this._curIndex >= this._numSamples * 2) {
  58. this._curIndex = 0;
  59. }
  60. }
  61. _generateSequence(numSamples) {
  62. this._sequence = [];
  63. this._curIndex = 0;
  64. this._numSamples = numSamples;
  65. for (let i = 1; i <= numSamples; ++i) {
  66. this._sequence.push(this._halton(i, this._baseX) - 0.5, this._halton(i, this._baseY) - 0.5);
  67. }
  68. }
  69. _halton(index, base) {
  70. let fraction = 1;
  71. let result = 0;
  72. while (index > 0) {
  73. fraction /= base;
  74. result += fraction * (index % base);
  75. index = ~~(index / base); // floor division
  76. }
  77. return result;
  78. }
  79. }
  80. //# sourceMappingURL=halton2DSequence.js.map