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

Message ListMessage List     Post MessagePost Message

  Data Selection on ThreeDScatter Chart
Posted by Baris E on Mar-12-2019 18:30
Hello,

I use the ThreeDScatter Chart for data visualization. And I want to highligt the data point when I clicked on it. After that I want to select multiple data points. Can you suggest a way for me?

Many thanks.

  Re: Data Selection on ThreeDScatter Chart
Posted by Peter Kwan on Mar-13-2019 03:10
Hi Baris,

There are many methods, depending on your programming language, whether it is a web or desktop application, and you exact requirements. For desktop applications, it also depends on the GUI framework (eg. MFC, Qt, Windows Forms, WPF, etc), because they have different methods of handling mouse events.

In our chart gallery, there is an example (the last chart in the following page):

https://www.advsofteng.com/gallery_map.html

In that example, the "highlighting" is simply by drawing a rectangle over the symbol, and "select multiple data points" is by clicking on multiple data points. Basically, the code handles the hot spot mouse click event. When the mouse clicks on a hot spot, it draws a rectangle over the symbol. In the link above, the drawing is by Javascript. For a desktop application, we can draw on a dynamic layer (like in the programmable track cursor sample code).

If you need further help, please inform me of the details - the programming language, web or desktop application, and the GUI framework (for desk application only).

Regards
Peter Kwan

  Re: Data Selection on ThreeDScatter Chart
Posted by Baris E on Mar-13-2019 13:08
Attachments:
Hi Peter,

Sorry for the missing information. I use C++ and Qt Framework for this project. I added a chart view below. I will try to draw a rectangle over the symbol but if you have any suggestion please share with me.

Regards
BE
Capture.PNG

  Re: Data Selection on ThreeDScatter Chart
Posted by Peter Kwan on Mar-14-2019 03:23
Attachments:
Hi Baris,

For Qt, first, create a chart with clickable symbols. You may use the sample code in the ChartDirector/qtdemo/qtdemo/qtdemo.pro for a reference. Almost all the charts, including the 3D scatter charts, in that sample code have clickable hot spots. Basically, in the "clicked" event, the code can use the ImageMapHandler to check which data point the mouse is over. Then the code can toggle a flag for the data point to mark the symbol as selected or unselected.

The "Programmable Trakc Cursor" sample programs (such as the "tracklabel" sample project) demonstrates how to draw on the dynamic layer. For your case, your code can loop through all the data points, and draw a rectangle if the data point is selected.

I have attached a simple example for your reference.

Hope this can help.

Regards
Peter Kwan
threedscatterselect.cpp
#include <QApplication>
#include "threedscatterselect.h"
#include <sstream>
#include <algorithm>
#include <assert.h>

using namespace std;


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    app.setStyleSheet("* {font-family:arial;font-size:11px}");
    ThreeDScatterSelect demo;
    demo.show();
    return app.exec();
}


ThreeDScatterSelect::ThreeDScatterSelect(QWidget *parent) :
    QDialog(parent), random(3)
{
    xData = random.getSeries(20, 100, -10, 10);
    yData = random.getSeries(20, 100, -10, 10);
    zData = random.getSeries(20, 100, -10, 10);
    selected.resize(xData.len);

    setWindowTitle("Track Line with Data Labels");

    // Create the QChartViewer and draw the chart
    m_ChartViewer = new QChartViewer(this);
    drawChart(m_ChartViewer);

    // Set the window to be of the same size as the chart
    setFixedSize(m_ChartViewer->width(), m_ChartViewer->height());

    // Set up the mouseMovePlotArea handler for drawing the track cursor
    connect(m_ChartViewer, SIGNAL(clicked(QMouseEvent*)), SLOT(onChartClicked(QMouseEvent*)));
}

ThreeDScatterSelect::~ThreeDScatterSelect()
{
    delete m_ChartViewer->getChart();
}

