ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Why is data added this way?
Posted by David Thielen on Mar-04-2021 09:18
Hi;

Ok, this is a hard question and the answer is on me. But I'm hoping you can help. I'm trying to figure out why it is calling ChartDirector this way.

First off, we convert charts in Word/Excel/PowerPoint to ChartDirector charts. So we in large degree are reading the properties in the chart1.xml file to set all the chart properties and pulling data from a database to populate the data in the chart. (The data comes from a datasource because the DOCX/PPTX/XLSX file is a template for a generated document.)

We support, as Office does, multiple chart types in a single chart, so column + line chart as well as any other legal combination. We do limit combined charts to a single axis on each side (our limitation, not Microsoft Office or ChartDirector). So left, right, top, & bottom but no 2nd axis on any side.

The X & Y values are set in very different places in the code. Also, in the midst of setting the Y values and axis below, it also sets the X axis labels (but not the data at that point).

ArrayList<BarLayer> barLayers;

// *** bar chart - 1 series ***
BarLayer layerOn;
double [] yValues;
barLayers.add(layerOn);
DataSet cdDataSet = layerOn.addDataSet(yValues);
cdDataSet.setDataName("series title");
cdDataSet.setDataColor(...);
// following two only called on first layer
firstBarLayer.setBorderColor(...);
firstBarLayer.setLegend(Chart.NoLegend);

// and now the legend out here, I assume to be able to specify the color
XYChart chart;
chart.getLegend().addKey("series title", colorSeries);

Axis xAxis, yAxis;
String[] xValsStrArr;
xAxis.setLabels(xValsStrArr);
yAxis setLinearScale(...);

// it calls this after each layer is added (probably can be called once when all are done)
for (BarLayer layerOn : barLayers)
layerOn.moveFront();

// *** line charts - 2 series ***
// this part called twice (two series)
LineLayer lineLayer;
double [] yValues;
barLayers.add(lineLayer);
DataSet cdDataSet = lineLayer.addDataSet(yValues);
cdDataSet.setDataName("series title");
cdDataSet.setDataColor(...);
// there's no firstLineLayer code???

Axis xAxis, yAxis;
String[] xValsStrArr;
xAxis.setLabels(xValsStrArr);
yAxis setLinearScale(...);

And the best I can tell, that's it. So the X values are explicitly set in the axis labels, but never in the layer with an AddDataSet(). And if the different series have different sub-sets of the X values, then can't this all get really screwed up?

And for the issues in https://www.chartdir.com/forum/download_thread.php?site=chartdir&bn=chartdir_support&thread=1614467536&new_thread=1 where you suggest calling chart.addScatterLayer(new double[] {xVals[i]}, new double[] {yVals[i]}) once per datapoint, can I do that instead of layer.addDataSet(yValues)? That will mean if I have 30 series points, I'm now creating 30 layers for my bar chart instead of 1 layer. Will they still all connect up ok? And same for the line chart?

Any help, guidance, suggestions greatly appreciated.

thanks - dave

  Re: Why is data added this way?
Posted by Peter Kwan on Mar-04-2021 13:04
Hi David,

I assume the code is written by someone else, and you are trying to understand how it works.

In many real charts, the x-coordinates can be treated as names for human reading and have no meaning to the computer. For example, the x-axis can be the names of the countries, and the y-axis be the population. The labels usually are evenly spaced along the x-axis, and the data representation (bars, points, etc) align with the labels. The chart only needs to spread the labels evenly on the x-axis, and match the bars/points etc, with the labels. No x-coordinates are necessary for positioning. The chart just puts the x-axis labels on the x-axis without interpreting what they mean.

In ChartDirector, for the above types of chart, the x-axis is configured with Axis.setLabels. The Axis.setLinearScale is not necessary and should be removed. There is no need to supply x-coordinates to the layers. The data points will match with the labels based on the array index. If there is no data for some labels, you can put Chart.NoValue in the data array.

Anything can be treated as labels, even dates, numbers, etc.. The important thing is that the labels are evenly spaced, and the data points match with the labels. Since the bars in a bar chart are usually evenly spaced, so almost all bar charts use this method.

For some charts, the data points can be anywhere and do not match with the labels. For example, for a line chart, if the x-axis are the weight of something and the y-axis their size, you may want the x-axis to be labelled as 0, 10, 20, 30, .... 100kg, but the weight data can be any value and can fall between two labels and not evenly spaced. For this type of chart, the Axis should be configured as Axis.setLinearScale, Axis.setLogScale of Axis.setDateScale (or just let ChartDirector auto-scale the axis), and Layer.setXData will be needed to provide x-coordinates for the line layer.

So if your charts can only have evenly spaced data points, the layers do not need x-coordinates. The layer can support subset of x labels by filling the empty positions with Chart.NoValue. If the layer contain points that are not aligned with the x labels (such as contains x = 14.75618 when the labels are 0, 10, 20, 30, 40), then it needs Layer.setXData. The code is like:

