added auto measuraments
This commit is contained in:
1 parent
44fc4cdf36
commit
0eceaf537b
7 files changed
+2182
-55
No files matched your search
+102
-5
@@ -48,9 +48,27 @@ class RowSet {
|
||||
/// about this many a row is chrome and no plot.
|
||||
static constexpr int kMaxRows = 8;
|
||||
static constexpr int kSlotsPerRow = 4;
|
||||
/// Readout marks per row per orientation: enough for a handful of level and time
|
||||
/// measurements to be shown at once, and a fixed number because a `Plot` fixes its cursor
|
||||
/// set at construction.
|
||||
static constexpr int kMeasureMarks = 6;
|
||||
|
||||
RowSet();
|
||||
|
||||
/// Which cursor instruments are up, from the toolbar's toggle. The two vertical
|
||||
/// markers are shared by every row (one stream time each, so they line up down the
|
||||
/// column); a horizontal ruler is per row, because each row has its own y axis.
|
||||
///
|
||||
/// `Mix` is the vertical pair with the *per-trace* readout instead of rulers: the
|
||||
/// pane then reports where each cursor crosses each trace, which is the value a
|
||||
/// ruler would have to be dragged to express.
|
||||
enum class CursorMode {
|
||||
Vertical, ///< two x markers, shared by all rows
|
||||
Horizontal, ///< two y rulers per row
|
||||
Both, ///< both instruments
|
||||
Mix, ///< the x pair, read off each trace
|
||||
};
|
||||
|
||||
struct Row {
|
||||
/// The figure's row, borrowed. Null for a row beyond `row_count()`, which is how
|
||||
/// every loop here and in the UI stays inside the rows that exist. Invalidated by
|
||||
@@ -82,16 +100,28 @@ class RowSet {
|
||||
plot::u32 cursor_a = 0;
|
||||
plot::u32 cursor_b = 0;
|
||||
plot::u32 ruler = 0;
|
||||
plot::u32 ruler_b = 0;
|
||||
/// The vertical line marking the trigger instant, drawn whenever an event is
|
||||
/// on screen (and parked outside the axis otherwise). Not the user's cursor:
|
||||
/// it keeps its position whatever the cursor toggle says.
|
||||
plot::u32 trigger_marker = 0;
|
||||
/// Off by default: the cursors are switched on from the toolbar, and a rebuild
|
||||
/// (any drop, any row-count change) must not switch them back off.
|
||||
bool cursors_visible = false;
|
||||
double cursor_a_x = 0.0;
|
||||
double cursor_b_x = 0.0;
|
||||
|
||||
/// The measurements' readout marks: a pool created with the plot (a `Plot` cannot add or
|
||||
/// drop a cursor after the fact) and parked unless a measurement is using the slot.
|
||||
std::array<plot::u32, kMeasureMarks> measure_h{};
|
||||
std::array<plot::u32, kMeasureMarks> measure_v{};
|
||||
|
||||
/// One marker per trace per cursor: where each vertical cursor crosses that trace's
|
||||
/// series, drawn only in `mix` mode. Two per slot because the pair crosses a trace
|
||||
/// at two places, and an annotation cannot be shared between them.
|
||||
std::array<plot::u32, kSlotsPerRow> crossing_a{};
|
||||
std::array<plot::u32, kSlotsPerRow> crossing_b{};
|
||||
|
||||
/// The two rulers' values. The vertical pair is *not* here: one stream time is
|
||||
/// shared by every row, so it lives on the `RowSet` where it cannot drift between
|
||||
/// rows.
|
||||
double ruler_y = 0.0;
|
||||
double ruler_b_y = 0.0;
|
||||
};
|
||||
|
||||
int row_count() const noexcept { return rows_; }
|
||||
@@ -152,6 +182,67 @@ class RowSet {
|
||||
void set_y_range(int row, double lo, double hi);
|
||||
|
||||
void set_cursors_visible(bool on);
|
||||
/// What the cursors are (see `CursorMode`). Switching parks the instruments the mode
|
||||
/// does not use rather than removing them: a `Plot` cannot drop a cursor.
|
||||
void set_cursor_mode(CursorMode mode);
|
||||
/// Places (or hides) the `mix` mode's crossing markers: for every plotted trace, the
|
||||
/// point where each cursor meets it. Called from `sync_cursors()` and when the mode
|
||||
/// changes, so the markers are never a frame behind the markers that cast them.
|
||||
void place_crossings();
|
||||
CursorMode cursor_mode() const noexcept { return cursor_mode_; }
|
||||
|
||||
/// The two vertical cursors' stream times; shared by every row.
|
||||
double cursor_a_x() const noexcept { return cursor_a_x_; }
|
||||
double cursor_b_x() const noexcept { return cursor_b_x_; }
|
||||
/// One row's ruler values, or 0 for a row that does not exist.
|
||||
double ruler_y(int row) const;
|
||||
double ruler_b_y(int row) const;
|
||||
/// How many `mix` crossing markers are on screen, and the first one's position: the
|
||||
/// probe's window onto "the marks follow the cursors".
|
||||
int crossings_visible() const;
|
||||
bool crossing_at(int row, int slot, bool second, double& x, double& y) const;
|
||||
|
||||
/// Whether the cursors are on. One flag for the whole set, not a copy per row: it is one
|
||||
/// piece of state (the toolbar's toggle), and a per-row copy is something a rebuild, an
|
||||
/// insert or a carried row can clear behind the user's back -- which is how a row could
|
||||
/// end up with its instruments parked while every other row showed them.
|
||||
bool cursors_visible() const noexcept { return cursors_on_; }
|
||||
|
||||
/// One measurement's readout mark on a row: a *level* (drawn as a horizontal ruler) or a
|
||||
/// *time* (a vertical marker). Which one a measurement needs is the measurement's own
|
||||
/// business; the row is the one that plots its signal.
|
||||
struct MeasureMark {
|
||||
int row = 0;
|
||||
bool level = false;
|
||||
double value = 0.0;
|
||||
plot::u32 color = 0;
|
||||
};
|
||||
|
||||
/// Places the measurements' marks and parks every pool slot they do not use. The marks are
|
||||
/// created unselectable (`Plot::set_cursor_selectable()`), so the pointer can neither hover
|
||||
/// nor drag them; this runs every frame because a mark is only correct for the window its
|
||||
/// measurement was computed over.
|
||||
void set_measure_marks(const std::vector<MeasureMark>& marks);
|
||||
/// How many marks the last `set_measure_marks()` placed: the probe's window onto "the
|
||||
/// measurement is drawn", as opposed to merely computed.
|
||||
int measure_marks_placed() const noexcept { return measure_marks_placed_; }
|
||||
|
||||
/// Frames the x window on the data row 0 holds, leaving every y axis alone. The x
|
||||
/// counterpart of `fit_all()`, for the one thing the y axes cannot say: how wide the
|
||||
/// window should be.
|
||||
void fit_x();
|
||||
|
||||
/// Adopts the instruments a gesture moved. The vertical pair is one time for the whole
|
||||
/// figure, so a drag on any row's marker moves every row's; a ruler belongs to its own
|
||||
/// row and is only read back. Either way the plot is where a drag writes, so this is the
|
||||
/// one place the app can see it -- and the pane reads what is stored here, which is why a
|
||||
/// ruler that was not read back showed a stale value while its marker on the plot moved.
|
||||
/// Called once a frame from the tick.
|
||||
void sync_cursors();
|
||||
|
||||
/// Puts both vertical cursors at a quarter and three quarters of the x window, and
|
||||
/// the two rulers at a third and two thirds of each row's y range. Also switches the
|
||||
/// cursors on, so the button cannot look dead.
|
||||
void reset_cursors();
|
||||
|
||||
/// Places the trigger marker at stream time `x` (seconds since the epoch), or
|
||||
@@ -237,6 +328,12 @@ class RowSet {
|
||||
double y_gutter_px_ = 0.0;
|
||||
bool y_gutter_reserved_ = false;
|
||||
std::array<Row, static_cast<std::size_t>(kMaxRows)> storage_{};
|
||||
CursorMode cursor_mode_ = CursorMode::Vertical;
|
||||
bool cursors_on_ = false;
|
||||
int measure_marks_placed_ = 0;
|
||||
/// The one stream time each vertical cursor is at, whatever row's copy was last moved.
|
||||
double cursor_a_x_ = 0.0;
|
||||
double cursor_b_x_ = 0.0;
|
||||
std::array<bool, static_cast<std::size_t>(kMaxRows)> row_dirty_{};
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user