Class S3Graph

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

Graph for the simplex \(S_3\). The graph is used to visualize the evolution of three traits by projecting them onto the corners of the simplex. The view renders parametric trajectories stored in a RingBuffer, exposes zoom and shift interactions, supports swapping trait assignments via a context menu, and allows exporting to PNG/SVG or CSV.

Responsibilities

  • Render a simplex (equilateral-triangle style) frame, subdivided levels, tick marks and colored corner labels according to a given S3Map.
  • Store and draw a time-ordered trajectory of composition vectors in a ring buffer; the buffer entries include time as the first element (internal format: [time, comp0, comp1, comp2, ...]).
  • Efficiently sample and append incoming data using a pixel-distance based threshold to avoid storing nearly identical consecutive points.
  • Draw start/end markers and arbitrary custom markers; export the stored trajectory in a human-readable CSV-like format.
  • Provide user interaction support: double-click and single-touch to set an initial composition, context menus to clear history, swap corner ordering, or remap corners to traits, tooltip support, zooming and shifting behavior provided by the hosting view.

Important behavior notes

  • A S3Map must be supplied (via setMap(S3Map)) to convert between data vectors and simplex/cartesian coordinates. The map also supplies the corner names and color ordering used for labels and export.
  • Incoming data points are added through addData(time, data, force). The data array passed to this method is expected to be the composition vector (without time) and will be prepended with the provided time before storing. If time is NaN special handling is applied (replace or append depending on the last stored time).
  • When a new sample has the same time (within numerical tolerance) as the last stored sample the last sample is replaced and the initial-state (start point) tracking is updated accordingly.
  • Buffer sampling threshold is computed in screen pixels (see calcBounds(int,int)); points closer than the threshold (squared) are not stored unless force is true.
  • Coordinate conversions for mouse/touch interactions map screen coordinates to scaled simplex coordinates in [0,1] (see scaledX(double) / scaledY(double)). A hit test inside(double,double) ensures interactions occur only when the pointer is inside the simplex triangle.

Rendering details

  • Painting occurs in paint(boolean) and delegates to paintS3(boolean) which sets up scaling, translation and zooming transforms before drawing.
  • Trajectory drawing uses the configured stroke styles and optionally draws start (green) and end (red) markers; custom markers may be filled or stroked depending on their metadata.
  • The simplex frame supports showing subdivision levels, tick marks and corner labels. The triangle aspect ratio is constrained so the simplex appears equilateral (see SQRT_2).

Context menu and UI interactions

  • Right-click (context menu) entries include: Clear history, Swap order of traits along the closest edge, and a submenu to set which trait is assigned to the closest corner when the module exposes more than three traits.
  • Double-click and touch events call the host view's setInitialState with the composition corresponding to the clicked location.
  • Tooltips are provided through an optional TooltipProvider (the S3Map is set as the tooltip provider by setMap(S3Map) when available).

Public API highlights

Notes and assumptions

  • The class assumes three displayed components for the simplex layout, but uses the provided S3Map.getOrder() and S3Map.getNames() to support modules with more than three underlying traits (allowing the user to choose which traits are shown at the corners).
  • The widget depends on host-provided styling flags (contained in style) to decide which visual elements to draw (ticks, labels, levels, frame, marker sizes, colors, etc.).
  • All coordinates conversion and painting apply scaling/zoom transforms; callers should trigger paint(boolean) when view parameters or data change.
