/*------------------------------------------------------------------------------ -- 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 #include #include #include #include #include #include #include #include #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(); 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;iat(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= 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