@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.111 → 2.0.0-next.112

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.
Files changed (55) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +73 -16
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +79 -7
  4. package/dist/navigation-instruments/compass/compass.d.ts +1 -1
  5. package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
  6. package/dist/navigation-instruments/compass/compass.js +1 -1
  7. package/dist/navigation-instruments/compass/compass.js.map +1 -1
  8. package/dist/navigation-instruments/current/current.d.ts +25 -0
  9. package/dist/navigation-instruments/current/current.d.ts.map +1 -1
  10. package/dist/navigation-instruments/current/current.js +25 -4
  11. package/dist/navigation-instruments/current/current.js.map +1 -1
  12. package/dist/navigation-instruments/heading/heading.js +1 -1
  13. package/dist/navigation-instruments/heading/heading.js.map +1 -1
  14. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.d.ts +6 -0
  15. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.d.ts.map +1 -1
  16. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.js +8 -1
  17. package/dist/navigation-instruments/pitch-roll-heave/pitch-roll-heave.js.map +1 -1
  18. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts +5 -2
  19. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts.map +1 -1
  20. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.js.map +1 -1
  21. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.d.ts +6 -0
  22. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.d.ts.map +1 -1
  23. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.js +19 -4
  24. package/dist/navigation-instruments/top-view-propulsion/top-view-propulsion.js.map +1 -1
  25. package/dist/navigation-instruments/watch/environment.d.ts +8 -0
  26. package/dist/navigation-instruments/watch/environment.d.ts.map +1 -1
  27. package/dist/navigation-instruments/watch/environment.js +3 -0
  28. package/dist/navigation-instruments/watch/environment.js.map +1 -1
  29. package/dist/navigation-instruments/watch/force-pattern.d.ts +20 -2
  30. package/dist/navigation-instruments/watch/force-pattern.d.ts.map +1 -1
  31. package/dist/navigation-instruments/watch/force-pattern.js +12 -5
  32. package/dist/navigation-instruments/watch/force-pattern.js.map +1 -1
  33. package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
  34. package/dist/navigation-instruments/watch/watch.js +6 -4
  35. package/dist/navigation-instruments/watch/watch.js.map +1 -1
  36. package/dist/navigation-instruments/wind/wind.d.ts +5 -2
  37. package/dist/navigation-instruments/wind/wind.d.ts.map +1 -1
  38. package/dist/navigation-instruments/wind/wind.js +5 -1
  39. package/dist/navigation-instruments/wind/wind.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/navigation-instruments/compass/compass.ts +2 -2
  42. package/src/navigation-instruments/current/current.stories.ts +33 -0
  43. package/src/navigation-instruments/current/current.ts +37 -3
  44. package/src/navigation-instruments/heading/heading.stories.ts +6 -4
  45. package/src/navigation-instruments/heading/heading.ts +1 -1
  46. package/src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts +8 -1
  47. package/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts +3 -3
  48. package/src/navigation-instruments/rate-of-turn/rate-of-turn.ts +5 -2
  49. package/src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts +20 -2
  50. package/src/navigation-instruments/watch/environment.ts +10 -0
  51. package/src/navigation-instruments/watch/force-pattern.spec.ts +42 -0
  52. package/src/navigation-instruments/watch/force-pattern.ts +44 -7
  53. package/src/navigation-instruments/watch/watch.ts +20 -5
  54. package/src/navigation-instruments/wind/wind.spec.ts +3 -1
  55. package/src/navigation-instruments/wind/wind.ts +12 -3
