Skip to content

Latest commit

 

History

History
603 lines (476 loc) · 16.8 KB

File metadata and controls

603 lines (476 loc) · 16.8 KB

PlotJuggler Plotting Library Requirements

This document describes the requirements for a custom plotting library to replace Qwt in PlotJuggler. The requirements are derived from analyzing the actual usage of Qwt functionality in the codebase.


0. Context and Motivation

0.1 Why Replace Qwt?

Reason Details
WASM Support Qwt is tightly coupled to Qt's widget system, making WebAssembly deployment difficult. A custom library can target WebGL/Canvas directly.
Qt Independence Decoupling from Qt allows alternative backends (native, web) and reduces dependency footprint. Qt remains an option but not a requirement.
Performance Need to visualize millions of points at 50 Hz refresh rate. Requires GPU acceleration and aggressive optimization strategies that Qwt doesn't provide out of the box.

0.2 Usage Patterns

Pattern Description
Scale Millions of data points per curve
Refresh Rate 50 Hz continuous updates
Streaming Live data ingestion while plotting
Synchronized Plots Multiple plots with linked X-axis (time), zoom, and pan

0.3 Library Scope

The library should provide an API at the same abstraction level as Qwt - a general-purpose 2D plotting library. It is NOT PlotJuggler-specific. PlotJuggler will integrate with it the same way it currently integrates with Qwt.

0.4 Technology Stack

Component Choice
Language C++ (modern C++17/20)
Build System CMake
Package Manager Conan

Design Goals

  • Qt Independence: Core rendering logic should be decoupled from Qt, with Qt as one possible backend
  • Hardware Acceleration: Support GPU-accelerated rendering (OpenGL, WebGL, Metal, Vulkan)
  • Cross-Platform: Linux, macOS, Windows, and WebAssembly
  • High Performance: Handle datasets with millions of points at 50 Hz

1. Core Plot Widget

1.1 Plot Canvas

  • Rectangular canvas area for rendering curves and annotations
  • Support multiple rendering backends:
    • Software rendering (CPU-based, fallback)
    • OpenGL (desktop)
    • WebGL (WASM)
    • Metal (macOS - optional)
  • Configurable background color
  • Mouse tracking on canvas

1.2 Plot Layout

  • Axes positioned around the canvas:
    • X-axis at bottom
    • Y-axis at left
    • (Optional) Secondary axes at top/right
  • Axis widgets with labels and tick marks
  • Canvas alignment to scale tick marks
  • Margins and spacing configuration

1.3 Coordinate System

  • Data space: Floating-point coordinates (double precision)
  • Pixel space: Integer coordinates for rendering
  • Bi-directional transformation between spaces
  • Support for inverted/flipped axes

2. Curve Rendering

2.1 Curve Styles

Style Description
Lines Connected line segments between points
Dots Individual points rendered as filled circles
LinesAndDots Lines with point markers at each data point
Sticks Vertical lines from each point to the X-axis
Steps Staircase pattern (horizontal then vertical)
StepsInverted Staircase pattern (vertical then horizontal)

2.2 Curve Attributes

  • Line color (RGB/RGBA)
  • Line width (1.0, 1.5, 2.0, 3.0 typical values)
  • Dot/point size (derived from line width)
  • Visibility toggle
  • Antialiasing enable/disable
  • Curve title/name for legend

2.3 Performance Optimizations

  • Point Filtering: Reduce rendered points when zoomed out (e.g., FilterPointsAggressive)
  • Polygon Clipping: Clip curve segments to visible canvas area
  • Dirty Rect Updates: Only repaint changed regions when possible
  • Level-of-Detail: Adapt rendering detail based on zoom level

2.4 Rendering Hints

  • RenderAntialiased: Smooth line rendering
  • Clip to canvas bounds

3. Data Series Interface

3.1 Abstract Data Series

class PlotSeriesData {
    virtual size_t size() const = 0;
    virtual PointF sample(size_t index) const = 0;
    virtual RectF boundingRect() const = 0;
};

3.2 Time Series Support

  • X values represent time, Y values represent data
  • Time offset support (shift all X values by offset)
  • Index lookup from X value (for cursor tracking)

3.3 XY Series Support

  • Arbitrary X/Y data (not time-based)
  • Merged from two separate time series (X from series A, Y from series B)

