@thi.ng/grid-iterators 2.0.4 → 2.1.2

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
@@ -3,7 +3,7 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [2.0.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@2.0.3...@thi.ng/grid-iterators@2.0.4) (2021-10-25)
6
+ ## [2.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@2.1.1...@thi.ng/grid-iterators@2.1.2) (2021-11-10)
7
7
 
8
8
  **Note:** Version bump only for package @thi.ng/grid-iterators
9
9
 
@@ -11,7 +11,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
11
11
 
12
12
 
13
13
 
14
- ## [2.0.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@2.0.2...@thi.ng/grid-iterators@2.0.3) (2021-10-15)
14
+ ## [2.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@2.1.0...@thi.ng/grid-iterators@2.1.1) (2021-11-04)
15
15
 
16
16
  **Note:** Version bump only for package @thi.ng/grid-iterators
17
17
 
@@ -19,17 +19,19 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
19
19
 
20
20
 
21
21
 
22
- ## [2.0.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@2.0.1...@thi.ng/grid-iterators@2.0.2) (2021-10-15)
23
-
24
- **Note:** Version bump only for package @thi.ng/grid-iterators
22
+ # [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@2.0.6...@thi.ng/grid-iterators@2.1.0) (2021-11-03)
25
23
 
26
24
 
25
+ ### Bug Fixes
27
26
 
