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

Message ListMessage List     Post MessagePost Message

  Scatter and surface chart
Posted by Michael P on Sep-26-2017 01:09
Attachments:
Dear Peter,

I am trying to combine a surface and scatter plot. I found this suggestion in 3D
http://www.chartdir.com/forum/download_thread.php?bn=chartdir_support&pattern=surface+scatter+3d&thread=1382004235#N1468520030

but I would only need a flat view of that (from above). Is there any easier solution for that possible?

And if I use a custom colorScale for the surface chart, how can I share it with the ThreeDScatterChart?
To me it seems they use different colors scales ... see attachment. Please ignore the ill-placed color axis ;)

best regards,
Michael
surface_scatter.png

  Re: Scatter and surface chart
Posted by Peter Kwan on Sep-27-2017 00:14
Hi Michael,

If you just need a flat view, then the surface chart becomes the same as a contour chart. May be you can consider to plot your chart using an XYChart, with a contour layer and some scatter layers for the symbols.

In ChartDirector, each XY scatter layer can only have symbols of the same color. If you have less than a few hundred symbols, you may simply use one symbol per layer. In this way, every symbol can be colored differently. The color of the symbol can be obtained by using the color axis of the contour layer (use ColorAxis.getColor), so it is consistent with the contour colors.

To use the above method to draw the chart in one pass, you would need to define the color scale using ColorAxis.setColorScale. If you do not define the color scale fully (eg. let ChartDirector automatically determine the axis scale or colors), the Color.getColor cannot be used before the chart is drawn. So two pass is needed - to draw a dummy chart to get the color scale, then draw the real chart using the color scale of the dummy chart.

For the one pass method, the code is like:

.... create contour layer as usual ....

// This is an example of the color scale (cAxis = color axis of contour layer)
double colors[] = { 0, 0x0000ff, 5, 0x008080, 10, 0x00ff00, 15, 0xcccc00, 20, 0xff0000 };
cAxis->setColorScale(DoubleArray(colors, (int)(sizeof(colors) / sizeof(colors[0]))));
cAxis->setLinearScale(0, 20, 5);

// Example scatter data
int scatterPointCount = 4;
double xCoor[] = { 2, 4, 6, 7 };
double yCoor[] = { 9, 5, 2, -5 };
double zCoor[] = { 0, 5, 10, 15 };

// Add the scatter symbols
for (int i = 0; i < scatterPointCount; ++i) {
     c->addScatterLayer(DoubleArray(xCoor + i, 1), DoubleArray(yCoor + i, 1), "",
Chart::GlassSphereShape, 13, cAxis->getColor(zCoor[i]))->moveFront(layer);
}

If you have many scatter points (eg. thousands), it is better to separate the scatter points into groups of the same color. (There are usually only finite number of colors. For example, a color axis 400 pixels high cannot possibly have more than 400 colors.) You can then add each group of symbols with a scatter layer. This limits the number of scatter layers to a few hundreds.

Regards
Peter Kwan

  Re: Scatter and surface chart
Posted by Michael P on Sep-27-2017 14:46
Dear Peter,
thanks for your advice, that way is exactly what I started yesterday :)
As I have only a "small" colorscale range and probably more than 1000 scatter points I will start grouping them.

Question: I was trying to add them by "dataSet-groups" using addDataSet but that function is not taking x- and y-arrays for the scatterpoints, but it would allow setting different colors.
How can I use addDataSet(...) on an XYChart scatterlayer?

thx again,
Michael

  Re: Scatter and surface chart
Posted by Peter Kwan on Sep-27-2017 21:33
Hi Michael,

The code to the symbols into groups are actually quite simple. Basically, you can use a hash map to store the points of the same colors. It is like:


struct LayerData
{
std::vector<double> x;
std::vector<double> y;
};

// Separate into groups
std::map<int, LayerData> groups;
for (int i = 0; i < scatterPointCount; ++i) {
    LayerData &d = groups[cAxis->getColor(zCoor[i])];
    d.x.push_back(xCoor[i]);
    d.y.push_back(yCoor[i]);
}

// Draw the layers
for (std::map<int, LayerData>::iterator e = groups.begin(); e != groups.end(); ++e) {
    LayerData &d = e->second;
    c->addScatterLayer(DoubleArray(&(d.x[0]), d.x.size()), DoubleArray(&(d.y[0]), d.y.size()), "",
        Chart::GlassSphereShape, 13, e->first);
}


Note that I have removed the "moveFront" call in the scatter layer. This is not necessary if your contour layer is behind the grid lines as is in the sample code. In case the contour layer is in front, it is better to move one contour layer to the back, rather than moving thousands of scatter layers to the front.


For the data set, the original purpose of the data set is for charts that can combine data. An example is the "stacked bar chart" - the stacks are created with multiple data series stacking up. For this to work, all data sets in a layer must use the same x-coordinates. If you have independent x and y coordinates, you can just use multiple layers. (The overhead of a data set is only slightly lower than that of a layer, and it is because the data set does not have x-coordinates.)


Hope this can help.

Regards
Peter Kwan