@mark1russell7/packing 0.2.2 → 0.2.4
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/README.md +11 -0
- package/build/index.d.ts +63 -26
- package/build/index.d.ts.map +1 -1
- package/build/index.js +312 -19
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters.ts +30 -5
- package/src/free.ts +3 -0
- package/src/index.ts +1 -1
- package/src/measures.ts +35 -3
- package/src/moves.ts +47 -0
- package/src/pack.ts +18 -4
- package/src/shelf.ts +203 -0
- package/src/skyline.ts +34 -7
package/src/skyline.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { countMove, MOVES } from "./moves.ts";
|
|
1
2
|
import { compareRects, type SortOrder } from "./order.ts";
|
|
2
3
|
import type { Rect } from "./rect.ts";
|
|
3
4
|
import type { FreeSpace } from "./space.ts";
|
|
@@ -11,6 +12,19 @@ import type { FreeSpace } from "./space.ts";
|
|
|
11
12
|
* `limit[x, x + rw)`. A second deque keeps that smallest value. No valid window gives the height `Infinity`.
|
|
12
13
|
*/
|
|
13
14
|
export function lowestWindow(skyline: ArrayLike<number>, width: number, rw: number, limit?: ArrayLike<number>, rh = 0): { x: number; y: number } {
|
|
15
|
+
const { x, y } = findWindow(skyline, width, rw, limit, rh);
|
|
16
|
+
return { x, y };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** The lowest window of `findWindow`, and `first`: the x of the leftmost valid window, or `-1` */
|
|
20
|
+
interface Window {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
first: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** This function is `lowestWindow`, and it also gives the x of the leftmost valid window. */
|
|
27
|
+
function findWindow(skyline: ArrayLike<number>, width: number, rw: number, limit?: ArrayLike<number>, rh = 0): Window {
|
|
14
28
|
if (limit !== undefined) return lowestLimitedWindow(skyline, limit, width, rw, rh);
|
|
15
29
|
const deque = new Int32Array(width);
|
|
16
30
|
let head = 0;
|
|
@@ -29,11 +43,16 @@ export function lowestWindow(skyline: ArrayLike<number>, width: number, rw: numb
|
|
|
29
43
|
}
|
|
30
44
|
}
|
|
31
45
|
}
|
|
32
|
-
return { x: bestX, y: bestY };
|
|
46
|
+
return { x: bestX, y: bestY, first: width >= rw ? 0 : -1 };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** This function counts the move of the skyline: a window that is lower than the leftmost valid window. */
|
|
50
|
+
function countWindow(w: Window): void {
|
|
51
|
+
if (Number.isFinite(w.y) && w.first >= 0 && w.x !== w.first) countMove(MOVES.skyline);
|
|
33
52
|
}
|
|
34
53
|
|
|
35
54
|
/** This function is `lowestWindow` with a limit for each cell. */
|
|
36
|
-
function lowestLimitedWindow(skyline: ArrayLike<number>, limit: ArrayLike<number>, width: number, rw: number, rh: number):
|
|
55
|
+
function lowestLimitedWindow(skyline: ArrayLike<number>, limit: ArrayLike<number>, width: number, rw: number, rh: number): Window {
|
|
37
56
|
const high = new Int32Array(width);
|
|
38
57
|
const low = new Int32Array(width);
|
|
39
58
|
let hh = 0;
|
|
@@ -42,6 +61,7 @@ function lowestLimitedWindow(skyline: ArrayLike<number>, limit: ArrayLike<number
|
|
|
42
61
|
let lt = 0;
|
|
43
62
|
let bestX = 0;
|
|
44
63
|
let bestY = Infinity;
|
|
64
|
+
let first = -1;
|
|
45
65
|
for (let i = 0; i < width; i++) {
|
|
46
66
|
while (ht > hh && skyline[high[ht - 1]!]! <= skyline[i]!) ht--;
|
|
47
67
|
high[ht++] = i;
|
|
@@ -51,13 +71,15 @@ function lowestLimitedWindow(skyline: ArrayLike<number>, limit: ArrayLike<number
|
|
|
51
71
|
if (low[lh]! <= i - rw) lh++;
|
|
52
72
|
if (i >= rw - 1) {
|
|
53
73
|
const max = skyline[high[hh]!]!;
|
|
54
|
-
|
|
74
|
+
const valid = max + rh <= limit[low[lh]!]!;
|
|
75
|
+
if (valid && first < 0) first = i - rw + 1;
|
|
76
|
+
if (max < bestY && valid) {
|
|
55
77
|
bestY = max;
|
|
56
78
|
bestX = i - rw + 1;
|
|
57
79
|
}
|
|
58
80
|
}
|
|
59
81
|
}
|
|
60
|
-
return { x: bestX, y: bestY };
|
|
82
|
+
return { x: bestX, y: bestY, first };
|
|
61
83
|
}
|
|
62
84
|
|
|
63
85
|
/** The options of `packSkyline` */
|
|
@@ -116,8 +138,10 @@ export function packSkyline<T>(rects: Rect<T>[], outer: Rect<T>, options: Skylin
|
|
|
116
138
|
y = 0;
|
|
117
139
|
for (let i = 0; i < width; i++) if (skyline[i]! > y) y = skyline[i]!;
|
|
118
140
|
} else {
|
|
119
|
-
|
|
141
|
+
const found = findWindow(skyline, width, rw);
|
|
142
|
+
({ x, y } = found);
|
|
120
143
|
if (outer.fixedSize && y + rh > outer.size.y) continue;
|
|
144
|
+
countWindow(found);
|
|
121
145
|
}
|
|
122
146
|
|
|
123
147
|
rect.position.set(x + outer.position.x, y + outer.position.y);
|
|
@@ -179,7 +203,8 @@ function packSkylineInSpace<T>(rects: Rect<T>[], outer: Rect<T>, order: SortOrde
|
|
|
179
203
|
outer.size.y = Math.max(outer.size.y, y + rh);
|
|
180
204
|
continue;
|
|
181
205
|
}
|
|
182
|
-
|
|
206
|
+
let found = findWindow(skyline, width, rw, limit, rh);
|
|
207
|
+
({ x, y } = found);
|
|
183
208
|
let sky: Float64Array = skyline;
|
|
184
209
|
let lim: Float64Array = limit;
|
|
185
210
|
if (!Number.isFinite(y)) {
|
|
@@ -189,10 +214,12 @@ function packSkylineInSpace<T>(rects: Rect<T>[], outer: Rect<T>, order: SortOrde
|
|
|
189
214
|
for (let i = 0; i < width; i++) {
|
|
190
215
|
while (Number.isFinite(lim[i]!) && lim[i]! - sky[i]! < rh && lim[i]! < end) [sky[i], lim[i]] = rangeOf(i, lim[i]!);
|
|
191
216
|
}
|
|
192
|
-
|
|
217
|
+
found = findWindow(sky, width, rw, lim, rh);
|
|
218
|
+
({ x, y } = found);
|
|
193
219
|
if (!Number.isFinite(y)) continue;
|
|
194
220
|
}
|
|
195
221
|
|
|
222
|
+
countWindow(found);
|
|
196
223
|
rect.position.set(x + ox, y + oy);
|
|
197
224
|
rect.wasPacked = true;
|
|
198
225
|
const top = y + rh;
|