@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 +28 -26
- package/README.md +51 -5
- package/circle.d.ts +15 -0
- package/circle.js +21 -1
- package/clipping.d.ts +42 -0
- package/clipping.js +76 -0
- package/column-ends.js +1 -1
- package/diagonal-ends.js +1 -1
- package/diagonal.js +1 -1
- package/flood-fill.d.ts +37 -0
- package/flood-fill.js +81 -0
- package/hilbert.js +1 -1
- package/hvline.d.ts +2 -0
- package/hvline.js +21 -1
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/line.d.ts +15 -0
- package/line.js +20 -1
- package/package.json +21 -9
- package/random.js +1 -1
- package/row-ends.js +1 -1
- package/spiral.js +1 -1
- package/utils.d.ts +0 -2
- package/utils.js +0 -2
- package/zcurve.js +1 -1
- package/zigzag-columns.js +1 -1
- package/zigzag-diagonal.js +1 -1
- package/zigzag-rows.js +1 -1
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
30
|
+
### Features
|
|
31
31
|
|
|
32
|
-
**
|
|
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
|
|
40
|
-
|
|
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:
|
|
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
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
package/flood-fill.d.ts
ADDED
|
@@ -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
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 "
|
|
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 "
|
|
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.
|
|
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/
|
|
39
|
-
"@thi.ng/
|
|
40
|
-
"@thi.ng/
|
|
41
|
-
"@thi.ng/
|
|
42
|
-
"@thi.ng/
|
|
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.
|
|
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": "
|
|
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
package/spiral.js
CHANGED
package/utils.d.ts
CHANGED
package/utils.js
CHANGED
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
package/zigzag-diagonal.js
CHANGED
package/zigzag-rows.js
CHANGED