colormapchart.cpp
298 lines
| 9.7 KiB
| text/x-c
|
CppLexer
|
r7 | /*------------------------------------------------------------------------------ | ||
-- 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 | ||||
----------------------------------------------------------------------------*/ | ||||
|
r0 | #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> | ||||
|
r1 | #include <QRgb> | ||
#define nbOfColors 65000 | ||||
|
r0 | |||
QT_CHARTS_BEGIN_NAMESPACE | ||||
ColorMapChart::ColorMapChart(QColorMapSeries *series, QGraphicsItem *item) | ||||
: ChartItem(series->d_func(), item), | ||||
m_series(series), | ||||
|
r1 | m_dirty(true), | ||
|
r2 | m_gradientType(Rainbow), | ||
|
r4 | m_colorbar(Q_NULLPTR), | ||
m_isColorBarDrawn(false), | ||||
|
r7 | m_currentClipRect(QRectF()) | ||
|
r0 | { | ||
// 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))); | ||||
|
r1 | connect(this,SIGNAL(gradientTypeChanged()), this, SLOT(populateColorTable())); | ||
m_colorTable = new QVector<QRgb>(); | ||||
m_colorTable->reserve(nbOfColors); | ||||
populateColorTable(); | ||||
|
r0 | } | ||
|
r4 | ColorMapChart::~ColorMapChart() | ||
{ | ||||
delete m_colorTable; | ||||
delete m_colorbar; | ||||
} | ||||
|
r0 | 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) | ||||
|
r3 | painter->save(); | ||
|
r7 | //m_series->setUseOpenGL(); | ||
|
r0 | |||
QRectF plotAreaRect = m_series->chart()->plotArea(); | ||||
|
r7 | QRectF clipRect = mapColorMapToPlotArea(); | ||
painter->setClipRect(clipRect); | ||||
|
r4 | |||
|
r7 | if(m_currentClipRect !=clipRect) | ||
{ | ||||
m_currentClipRect = clipRect; | ||||
m_grid.reserve(clipRect.width()*clipRect.height()); | ||||
m_grid.resize(clipRect.width()*clipRect.height()); | ||||
|
r5 | |||
|
r7 | 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); | ||
|
r4 | addColorBar(plotAreaRect); | ||
} | ||||
|
r7 | QImage colorMapImage(clipRect.width(),clipRect.height(),QImage::Format_RGB32); | ||
|
r0 | //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()); | ||||
|
r7 | 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) | ||||
{ | ||||
|
r0 | double maxZ = m_series->maxZ(); | ||
double minZ = m_series->minZ(); | ||||
double rangeZ = maxZ - minZ; | ||||
|
r3 | int imageWidth = colorMapImage.width(); | ||
int imageHeight = colorMapImage.height(); | ||||
for(int i=0;i<imageWidth;i++) | ||||
|
r0 | { | ||
|
r3 | for(int j=0;j<imageHeight;j++) | ||
|
r0 | { | ||
|
r5 | double value = m_grid.at(i+j*(imageWidth)); | ||
|
r0 | double pix=((value-minZ)/rangeZ); | ||
|
r1 | int indexInColorTable = pix*(nbOfColors-1); | ||
colorMapImage.setPixel(i,j,m_colorTable->at(indexInColorTable)); | ||||
|
r0 | } | ||
} | ||||
} | ||||
/*! | ||||
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; | ||||
|
r1 | case BlackAndWhite : | ||
|
r0 | gradient.setColorAt(1.0, Qt::black); | ||
gradient.setColorAt(0.0, Qt::white); | ||||
break; | ||||
|
r1 | case ReverseBlackAndWhite : | ||
gradient.setColorAt(1.0, Qt::white); | ||||
gradient.setColorAt(0.0, Qt::black); | ||||
break; | ||||
|
r0 | default: | ||
break; | ||||
} | ||||
|
r1 | 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(); | ||||
|
r0 | } | ||
|
r1 | /*! | ||
Creates a color table corresponding to the gradient type currently selected. | ||||
*/ | ||||
void ColorMapChart::populateColorTable() | ||||
{ | ||||
QLinearGradient gradient = createColorMapGradient(m_gradientType); | ||||
QGradientStops colorStops = gradient.stops(); | ||||
|
r0 | |||
|
r1 | 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())); | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||
|
r0 | |||
//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 | ||||