|
|
/*------------------------------------------------------------------------------
|
|
|
-- This file is a part of the ColorMapChart API
|
|
|
-- Copyright (C) 2016, Plasma Physics Laboratory - CNRS
|
|
|
--
|
|
|
-- This program is free software; you can redistribute it and/or modify
|
|
|
-- it under the terms of the GNU General Public License as published by
|
|
|
-- the Free Software Foundation; either version 2 of the License, or
|
|
|
-- (at your option) any later version.
|
|
|
--
|
|
|
-- This program is distributed in the hope that it will be useful,
|
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-- GNU General Public License for more details.
|
|
|
--
|
|
|
-- You should have received a copy of the GNU General Public License
|
|
|
-- along with this program; if not, write to the Free Software
|
|
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
-------------------------------------------------------------------------------*/
|
|
|
/*-- Author : Hugo Winter
|
|
|
-- Mail : hugo.winter@lpp.polytechnique.fr
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
|
|
#include <private/colormapchart_p.h>
|
|
|
#include <QtCharts/QColorMapSeries>
|
|
|
#include <private/qcolormapseries_p.h>
|
|
|
#include <private/chartpresenter_p.h>
|
|
|
#include <private/abstractdomain_p.h>
|
|
|
#include <private/chartdataset_p.h>
|
|
|
#include <private/qabstractaxis_p.h>
|
|
|
#include <QtGui/QPainter>
|
|
|
|
|
|
#include <QRgb>
|
|
|
|
|
|
#define nbOfColors 65000
|
|
|
|
|
|
QT_CHARTS_BEGIN_NAMESPACE
|
|
|
|
|
|
ColorMapChart::ColorMapChart(QColorMapSeries *series, QGraphicsItem *item)
|
|
|
: ChartItem(series->d_func(), item),
|
|
|
m_series(series),
|
|
|
m_dirty(true),
|
|
|
m_gradientType(Rainbow),
|
|
|
m_colorbar(Q_NULLPTR),
|
|
|
m_isColorBarDrawn(false),
|
|
|
m_currentClipRect(QRectF())
|
|
|
{
|
|
|
// QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
|
|
|
// QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
|
|
|
// QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
|
|
|
// QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
|
|
|
// QObject::connect(series, SIGNAL(pointsRemoved(int, int)), this, SLOT(handlePointsRemoved(int, int)));
|
|
|
// QObject::connect(this, SIGNAL(clicked(Point3D)), series, SIGNAL(clicked(Point3D)));
|
|
|
// QObject::connect(this, SIGNAL(hovered(Point3D,bool)), series, SIGNAL(hovered(Point3D,bool)));
|
|
|
// QObject::connect(this, SIGNAL(pressed(Point3D)), series, SIGNAL(pressed(Point3D)));
|
|
|
// QObject::connect(this, SIGNAL(released(Point3D)), series, SIGNAL(released(Point3D)));
|
|
|
// QObject::connect(this, SIGNAL(doubleClicked(Point3D)), series, SIGNAL(doubleClicked(Point3D)));
|
|
|
|
|
|
connect(this,SIGNAL(gradientTypeChanged()), this, SLOT(populateColorTable()));
|
|
|
|
|
|
m_colorTable = new QVector<QRgb>();
|
|
|
m_colorTable->reserve(nbOfColors);
|
|
|
populateColorTable();
|
|
|
}
|
|
|
|
|
|
ColorMapChart::~ColorMapChart()
|
|
|
{
|
|
|
delete m_colorTable;
|
|
|
delete m_colorbar;
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::setDirty(bool dirty)
|
|
|
{
|
|
|
m_dirty = dirty;
|
|
|
}
|
|
|
|
|
|
QRectF ColorMapChart::boundingRect() const
|
|
|
{
|
|
|
return m_rect;
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
|
{
|
|
|
Q_UNUSED(widget)
|
|
|
Q_UNUSED(option)
|
|
|
|
|
|
painter->save();
|
|
|
//m_series->setUseOpenGL();
|
|
|
|
|
|
QRectF plotAreaRect = m_series->chart()->plotArea();
|
|
|
QRectF clipRect = mapColorMapToPlotArea();
|
|
|
painter->setClipRect(clipRect);
|
|
|
|
|
|
if(m_currentClipRect !=clipRect)
|
|
|
{
|
|
|
m_currentClipRect = clipRect;
|
|
|
m_grid.reserve(clipRect.width()*clipRect.height());
|
|
|
m_grid.resize(clipRect.width()*clipRect.height());
|
|
|
|
|
|
m_series->getUniformGrid(qMax(m_series->minX(),domain()->minX()),qMin(m_series->maxX(),domain()->maxX()),qMax(m_series->minY(),domain()->minY()),qMin(m_series->maxY(),domain()->maxY()), clipRect.width(),clipRect.height(),m_grid, QColorMapSeries::LastPixel);
|
|
|
addColorBar(plotAreaRect);
|
|
|
}
|
|
|
|
|
|
QImage colorMapImage(clipRect.width(),clipRect.height(),QImage::Format_RGB32);
|
|
|
//http://doc.qt.io/qt-4.8/qimage.html#details :Warning: This will create a QImage with uninitialized data. Call fill() to fill the image with an appropriate pixel value before drawing onto it with QPainter.
|
|
|
colorMapImage.fill(QColor(Qt::white).rgb());
|
|
|
|
|
|
fillColorMapImage(colorMapImage);
|
|
|
|
|
|
painter->drawImage(clipRect,colorMapImage);
|
|
|
painter->restore();
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::addColorBar(QRectF plotAreaRect)
|
|
|
{
|
|
|
double maxZ = m_series->maxZ();
|
|
|
double minZ = m_series->minZ();
|
|
|
|
|
|
if(m_isColorBarDrawn)
|
|
|
m_series->chart()->removeAxis(m_colorbar);
|
|
|
|
|
|
m_colorbar = new QColorBarAxis(plotAreaRect,createColorMapGradient(m_gradientType),minZ, maxZ,this);
|
|
|
m_series->chart()->addAxis(m_colorbar, Qt::AlignRight);
|
|
|
m_isColorBarDrawn = true;
|
|
|
}
|
|
|
|
|
|
QRectF ColorMapChart::mapColorMapToPlotArea()
|
|
|
{
|
|
|
QRectF plotAreaRect = m_series->chart()->plotArea();
|
|
|
|
|
|
double seriesMinX = m_series->minX();
|
|
|
double seriesMaxX = m_series->maxX();
|
|
|
double seriesMinY = m_series->minY();
|
|
|
double seriesMaxY = m_series->maxY();
|
|
|
|
|
|
double domainMinX = domain()->minX();
|
|
|
double domainMaxX = domain()->maxX();
|
|
|
double domainMinY = domain()->minY();
|
|
|
double domainMaxY = domain()->maxY();
|
|
|
|
|
|
double widthToPaint = (qMin(seriesMaxX, domainMaxX)-qMax(seriesMinX, domainMinX))*plotAreaRect.width()/(domainMaxX-domainMinX);
|
|
|
double heightTopaint= (qMin(seriesMaxY, domainMaxY)-qMax(seriesMinY, domainMinY))*plotAreaRect.height()/(domainMaxY-domainMinY);
|
|
|
|
|
|
QSizeF size = QSize(widthToPaint,heightTopaint);
|
|
|
|
|
|
double pointX = (qMax(seriesMinX,domainMinX)-domainMinX)*plotAreaRect.width()/(domainMaxX-domainMinX);
|
|
|
double pointY = (domainMaxY-qMin(seriesMaxY,domainMaxY))*plotAreaRect.height()/(domainMaxY-domainMinY);
|
|
|
|
|
|
return QRectF(QPointF(pointX,pointY) ,size);
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::fillColorMapImage(QImage &colorMapImage)
|
|
|
{
|
|
|
double maxZ = m_series->maxZ();
|
|
|
double minZ = m_series->minZ();
|
|
|
double rangeZ = maxZ - minZ;
|
|
|
|
|
|
int imageWidth = colorMapImage.width();
|
|
|
int imageHeight = colorMapImage.height();
|
|
|
|
|
|
for(int i=0;i<imageWidth;i++)
|
|
|
{
|
|
|
for(int j=0;j<imageHeight;j++)
|
|
|
{
|
|
|
double value = m_grid.at(i+j*(imageWidth));
|
|
|
double pix=((value-minZ)/rangeZ);
|
|
|
int indexInColorTable = pix*(nbOfColors-1);
|
|
|
colorMapImage.setPixel(i,j,m_colorTable->at(indexInColorTable));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*!
|
|
|
Returns the predefined QLinearGradient corresponding to the \a gradientType passed as argument.
|
|
|
*/
|
|
|
QLinearGradient ColorMapChart::createColorMapGradient(GradientType gradientType)
|
|
|
{
|
|
|
QLinearGradient gradient(0,0,1,100);
|
|
|
switch(gradientType)
|
|
|
{
|
|
|
case Rainbow :
|
|
|
gradient.setColorAt(1.0,Qt::darkRed);
|
|
|
gradient.setColorAt(0.8,Qt::red);
|
|
|
gradient.setColorAt(0.6,Qt::yellow);
|
|
|
gradient.setColorAt(0.4,Qt::green);
|
|
|
gradient.setColorAt(0.2,Qt::cyan);
|
|
|
gradient.setColorAt(0.0,Qt::blue);
|
|
|
break;
|
|
|
case CyclingRainbow :
|
|
|
gradient.setColorAt(1.0,Qt::red);
|
|
|
gradient.setColorAt(0.8,Qt::yellow);
|
|
|
gradient.setColorAt(0.6,Qt::green);
|
|
|
gradient.setColorAt(0.4,Qt::cyan);
|
|
|
gradient.setColorAt(0.2,Qt::blue);
|
|
|
gradient.setColorAt(0.0,Qt::magenta);
|
|
|
break;
|
|
|
case BlackAndWhite :
|
|
|
gradient.setColorAt(1.0, Qt::black);
|
|
|
gradient.setColorAt(0.0, Qt::white);
|
|
|
break;
|
|
|
case ReverseBlackAndWhite :
|
|
|
gradient.setColorAt(1.0, Qt::white);
|
|
|
gradient.setColorAt(0.0, Qt::black);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
return gradient;
|
|
|
}
|
|
|
|
|
|
/*!
|
|
|
Changes the type of gradient used to paint the ColorMap.
|
|
|
*/
|
|
|
void ColorMapChart::changeGradient(GradientType gradientType)
|
|
|
{
|
|
|
if(m_gradientType == gradientType)
|
|
|
return;
|
|
|
else
|
|
|
m_gradientType = gradientType;
|
|
|
emit gradientTypeChanged();
|
|
|
}
|
|
|
|
|
|
/*!
|
|
|
Creates a color table corresponding to the gradient type currently selected.
|
|
|
*/
|
|
|
void ColorMapChart::populateColorTable()
|
|
|
{
|
|
|
QLinearGradient gradient = createColorMapGradient(m_gradientType);
|
|
|
QGradientStops colorStops = gradient.stops();
|
|
|
|
|
|
for(int i=0;i<nbOfColors;i++)
|
|
|
{
|
|
|
double colorIndex = (double)i/nbOfColors;
|
|
|
for(int k =0;k<colorStops.size()-1;k++)
|
|
|
{
|
|
|
QGradientStop lowerBound = colorStops.at(k);
|
|
|
QGradientStop upperBound = colorStops.at(k+1);
|
|
|
if(colorIndex >= lowerBound.first && colorIndex < upperBound.first)
|
|
|
{
|
|
|
double ratio = (colorIndex-lowerBound.first)/(upperBound.first - lowerBound.first);
|
|
|
int red = (int)((1-ratio)*lowerBound.second.red() + ratio*upperBound.second.red());
|
|
|
int green = (int)((1-ratio)*lowerBound.second.green() + ratio*upperBound.second.green());
|
|
|
int blue = (int)((1-ratio)*lowerBound.second.blue() + ratio*upperBound.second.blue());
|
|
|
m_colorTable->append(qRgb(red, green, blue));
|
|
|
break;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(k==colorStops.size()-2)
|
|
|
{
|
|
|
m_colorTable->append(qRgb(colorStops.at(colorStops.size()-1).second.red(), colorStops.at(colorStops.size()-1).second.green(), colorStops.at(colorStops.size()-1).second.blue()));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
//handlers
|
|
|
|
|
|
void ColorMapChart::handlePointAdded(int index)
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::handlePointRemoved(int index)
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::handlePointsRemoved(int index, int count)
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::handlePointReplaced(int index)
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::handlePointsReplaced()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
void ColorMapChart::handleDomainUpdated()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
bool ColorMapChart::isEmpty()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
#include "moc_colormapchart_p.cpp"
|
|
|
|
|
|
QT_CHARTS_END_NAMESPACE
|
|
|
|