Table of Contents

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) — tune icon dropdown listing every StepPropertyAccessDictionary key with a GetQuantityFunc, sorted by PresentAttribute.Name. Picking a key calls POST /api/player/inspecting-key and re-fetches the chart.
    • X-axis picker — IndexByTime (default) / IndexByStep.
    • Window chip — displays [dispBegin..absDispEnd] / count for at-a-glance scope.
    • zoom_out_map reset button — returns the window to the full mission.
  • Body — UplotChart.vue rendering 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() .. AbsDispEnd window is fetched, at a bucket count matching the chart's pixel width. The server-side ClStrip.GetMinMaxList(threshold, itemCount) handles down-sampling.
  • Pointer interactions:
    • wheel over the plot area → POST /api/cl-strip/wheel with scale = Math.pow(1.05, deltaY * 1/166) + xPositionPercentage.
    • Right / middle-button drag → POST /api/cl-strip/pan with accumulated xOffsetPercentage. Frame-batched via requestAnimationFrame. Touch / pen drags also pan without a button modifier.
    • Left click → POST /api/cl-strip/select-step with the nearest bucket's original step index (via chart.valToPos reverse lookup).
    • Mouse move (debounced 80 ms) → POST /api/cl-strip/enter-step for hover.
  • Live refresh. useClStripHub subscribes to DispRangeChanged (re-fetch when anyone else zooms / pans) and Updated (coalesced re-broadcast while a mission is running). PlayerStatusHub.hasProject rising edge also triggers a refetch.
  • Client-side debounce. BaseStripChart.load() is debounced 50 ms on the client so a burst of Updated events 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-range body { dispBegin, dispEnd }.
    • POST /api/cl-strip/wheel body { scale, xPositionPercentage, xValueCategory }.
    • POST /api/cl-strip/pan body { xOffsetPercentage, xValueCategory }. Legacy feelingRatio=2.
    • POST /api/cl-strip/select-step body { stepIndex }ClStrip.SetSelectedPos(...).
    • POST /api/cl-strip/enter-step body { stepIndex } (nullable) → ClStrip.SetEnteredPos(...).
  • Players/ClStripHub.cs + Players/ClStripBroadcastService.cs — SignalR at /clStripHub. Broadcasts DispRangeChanged(snapshot), StepSelected({ stepIndex }), StepEntered({ stepIndex }), Updated(snapshot). Single-flight Interlocked mutex coalesces re-broadcasts; client debounce handles the rest of the rate-limiting.

Deferred

  • Y-axis custom tick formatter (e.g. 0.6060% for Availability). Port is axes[1].values: (_, vals) => vals.map(v => \${(v*100).toFixed(0)}%`)` in uPlot; not yet applied. Same one-liner for µm / N suffixes.
  • triggerHover external programmatic hover — the server-side event flow + client-side hover-on-drag are shipped, but the uPlot cursor is not yet programmatically positioned on incoming StepEntered events from other charts. Pure UX polish.
  • RangeColorRule per-value colour bands — legacy paints bar backgrounds by value thresholds. Requires a custom uPlot draw hook.
  • VRange modes (Fit / Lock / Symmetric) from StripIndividualInputGroup — uPlot supports via scales.y.range function; deferred (auto-fit default is fine for now).