//
// Draw the chart and display it in the given viewer
//
void ThreeDScatterSelect::drawChart(QChartViewer *viewer)
{
    // Create a ThreeDScatterChart object of size 720 x 520 pixels
    ThreeDScatterChart *c = new ThreeDScatterChart(720, 520);

    // Add a title to the chart using 20 points Times New Roman Italic font
    c->addTitle("3D Scatter Chart (2)  ", "timesi.ttf", 20);

    // Set the center of the plot region at (350, 240), and set width x depth x height to 360 x 360
    // x 270 pixels
    c->setPlotRegion(350, 240, 360, 360, 270);

    // Set the elevation and rotation angles to 15 and 30 degrees
    c->setViewAngle(15, 30);

    // Add a scatter group to the chart using 13 pixels glass sphere symbols, in which the color
    // depends on the z value of the symbol
    ThreeDScatterGroup *g = c->addScatterGroup(xData, yData, zData, "", Chart::GlassSphere2Shape,
        13, Chart::SameAsMainColor);

    // Add grey (888888) drop lines to the symbols
    g->setDropLine(0x888888);

    // Add a color axis (the legend) in which the left center is anchored at (645, 220). Set the
    // length to 200 pixels and the labels on the right side. Use smooth gradient coloring.
    c->setColorAxis(645, 220, Chart::Left, 200, Chart::Right)->setColorGradient();

    // Set the x, y and z axis titles using 10 points Arial Bold font
    c->xAxis()->setTitle("X-Axis Place Holder", "arialbd.ttf", 10);
    c->yAxis()->setTitle("Y-Axis Place Holder", "arialbd.ttf", 10);
    c->zAxis()->setTitle("Z-Axis Place Holder", "arialbd.ttf", 10);

    // Output the chart
    viewer->setChart(c);

    // Include tool tip for the chart
    viewer->setImageMap(
        c->getHTMLImageMap("clickable", "index={dataItem}", ""));
}

void ThreeDScatterSelect::drawDynamicLayer(QChartViewer *viewer)
{
    ThreeDScatterChart *c = (ThreeDScatterChart *)viewer->getChart();
    DrawArea *d = c->initDynamicLayer();
    for (int i = 0; i < (int)selected.size(); ++i)
    {
        if (selected[i])
        {
            int x = c->getXCoor(xData[i], yData[i], zData[i]);
            int y = c->getYCoor(xData[i], yData[i], zData[i]);
            d->rect(x - 8, y - 8, x + 8, y + 8, 0x000000, Chart::Transparent, Chart::flatBorder(2));
        }
    }
    viewer->updateDisplay();
}

//
// User clicks on the QChartViewer
//
void ThreeDScatterSelect::onChartClicked(QMouseEvent * /*event*/)
{
    QChartViewer *viewer = (QChartViewer *)QObject::sender();
    ImageMapHandler *handler = viewer->getImageMapHandler();
    if (0 != handler)
    {
        // Query the ImageMapHandler to see if the mouse is on a clickable hot spot. We
        // consider the hot spot as clickable if its href ("path") parameter is not empty.
        const char *path = handler->getValue("path");
        if ((0 != path) && (0 != *path))
        {
            const char *strIndex = handler->getValue("index");
            if (0 != strIndex)
            {
                int index  = atoi(strIndex);
                selected[index] = !selected[index];
                drawDynamicLayer(viewer);
            }
        }
    }
}
threedscatterselect.h
#ifndef THREEDSCATTERSELECT_H
#define THREEDSCATTERSELECT_H

#include <QDialog>
#include "qchartviewer.h"
#include <vector>


class ThreeDScatterSelect : public QDialog {
    Q_OBJECT
public:
    ThreeDScatterSelect(QWidget *parent = 0);
    ~ThreeDScatterSelect();

private:
    RanSeries random;
    DoubleArray xData;
    DoubleArray yData;
    DoubleArray zData;
    std::vector<bool> selected;

    QChartViewer *m_ChartViewer;
    void drawChart(QChartViewer *viewer);           // Draw chart
    void drawDynamicLayer(QChartViewer *viewer);


private slots:
    void onChartClicked(QMouseEvent * /*event*/);
};

#endif // THREEDSCATTERSELECT_H

  Re: Data Selection on ThreeDScatter Chart
Posted by Baris E on Mar-22-2019 12:53
Hello Peter,

Thank you so much your answer. It works :)

Regards