smart_arrays_plot_polyline 2.0.1
smart_arrays_plot_polyline: ^2.0.1

Dart js
Flutter web

Plots small or big 1D arrays in form of polylines in the browser, optionally with axes and legend text. Many configuration options of the view are provided.

example/example.dart

import 'dart:html';
import 'dart:svg';

import 'package:smart_arrays_plot_polyline/smart_arrays_plot_polyline.dart';
import 'dart:typed_data';
import 'dart:math' as math;

import 'sample_data.dart';

/// Demonstrates the usage of th package 'smart_arrays_plot_polyline' by displaying
/// two arrays (containing some periods of sin(x) and a sin(x)/x) as polylines
/// along with coordinate axes, a coordinate grid, a border and a legend.
/// This example can be directly executed via
/// 'https://smart.specpad.bplaced.net/smart_arrays_polyline/example.html'.
main() {
  // Fill 2 arrays with a sinc and a sine function, to be displayed later
  Float64List sinc = SampleData.genSinc(100.0, 0.0, 8, 2000, false)[1],
      sine = SampleData.genSine(20.0, 0.0, 0.0, 8, 2000, false)[1];

  // Set up the containers where the graphics is to be drawn
  computeLayout();

  // Compute the polylines for the graphical display of sinc and sine
  Polyline plSinc = Polyline(sinc, 0, sinc.length - 1, dataAreaRect.width,
      dataAreaRect.height, null, null, null, {PyA.YPOSITION_ZERO: "0.8"});

  Polyline plSine = Polyline(sine, 0, sine.length - 1, dataAreaRect.width,
      dataAreaRect.height, null, null, null, {
    PyA.YPOSITION_ZERO: "0.8", // same vertical posisition as sinc
    PyA.REFYMAX: "${plSinc.ymax}", // sine vertical scale is relative to sinc
    PyA.STROKE: "red", // draw sine in a different color
  });

  // Compute x and y axis for the sinc function (sine will be relative to sinc)
  computeAxes(plSinc);

  // Set up a legend to be displayed in addition to the polylines
  Legend legend = Legend({
    LegA.TOP_TITLE: "Example for 'smart_arrays_plot_polyline'",
    LegA.X: "45",
    LegA.Y: "15"
  }, 2);
  legend.setText("1", " 20 * sin(x)", "red");
  legend.setText("2", "100 * sin(x) / x", "blue");

  // append sinc and sine polylines and the legend to the "data area" of the layout
  dataArea.append(plSinc.polylineContainer);
  dataArea.append(plSine.polylineContainer);
  dataArea.append(legend.legendContainer);

  // append x axis, y axis and axes grid to the "plot area"  of the layout
  plotArea.append(xaxis.labelsContainer);
  plotArea.append(yaxis.labelsContainer);
  plotArea.append(xaxis.xyGrid.gridContainer);
  plotArea.append(yaxis.xyGrid.gridContainer);
}

/// These div html elements are defined in 'example.html'. [plotDiv], which is
/// embedded in [appDiv], will contain the entire graphics, taking all of the
/// remaining browser window space.
DivElement appDiv, plotDiv;

/// All graphics is drawn using SVG Scalable Vector Graphics. [plotArea] is
/// added to [plotDiv] and contains the entire plot. [dataArea] is added
/// to [plotArea] and contains the polylines and the legend. The axes are
/// drawn outside the [dataArea] but within the [plotArea].
SvgSvgElement plotArea, dataArea;

/// A frame around the 'dataArea'.
RectElement dataAreaBorder;

/// The coordinates with respect to their container
math.Rectangle<int> plotAreaRect,
    dataAreaRect,
    xaxisRect,
    yaxisRect,
    dataInsets;

/// The axes
Axis xaxis, yaxis;