layer.addDataSet(yVals, ...);
layer.setXData(xVals);

In a line layer, the points are connected with lines. So a line layer needs to see all the points. The chart.addScatterLayer method suggested in my previous message adds one symbol per layer, so each layer only sees one data point. This is not applicable to a line layer which must see all data points in the same layer. Instead, the setXData method can be used. The addScatterLayer can also use setXData.

For bar layers, I suggest to put all the bars in the same layer. If you do need to provide x-coordinates, you can use Layer.setXData. In some cases, a bar layer would need to see all the bars to draw them in properly. For example, if Chart.TouchBar is used, the bar width needs to be adjusted so as to exactly touch adjacent bars, so the BarLayer needs to know where are the other bars. For 3D bars, they can overlap and needs to be rendered in proper order. An example is:

https://www.advsofteng.com/doc/cdjava.htm#softmultibar.htm

Regards
Peter Kwan

  Re: Why is data added this way?
Posted by David Thielen on Mar-05-2021 00:59
Hi Peter;

This is a giant help - thank you. I'm going to have to dive into all this now and make this work right.

One immediate question. As a line chart needs to use setXData(), how do I then set markers for a specific point in the line chart?

thanks - dave

  Re: Why is data added this way?
Posted by Peter Kwan on Mar-05-2021 03:12
Hi David,

For a line chart, using setXData is optional. If the data points are evenly spaced like a bar chart, it is common not to use x coordinates. If the data points are unevenly spaced, then you would need to use setXData to provide the x coordinates.

In my previous message, I suggest to use addScatterLayer to add a marker. In another post, I also mention the addCustomDataLabel as an alternative.

With the addScatterLayer method, if your LineLayer uses setXData(xVals), and you want to add a symbol for the point at array index N, the code is:

ScatterLayer layer = c.addScatterLayer(new double[] { xVals[N] }, new double[] { yVals[N] }, ........);

The coordinates used for the scatter layer is just the coordinates of the point in the line layer.

If your LineLayer does not have x coordinates, the array index will be used as the x coordinate, so the code becomes:

ScatterLayer layer = c.addScatterLayer(new double[] { N }, new double[] { yVals[N] }, ........);

I forgot if I have already mentioned about the following sample code, which adds different symbols to the data points of a line chart.

https://www.advsofteng.com/doc/cdjava.htm#multisymbolline.htm

The above example is suitable for many data points but only a few symbol types. It uses one scatter layer per symbol type (instead of one scatter layer per symbol).

Regards
Peter Kwan

  Re: Why is data added this way?
Posted by David Thielen on Mar-06-2021 23:30
Hi Peter;

First off you say I should not call setLinearScale(). I am calling that for the Y axis, not the X axis. Don't I need to set it for the Y axis to get the range I want?

Second, I think your example is telling me to create a line layer. And then also create a scatter layer where the purpose of the scatter layer is to render the per data point markers?

In other words, I can not do unique markers for data points in a line layer. I have to draw them separately on top of the line layer.

Third, if I add three layers in the following order:
Layer layer1 = c.addLayer();
Layer layer2 = c.addLayer();
Layer layer3 = c.addLayer();

Then layer1 will be topmost and rendered over layer2 & layer 3. And layer2 will be rendered over layer3. Is that correct?

  Re: Why is data added this way?
Posted by Peter Kwan on Mar-08-2021 23:57
Hi David,

Sorry, for the setLinearScale, I thought it was for the x-axis in which case it is unnecessary, the x-axis already has Axis.setLabels. It is OK to call it for the y-axis. If you do not call it for the y-axis, ChartDirector will auto-scale the y-axis. Sometimes people would like to determine the scale with their own code, in this case setLinearScale can be used.

For the unique symbols, the easiest method is to use scatter layers for the symbols and line layers for the lines. You just use the same data for both types of layers, so that the position of the symbols will be the same as the data points used for the line layer. We use this method is the sample code that comes with ChartDirector. If you want to logically group it into a single "layer", you can write your own function "addMyLineScatterLayer" which calls addScatterLayer and addLineLayer internally with the same data points.

If you add 3 layers, by default, the first layer will be on top, and render overs the second and third layer. You can use Layer.moveFront/Layer.moveBack to change the ordering.

https://www.advsofteng.com/doc/cdnet.htm#Layer.moveFront.htm
https://www.advsofteng.com/doc/cdnet.htm#Layer.moveBack.htm

Regards
Peter Kwan

  Re: Why is data added this way?
Posted by David Thielen on Mar-05-2021 01:01
Hi again;

Also, I have a suggestion for you. I think you should put together an "Intro to ChartDirector" and put what you wrote here, and any other answers you have posted that give this big picture view, and point people at that to start.

What you put here is super valuable to understand how to use ChartDirector.

thanks - dave