Class ParaGraph

All Implemented Interfaces:
DoubleClickHandler, HasAllDragAndDropHandlers, HasAllFocusHandlers, HasAllGestureHandlers, HasAllKeyHandlers, HasAllMouseHandlers, HasAllTouchHandlers, HasBlurHandlers, HasClickHandlers, HasContextMenuHandlers, HasDoubleClickHandlers, HasDragEndHandlers, HasDragEnterHandlers, HasDragHandlers, HasDragLeaveHandlers, HasDragOverHandlers, HasDragStartHandlers, HasDropHandlers, HasFocusHandlers, HasGestureChangeHandlers, HasGestureEndHandlers, HasGestureStartHandlers, HasKeyDownHandlers, HasKeyPressHandlers, HasKeyUpHandlers, HasMouseDownHandlers, HasMouseMoveHandlers, HasMouseOutHandlers, HasMouseOverHandlers, HasMouseUpHandlers, HasMouseWheelHandlers, HasTouchCancelHandlers, HasTouchEndHandlers, HasTouchMoveHandlers, HasTouchStartHandlers, MouseDownHandler, MouseMoveHandler, MouseOutHandler, MouseUpHandler, MouseWheelHandler, TouchEndHandler, TouchMoveHandler, TouchStartHandler, HasAttachHandlers, EventHandler, HasHandlers, EventListener, AcceptsOneWidget, Focusable, HasFocus, HasOneWidget, HasVisibility, HasWidgets, HasWidgets.ForIsWidget, IsWidget, RequiresResize, SourcesClickEvents, SourcesFocusEvents, SourcesKeyboardEvents, SourcesMouseEvents, SourcesMouseWheelEvents, Iterable<Widget>, AbstractGraph.HasTrajectory, AbstractGraph.Shifter, AbstractGraph.Shifting, AbstractGraph.Zoomer, AbstractGraph.Zooming, ContextMenu.Listener, ContextMenu.Provider, Tooltip.Provider

ParaGraph is a specialized 2D parametric/phase-plane graph component for visualizing trajectories produced by a simulation module. Each data sample is expected to be a double[] whose first element is the time and the remaining elements represent the state vector. ParaGraph maps those state vectors into phase-plane coordinates via a HasPhase2D.Data2Phase mapper and draws the resulting parametric curve onto a canvas.

Key responsibilities:

  • Maintain a bounded history of parametric data points in a RingBuffer<double[]>, where each stored array has the time prepended as the first element.
  • Coalesce incoming samples to conserve memory: samples are appended only when the estimated distance (in phase plane units) to the previous stored point exceeds a configurable threshold (derived from a minimum pixel spacing), unless explicitly forced.
  • Handle special time values (NaN) and duplicate times: duplicate times replace the last sample; NaN times mark new trajectory segments and update the recorded initial state accordingly.
  • Map simulation state <-> phase coordinates using a HasPhase2D.Data2Phase instance. If the mapper implements BasicTooltipProvider it will be used as the tooltip provider for parametric tooltips.
  • Render the trajectory with optional start/end markers and custom markers. The drawing code takes into account current axis ranges, scaling, translation and zooming.
  • Provide interactive features:
    • Double-click or single-touch on the phase plane to convert the clicked phase coordinates back into a simulation initial state and set it on the view.
    • Context menu actions to clear the canvas and toggle autoscaling of axes.
    • Tooltip support for coordinates via a configured tooltip provider.
  • Autoscale axes to fit the visible data when enabled. Autoscaling computes min/max ranges from the mapper over the current buffer and rounds to sensible tick-friendly bounds. Percent scales are clamped to [0,1] when configured.
  • Export trajectory data to a text format (time, x, y) using the configured mapper and a Formatter for numeric formatting.

Rendering details:

  • Painting is scheduled with Scheduler.scheduleDeferred(Scheduler.ScheduledCommand) to avoid redundant immediate repaints; a paintScheduled flag prevents oversubscription of repaint requests.
  • Canvas transform sequence: global scale, translation for view corner and bounds, additional zoom factor, and Y-axis flip to map mathematical coordinates to canvas pixel coordinates.
  • Line width is increased slightly when using semi-transparent trajectory colors to improve visibility.