/// Computes the plot layout: Sets up the graphics containers and their
/// relative coordinates and sizes.
void computeLayout() {
  // get divs from 'example.html'
  appDiv = (querySelector("#app_div") as DivElement);
  plotDiv = (querySelector("#plot_div") as DivElement);

  // the plot takes all available space
  plotDiv.style
    ..width = "${appDiv.clientWidth}px"
    ..height = "${appDiv.clientHeight}px";

  // Reserve space in pixels for the axes labels and a border around everthing.
  int xaxAreaHeight = 70, yaxAreaWidth = 80, borderAreaSize = 15;

  // will contain the entire plot
  plotAreaRect = math.Rectangle<int>(
      borderAreaSize,
      borderAreaSize,
      plotDiv.clientWidth - 2 * borderAreaSize,
      plotDiv.clientHeight - 2 * borderAreaSize);

  // all coordinates in the following rectangles are are relative to plotRect
  dataInsets = math.Rectangle<int>(borderAreaSize, borderAreaSize, 0, 0);

  // will contain the polylines and the legend
  dataAreaRect = math.Rectangle<int>(
      yaxAreaWidth,
      dataInsets.top,
      plotAreaRect.width - yaxAreaWidth - dataInsets.left,
      plotAreaRect.height - xaxAreaHeight);

  // will contain the x axis tic marks and text labels
  xaxisRect = math.Rectangle<int>(
      dataAreaRect.left,
      dataAreaRect.top + dataAreaRect.height,
      dataAreaRect.width,
      xaxAreaHeight);

  // will contain the y axis tic marks and text labels
  yaxisRect = math.Rectangle<int>(dataAreaRect.left - yaxAreaWidth,
      dataAreaRect.top, yaxAreaWidth, dataAreaRect.height);

  // will contain all axes and the data area (polylines and legend)
  plotArea = new SvgSvgElement();
  SVG.setAttr(plotArea, {
    SVG.WIDTH: "${plotAreaRect.width}",
    SVG.HEIGHT: "${plotAreaRect.height}",
  });

  // will contain polylines and legend
  dataArea = new SvgSvgElement();
  SVG.setAttr(dataArea, {
    SVG.X: "${dataAreaRect.left}",
    SVG.Y: "${dataAreaRect.top}",
    SVG.WIDTH: "${dataAreaRect.width}",
    SVG.HEIGHT: "${dataAreaRect.height}",
  });

  // a border around the data area
  dataAreaBorder = new RectElement();
  SVG.setAttr(dataAreaBorder, {
    SVG.X: "${dataAreaRect.left}",
    SVG.Y: "${dataAreaRect.top}",
    SVG.WIDTH: "${dataAreaRect.width}",
    SVG.HEIGHT: "${dataAreaRect.height}",
    SVG.FILL: "none",
    SVG.STROKE: "darkgreen",
    SVG.STROKE_WIDTH: "2"
  });

  // now stack the plot containers.
  plotDiv.append(plotArea);
  plotArea.append(dataArea);
  plotArea.append(dataAreaBorder); // draw above dataArea
} // computeLayout()

/// Computes x and y axes for [polyline]
void computeAxes(Polyline polyline) {
  // compute x axis
  xaxis = Axis.coord(
      polyline.array.length, // # points in the polyline's data array
      polyline.xValues.first, // display the array from this index
      polyline.xValues.last, // until this index
      0, // physical unit of 1st point: we choose the point number here.
      (polyline.array.length - 1).toDouble(), // phys. axis width, in points
      true, // mode for converting point index to physical unit
      null, // no extra calibration factor of axis labels
      dataAreaRect.width, // axis length in pixels
      xaxisRect.height, // height of axis area (reserves space for the labels)
      dataAreaRect.height, // grid line length, needed if 'grid' chosen
      "point number", // x axis legend text
      "bg", // axis at "b" bottom of data area, with a "g" grid, not reversed
      polyline.xphysToXscreen, // method converting physical to screen coord.
      {
        AxA.XYGRID_STROKE: "pink",
        AxA.XYGRID_STROKE_OPACITY: "1.0",
        AxA.XYGRID_STROKE_DASH: "10"
      }, // x grid color different from default
      null // no mouse or touch interaction in this example
      );

  // set the x axis container positions as computed by [computeLayout].
  SVG.setAttr(xaxis.labelsContainer, {
    SVG.X: "${xaxisRect.left - xaxis.extra_space_for_edge_labels_x}",
    SVG.Y: "${xaxisRect.top}"
  });

  // set the x axis grid container positions as computed by [computeLayout].
  SVG.setAttr(xaxis.xyGrid.gridContainer,
      {SVG.X: "${dataAreaRect.left}", SVG.Y: "${dataAreaRect.top}"});

  // compute y axis (intensity axis)
  double firstY = polyline.yScreenToYphys(0);
  double lastY = polyline.yScreenToYphys(dataAreaRect.height);
  if (firstY == null) firstY = polyline.ymin;
  if (lastY == null) lastY = polyline.ymax;
  yaxis = Axis.intens(
      firstY / polyline.yscale, // axis range, account for [PyA.YSCALE]
      lastY / polyline.yscale,
      null, // no rescaling of y axis
      null, // like above, no rescaling of y axis
      null, // would only relevant for reversed axis
      dataAreaRect.height, // axis length in pixels
      yaxisRect.width, // height of axis area (reserves space for the labels)
      dataAreaRect.width, // grid line length, needed if 'grid' chosen
      "function value",
      "bg", // "b"=position left of data area, "g"= with a grid
      polyline.yphysToYscreen, // method converting physical to screen coord.
      null, // no extra axis attributes specfied here
      null // no mouse or touch interaction in this example
      );

  // set the y axis container positions as computed by [computeLayout].
  SVG.setAttr(yaxis.labelsContainer, {
    SVG.X: "${yaxisRect.left}",
    SVG.Y: "${yaxisRect.top - yaxis.extra_space_for_edge_labels_y}"
  });

  // set the y axis grid container positions as computed by [computeLayout].
  SVG.setAttr(yaxis.xyGrid.gridContainer,
      {SVG.X: "${dataAreaRect.left}", SVG.Y: "${dataAreaRect.top}"});
}
1
likes
90
pub points
67%
popularity

Plots small or big 1D arrays in form of polylines in the browser, optionally with axes and legend text. Many configuration options of the view are provided.

Homepage

Documentation

API reference

Uploader

specpad@gmail.com

License

BSD (LICENSE)

Dependencies

build_runner, build_web_compilers, pedantic, smart_arrays_base, smart_arrays_compress

More

Packages that depend on smart_arrays_plot_polyline