* feat(region-routing): P1 tagging + region_routes primitive + read/write API + preview launcher - config.py: add Coverage.region_tagging (bool=False); add RegionRouteMatrix dataclass (enabled, cells) above NotificationsConfig; add region_routes field to NotificationsConfig; add explicit hydration branch for region_routes in _dict_to_dataclass mirroring destinations pattern. - coverage_area.py: add MonitoringArea.name (str|None=None, frozen); update areas_from_config to preserve name; refactor inline geom extraction from classify_event_areas into shared _event_geom_json helper; add matching_area_names(geom_json, areas)->list[str] (additive, all named matches, config-order, deduped; gate unchanged); add event_region_names convenience wrapper. - coverage_filter.py: add region_tagging ctor kwarg; stamp event.region/ regions before the gate when region_tagging=True and areas non-empty and not event.regions (never clobbers satpass preset). - pipeline/__init__.py: wire region_tagging into CoverageFilter construction. - notification_routes.py: add GET /notifications/regions (named coverage area names, config-order, deduped); GET /notifications/region-routing (matrix as JSON); POST /notifications/region-routing (explicit RMW — only region_routes changes, toggles/rules/destinations survive). - scripts/preview_dashboard.py: mesh-free launcher — dashboard API only, no mesh connector, no broadcast loop; vite runs separately. All 87 coverage tests pass; 300 total pass; 6 pre-existing failures unchanged (adapter config count mismatch + MeshCore EventType.NEW_CONTACT). * feat(region-routing): manual region x family matrix editor page Adds RegionRoutingMatrix.tsx — a plain editor over the region_routes config primitive. Rows = families (via useFamilies()), cols = regions (from GET /api/notifications/regions). Each cell exposes MT channel (ChannelPicker single + includeDisabled), MC channel name (text input), min_severity select (routine/priority/critical/immediate), and an enabled checkbox. Only cells where MT or MC is set are included in the sparse POST payload. Master enable toggle maps to top-level enabled. MT budget guard warns when more than 7 distinct MT indices are in use. Sticky family column; horizontal scroll for wide region sets. Registers route /region-routing in App.tsx and adds "Region Routing" nav entry (Map icon) under the Meshtastic section in Layout.tsx, immediately after Routing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(region-routing): regions endpoint reads saved (disk) coverage so routing columns are dynamic without a bot restart; preview reloads config after writes * feat(routing): unify MT/MC routing into per-family cards; region routing as an in-card expand; remove rules/destinations UI + standalone page * refactor(routing): move Meshtastic Routing from /notifications to /meshtastic/routing (mirror /meshcore/routing); redirect legacy path * feat(region-routing): dispatcher honors region_routes matrix (authoritative-on-match, per-region cooldown, per-channel dedup); non-matrix path unchanged Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(region-routing): matrix dedup key must match boot-restore 2-tuple form (prevents restart re-broadcast flood); regression test --------- Co-authored-by: Matt Johnson <mj@k7zvx.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| src | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
d3-delaunay
Georgy “The Voronator” Voronoy
This is a fast library for computing the Voronoi diagram of a set of two-dimensional points. It is based on Delaunator, a fast library for computing the Delaunay triangulation using sweep algorithms. The Voronoi diagram is constructed by connecting the circumcenters of adjacent triangles in the Delaunay triangulation.
For an interactive explanation of how this library works, see The Delaunay’s Dual.
Installing
If you use npm, npm install d3-delaunay. You can also download the latest release on GitHub. For vanilla HTML in modern browsers, import d3-delaunay from Skypack:
<script type="module">
import {Delaunay} from "https://cdn.skypack.dev/d3-delaunay@6";
const points = [[0, 0], [0, 1], [1, 0], [1, 1]];
const delaunay = Delaunay.from(points);
const voronoi = delaunay.voronoi([0, 0, 960, 500]);
</script>
For legacy environments, you can load d3-delaunay’s UMD bundle from an npm-based CDN such as jsDelivr; a d3 global is exported:
<script src="https://cdn.jsdelivr.net/npm/d3-delaunay@6"></script>
<script>
const delaunay = d3.Delaunay.from(points);
</script>
API Reference
Delaunay
Returns the Delaunay triangulation for the given flat array [x0, y0, x1, y1, …] of points.
const delaunay = new Delaunay(Float64Array.of(0, 0, 0, 1, 1, 0, 1, 1));
# Delaunay.from(points[, fx[, fy[, that]]]) <>
Returns the Delaunay triangulation for the given array or iterable of points. If fx and fy are not specified, then points is assumed to be an array of two-element arrays of numbers: [[x0, y0], [x1, y1], …]. Otherwise, fx and fy are functions that are invoked for each element in the points array in order, and must return the respective x- and y-coordinate for each point. If that is specified, the functions fx and fy are invoked with that as this. (See Array.from for reference.)
const delaunay = Delaunay.from([[0, 0], [0, 1], [1, 0], [1, 1]]);
# delaunay.points
The coordinates of the points as an array [x0, y0, x1, y1, …]. Typically, this is a Float64Array, however you can use any array-like type in the constructor.
# delaunay.halfedges
The halfedge indexes as an Int32Array [j0, j1, …]. For each index 0 ≤ i < halfedges.length, there is a halfedge from triangle vertex j = halfedges[i] to triangle vertex i. Equivalently, this means that triangle ⌊i / 3⌋ is adjacent to triangle ⌊j / 3⌋. If j is negative, then triangle ⌊i / 3⌋ is an exterior triangle on the convex hull. For example, to render the internal edges of the Delaunay triangulation:
const {points, halfedges, triangles} = delaunay;
for (let i = 0, n = halfedges.length; i < n; ++i) {
const j = halfedges[i];
if (j < i) continue;
const ti = triangles[i];
const tj = triangles[j];
context.moveTo(points[ti * 2], points[ti * 2 + 1]);
context.lineTo(points[tj * 2], points[tj * 2 + 1]);
}
See also delaunay.render.
# delaunay.hull
An Int32Array of point indexes that form the convex hull in counterclockwise order. If the points are collinear, returns them ordered.
See also delaunay.renderHull.
# delaunay.triangles
The triangle vertex indexes as an Uint32Array [i0, j0, k0, i1, j1, k1, …]. Each contiguous triplet of indexes i, j, k forms a counterclockwise triangle. The coordinates of the triangle’s points can be found by going through delaunay.points. For example, to render triangle i:
const {points, triangles} = delaunay;
const t0 = triangles[i * 3 + 0];
const t1 = triangles[i * 3 + 1];
const t2 = triangles[i * 3 + 2];
context.moveTo(points[t0 * 2], points[t0 * 2 + 1]);
context.lineTo(points[t1 * 2], points[t1 * 2 + 1]);
context.lineTo(points[t2 * 2], points[t2 * 2 + 1]);
context.closePath();
See also delaunay.renderTriangle.
# delaunay.inedges
The incoming halfedge indexes as a Int32Array [e0, e1, e2, …]. For each point i, inedges[i] is the halfedge index e of an incoming halfedge. For coincident points, the halfedge index is -1; for points on the convex hull, the incoming halfedge is on the convex hull; for other points, the choice of incoming halfedge is arbitrary. The inedges table can be used to traverse the Delaunay triangulation; see also delaunay.neighbors.
Returns the index of the input point that is closest to the specified point ⟨x, y⟩. The search is started at the specified point i. If i is not specified, it defaults to zero.
Returns an iterable over the indexes of the neighboring points to the specified point i. The iterable is empty if i is a coincident point.
# delaunay.render([context]) <>
Renders the edges of the Delaunay triangulation to the specified context. The specified context must implement the context.moveTo and context.lineTo methods from the CanvasPathMethods API. If a context is not specified, an SVG path string is returned instead.
# delaunay.renderHull([context]) <>
Renders the convex hull of the Delaunay triangulation to the specified context. The specified context must implement the context.moveTo and context.lineTo methods from the CanvasPathMethods API. If a context is not specified, an SVG path string is returned instead.
# delaunay.renderTriangle(i[, context]) <>
Renders triangle i of the Delaunay triangulation to the specified context. The specified context must implement the context.moveTo, context.lineTo and context.closePath methods from the CanvasPathMethods API. If a context is not specified, an SVG path string is returned instead.
# delaunay.renderPoints([context][, radius]) <>
Renders the input points of the Delaunay triangulation to the specified context as circles with the specified radius. If radius is not specified, it defaults to 2. The specified context must implement the context.moveTo and context.arc methods from the CanvasPathMethods API. If a context is not specified, an SVG path string is returned instead.
Returns the closed polygon [[x0, y0], [x1, y1], …, [x0, y0]] representing the convex hull.
# delaunay.trianglePolygons() <>
Returns an iterable over the polygons for each triangle, in order.
# delaunay.trianglePolygon(i) <>
Returns the closed polygon [[x0, y0], [x1, y1], [x2, y2], [x0, y0]] representing the triangle i.
Updates the triangulation after the points have been modified in-place.
# delaunay.voronoi([bounds]) <>
Returns the Voronoi diagram for the associated points. When rendering, the diagram will be clipped to the specified bounds = [xmin, ymin, xmax, ymax]. If bounds is not specified, it defaults to [0, 0, 960, 500]. See To Infinity and Back Again for an interactive explanation of Voronoi cell clipping.
The Voronoi diagram is returned even in degenerate cases where no triangulation exists — namely 0, 1 or 2 points, and collinear points.
Voronoi
# voronoi.delaunay
The Voronoi diagram’s associated Delaunay triangulation.
# voronoi.circumcenters
The circumcenters of the Delaunay triangles as a Float64Array [cx0, cy0, cx1, cy1, …]. Each contiguous pair of coordinates cx, cy is the circumcenter for the corresponding triangle. These circumcenters form the coordinates of the Voronoi cell polygons.
# voronoi.vectors
A Float64Array [vx0, vy0, wx0, wy0, …] where each non-zero quadruple describes an open (infinite) cell on the outer hull, giving the directions of two open half-lines.
# voronoi.xmin
# voronoi.ymin
# voronoi.xmax
# voronoi.ymax
The bounds of the viewport [xmin, ymin, xmax, ymax] for rendering the Voronoi diagram. These values only affect the rendering methods (voronoi.render, voronoi.renderBounds, cell.render).
# voronoi.contains(i, x, y) <>
Returns true if the cell with the specified index i contains the specified point ⟨x, y⟩. (This method is not affected by the associated Voronoi diagram’s viewport bounds.)
Returns an iterable over the indexes of the cells that share a common edge with the specified cell i. Voronoi neighbors are always neighbors on the Delaunay graph, but the converse is false when the common edge has been clipped out by the Voronoi diagram’s viewport.
# voronoi.render([context]) <>
Renders the mesh of Voronoi cells to the specified context. The specified context must implement the context.moveTo and context.lineTo methods from the CanvasPathMethods API. If a context is not specified, an SVG path string is returned instead.
# voronoi.renderBounds([context]) <>
Renders the viewport extent to the specified context. The specified context must implement the context.rect method from the CanvasPathMethods API. Equivalent to context.rect(voronoi.xmin, voronoi.ymin, voronoi.xmax - voronoi.xmin, voronoi.ymax - voronoi.ymin). If a context is not specified, an SVG path string is returned instead.
# voronoi.renderCell(i[, context]) <>
Renders the cell with the specified index i to the specified context. The specified context must implement the context.moveTo , context.lineTo and context.closePath methods from the CanvasPathMethods API. If a context is not specified, an SVG path string is returned instead.
Returns an iterable over the non-empty polygons for each cell, with the cell index as property.
Returns the convex, closed polygon [[x0, y0], [x1, y1], …, [x0, y0]] representing the cell for the specified point i.
Updates the Voronoi diagram and underlying triangulation after the points have been modified in-place — useful for Lloyd’s relaxation.