27
+ * **grid-iterators:** fix imports, readme ([adff976](https://github.com/thi-ng/umbrella/commit/adff976f8b370108fbc29796a39f243513bc5504))
28
28
 
29
29
 
30
- ## [2.0.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@2.0.0...@thi.ng/grid-iterators@2.0.1) (2021-10-13)
30
+ ### Features
31
31
 
32
- **Note:** Version bump only for package @thi.ng/grid-iterators
32
+ * **grid-iterators:** add clipped shape iterators ([611f0da](https://github.com/thi-ng/umbrella/commit/611f0da940ab05e1e88b3daafb6cacb8297580a5))
33
+ * **grid-iterators:** add floodFill(), update deps ([4634cf1](https://github.com/thi-ng/umbrella/commit/4634cf14aed00837068ffa6a77735f5ab04faf73))
34
+ * **pixel:** add flood fill functions ([65796b9](https://github.com/thi-ng/umbrella/commit/65796b96fe77d5c4b999dd8cedfd142ea243a200))
33
35
 
34
36
 
35
37
 
@@ -64,39 +66,39 @@ Also:
64
66
 
65
67
 
66
68
 
67
- ## [1.0.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@1.0.4...@thi.ng/grid-iterators@1.0.5) (2021-09-03)
69
+ ## [1.0.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@1.0.4...@thi.ng/grid-iterators@1.0.5) (2021-09-03)
68
70
 
69
- **Note:** Version bump only for package @thi.ng/grid-iterators
71
+ **Note:** Version bump only for package @thi.ng/grid-iterators
70
72
 
71
- ## [0.4.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.4.23...@thi.ng/grid-iterators@0.4.24) (2021-03-03)
73
+ ## [0.4.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.4.23...@thi.ng/grid-iterators@0.4.24) (2021-03-03)
72
74
 
73
- ### Bug Fixes
75
+ ### Bug Fixes
74
76
 
75
- - **grid-iterators:** enforce int coords ([e8e570f](https://github.com/thi-ng/umbrella/commit/e8e570fa57640569554084a846cbde54966c0b06))
77
+ - **grid-iterators:** enforce int coords ([e8e570f](https://github.com/thi-ng/umbrella/commit/e8e570fa57640569554084a846cbde54966c0b06))
76
78
 
77
- # [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.3.17...@thi.ng/grid-iterators@0.4.0) (2020-06-20)
79
+ # [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.3.17...@thi.ng/grid-iterators@0.4.0) (2020-06-20)
78
80
 
79
- ### Features
81
+ ### Features
80
82
 
81
- - **grid-iterators:** add new iterators ([e08985e](https://github.com/thi-ng/umbrella/commit/e08985ee07a2bc449e4f2126191a96261ef6dfb0))
83
+ - **grid-iterators:** add new iterators ([e08985e](https://github.com/thi-ng/umbrella/commit/e08985ee07a2bc449e4f2126191a96261ef6dfb0))
82
84
 
83
- # [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.2.3...@thi.ng/grid-iterators@0.3.0) (2020-02-25)
85
+ # [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.2.3...@thi.ng/grid-iterators@0.3.0) (2020-02-25)
84
86
 
85
- ### Features
87
+ ### Features
86
88
 
87
- - **grid-iterators:** add line & circle iterators ([a6b757d](https://github.com/thi-ng/umbrella/commit/a6b757dd350e46404bfd2f82e58d8a3bc2c5b133))
89
+ - **grid-iterators:** add line & circle iterators ([a6b757d](https://github.com/thi-ng/umbrella/commit/a6b757dd350e46404bfd2f82e58d8a3bc2c5b133))
88
90
 
89
- # [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.1.0...@thi.ng/grid-iterators@0.2.0) (2019-11-09)
91
+ # [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/grid-iterators@0.1.0...@thi.ng/grid-iterators@0.2.0) (2019-11-09)
90
92
 
91
- ### Features
93
+ ### Features
92
94
 
93
- - **grid-iterators:** add interleave fns ([c883ea0](https://github.com/thi-ng/umbrella/commit/c883ea03d9a37698533d981a96f7122828731364))
94
- - **grid-iterators:** add z-curve & random iterators, add deps ([ba8ed18](https://github.com/thi-ng/umbrella/commit/ba8ed18cd84db77ccb35ed95586c66151cf1d690))
95
- - **grid-iterators:** add zigzagDiagonal(), update readme, rename files ([5630055](https://github.com/thi-ng/umbrella/commit/56300557f395698f82b453c79956ada72726444a))
96
- - **grid-iterators:** make row args optional ([60dccfc](https://github.com/thi-ng/umbrella/commit/60dccfcb0ba1d731eeecd4c12433d44b5491e7a7))
95
+ - **grid-iterators:** add interleave fns ([c883ea0](https://github.com/thi-ng/umbrella/commit/c883ea03d9a37698533d981a96f7122828731364))
96
+ - **grid-iterators:** add z-curve & random iterators, add deps ([ba8ed18](https://github.com/thi-ng/umbrella/commit/ba8ed18cd84db77ccb35ed95586c66151cf1d690))
97
+ - **grid-iterators:** add zigzagDiagonal(), update readme, rename files ([5630055](https://github.com/thi-ng/umbrella/commit/56300557f395698f82b453c79956ada72726444a))
98
+ - **grid-iterators:** make row args optional ([60dccfc](https://github.com/thi-ng/umbrella/commit/60dccfcb0ba1d731eeecd4c12433d44b5491e7a7))
97
99
 
98
- # 0.1.0 (2019-09-21)
100
+ # 0.1.0 (2019-09-21)
99
101
 
100
- ### Features
102
+ ### Features
101
103
 
102
104
  - **grid-iterators:** import as new package, incl. assets ([fe4ee00](https://github.com/thi-ng/umbrella/commit/fe4ee00))
package/README.md CHANGED
@@ -22,6 +22,7 @@ This project is part of the
22
22
  - [Zigzag columns](#zigzag-columns)
23
23
  - [Zigzag diagonal](#zigzag-diagonal)
24
24
  - [Zigzag rows](#zigzag-rows)
25
+ - [Flood filling](#flood-filling)
25
26
  - [Miscellaneous](#miscellaneous)
26
27
  - [Status](#status)
27
28
  - [Related packages](#related-packages)
@@ -34,10 +35,11 @@ This project is part of the
34
35
 
35
36
  ## About
36
37
 
37
- 2D grid iterators w/ multiple orderings.
38
+ 2D grid and shape iterators w/ multiple orderings.
38
39
 
39
- Provides the 15 following orderings to generate grid coordinates and
40
- additional iterators for shape rasterization:
40
+ Provides the altogether 25 following orderings to generate grid coordinates,
41
+ including iterators for shape rasterization, drawing, clipping, filling,
42
+ processing in general:
41
43
 
42
44
  ### Columns
43
45
 
@@ -138,9 +140,50 @@ For more basic 2D/3D grid iteration, also see `range2d()` & `range3d()`
138
140
  in
139
141
  [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers).
140
142
 
143
+ ### Flood filling
144
+
145
+ The `floodFill()` iterator can be used to iterate arbitrary 2D grids using an
146
+ user-provided predicate function. The function recursively explores (in a
147
+ row-major manner) the space in the `[0,0]..(width,height)` interval, starting at
148
+ given `x,y` and continues as long given predicate function returns a truthy
149
+ value. Any eligible 90-degree connected regions will be found and iterated
150
+ recursively. The predicate function is used to select eligible grid cells
151
+ (e.g. "pixels" of sorts).
152
+
153
+ ```ts
154
+ // source "image"
155
+ const img = [
156
+ "█", " ", " ", " ", "█",
157
+ "█", " ", "█", " ", " ",
158
+ " ", " ", "█", " ", "█",
159
+ " ", "█", "█", " ", " ",
160
+ " ", " ", " ", "█", "█",
161
+ ];
162
+
163
+ // flood fill iterator from point (1,0)
164
+ // only accept " " as source pixel value
165
+ // image size is 5x5
166
+ const region = floodFill((x, y) => img[x + y * 5] === " ", 1, 0, 5, 5);
167
+
168
+ // label filled pixels using increasing ASCII values
169
+ let ascii = 65; // "A"
170
+ for(let [x,y] of region) img[x + y * 5] = String.fromCharCode(ascii++);
171
+
172
+ // result image showing fill order
173
+ img
174
+ // [
175
+ // "█", "A", "B", "C", "█",
176
+ // "█", "I", "█", "D", "E",
177
+ // "K", "J", "█", "F", "█",
178
+ // "L", "█", "█", "G", "H",
179
+ // "M", "N", "O", "█", "█"
180
+ // ]
181
+ ```
182
+
141
183
  ### Miscellaneous
142
184
 
143
- Additionally, the following shape iterators are available:
185
+ Additionally, the following shape iterators are available, all also with
186
+ optional clipping:
144
187
 
145
188
  - [circle](https://github.com/thi-ng/umbrella/tree/develop/packages/grid-iterators/src/circle.ts) (Bresenham)
146
189
  - [hline](https://github.com/thi-ng/umbrella/tree/develop/packages/grid-iterators/src/hvline.ts)
@@ -156,6 +199,7 @@ Additionally, the following shape iterators are available:
156
199
  ### Related packages
157
200
 
158
201
  - [@thi.ng/morton](https://github.com/thi-ng/umbrella/tree/develop/packages/morton) - Z-order curve / Morton encoding, decoding & range extraction for arbitrary dimensions
202
+ - [@thi.ng/rasterize](https://github.com/thi-ng/umbrella/tree/develop/packages/rasterize) - 2D shape drawing & rasterization
159
203
  - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers) - Lightweight transducer implementations for ES6 / TypeScript
160
204
 
161
205
  ## Installation
@@ -181,12 +225,14 @@ node --experimental-repl-await
181
225
  > const gridIterators = await import("@thi.ng/grid-iterators");
182
226
  ```
183
227
 
184
- Package sizes (gzipped, pre-treeshake): ESM: 1.50 KB
228
+ Package sizes (gzipped, pre-treeshake): ESM: 2.22 KB
185
229
 
186
230
  ## Dependencies
187
231
 
232
+ - [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api)
188
233
  - [@thi.ng/arrays](https://github.com/thi-ng/umbrella/tree/develop/packages/arrays)
189
234
  - [@thi.ng/binary](https://github.com/thi-ng/umbrella/tree/develop/packages/binary)
235
+ - [@thi.ng/bitfield](https://github.com/thi-ng/umbrella/tree/develop/packages/bitfield)
190
236
  - [@thi.ng/morton](https://github.com/thi-ng/umbrella/tree/develop/packages/morton)
191
237
  - [@thi.ng/random](https://github.com/thi-ng/umbrella/tree/develop/packages/random)
192
238
  - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers)
package/circle.d.ts CHANGED
@@ -1,2 +1,17 @@
1
1
  export declare function circle(cx: number, cy: number, r: number, fill?: boolean): Generator<number[], void, unknown>;
2
+ /**
3
+ * Version of {@link circle} yielding only coordinates in rect defined by
4
+ * `left,top`..`right,bottom`. Returns undefined if circle lies completely
5
+ * outside given clip rectangle.
6
+ *
7
+ * @param cx
8
+ * @param cy
9
+ * @param r
10
+ * @param left
11
+ * @param top
12
+ * @param right
13
+ * @param bottom
14
+ * @param fill
15
+ */
16
+ export declare const circleClipped: (cx: number, cy: number, r: number, left: number, top: number, right: number, bottom: number, fill?: boolean) => Generator<number[], void, unknown> | undefined;
2
17
  //# sourceMappingURL=circle.d.ts.map
package/circle.js CHANGED
@@ -1,5 +1,6 @@
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
+ import { clipped, intersectRectCircle } from "./clipping.js";
1
3
  import { hline } from "./hvline.js";
2
- import { asInt } from "./utils.js";
3
4
  export function* circle(cx, cy, r, fill = true) {
4
5
  [cx, cy, r] = asInt(cx, cy, r);
5
6
  if (r < 1)
@@ -51,3 +52,22 @@ export function* circle(cx, cy, r, fill = true) {
51
52
  dx2 += 2;
52
53
  }
53
54
  }
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;
73
+ };
package/clipping.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ import type { FnU7, FnU8, Tuple } from "@thi.ng/api";
2
+ /**
3
+ * Filters points from `src` iterable to remove any falling outside the rect
4
+ * defined by `left,top`..`right,bottom`.
5
+ *
6
+ * @param src
7
+ * @param left
8
+ * @param top
9
+ * @param right
10
+ * @param bottom
11
+ */
12
+ export declare function clipped(src: Iterable<number[]>, left: number, top: number, right: number, bottom: number): Generator<number[], void, unknown>;
13
+ /**
14
+ * Based on {@link @thi.ng/geom-isec}, but inlined to avoid dependency.
15
+ *
16
+ * @param x
17
+ * @param y
18
+ * @param w
19
+ * @param h
20
+ * @param cx
21
+ * @param cy
22
+ * @param r
23
+ *
24
+ * @internal
25
+ */
26
+ export declare const intersectRectCircle: FnU7<number, boolean>;
27
+ /**
28
+ * Based on {@link @thi.ng/geom-clip-line#liangBarsky2Raw}, but with diff return type.
29
+ *
30
+ * @param ax
31
+ * @param ay
32
+ * @param bx
33
+ * @param by
34
+ * @param minx
35
+ * @param miny
36
+ * @param maxx
37
+ * @param maxy
38
+ *
39
+ * @internal
40
+ */
41
+ export declare const liangBarsky: FnU8<number, Tuple<number, 4> | undefined>;
42
+ //# sourceMappingURL=clipping.d.ts.map
package/clipping.js ADDED
@@ -0,0 +1,76 @@
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
+ }
16
+ }
17
+ /** @internal */
18
+ const axis = (a, b, c) => (a < b ? a - b : a > b + c ? a - b - c : 0) ** 2;
19
+ /**
20
+ * Based on {@link @thi.ng/geom-isec}, but inlined to avoid dependency.
21
+ *
22
+ * @param x
23
+ * @param y
24
+ * @param w
25
+ * @param h
26
+ * @param cx
27
+ * @param cy
28
+ * @param r
29
+ *
30
+ * @internal
31
+ */
32
+ export const intersectRectCircle = (x, y, w, h, cx, cy, r) => axis(cx, x, w) + axis(cy, y, h) <= r * r;
33
+ /**
34
+ * Based on {@link @thi.ng/geom-clip-line#liangBarsky2Raw}, but with diff return type.
35
+ *
36
+ * @param ax
37
+ * @param ay
38
+ * @param bx
39
+ * @param by
40
+ * @param minx
41
+ * @param miny
42
+ * @param maxx
43
+ * @param maxy
44
+ *
45
+ * @internal
46
+ */
47
+ export const liangBarsky = (ax, ay, bx, by, minx, miny, maxx, maxy) => {
48
+ const dx = bx - ax;
49
+ const dy = by - ay;
50
+ let alpha = 0;
51
+ let beta = 1;
52
+ const clip = (p, q) => {
53
+ if (p < 0) {
54
+ const r = q / p;
55
+ if (r > beta)
56
+ return false;
57
+ r > alpha && (alpha = r);
58
+ }
59
+ else if (p > 0) {
60
+ const r = q / p;
61
+ if (r < alpha)
62
+ return false;
63
+ r < beta && (beta = r);
64
+ }
65
+ else if (q < 0) {
66
+ return false;
67
+ }
68
+ return true;
69
+ };
70
+ return clip(-dx, ax - minx) &&
71
+ clip(dx, maxx - ax) &&
72
+ clip(-dy, ay - miny) &&
73
+ clip(dy, maxy - ay)
74
+ ? [alpha * dx + ax, alpha * dy + ay, beta * dx + ax, beta * dy + ay]
75
+ : undefined;
76
+ };
package/column-ends.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Filtered version of {@link columns2d}, only including end points of
4
4
  * each column.
package/diagonal-ends.js CHANGED
@@ -1,5 +1,5 @@
1
+ import { asInt } from "@thi.ng/api/typedarray";
1
2
  import { diagonal2d } from "./diagonal.js";
2
- import { asInt } from "./utils.js";
3
3
  /**
4
4
  * Filtered version of {@link diagonal2d}, only including end points of
5
5
  * the diagonals, apart from the very first and last points: `[0,0]` and
package/diagonal.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Yields sequence of 2D grid coordinates in diagonal order starting at
4
4
  * [0,0] and using given `cols` and `rows`. Each diagonal starts at y=0
@@ -0,0 +1,37 @@
1
+ import type { Predicate2 } from "@thi.ng/api";
2
+ /**
3
+ * Yields an iterator of 2D coordinates of the connected region around `x,y` for
4
+ * which the given predicate succeeds. I.e. The function recursively explores
5
+ * (in a row-major manner) the space in the `[0,0]..(width,height)` interval,
6
+ * starting at given `x,y` and continues as long given predicate function
7
+ * returns a truthy value.
8
+ *
9
+ * @remarks
10
+ * Only the behavior is recursive, not the actual implementation (stack based).
11
+ * Grid cells are visited max. once. A bit field is used to mark visited cells.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const img = [
16
+ * 1,0,1,0,
17
+ * 0,0,0,0,
18
+ * 0,1,1,0,
19
+ * 0,1,1,1,
20
+ * ];
21
+ *
22
+ * // flood fill connected region from point (2,1)
23
+ * [...floodFill((x, y) => img[y * 4 + x] === 0, 2, 1, 4, 4)]
24
+ * // [
25
+ * // [2, 1], [1, 1], [0, 1], [3, 1], [3, 2],
26
+ * // [3, 0], [0, 2], [0, 3], [1, 0]
27
+ * // ]
28
+ * ```
29
+ *
30
+ * @param pred
31
+ * @param x
32
+ * @param y
33
+ * @param width
34
+ * @param height
35
+ */
36
+ export declare function floodFill(pred: Predicate2<number>, x: number, y: number, width: number, height: number): Generator<number[], void, unknown>;
37
+ //# sourceMappingURL=flood-fill.d.ts.map
package/flood-fill.js ADDED
@@ -0,0 +1,81 @@
1
+ import { defBitField } from "@thi.ng/bitfield/bitfield";
2
+ /**
3
+ * Yields an iterator of 2D coordinates of the connected region around `x,y` for
4
+ * which the given predicate succeeds. I.e. The function recursively explores
5
+ * (in a row-major manner) the space in the `[0,0]..(width,height)` interval,
6
+ * starting at given `x,y` and continues as long given predicate function
7
+ * returns a truthy value.
8
+ *
9
+ * @remarks
10
+ * Only the behavior is recursive, not the actual implementation (stack based).
11
+ * Grid cells are visited max. once. A bit field is used to mark visited cells.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const img = [
16
+ * 1,0,1,0,
17
+ * 0,0,0,0,
18
+ * 0,1,1,0,
19
+ * 0,1,1,1,
20
+ * ];
21
+ *
22
+ * // flood fill connected region from point (2,1)
23
+ * [...floodFill((x, y) => img[y * 4 + x] === 0, 2, 1, 4, 4)]
24
+ * // [
25
+ * // [2, 1], [1, 1], [0, 1], [3, 1], [3, 2],
26
+ * // [3, 0], [0, 2], [0, 3], [1, 0]
27
+ * // ]
28
+ * ```
29
+ *
30
+ * @param pred
31
+ * @param x
32
+ * @param y
33
+ * @param width
34
+ * @param height
35
+ */
36
+ export function* floodFill(pred, x, y, width, height) {
37
+ x |= 0;
38
+ y |= 0;
39
+ if (!pred(x, y))
40
+ return;
41
+ const queue = [[x, y]];
42
+ const visited = defBitField(width * height);
43
+ height--;
44
+ while (queue.length) {
45
+ [x, y] = queue.pop();
46
+ yield* partialRow(pred, queue, visited, x, y, width, height, -1);
47
+ yield* partialRow(pred, queue, visited, x + 1, y, width, height, 1);
48
+ }
49
+ }
50
+ /** @internal */
51
+ function* partialRow(pred, queue, visited, x, y, width, height1, step) {
52
+ let idx = y * width + x;
53
+ if (visited.at(idx))
54
+ return;
55
+ let scanUp = false;
56
+ let scanDown = false;
57
+ while (x >= 0 && x < width && pred(x, y)) {
58
+ visited.setAt(idx);
59
+ yield [x, y];
60
+ if (y > 0) {
61
+ if (pred(x, y - 1) && !scanUp) {
62
+ queue.push([x, y - 1]);
63
+ scanUp = true;
64
+ }
65
+ else {
66
+ scanUp = false;
67
+ }
68
+ }
69
+ if (y < height1) {
70
+ if (pred(x, y + 1) && !scanDown) {
71
+ queue.push([x, y + 1]);
72
+ scanDown = true;
73
+ }
74
+ else {
75
+ scanDown = false;
76
+ }
77
+ }
78
+ x += step;
79
+ idx += step;
80
+ }
81
+ }
package/hilbert.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Yields sequence of 2D grid coordinates along 2D Hilbert curve using
4
4
  * given `cols` and `rows` (each max. 32768 (2^15)).
package/hvline.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export declare function hline(x: number, y: number, len: number): Generator<number[], void, unknown>;
2
2
  export declare function vline(x: number, y: number, len: number): Generator<number[], void, unknown>;
3
+ export declare function hlineClipped(x: number, y: number, len: number, left: number, top: number, right: number, bottom: number): Generator<number[], void, unknown>;
4
+ export declare function vlineClipped(x: number, y: number, len: number, left: number, top: number, right: number, bottom: number): Generator<number[], void, unknown>;
3
5
  //# sourceMappingURL=hvline.d.ts.map
package/hvline.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  export function* hline(x, y, len) {
3
3
  [x, y, len] = asInt(x, y, len);
4
4
  for (const xmax = x + len; x < xmax; x++) {
@@ -11,3 +11,23 @@ export function* vline(x, y, len) {
11
11
  yield [x, y];
12
12
  }
13
13
  }
14
+ export function* hlineClipped(x, y, len, left, top, right, bottom) {
15
+ [x, y, len] = asInt(x, y, len);
16
+ if (x >= right || y < top || y >= bottom)
17
+ return;
18
+ if (x < left) {
19
+ len += x - left;
20
+ x = left;
21
+ }
22
+ yield* hline(x, y, Math.min(len, right - x));
23
+ }
24
+ export function* vlineClipped(x, y, len, left, top, right, bottom) {
25
+ [x, y, len] = asInt(x, y, len);
26
+ if (x < left || x >= right || y >= bottom)
27
+ return;
28
+ if (y < top) {
29
+ len += y - top;
30
+ y = top;
31
+ }
32
+ yield* vline(x, y, Math.min(len, bottom - y));
33
+ }
package/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  export * from "./circle.js";
2
+ export * from "./clipping.js";
2
3
  export * from "./column-ends.js";
3
4
  export * from "./columns.js";
4
5
  export * from "./diagonal.js";
5
6
  export * from "./diagonal-ends.js";
7
+ export * from "./flood-fill.js";
6
8
  export * from "./hilbert.js";
7
9
  export * from "./hvline.js";
8
10
  export * from "./interleave.js";
package/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  export * from "./circle.js";
2
+ export * from "./clipping.js";
2
3
  export * from "./column-ends.js";
3
4
  export * from "./columns.js";
4
5
  export * from "./diagonal.js";
5
6
  export * from "./diagonal-ends.js";
7
+ export * from "./flood-fill.js";
6
8
  export * from "./hilbert.js";
7
9
  export * from "./hvline.js";
8
10
  export * from "./interleave.js";
package/line.d.ts CHANGED
@@ -1,2 +1,17 @@
1
1
  export declare function line(ax: number, ay: number, bx: number, by: number): Generator<number[], void, unknown>;
2
+ /**
3
+ * Version of {@link line} yielding only coordinates in rect defined by
4
+ * `left,top`..`right,bottom`. Returns undefined if circle lies completely
5
+ * outside given clip rectangle.
6
+ *
7
+ * @param x1
8
+ * @param y1
9
+ * @param x2
10
+ * @param y2
11
+ * @param left
12
+ * @param top
13
+ * @param right
14
+ * @param bottom
15
+ */
16
+ export declare const lineClipped: (x1: number, y1: number, x2: number, y2: number, left: number, top: number, right: number, bottom: number) => Generator<number[], void, unknown> | undefined;
2
17
  //# sourceMappingURL=line.d.ts.map
package/line.js CHANGED
@@ -1,4 +1,5 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
+ import { liangBarsky } from "./clipping.js";
2
3
  export function* line(ax, ay, bx, by) {
3
4
  [ax, ay, bx, by] = asInt(ax, ay, bx, by);
4
5
  const dx = Math.abs(bx - ax);
@@ -21,3 +22,21 @@ export function* line(ax, ay, bx, by) {
21
22
  }
22
23
  }
23
24
  }
25
+ /**
26
+ * Version of {@link line} yielding only coordinates in rect defined by
27
+ * `left,top`..`right,bottom`. Returns undefined if circle lies completely
28
+ * outside given clip rectangle.
29
+ *
30
+ * @param x1
31
+ * @param y1
32
+ * @param x2
33
+ * @param y2
34
+ * @param left
35
+ * @param top
36
+ * @param right
37
+ * @param bottom
38
+ */
39
+ export const lineClipped = (x1, y1, x2, y2, left, top, right, bottom) => {
40
+ const res = liangBarsky(x1, y1, x2, y2, left, top, right, bottom);
41
+ return res ? line(res[0], res[1], res[2], res[3]) : undefined;
42
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@thi.ng/grid-iterators",
3
- "version": "2.0.4",
4
- "description": "2D grid iterators w/ multiple orderings",
3
+ "version": "2.1.2",
4
+ "description": "2D grid and shape iterators w/ multiple orderings",
5
5
  "type": "module",
6
6
  "module": "./index.js",
7
7
  "typings": "./index.d.ts",
@@ -35,23 +35,28 @@
35
35
  "test": "testament test"
36
36
  },
37
37
  "dependencies": {
38
- "@thi.ng/arrays": "^2.0.4",
39
- "@thi.ng/binary": "^3.0.4",
40
- "@thi.ng/morton": "^3.0.4",
41
- "@thi.ng/random": "^3.1.0",
42
- "@thi.ng/transducers": "^8.0.4"
38
+ "@thi.ng/api": "^8.2.0",
39
+ "@thi.ng/arrays": "^2.0.8",
40
+ "@thi.ng/binary": "^3.0.8",
41
+ "@thi.ng/bitfield": "^2.0.8",
42
+ "@thi.ng/morton": "^3.0.8",
43
+ "@thi.ng/random": "^3.1.4",
44
+ "@thi.ng/transducers": "^8.0.8"
43
45
  },
44
46
  "devDependencies": {
45
- "@thi.ng/testament": "^0.1.4"
47
+ "@thi.ng/testament": "^0.1.6"
46
48
  },
47
49
  "keywords": [
48
50
  "2d",
49
51
  "binary",
50
52
  "circle",
53
+ "clipping",
51
54
  "diagonal",
55
+ "floodfill",
52
56
  "grid",
53
57
  "hilbert",
54
58
  "iterator",
59
+ "line",
55
60
  "morton",
56
61
  "random",
57
62
  "spiral",
@@ -76,6 +81,9 @@
76
81
  "./circle": {
77
82
  "import": "./circle.js"
78
83
  },
84
+ "./clipping": {
85
+ "import": "./clipping.js"
86
+ },
79
87
  "./column-ends": {
80
88
  "import": "./column-ends.js"
81
89
  },
@@ -88,6 +96,9 @@
88
96
  "./diagonal": {
89
97
  "import": "./diagonal.js"
90
98
  },
99
+ "./flood-fill": {
100
+ "import": "./flood-fill.js"
101
+ },
91
102
  "./hilbert": {
92
103
  "import": "./hilbert.js"
93
104
  },
@@ -128,9 +139,10 @@
128
139
  "thi.ng": {
129
140
  "related": [
130
141
  "morton",
142
+ "rasterize",
131
143
  "transducers"
132
144
  ],
133
145
  "year": 2019
134
146
  },
135
- "gitHead": "9ff00a103f76cc4917ef3f244132e218f2300a05"
147
+ "gitHead": "5fe52419af63984ebe53032201b2a6174b9cb159"
136
148
  }
package/random.js CHANGED
@@ -1,7 +1,7 @@
1
+ import { asInt } from "@thi.ng/api/typedarray";
1
2
  import { shuffle } from "@thi.ng/arrays/shuffle";
2
3
  import { SYSTEM } from "@thi.ng/random/system";
3
4
  import { range } from "@thi.ng/transducers/range";
4
- import { asInt } from "./utils.js";
5
5
  /**
6
6
  * Yields 2D grid coordinates in random order w/ support for optional
7
7
  * {@link @thi.ng/random#IRandom} implementation (default:
package/row-ends.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Filtered version of {@link rows2d}, only including end points of
4
4
  * each row.
package/spiral.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Yields sequence of 2D grid coordinates in outward spiral order
4
4
  * starting from the center, given `cols` and `rows`.
package/utils.d.ts CHANGED
@@ -6,6 +6,4 @@
6
6
  * @internal
7
7
  */
8
8
  export declare const swapxy: (p: number[]) => number[];
9
- /** @internal */
10
- export declare const asInt: (...args: number[]) => number[];
11
9
  //# sourceMappingURL=utils.d.ts.map
package/utils.js CHANGED
@@ -12,5 +12,3 @@ export const swapxy = (p) => {
12
12
  p[1] = t;
13
13
  return p;
14
14
  };
15
- /** @internal */
16
- export const asInt = (...args) => args.map((x) => x | 0);
package/zcurve.js CHANGED
@@ -1,6 +1,6 @@
1
+ import { asInt } from "@thi.ng/api/typedarray";
1
2
  import { ceilPow2 } from "@thi.ng/binary/pow";
2
3
  import { demux2 } from "@thi.ng/morton/mux";
3
- import { asInt } from "./utils.js";
4
4
  /**
5
5
  * Yields 2D grid coordinates in Z-curve (Morton) order. A perfect
6
6
  * Z-curve is only generated if `cols` AND `rows` are equal and a power
package/zigzag-columns.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Yields sequence of 2D grid coordinates in zigzag column order
4
4
  * starting from [0,0], given `cols` and `rows`.
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Similar to {@link diagonal2d}, but yields 2D grid coordinates in zigzag
4
4
  * diagonal order starting at [0,0] and using given `cols` and `rows`.
package/zigzag-rows.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asInt } from "./utils.js";
1
+ import { asInt } from "@thi.ng/api/typedarray";
2
2
  /**
3
3
  * Yields sequence of 2D grid coordinates in zigzag row order starting
4
4
  * from [0,0], given `cols` and `rows`.