3D Numerical Chart

The chart

The 3D charting API is built on top of JWt's 3D painting API. A chart is represented by a WCartesian3DChart, which derives from WGLWidget.

Based on the sort of data that will be shown, a chart is one of two types (the same as for 2D charts):

  • a CategoryChart for categorized data
  • a ScatterPlot for numerical data

Types of data

All data that can be shown in a 3D chart, has to derive from WAbstractDataSeries3D. Instances of this class include a model containing the actual data and all logic to draw themselves on the chart. This means all graphical features of the data (color, point size ...) are also part of this class.

JWt provides three built-in classes representing data:

  • WGridData: data lying on a grid specified by an x- and y-axis
  • WEquidistantGridData: data lying on a grid with an equidistant x- and y-axis
  • WScatterData: data containing a collection of unconstrained points

Each instance of these data series has a WAbstractItemModel backing them. The model for all these data series has to be provided as a table.
In WGridData, the table must contain one column representing the x-axis values and one row representing the y-axis values. All other values then specify the z-axis value belonging to the corresponding (x, y) pair.
The backing model for WEquidistantGridData is similar, with the difference that no x- and y-axis values are required. These can be specified directly to the class instance using setXAbscis(double XMinimum, double deltaX) and setYAbscis(double YMinimum, double deltaY).
The model for WScatterData must have three columns containing (x, y, z) values for every point.

All grid-based data has the additional feature that the visualization of the data is determined by its Series3DType, which can be either of three values:

  • PointSeries3D
  • SurfaceSeries3D
  • BarSeries3D
Note that PointSeries3D and SurfaceSeries3D only apply to a chart of type ScatterPlot and BarSeries3D only applies to a CategoryChart.

source
  void NumChart3d() {
    WContainerWidget container = new WContainerWidget();
    WCartesian3DChart chart = new WCartesian3DChart((WContainerWidget) container);
    chart.setType(ChartType.Scatter);
    chart.setRenderOptions(EnumSet.of(GLRenderOption.ClientSide, GLRenderOption.AntiAliasing));
    final WCssDecorationStyle style = new WCssDecorationStyle();
    style.setBorder(
        new WBorder(BorderStyle.Solid, BorderWidth.Medium, new WColor(StandardColor.Black)));
    chart.setDecorationStyle(style);
    chart.resize(new WLength(900), new WLength(700));
    chart.setGridEnabled(Plane.XY, Axis.X3D, true);
    chart.setGridEnabled(Plane.XY, Axis.Y3D, true);
    chart.setGridEnabled(Plane.XZ, Axis.X3D, true);
    chart.setGridEnabled(Plane.XZ, Axis.Z3D, true);
    chart.setGridEnabled(Plane.YZ, Axis.Y3D, true);
    chart.setGridEnabled(Plane.YZ, Axis.Z3D, true);
    chart.axis(Axis.X3D).setTitle("X");
    chart.axis(Axis.Y3D).setTitle("Y");
    chart.axis(Axis.Z3D).setTitle("Z");
    chart.setIntersectionLinesEnabled(true);
    chart.setIntersectionLinesColor(new WColor(0, 255, 255));
    SombreroData model1 = new SombreroData(40, 40);
    WGridData dataset1 = new WGridData(model1);
    dataset1.setType(Series3DType.Surface);
    dataset1.setSurfaceMeshEnabled(true);
    WStandardColorMap colormap =
        new WStandardColorMap(dataset1.minimum(Axis.Z3D), dataset1.maximum(Axis.Z3D), true);
    dataset1.setColorMap(colormap);
    PlaneData model2 = new PlaneData(40, 40);
    for (int i = 0; i < model2.getRowCount(); i++) {
      model2.setData(i, 0, 5, ItemDataRole.MarkerScaleFactor);
      model2.setData(i, model2.getColumnCount() - 1, 5, ItemDataRole.MarkerScaleFactor);
    }
    for (int i = 0; i < model2.getColumnCount(); i++) {
      model2.setData(0, i, 5, ItemDataRole.MarkerScaleFactor);
      model2.setData(model2.getRowCount() - 1, i, 5, ItemDataRole.MarkerScaleFactor);
    }
    for (int i = 0; i < model2.getRowCount(); i++) {
      model2.setData(i, 5, new WColor(0, 255, 0), ItemDataRole.MarkerBrushColor);
      model2.setData(i, 6, new WColor(0, 0, 255), ItemDataRole.MarkerBrushColor);
      model2.setData(i, 7, new WColor(0, 255, 0), ItemDataRole.MarkerBrushColor);
      model2.setData(i, 8, new WColor(0, 0, 255), ItemDataRole.MarkerBrushColor);
    }
    WEquidistantGridData dataset2 = new WEquidistantGridData(model2, -10, 0.5f, -10, 0.5f);
    SpiralData model3 = new SpiralData(100);
    WScatterData dataset3 = new WScatterData(model3);
    dataset3.setPointSize(5);
    HorizontalPlaneData model4 = new HorizontalPlaneData(20, 20);
    WEquidistantGridData dataset4 = new WEquidistantGridData(model4, -10, 1.0f, -10, 1.0f);
    dataset4.setType(Series3DType.Surface);
    dataset4.setSurfaceMeshEnabled(true);
    chart.addDataSeries(dataset1);
    chart.addDataSeries(dataset2);
    chart.addDataSeries(dataset3);
    chart.addDataSeries(dataset4);
    chart.setAlternativeContent(new WImage(new WLink("pics/numericalChartScreenshot.png")));
  }