data-navigator 3.3.0 → 3.3.1

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/index.cjs CHANGED
@@ -2704,17 +2704,23 @@ function convexHullPath(points) {
2704
2704
  return `M${fmt(first.x)},${fmt(first.y)}` + rest.map((p) => `L${fmt(p.x)},${fmt(p.y)}`).join("") + "Z";
2705
2705
  }
2706
2706
  function expandHull(hullPoints, padPx) {
2707
- if (padPx === 0 || hullPoints.length === 0)
2707
+ const n = hullPoints.length;
2708
+ if (padPx === 0 || n < 3)
2708
2709
  return hullPoints;
2709
- const cx = hullPoints.reduce((s, p) => s + p.x, 0) / hullPoints.length;
2710
- const cy = hullPoints.reduce((s, p) => s + p.y, 0) / hullPoints.length;
2711
- return hullPoints.map((p) => {
2712
- const dx = p.x - cx;
2713
- const dy = p.y - cy;
2714
- const dist = Math.hypot(dx, dy);
2715
- if (dist === 0)
2716
- return p;
2717
- return { x: p.x + dx / dist * padPx, y: p.y + dy / dist * padPx };
2710
+ const area = hullPoints.reduce((s, p, i) => {
2711
+ const q = hullPoints[(i + 1) % n];
2712
+ return s + p.x * q.y - q.x * p.y;
2713
+ }, 0);
2714
+ const sign = Math.sign(area);
2715
+ const normal = (a, b) => {
2716
+ const len = Math.hypot(b.x - a.x, b.y - a.y);
2717
+ return { x: sign * (b.y - a.y) / len, y: sign * (a.x - b.x) / len };
2718
+ };
2719
+ return hullPoints.map((p, i) => {
2720
+ const n1 = normal(hullPoints[(i + n - 1) % n], p);
2721
+ const n2 = normal(p, hullPoints[(i + 1) % n]);
2722
+ const scale = padPx / (1 + n1.x * n2.x + n1.y * n2.y);
2723
+ return { x: p.x + (n1.x + n2.x) * scale, y: p.y + (n1.y + n2.y) * scale };
2718
2724
  });
2719
2725
  }
2720
2726
  function rectCorners(r) {
package/dist/index.d.cts CHANGED
@@ -372,8 +372,8 @@ declare function grahamScan(points: Point[]): Point[];
372
372
  */
373
373
  declare function convexHullPath(points: Point[]): string;
374
374
  /**
375
- * Expand a convex hull polygon outward from its centroid by `padPx` pixels.
376
- * Each hull vertex is pushed radially away from the centroid.
375
+ * Expand a convex hull polygon by moving each edge outward by `padPx` pixels.
376
+ * Corners are placed where neighboring edges meet (miter join).
377
377
  */
378
378
  declare function expandHull(hullPoints: Point[], padPx: number): Point[];
379
379
  /**
package/dist/index.d.ts CHANGED
@@ -372,8 +372,8 @@ declare function grahamScan(points: Point[]): Point[];
372
372
  */
373
373
  declare function convexHullPath(points: Point[]): string;
374
374
  /**
375
- * Expand a convex hull polygon outward from its centroid by `padPx` pixels.
376
- * Each hull vertex is pushed radially away from the centroid.
375
+ * Expand a convex hull polygon by moving each edge outward by `padPx` pixels.
376
+ * Corners are placed where neighboring edges meet (miter join).
377
377
  */
378
378
  declare function expandHull(hullPoints: Point[], padPx: number): Point[];
379
379
  /**
package/dist/index.js CHANGED
@@ -2670,17 +2670,23 @@ function convexHullPath(points) {
2670
2670
  return `M${fmt(first.x)},${fmt(first.y)}` + rest.map((p) => `L${fmt(p.x)},${fmt(p.y)}`).join("") + "Z";
2671
2671
  }
2672
2672
  function expandHull(hullPoints, padPx) {
2673
- if (padPx === 0 || hullPoints.length === 0)
2673
+ const n = hullPoints.length;
2674
+ if (padPx === 0 || n < 3)
2674
2675
  return hullPoints;
2675
- const cx = hullPoints.reduce((s, p) => s + p.x, 0) / hullPoints.length;
2676
- const cy = hullPoints.reduce((s, p) => s + p.y, 0) / hullPoints.length;
2677
- return hullPoints.map((p) => {
2678
- const dx = p.x - cx;
2679
- const dy = p.y - cy;
2680
- const dist = Math.hypot(dx, dy);
2681
- if (dist === 0)
2682
- return p;
2683
- return { x: p.x + dx / dist * padPx, y: p.y + dy / dist * padPx };
2676
+ const area = hullPoints.reduce((s, p, i) => {
2677
+ const q = hullPoints[(i + 1) % n];
2678
+ return s + p.x * q.y - q.x * p.y;
2679
+ }, 0);
2680
+ const sign = Math.sign(area);
2681
+ const normal = (a, b) => {
2682
+ const len = Math.hypot(b.x - a.x, b.y - a.y);
2683
+ return { x: sign * (b.y - a.y) / len, y: sign * (a.x - b.x) / len };
2684
+ };
2685
+ return hullPoints.map((p, i) => {
2686
+ const n1 = normal(hullPoints[(i + n - 1) % n], p);
2687
+ const n2 = normal(p, hullPoints[(i + 1) % n]);
2688
+ const scale = padPx / (1 + n1.x * n2.x + n1.y * n2.y);
2689
+ return { x: p.x + (n1.x + n2.x) * scale, y: p.y + (n1.y + n2.y) * scale };
2684
2690
  });
2685
2691
  }
2686
2692
  function rectCorners(r) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "data-navigator",
3
3
  "author": "Frank Elavsky",
4
- "version": "3.3.0",
4
+ "version": "3.3.1",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",