Author:
Christoph Hauert
  • Field Details

    • init

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

      The lower left corner of the simplex.
    • e1

      The lower right corner of the simplex.
    • e2

      The upper corner of the simplex.
    • outline

      Path2D outline
      The path that outlines the simplex.
    • map

      S3Map map
      The map for converting data to simplex coordinates (cartesian).
    • role

      int role
      The identifier of the role of the data.
    • SQRT_2

      static final double SQRT_2
      Constant for \(\sqrt{2}\). Aspect ratio of equilateral triangle.
      See Also:
    • 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:
    • swapOrderMenu

      private ContextMenuItem swapOrderMenu
      The context menu item to swap the order of the traits along the closest edge.
    • clearMenu

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

      private ContextMenu setTraitMenu
      The context menu to select the trait in the closest corner.
    • SWAP_MENU_LABEL

      private static final String SWAP_MENU_LABEL
      The label of the swap order menu item.
      See Also:
    • SWAP_MENU

      private static final String SWAP_MENU
      The prefix of the swap order menu item.
      See Also:
    • SWAP_MENU_ARROW

      private static final String SWAP_MENU_ARROW
      The arrow symbol used in the swap order menu item.
      See Also:
  • Constructor Details

    • S3Graph

      public S3Graph(S3 view, Module<?> module, int role)
      Create a new simplex \(S_3\) graph for module running in view with the specified role.
      Parameters:
      view - the view of this graph
      module - the module backing the graph
      role - the role of the data
  • 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(S3Map map)
      Set the map for converting data to simplex coordinates.
      Parameters:
      map - the conversion map
    • getMap

      public S3Map getMap()
      Get the map for converting data to simplex coordinates.
      Returns:
      the conversion map
    • reset

      public void reset()
      Description copied from class: AbstractGraph
      Reset the graph. Clear canvas and messages.
      Overrides:
      reset in class AbstractGraph<double[]>
    • 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[] data, double lastt)
      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:
      data - the data to add
      lastt - the time of the last data point in the buffer
    • 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
    • paintS3

      private void paintS3(boolean withMarkers)
      Paint the trajectory in the simplex. 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
    • drawTrajectory

      private void drawTrajectory(double w, double h)
      Draw the trajectory stored in the buffer.
      Parameters:
      w - graph width
      h - graph height
    • drawStartEndMarkers

      private void drawStartEndMarkers(double w, double h)
      Draw start and end markers for the trajectory.
      Parameters:
      w - graph width
      h - graph height
    • drawCustomMarkers

      private void drawCustomMarkers(double w, double h)
      Draw any additional markers stored in markers.
      Parameters:
      w - graph width
      h - graph height
    • 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
    • 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
    • drawFrame

      public void drawFrame(int sLevels)
      Draws the frame of the simplex. The corners are marked by the trait names in their respective colours. For visual guidance each side is subdivided into sLevels sublevels.
      Parameters:
      sLevels - the number of sublevels for the frame
    • drawOutline

      private void drawOutline()
      Draw the outline of the simplex.
    • drawS3Levels

      private void drawS3Levels(int levels, double width, double height)
      Draw the subdivision levels of the simplex.
      Parameters:
      levels - the number of sublevels
      width - the width of the simplex
      height - the height of the simplex
    • drawS3Ticks

      private void drawS3Ticks(int levels, double width, double height)
      Draw the ticks along the boundaries of the simplex.
      Parameters:
      levels - the number of sublevels
      width - the width of the simplex
      height - the height of the simplex
    • drawCornerLabels

      private void drawCornerLabels(double width, double height)
      Draw the corner labels of the simplex in their respective colours.
      Parameters:
      width - the width of the simplex
      height - the height of the simplex
    • onDoubleClick

      public void onDoubleClick(DoubleClickEvent event)
      Specified by:
      onDoubleClick in interface DoubleClickHandler
    • 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:
    • scaledX

      double scaledX(double x)
      Convert the x-component of the screen coordinates (x, y) into scaled (Cartesian) coordinates in [0, 1].
      Parameters:
      x - the x-coordinate on screen
      Returns:
      the scaled coordinate
    • scaledY

      double scaledY(double y)
      Convert the y-component of the screen coordinates (x, y) into scaled (Cartesian) coordinates in [0, 1].
      Parameters:
      y - the y-coordinate on screen
      Returns:
      the scaled coordinate
    • processInitXY

      private void processInitXY(int x, int 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
    • 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

      protected boolean inside(double sx, double sy)
      Check if point (in scaled user coordinates) lies inside of simplex.
      Parameters:
      sx - x-coordinate of point
      sy - y-coordinate of point
      Returns:
      true if inside
    • 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:
    • addClearMenu

      private void addClearMenu(ContextMenu menu)
      Helper method to process the clear context menu.
      Parameters:
      menu - the context menu to populate
    • addSwapOrderMenu

      private void addSwapOrderMenu(ContextMenu menu, int x, int y)
      Helper method to process the swap order submenu logic of the context menu.
      Parameters:
      menu - the context menu to populate
      x - the x-coordinate of the mouse pointer
      y - the y-coordinate of the mouse pointer
    • swapOrder

      private void swapOrder(int[] order, int i, int j)
      Helper method to swap two entries in the order array.
      Parameters:
      order - the order array
      i - the index of the first entry
      j - the index of the second entry
    • addSetTraitMenu

      private void addSetTraitMenu(ContextMenu menu, int x, int y)
      Helper method to process the select traits submenu. For modules with more than three traits, a submenu is created to allow the user to select the trait for each corner.
      Parameters:
      menu - the context menu to populate
      x - the x-coordinate of the mouse pointer
      y - the y-coordinate of the mouse pointer
    • closestCorner

      protected int closestCorner(double x, double y)
      Find the corner closest to the point (x, y).
      Parameters:
      x - the x-coordinate of the point
      y - the y-coordinate of the point
      Returns:
      the index of the closest corner
    • closestEdge

      protected int closestEdge(double x, double y)
      Find the edge closest to the point (x, y).
      Parameters:
      x - the x-coordinate of the point
      y - the y-coordinate of the point
      Returns:
      the index of the closest edge
    • 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