Strip Charts
The strip charts visualise a windowed, downsampled view of the full mission timeline for physics / quality aspects that are computed per step across the whole NC program. They are rendered as min/max banded series over the ClStrip.GetDispBegin() .. AbsDispEnd window. Operators use them to spot which segments of the mission are loading the spindle, degrading surface quality, or hitting thermal limits.
The anatomy covers three strip charts in the webservice, all sharing BaseStripChart.vue:
| Chart | Source Aspect | Items |
|---|---|---|
| Plural Strip Availability Chart | Availability |
Yielding-stress / max-spindle-torque / max-spindle-power / spindle-working-temperature / thermal-yield ratios (5 series). |
| Plural Strip Roughness Chart | SurfaceRoughness |
Re-cut depth + program-side cusp + Δ tip deflection X / Y / Z in µm (5 series). |
| Strip Individual Chart | Individual |
One series of a user-picked StepPropertyAccessDictionary key (≈90 keys). |
Key Model: MachiningProject via LocalProjectService.ClStrip + LocalProjectService.StepPropertyAccessDictionary.
Layout
Each strip chart is a card:
- Header Row
- Title label (aspect name).
- Aspect picker (Individual chart only) —
tuneicon dropdown listing everyStepPropertyAccessDictionarykey with aGetQuantityFunc, sorted byPresentAttribute.Name. Picking a key callsPOST /api/player/inspecting-keyand re-fetches the chart. - X-axis picker —
IndexByTime(default) /IndexByStep. - Window chip — displays
[dispBegin..absDispEnd] / countfor at-a-glance scope. zoom_out_mapreset button — returns the window to the full mission.
- Body —
UplotChart.vuerendering one min/max band pair per item (two stroked series of the same colour + a filled band at 15% opacity). - “No physics data” overlay — shown when every item's min / max arrays are all NaN (typical for Availability without a physics licence).
Behavior
- Windowed fetch. Only the
ClStrip.GetDispBegin() .. AbsDispEndwindow is fetched, at a bucket count matching the chart's pixel width. The server-sideClStrip.GetMinMaxList(threshold, itemCount)handles down-sampling. - Pointer interactions:
wheelover the plot area →POST /api/cl-strip/wheelwithscale = Math.pow(1.05, deltaY * 1/166)+xPositionPercentage.- Right / middle-button drag →
POST /api/cl-strip/panwith accumulatedxOffsetPercentage. Frame-batched viarequestAnimationFrame. Touch / pen drags also pan without a button modifier. - Left click →
POST /api/cl-strip/select-stepwith the nearest bucket's original step index (viachart.valToPosreverse lookup). - Mouse move (debounced 80 ms) →
POST /api/cl-strip/enter-stepfor hover.
- Live refresh.
useClStripHubsubscribes toDispRangeChanged(re-fetch when anyone else zooms / pans) andUpdated(coalesced re-broadcast while a mission is running).PlayerStatusHub.hasProjectrising edge also triggers a refetch. - Client-side debounce.
BaseStripChart.load()is debounced 50 ms on the client so a burst ofUpdatedevents during a fast-running mission coalesces into one fetch.
Source Code Path
See HiNC App Anatomy for git repository links.
WPF Application Source Code Path
- Not implemented.
Web Page Application Source Code Path
HiNC-2025-webservice (Quasar CLI SPA):
wwwroot-src/src/components/player/charts/BaseStripChart.vue— shared strip-chart skeleton.wwwroot-src/src/components/player/charts/UplotChart.vue— uplot wrapper.wwwroot-src/src/components/player/charts/PluralStripAvailabilityChart.vue— availability chart.wwwroot-src/src/components/player/charts/PluralStripRoughnessChart.vue— surface-roughness chart.wwwroot-src/src/components/player/charts/StripIndividualChart.vue— aspect-picker individual chart.wwwroot-src/src/api/clStrip.ts— typed REST wrappers:getClStripRange,setClStripDispRange,clStripWheel,clStripPan,selectClStripStep,enterClStripStep.wwwroot-src/src/composables/useClStripHub.ts— singleton hub wrapper (same ref-counting pattern as the other player hubs).Players/PlayerChartsController.cs— strip-chart data:GET /api/player/strip-chart?aspect=Availability|SurfaceRoughness|Individual&xValueCategory=IndexByTime|IndexByStep&widthHint=…&dispBegin=…&dispEnd=…&inspectingKey=…→{ xs, indexes, items:[{ key, label, unit, min, max }], isXTicksRangeMode, dispBegin, absDispEnd, count }.
Players/ClStripController.cs— range manipulation (server-side counterparts of the pointer handlers above):GET /api/cl-strip/range— snapshot{ dispBegin, absDispEnd, count, selectedIndex, enteredIndex }.POST /api/cl-strip/disp-rangebody{ dispBegin, dispEnd }.POST /api/cl-strip/wheelbody{ scale, xPositionPercentage, xValueCategory }.POST /api/cl-strip/panbody{ xOffsetPercentage, xValueCategory }. LegacyfeelingRatio=2.POST /api/cl-strip/select-stepbody{ stepIndex }→ClStrip.SetSelectedPos(...).POST /api/cl-strip/enter-stepbody{ stepIndex }(nullable) →ClStrip.SetEnteredPos(...).
Players/ClStripHub.cs+Players/ClStripBroadcastService.cs— SignalR at/clStripHub. BroadcastsDispRangeChanged(snapshot),StepSelected({ stepIndex }),StepEntered({ stepIndex }),Updated(snapshot). Single-flightInterlockedmutex coalesces re-broadcasts; client debounce handles the rest of the rate-limiting.
Deferred
- Y-axis custom tick formatter (e.g.
0.60→60%for Availability). Port isaxes[1].values: (_, vals) => vals.map(v => \${(v*100).toFixed(0)}%`)` in uPlot; not yet applied. Same one-liner for µm / N suffixes. triggerHoverexternal programmatic hover — the server-side event flow + client-side hover-on-drag are shipped, but the uPlot cursor is not yet programmatically positioned on incomingStepEnteredevents from other charts. Pure UX polish.RangeColorRuleper-value colour bands — legacy paints bar backgrounds by value thresholds. Requires a custom uPlotdrawhook.VRangemodes (Fit / Lock / Symmetric) fromStripIndividualInputGroup— uPlot supports viascales.y.rangefunction; deferred (auto-fit default is fine for now).
Related Pages
- Cycle-Line Charts — per-selected-step charts that share the same
uplotengine. - Player Panel — top-level layout that hosts the charts.