protosprite-geom 0.2.5 → 0.3.0
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/dist/src/trace/trace.js +28 -28
- package/dist/src/trace/trace.js.map +1 -1
- package/package.json +4 -3
- package/src/trace/trace.ts +26 -28
- package/src/types/marchingsquares.d.ts +0 -22
package/dist/src/trace/trace.js
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { contours } from 'd3-contour';
|
|
2
2
|
import { Vec2Data } from '../core/data.js';
|
|
3
3
|
|
|
4
4
|
function traceContours(imageData, alphaThreshold = 1) {
|
|
5
5
|
const { width, height, data } = imageData;
|
|
6
|
-
// Build a
|
|
6
|
+
// Build a 1D flat array of alpha values with 1px of zero-padding on all sides.
|
|
7
7
|
// This ensures marching squares can properly close contours when opaque
|
|
8
|
-
// pixels touch the image edge, without producing a spurious outer loop
|
|
9
|
-
// (which the library's built-in frame does).
|
|
8
|
+
// pixels touch the image edge, without producing a spurious outer loop.
|
|
10
9
|
const paddedW = width + 2;
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
grid.push(new Array(paddedW).fill(0));
|
|
10
|
+
const paddedH = height + 2;
|
|
11
|
+
const grid = new Array(paddedW * paddedH).fill(0);
|
|
14
12
|
for (let y = 0; y < height; y++) {
|
|
15
|
-
const row = [0]; // left padding
|
|
16
13
|
for (let x = 0; x < width; x++) {
|
|
17
|
-
const
|
|
18
|
-
|
|
14
|
+
const srcIdx = (y * width + x) * 4;
|
|
15
|
+
// d3-contour indexes as values[i + j * width] where i=col, j=row
|
|
16
|
+
const dstIdx = (x + 1) + (y + 1) * paddedW;
|
|
17
|
+
grid[dstIdx] = data[srcIdx + 3]; // alpha channel
|
|
19
18
|
}
|
|
20
|
-
row.push(0); // right padding
|
|
21
|
-
grid.push(row);
|
|
22
19
|
}
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
// Run marching squares via d3-contour on the padded grid.
|
|
21
|
+
// smooth(false) produces staircase edges matching the original behavior.
|
|
22
|
+
const generator = contours()
|
|
23
|
+
.size([paddedW, paddedH])
|
|
24
|
+
.smooth(false);
|
|
25
|
+
const multiPolygon = generator.contour(grid, alphaThreshold);
|
|
26
|
+
// Extract rings from the GeoJSON MultiPolygon, subtracting the 1px padding offset.
|
|
29
27
|
const result = [];
|
|
30
|
-
for (const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
for (const polygon of multiPolygon.coordinates) {
|
|
29
|
+
for (const ring of polygon) {
|
|
30
|
+
if (ring.length < 3)
|
|
31
|
+
continue;
|
|
32
|
+
const polyVerts = [];
|
|
33
|
+
for (const [px, py] of ring) {
|
|
34
|
+
const v = new Vec2Data();
|
|
35
|
+
v.x = px - 1;
|
|
36
|
+
v.y = py - 1;
|
|
37
|
+
polyVerts.push(v);
|
|
38
|
+
}
|
|
39
|
+
result.push(polyVerts);
|
|
39
40
|
}
|
|
40
|
-
result.push(polygon);
|
|
41
41
|
}
|
|
42
42
|
return result;
|
|
43
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.js","sources":["../../../src/trace/trace.ts"],"sourcesContent":[null],"names":[],"mappings":";;;SAUgB,aAAa,CAC3B,SAAwB,EACxB,iBAAyB,CAAC,EAAA;IAE1B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS
|
|
1
|
+
{"version":3,"file":"trace.js","sources":["../../../src/trace/trace.ts"],"sourcesContent":[null],"names":[],"mappings":";;;SAUgB,aAAa,CAC3B,SAAwB,EACxB,iBAAyB,CAAC,EAAA;IAE1B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS;;;;AAKzC,IAAA,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC;AACzB,IAAA,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC;AAC1B,IAAA,MAAM,IAAI,GAAG,IAAI,KAAK,CAAS,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAEzD,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE;AAC/B,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;YAC9B,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC;;AAElC,YAAA,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,OAAO;AAC1C,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClC;IACF;;;IAIA,MAAM,SAAS,GAAG,QAAQ;AACvB,SAAA,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC;SACvB,MAAM,CAAC,KAAK,CAAC;IAEhB,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC;;IAG5D,MAAM,MAAM,GAAiB,EAAE;AAC/B,IAAA,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,WAAW,EAAE;AAC9C,QAAA,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE;AAC1B,YAAA,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE;YACrB,MAAM,SAAS,GAAe,EAAE;YAChC,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE;AAC3B,gBAAA,MAAM,CAAC,GAAG,IAAI,QAAQ,EAAE;AACxB,gBAAA,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACZ,gBAAA,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACZ,gBAAA,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YACnB;AACA,YAAA,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QACxB;IACF;AAEA,IAAA,OAAO,MAAM;AACf;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "protosprite-geom",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "Polygon geometry tracing and encoding for protosprite",
|
|
6
6
|
"main": "dist/core.js",
|
|
7
7
|
"types": "dist/src/core/index.d.ts",
|
|
@@ -45,16 +45,17 @@
|
|
|
45
45
|
"@bufbuild/buf": "^1.56.0",
|
|
46
46
|
"@bufbuild/protobuf": "^2.7.0",
|
|
47
47
|
"@bufbuild/protoc-gen-es": "^2.7.0",
|
|
48
|
+
"d3-contour": "^4.0.2",
|
|
48
49
|
"jimp": "^1.6.0",
|
|
49
|
-
"marchingsquares": "^1.3.3",
|
|
50
50
|
"poly-decomp": "^0.3.0",
|
|
51
|
-
"protosprite-core": "^0.
|
|
51
|
+
"protosprite-core": "^0.3.0",
|
|
52
52
|
"simplify-js": "^1.2.4",
|
|
53
53
|
"tslib": "^2.8.1",
|
|
54
54
|
"typescript": "^5.9.2"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@rollup/plugin-typescript": "^12.1.4",
|
|
58
|
+
"@types/d3-contour": "^3.0.6",
|
|
58
59
|
"rollup": "^4.48.1"
|
|
59
60
|
},
|
|
60
61
|
"gitHead": "842676edbb77aff985b2d3acd67324be4cecd753"
|
package/src/trace/trace.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { contours } from "d3-contour";
|
|
2
2
|
|
|
3
3
|
import { Vec2Data } from "../core/data.js";
|
|
4
4
|
|
|
@@ -14,46 +14,44 @@ export function traceContours(
|
|
|
14
14
|
): Vec2Data[][] {
|
|
15
15
|
const { width, height, data } = imageData;
|
|
16
16
|
|
|
17
|
-
// Build a
|
|
17
|
+
// Build a 1D flat array of alpha values with 1px of zero-padding on all sides.
|
|
18
18
|
// This ensures marching squares can properly close contours when opaque
|
|
19
|
-
// pixels touch the image edge, without producing a spurious outer loop
|
|
20
|
-
// (which the library's built-in frame does).
|
|
19
|
+
// pixels touch the image edge, without producing a spurious outer loop.
|
|
21
20
|
const paddedW = width + 2;
|
|
22
21
|
const paddedH = height + 2;
|
|
23
|
-
const grid
|
|
24
|
-
|
|
25
|
-
// Top padding row.
|
|
26
|
-
grid.push(new Array(paddedW).fill(0));
|
|
22
|
+
const grid = new Array<number>(paddedW * paddedH).fill(0);
|
|
27
23
|
|
|
28
24
|
for (let y = 0; y < height; y++) {
|
|
29
|
-
const row: number[] = [0]; // left padding
|
|
30
25
|
for (let x = 0; x < width; x++) {
|
|
31
|
-
const
|
|
32
|
-
|
|
26
|
+
const srcIdx = (y * width + x) * 4;
|
|
27
|
+
// d3-contour indexes as values[i + j * width] where i=col, j=row
|
|
28
|
+
const dstIdx = (x + 1) + (y + 1) * paddedW;
|
|
29
|
+
grid[dstIdx] = data[srcIdx + 3]; // alpha channel
|
|
33
30
|
}
|
|
34
|
-
row.push(0); // right padding
|
|
35
|
-
grid.push(row);
|
|
36
31
|
}
|
|
37
32
|
|
|
38
|
-
//
|
|
39
|
-
|
|
33
|
+
// Run marching squares via d3-contour on the padded grid.
|
|
34
|
+
// smooth(false) produces staircase edges matching the original behavior.
|
|
35
|
+
const generator = contours()
|
|
36
|
+
.size([paddedW, paddedH])
|
|
37
|
+
.smooth(false);
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
// noFrame: true since we added our own padding.
|
|
43
|
-
const contours = isoContours(grid, alphaThreshold, { noFrame: true });
|
|
39
|
+
const multiPolygon = generator.contour(grid, alphaThreshold);
|
|
44
40
|
|
|
45
|
-
//
|
|
41
|
+
// Extract rings from the GeoJSON MultiPolygon, subtracting the 1px padding offset.
|
|
46
42
|
const result: Vec2Data[][] = [];
|
|
47
|
-
for (const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
for (const polygon of multiPolygon.coordinates) {
|
|
44
|
+
for (const ring of polygon) {
|
|
45
|
+
if (ring.length < 3) continue;
|
|
46
|
+
const polyVerts: Vec2Data[] = [];
|
|
47
|
+
for (const [px, py] of ring) {
|
|
48
|
+
const v = new Vec2Data();
|
|
49
|
+
v.x = px - 1;
|
|
50
|
+
v.y = py - 1;
|
|
51
|
+
polyVerts.push(v);
|
|
52
|
+
}
|
|
53
|
+
result.push(polyVerts);
|
|
55
54
|
}
|
|
56
|
-
result.push(polygon);
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
return result;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
declare module "marchingsquares" {
|
|
2
|
-
export function isoContours(
|
|
3
|
-
data: number[][],
|
|
4
|
-
threshold: number,
|
|
5
|
-
options?: {
|
|
6
|
-
linearRing?: boolean;
|
|
7
|
-
noQuadTree?: boolean;
|
|
8
|
-
noFrame?: boolean;
|
|
9
|
-
}
|
|
10
|
-
): number[][][];
|
|
11
|
-
|
|
12
|
-
export function isoBands(
|
|
13
|
-
data: number[][],
|
|
14
|
-
minV: number,
|
|
15
|
-
bandWidth: number,
|
|
16
|
-
options?: {
|
|
17
|
-
linearRing?: boolean;
|
|
18
|
-
noQuadTree?: boolean;
|
|
19
|
-
noFrame?: boolean;
|
|
20
|
-
}
|
|
21
|
-
): number[][][];
|
|
22
|
-
}
|