Buffering and sampling:

  • bufferThreshold is computed in calcBounds from MIN_PIXELS and the current scale and axis ranges. It represents the squared minimal distance (in data units) required between successive stored samples and prevents storing points closer than a few screen pixels.
  • Initial trajectory starting point is stored in init and updated whenever the buffer begins a new segment (empty buffer) or when a NaN time indicates a new starting point.

Usage notes:

  • Call setMap(Data2Phase) to provide a domain-specific mapping between model state and phase-plane coordinates. A default TraitMap is created lazily if none is set.
  • Use addData(double, double[], boolean) to append samples from the simulation. The method clones and prepends the time to the provided array before storing it in the buffer.
  • Enable or disable autoscaling via the context menu or autoscale().
Author:
Christoph Hauert
See Also:
  • Field Details

    • init

      double[] init
      The starting point of the most recent trajectory.
    • map

      The map for converting data to phase plane coordinates.
    • bufferThreshold

      private double bufferThreshold
      Threshold for storing new data point in buffer. Roughly corresponds to the squared distance between two points that are at least a pixel apart.
    • MIN_PIXELS

      private static final double MIN_PIXELS
      The minimum distance between two subsequent points in pixels.
      See Also:
    • MIN_ZOOM_FACTOR

      private static final double MIN_ZOOM_FACTOR
      Minimum zoom level to avoid unbounded ranges.
      See Also:
    • domain

      private final Rectangle2D domain
      Reusable rectangle for the domain bounds.
    • viewState

      private final ParaGraph.ViewState viewState
      Reusable view state for zooming and shifting calculations.
    • NEAR_ZERO

      private static final double NEAR_ZERO
      Threshold below which linear axis bounds are snapped to zero.
      See Also:
    • autoscalePoint

      private final Point2D autoscalePoint
      Reusable point for autoscale calculations.
    • paintScheduled

      private boolean paintScheduled
      The flag to indicate whether painting is already scheduled. Subsequent requests are ignored.
    • clearMenu

      private ContextMenuItem clearMenu
      The context menu item to clear the canvas.
    • zoomFitMenu

      private ContextMenuItem zoomFitMenu
      The context menu item to zoom to fit the buffered data.
  • Constructor Details

    • ParaGraph

      public ParaGraph(Phase2D view, Module<?> module)
      Create new parametric graph for module running in view.
      Parameters:
      view - the view of this graph
      module - the module backing the graph
  • Method Details

    • onLoad

      protected void onLoad()
      Overrides:
      onLoad in class AbstractGraph<double[]>
    • activate

      public void activate()
      Description copied from class: AbstractGraph
      Perform necessary preparations to show the graph in the GUI. Attaches mouse and touch handlers for graphs that implement AbstractGraph.Zooming or AbstractGraph.Shifting interfaces.
      Overrides:
      activate in class AbstractGraph<double[]>
      See Also:
    • setMap

      public void setMap(HasPhase2D.Data2Phase map)
      Set the map for converting data to phase plane coordinates.
      Parameters:
      map - the conversion map
    • getMap

      public HasPhase2D.Data2Phase getMap()
      Get the map for converting data to phase plane coordinates.
      Returns:
      the conversion map
    • addData

      public void addData(double t, double[] data, boolean force)
      Add data to the graph. The time t is prepended to the data as the first element.
      Parameters:
      t - the time of the data
      data - the data to add
      force - true to force adding the data
      Implementation Notes:
      • The data array is cloned and the time prepended before adding it to the buffer.
      • In order to conserve memory the data is added only if the distance between the new data point and the last point in the buffer is larger than threshold bufferThreshold, unless force == true.
    • handleEmptyBuffer

      private void handleEmptyBuffer(double t, double[] data)
      Handle the case that the buffer is empty. Add data to the buffer and set the initial state.
      Parameters:
      t - the time at which the data is recorded
      data - the data to add
    • handleNaNTime

      private void handleNaNTime(double lastt, double t, double[] data, int len)
      Handle the case that the time t is NaN. If the last time in the buffer is also NaN the last data point is replaced by the new data, otherwise the new data is appended to the buffer. The initial state is updated accordingly.
      Parameters:
      lastt - the time of the last data point in the buffer
      t - the time of the data
      data - the data to add
      len - the length of the data array (including time)
    • distSq

      private double distSq(double[] vec, double[] buf)
      Helper method to calculate the distance squared between two vectors.
      Parameters:
      vec - the first vector
      buf - the second vector
      Returns:
      the squared distance
    • paint

      public boolean paint(boolean force)
      Description copied from class: AbstractGraph
      Draw the graph. For re-drawing the graph, set force to true.
      Overrides:
      paint in class AbstractGraph<double[]>
      Parameters:
      force - true to force re-drawing of graph
      Returns:
      true if painting skipped
    • paintPara

      private void paintPara(boolean withMarkers)
      Paint the trajectory in the phase plane. If withMarkers is true the start and end points of the trajectory are marked with green and red circles, respectively.
      Parameters:
      withMarkers - true to mark start and end points
    • drawFrameForView

      private void drawFrameForView(ParaGraph.ViewState state, int xLevels, int yLevels)
      Draw the frame using the visible ranges implied by the current zoom and shift.
      Parameters:
      state - the current view state
      xLevels - number of x-axis levels
      yLevels - number of y-axis levels
    • applyVisibleRanges

      private void applyVisibleRanges(ParaGraph.ViewState state)
      Adjust axis ranges to match the current zoom and shift.
      Parameters:
      state - the current view state
    • currentViewState

      private ParaGraph.ViewState currentViewState()
      Update and return the cached view state for the current axis ranges.
      Returns:
      the updated view state
    • drawTrajectory

      private void drawTrajectory(Point2D currPt, Point2D nextPt, double xScale, double yScale)
      Draw the trajectory stored in the buffer.
      Parameters:
      currPt - the storage for the current point
      nextPt - the storage for the next point
      xScale - the x-axis scale
      yScale - the y-axis scale
    • drawStartEndMarkers

      private void drawStartEndMarkers(Point2D aPt, double xScale, double yScale)
      Draw start and end markers for the trajectory.
      Parameters:
      aPt - the storage for a point
      xScale - the x-axis scale
      yScale - the y-axis scale
    • drawCustomMarkers

      private void drawCustomMarkers(Point2D pt, double xScale, double yScale)
      Draw custom markers stored in AbstractGraph.markers.
      Parameters:
      pt - temporary storage for points
      xScale - the x-axis scale
      yScale - the y-axis scale
    • drawMarkerCircle

      private void drawMarkerCircle(Point2D pt, double xScale, double yScale, boolean fill, double radius)
      Draw a marker circle in screen coordinates to avoid distortion from scaling.
      Parameters:
      pt - marker location in data coordinates
      xScale - base x-axis scale
      yScale - base y-axis scale
      fill - true for filled markers, false for outline
      radius - marker radius in screen pixels
    • calcBounds

      public void calcBounds(int width, int height)
      Description copied from class: AbstractGraph
      Calculate bounds of drawing area.
      Overrides:
      calcBounds in class AbstractGraph<double[]>
      Parameters:
      width - the width of the drawing area
      height - the height of the drawing area
    • autoscale

      public void autoscale()
      Automatically adjust the range of autoscaled axes to fit the data in the buffer.
    • zoom

      public void zoom()
      Description copied from class: AbstractGraph
      Reset zoom. Default implementation for graphs that implement Zooming.
      Specified by:
      zoom in interface AbstractGraph.Zooming
      Overrides:
      zoom in class AbstractGraph<double[]>
      See Also:
    • zoom

      public void zoom(double zoom)
      Description copied from class: AbstractGraph
      Adjust zoom level by the factor zoom. Default implementation for graphs that implement Zooming.
      Specified by:
      zoom in interface AbstractGraph.Zooming
      Overrides:
      zoom in class AbstractGraph<double[]>
      Parameters:
      zoom - the new zoom level
      See Also:
    • zoom

      public void zoom(double zoom, int x, int y)
      Description copied from class: AbstractGraph
      Adjust zoom level by the factor zoom with the center at coordinates (x,y) (in display coordinates as provided by event listeners). Default implementation for graphs that implement Zooming.
      Specified by:
      zoom in interface AbstractGraph.Zoomer
      Overrides:
      zoom in class AbstractGraph<double[]>
      Parameters:
      zoom - the new zoom level
      x - the x-coordinate of the zoom center
      y - the y-coordinate of the zoom center
      See Also:
    • shift

      public void shift(int dx, int dy)
      Description copied from class: AbstractGraph
      Shift the (zoomed) graph within the view port by (dx, dy). Default implementation for graphs that implement Shifting.
      Specified by:
      shift in interface AbstractGraph.Shifter
      Overrides:
      shift in class AbstractGraph<double[]>
      Parameters:
      dx - the horizontal shift of the graph
      dy - the vertical shift of the graph
      See Also:
    • computeMinZoom

      private double computeMinZoom(double baseRange, double domainWidth)
      Compute minimum zoom factor for a base range and domain width.
      Parameters:
      baseRange - axis range in data units
      domainWidth - width of the constrained domain
      Returns:
      minimum zoom factor that keeps the view within the domain
    • updateDomain

      private Rectangle2D updateDomain()
      Return the current domain limits for zooming and shifting.
      Returns:
      the domain rectangle (origin at minimum values)
    • clampViewCorner

      private void clampViewCorner(ParaGraph.ViewState state)
      Clamp the current view corner to keep the visible range inside the domain.
      Parameters:
      state - the current view state
    • setViewCorner

      private void setViewCorner(ParaGraph.ViewState state, double cornerX, double cornerY)
      Clamp and apply the view corner for the provided state.
      Parameters:
      state - the current view state
      cornerX - candidate x view corner
      cornerY - candidate y view corner
    • clampViewX

      private double clampViewX(double corner, double zoom, double width, double baseRangeX)
      Clamp a horizontal view corner to keep the visible range inside the domain.
      Parameters:
      corner - candidate view corner (pixels)
      zoom - zoom factor for x-axis
      width - frame width in pixels
      baseRangeX - base x-axis range
      Returns:
      clamped view corner value
    • clampViewY

      private double clampViewY(double corner, double zoom, double height, double baseRangeY)
      Clamp a vertical view corner to keep the visible range inside the domain.
      Parameters:
      corner - candidate view corner (pixels)
      zoom - zoom factor for y-axis
      height - frame height in pixels
      baseRangeY - base y-axis range
      Returns:
      clamped view corner value
    • clearHistory

      public void clearHistory()
      Description copied from class: AbstractGraph
      Clear the history of the graph (if there is one).
      Overrides:
      clearHistory in class AbstractGraph<double[]>
    • updateAutoscale

      private void updateAutoscale()
      Update autoscale ranges based on the most recent buffered point.
    • ensureAutoscaleVisible

      private void ensureAutoscaleVisible()
      Shift the view corner to keep the latest autoscale point visible without shrinking the current ranges.
    • applyRanges

      private void applyRanges(double minX, double maxX, double minY, double maxY, boolean applyX, boolean applyY)
      Apply axis ranges with axis-specific constraints.
      Parameters:
      minX - minimum x value
      maxX - maximum x value
      minY - minimum y value
      maxY - maximum y value
      applyX - whether to update the x-axis range
      applyY - whether to update the y-axis range
    • enforceEqualAxisScale

      private void enforceEqualAxisScale()
      Enforce equal units-per-pixel scale on both axes for linear plots.
    • setCenteredX

      private void setCenteredX(double range, boolean clamp, double domainMin, double domainMax)
      Center and optionally clamp the x-range.
      Parameters:
      range - target range
      clamp - whether to clamp to the domain
      domainMin - domain minimum
      domainMax - domain maximum
    • setCenteredY

      private void setCenteredY(double range, boolean clamp, double domainMin, double domainMax)
      Center and optionally clamp the y-range.
      Parameters:
      range - target range
      clamp - whether to clamp to the domain
      domainMin - domain minimum
      domainMax - domain maximum
    • zoomToFit

      private void zoomToFit()
      Set axis ranges to fit the full buffered trajectory and reset zoom factor.
    • applyXConstraints

      private void applyXConstraints()
      Clamp and snap the x-axis range according to axis settings.
    • applyYConstraints

      private void applyYConstraints()
      Clamp and snap the y-axis range according to axis settings.
    • snapNearZero

      private double snapNearZero(double value)
      Snap small linear values to zero.
      Parameters:
      value - input value
      Returns:
      snapped value
    • clampPercentMin

      private double clampPercentMin(double value)
      Clamp the minimum of a percent axis.
      Parameters:
      value - input value
      Returns:
      clamped value
    • clampPercentMax

      private double clampPercentMax(double value)
      Clamp the maximum of a percent axis.
      Parameters:
      value - input value
      Returns:
      clamped value
    • clampLogMin

      private double clampLogMin(double value)
      Clamp the minimum of a log-scaled axis.
      Parameters:
      value - input value
      Returns:
      clamped value
    • schedulePaint

      protected void schedulePaint()
      Schedule painting of the graph. If painting is already scheduled, subsequent requests are ignored.
      See Also:
    • export

      public void export(AbstractGraph.MyContext2d ctx)
      Description copied from class: AbstractGraph
      Export the graphical context ctx.
      Specified by:
      export in class AbstractGraph<double[]>
      Parameters:
      ctx - the graphical context to export
    • onDoubleClick

      public void onDoubleClick(DoubleClickEvent event)
      Specified by:
      onDoubleClick in interface DoubleClickHandler
    • processInitXY

      private void processInitXY(double x, double y)
      Helper method to convert screen coordinates into an initial configuration and set the controller's initial state.
      Parameters:
      x - the x-coordinate on screen
      y - the y-coordinate on screen
    • onTouchStart

      public void onTouchStart(TouchStartEvent event)
      Description copied from class: AbstractGraph

      The graph reacts to different kinds of touches: short touches or taps (&lt;250 msec) and long touches (&gt;250 msec). Long touches trigger different actions depending on the number of fingers:

      Single finger
      Initiate shifting the view
      Two fingers
      Initiate pinching zoom.
      Specified by:
      onTouchStart in interface TouchStartHandler
      Overrides:
      onTouchStart in class AbstractGraph<double[]>
      See Also:
    • getTooltipAt

      public String getTooltipAt(int x, int y)
      Description copied from interface: Tooltip.Provider
      Get the tooltip information for the location with coordinates (x, y). The returned string may include HTML elements for formatting.
      Specified by:
      getTooltipAt in interface Tooltip.Provider
      Parameters:
      x - the x-coordinate for the tooltip
      y - the y-coordinate for the tooltip
      Returns:
      the (formatted) string with the tooltip info
    • inside

      private boolean inside(double x, double y)
      Check if point (in user coordinates but not yet scaled to axes) lies inside of phase plane.
      Parameters:
      x - x-coordinate of point
      y - y-coordinate of point
      Returns:
      true if inside
    • inside

      protected boolean inside(int x, int y)
      Description copied from class: AbstractGraph
      Check if the event coordinates are inside the interactive plot area. Default implementation accepts all coordinates.
      Overrides:
      inside in class AbstractGraph<double[]>
      Parameters:
      x - the x-coordinate relative to the graph element
      y - the y-coordinate relative to the graph element
      Returns:
      true if inside the interactive plot area
    • populateZoomMenu

      protected void populateZoomMenu(ContextMenu menu)
      Description copied from class: AbstractGraph
      Populate the zoom submenu with standard zoom actions.
      Overrides:
      populateZoomMenu in class AbstractGraph<double[]>
      Parameters:
      menu - the zoom submenu to populate
    • populateContextMenuAt

      public void populateContextMenuAt(ContextMenu menu, int x, int y)
      Description copied from class: AbstractGraph
      Populate context menu menu in listening widget at (relative) position (x,y).

      Adds buffer size menu and queries the view to add further functionality.

      Specified by:
      populateContextMenuAt in interface ContextMenu.Provider
      Overrides:
      populateContextMenuAt in class AbstractGraph<double[]>
      Parameters:
      menu - context menu entries are added here
      x - horizontal coordinate (relative to listening widget)
      y - horizontal coordinate (relative to listening widget)
      See Also:
    • exportTrajectory

      public void exportTrajectory(StringBuilder export)
      Description copied from interface: AbstractGraph.HasTrajectory
      Export the trajectory of the graph to export.
      Specified by:
      exportTrajectory in interface AbstractGraph.HasTrajectory
      Parameters:
      export - the string builder to export the trajectory