3.4 Range Queries

  • getVisualizationRangeX(): Return min/max X of data
  • getVisualizationRangeY(Range rangeX): Return min/max Y within X range
  • Used for auto-zoom calculations

3.5 Caching

  • Transformed/processed data caching
  • Reset cache on data update
  • Incremental cache updates for streaming data

4. Axis System

4.1 Scale Drawing

  • Tick mark positions (major and minor)
  • Tick labels with configurable formatting
  • Custom label drawing (e.g., date/time formatting)
  • Scale divisions

4.2 Scale Engine

  • Linear scale calculation
  • Floating point attribute (axis doesn't include 0 unless data requires)
  • Auto-scale from data range
  • Manual scale bounds

4.3 Scale Map (Coordinate Transformation)

class ScaleMap {
    double transform(double dataValue) const;     // data -> pixel
    double invTransform(double pixelValue) const; // pixel -> data
    double s1() const;  // data min
    double s2() const;  // data max
};

4.4 Axis Features

  • Per-axis enable/disable
  • Axis scale setter: setAxisScale(axisId, min, max)
  • Auto-scaling toggle
  • Inverted axis direction (min at top/right)

4.5 Date/Time Axis

  • Format timestamps as human-readable dates
  • Multiple format options:
    • hh:mm:ss.z (time only)
    • hh:mm:ss.z\nyyyy MMM dd (time and date)

5. Interactive Zooming

5.1 Rectangle Zoom

  • Click and drag to select zoom rectangle
  • Rubber band visualization during selection
  • Minimum zoom size threshold
  • Accept/reject based on selection size

5.2 Mouse Wheel Zoom

  • Zoom centered on cursor position
  • Configurable zoom factor per wheel step
  • Per-axis zoom modes:
    • BOTH_AXES: Uniform zoom
    • X_AXIS: Only zoom X
    • Y_AXIS: Only zoom Y
  • Wheel on axis widget zooms only that axis

5.3 Zoom Constraints

  • Axis limits (min/max bounds)
  • Aspect ratio preservation (for XY plots)
  • Minimum/maximum zoom levels

5.4 Zoom Controls

  • Zoom in key (Ctrl+Plus)
  • Zoom out key (Ctrl+Minus)
  • Reset zoom / zoom to fit

6. Panning

6.1 Mouse Panning

  • Click and drag to pan the view
  • Configurable mouse button:
    • Middle mouse button (default)
    • Ctrl + Left mouse button
    • Left mouse button (alternative mode)
  • Pan cursor feedback

6.2 Pan Constraints

  • Optional axis limits (prevent panning past data bounds)

7. Markers and Annotations

7.1 Point Markers

  • Position at (x, y) coordinate
  • Symbol types:
    • Ellipse/Circle
    • (Extensible to other shapes)
  • Symbol attributes:
    • Fill color
    • Border pen
    • Size

7.2 Line Markers

  • Vertical line at X position
  • Horizontal line at Y position
  • Line style (solid, dashed, dotted)
  • Line color and width

7.3 Text Labels

  • Position at (x, y)
  • Rich text support (HTML-like formatting)
  • Background brush with configurable alpha
  • Border pen (optional)
  • Font configuration
  • Text alignment (left, center, right)
  • Label alignment relative to position

7.4 Marker Visibility

  • Show/hide individual markers
  • Visibility based on data availability

8. Curve Tracker / Crosshair

8.1 Vertical Tracker Line

  • Follows X position (time for timeseries)
  • Shows values of all curves at that X
  • Color-coded per curve

8.2 Tracker Display Modes

Mode Description
LINE_ONLY Just the vertical line
VALUE Line + numeric values
VALUE_NAME Line + values + curve names

8.3 Point Markers

  • Show marker dot on each curve at tracker X position
  • Color matches curve color
  • Hide when curve point outside visible range

8.4 Reference Line

  • Secondary tracker for delta comparison
  • Show delta values (current - reference)
  • Different color from primary tracker

8.5 Smart Positioning

  • Text box positioned to avoid overlapping tracker line
  • Flip position when reaching canvas edge
  • Semi-transparent background

9. Legend

9.1 In-Canvas Legend

  • Rendered inside the plot canvas
  • Configurable position (corners, custom alignment)
  • Draggable position (optional)

9.2 Legend Items

  • Curve color indicator (line segment or symbol)
  • Curve name/title
  • Click to toggle curve visibility
  • Visual feedback for hidden curves (grayed text)

9.3 Legend Appearance

  • Background with border
  • Border radius (rounded corners optional)
  • Font size configuration
  • Margins and spacing
  • Collapse/expand toggle button

9.4 Legend Interaction

  • Mouse wheel on legend adjusts font size
  • Click legend item toggles visibility
  • Click collapse button to minimize

10. Grid

10.1 Grid Lines

  • Major grid lines for X and Y
  • Minor grid lines (optional)
  • Grid line style (solid, dotted, dashed)
  • Grid line color and width

10.2 Grid Control

  • Enable/disable per axis
  • Enable/disable minor lines independently

11. Custom Plot Items

11.1 Background Color Regions

  • Draw colored rectangles based on data series values
  • Color mapped from data values via colormap
  • Time-aligned regions

11.2 Custom Item Interface

class PlotItem {
    virtual int rtti() const = 0;  // Runtime type identification
    virtual void draw(Painter*, ScaleMap& xMap, ScaleMap& yMap, RectF& canvasRect) = 0;
    virtual RectF boundingRect() const = 0;
    void attach(Plot* plot);
    void detach();
    void setVisible(bool);
    void setZ(double);  // Stack order
};

12. Rendering and Export

12.1 Export Formats

  • PNG (raster)
  • JPEG (raster)
  • SVG (vector)

12.2 Export Features

  • Configurable resolution/dimensions
  • Copy to clipboard
  • Save to file dialog

12.3 Renderer

class PlotRenderer {
    void render(Plot* plot, Painter* painter, Rect targetRect);
};

13. Event Handling

13.1 Mouse Events

  • Press, release, move, wheel
  • Button identification (left, middle, right)
  • Modifier keys (Ctrl, Shift, Alt)

13.2 Event Patterns

  • Configurable mouse patterns for actions
  • Pattern matching for zoom, pan, etc.

13.3 Canvas Events

  • Drag and drop support (for curve dragging)
  • Accept/reject drop based on data type

14. Performance Requirements

14.1 Target Metrics

Metric Target
Points per curve 1,000,000+ (millions)
Curves per plot 20+
Replot rate 50 Hz (20ms budget)
Zoom/pan latency <20ms
Streaming ingest Continuous append without frame drops

14.2 Optimization Strategies

  • Point decimation: Reduce to ~2-4x pixel width points when zoomed out
  • GPU-based rendering: Offload line/point drawing to shaders
  • Incremental updates: Only upload new data to GPU for streaming
  • Spatial indexing: Fast range queries (e.g., for Y min/max in X range)
  • Double buffering: Render next frame while displaying current
  • Level-of-detail: Pre-computed min/max pyramids for fast zoom-out

14.2.1 Min-Max Tree Decimation (Recommended)

Reference: KDAB - A Speed-Up for Charting on Embedded

Instead of rendering individual points, render one vertical line per pixel column spanning from the minimum to maximum Y value in that column's X range. This reduces millions of points to ~1000-2000 line segments (screen width).

Data Structure: Min-Max Tree

- Binary tree where each node stores (min, max) of its subtree
- Array-based layout (infix ordering) for cache efficiency
- Bit operations for parent/child navigation (no pointers)
- Query: O(log n) for min/max in any X range
- Update: O(log n) append, only bubbles up if min/max changes

Performance Results (from KDAB):

Points Naive Rendering Min-Max Tree
300,000 >2000 ms ~3 ms

Why this matters for PlotJuggler:

  • 1M points → ~1000 vertical lines (one per pixel column)
  • Streaming: O(log n) update per new point
  • Zoom: Query any range in O(log n)
  • Memory: 2x overhead (min + max per node) but worth it

14.3 Memory Efficiency

  • Zero-copy data interface where possible (point to user's data)
  • Lazy bounding rect calculation with caching
  • GPU buffer reuse (avoid re-allocation per frame)
  • Memory-mapped file support for very large datasets (optional)

14.4 Streaming Considerations

  • Append-only data path optimized for minimal overhead
  • Ring buffer support for fixed-window streaming
  • Async data upload to GPU (don't block main thread)

15. Architecture Requirements

15.1 Qt Independence Layer

+-------------------+
|   Application     |
+-------------------+
         |
+-------------------+
|  PlotLib Core     |  <- Qt-independent
|  (Data, Math,     |
|   Rendering API)  |
+-------------------+
         |
+-------------------+  +-------------------+  +-------------------+
|  Qt Backend       |  | Web/Canvas Backend|  | Other Backend     |
|  (QWidget,        |  | (WebGL, Canvas2D) |  | (SDL, etc.)       |
|   QPainter,       |  |                   |  |                   |
|   QOpenGLWidget)  |  |                   |  |                   |
+-------------------+  +-------------------+  +-------------------+

15.2 Core Components (Qt-Independent)

  • Data series interfaces
  • Coordinate transformation math
  • Curve algorithms (line simplification, point filtering)
  • Scale calculations
  • Color and style definitions
  • Event abstraction

15.3 Backend Requirements

  • Abstract Painter interface
  • Abstract Widget/Canvas interface
  • Input event translation
  • Timer/animation support

16. Platform-Specific Considerations

16.1 Desktop (Linux, macOS, Windows)

  • Native OpenGL support
  • High-DPI display handling
  • System color scheme integration

16.2 WebAssembly (WASM)

  • WebGL 2.0 rendering
  • Canvas 2D fallback
  • Touch event handling
  • Browser-compatible event loop
  • Memory constraints awareness

17. Summary of Qwt Classes Used

Qwt Class Purpose Custom Equivalent Needed
QwtPlot Main plot widget Plot
QwtPlotCanvas Software canvas PlotCanvas
QwtPlotOpenGLCanvas OpenGL canvas GLPlotCanvas
QwtPlotCurve Curve rendering PlotCurve
QwtSeriesData<QPointF> Data interface PlotSeriesData
QwtScaleMap Coordinate transform ScaleMap
QwtScaleDraw Axis drawing ScaleDraw
QwtScaleEngine Scale calculation ScaleEngine
QwtPlotZoomer Rectangle zoom PlotZoomer
QwtPlotMagnifier Wheel zoom PlotMagnifier
QwtPlotPanner Pan/drag PlotPanner
QwtPlotMarker Point/line markers PlotMarker
QwtSymbol Marker symbols MarkerSymbol
QwtPlotLegendItem In-canvas legend PlotLegend
QwtPlotGrid Grid lines PlotGrid
QwtPlotItem Base plot item PlotItem
QwtPlotRenderer Export rendering PlotRenderer
QwtText Rich text labels PlotText
QwtPainter Optimized painting Painter
QwtEventPattern Input patterns EventPattern

18. Not Required (Unused Qwt Features)

The following Qwt features are not used by PlotJuggler and do not need to be implemented:

  • Polar plots (QwtPolarPlot)
  • Bar charts (QwtPlotBarChart)
  • Spectrograms / heatmaps (QwtPlotSpectrogram)
  • Histogram (QwtPlotHistogram)
  • Vector fields (QwtPlotVectorField)
  • Trading curves (OHLC)
  • Dials, knobs, sliders
  • Compass, analog clock widgets
  • Multi-bar charts
  • Shape items
  • SVG items
  • Interval curves
  • Curve fitting (Bezier, spline)
  • Raster items

19. Implementation Priority

Phase 1: Core Rendering

  1. Plot canvas with software rendering
  2. Basic curve rendering (lines, dots)
  3. Axis system with linear scales
  4. Coordinate transformation

Phase 2: Interaction

  1. Mouse wheel zoom
  2. Rectangle zoom selection
  3. Panning
  4. Event handling abstraction

Phase 3: Annotations

  1. Point and line markers
  2. Text labels
  3. Grid lines
  4. Curve tracker

Phase 4: Polish

  1. Legend
  2. Export (PNG, SVG)
  3. Custom plot items
  4. Date/time axis

Phase 5: Acceleration

  1. OpenGL backend
  2. WebGL backend for WASM
  3. Performance optimization

20. Testing Requirements

20.1 Visual Regression Tests

  • Render known datasets and compare to reference images
  • Test all curve styles
  • Test zoom/pan states

20.2 Performance Tests

  • Benchmark with 100k, 1M, 10M points
  • Measure replot time at 50 Hz target
  • Profile memory usage and GPU memory
  • Streaming throughput tests (points/second)

20.3 Platform Tests

  • Test on all target platforms (Linux, macOS, Windows)
  • Verify WASM build and runtime in major browsers
  • Test touch input on mobile browsers

20.4 Synchronization Tests

  • Multiple plots with linked axes
  • Verify frame timing consistency
  • Test zoom/pan propagation latency