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.
@@ -1,43 +1,43 @@
1
- import { isoContours } from 'marchingsquares';
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 2D grid of alpha values with 1px of zero-padding on all sides.
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 grid = [];
12
- // Top padding row.
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 idx = (y * width + x) * 4;
18
- row.push(data[idx + 3]); // alpha channel
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
- // Bottom padding row.
24
- grid.push(new Array(paddedW).fill(0));
25
- // Run marching squares on the padded grid.
26
- // noFrame: true since we added our own padding.
27
- const contours = isoContours(grid, alphaThreshold, { noFrame: true });
28
- // Convert to Vec2Data arrays, subtracting the 1px padding offset.
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 contour of contours) {
31
- if (contour.length < 3)
32
- continue;
33
- const polygon = [];
34
- for (const point of contour) {
35
- const v = new Vec2Data();
36
- v.x = point[0] - 1;
37
- v.y = point[1] - 1;
38
- polygon.push(v);
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;;;;;AAMzC,IAAA,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC;IAEzB,MAAM,IAAI,GAAe,EAAE;;AAG3B,IAAA,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAErC,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE;AAC/B,QAAA,MAAM,GAAG,GAAa,CAAC,CAAC,CAAC,CAAC;AAC1B,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;YAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC;AAC/B,YAAA,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1B;AACA,QAAA,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAChB;;AAGA,IAAA,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;;AAIrC,IAAA,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;IAGrE,MAAM,MAAM,GAAiB,EAAE;AAC/B,IAAA,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AAC9B,QAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE;QACxB,MAAM,OAAO,GAAe,EAAE;AAC9B,QAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;AAC3B,YAAA,MAAM,CAAC,GAAG,IAAI,QAAQ,EAAE;YACxB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;YAClB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;AAClB,YAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjB;AACA,QAAA,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;IACtB;AAEA,IAAA,OAAO,MAAM;AACf;;;;"}
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.2.5",
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.2.4",
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"
@@ -1,4 +1,4 @@
1
- import { isoContours } from "marchingsquares";
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 2D grid of alpha values with 1px of zero-padding on all sides.
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: number[][] = [];
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 idx = (y * width + x) * 4;
32
- row.push(data[idx + 3]); // alpha channel
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
- // Bottom padding row.
39
- grid.push(new Array(paddedW).fill(0));
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
- // Run marching squares on the padded grid.
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
- // Convert to Vec2Data arrays, subtracting the 1px padding offset.
41
+ // Extract rings from the GeoJSON MultiPolygon, subtracting the 1px padding offset.
46
42
  const result: Vec2Data[][] = [];
47
- for (const contour of contours) {
48
- if (contour.length < 3) continue;
49
- const polygon: Vec2Data[] = [];
50
- for (const point of contour) {
51
- const v = new Vec2Data();
52
- v.x = point[0] - 1;
53
- v.y = point[1] - 1;
54
- polygon.push(v);
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
- }