* 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>
4.5 KiB
robust-predicates
Fast robust predicates for computational geometry in JavaScript. Provides reliable 2D and 3D point orientation tests (orient2d, orient3d, incircle, insphere) that are not susceptible to floating point errors (without sacrificing performance). A modern port of Jonathan R Shewchuk's C code, an industry standard since 1996.
Figure: non-robust vs robust orient2d test for points within a tiny range (2-42).
Demo
API
Note: unlike J. Shewchuk's original code, all the functions in this library assume y axis is oriented downwards ↓, so the semantics are different.
orient2d(ax,ay, bx,by, cx,cy)
- Returns a positive value if the points
a,b, andcoccur in counterclockwise order (clies to the left of the directed line defined by pointsaandb). - Returns a negative value if they occur in clockwise order (
clies to the right of the directed lineab). - Returns zero if they are collinear.
The result is also an approximation of twice the signed area of the triangle defined by the three points.
incircle(ax,ay, bx,by, cx,cy, dx,dy)
- Returns a positive value if the point
dlies outside the circle passing througha,b, andc. - Returns a negative value if it lies inside.
- Returns zero if the four points are cocircular.
The points a, b, and c must be in counterclockwise order, or the sign of the result will be reversed.
orient3d(ax,ay,az, bx,by,bz, cx,cy,cz, dx,dy,dz)
- Returns a positive value if the point
dlies above the plane passing througha,b, andc, meaning thata,b, andcappear in counterclockwise order when viewed fromd. - Returns a negative value if
dlies below the plane. - Returns zero if the points are coplanar.
The result is also an approximation of six times the signed volume of the tetrahedron defined by the four points.
insphere(ax,ay,az, bx,by,bz, cx,cy,cz, dx,dy,dz, ex,ey,ez)
- Returns a positive value if the point
elies outside the sphere passing througha,b,c, andd. - Returns a negative value if it lies inside.
- Returns zero if the five points are cospherical.
The points a, b, c, and d must be ordered so that they have a positive orientation
(as defined by orient3d), or the sign of the result will be reversed.
orient2dfast, orient3dfast, incirclefast, inspherefast
Simple, approximate, non-robust versions of predicates above. Use when robustness isn't needed.
Example
import {orient2d} from 'robust-predicates';
const ccw = orient2d(ax, ay, bx, by, cx, cy) > 0;
Install
Install with npm install robust-predicates or yarn add robust-predicates, or use one of the browser builds:
- predicates.min.js (all predicates)
- orient2d.min.js (
orient2d,orient2dfast) - orient3d.min.js (
orient3d,orient3dfast) - incircle.min.js (
incircle,incirclefast) - insphere.min.js (
insphere,inspherefast)
Thanks
This project is just a port — all the brilliant, hard work was done by Jonathan Richard Shewchuk.
The port was also inspired by Mikola Lysenko's excellent Robust Arithmetic Notes and related projects like robust-orientation and robust-in-sphere.
License
Since the original code is in the public domain, this project follows the same choice. See Unlicense.