@@ -1 +1 @@
1
- {"version":3,"file":"heading.js","sources":["../../../src/navigation-instruments/heading/heading.ts"],"sourcesContent":["import {LitElement, PropertyValues, css, html, nothing} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {\n CogArrowStyle,\n HdgArrowStyle,\n cogArrow,\n hdgArrow,\n} from '../course-arrows/course-arrows.js';\nimport {\n CompassCenterReadout,\n CompassReadoutSource,\n centerReadoutStyles,\n renderCenterReadouts,\n resolveCompassCenterReadouts,\n} from '../readout/center-readout.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport {\n applyPinnedHostSize,\n computeRadialFrame,\n measureContainerPx,\n NORTH_ARROW_WIDTH_PX,\n NSWE_LABEL_WIDTH_PX,\n type RadialFrame,\n} from '../../svghelpers/radial-frame.js';\nimport {VesselImage, VesselImageSize, WatchCircleType} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {Priority} from '../types.js';\nimport {customElement} from '../../decorator.js';\nexport {HdgArrowStyle, CogArrowStyle};\nexport {CompassReadoutSource};\nexport type {CompassCenterReadout};\n\nexport enum CompassDirection {\n NorthUp = 'northUp',\n HeadingUp = 'headingUp',\n CourseUp = 'courseUp',\n}\n\nexport enum HeadingPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n}\n\n/**\n * `<obc-heading>` – Heading instrument with HDG/COG arrows over a single-ring\n * watch face, with optional vessel silhouette and center readouts.\n *\n * Renders a circular instrument that displays heading (HDG) and course over\n * ground (COG) as rotating arrows. It supports a heading setpoint with auto\n * at-setpoint detection, advice zones, north-up/heading-up/course-up\n * orientation, an optional vessel image, and center readouts replacing the\n * vessel.\n *\n * ## Features\n *\n * - **Direction modes**: `northUp` (default), `headingUp`, or `courseUp`\n * via the `direction` property.\n * - **HDG / COG arrows**: Two arrows overlay the watch face, rotating\n * independently; their look is selected per arrow via `hdgArrowStyle`\n * (`needle` default, `arrowHead`, `vector`, `beamLine`) and\n * `cogArrowStyle` (`needle` default, `arrowHead`, `vector`,\n * `velocityVector`).\n * - **Vessel image**: Optional vessel silhouette via `vesselImage`\n * (hidden by default), centered and rotating with heading.\n * - **Center readouts**: `centerReadouts` replaces the vessel with up to\n * three readouts (first on top, the rest below a horizontal divider);\n * values bind to the instrument's own inputs per entry `source`.\n * - **Heading setpoint**: Optional setpoint marker with auto at-setpoint\n * detection via `headingSetpoint`, `atHeadingSetpoint`, and deadband\n * tuning properties.\n * - **Advice zones**: Pass `headingAdvices` to render caution/alert arcs.\n * - **Color priority**: Set `priority` to `Priority.enhanced` and select\n * the accented elements via `priorityElements`.\n *\n * ## Usage Guidelines\n *\n * - Set `heading` and `courseOverGround` to the current sensor values in\n * degrees.\n * - Use `obc-compass` instead when rate-of-turn, wind or current overlays\n * are needed — this instrument is the reduced heading-focused variant.\n *\n * ## Example\n *\n * ```html\n * <obc-heading\n * heading=\"45\"\n * courseOverGround=\"50\"\n * direction=\"northUp\"\n * headingSetpoint=\"90\"\n * ></obc-heading>\n * ```\n *\n * @ignition-base-height: 512px\n * @ignition-base-width: 512px\n * @stable\n */\n@customElement('obc-heading')\nexport class ObcHeading extends LitElement {\n @property({type: Number}) heading = 0;\n @property({type: Number}) courseOverGround = 0;\n\n @property({type: Number}) headingSetpoint: number | null = null;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==false */\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint: boolean =\n true;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==true */\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) animateSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) touching: boolean = false;\n @property({type: Array, attribute: false}) headingAdvices: AngleAdvice[] = [];\n @property({type: String}) direction: CompassDirection =\n CompassDirection.NorthUp;\n @property({type: String}) priority: Priority = Priority.regular;\n /** @availableWhen priority==enhanced */\n @property({type: Array, attribute: false})\n priorityElements: HeadingPriorityElement[] = [HeadingPriorityElement.hdg];\n /**\n * The vessel silhouette shown in the center, rotating with heading. When\n * unset (default) no vessel is shown; hidden while `centerReadouts` is\n * non-empty.\n * @availableWhen centerReadouts==[]\n */\n @property({type: String}) vesselImage: VesselImage | undefined;\n /**\n * Center readouts replacing the vessel: the first entry renders on top,\n * the rest side by side below a horizontal divider. Values bind per entry\n * `source` (`hdg` → `heading`, `cog` → `courseOverGround`; `rot` has no\n * input on this instrument and renders a dash) and colors follow\n * `priorityElements`. While non-empty, the crosshair's center is cut out\n * so the readouts sit on a clean face.\n */\n @property({type: Array, attribute: false})\n centerReadouts: CompassCenterReadout[] = [];\n /** HDG arrow style: `needle` (default), `arrowHead`, `vector`, or `beamLine`. */\n @property({type: String}) hdgArrowStyle: HdgArrowStyle = HdgArrowStyle.needle;\n /** COG arrow style: `needle` (default), `arrowHead`, `vector`, or `velocityVector`. */\n @property({type: String}) cogArrowStyle: CogArrowStyle = CogArrowStyle.needle;\n /** Show compass NSEW labels. */\n @property({type: Boolean}) showLabels: boolean = false;\n /** When true, labels and north arrow are placed inside the outer ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n /**\n * Outer-ring diameter in CSS pixels. When set, the instrument renders at a\n * fixed intrinsic size derived from the ring, arc shape and label reserve —\n * so instruments sharing the same value have identical ring circumference\n * regardless of label width or arc extent (like obc-donut-chart's\n * fixedHeight). When unset (default), the instrument fills its container.\n */\n @property({type: Number, attribute: 'face-diameter'})\n faceDiameter: number | undefined;\n\n private _headingSp = new SetpointBundle({\n angularWraparound: true,\n onAnimationEnd: () => this.requestUpdate(),\n });\n\n override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n this._headingSp.sync({\n setpoint: this.headingSetpoint ?? undefined,\n newSetpoint: this.newHeadingSetpoint,\n atSetpoint: this.atHeadingSetpoint,\n touching: this.touching,\n autoAtSetpoint: this.autoAtHeadingSetpoint,\n autoAtSetpointDeadband: this.autoAtHeadingSetpointDeadband,\n setpointAtZeroDeadband: this.headingSetpointAtZeroDeadband,\n setpointOverride: this.headingSetpointOverride,\n animateSetpoint: this.animateSetpoint,\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._headingSp.dispose();\n }\n\n // @ts-expect-error TS6133: The controller ensures that the render\n // function is called on resize of the element\n private _resizeController = new ResizeController(this, {});\n\n /**\n * Pixel cost of the outside decor: the always-rendered north-arrow glyph\n * plus, only while shown, the NSWE labels (both keep a constant on-screen\n * size via `1/scale` terms). Feeds the frame's width-aware reserve,\n * replacing the former empirical `72 + delta(clientSize)` padding.\n */\n private getOutsideDecorPx(): number {\n if (this.tickmarksInside) {\n return 0;\n }\n return NORTH_ARROW_WIDTH_PX + (this.showLabels ? NSWE_LABEL_WIDTH_PX : 0);\n }\n\n /** Whether the host size styles were set by applyPinnedHostSize. */\n private _hostSizePinned = false;\n private _frame: RadialFrame | undefined;\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n this._hostSizePinned = applyPinnedHostSize(\n this,\n this._frame,\n this._hostSizePinned\n );\n }\n\n private get angleAdviceRaw(): AngleAdviceRaw[] {\n return this.headingAdvices.map(({minAngle, maxAngle, hinted, type}) => {\n const state =\n this.heading >= minAngle && this.heading <= maxAngle\n ? AdviceState.triggered\n : hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {minAngle, maxAngle, type, state};\n });\n }\n\n private priorityFor(element: HeadingPriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private readoutPriorityFor(source: CompassReadoutSource): Priority {\n if (source === CompassReadoutSource.hdg) {\n return this.priorityFor(HeadingPriorityElement.hdg);\n }\n if (source === CompassReadoutSource.cog) {\n return this.priorityFor(HeadingPriorityElement.cog);\n }\n return Priority.regular;\n }\n\n private get hasCenterReadouts(): boolean {\n return this.centerReadouts.length > 0;\n }\n\n /**\n * The face gains the double-band ring while center content (vessel or\n * readouts) is shown, per the design's vessel/center-label faces.\n */\n private get watchCircleType(): WatchCircleType {\n return this.vesselImage !== undefined || this.hasCenterReadouts\n ? WatchCircleType.double\n : WatchCircleType.single;\n }\n\n private getRotation(): number | undefined {\n if (this.direction === CompassDirection.NorthUp) {\n return undefined;\n } else if (this.direction === CompassDirection.HeadingUp) {\n return -this.heading;\n } else if (this.direction === CompassDirection.CourseUp) {\n return -this.courseOverGround;\n }\n return undefined;\n }\n\n override render() {\n const tickmarks: Tickmark[] = [\n {angle: 0, type: TickmarkType.main},\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n {angle: 270, type: TickmarkType.main},\n ];\n\n const frame = computeRadialFrame({\n basePadding: 72,\n labelWidthPx: this.getOutsideDecorPx(),\n containerPx: measureContainerPx(this),\n faceDiameter: this.faceDiameter,\n });\n this._frame = frame;\n const viewBox = frame.viewBox;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .arcFrame=${frame}\n .advices=${this.angleAdviceRaw}\n .tickmarks=${tickmarks}\n .watchCircleType=${this.watchCircleType}\n .vessels=${this.vesselImage !== undefined && !this.hasCenterReadouts\n ? [\n {\n size: VesselImageSize.medium,\n vesselImage: this.vesselImage,\n transform: `rotate(${this.heading}deg)`,\n },\n ]\n : []}\n .showLabels=${this.showLabels && !frame.labelsHidden}\n .tickmarksInside=${this.tickmarksInside}\n .crosshairEnabled=${true}\n .crosshairCenterCutout=${this.hasCenterReadouts}\n .northArrow=${!frame.labelsHidden}\n .angleSetpoint=${this.headingSetpoint ?? undefined}\n .newAngleSetpoint=${this.newHeadingSetpoint}\n .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}\n .angleSetpointAtZeroDeadband=${this.headingSetpointAtZeroDeadband}\n .setpointOverride=${this.headingSetpointOverride}\n .priority=${this.priority}\n .animateSetpoint=${this.animateSetpoint}\n .rotation=${this.getRotation()}\n >\n </obc-watch>\n <svg viewBox=\"${viewBox}\">\n ${hdgArrow(\n this.hdgArrowStyle,\n this.heading + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.hdg)\n )}\n ${cogArrow(\n this.cogArrowStyle,\n this.courseOverGround + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.cog)\n )}\n </svg>\n ${this.hasCenterReadouts\n ? html`<div class=\"center-readout-overlay\">\n ${renderCenterReadouts(\n resolveCompassCenterReadouts(this.centerReadouts, {\n heading: this.heading,\n courseOverGround: this.courseOverGround,\n priorityFor: (source) => this.readoutPriorityFor(source),\n })\n )}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n static override styles = [\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .center-readout-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n }\n\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-heading': ObcHeading;\n }\n}\n"],"names":["CompassDirection","HeadingPriorityElement"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmCO,IAAK,qCAAAA,sBAAL;AACLA,oBAAA,SAAA,IAAU;AACVA,oBAAA,WAAA,IAAY;AACZA,oBAAA,UAAA,IAAW;AAHD,SAAAA;AAAA,GAAA,oBAAA,CAAA,CAAA;AAML,IAAK,2CAAAC,4BAAL;AACLA,0BAAA,KAAA,IAAM;AACNA,0BAAA,KAAA,IAAM;AAFI,SAAAA;AAAA,GAAA,0BAAA,CAAA,CAAA;AA2DL,IAAM,aAAN,cAAyB,WAAW;AAAA,EAApC,cAAA;AAAA,UAAA,GAAA,SAAA;AACqB,SAAA,UAAU;AACV,SAAA,mBAAmB;AAEnB,SAAA,kBAAiC;AAIhC,SAAA,oBAA6B;AAE9B,SAAA,gCAAwC;AAEvC,SAAA,0BAAmC;AAEjB,SAAA,wBAC3C;AAEwB,SAAA,gCAAwC;AAEvC,SAAA,kBAA2B;AAE3B,SAAA,WAAoB;AACJ,SAAA,iBAAgC,CAAA;AACjD,SAAA,YACxB;AACwB,SAAA,WAAqB,SAAS;AAGxD,SAAA,mBAA6C;AAAA,MAAC;AAAA;AAAA,IAAA;AAiB9C,SAAA,iBAAyC,CAAA;AAEf,SAAA,gBAA+B,cAAc;AAE7C,SAAA,gBAA+B,cAAc;AAE5C,SAAA,aAAsB;AAEtB,SAAA,kBAA2B;AAWtD,SAAQ,aAAa,IAAI,eAAe;AAAA,MACtC,mBAAmB;AAAA,MACnB,gBAAgB,MAAM,KAAK,cAAA;AAAA,IAAc,CAC1C;AAwBD,SAAQ,oBAAoB,IAAI,iBAAiB,MAAM,CAAA,CAAE;AAgBzD,SAAQ,kBAAkB;AAAA,EAAA;AAAA,EAtCjB,WAAW,SAA+B;AACjD,UAAM,WAAW,OAAO;AACxB,SAAK,WAAW,KAAK;AAAA,MACnB,UAAU,KAAK,mBAAmB;AAAA,MAClC,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,wBAAwB,KAAK;AAAA,MAC7B,wBAAwB,KAAK;AAAA,MAC7B,kBAAkB,KAAK;AAAA,MACvB,iBAAiB,KAAK;AAAA,IAAA,CACvB;AAAA,EACH;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA;AACN,SAAK,WAAW,QAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,oBAA4B;AAClC,QAAI,KAAK,iBAAiB;AACxB,aAAO;AAAA,IACT;AACA,WAAO,wBAAwB,KAAK,aAAa,sBAAsB;AAAA,EACzE;AAAA,EAMS,QAAQ,SAA+B;AAC9C,UAAM,QAAQ,OAAO;AACrB,SAAK,kBAAkB;AAAA,MACrB;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAAA,EAET;AAAA,EAEA,IAAY,iBAAmC;AAC7C,WAAO,KAAK,eAAe,IAAI,CAAC,EAAC,UAAU,UAAU,QAAQ,WAAU;AACrE,YAAM,QACJ,KAAK,WAAW,YAAY,KAAK,WAAW,WACxC,YAAY,YACZ,SACE,YAAY,SACZ,YAAY;AACpB,aAAO,EAAC,UAAU,UAAU,MAAM,MAAA;AAAA,IACpC,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,SAA2C;AAC7D,UAAM,WAAW,MAAM,QAAQ,KAAK,gBAAgB,IAChD,KAAK,mBACL,CAAA;AACJ,WAAO,SAAS,SAAS,OAAO,IAAI,KAAK,WAAW,SAAS;AAAA,EAC/D;AAAA,EAEQ,mBAAmB,QAAwC;AACjE,QAAI,WAAW,qBAAqB,KAAK;AACvC,aAAO,KAAK;AAAA,QAAY;AAAA;AAAA,MAAA;AAAA,IAC1B;AACA,QAAI,WAAW,qBAAqB,KAAK;AACvC,aAAO,KAAK;AAAA,QAAY;AAAA;AAAA,MAAA;AAAA,IAC1B;AACA,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,IAAY,oBAA6B;AACvC,WAAO,KAAK,eAAe,SAAS;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,kBAAmC;AAC7C,WAAO,KAAK,gBAAgB,UAAa,KAAK,oBAC1C,gBAAgB,SAChB,gBAAgB;AAAA,EACtB;AAAA,EAEQ,cAAkC;AACxC,QAAI,KAAK,cAAc,WAA0B;AAC/C,aAAO;AAAA,IACT,WAAW,KAAK,cAAc,aAA4B;AACxD,aAAO,CAAC,KAAK;AAAA,IACf,WAAW,KAAK,cAAc,YAA2B;AACvD,aAAO,CAAC,KAAK;AAAA,IACf;AACA,WAAO;AAAA,EACT;AAAA,EAES,SAAS;AAChB,UAAM,YAAwB;AAAA,MAC5B,EAAC,OAAO,GAAG,MAAM,aAAa,KAAA;AAAA,MAC9B,EAAC,OAAO,IAAI,MAAM,aAAa,KAAA;AAAA,MAC/B,EAAC,OAAO,KAAK,MAAM,aAAa,KAAA;AAAA,MAChC,EAAC,OAAO,KAAK,MAAM,aAAa,KAAA;AAAA,IAAI;AAGtC,UAAM,QAAQ,mBAAmB;AAAA,MAC/B,aAAa;AAAA,MACb,cAAc,KAAK,kBAAA;AAAA,MACnB,aAAa,mBAAmB,IAAI;AAAA,MACpC,cAAc,KAAK;AAAA,IAAA,CACpB;AACD,SAAK,SAAS;AACd,UAAM,UAAU,MAAM;AAEtB,WAAO;AAAA;AAAA;AAAA,sBAGW,KAAK,QAAQ;AAAA,sBACb,KAAK;AAAA,qBACN,KAAK,cAAc;AAAA,uBACjB,SAAS;AAAA,6BACH,KAAK,eAAe;AAAA,qBAC5B,KAAK,gBAAgB,UAAa,CAAC,KAAK,oBAC/C;AAAA,MACE;AAAA,QACE,MAAM,gBAAgB;AAAA,QACtB,aAAa,KAAK;AAAA,QAClB,WAAW,UAAU,KAAK,OAAO;AAAA,MAAA;AAAA,IACnC,IAEF,CAAA,CAAE;AAAA,wBACQ,KAAK,cAAc,CAAC,MAAM,YAAY;AAAA,6BACjC,KAAK,eAAe;AAAA,8BACnB,IAAI;AAAA,mCACC,KAAK,iBAAiB;AAAA,wBACjC,CAAC,MAAM,YAAY;AAAA,2BAChB,KAAK,mBAAmB,MAAS;AAAA,8BAC9B,KAAK,kBAAkB;AAAA,6BACxB,KAAK,WAAW,kBAAkB,KAAK,OAAO,CAAC;AAAA,yCACnC,KAAK,6BAA6B;AAAA,8BAC7C,KAAK,uBAAuB;AAAA,sBACpC,KAAK,QAAQ;AAAA,6BACN,KAAK,eAAe;AAAA,sBAC3B,KAAK,aAAa;AAAA;AAAA;AAAA,wBAGhB,OAAO;AAAA,YACnB;AAAA,MACA,KAAK;AAAA,MACL,KAAK,WAAW,KAAK,YAAA,KAAiB;AAAA,MACtC,KAAK;AAAA,QAAY;AAAA;AAAA,MAAA;AAAA,IAA0B,CAC5C;AAAA,YACC;AAAA,MACA,KAAK;AAAA,MACL,KAAK,oBAAoB,KAAK,YAAA,KAAiB;AAAA,MAC/C,KAAK;AAAA,QAAY;AAAA;AAAA,MAAA;AAAA,IAA0B,CAC5C;AAAA;AAAA,UAED,KAAK,oBACH;AAAA,gBACI;AAAA,MACA,6BAA6B,KAAK,gBAAgB;AAAA,QAChD,SAAS,KAAK;AAAA,QACd,kBAAkB,KAAK;AAAA,QACvB,aAAa,CAAC,WAAW,KAAK,mBAAmB,MAAM;AAAA,MAAA,CACxD;AAAA,IAAA,CACF;AAAA,sBAEH,OAAO;AAAA;AAAA;AAAA,EAGjB;AAqCF;AA5Ra,WAyPK,SAAS;AAAA,EACvB;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCF;AA1R0B,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GADb,WACe,WAAA,WAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAFb,WAEe,WAAA,oBAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAJb,WAIe,WAAA,mBAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GANb,WAMe,WAAA,sBAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GARd,WAQgB,WAAA,qBAAA,CAAA;AAED,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAVb,WAUe,WAAA,iCAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAZd,WAYgB,WAAA,2BAAA,CAAA;AAEkB,gBAAA;AAAA,EAA5C,SAAS,EAAC,MAAM,SAAS,WAAW,OAAM;AAAA,GAdhC,WAckC,WAAA,yBAAA,CAAA;AAGnB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAjBb,WAiBe,WAAA,iCAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAnBd,WAmBgB,WAAA,mBAAA,CAAA;AAEA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GArBd,WAqBgB,WAAA,YAAA,CAAA;AACgB,gBAAA;AAAA,EAA1C,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GAtB9B,WAsBgC,WAAA,kBAAA,CAAA;AACjB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAvBb,WAuBe,WAAA,aAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAzBb,WAyBe,WAAA,YAAA,CAAA;AAG1B,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GA3B9B,WA4BX,WAAA,oBAAA,CAAA;AAO0B,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAnCb,WAmCe,WAAA,eAAA,CAAA;AAU1B,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GA5C9B,WA6CX,WAAA,kBAAA,CAAA;AAE0B,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA/Cb,WA+Ce,WAAA,iBAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAjDb,WAiDe,WAAA,iBAAA,CAAA;AAEC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAnDd,WAmDgB,WAAA,cAAA,CAAA;AAEA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GArDd,WAqDgB,WAAA,mBAAA,CAAA;AAS3B,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,QAAQ,WAAW,iBAAgB;AAAA,GA7DzC,WA8DX,WAAA,gBAAA,CAAA;AA9DW,aAAN,gBAAA;AAAA,EADN,cAAc,aAAa;AAAA,GACf,UAAA;"}
1
+ {"version":3,"file":"heading.js","sources":["../../../src/navigation-instruments/heading/heading.ts"],"sourcesContent":["import {LitElement, PropertyValues, css, html, nothing} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {\n CogArrowStyle,\n HdgArrowStyle,\n cogArrow,\n hdgArrow,\n} from '../course-arrows/course-arrows.js';\nimport {\n CompassCenterReadout,\n CompassReadoutSource,\n centerReadoutStyles,\n renderCenterReadouts,\n resolveCompassCenterReadouts,\n} from '../readout/center-readout.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport {\n applyPinnedHostSize,\n computeRadialFrame,\n measureContainerPx,\n NORTH_ARROW_WIDTH_PX,\n NSWE_LABEL_WIDTH_PX,\n type RadialFrame,\n} from '../../svghelpers/radial-frame.js';\nimport {VesselImage, VesselImageSize, WatchCircleType} from '../watch/watch.js';\nimport {SetpointBundle} from '../../svghelpers/setpoint-bundle.js';\nimport {Priority} from '../types.js';\nimport {customElement} from '../../decorator.js';\nexport {HdgArrowStyle, CogArrowStyle};\nexport {CompassReadoutSource};\nexport type {CompassCenterReadout};\n\nexport enum CompassDirection {\n NorthUp = 'northUp',\n HeadingUp = 'headingUp',\n CourseUp = 'courseUp',\n}\n\nexport enum HeadingPriorityElement {\n hdg = 'hdg',\n cog = 'cog',\n}\n\n/**\n * `<obc-heading>` – Heading instrument with HDG/COG arrows over a single-ring\n * watch face, with optional vessel silhouette and center readouts.\n *\n * Renders a circular instrument that displays heading (HDG) and course over\n * ground (COG) as rotating arrows. It supports a heading setpoint with auto\n * at-setpoint detection, advice zones, north-up/heading-up/course-up\n * orientation, an optional vessel image, and center readouts replacing the\n * vessel.\n *\n * ## Features\n *\n * - **Direction modes**: `northUp` (default), `headingUp`, or `courseUp`\n * via the `direction` property.\n * - **HDG / COG arrows**: Two arrows overlay the watch face, rotating\n * independently; their look is selected per arrow via `hdgArrowStyle`\n * (`needle` default, `arrowHead`, `vector`, `beamLine`) and\n * `cogArrowStyle` (`needle` default, `arrowHead`, `vector`,\n * `velocityVector`).\n * - **Vessel image**: Optional vessel silhouette via `vesselImage`\n * (hidden by default), centered and rotating with heading.\n * - **Center readouts**: `centerReadouts` replaces the vessel with up to\n * three readouts (first on top, the rest below a horizontal divider);\n * values bind to the instrument's own inputs per entry `source`.\n * - **Heading setpoint**: Optional setpoint marker with auto at-setpoint\n * detection via `headingSetpoint`, `atHeadingSetpoint`, and deadband\n * tuning properties.\n * - **Advice zones**: Pass `headingAdvices` to render caution/alert arcs.\n * - **Color priority**: Set `priority` to `Priority.enhanced` and select\n * the accented elements via `priorityElements`.\n *\n * ## Usage Guidelines\n *\n * - Set `heading` and `courseOverGround` to the current sensor values in\n * degrees.\n * - Use `obc-compass` instead when rate-of-turn, wind or current overlays\n * are needed — this instrument is the reduced heading-focused variant.\n *\n * ## Example\n *\n * ```html\n * <obc-heading\n * heading=\"45\"\n * courseOverGround=\"50\"\n * direction=\"northUp\"\n * headingSetpoint=\"90\"\n * ></obc-heading>\n * ```\n *\n * @ignition-base-height: 512px\n * @ignition-base-width: 512px\n * @stable\n */\n@customElement('obc-heading')\nexport class ObcHeading extends LitElement {\n @property({type: Number}) heading = 0;\n @property({type: Number}) courseOverGround = 0;\n\n @property({type: Number}) headingSetpoint: number | null = null;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) newHeadingSetpoint: number | undefined;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==false */\n @property({type: Boolean}) atHeadingSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Number}) headingSetpointAtZeroDeadband: number = 0.5;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) headingSetpointOverride: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean, attribute: false}) autoAtHeadingSetpoint: boolean =\n true;\n /** @availableWhen headingSetpoint!=null && autoAtHeadingSetpoint==true */\n @property({type: Number}) autoAtHeadingSetpointDeadband: number = 2;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) animateSetpoint: boolean = false;\n /** @availableWhen headingSetpoint!=null */\n @property({type: Boolean}) touching: boolean = false;\n @property({type: Array, attribute: false}) headingAdvices: AngleAdvice[] = [];\n @property({type: String}) direction: CompassDirection =\n CompassDirection.NorthUp;\n @property({type: String}) priority: Priority = Priority.regular;\n /** @availableWhen priority==enhanced */\n @property({type: Array, attribute: false})\n priorityElements: HeadingPriorityElement[] = [HeadingPriorityElement.hdg];\n /**\n * The vessel silhouette shown in the center, rotating with heading. When\n * unset (default) no vessel is shown; hidden while `centerReadouts` is\n * non-empty.\n * @availableWhen centerReadouts==[]\n */\n @property({type: String}) vesselImage: VesselImage | undefined;\n /**\n * Center readouts replacing the vessel: the first entry renders on top,\n * the rest side by side below a horizontal divider. Values bind per entry\n * `source` (`hdg` → `heading`, `cog` → `courseOverGround`; `rot` has no\n * input on this instrument and renders a dash) and colors follow\n * `priorityElements`. While non-empty, the crosshair's center is cut out\n * so the readouts sit on a clean face.\n */\n @property({type: Array, attribute: false})\n centerReadouts: CompassCenterReadout[] = [];\n /** HDG arrow style: `needle` (default), `arrowHead`, `vector`, or `beamLine`. */\n @property({type: String}) hdgArrowStyle: HdgArrowStyle = HdgArrowStyle.needle;\n /** COG arrow style: `needle` (default), `arrowHead`, `vector`, or `velocityVector`. */\n @property({type: String}) cogArrowStyle: CogArrowStyle = CogArrowStyle.needle;\n /** Show compass NSEW labels. */\n @property({type: Boolean}) showLabels: boolean = false;\n /** When true, labels and north arrow are placed inside the outer ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n /**\n * Outer-ring diameter in CSS pixels. When set, the instrument renders at a\n * fixed intrinsic size derived from the ring, arc shape and label reserve —\n * so instruments sharing the same value have identical ring circumference\n * regardless of label width or arc extent (like obc-donut-chart's\n * fixedHeight). When unset (default), the instrument fills its container.\n */\n @property({type: Number, attribute: 'face-diameter'})\n faceDiameter: number | undefined;\n\n private _headingSp = new SetpointBundle({\n angularWraparound: true,\n onAnimationEnd: () => this.requestUpdate(),\n });\n\n override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n this._headingSp.sync({\n setpoint: this.headingSetpoint ?? undefined,\n newSetpoint: this.newHeadingSetpoint,\n atSetpoint: this.atHeadingSetpoint,\n touching: this.touching,\n autoAtSetpoint: this.autoAtHeadingSetpoint,\n autoAtSetpointDeadband: this.autoAtHeadingSetpointDeadband,\n setpointAtZeroDeadband: this.headingSetpointAtZeroDeadband,\n setpointOverride: this.headingSetpointOverride,\n animateSetpoint: this.animateSetpoint,\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._headingSp.dispose();\n }\n\n // @ts-expect-error TS6133: The controller ensures that the render\n // function is called on resize of the element\n private _resizeController = new ResizeController(this, {});\n\n /**\n * Pixel cost of the outside decor: the always-rendered north-arrow glyph\n * plus, only while shown, the NSWE labels (both keep a constant on-screen\n * size via `1/scale` terms). Feeds the frame's width-aware reserve,\n * replacing the former empirical `72 + delta(clientSize)` padding.\n */\n private getOutsideDecorPx(): number {\n if (this.tickmarksInside) {\n return 0;\n }\n return NORTH_ARROW_WIDTH_PX + (this.showLabels ? NSWE_LABEL_WIDTH_PX : 0);\n }\n\n /** Whether the host size styles were set by applyPinnedHostSize. */\n private _hostSizePinned = false;\n private _frame: RadialFrame | undefined;\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n this._hostSizePinned = applyPinnedHostSize(\n this,\n this._frame,\n this._hostSizePinned\n );\n }\n\n private get angleAdviceRaw(): AngleAdviceRaw[] {\n return this.headingAdvices.map(({minAngle, maxAngle, hinted, type}) => {\n const state =\n this.heading >= minAngle && this.heading <= maxAngle\n ? AdviceState.triggered\n : hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {minAngle, maxAngle, type, state};\n });\n }\n\n private priorityFor(element: HeadingPriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private readoutPriorityFor(source: CompassReadoutSource): Priority {\n if (source === CompassReadoutSource.hdg) {\n return this.priorityFor(HeadingPriorityElement.hdg);\n }\n if (source === CompassReadoutSource.cog) {\n return this.priorityFor(HeadingPriorityElement.cog);\n }\n return Priority.regular;\n }\n\n private get hasCenterReadouts(): boolean {\n return this.centerReadouts.length > 0;\n }\n\n /**\n * The face gains the double-band ring while center content (vessel or\n * readouts) is shown, per the design's vessel/center-label faces.\n */\n private get watchCircleType(): WatchCircleType {\n return this.vesselImage !== undefined || this.hasCenterReadouts\n ? WatchCircleType.double\n : WatchCircleType.single;\n }\n\n private getRotation(): number | undefined {\n if (this.direction === CompassDirection.NorthUp) {\n return undefined;\n } else if (this.direction === CompassDirection.HeadingUp) {\n return -this.heading;\n } else if (this.direction === CompassDirection.CourseUp) {\n return -this.courseOverGround;\n }\n return undefined;\n }\n\n override render() {\n const tickmarks: Tickmark[] = [\n {angle: 0, type: TickmarkType.main},\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n {angle: 270, type: TickmarkType.main},\n ];\n\n const frame = computeRadialFrame({\n basePadding: 72,\n labelWidthPx: this.getOutsideDecorPx(),\n containerPx: measureContainerPx(this),\n faceDiameter: this.faceDiameter,\n });\n this._frame = frame;\n const viewBox = frame.viewBox;\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .arcFrame=${frame}\n .advices=${this.angleAdviceRaw}\n .tickmarks=${tickmarks}\n .watchCircleType=${this.watchCircleType}\n .vessels=${this.vesselImage !== undefined && !this.hasCenterReadouts\n ? [\n {\n size: VesselImageSize.medium,\n vesselImage: this.vesselImage,\n transform: `rotate(${this.heading}deg)`,\n },\n ]\n : []}\n .showLabels=${this.showLabels && !frame.labelsHidden}\n .tickmarksInside=${this.tickmarksInside}\n .crosshairEnabled=${true}\n .crosshairCenterCutout=${this.hasCenterReadouts}\n .northArrow=${true}\n .angleSetpoint=${this.headingSetpoint ?? undefined}\n .newAngleSetpoint=${this.newHeadingSetpoint}\n .atAngleSetpoint=${this._headingSp.computeAtSetpoint(this.heading)}\n .angleSetpointAtZeroDeadband=${this.headingSetpointAtZeroDeadband}\n .setpointOverride=${this.headingSetpointOverride}\n .priority=${this.priority}\n .animateSetpoint=${this.animateSetpoint}\n .rotation=${this.getRotation()}\n >\n </obc-watch>\n <svg viewBox=\"${viewBox}\">\n ${hdgArrow(\n this.hdgArrowStyle,\n this.heading + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.hdg)\n )}\n ${cogArrow(\n this.cogArrowStyle,\n this.courseOverGround + (this.getRotation() ?? 0),\n this.priorityFor(HeadingPriorityElement.cog)\n )}\n </svg>\n ${this.hasCenterReadouts\n ? html`<div class=\"center-readout-overlay\">\n ${renderCenterReadouts(\n resolveCompassCenterReadouts(this.centerReadouts, {\n heading: this.heading,\n courseOverGround: this.courseOverGround,\n priorityFor: (source) => this.readoutPriorityFor(source),\n })\n )}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n static override styles = [\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .center-readout-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n }\n\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-heading': ObcHeading;\n }\n}\n"],"names":["CompassDirection","HeadingPriorityElement"],"mappings":"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"}
@@ -122,6 +122,12 @@ export declare class ObcPitchRollHeave extends LitElement {
122
122
  * `obc-watch` renders its crosshair after the bands, i.e. on top of them.
123
123
  * Drawing it here puts it under the watch layer, so the bands and the heave
124
124
  * column mask it naturally.
125
+ *
126
+ * In `single-scale` nothing frames the segment above the vessel (the other
127
+ * three arms end under the pitch band, roll band and heave column), so the
128
+ * vertical arm stops at the centre instead of continuing upward. In
129
+ * `dual-scale` the top roll band gives it a natural endpoint, so the full
130
+ * arm is kept.
125
131
  */
126
132
  private renderCrosshair;
127
133
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"pitch-roll-heave.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkD,MAAM,KAAK,CAAC;AAEhF,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EAOZ,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAgBrC,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,mDAAmD,CAAC;AAE3D,oBAAY,qBAAqB;IAC/B,2EAA2E;IAC3E,WAAW,iBAAiB;IAC5B,8DAA8D;IAC9D,SAAS,eAAe;CACzB;AAED,oBAAY,6BAA6B;IACvC,KAAK,UAAU;IACf,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AA2ED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IACrB,IAAI,EAAE,qBAAqB,CACjB;IAEV,KAAK,SAAK;IACV,IAAI,SAAK;IACT,KAAK,SAAK;IACV,WAAW,SAAK;IAChB,WAAW,SAAK;IAChB,UAAU,SAAK;IACf,UAAU,SAAK;IACf,aAAa,SAAK;IAClB,aAAa,SAAK;IAC5C,gFAAgF;IACtD,UAAU,SAAM;IAE1C;;;;OAIG;IACuB,aAAa,SAAM;IAC7C,8CAA8C;IACpB,YAAY,SAAM;IACjB,YAAY,UAAS;IAEhD;;;;;OAKG;IACwB,UAAU,UAAS;IAC9C,sCAAsC;IACZ,UAAU,SAAW;IAC/C,sCAAsC;IACZ,SAAS,SAAU;IAC7C,sCAAsC;IACZ,UAAU,SAAW;IAC/C;;;OAGG;IACuB,IAAI,SAAS;IACvC;;;OAGG;IACuB,SAAS,SAAO;IAC1C,sCAAsC;IACZ,cAAc,SAAK;IAE7C,4DAA4D;IAClC,eAAe,EAAE,WAAW,CAAuB;IAC7E,4DAA4D;IAClC,eAAe,EAAE,WAAW,CAAuB;IAC7E,4DAA4D;IAClC,cAAc,SAAK;IAEnB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAa;IAC/C,aAAa,EAAE,MAAM,GAAG,SAAS,CAAa;IACxE,+CAA+C;IACpB,kBAAkB,UAAS;IACtD,8CAA8C;IACnB,iBAAiB,UAAS;IAC5B,WAAW,EAAE,YAAY,EAAE,CAAM;IAEhC,QAAQ,EAAE,QAAQ,CAAoB;IAEhE,gBAAgB,EAAE,6BAA6B,EAAE,CAI/C;IAEF,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,QAAQ;IAMhB,OAAO,KAAK,wBAAwB,GAKnC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,8EAA8E;IAC9E,OAAO,KAAK,YAAY,GAEvB;IAED;;;OAGG;IACH,OAAO,KAAK,sBAAsB,GAKjC;IAED;;;;OAIG;IACH,OAAO,KAAK,qBAAqB,GAIhC;IAEQ,MAAM;IAuEf;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;IA+CzB,OAAO,KAAK,YAAY,GAWvB;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,UAAU;IA2IlB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IA4GxB,uEAAuE;IACvE,OAAO,CAAC,UAAU;IA4BlB,yEAAyE;IACzE,OAAO,CAAC,eAAe;IAqGvB,OAAO,CAAC,OAAO;IAqCf,OAAgB,MAAM,4BA2BpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,iBAAiB,CAAC;KAC3C;CACF"}
1
+ {"version":3,"file":"pitch-roll-heave.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkD,MAAM,KAAK,CAAC;AAEhF,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EAOZ,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAgBrC,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,mDAAmD,CAAC;AAE3D,oBAAY,qBAAqB;IAC/B,2EAA2E;IAC3E,WAAW,iBAAiB;IAC5B,8DAA8D;IAC9D,SAAS,eAAe;CACzB;AAED,oBAAY,6BAA6B;IACvC,KAAK,UAAU;IACf,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AA2ED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IACrB,IAAI,EAAE,qBAAqB,CACjB;IAEV,KAAK,SAAK;IACV,IAAI,SAAK;IACT,KAAK,SAAK;IACV,WAAW,SAAK;IAChB,WAAW,SAAK;IAChB,UAAU,SAAK;IACf,UAAU,SAAK;IACf,aAAa,SAAK;IAClB,aAAa,SAAK;IAC5C,gFAAgF;IACtD,UAAU,SAAM;IAE1C;;;;OAIG;IACuB,aAAa,SAAM;IAC7C,8CAA8C;IACpB,YAAY,SAAM;IACjB,YAAY,UAAS;IAEhD;;;;;OAKG;IACwB,UAAU,UAAS;IAC9C,sCAAsC;IACZ,UAAU,SAAW;IAC/C,sCAAsC;IACZ,SAAS,SAAU;IAC7C,sCAAsC;IACZ,UAAU,SAAW;IAC/C;;;OAGG;IACuB,IAAI,SAAS;IACvC;;;OAGG;IACuB,SAAS,SAAO;IAC1C,sCAAsC;IACZ,cAAc,SAAK;IAE7C,4DAA4D;IAClC,eAAe,EAAE,WAAW,CAAuB;IAC7E,4DAA4D;IAClC,eAAe,EAAE,WAAW,CAAuB;IAC7E,4DAA4D;IAClC,cAAc,SAAK;IAEnB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAa;IAC/C,aAAa,EAAE,MAAM,GAAG,SAAS,CAAa;IACxE,+CAA+C;IACpB,kBAAkB,UAAS;IACtD,8CAA8C;IACnB,iBAAiB,UAAS;IAC5B,WAAW,EAAE,YAAY,EAAE,CAAM;IAEhC,QAAQ,EAAE,QAAQ,CAAoB;IAEhE,gBAAgB,EAAE,6BAA6B,EAAE,CAI/C;IAEF,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,QAAQ;IAMhB,OAAO,KAAK,wBAAwB,GAKnC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,8EAA8E;IAC9E,OAAO,KAAK,YAAY,GAEvB;IAED;;;OAGG;IACH,OAAO,KAAK,sBAAsB,GAKjC;IAED;;;;OAIG;IACH,OAAO,KAAK,qBAAqB,GAIhC;IAEQ,MAAM;IAuEf;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,eAAe;IAiBvB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;IA+CzB,OAAO,KAAK,YAAY,GAWvB;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,UAAU;IA2IlB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IA4GxB,uEAAuE;IACvE,OAAO,CAAC,UAAU;IA4BlB,yEAAyE;IACzE,OAAO,CAAC,eAAe;IAqGvB,OAAO,CAAC,OAAO;IAqCf,OAAgB,MAAM,4BA2BpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,iBAAiB,CAAC;KAC3C;CACF"}
@@ -200,9 +200,16 @@ let ObcPitchRollHeave = class extends LitElement {
200
200
  * `obc-watch` renders its crosshair after the bands, i.e. on top of them.
201
201
  * Drawing it here puts it under the watch layer, so the bands and the heave
202
202
  * column mask it naturally.
203
+ *
204
+ * In `single-scale` nothing frames the segment above the vessel (the other
205
+ * three arms end under the pitch band, roll band and heave column), so the
206
+ * vertical arm stops at the centre instead of continuing upward. In
207
+ * `dual-scale` the top roll band gives it a natural endpoint, so the full
208
+ * arm is kept.
203
209
  */
204
210
  renderCrosshair() {
205
211
  const r = OUTER_RING_RADIUS;
212
+ const yTop = this.isDualScale ? -r : 0;
206
213
  return svg`
207
214
  <line
208
215
  x1=${-r} y1="0" x2=${r} y2="0"
@@ -210,7 +217,7 @@ let ObcPitchRollHeave = class extends LitElement {
210
217
  vector-effect="non-scaling-stroke"
211
218
  />
212
219
  <line
213
- x1="0" y1=${-r} x2="0" y2=${r}
220
+ x1="0" y1=${yTop} x2="0" y2=${r}
214
221
  stroke="var(--instrument-frame-tertiary-color)"
215
222
  vector-effect="non-scaling-stroke"
216
223
  />
@@ -1 +1 @@
1
- {"version":3,"file":"pitch-roll-heave.js","sources":["../../../src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg, type SVGTemplateResult} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n type WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {arcTickmarks, TickmarkType, type Tickmark} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, type AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport {\n CenterReadoutArrangement,\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n} from '../../svghelpers/arc-frame.js';\nimport {\n linearTickInterval,\n watchfaceLinear,\n} from '../../building-blocks/instrument-linear/instrument-linear.js';\nimport type {\n LinearAdvice,\n LinearAdviceRaw,\n} from '../../building-blocks/instrument-linear/advice.js';\n\nexport enum ObcPitchRollHeaveType {\n /** Pitch on the right, roll at the bottom, heave in the left band slot. */\n singleScale = 'single-scale',\n /** Pitch and roll mirrored onto both sides, heave centred. */\n dualScale = 'dual-scale',\n}\n\nexport enum PitchRollHeavePriorityElement {\n pitch = 'pitch',\n roll = 'roll',\n heave = 'heave',\n}\n\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n/**\n * Minimum diagonal clearance, in central-layer pixels, between the zoomed\n * heave column and the adjacent roll band. Matches the constant\n * `obc-pitch-roll` uses between its own adjacent arcs.\n */\nconst CORNER_GAP_PX = 32;\n\n/** Numerical safety floor when an axis arc has to collapse for clearance. */\nconst MIN_ARC_HALF_DEG = 2;\n\n/** Width of the tick lane inside the heave column, in SVG units. */\nconst HEAVE_SCALE_WIDTH = 24;\n\n/** Band thickness at the natural, un-zoomed radii. */\nconst NOMINAL_BAND =\n OUTER_RING_RADIUS - innerRingRadiusFor(WatchCircleType.double);\n\n/**\n * Clearance kept between the centred (`dual-scale`) heave column's corners and\n * the surrounding band, in central-layer pixels. Sized so the un-zoomed\n * default is untouched — there the corner sits 13.2 units inside the free\n * radius — while the tighter zoomed layout is pulled back off the bands.\n */\nconst HEAVE_CENTRE_GAP_PX = 10;\n\n/**\n * The band slot the heave column fills, in central-layer coordinates.\n *\n * `outerR`/`innerR` bound the slot radially; `capRadius` is the radius of the\n * pitch arc's outer edge about its own origin, which is what the column's\n * height is measured against so the two line up. Un-zoomed the two radii\n * coincide; under zoom the arc is drawn on a shifted sub-watch and they differ.\n */\ninterface HeaveBand {\n outerR: number;\n innerR: number;\n capRadius: number;\n pitchDeg: number;\n}\n\n/**\n * Natural size of the heave column: as thick as the band slot, and tall enough\n * that its top and bottom edges sit level with the pitch arc's end caps.\n */\nfunction heaveColumnSize(band: HeaveBand): {width: number; height: number} {\n return {\n width: band.outerR - band.innerR,\n height: 2 * band.capRadius * Math.sin((band.pitchDeg * Math.PI) / 180),\n };\n}\n\n/**\n * Distance from a point to an axis-aligned rectangle; 0 when the point is\n * inside. Used to keep the zoomed roll band clear of the heave column, which\n * — unlike the arc-to-arc case — is a rectangle, so a corner may clear it on\n * one axis alone.\n */\nfunction distanceToRect(\n px: number,\n py: number,\n x0: number,\n y0: number,\n x1: number,\n y1: number\n): number {\n const dx = Math.max(0, x0 - px, px - x1);\n const dy = Math.max(0, y0 - py, py - y1);\n return Math.hypot(dx, dy);\n}\n\n/**\n * `<obc-pitch-roll-heave>` — Combined pitch, roll and heave indicator.\n *\n * Places a pitch arc, a roll arc and a linear heave column around one watch\n * face. The heave column occupies the same radial slot as the arcs, and its\n * height is derived from the pitch arc so its top and bottom edges sit level\n * with the pitch arc's end caps.\n *\n * Variants (`type`):\n * - `single-scale` (default) — pitch on the right, roll at the bottom, heave in\n * the left slot, vessel silhouettes in the centre.\n * - `dual-scale` — pitch and roll mirrored onto the opposite sides, with the\n * heave column moved to the centre.\n *\n * Set `hasReadout` to replace the centre content with stacked pitch, roll and\n * heave readouts, and `zoomToFitArc` to enlarge narrow arcs so they fill the\n * available space.\n *\n * @element obc-pitch-roll-heave\n * @experimental\n */\n@customElement('obc-pitch-roll-heave')\nexport class ObcPitchRollHeave extends LitElement {\n @property({type: String}) type: ObcPitchRollHeaveType =\n ObcPitchRollHeaveType.singleScale;\n\n @property({type: Number}) pitch = 0;\n @property({type: Number}) roll = 0;\n @property({type: Number}) heave = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: Number}) minTrendHeave = 0;\n @property({type: Number}) maxTrendHeave = 0;\n /** Half-extent of the heave scale in metres; the column spans `±heaveRange`. */\n @property({type: Number}) heaveRange = 10;\n\n /**\n * Half-extent of the pitch arc in degrees. Also drives the heave column\n * height, which is `2 · outerRadius · sin(pitchArcAngle)` so the column's\n * edges stay level with the pitch arc's end caps.\n */\n @property({type: Number}) pitchArcAngle = 30;\n /** Half-extent of the roll arc in degrees. */\n @property({type: Number}) rollArcAngle = 45;\n @property({type: Boolean}) zoomToFitArc = false;\n\n /**\n * Replaces the centre content with stacked pitch, roll and heave readouts.\n * Ignored when `type` is `dual-scale`, where the heave column occupies the\n * centre.\n * @availableWhen type==singleScale\n */\n @property({type: Boolean}) hasReadout = false;\n /** @availableWhen hasReadout==true */\n @property({type: String}) pitchLabel = 'Pitch';\n /** @availableWhen hasReadout==true */\n @property({type: String}) rollLabel = 'Roll';\n /** @availableWhen hasReadout==true */\n @property({type: String}) heaveLabel = 'Heave';\n /**\n * Unit shown in the pitch and roll readouts.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG';\n /**\n * Unit shown in the heave readout.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) heaveUnit = 'm';\n /** @availableWhen hasReadout==true */\n @property({type: Number}) fractionDigits = 0;\n\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: Number}) scaleForeImage = 1;\n\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n /** @availableWhen maxPitchAdvice!=undefined */\n @property({type: Boolean}) triggerPitchAdvice = false;\n /** @availableWhen maxRollAdvice!=undefined */\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: Array}) heaveAdvice: LinearAdvice[] = [];\n\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: PitchRollHeavePriorityElement[] = [\n PitchRollHeavePriorityElement.pitch,\n PitchRollHeavePriorityElement.roll,\n PitchRollHeavePriorityElement.heave,\n ];\n\n private priorityFor(element: PitchRollHeavePriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private needleColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private barColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n private get isDualScale(): boolean {\n return this.type === ObcPitchRollHeaveType.dualScale;\n }\n\n /** The centre readouts replace the vessels; never available in dual scale. */\n private get showsReadout(): boolean {\n return this.hasReadout && !this.isDualScale;\n }\n\n /**\n * Pitch half-extent, capped so a roll arc of the minimum size still fits in\n * the remaining quadrant.\n */\n private get requestedPitchArcAngle(): number {\n return Math.min(\n 90 - MIN_ARC_HALF_DEG,\n normalizeArcAngle(this.pitchArcAngle, 30)\n );\n }\n\n /**\n * Roll half-extent, clamped so the pitch and roll arcs cannot meet: the two\n * diagonal gaps each span `90 - pitch - roll` degrees, so the pair has to\n * stay under 90° combined.\n */\n private get requestedRollArcAngle(): number {\n const roll = normalizeArcAngle(this.rollArcAngle, 45);\n const headroom = 90 - this.requestedPitchArcAngle;\n return Math.max(MIN_ARC_HALF_DEG, Math.min(roll, headroom));\n }\n\n override render() {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const overlayViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n\n const layout = this.zoomToFitArc\n ? this.zoomLayout(pitchReq, rollReq)\n : undefined;\n const band: HeaveBand = layout?.band ?? {\n outerR: OUTER_RING_RADIUS,\n innerR: innerRingRadiusFor(WatchCircleType.double),\n capRadius: OUTER_RING_RADIUS,\n pitchDeg: pitchReq,\n };\n\n return html`\n <div class=\"container\">\n <svg viewBox=${overlayViewBox}>\n ${this.showsReadout ? nothing : this.renderCrosshair()}\n ${this.renderOverlayVessels()}\n ${this.zoomToFitArc || this.isDualScale\n ? nothing\n : this.renderComplement(pitchReq)}\n ${this.renderHeaveColumn(band)}\n </svg>\n ${layout\n ? this.renderZoomedArcs(layout)\n : this.renderFullWatch(pitchReq, rollReq)}\n ${this.showsReadout\n ? html`<div class=\"readout\">\n ${renderCenterReadouts(\n [\n {\n value: this.pitch,\n label: this.pitchLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.pitch\n ),\n },\n {\n value: this.roll,\n label: this.rollLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.roll\n ),\n },\n {\n value: this.heave,\n label: this.heaveLabel,\n unit: this.heaveUnit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.heave\n ),\n },\n ],\n CenterReadoutArrangement.stacked\n )}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n /**\n * Crosshair drawn on the overlay rather than through `obc-watch`'s own\n * `crosshairEnabled`: the design has the arc bands covering the arms, but\n * `obc-watch` renders its crosshair after the bands, i.e. on top of them.\n * Drawing it here puts it under the watch layer, so the bands and the heave\n * column mask it naturally.\n */\n private renderCrosshair(): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n return svg`\n <line\n x1=${-r} y1=\"0\" x2=${r} y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n <line\n x1=\"0\" y1=${-r} x2=\"0\" y2=${r}\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Vessel silhouettes on the centre layer. Only needed under zoom — the\n * un-zoomed path hands them to `obc-watch` via `vessels`, while the zoomed\n * sub-watches have no room for them.\n */\n private renderOverlayVessels(): SVGTemplateResult | typeof nothing {\n if (!this.zoomToFitArc || this.isDualScale || this.showsReadout) {\n return nothing;\n }\n const vesselScale = 224 / 160;\n return svg`\n <g style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageSide]}\n </g>\n <g style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageFore]}\n </g>\n `;\n }\n\n /**\n * Thin ring bridging the empty span across the top, from where the heave\n * column's upper edge crosses the outer ring round to the pitch arc's start.\n * Because the column height is derived from the pitch arc, both ends land at\n * `±pitchArcAngle` off the vertical, making the ring symmetric. The two\n * diagonal gaps lower down are left open by design.\n */\n private renderComplement(pitchDeg: number): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n const rad = (pitchDeg * Math.PI) / 180;\n // Ring runs clockwise from (270 + pitchDeg) through 0 to (90 - pitchDeg).\n const x1 = -r * Math.cos(rad);\n const y1 = -r * Math.sin(rad);\n const x2 = r * Math.cos(rad);\n const y2 = -r * Math.sin(rad);\n return svg`\n <path\n d=\"M ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Linear heave scale, built from the same building block `obc-heave` uses.\n *\n * The column fills the band's radial slot, so its width equals the band\n * thickness and its height keeps its top and bottom edges level with the\n * pitch arc's end caps. In `single-scale` it sits in the left slot and is\n * mirrored so the tick lane faces outward; in `dual-scale` it moves to the\n * centre, unmirrored, and shrinks if the zoomed bands leave too little room.\n */\n private renderHeaveColumn(band: HeaveBand): SVGTemplateResult {\n const {width, height: naturalHeight} = heaveColumnSize(band);\n let height = naturalHeight;\n let offsetX = -(band.outerR + band.innerR) / 2;\n\n if (this.isDualScale) {\n offsetX = 0;\n // The centred column has to stay inside whatever the bands leave free.\n // Only the height gives way: the column's thickness reads as a match for\n // the band thickness, and shrinking both would break that.\n const free = band.innerR - HEAVE_CENTRE_GAP_PX;\n const halfWidth = width / 2;\n const maxHalfHeight =\n free > halfWidth ? Math.sqrt(free * free - halfWidth * halfWidth) : 0;\n height = Math.min(height, 2 * maxHalfHeight);\n }\n\n const scaleWidth = HEAVE_SCALE_WIDTH * Math.min(1, width / NOMINAL_BAND);\n\n const gauge = watchfaceLinear(\n {\n height,\n width,\n scaleWidth,\n minValue: -this.heaveRange,\n maxValue: this.heaveRange,\n },\n [{min: this.minTrendHeave, max: this.maxTrendHeave}],\n {value: this.heave},\n {container: 'var(--instrument-frame-primary-color)'},\n {\n hideContainer: false,\n off: false,\n priority: this.priorityFor(PitchRollHeavePriorityElement.heave),\n },\n {\n mainTickmarks: [],\n primaryTickmarkInterval: 0,\n secondaryTickmarkInterval: linearTickInterval(height, this.heaveRange),\n },\n this.heaveAdvices\n );\n\n const mirror = this.isDualScale ? '' : ' scale(-1, 1)';\n return svg`<g transform=\"translate(${offsetX}, 0)${mirror}\">${gauge}</g>`;\n }\n\n private get heaveAdvices(): LinearAdviceRaw[] {\n return this.heaveAdvice.map((advice) => {\n const isActive =\n this.maxTrendHeave >= advice.min && this.minTrendHeave <= advice.max;\n const state = isActive\n ? AdviceState.triggered\n : advice.hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {...advice, state} satisfies LinearAdviceRaw;\n });\n }\n\n /**\n * Zoom-fit geometry, computed once per render and shared by the arc layer\n * and the heave column.\n *\n * Frames are built at the REQUESTED half-extents with the same math as\n * `obc-pitch` / `obc-roll`, so each sub-watch matches its standalone\n * equivalent. Two clearance passes then shorten only the *rendered* arcs —\n * the frames stay untouched, so band thickness, position and zoom level are\n * preserved:\n *\n * 1. pitch vs roll at the diagonal, ratio-preserving, exactly as\n * `obc-pitch-roll` does it;\n * 2. roll vs the heave column, `single-scale` only, shortening the roll arc\n * alone. Because the column's height follows the pitch arc, pass 1 already\n * pulls the column in whenever pitch shrinks, so pitch needs no second\n * pass.\n */\n private zoomLayout(pitchReq: number, rollReq: number) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const innerNat = innerRingRadiusFor(WatchCircleType.double);\n const buildFrame = (halfDeg: number) => {\n const areas: WatchArea[] = [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerNat,\n extension: ext,\n targetSize,\n });\n const subArcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n const scale = (CENTRE_HALF * 2) / subArcFrame.width;\n const outerR = (OUTER_RING_RADIUS + baseFrame.radiusOffset) * scale;\n const innerR = (innerNat + baseFrame.radiusOffset) * scale;\n return {subArcFrame, outerR, innerR};\n };\n const pitchFrame = buildFrame(pitchReq);\n const rollFrame = buildFrame(rollReq);\n\n const OR = OUTER_RING_RADIUS;\n const toRad = (deg: number) => (deg * Math.PI) / 180;\n const signedDist = (\n px: number,\n py: number,\n qx: number,\n qy: number\n ): number => {\n const dx = qx - px;\n const dy = qy - py;\n const mag = Math.hypot(dx, dy);\n return dx > 0 && dy > 0 ? mag : -mag;\n };\n // Diagonal gap between two adjacent cardinal bands. All such gaps in this\n // layout are congruent, so one pair stands in for the rest.\n const minGap = (apRad: number, arRad: number): number => {\n const cosP = Math.cos(apRad);\n const sinP = Math.sin(apRad);\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const p1x = pitchFrame.innerR * sinP;\n const p1y = pitchFrame.outerR - OR - pitchFrame.innerR * cosP;\n const p2x = pitchFrame.outerR * sinP;\n const p2y = pitchFrame.outerR - OR - pitchFrame.outerR * cosP;\n const q1x = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n const q1y = -rollFrame.innerR * sinR;\n const q2x = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const q2y = -rollFrame.outerR * sinR;\n return Math.min(\n signedDist(p1x, p1y, q1x, q1y),\n signedDist(p2x, p2y, q2x, q2y)\n );\n };\n\n let aP = toRad(pitchReq);\n let aR = toRad(rollReq);\n if (minGap(aP, aR) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (minGap(aP * mid, aR * mid) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n aP *= lo;\n aR *= lo;\n }\n const pitchClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aP * 180) / Math.PI);\n let rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aR * 180) / Math.PI);\n\n const bandFor = (pitchDeg: number): HeaveBand => ({\n outerR: OR,\n innerR: OR - (pitchFrame.outerR - pitchFrame.innerR),\n capRadius: pitchFrame.outerR,\n pitchDeg,\n });\n\n if (!this.isDualScale) {\n // Roll's left end caps versus the heave column rectangle. Shrinking the\n // roll arc moves both caps toward the bottom cardinal, away from the\n // column, so the gap grows monotonically as the scalar shrinks.\n const band = bandFor(pitchClampedDeg);\n const {width, height} = heaveColumnSize(band);\n const x1 = -band.innerR;\n const x0 = x1 - width;\n const y1 = height / 2;\n const heaveGap = (arRad: number): number => {\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const outerX = -rollFrame.outerR * sinR;\n const outerY = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const innerX = -rollFrame.innerR * sinR;\n const innerY = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n return Math.min(\n distanceToRect(outerX, outerY, x0, -y1, x1, y1),\n distanceToRect(innerX, innerY, x0, -y1, x1, y1)\n );\n };\n if (heaveGap(toRad(rollClampedDeg)) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = rollClampedDeg;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (heaveGap(toRad(mid)) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, lo);\n }\n }\n\n return {\n pitchFrame,\n rollFrame,\n pitchClampedDeg,\n rollClampedDeg,\n band: bandFor(pitchClampedDeg),\n };\n }\n\n /**\n * Zoomed-arc layer: CSS-rotated `<obc-watch>` instances, each holding a\n * single arc rendered at the watch's natural top and rotated onto its\n * cardinal. `single-scale` places pitch right and roll bottom; `dual-scale`\n * mirrors both. The heave column lives on the centre overlay.\n */\n private renderZoomedArcs(layout: ReturnType<typeof this.zoomLayout>) {\n const {pitchFrame, rollFrame, pitchClampedDeg, rollClampedDeg} = layout;\n\n const subAreas = (halfDeg: number): WatchArea[] => [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n // Clip each sub-watch to the sector its (possibly shortened) arc covers so\n // the indicator cannot leak past the visible band.\n const sectorClip = (\n halfDeg: number,\n frame: typeof rollFrame.subArcFrame\n ): string => {\n const oxPct = (-frame.x / frame.width) * 100;\n const oyPct = (-frame.y / frame.height) * 100;\n const dxPct = oyPct * Math.tan((halfDeg * Math.PI) / 180);\n const lx = Math.max(0, oxPct - dxPct);\n const rx = Math.min(100, oxPct + dxPct);\n return `polygon(${oxPct}% ${oyPct}%, ${lx}% 0%, ${rx}% 0%)`;\n };\n\n const axis = (\n element: PitchRollHeavePriorityElement,\n frame: typeof rollFrame,\n halfDeg: number,\n value: number,\n avgMin: number,\n avgMax: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => ({\n arcFrame: frame.subArcFrame,\n areas: subAreas(halfDeg),\n barAreas: [\n {\n startAngle: avgMin,\n endAngle: avgMax,\n fillColor: this.barColor(element),\n },\n ],\n needles: [\n {\n angle: value,\n fillColor: this.needleColor(element),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ],\n advices: this.subAdvices(halfDeg, max, trigger, cap),\n tickmarks: [\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(0, halfDeg),\n ],\n clipPath: sectorClip(halfDeg, frame.subArcFrame),\n });\n\n const pitchAxis = axis(\n PitchRollHeavePriorityElement.pitch,\n pitchFrame,\n pitchClampedDeg,\n this.pitch,\n this.minAvgPitch,\n this.maxAvgPitch,\n this.maxPitchAdvice,\n this.triggerPitchAdvice,\n 30\n );\n const rollAxis = axis(\n PitchRollHeavePriorityElement.roll,\n rollFrame,\n rollClampedDeg,\n this.roll,\n this.minAvgRoll,\n this.maxAvgRoll,\n this.maxRollAdvice,\n this.triggerRollAdvice,\n 45\n );\n\n const subWatch = (rotation: number, a: typeof pitchAxis) => html`\n <obc-watch\n class=\"sub-watch\"\n style=\"transform: rotate(${rotation}deg); clip-path: ${a.clipPath};\"\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${true}\n .arcFrame=${a.arcFrame}\n .areas=${a.areas}\n .barAreas=${a.barAreas}\n .needles=${a.needles}\n .vessels=${[]}\n .tickmarks=${a.tickmarks}\n .advices=${a.advices}\n ></obc-watch>\n `;\n\n return html`\n ${subWatch(90, pitchAxis)} ${subWatch(180, rollAxis)}\n ${this.isDualScale\n ? html`${subWatch(270, pitchAxis)} ${subWatch(0, rollAxis)}`\n : nothing}\n `;\n }\n\n /** Caution bands for one sub-watch axis, at sub-watch-local angles. */\n private subAdvices(\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ): AngleAdviceRaw[] {\n if (max === undefined) return [];\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n return [\n {\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n },\n {\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n },\n ];\n }\n\n /** Areas, tickmarks, bars and needles for the un-zoomed single watch. */\n private renderFullWatch(pitchDeg: number, rollDeg: number) {\n const arc = (center: number, half: number): WatchArea => ({\n startAngle: center - half,\n endAngle: center + half,\n roundOutsideCut: true,\n roundInsideCut: true,\n });\n\n const areas: WatchArea[] = [arc(90, pitchDeg), arc(180, rollDeg)];\n const tickmarks: Tickmark[] = [\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n ...arcTickmarks(90, pitchDeg),\n ...arcTickmarks(180, rollDeg),\n ];\n const barAreas = [\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n },\n ];\n const needles = [\n {\n angle: 90 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 180 + this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n\n if (this.isDualScale) {\n areas.push(arc(270, pitchDeg), arc(0, rollDeg));\n tickmarks.push(\n {angle: 270, type: TickmarkType.main},\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(270, pitchDeg),\n ...arcTickmarks(0, rollDeg)\n );\n barAreas.push(\n {\n startAngle: 270 + this.minAvgPitch,\n endAngle: 270 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n }\n );\n needles.push(\n {\n angle: 270 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n }\n );\n }\n\n return html`\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${false}\n .areas=${areas}\n .barAreas=${barAreas}\n .needles=${needles}\n .vessels=${this.isDualScale || this.showsReadout\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${tickmarks}\n .advices=${this.advices(pitchDeg, rollDeg)}\n ></obc-watch>\n `;\n }\n\n private advices(pitchDeg: number, rollDeg: number): AngleAdviceRaw[] {\n const advices: AngleAdviceRaw[] = [];\n const push = (\n center: number,\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => {\n if (max === undefined) return;\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n advices.push({\n minAngle: center - outer,\n maxAngle: center - inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: center + inner,\n maxAngle: center + outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n });\n };\n push(90, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(180, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n if (this.isDualScale) {\n push(270, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(0, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n }\n return advices;\n }\n\n static override styles = [\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .readout {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pitch-roll-heave': ObcPitchRollHeave;\n }\n}\n"],"names":["ObcPitchRollHeaveType","PitchRollHeavePriorityElement"],"mappings":"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"}
1
+ {"version":3,"file":"pitch-roll-heave.js","sources":["../../../src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg, type SVGTemplateResult} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n type WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {arcTickmarks, TickmarkType, type Tickmark} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, type AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport {\n CenterReadoutArrangement,\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n} from '../../svghelpers/arc-frame.js';\nimport {\n linearTickInterval,\n watchfaceLinear,\n} from '../../building-blocks/instrument-linear/instrument-linear.js';\nimport type {\n LinearAdvice,\n LinearAdviceRaw,\n} from '../../building-blocks/instrument-linear/advice.js';\n\nexport enum ObcPitchRollHeaveType {\n /** Pitch on the right, roll at the bottom, heave in the left band slot. */\n singleScale = 'single-scale',\n /** Pitch and roll mirrored onto both sides, heave centred. */\n dualScale = 'dual-scale',\n}\n\nexport enum PitchRollHeavePriorityElement {\n pitch = 'pitch',\n roll = 'roll',\n heave = 'heave',\n}\n\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n/**\n * Minimum diagonal clearance, in central-layer pixels, between the zoomed\n * heave column and the adjacent roll band. Matches the constant\n * `obc-pitch-roll` uses between its own adjacent arcs.\n */\nconst CORNER_GAP_PX = 32;\n\n/** Numerical safety floor when an axis arc has to collapse for clearance. */\nconst MIN_ARC_HALF_DEG = 2;\n\n/** Width of the tick lane inside the heave column, in SVG units. */\nconst HEAVE_SCALE_WIDTH = 24;\n\n/** Band thickness at the natural, un-zoomed radii. */\nconst NOMINAL_BAND =\n OUTER_RING_RADIUS - innerRingRadiusFor(WatchCircleType.double);\n\n/**\n * Clearance kept between the centred (`dual-scale`) heave column's corners and\n * the surrounding band, in central-layer pixels. Sized so the un-zoomed\n * default is untouched — there the corner sits 13.2 units inside the free\n * radius — while the tighter zoomed layout is pulled back off the bands.\n */\nconst HEAVE_CENTRE_GAP_PX = 10;\n\n/**\n * The band slot the heave column fills, in central-layer coordinates.\n *\n * `outerR`/`innerR` bound the slot radially; `capRadius` is the radius of the\n * pitch arc's outer edge about its own origin, which is what the column's\n * height is measured against so the two line up. Un-zoomed the two radii\n * coincide; under zoom the arc is drawn on a shifted sub-watch and they differ.\n */\ninterface HeaveBand {\n outerR: number;\n innerR: number;\n capRadius: number;\n pitchDeg: number;\n}\n\n/**\n * Natural size of the heave column: as thick as the band slot, and tall enough\n * that its top and bottom edges sit level with the pitch arc's end caps.\n */\nfunction heaveColumnSize(band: HeaveBand): {width: number; height: number} {\n return {\n width: band.outerR - band.innerR,\n height: 2 * band.capRadius * Math.sin((band.pitchDeg * Math.PI) / 180),\n };\n}\n\n/**\n * Distance from a point to an axis-aligned rectangle; 0 when the point is\n * inside. Used to keep the zoomed roll band clear of the heave column, which\n * — unlike the arc-to-arc case — is a rectangle, so a corner may clear it on\n * one axis alone.\n */\nfunction distanceToRect(\n px: number,\n py: number,\n x0: number,\n y0: number,\n x1: number,\n y1: number\n): number {\n const dx = Math.max(0, x0 - px, px - x1);\n const dy = Math.max(0, y0 - py, py - y1);\n return Math.hypot(dx, dy);\n}\n\n/**\n * `<obc-pitch-roll-heave>` — Combined pitch, roll and heave indicator.\n *\n * Places a pitch arc, a roll arc and a linear heave column around one watch\n * face. The heave column occupies the same radial slot as the arcs, and its\n * height is derived from the pitch arc so its top and bottom edges sit level\n * with the pitch arc's end caps.\n *\n * Variants (`type`):\n * - `single-scale` (default) — pitch on the right, roll at the bottom, heave in\n * the left slot, vessel silhouettes in the centre.\n * - `dual-scale` — pitch and roll mirrored onto the opposite sides, with the\n * heave column moved to the centre.\n *\n * Set `hasReadout` to replace the centre content with stacked pitch, roll and\n * heave readouts, and `zoomToFitArc` to enlarge narrow arcs so they fill the\n * available space.\n *\n * @element obc-pitch-roll-heave\n * @experimental\n */\n@customElement('obc-pitch-roll-heave')\nexport class ObcPitchRollHeave extends LitElement {\n @property({type: String}) type: ObcPitchRollHeaveType =\n ObcPitchRollHeaveType.singleScale;\n\n @property({type: Number}) pitch = 0;\n @property({type: Number}) roll = 0;\n @property({type: Number}) heave = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: Number}) minTrendHeave = 0;\n @property({type: Number}) maxTrendHeave = 0;\n /** Half-extent of the heave scale in metres; the column spans `±heaveRange`. */\n @property({type: Number}) heaveRange = 10;\n\n /**\n * Half-extent of the pitch arc in degrees. Also drives the heave column\n * height, which is `2 · outerRadius · sin(pitchArcAngle)` so the column's\n * edges stay level with the pitch arc's end caps.\n */\n @property({type: Number}) pitchArcAngle = 30;\n /** Half-extent of the roll arc in degrees. */\n @property({type: Number}) rollArcAngle = 45;\n @property({type: Boolean}) zoomToFitArc = false;\n\n /**\n * Replaces the centre content with stacked pitch, roll and heave readouts.\n * Ignored when `type` is `dual-scale`, where the heave column occupies the\n * centre.\n * @availableWhen type==singleScale\n */\n @property({type: Boolean}) hasReadout = false;\n /** @availableWhen hasReadout==true */\n @property({type: String}) pitchLabel = 'Pitch';\n /** @availableWhen hasReadout==true */\n @property({type: String}) rollLabel = 'Roll';\n /** @availableWhen hasReadout==true */\n @property({type: String}) heaveLabel = 'Heave';\n /**\n * Unit shown in the pitch and roll readouts.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG';\n /**\n * Unit shown in the heave readout.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) heaveUnit = 'm';\n /** @availableWhen hasReadout==true */\n @property({type: Number}) fractionDigits = 0;\n\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n /** @availableWhen type==singleScale && hasReadout==false */\n @property({type: Number}) scaleForeImage = 1;\n\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n /** @availableWhen maxPitchAdvice!=undefined */\n @property({type: Boolean}) triggerPitchAdvice = false;\n /** @availableWhen maxRollAdvice!=undefined */\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: Array}) heaveAdvice: LinearAdvice[] = [];\n\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: PitchRollHeavePriorityElement[] = [\n PitchRollHeavePriorityElement.pitch,\n PitchRollHeavePriorityElement.roll,\n PitchRollHeavePriorityElement.heave,\n ];\n\n private priorityFor(element: PitchRollHeavePriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private needleColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private barColor(element: PitchRollHeavePriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n private get isDualScale(): boolean {\n return this.type === ObcPitchRollHeaveType.dualScale;\n }\n\n /** The centre readouts replace the vessels; never available in dual scale. */\n private get showsReadout(): boolean {\n return this.hasReadout && !this.isDualScale;\n }\n\n /**\n * Pitch half-extent, capped so a roll arc of the minimum size still fits in\n * the remaining quadrant.\n */\n private get requestedPitchArcAngle(): number {\n return Math.min(\n 90 - MIN_ARC_HALF_DEG,\n normalizeArcAngle(this.pitchArcAngle, 30)\n );\n }\n\n /**\n * Roll half-extent, clamped so the pitch and roll arcs cannot meet: the two\n * diagonal gaps each span `90 - pitch - roll` degrees, so the pair has to\n * stay under 90° combined.\n */\n private get requestedRollArcAngle(): number {\n const roll = normalizeArcAngle(this.rollArcAngle, 45);\n const headroom = 90 - this.requestedPitchArcAngle;\n return Math.max(MIN_ARC_HALF_DEG, Math.min(roll, headroom));\n }\n\n override render() {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const overlayViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n\n const layout = this.zoomToFitArc\n ? this.zoomLayout(pitchReq, rollReq)\n : undefined;\n const band: HeaveBand = layout?.band ?? {\n outerR: OUTER_RING_RADIUS,\n innerR: innerRingRadiusFor(WatchCircleType.double),\n capRadius: OUTER_RING_RADIUS,\n pitchDeg: pitchReq,\n };\n\n return html`\n <div class=\"container\">\n <svg viewBox=${overlayViewBox}>\n ${this.showsReadout ? nothing : this.renderCrosshair()}\n ${this.renderOverlayVessels()}\n ${this.zoomToFitArc || this.isDualScale\n ? nothing\n : this.renderComplement(pitchReq)}\n ${this.renderHeaveColumn(band)}\n </svg>\n ${layout\n ? this.renderZoomedArcs(layout)\n : this.renderFullWatch(pitchReq, rollReq)}\n ${this.showsReadout\n ? html`<div class=\"readout\">\n ${renderCenterReadouts(\n [\n {\n value: this.pitch,\n label: this.pitchLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.pitch\n ),\n },\n {\n value: this.roll,\n label: this.rollLabel,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.roll\n ),\n },\n {\n value: this.heave,\n label: this.heaveLabel,\n unit: this.heaveUnit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priorityFor(\n PitchRollHeavePriorityElement.heave\n ),\n },\n ],\n CenterReadoutArrangement.stacked\n )}\n </div>`\n : nothing}\n </div>\n `;\n }\n\n /**\n * Crosshair drawn on the overlay rather than through `obc-watch`'s own\n * `crosshairEnabled`: the design has the arc bands covering the arms, but\n * `obc-watch` renders its crosshair after the bands, i.e. on top of them.\n * Drawing it here puts it under the watch layer, so the bands and the heave\n * column mask it naturally.\n *\n * In `single-scale` nothing frames the segment above the vessel (the other\n * three arms end under the pitch band, roll band and heave column), so the\n * vertical arm stops at the centre instead of continuing upward. In\n * `dual-scale` the top roll band gives it a natural endpoint, so the full\n * arm is kept.\n */\n private renderCrosshair(): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n const yTop = this.isDualScale ? -r : 0;\n return svg`\n <line\n x1=${-r} y1=\"0\" x2=${r} y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n <line\n x1=\"0\" y1=${yTop} x2=\"0\" y2=${r}\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Vessel silhouettes on the centre layer. Only needed under zoom — the\n * un-zoomed path hands them to `obc-watch` via `vessels`, while the zoomed\n * sub-watches have no room for them.\n */\n private renderOverlayVessels(): SVGTemplateResult | typeof nothing {\n if (!this.zoomToFitArc || this.isDualScale || this.showsReadout) {\n return nothing;\n }\n const vesselScale = 224 / 160;\n return svg`\n <g style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageSide]}\n </g>\n <g style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\">\n ${vesselImages[this.vesselImageFore]}\n </g>\n `;\n }\n\n /**\n * Thin ring bridging the empty span across the top, from where the heave\n * column's upper edge crosses the outer ring round to the pitch arc's start.\n * Because the column height is derived from the pitch arc, both ends land at\n * `±pitchArcAngle` off the vertical, making the ring symmetric. The two\n * diagonal gaps lower down are left open by design.\n */\n private renderComplement(pitchDeg: number): SVGTemplateResult {\n const r = OUTER_RING_RADIUS;\n const rad = (pitchDeg * Math.PI) / 180;\n // Ring runs clockwise from (270 + pitchDeg) through 0 to (90 - pitchDeg).\n const x1 = -r * Math.cos(rad);\n const y1 = -r * Math.sin(rad);\n const x2 = r * Math.cos(rad);\n const y2 = -r * Math.sin(rad);\n return svg`\n <path\n d=\"M ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n vector-effect=\"non-scaling-stroke\"\n />\n `;\n }\n\n /**\n * Linear heave scale, built from the same building block `obc-heave` uses.\n *\n * The column fills the band's radial slot, so its width equals the band\n * thickness and its height keeps its top and bottom edges level with the\n * pitch arc's end caps. In `single-scale` it sits in the left slot and is\n * mirrored so the tick lane faces outward; in `dual-scale` it moves to the\n * centre, unmirrored, and shrinks if the zoomed bands leave too little room.\n */\n private renderHeaveColumn(band: HeaveBand): SVGTemplateResult {\n const {width, height: naturalHeight} = heaveColumnSize(band);\n let height = naturalHeight;\n let offsetX = -(band.outerR + band.innerR) / 2;\n\n if (this.isDualScale) {\n offsetX = 0;\n // The centred column has to stay inside whatever the bands leave free.\n // Only the height gives way: the column's thickness reads as a match for\n // the band thickness, and shrinking both would break that.\n const free = band.innerR - HEAVE_CENTRE_GAP_PX;\n const halfWidth = width / 2;\n const maxHalfHeight =\n free > halfWidth ? Math.sqrt(free * free - halfWidth * halfWidth) : 0;\n height = Math.min(height, 2 * maxHalfHeight);\n }\n\n const scaleWidth = HEAVE_SCALE_WIDTH * Math.min(1, width / NOMINAL_BAND);\n\n const gauge = watchfaceLinear(\n {\n height,\n width,\n scaleWidth,\n minValue: -this.heaveRange,\n maxValue: this.heaveRange,\n },\n [{min: this.minTrendHeave, max: this.maxTrendHeave}],\n {value: this.heave},\n {container: 'var(--instrument-frame-primary-color)'},\n {\n hideContainer: false,\n off: false,\n priority: this.priorityFor(PitchRollHeavePriorityElement.heave),\n },\n {\n mainTickmarks: [],\n primaryTickmarkInterval: 0,\n secondaryTickmarkInterval: linearTickInterval(height, this.heaveRange),\n },\n this.heaveAdvices\n );\n\n const mirror = this.isDualScale ? '' : ' scale(-1, 1)';\n return svg`<g transform=\"translate(${offsetX}, 0)${mirror}\">${gauge}</g>`;\n }\n\n private get heaveAdvices(): LinearAdviceRaw[] {\n return this.heaveAdvice.map((advice) => {\n const isActive =\n this.maxTrendHeave >= advice.min && this.minTrendHeave <= advice.max;\n const state = isActive\n ? AdviceState.triggered\n : advice.hinted\n ? AdviceState.hinted\n : AdviceState.regular;\n return {...advice, state} satisfies LinearAdviceRaw;\n });\n }\n\n /**\n * Zoom-fit geometry, computed once per render and shared by the arc layer\n * and the heave column.\n *\n * Frames are built at the REQUESTED half-extents with the same math as\n * `obc-pitch` / `obc-roll`, so each sub-watch matches its standalone\n * equivalent. Two clearance passes then shorten only the *rendered* arcs —\n * the frames stay untouched, so band thickness, position and zoom level are\n * preserved:\n *\n * 1. pitch vs roll at the diagonal, ratio-preserving, exactly as\n * `obc-pitch-roll` does it;\n * 2. roll vs the heave column, `single-scale` only, shortening the roll arc\n * alone. Because the column's height follows the pitch arc, pass 1 already\n * pulls the column in whenever pitch shrinks, so pitch needs no second\n * pass.\n */\n private zoomLayout(pitchReq: number, rollReq: number) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const innerNat = innerRingRadiusFor(WatchCircleType.double);\n const buildFrame = (halfDeg: number) => {\n const areas: WatchArea[] = [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerNat,\n extension: ext,\n targetSize,\n });\n const subArcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n const scale = (CENTRE_HALF * 2) / subArcFrame.width;\n const outerR = (OUTER_RING_RADIUS + baseFrame.radiusOffset) * scale;\n const innerR = (innerNat + baseFrame.radiusOffset) * scale;\n return {subArcFrame, outerR, innerR};\n };\n const pitchFrame = buildFrame(pitchReq);\n const rollFrame = buildFrame(rollReq);\n\n const OR = OUTER_RING_RADIUS;\n const toRad = (deg: number) => (deg * Math.PI) / 180;\n const signedDist = (\n px: number,\n py: number,\n qx: number,\n qy: number\n ): number => {\n const dx = qx - px;\n const dy = qy - py;\n const mag = Math.hypot(dx, dy);\n return dx > 0 && dy > 0 ? mag : -mag;\n };\n // Diagonal gap between two adjacent cardinal bands. All such gaps in this\n // layout are congruent, so one pair stands in for the rest.\n const minGap = (apRad: number, arRad: number): number => {\n const cosP = Math.cos(apRad);\n const sinP = Math.sin(apRad);\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const p1x = pitchFrame.innerR * sinP;\n const p1y = pitchFrame.outerR - OR - pitchFrame.innerR * cosP;\n const p2x = pitchFrame.outerR * sinP;\n const p2y = pitchFrame.outerR - OR - pitchFrame.outerR * cosP;\n const q1x = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n const q1y = -rollFrame.innerR * sinR;\n const q2x = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const q2y = -rollFrame.outerR * sinR;\n return Math.min(\n signedDist(p1x, p1y, q1x, q1y),\n signedDist(p2x, p2y, q2x, q2y)\n );\n };\n\n let aP = toRad(pitchReq);\n let aR = toRad(rollReq);\n if (minGap(aP, aR) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (minGap(aP * mid, aR * mid) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n aP *= lo;\n aR *= lo;\n }\n const pitchClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aP * 180) / Math.PI);\n let rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aR * 180) / Math.PI);\n\n const bandFor = (pitchDeg: number): HeaveBand => ({\n outerR: OR,\n innerR: OR - (pitchFrame.outerR - pitchFrame.innerR),\n capRadius: pitchFrame.outerR,\n pitchDeg,\n });\n\n if (!this.isDualScale) {\n // Roll's left end caps versus the heave column rectangle. Shrinking the\n // roll arc moves both caps toward the bottom cardinal, away from the\n // column, so the gap grows monotonically as the scalar shrinks.\n const band = bandFor(pitchClampedDeg);\n const {width, height} = heaveColumnSize(band);\n const x1 = -band.innerR;\n const x0 = x1 - width;\n const y1 = height / 2;\n const heaveGap = (arRad: number): number => {\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n const outerX = -rollFrame.outerR * sinR;\n const outerY = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const innerX = -rollFrame.innerR * sinR;\n const innerY = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n return Math.min(\n distanceToRect(outerX, outerY, x0, -y1, x1, y1),\n distanceToRect(innerX, innerY, x0, -y1, x1, y1)\n );\n };\n if (heaveGap(toRad(rollClampedDeg)) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = rollClampedDeg;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (heaveGap(toRad(mid)) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, lo);\n }\n }\n\n return {\n pitchFrame,\n rollFrame,\n pitchClampedDeg,\n rollClampedDeg,\n band: bandFor(pitchClampedDeg),\n };\n }\n\n /**\n * Zoomed-arc layer: CSS-rotated `<obc-watch>` instances, each holding a\n * single arc rendered at the watch's natural top and rotated onto its\n * cardinal. `single-scale` places pitch right and roll bottom; `dual-scale`\n * mirrors both. The heave column lives on the centre overlay.\n */\n private renderZoomedArcs(layout: ReturnType<typeof this.zoomLayout>) {\n const {pitchFrame, rollFrame, pitchClampedDeg, rollClampedDeg} = layout;\n\n const subAreas = (halfDeg: number): WatchArea[] => [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n // Clip each sub-watch to the sector its (possibly shortened) arc covers so\n // the indicator cannot leak past the visible band.\n const sectorClip = (\n halfDeg: number,\n frame: typeof rollFrame.subArcFrame\n ): string => {\n const oxPct = (-frame.x / frame.width) * 100;\n const oyPct = (-frame.y / frame.height) * 100;\n const dxPct = oyPct * Math.tan((halfDeg * Math.PI) / 180);\n const lx = Math.max(0, oxPct - dxPct);\n const rx = Math.min(100, oxPct + dxPct);\n return `polygon(${oxPct}% ${oyPct}%, ${lx}% 0%, ${rx}% 0%)`;\n };\n\n const axis = (\n element: PitchRollHeavePriorityElement,\n frame: typeof rollFrame,\n halfDeg: number,\n value: number,\n avgMin: number,\n avgMax: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => ({\n arcFrame: frame.subArcFrame,\n areas: subAreas(halfDeg),\n barAreas: [\n {\n startAngle: avgMin,\n endAngle: avgMax,\n fillColor: this.barColor(element),\n },\n ],\n needles: [\n {\n angle: value,\n fillColor: this.needleColor(element),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ],\n advices: this.subAdvices(halfDeg, max, trigger, cap),\n tickmarks: [\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(0, halfDeg),\n ],\n clipPath: sectorClip(halfDeg, frame.subArcFrame),\n });\n\n const pitchAxis = axis(\n PitchRollHeavePriorityElement.pitch,\n pitchFrame,\n pitchClampedDeg,\n this.pitch,\n this.minAvgPitch,\n this.maxAvgPitch,\n this.maxPitchAdvice,\n this.triggerPitchAdvice,\n 30\n );\n const rollAxis = axis(\n PitchRollHeavePriorityElement.roll,\n rollFrame,\n rollClampedDeg,\n this.roll,\n this.minAvgRoll,\n this.maxAvgRoll,\n this.maxRollAdvice,\n this.triggerRollAdvice,\n 45\n );\n\n const subWatch = (rotation: number, a: typeof pitchAxis) => html`\n <obc-watch\n class=\"sub-watch\"\n style=\"transform: rotate(${rotation}deg); clip-path: ${a.clipPath};\"\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${true}\n .arcFrame=${a.arcFrame}\n .areas=${a.areas}\n .barAreas=${a.barAreas}\n .needles=${a.needles}\n .vessels=${[]}\n .tickmarks=${a.tickmarks}\n .advices=${a.advices}\n ></obc-watch>\n `;\n\n return html`\n ${subWatch(90, pitchAxis)} ${subWatch(180, rollAxis)}\n ${this.isDualScale\n ? html`${subWatch(270, pitchAxis)} ${subWatch(0, rollAxis)}`\n : nothing}\n `;\n }\n\n /** Caution bands for one sub-watch axis, at sub-watch-local angles. */\n private subAdvices(\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ): AngleAdviceRaw[] {\n if (max === undefined) return [];\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n return [\n {\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n },\n {\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n },\n ];\n }\n\n /** Areas, tickmarks, bars and needles for the un-zoomed single watch. */\n private renderFullWatch(pitchDeg: number, rollDeg: number) {\n const arc = (center: number, half: number): WatchArea => ({\n startAngle: center - half,\n endAngle: center + half,\n roundOutsideCut: true,\n roundInsideCut: true,\n });\n\n const areas: WatchArea[] = [arc(90, pitchDeg), arc(180, rollDeg)];\n const tickmarks: Tickmark[] = [\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n ...arcTickmarks(90, pitchDeg),\n ...arcTickmarks(180, rollDeg),\n ];\n const barAreas = [\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n },\n ];\n const needles = [\n {\n angle: 90 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 180 + this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n\n if (this.isDualScale) {\n areas.push(arc(270, pitchDeg), arc(0, rollDeg));\n tickmarks.push(\n {angle: 270, type: TickmarkType.main},\n {angle: 0, type: TickmarkType.main},\n ...arcTickmarks(270, pitchDeg),\n ...arcTickmarks(0, rollDeg)\n );\n barAreas.push(\n {\n startAngle: 270 + this.minAvgPitch,\n endAngle: 270 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollHeavePriorityElement.pitch),\n },\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollHeavePriorityElement.roll),\n }\n );\n needles.push(\n {\n angle: 270 + this.pitch,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollHeavePriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n }\n );\n }\n\n return html`\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${false}\n .areas=${areas}\n .barAreas=${barAreas}\n .needles=${needles}\n .vessels=${this.isDualScale || this.showsReadout\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${tickmarks}\n .advices=${this.advices(pitchDeg, rollDeg)}\n ></obc-watch>\n `;\n }\n\n private advices(pitchDeg: number, rollDeg: number): AngleAdviceRaw[] {\n const advices: AngleAdviceRaw[] = [];\n const push = (\n center: number,\n halfDeg: number,\n max: number | undefined,\n trigger: boolean,\n cap: number\n ) => {\n if (max === undefined) return;\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n advices.push({\n minAngle: center - outer,\n maxAngle: center - inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: center + inner,\n maxAngle: center + outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n });\n };\n push(90, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(180, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n if (this.isDualScale) {\n push(270, pitchDeg, this.maxPitchAdvice, this.triggerPitchAdvice, 30);\n push(0, rollDeg, this.maxRollAdvice, this.triggerRollAdvice, 45);\n }\n return advices;\n }\n\n static override styles = [\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .readout {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pitch-roll-heave': ObcPitchRollHeave;\n }\n}\n"],"names":["ObcPitchRollHeaveType","PitchRollHeavePriorityElement"],"mappings":"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"}
@@ -23,7 +23,8 @@ export { RotType, RotPosition };
23
23
  * - **Track bar** (`hasTrackBar`): A bar in the ring band growing from the
24
24
  * twelve o'clock position to the measured rate of turn, with a needle
25
25
  * marker at its end and sector tickmarks (pairs with
26
- * `watchCircleType="double"` for the banded face).
26
+ * `watchCircleType="double"` for the banded face, or `"triple"` when the
27
+ * ROT dots sit on the inner circle).
27
28
  * - **Center readout** (`hasReadout`): A centered readout showing the
28
29
  * measured rate of turn (label `ROT`, unit `DEG/min` by default).
29
30
  * - **Color priority**: Uses `priority` to select regular or enhanced color
@@ -74,7 +75,9 @@ export declare class ObcRateOfTurn extends LitElement {
74
75
  * When `true`, shows a bar in the ring band from the twelve o'clock
75
76
  * position to the measured rate of turn, with a needle marker at its end
76
77
  * and sector tickmarks. Pairs with `watchCircleType="double"` for the
77
- * banded face. Driven by `rateOfTurnDegreesPerMinute` only.
78
+ * banded face or `"triple"` when `rotPosition` is `innerCircle`, so the
79
+ * dots get their inner track too. Driven by `rateOfTurnDegreesPerMinute`
80
+ * only.
78
81
  */
79
82
  hasTrackBar: boolean;
80
83
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"rate-of-turn.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgC,MAAM,KAAK,CAAC;AAE9D,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAC,eAAe,EAAE,OAAO,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAUxE,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C;;;OAGG;IACuB,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzE;;;OAGG;IACuB,qBAAqB,EAAE,MAAM,CAAM;IAE7D;;;;OAIG;IACuB,kBAAkB,EAAE,MAAM,CAAK;IAE/B,OAAO,EAAE,OAAO,CAAgB;IAChC,WAAW,EAAE,WAAW,CAAqB;IAC7C,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,MAAM,CAAK;IAC1B,WAAW,EAAE,MAAM,CAAM;IACzB,eAAe,EAAE,eAAe,CACjC;IACE,gBAAgB,EAAE,OAAO,CAAS;IACnC,iBAAiB,EAAE,MAAM,CAAyB;IAC5E;;;;;OAKG;IACwB,WAAW,EAAE,OAAO,CAAS;IACxD;;;;;OAKG;IACuB,WAAW,EAAE,MAAM,CAAM;IACnD;;;OAGG;IACuB,YAAY,EAAE,MAAM,CAAM;IACpD;;;OAGG;IACwB,UAAU,EAAE,OAAO,CAAS;IACvD;;;OAGG;IACuB,KAAK,SAAS;IACxC;;;OAGG;IACuB,IAAI,SAAa;IAC3C;;;OAGG;IACuB,cAAc,SAAK;IAE7C,OAAO,KAAK,aAAa,GAKxB;IAED,OAAO,KAAK,aAAa,GAaxB;IAED,OAAO,KAAK,gBAAgB,GAc3B;IAED,OAAO,KAAK,cAAc,GAOzB;IAED,OAAgB,MAAM,4BA6BpB;IAEO,MAAM;CAoDhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,aAAa,CAAC;KACnC;CACF"}
1
+ {"version":3,"file":"rate-of-turn.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgC,MAAM,KAAK,CAAC;AAE9D,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAC,eAAe,EAAE,OAAO,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAUxE,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C;;;OAGG;IACuB,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzE;;;OAGG;IACuB,qBAAqB,EAAE,MAAM,CAAM;IAE7D;;;;OAIG;IACuB,kBAAkB,EAAE,MAAM,CAAK;IAE/B,OAAO,EAAE,OAAO,CAAgB;IAChC,WAAW,EAAE,WAAW,CAAqB;IAC7C,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,MAAM,CAAK;IAC1B,WAAW,EAAE,MAAM,CAAM;IACzB,eAAe,EAAE,eAAe,CACjC;IACE,gBAAgB,EAAE,OAAO,CAAS;IACnC,iBAAiB,EAAE,MAAM,CAAyB;IAC5E;;;;;;;OAOG;IACwB,WAAW,EAAE,OAAO,CAAS;IACxD;;;;;OAKG;IACuB,WAAW,EAAE,MAAM,CAAM;IACnD;;;OAGG;IACuB,YAAY,EAAE,MAAM,CAAM;IACpD;;;OAGG;IACwB,UAAU,EAAE,OAAO,CAAS;IACvD;;;OAGG;IACuB,KAAK,SAAS;IACxC;;;OAGG;IACuB,IAAI,SAAa;IAC3C;;;OAGG;IACuB,cAAc,SAAK;IAE7C,OAAO,KAAK,aAAa,GAKxB;IAED,OAAO,KAAK,aAAa,GAaxB;IAED,OAAO,KAAK,gBAAgB,GAc3B;IAED,OAAO,KAAK,cAAc,GAOzB;IAED,OAAgB,MAAM,4BA6BpB;IAEO,MAAM;CAoDhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,aAAa,CAAC;KACnC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"rate-of-turn.js","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"sourcesContent":["import {LitElement, css, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {WatchCircleType, RotType, RotPosition} from '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport instrumentReadoutStyle from '../readout/instrument-readout.css?inline';\nimport {ROT_ZERO_DEADBAND_DEG} from './rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\n\nexport {RotType, RotPosition};\n\n/**\n * `<obc-rate-of-turn>` — Standalone rate-of-turn indicator rendered on a circular watch face.\n *\n * Wraps `<obc-watch>` to display a spinning-dot or arc-bar ROT visualization\n * without any additional instrument overlays. Useful for isolating the ROT\n * indicator in layouts where heading/compass elements are handled separately.\n *\n * ## Features\n *\n * - **Dot mode** (`rotType=\"dots\"`): Five evenly-spaced dots spin at the\n * resolved rotations-per-minute (derived from\n * `rateOfTurnDegreesPerMinute × rotDotAnimationFactor / 360`).\n * - **Bar mode** (`rotType=\"bar\"`): A banana-shaped arc from `barStartAngle`\n * to `barEndAngle` with clipped spinning dots inside.\n * - **Track position**: Place the indicator on the outer scale ring\n * (`rotPosition=\"scale\"`) or the inner circle\n * (`rotPosition=\"innerCircle\"`).\n * - **Track bar** (`hasTrackBar`): A bar in the ring band growing from the\n * twelve o'clock position to the measured rate of turn, with a needle\n * marker at its end and sector tickmarks (pairs with\n * `watchCircleType=\"double\"` for the banded face).\n * - **Center readout** (`hasReadout`): A centered readout showing the\n * measured rate of turn (label `ROT`, unit `DEG/min` by default).\n * - **Color priority**: Uses `priority` to select regular or enhanced color\n * palette; `rotPortStarboard` colors the track bar and needle by turn\n * direction.\n *\n * ## Usage Guidelines\n *\n * - Set `rateOfTurnDegreesPerMinute` to the current sensor value in degrees\n * per minute (the maritime/AIS convention). Sign controls direction\n * (positive = starboard / clockwise).\n * - Tune `rotDotAnimationFactor` to amplify the dot animation independently\n * of the physical value (default `18` ≈ 1 rpm at 20°/min).\n * - In bar mode, `barStartAngle` and `barEndAngle` define the static arc\n * span (0° = 12 o'clock, clockwise).\n * - Change `watchCircleType` to match the surrounding instrument ring style\n * (e.g. `triple` for compass contexts).\n *\n * @element obc-rate-of-turn\n * @stable\n */\n@customElement('obc-rate-of-turn')\nexport class ObcRateOfTurn extends LitElement {\n /**\n * Measured rate of turn in degrees per minute (positive = starboard).\n * When `undefined`, the legacy `rotationsPerMinute` value is used.\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n\n /**\n * Visual amplification applied to the spinning dot animation. Default `18`\n * keeps the legacy visual feel (≈1 rpm at 20°/min).\n */\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n\n /**\n * @deprecated Use `rateOfTurnDegreesPerMinute` (and optionally\n * `rotDotAnimationFactor`) instead. Takes effect only when\n * `rateOfTurnDegreesPerMinute` is `undefined`.\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n\n @property({type: String}) rotType: RotType = RotType.dots;\n @property({type: String}) rotPosition: RotPosition = RotPosition.scale;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Number}) barStartAngle: number = 0;\n @property({type: Number}) barEndAngle: number = 30;\n @property({type: String}) watchCircleType: WatchCircleType =\n WatchCircleType.single;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n /**\n * When `true`, shows a bar in the ring band from the twelve o'clock\n * position to the measured rate of turn, with a needle marker at its end\n * and sector tickmarks. Pairs with `watchCircleType=\"double\"` for the\n * banded face. Driven by `rateOfTurnDegreesPerMinute` only.\n */\n @property({type: Boolean}) hasTrackBar: boolean = false;\n /**\n * Bar-extent reference value in **degrees per minute**: the track bar\n * reaches ±`rotArcExtent` when the measured ROT equals ±`rotMaxValue`.\n * Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /**\n * Arc extent of the track bar in degrees per direction. Default `60`.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotArcExtent: number = 60;\n /**\n * When `true`, shows a centered `<obc-readout>` with the measured rate of\n * turn. Shows a dash while `rateOfTurnDegreesPerMinute` is unset.\n */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * Readout label. Default `ROT`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) label = 'ROT';\n /**\n * Readout unit. Default `DEG/min`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG/min';\n /**\n * Number of fraction digits shown in the readout. Default `0`.\n * @availableWhen hasReadout==true\n */\n @property({type: Number}) fractionDigits = 0;\n\n private get trackBarAngle(): number {\n const max = this.rotMaxValue || 1;\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n const ratio = Math.max(-1, Math.min(1, rot / max));\n return ratio * this.rotArcExtent;\n }\n\n private get trackBarColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-secondary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-secondary-color)';\n }\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get trackNeedleColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-primary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-primary-color)';\n }\n return 'var(--instrument-regular-secondary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get trackTickmarks(): Tickmark[] {\n const ticks: Tickmark[] = [{angle: 0, type: TickmarkType.main}];\n for (let angle = 30; angle <= this.rotArcExtent; angle += 30) {\n ticks.push({angle, type: TickmarkType.primary});\n ticks.push({angle: -angle, type: TickmarkType.primary});\n }\n return ticks;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .center-readout-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n }\n `,\n ];\n\n override render() {\n return html`<div class=\"container\">\n <obc-watch\n .watchCircleType=${this.watchCircleType}\n .priority=${this.priority}\n .tickmarks=${this.hasTrackBar ? this.trackTickmarks : []}\n .barAreas=${this.hasTrackBar\n ? [\n {\n startAngle: 0,\n endAngle: this.trackBarAngle,\n fillColor: this.trackBarColor,\n },\n ]\n : []}\n .needles=${this.hasTrackBar\n ? [\n {\n angle: this.trackBarAngle,\n fillColor: this.trackNeedleColor,\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]\n : []}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.barStartAngle}\n .rotEndAngle=${this.barEndAngle}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband}\n ></obc-watch>\n ${this.hasReadout\n ? html`<div class=\"center-readout-overlay\">\n ${renderCenterReadouts([\n {\n value: this.rateOfTurnDegreesPerMinute ?? null,\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priority,\n centerValue: true,\n centerMeta: true,\n },\n ])}\n </div>`\n : nothing}\n </div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rate-of-turn': ObcRateOfTurn;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rate-of-turn.js","sources":["../../../src/navigation-instruments/rate-of-turn/rate-of-turn.ts"],"sourcesContent":["import {LitElement, css, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {WatchCircleType, RotType, RotPosition} from '../watch/watch.js';\nimport {Tickmark, TickmarkType} from '../watch/tickmark.js';\nimport {\n centerReadoutStyles,\n renderCenterReadouts,\n} from '../readout/center-readout.js';\nimport {ReadoutSize} from '../readout/readout.js';\nimport instrumentReadoutStyle from '../readout/instrument-readout.css?inline';\nimport {ROT_ZERO_DEADBAND_DEG} from './rot-renderer.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\n\nexport {RotType, RotPosition};\n\n/**\n * `<obc-rate-of-turn>` — Standalone rate-of-turn indicator rendered on a circular watch face.\n *\n * Wraps `<obc-watch>` to display a spinning-dot or arc-bar ROT visualization\n * without any additional instrument overlays. Useful for isolating the ROT\n * indicator in layouts where heading/compass elements are handled separately.\n *\n * ## Features\n *\n * - **Dot mode** (`rotType=\"dots\"`): Five evenly-spaced dots spin at the\n * resolved rotations-per-minute (derived from\n * `rateOfTurnDegreesPerMinute × rotDotAnimationFactor / 360`).\n * - **Bar mode** (`rotType=\"bar\"`): A banana-shaped arc from `barStartAngle`\n * to `barEndAngle` with clipped spinning dots inside.\n * - **Track position**: Place the indicator on the outer scale ring\n * (`rotPosition=\"scale\"`) or the inner circle\n * (`rotPosition=\"innerCircle\"`).\n * - **Track bar** (`hasTrackBar`): A bar in the ring band growing from the\n * twelve o'clock position to the measured rate of turn, with a needle\n * marker at its end and sector tickmarks (pairs with\n * `watchCircleType=\"double\"` for the banded face, or `\"triple\"` when the\n * ROT dots sit on the inner circle).\n * - **Center readout** (`hasReadout`): A centered readout showing the\n * measured rate of turn (label `ROT`, unit `DEG/min` by default).\n * - **Color priority**: Uses `priority` to select regular or enhanced color\n * palette; `rotPortStarboard` colors the track bar and needle by turn\n * direction.\n *\n * ## Usage Guidelines\n *\n * - Set `rateOfTurnDegreesPerMinute` to the current sensor value in degrees\n * per minute (the maritime/AIS convention). Sign controls direction\n * (positive = starboard / clockwise).\n * - Tune `rotDotAnimationFactor` to amplify the dot animation independently\n * of the physical value (default `18` ≈ 1 rpm at 20°/min).\n * - In bar mode, `barStartAngle` and `barEndAngle` define the static arc\n * span (0° = 12 o'clock, clockwise).\n * - Change `watchCircleType` to match the surrounding instrument ring style\n * (e.g. `triple` for compass contexts).\n *\n * @element obc-rate-of-turn\n * @stable\n */\n@customElement('obc-rate-of-turn')\nexport class ObcRateOfTurn extends LitElement {\n /**\n * Measured rate of turn in degrees per minute (positive = starboard).\n * When `undefined`, the legacy `rotationsPerMinute` value is used.\n */\n @property({type: Number}) rateOfTurnDegreesPerMinute: number | undefined;\n\n /**\n * Visual amplification applied to the spinning dot animation. Default `18`\n * keeps the legacy visual feel (≈1 rpm at 20°/min).\n */\n @property({type: Number}) rotDotAnimationFactor: number = 18;\n\n /**\n * @deprecated Use `rateOfTurnDegreesPerMinute` (and optionally\n * `rotDotAnimationFactor`) instead. Takes effect only when\n * `rateOfTurnDegreesPerMinute` is `undefined`.\n */\n @property({type: Number}) rotationsPerMinute: number = 1;\n\n @property({type: String}) rotType: RotType = RotType.dots;\n @property({type: String}) rotPosition: RotPosition = RotPosition.scale;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Number}) barStartAngle: number = 0;\n @property({type: Number}) barEndAngle: number = 30;\n @property({type: String}) watchCircleType: WatchCircleType =\n WatchCircleType.single;\n @property({type: Boolean}) rotPortStarboard: boolean = false;\n @property({type: Number}) rotAtZeroDeadband: number = ROT_ZERO_DEADBAND_DEG;\n /**\n * When `true`, shows a bar in the ring band from the twelve o'clock\n * position to the measured rate of turn, with a needle marker at its end\n * and sector tickmarks. Pairs with `watchCircleType=\"double\"` for the\n * banded face — or `\"triple\"` when `rotPosition` is `innerCircle`, so the\n * dots get their inner track too. Driven by `rateOfTurnDegreesPerMinute`\n * only.\n */\n @property({type: Boolean}) hasTrackBar: boolean = false;\n /**\n * Bar-extent reference value in **degrees per minute**: the track bar\n * reaches ±`rotArcExtent` when the measured ROT equals ±`rotMaxValue`.\n * Default `60` aligns with ES-TRIN 2025/1 Art. 3.02.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotMaxValue: number = 60;\n /**\n * Arc extent of the track bar in degrees per direction. Default `60`.\n * @availableWhen hasTrackBar==true\n */\n @property({type: Number}) rotArcExtent: number = 60;\n /**\n * When `true`, shows a centered `<obc-readout>` with the measured rate of\n * turn. Shows a dash while `rateOfTurnDegreesPerMinute` is unset.\n */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * Readout label. Default `ROT`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) label = 'ROT';\n /**\n * Readout unit. Default `DEG/min`.\n * @availableWhen hasReadout==true\n */\n @property({type: String}) unit = 'DEG/min';\n /**\n * Number of fraction digits shown in the readout. Default `0`.\n * @availableWhen hasReadout==true\n */\n @property({type: Number}) fractionDigits = 0;\n\n private get trackBarAngle(): number {\n const max = this.rotMaxValue || 1;\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n const ratio = Math.max(-1, Math.min(1, rot / max));\n return ratio * this.rotArcExtent;\n }\n\n private get trackBarColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-secondary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-secondary-color)';\n }\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get trackNeedleColor(): string {\n if (this.rotPortStarboard) {\n const rot = this.rateOfTurnDegreesPerMinute ?? 0;\n if (rot > 0) {\n return 'var(--instrument-starboard-primary-color)';\n }\n if (rot < 0) {\n return 'var(--instrument-port-primary-color)';\n }\n return 'var(--instrument-regular-secondary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get trackTickmarks(): Tickmark[] {\n const ticks: Tickmark[] = [{angle: 0, type: TickmarkType.main}];\n for (let angle = 30; angle <= this.rotArcExtent; angle += 30) {\n ticks.push({angle, type: TickmarkType.primary});\n ticks.push({angle: -angle, type: TickmarkType.primary});\n }\n return ticks;\n }\n\n static override styles = [\n unsafeCSS(instrumentReadoutStyle),\n centerReadoutStyles,\n css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n .center-readout-overlay {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n }\n `,\n ];\n\n override render() {\n return html`<div class=\"container\">\n <obc-watch\n .watchCircleType=${this.watchCircleType}\n .priority=${this.priority}\n .tickmarks=${this.hasTrackBar ? this.trackTickmarks : []}\n .barAreas=${this.hasTrackBar\n ? [\n {\n startAngle: 0,\n endAngle: this.trackBarAngle,\n fillColor: this.trackBarColor,\n },\n ]\n : []}\n .needles=${this.hasTrackBar\n ? [\n {\n angle: this.trackBarAngle,\n fillColor: this.trackNeedleColor,\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]\n : []}\n .rotType=${this.rotType}\n .rotPosition=${this.rotPosition}\n .rotStartAngle=${this.barStartAngle}\n .rotEndAngle=${this.barEndAngle}\n .rateOfTurnDegreesPerMinute=${this.rateOfTurnDegreesPerMinute}\n .rotDotAnimationFactor=${this.rotDotAnimationFactor}\n .rotationsPerMinute=${this.rotationsPerMinute}\n .rotPortStarboard=${this.rotPortStarboard}\n .rotAtZeroDeadband=${this.rotAtZeroDeadband}\n ></obc-watch>\n ${this.hasReadout\n ? html`<div class=\"center-readout-overlay\">\n ${renderCenterReadouts([\n {\n value: this.rateOfTurnDegreesPerMinute ?? null,\n label: this.label,\n unit: this.unit,\n fractionDigits: this.fractionDigits,\n size: ReadoutSize.large,\n priority: this.priority,\n centerValue: true,\n centerMeta: true,\n },\n ])}\n </div>`\n : nothing}\n </div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rate-of-turn': ObcRateOfTurn;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -139,6 +139,12 @@ export declare class ObcTopViewPropulsion extends LitElement {
139
139
  private get secondaryColor();
140
140
  private renderSecondaryArc;
141
141
  private renderLoadingArc;
142
+ /**
143
+ * Thin outline on the track band's inner edge, always shown per the
144
+ * design's track face. Drawn on the overlay because the watch paints its
145
+ * band bars over the ring circles, which would swallow a watch-side line.
146
+ */
147
+ private renderInnerRingLine;
142
148
  private renderPropeller;
143
149
  render(): import('lit-html').TemplateResult<1>;
144
150
  static styles: import('lit').CSSResult;
@@ -1 +1 @@
1
- {"version":3,"file":"top-view-propulsion.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"top-view-propulsion.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,8 @@ import { ResizeController } from "@lit-labs/observers/resize-controller.js";
4
4
  import { observeInnerBox, applyPinnedHostSize, computeRadialFrame, measureContainerPx, estimateLabelWidthPx } from "../../svghelpers/radial-frame.js";
5
5
  import { InstrumentState, Priority } from "../types.js";
6
6
  import { SetpointBundle } from "../../svghelpers/setpoint-bundle.js";
7
- import { OUTER_RING_RADIUS } from "../watch/watch.js";
8
- import { PRIMARY_SUBBAND_INNER_RADIUS, PRIMARY_SUBBAND_NEEDLE_LENGTH, LANE_DIVIDER_RADIUS, LANE_DIVIDER_WIDTH, renderSecondaryLine, arcPath } from "../watch/secondary-lane.js";
7
+ import { WatchCircleType, OUTER_RING_RADIUS } from "../watch/watch.js";
8
+ import { PRIMARY_SUBBAND_INNER_RADIUS, PRIMARY_SUBBAND_NEEDLE_LENGTH, LANE_DIVIDER_RADIUS, LANE_DIVIDER_WIDTH, renderSecondaryLine, arcPath, BAND_INNER_RADIUS } from "../watch/secondary-lane.js";
9
9
  import { TickmarkStyle, TickmarkType } from "../watch/tickmark.js";
10
10
  import { PropellerImage, propellerImages } from "../watch/propeller.js";
11
11
  import { customElement } from "../../decorator.js";
@@ -248,6 +248,20 @@ let ObcTopViewPropulsion = class extends LitElement {
248
248
  stroke-linecap="round"
249
249
  ></path>`;
250
250
  }
251
+ /**
252
+ * Thin outline on the track band's inner edge, always shown per the
253
+ * design's track face. Drawn on the overlay because the watch paints its
254
+ * band bars over the ring circles, which would swallow a watch-side line.
255
+ */
256
+ renderInnerRingLine() {
257
+ return svg`<circle
258
+ r=${BAND_INNER_RADIUS}
259
+ fill="none"
260
+ stroke="var(--instrument-frame-tertiary-color)"
261
+ stroke-width="1"
262
+ vector-effect="non-scaling-stroke"
263
+ ></circle>`;
264
+ }
251
265
  renderPropeller() {
252
266
  return svg`<g transform="scale(${PROPELLER_SCALE}) translate(-80 -80)">${propellerImages[this.propeller]}</g>`;
253
267
  }
@@ -268,6 +282,7 @@ let ObcTopViewPropulsion = class extends LitElement {
268
282
  <obc-watch
269
283
  .touching=${this.touching}
270
284
  .arcFrame=${frame}
285
+ .watchCircleType=${WatchCircleType.double}
271
286
  .tickmarks=${shownTickmarks}
272
287
  .state=${this.state}
273
288
  .priority=${this.priority}
@@ -285,8 +300,8 @@ let ObcTopViewPropulsion = class extends LitElement {
285
300
  .tickmarkStyle=${this.tickmarkStyle}
286
301
  ></obc-watch>
287
302
  <svg viewBox=${frame.viewBox} xmlns="http://www.w3.org/2000/svg">
288
- ${this.renderLoadingArc()} ${this.renderSecondaryArc()}
289
- ${this.renderPropeller()}
303
+ ${this.renderInnerRingLine()} ${this.renderLoadingArc()}
304
+ ${this.renderSecondaryArc()} ${this.renderPropeller()}
290
305
  </svg>
291
306
  </div>
292
307
  `;