##// END OF EJS Templates
test parallel
test parallel

File last commit:

r6:1b9b32d0fd2e default
r6:1b9b32d0fd2e default
Show More
qcolormapseries.cpp
645 lines | 17.2 KiB | text/x-c | CppLexer
#include "qcolormapseries.h"
#include <private/qcolormapseries_p.h>
#include <private/abstractdomain_p.h>
#include <QtCharts/QValueAxis>
#include <private/colormapchart_p.h>
#include <QtCharts/QColorMapLegendMarker>
#include <private/charthelpers_p.h>
#include <private/qchart_p.h>
#include <QtGui/QPainter>
#include <cmath>
#include "omp.h"
#include "qcolorbaraxis.h"
QT_CHARTS_BEGIN_NAMESPACE
/*!
\internal
Constructs empty series object which is a child of \a parent.
When series object is added to QChart instance ownerships is transferred.
*/
QColorMapSeries::QColorMapSeries(QObject *parent)
: QAbstractSeries(*new QColorMapSeriesPrivate(this), parent)
{
}
/*!
\internal
Constructs empty series object which is a child of \a parent.
When series object is added to QChart instance ownerships is transferred.
*/
QColorMapSeries::QColorMapSeries(QColorMapSeriesPrivate &d, QObject *parent)
: QAbstractSeries(d, parent)
{
}
/*!
Destroys the object. Series added to QChart instances are owned by those,
and are destroyed when QChart instances are destroyed.
*/
QColorMapSeries::~QColorMapSeries()
{
}
/*!
\fn virtual SeriesType QBoxPlotSeries::type() const
\brief Returns type of series.
\sa QAbstractSeries, SeriesType
*/
QAbstractSeries::SeriesType QColorMapSeries::type() const
{
return QAbstractSeries::SeriesTypeColorMap;
}
/*!
Adds data part \a dataPart to the series.\n
If \a copy is true, adds a copy of the data part instead.
*/
void QColorMapSeries::append(ColorMapDataPart* dataPart, bool copy)
{
Q_D(QColorMapSeries);
if(copy)
d->m_dataParts << new ColorMapDataPart(dataPart);
else
d->m_dataParts << dataPart;
d->recomputeDataRange();
emit dataPartAdded(d->m_dataParts.count() - 1);
}
/*!
This is an overloaded function.\n
Adds data parts \a dataParts to the series.\n
If \a copy is true, adds a copy of the data part instead.
*/
void QColorMapSeries::append(const QList<ColorMapDataPart*> &dataParts, bool copy)
{
foreach (ColorMapDataPart* dataPart , dataParts)
append(dataPart,copy);
}
/*!
Returns number of data parts within series.
*/
int QColorMapSeries::count() const
{
Q_D(const QColorMapSeries);
return d->m_dataParts.count();
}
/*!
Stream operator for adding a data part \a point to the series.
\sa append()
*/
QColorMapSeries &QColorMapSeries::operator <<(const ColorMapDataPart &dataPart)
{
append(new ColorMapDataPart(dataPart));
return *this;
}
/*!
Stream operator for adding a vector of data parts \a dataParts to the series.
\sa append()
*/
QColorMapSeries &QColorMapSeries::operator <<(const QList<ColorMapDataPart*> &dataParts)
{
append(dataParts);
return *this;
}
/*!
Returns a ColorMapData part containing a uniform grid of data points to be mapped in a ColorMapChart.\n
The rectangle of data returned is determined by \a width and \height,\n
from the position \a xpos , \a ypos (starting at the top left corner of the plot area).\n
When there are more points than pixels, \a strategy is applied to determine which to choose.
*/
void QColorMapSeries::getUniformGrid(int xpos, int ypos,int width, int height, QVector<double> &grid, QColorMapSeries::Strategy strategy)
{
Q_D(QColorMapSeries);
d->getUniformGrid(xpos, ypos,width,height, grid, strategy);
}
//void QColorMapSeries::attachAxis(QAbstractAxis *axis)
//{
// axis = static_cast<QColorBarAxis*>();
// if(axis)
// {
// }
// else
// {
// QAbstractSeries::attachAxis(axis);
// }
//}
/*!
Sets \a pen used for drawing points on the chart. If the pen is not defined, the
pen from chart theme is used.
\sa QChart::setTheme()
*/
void QColorMapSeries::setPen(const QPen &pen)
{
Q_D(QColorMapSeries);
if (d->m_pen != pen)
{
//bool emitColorChanged = d->m_pen.color() != pen.color();
d->m_pen = pen;
emit d->updated();
// if (emitColorChanged)
// emit colorChanged(pen.color());
emit penChanged(pen);
}
}
QPen QColorMapSeries::pen() const
{
Q_D(const QColorMapSeries);
if (d->m_pen == QChartPrivate::defaultPen())
return QPen();
else
return d->m_pen;
}
/*!
Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
from chart theme setting is used.
\sa QChart::setTheme()
*/
void QColorMapSeries::setBrush(const QBrush &brush)
{
Q_D(QColorMapSeries);
if (d->m_brush != brush)
{
d->m_brush = brush;
emit d->updated();
}
}
QBrush QColorMapSeries::brush() const
{
Q_D(const QColorMapSeries);
if (d->m_brush == QChartPrivate::defaultBrush())
return QBrush();
else
return d->m_brush;
}
//void QColorMapSeries::setColor(const QColor &color)
//{
// QPen p = pen();
// if (p.color() != color)
// {
// p.setColor(color);
// setPen(p);
// }
//}
//QColor QColorMapSeries::color() const
//{
// return pen().color();
//}
//void QColorMapSeries::setPointsVisible(bool visible)
//{
// Q_D(QColorMapSeries);
// if (d->m_pointsVisible != visible)
// {
// d->m_pointsVisible = visible;
// emit d->updated();
// }
//}
//bool QColorMapSeries::pointsVisible() const
//{
// Q_D(const QColorMapSeries);
// return d->m_pointsVisible;
//}
//void QColorMapSeries::setPointLabelsFormat(const QString &format)
//{
// Q_D(QColorMapSeries);
// if (d->m_pointLabelsFormat != format)
// {
// d->m_pointLabelsFormat = format;
// emit pointLabelsFormatChanged(format);
// }
//}
//QString QColorMapSeries::pointLabelsFormat() const
//{
// Q_D(const QColorMapSeries);
// return d->m_pointLabelsFormat;
//}
//void QColorMapSeries::setPointLabelsVisible(bool visible)
//{
// Q_D(QColorMapSeries);
// if (d->m_pointLabelsVisible != visible)
// {
// d->m_pointLabelsVisible = visible;
// emit pointLabelsVisibilityChanged(visible);
// }
//}
//bool QColorMapSeries::pointLabelsVisible() const
//{
// Q_D(const QColorMapSeries);
// return d->m_pointLabelsVisible;
//}
//void QColorMapSeries::setPointLabelsFont(const QFont &font)
//{
// Q_D(QColorMapSeries);
// if (d->m_pointLabelsFont != font) {
// d->m_pointLabelsFont = font;
// emit pointLabelsFontChanged(font);
// }
//}
//QFont QColorMapSeries::pointLabelsFont() const
//{
// Q_D(const QColorMapSeries);
// return d->m_pointLabelsFont;
//}
//void QColorMapSeries::setPointLabelsColor(const QColor &color)
//{
// Q_D(QColorMapSeries);
// if (d->m_pointLabelsColor != color) {
// d->m_pointLabelsColor = color;
// emit pointLabelsColorChanged(color);
// }
//}
//QColor QColorMapSeries::pointLabelsColor() const
//{
// Q_D(const QColorMapSeries);
// if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
// return QPen().color();
// else
// return d->m_pointLabelsColor;
//}
//void QColorMapSeries::setPointLabelsClipping(bool enabled)
//{
// Q_D(QColorMapSeries);
// if (d->m_pointLabelsClipping != enabled) {
// d->m_pointLabelsClipping = enabled;
// emit pointLabelsClippingChanged(enabled);
// }
//}
//bool QColorMapSeries::pointLabelsClipping() const
//{
// Q_D(const QColorMapSeries);
// return d->m_pointLabelsClipping;
//}
/*!
Returns the minimum value of the series on the X axis.
*/
double QColorMapSeries::minX()
{
Q_D(QColorMapSeries);
return d->m_minX;
}
/*!
Returns the minimum value of the series on the Y axis.
*/
double QColorMapSeries::minY()
{
Q_D(QColorMapSeries);
return d->m_minY;
}
/*!
Returns the minimum value of the series on the Z axis.
*/
double QColorMapSeries::minZ()
{
Q_D(QColorMapSeries);
return d->m_minZ;
}
/*!
Returns the maximum value of the series on the X axis.
*/
double QColorMapSeries::maxX()
{
Q_D(QColorMapSeries);
return d->m_maxX;
}
/*!
Returns the maximum value of the series on the Y axis.
*/
double QColorMapSeries::maxY()
{
Q_D(QColorMapSeries);
return d->m_maxY;
}
/*!
Returns the maximum value of the series on the Z axis.
*/
double QColorMapSeries::maxZ()
{
Q_D(QColorMapSeries);
return d->m_maxZ;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
QColorMapSeriesPrivate::QColorMapSeriesPrivate(QColorMapSeries *q)
: QAbstractSeriesPrivate(q),
m_pen(QChartPrivate::defaultPen()),
m_brush(QChartPrivate::defaultBrush()),
m_pointsVisible(false),
m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")), //TODO : change
m_pointLabelsVisible(false),
m_pointLabelsFont(QChartPrivate::defaultFont()),
m_pointLabelsColor(QChartPrivate::defaultPen().color()),
m_pointLabelsClipping(true)
{
}
void QColorMapSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
{
Q_Q(QColorMapSeries);
ColorMapChart *colormap = new ColorMapChart(q,parent);
m_item.reset(colormap);
QAbstractSeriesPrivate::initializeGraphics(parent);
}
void QColorMapSeriesPrivate::initializeDomain()
{
domain()->setRange(m_minX, m_maxX, m_minY, m_maxY);
}
void QColorMapSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
{
// Q_Q(QColorMapSeries);
// const QList<QGradient> gradients = theme->seriesGradients();
// const QList<QColor> colors = theme->seriesColors();
// if (forced || QChartPrivate::defaultPen() == m_pen) {
// QPen pen;
// pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0));
// pen.setWidthF(2);
// q->setPen(pen);
// }
// if (forced || QChartPrivate::defaultBrush() == m_brush) {
// QBrush brush(colors.at(index % colors.size()));
// q->setBrush(brush);
// }
// if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
// QColor color = theme->labelBrush().color();
// q->setPointLabelsColor(color);
// }
}
QList<QLegendMarker*> QColorMapSeriesPrivate::createLegendMarkers(QLegend* legend)
{
Q_Q(QColorMapSeries);
QList<QLegendMarker*> list;
return list << new QColorMapLegendMarker(q,legend);
}
void QColorMapSeriesPrivate::initializeAxes()
{
}
QAbstractAxis::AxisType QColorMapSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
{
Q_UNUSED(orientation);
return QAbstractAxis::AxisTypeValue;
}
QAbstractAxis* QColorMapSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
{
Q_UNUSED(orientation);
return new QValueAxis;
}
void QColorMapSeriesPrivate::getUniformGrid(int xpos, int ypos, int width, int height, QVector<double> &grid, QColorMapSeries::Strategy strategy)
{
double dx = (m_maxX - m_minX)/(double)width;
double dy = (m_maxY - m_minY)/(double)height;
int index=0;
QVector<Point3D> cluster;
cluster.reserve(height*width/1000);
int x = 0;
int y = 0;
for (auto cell= grid.begin();cell<grid.end();++cell)
{
x = index%width;
y = index/width;
cluster.resize(0);
this->buildCluster(x,y,dx,dy,cluster);
if(strategy == QColorMapSeries::LastPixel)
*cell=this->clusterStrategyLast(cluster);
else if(strategy == QColorMapSeries::MeanPixel)
*cell=this->clusterStrategyMean(cluster);
else if(strategy == QColorMapSeries::MedianPixel)
*cell=this->clusterStrategyMedian(cluster);
index++;
}
//#pragma omp for
// for(int y = 0;y<height;y++)
// {
// for(int x =0;x<width;x++)
// {
// cluster.resize(0);
// this->buildCluster(x,y,dx,dy,cluster);
// if(strategy == QColorMapSeries::LastPixel)
// grid[width*y+x] = this->clusterStrategyLast(cluster);
// else if(strategy == QColorMapSeries::MeanPixel)
// grid[width*y+x] = this->clusterStrategyMean(cluster);
// else if(strategy == QColorMapSeries::MedianPixel)
// grid[width*y+x] = this->clusterStrategyMedian(cluster);
// }
// }
}
double QColorMapSeriesPrivate::computeValuePixel()
{
}
/*!
Recompute the data range on X, Y and Z axes each time a ColorMapDataPart is added to the series.\n
The minimum distance between 2 adjacent values on X and Y axis is added to the maximum on X and Y respectively\n
in order to take account of the width of the last element.
*/
void QColorMapSeriesPrivate::recomputeDataRange()
{
//TODO : if non empty
m_minX = m_dataParts.first()->timesSeries().first();
m_maxX = m_dataParts.last()->timesSeries().last();
m_minY = m_dataParts.last()->ySeries().last();
m_maxY = m_dataParts.last()->ySeries().first();
m_minZ = m_dataParts.first()->dataSeries().first();
m_maxZ = m_dataParts.last()->dataSeries().last();
double minDeltaX=m_maxX-m_minX;
double minDeltaY=m_minY-m_maxY;
foreach(ColorMapDataPart* datapart, m_dataParts)
{
m_minY = qMin(datapart->ySeries().first(),m_minY);
m_maxY = qMax(datapart->ySeries().last(),m_maxY);
for(int i=1;i<datapart->timesSeries().size();i++)
{
double newDeltaX=datapart->timesSeries()[i]-datapart->timesSeries()[i-1];
minDeltaX=qMin(minDeltaX,newDeltaX);
}
for(int i=1;i<datapart->ySeries().size();i++)
{
double newDeltaY=datapart->ySeries()[i]-datapart->ySeries()[i-1];
minDeltaY=qMin(minDeltaY,newDeltaY);
}
for (int i = 0; i < datapart->dataSeries().count(); i++)
{
double z = datapart->dataSeries().at(i);
m_minZ = qMin(m_minZ, z);
m_maxZ = qMax(m_maxZ, z);
}
}
m_maxX+=minDeltaX;
m_maxY+=minDeltaY;
}
/*!
Returns the last value (bottom right Z value) of a \a cluster of points passed as argument.
*/
double QColorMapSeriesPrivate::clusterStrategyLast(QVector<Point3D>& cluster)
{
if(!cluster.isEmpty())
return cluster.last().value();
return 0;
}
/*!
Returns the mean value (mean Z value) of a \a cluster of points passed as argument.
*/
double QColorMapSeriesPrivate::clusterStrategyMean(QVector<Point3D>& cluster)
{
if(!cluster.isEmpty())
{
double sum=0;
int count =0;
for(int i =0;i<cluster.size();i++)
{
if(!isnan(Point3D(cluster.at(i)).value()))
{
sum+= Point3D(cluster.at(i)).value();
count++;
}
}
return (sum/count);
}
return 0;
}
/*!
Returns the median value (median Z value) of a \a cluster of points passed as argument.
*/
double QColorMapSeriesPrivate::clusterStrategyMedian(QVector<Point3D>& cluster)
{
if(!cluster.isEmpty())
{
QVector<double> *copy = new QVector<double>();
for(int i =0;i<cluster.size();i++)
{
if(!isnan(Point3D(cluster.at(i)).value()))
copy->append(Point3D(cluster.at(i)).value());
}
if(!copy->isEmpty())
{
std::sort(copy->begin(), copy->end());
if(copy->count() & 1) // odd
{
int middle = (copy->count()+1)/2;
return copy->at(middle-1);
}
else //even
{
int middle = copy->count()/2;
return (copy->at(middle-1)+copy->at(middle))/2;
}
}
}
return 0;
}
/*!
Computes which data points correspond to the given position and returns the in a \a cluster.
*/
void QColorMapSeriesPrivate::buildCluster(int xpos, int ypos, double dx, double dy, QVector<Point3D>& cluster)
{
foreach(ColorMapDataPart *dataPart, m_dataParts)
{
QPair<int,int> xRange = dataPart->getRange(dataPart->timesSeries(),m_minX+xpos*dx,m_minX+(xpos+1)*dx);
QPair<int,int> yRange = dataPart->getRange(dataPart->ySeries(),m_maxY-(ypos+1)*dy,m_maxY-ypos*dy);
int timeSeriesSize = dataPart->timesSeries().size();
if(xRange.first != xRange.second && yRange.first != yRange.second)
{
for(int i =xRange.first+1;i<xRange.second;i++)
{
qreal xval=dataPart->timesSeries()[i];
for(int j=yRange.first+1;j<yRange.second;j++)
{
qreal yval=dataPart->ySeries()[j];
qreal val=dataPart->dataSeries()[ i + (timeSeriesSize * j)];
cluster.append(Point3D(xval,yval,val));
}
}
}
}
}
void QColorMapSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options,
int duration, QEasingCurve &curve)
{
// ColorMapChart *item = static_cast<ColorMapChart *>(m_item.data());
// Q_ASSERT(item);
// if (item->animation())
// item->animation()->stopAndDestroyLater();
// if (options.testFlag(QChart::SeriesAnimations))
// item->setAnimation(new XYAnimation(item, duration, curve));
// else
// item->setAnimation(0);
QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
}
#include "moc_qcolormapseries.cpp"
#include "moc_qcolormapseries_p.cpp"
QT_CHARTS_END_NAMESPACE