@thi.ng/grid-iterators 4.0.35 → 4.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-09T19:12:03Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
package/README.md CHANGED
@@ -241,7 +241,7 @@ For Node.js REPL:
241
241
  const gridIterators = await import("@thi.ng/grid-iterators");
242
242
  ```
243
243
 
244
- Package sizes (brotli'd, pre-treeshake): ESM: 2.58 KB
244
+ Package sizes (brotli'd, pre-treeshake): ESM: 2.61 KB
245
245
 
246
246
  ## Dependencies
247
247
 
package/api.js CHANGED
@@ -1 +0,0 @@
1
- export {};
package/circle.js CHANGED
@@ -1,73 +1,60 @@
1
1
  import { asInt } from "@thi.ng/api/typedarray";
2
2
  import { clipped, intersectRectCircle } from "./clipping.js";
3
3
  import { hline } from "./hvline.js";
4
- export function* circle(cx, cy, r, fill = true) {
5
- [cx, cy, r] = asInt(cx, cy, r);
6
- if (r < 1)
7
- return;
8
- let x = 0;
9
- let y = r;
10
- let y2 = r * r;
11
- let sum = y2 + r;
12
- let dx2 = 1;
13
- let dy2 = 2 * r - 1;
14
- while (x <= y) {
15
- if (fill) {
16
- yield* hline(cx - y, cy + x, y << 1);
17
- if (x)
18
- yield* hline(cx - y, cy - x, y << 1);
4
+ function* circle(cx, cy, r, fill = true) {
5
+ [cx, cy, r] = asInt(cx, cy, r);
6
+ if (r < 1)
7
+ return;
8
+ let x = 0;
9
+ let y = r;
10
+ let y2 = r * r;
11
+ let sum = y2 + r;
12
+ let dx2 = 1;
13
+ let dy2 = 2 * r - 1;
14
+ while (x <= y) {
15
+ if (fill) {
16
+ yield* hline(cx - y, cy + x, y << 1);
17
+ if (x)
18
+ yield* hline(cx - y, cy - x, y << 1);
19
+ } else {
20
+ yield [cx - y, cy + x];
21
+ if (y)
22
+ yield [cx + y, cy + x];
23
+ if (x) {
24
+ yield [cx - y, cy - x];
25
+ if (y)
26
+ yield [cx + y, cy - x];
27
+ }
28
+ if (x !== y) {
29
+ yield [cx - x, cy - y];
30
+ if (x)
31
+ yield [cx + x, cy - y];
32
+ if (y) {
33
+ yield [cx - x, cy + y];
34
+ if (x)
35
+ yield [cx + x, cy + y];
19
36
  }
20
- else {
21
- yield [cx - y, cy + x];
22
- if (y)
23
- yield [cx + y, cy + x];
24
- if (x) {
25
- yield [cx - y, cy - x];
26
- if (y)
27
- yield [cx + y, cy - x];
28
- }
29
- if (x !== y) {
30
- yield [cx - x, cy - y];
31
- if (x)
32
- yield [cx + x, cy - y];
33
- if (y) {
34
- yield [cx - x, cy + y];
35
- if (x)
36
- yield [cx + x, cy + y];
37
- }
38
- }
39
- }
40
- sum -= dx2;
41
- if (sum <= y2) {
42
- if (fill && x !== y) {
43
- yield* hline(cx - x, cy - y, x << 1);
44
- if (y)
45
- yield* hline(cx - x, cy + y, x << 1);
46
- }
47
- y--;
48
- y2 -= dy2;
49
- dy2 -= 2;
50
- }
51
- x++;
52
- dx2 += 2;
37
+ }
53
38
  }
39
+ sum -= dx2;
40
+ if (sum <= y2) {
41
+ if (fill && x !== y) {
42
+ yield* hline(cx - x, cy - y, x << 1);
43
+ if (y)
44
+ yield* hline(cx - x, cy + y, x << 1);
45
+ }
46
+ y--;
47
+ y2 -= dy2;
48
+ dy2 -= 2;
49
+ }
50
+ x++;
51
+ dx2 += 2;
52
+ }
54
53
  }
55
- /**
56
- * Version of {@link circle} yielding only coordinates in rect defined by
57
- * `left,top`..`right,bottom`. Returns undefined if circle lies completely
58
- * outside given clip rectangle.
59
- *
60
- * @param cx -
61
- * @param cy -
62
- * @param r -
63
- * @param left -
64
- * @param top -
65
- * @param right -
66
- * @param bottom -
67
- * @param fill -
68
- */
69
- export const circleClipped = (cx, cy, r, left, top, right, bottom, fill = true) => {
70
- return intersectRectCircle(left, top, right, bottom, cx, cy, r)
71
- ? clipped(circle(cx, cy, r, fill), left, top, right, bottom)
72
- : undefined;
54
+ const circleClipped = (cx, cy, r, left, top, right, bottom, fill = true) => {
55
+ return intersectRectCircle(left, top, right, bottom, cx, cy, r) ? clipped(circle(cx, cy, r, fill), left, top, right, bottom) : void 0;
56
+ };
57
+ export {
58
+ circle,
59
+ circleClipped
73
60
  };
package/clipping.js CHANGED
@@ -1,77 +1,36 @@
1
- /**
2
- * Filters points from `src` iterable to remove any falling outside the rect
3
- * defined by `left,top`..`right,bottom`.
4
- *
5
- * @param src -
6
- * @param left -
7
- * @param top -
8
- * @param right -
9
- * @param bottom -
10
- */
11
- export function* clipped(src, left, top, right, bottom) {
12
- for (let p of src) {
13
- if (p[0] >= left && p[0] < right && p[1] >= top && p[1] < bottom)
14
- yield p;
15
- }
1
+ function* clipped(src, left, top, right, bottom) {
2
+ for (let p of src) {
3
+ if (p[0] >= left && p[0] < right && p[1] >= top && p[1] < bottom)
4
+ yield p;
5
+ }
16
6
  }
17
- /** @internal */
18
7
  const axis = (a, b, c) => (a < b ? a - b : a > b + c ? a - b - c : 0) ** 2;
19
- /**
20
- * Based on [thi.ng/geom-isec](https://thi.ng/geom-isec), but inlined to avoid
21
- * dependency.
22
- *
23
- * @param x -
24
- * @param y -
25
- * @param w -
26
- * @param h -
27
- * @param cx -
28
- * @param cy -
29
- * @param r -
30
- *
31
- * @internal
32
- */
33
- export const intersectRectCircle = (x, y, w, h, cx, cy, r) => axis(cx, x, w) + axis(cy, y, h) <= r * r;
34
- /**
35
- * Based on [`liangBarsky2Raw()`](https://docs.thi.ng/umbrella/geom-clip-line/functions/liangBarsky2Raw.html), but with diff return type.
36
- *
37
- * @param ax -
38
- * @param ay -
39
- * @param bx -
40
- * @param by -
41
- * @param minx -
42
- * @param miny -
43
- * @param maxx -
44
- * @param maxy -
45
- *
46
- * @internal
47
- */
48
- export const liangBarsky = (ax, ay, bx, by, minx, miny, maxx, maxy) => {
49
- const dx = bx - ax;
50
- const dy = by - ay;
51
- let alpha = 0;
52
- let beta = 1;
53
- const clip = (p, q) => {
54
- if (p < 0) {
55
- const r = q / p;
56
- if (r > beta)
57
- return false;
58
- r > alpha && (alpha = r);
59
- }
60
- else if (p > 0) {
61
- const r = q / p;
62
- if (r < alpha)
63
- return false;
64
- r < beta && (beta = r);
65
- }
66
- else if (q < 0) {
67
- return false;
68
- }
69
- return true;
70
- };
71
- return clip(-dx, ax - minx) &&
72
- clip(dx, maxx - ax) &&
73
- clip(-dy, ay - miny) &&
74
- clip(dy, maxy - ay)
75
- ? [alpha * dx + ax, alpha * dy + ay, beta * dx + ax, beta * dy + ay]
76
- : undefined;
8
+ const intersectRectCircle = (x, y, w, h, cx, cy, r) => axis(cx, x, w) + axis(cy, y, h) <= r * r;
9
+ const liangBarsky = (ax, ay, bx, by, minx, miny, maxx, maxy) => {
10
+ const dx = bx - ax;
11
+ const dy = by - ay;
12
+ let alpha = 0;
13
+ let beta = 1;
14
+ const clip = (p, q) => {
15
+ if (p < 0) {
16
+ const r = q / p;
17
+ if (r > beta)
18
+ return false;
19
+ r > alpha && (alpha = r);
20
+ } else if (p > 0) {
21
+ const r = q / p;
22
+ if (r < alpha)
23
+ return false;
24
+ r < beta && (beta = r);
25
+ } else if (q < 0) {
26
+ return false;
27
+ }
28
+ return true;
29
+ };
30
+ return clip(-dx, ax - minx) && clip(dx, maxx - ax) && clip(-dy, ay - miny) && clip(dy, maxy - ay) ? [alpha * dx + ax, alpha * dy + ay, beta * dx + ax, beta * dy + ay] : void 0;
31
+ };
32
+ export {
33
+ clipped,
34
+ intersectRectCircle,
35
+ liangBarsky
77
36
  };
package/column-ends.js CHANGED
@@ -1,15 +1,12 @@
1
1
  import { __opts } from "./utils.js";
2
- /**
3
- * Filtered version of {@link columns2d}, only including end points of
4
- * each column.
5
- *
6
- * @param opts -
7
- */
8
- export function* columnEnds2d(opts) {
9
- let { cols, rows, tx } = __opts(opts);
10
- rows--;
11
- for (let x = 0; x < cols; x++) {
12
- yield tx(x, 0);
13
- yield tx(x, rows);
14
- }
2
+ function* columnEnds2d(opts) {
3
+ let { cols, rows, tx } = __opts(opts);
4
+ rows--;
5
+ for (let x = 0; x < cols; x++) {
6
+ yield tx(x, 0);
7
+ yield tx(x, rows);
8
+ }
15
9
  }
10
+ export {
11
+ columnEnds2d
12
+ };
package/columns.js CHANGED
@@ -1,11 +1,9 @@
1
1
  import { repeatedly2d } from "@thi.ng/transducers/repeatedly2d";
2
2
  import { __opts } from "./utils.js";
3
- /**
4
- * Yields sequence of 2D grid coordinates in column-major order.
5
- *
6
- * @param opts -
7
- */
8
- export const columns2d = (opts) => {
9
- const { cols, rows, tx } = __opts(opts);
10
- return repeatedly2d((y, x) => tx(x, y), rows | 0, cols | 0);
3
+ const columns2d = (opts) => {
4
+ const { cols, rows, tx } = __opts(opts);
5
+ return repeatedly2d((y, x) => tx(x, y), rows | 0, cols | 0);
6
+ };
7
+ export {
8
+ columns2d
11
9
  };
package/diagonal-ends.js CHANGED
@@ -1,28 +1,21 @@
1
1
  import { diagonal2d } from "./diagonal.js";
2
2
  import { __opts } from "./utils.js";
3
- /**
4
- * Filtered version of {@link diagonal2d}, only including end points of the
5
- * diagonals. Unless `all` option is enabled (default: false), the very first
6
- * and last points are skipped, i.e. `[0,0]` and `[cols-1, rows-1]`.
7
- *
8
- * @remarks
9
- * `cols` and `rows` MUST be both >= 2.
10
- *
11
- * @param opts -
12
- */
13
- export function* diagonalEnds2d(opts) {
14
- const { cols, rows, tx } = __opts(opts);
15
- const num = cols * rows - 1;
16
- const maxX = cols - 1;
17
- const maxY = rows - 1;
18
- const check = opts.all ? (i) => i > 0 && i < num : () => true;
19
- let i = 0;
20
- for (let p of diagonal2d({ cols, rows })) {
21
- if (check(i)) {
22
- const [x, y] = p;
23
- if (x === 0 || x === maxX || y === 0 || y === maxY)
24
- yield tx(x, y);
25
- }
26
- i++;
3
+ function* diagonalEnds2d(opts) {
4
+ const { cols, rows, tx } = __opts(opts);
5
+ const num = cols * rows - 1;
6
+ const maxX = cols - 1;
7
+ const maxY = rows - 1;
8
+ const check = opts.all ? (i2) => i2 > 0 && i2 < num : () => true;
9
+ let i = 0;
10
+ for (let p of diagonal2d({ cols, rows })) {
11
+ if (check(i)) {
12
+ const [x, y] = p;
13
+ if (x === 0 || x === maxX || y === 0 || y === maxY)
14
+ yield tx(x, y);
27
15
  }
16
+ i++;
17
+ }
28
18
  }
19
+ export {
20
+ diagonalEnds2d
21
+ };
package/diagonal-slope.js CHANGED
@@ -1,112 +1,80 @@
1
1
  import { assert } from "@thi.ng/errors/assert";
2
2
  import { __opts } from "./utils.js";
3
- /**
4
- * Similar to {@link diagonalSlopeX}. Yields sequence of 2D grid coordinates in
5
- * diagonal order with configurable slope, starting at [0,0]. Each diagonal
6
- * starts at y=0 and progresses in +y direction and every `step` steps, one
7
- * step in -x direction.
8
- *
9
- * @example
10
- * ```ts
11
- * // iterate grid in diagonals of 1:3 ratio (x:y)
12
- * [...diagonalSlopeY({ cols: 5, step: 3 })]
13
- * // [
14
- * // [0, 0], [0, 1 ], [0, 2 ],
15
- * // [1, 0], [1, 1 ], [1, 2 ],
16
- * // [0, 3], [0, 4 ], [2, 0 ],
17
- * // [2, 1], [2, 2 ], [1, 3 ],
18
- * // [1, 4], [3, 0 ], [3, 1 ],
19
- * // [3, 2], [2, 3 ], [2, 4 ],
20
- * // [4, 0], [4, 1 ], [4, 2 ],
21
- * // [3, 3], [3, 4 ], [4, 3 ],
22
- * // [4, 4]
23
- * // ]
24
- * ```
25
- *
26
- * @param opts -
27
- */
28
- export function* diagonalSlopeY(opts) {
29
- const { cols, rows, tx } = __opts(opts);
30
- const maxX = cols - 1;
31
- const slope = opts.slope | 0;
32
- assert(slope > 0, "slope must be > 0");
33
- const num = cols * rows - 1;
34
- let x = 0;
35
- let y = 0;
36
- let nx = Math.min(1, maxX);
37
- let ny = nx > 0 ? 0 : slope;
38
- let n = slope;
39
- const reset = () => {
3
+ function* diagonalSlopeY(opts) {
4
+ const { cols, rows, tx } = __opts(opts);
5
+ const maxX = cols - 1;
6
+ const slope = opts.slope | 0;
7
+ assert(slope > 0, "slope must be > 0");
8
+ const num = cols * rows - 1;
9
+ let x = 0;
10
+ let y = 0;
11
+ let nx = Math.min(1, maxX);
12
+ let ny = nx > 0 ? 0 : slope;
13
+ let n = slope;
14
+ const reset = () => {
15
+ n = slope;
16
+ x = nx;
17
+ y = ny;
18
+ if (nx < maxX)
19
+ nx++;
20
+ else
21
+ ny += slope;
22
+ };
23
+ for (let i = 0; i <= num; i++) {
24
+ yield tx(x, y);
25
+ if (--n > 0) {
26
+ y++;
27
+ if (y >= rows)
28
+ reset();
29
+ } else {
30
+ x--;
31
+ y++;
32
+ if (x < 0 || y >= rows)
33
+ reset();
34
+ else
40
35
  n = slope;
41
- x = nx;
42
- y = ny;
43
- if (nx < maxX)
44
- nx++;
45
- else
46
- ny += slope;
47
- };
48
- for (let i = 0; i <= num; i++) {
49
- yield tx(x, y);
50
- if (--n > 0) {
51
- y++;
52
- if (y >= rows)
53
- reset();
54
- }
55
- else {
56
- x--;
57
- y++;
58
- if (x < 0 || y >= rows)
59
- reset();
60
- else
61
- n = slope;
62
- }
63
36
  }
37
+ }
64
38
  }
65
- /**
66
- * Similar to {@link diagonalSlopeY}. Yields sequence of 2D grid coordinates in
67
- * diagonal order with configurable slope, starting at [step-1,0]. Each
68
- * diagonal starts at y=0 and progresses in -x direction and every `step`
69
- * steps, one step in +y direction.
70
- *
71
- * @param opts -
72
- */
73
- export function* diagonalSlopeX(opts) {
74
- const { cols, rows, tx } = __opts(opts);
75
- const maxX = cols - 1;
76
- const slope = opts.slope | 0;
77
- assert(slope > 0, "slope must be > 0");
78
- const num = cols * rows - 1;
79
- let x = Math.min(slope - 1, maxX);
80
- let y = 0;
81
- let n = x + 1;
82
- let nx = Math.min(x + slope, maxX);
83
- let ny = nx > 0 ? 0 : slope;
84
- const reset = () => {
85
- x = nx;
86
- y = ny;
87
- if (nx < maxX) {
88
- nx = Math.min(nx + slope, maxX);
89
- n = slope;
90
- }
91
- else {
92
- ny++;
93
- n = (x % slope) + 1;
94
- }
95
- };
96
- for (let i = 0; i <= num; i++) {
97
- yield tx(x, y);
98
- if (--n > 0) {
99
- x--;
100
- if (x < 0)
101
- reset();
102
- }
103
- else {
104
- x--;
105
- y++;
106
- if (x < 0 || y >= rows)
107
- reset();
108
- else
109
- n = slope;
110
- }
39
+ function* diagonalSlopeX(opts) {
40
+ const { cols, rows, tx } = __opts(opts);
41
+ const maxX = cols - 1;
42
+ const slope = opts.slope | 0;
43
+ assert(slope > 0, "slope must be > 0");
44
+ const num = cols * rows - 1;
45
+ let x = Math.min(slope - 1, maxX);
46
+ let y = 0;
47
+ let n = x + 1;
48
+ let nx = Math.min(x + slope, maxX);
49
+ let ny = nx > 0 ? 0 : slope;
50
+ const reset = () => {
51
+ x = nx;
52
+ y = ny;
53
+ if (nx < maxX) {
54
+ nx = Math.min(nx + slope, maxX);
55
+ n = slope;
56
+ } else {
57
+ ny++;
58
+ n = x % slope + 1;
111
59
  }
60
+ };
61
+ for (let i = 0; i <= num; i++) {
62
+ yield tx(x, y);
63
+ if (--n > 0) {
64
+ x--;
65
+ if (x < 0)
66
+ reset();
67
+ } else {
68
+ x--;
69
+ y++;
70
+ if (x < 0 || y >= rows)
71
+ reset();
72
+ else
73
+ n = slope;
74
+ }
75
+ }
112
76
  }
77
+ export {
78
+ diagonalSlopeX,
79
+ diagonalSlopeY
80
+ };
package/diagonal.js CHANGED
@@ -1,32 +1,24 @@
1
1
  import { __opts } from "./utils.js";
2
- /**
3
- * Yields sequence of 2D grid coordinates in diagonal order starting at [0,0]
4
- * and using given `cols` and `rows`. Each diagonal starts at y=0 and progresses
5
- * in -x,+y direction.
6
- *
7
- * Ported & modified from original Java code by Christopher Kulla.
8
- * https://sourceforge.net/p/sunflow/code/HEAD/tree/trunk/src/org/sunflow/core/bucket/DiagonalBucketOrder.java
9
- *
10
- * @param opts -
11
- */
12
- export function* diagonal2d(opts) {
13
- const { cols, rows, tx } = __opts(opts);
14
- const num = cols * rows - 1;
15
- for (let x = 0, y = 0, nx = 1, ny = 0, i = 0; i <= num; i++) {
16
- yield tx(x, y);
17
- if (i !== num) {
18
- do {
19
- if (y === ny) {
20
- y = 0;
21
- x = nx;
22
- ny++;
23
- nx++;
24
- }
25
- else {
26
- x--;
27
- y++;
28
- }
29
- } while (y >= rows || x >= cols);
2
+ function* diagonal2d(opts) {
3
+ const { cols, rows, tx } = __opts(opts);
4
+ const num = cols * rows - 1;
5
+ for (let x = 0, y = 0, nx = 1, ny = 0, i = 0; i <= num; i++) {
6
+ yield tx(x, y);
7
+ if (i !== num) {
8
+ do {
9
+ if (y === ny) {
10
+ y = 0;
11
+ x = nx;
12
+ ny++;
13
+ nx++;
14
+ } else {
15
+ x--;
16
+ y++;
30
17
  }
18
+ } while (y >= rows || x >= cols);
31
19
  }
20
+ }
32
21
  }
22
+ export {
23
+ diagonal2d
24
+ };