mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 14:40:26 -05:00
Avoid pixel size for easier config across multiple environments Set default font size for plots to 10 points Use Small instead of XSmall for default font in plot Remove pt postfix to indicate point size
475 lines
14 KiB
C++
475 lines
14 KiB
C++
/*
|
|
* NightCharts
|
|
* Copyright (C) 2010 by Alexander A. Avdonin, Artem N. Ivanov / ITGears Co.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
* Please contact gordos.kund@gmail.com with any questions on this license.
|
|
*/
|
|
|
|
#define _USE_MATH_DEFINES
|
|
#include "nightcharts.h"
|
|
|
|
#include <QPainterPath>
|
|
#include <QPalette>
|
|
|
|
Nightcharts::Nightcharts()//QPainter *painter)
|
|
|
|
{
|
|
font.setFamily("verdana");
|
|
font.setPointSize(15);
|
|
//painter = painter;
|
|
//painter->setFont(font);
|
|
ctype = Nightcharts::Dpie;
|
|
cltype = Nightcharts::Vertical;
|
|
cX = 0;
|
|
cY = 0;
|
|
cW = 100;
|
|
cH = 100;
|
|
lX = cX+cW+20;
|
|
lY = cY;
|
|
shadows = true;
|
|
|
|
// NOTE: This value is accumulated, and might end up with overflow
|
|
// Was originally uninitialized, and caused overflow issues and invalid drawing when running debug
|
|
// Suggest rewrite and use locally defined aggregatedAngle (see below for usage)
|
|
palpha = 0.0;
|
|
|
|
textColor = QPalette().color(QPalette::Text);
|
|
}
|
|
|
|
Nightcharts::~Nightcharts()
|
|
{
|
|
pieces.clear();
|
|
}
|
|
|
|
int Nightcharts::addPiece(QString name,Qt::GlobalColor color,float Percentage)
|
|
{
|
|
this->nPiece++;
|
|
|
|
pieceNC piece;
|
|
piece.addName(name);
|
|
piece.setColor(color);
|
|
piece.setPerc(Percentage);
|
|
pieces.append(piece);
|
|
|
|
return 0;
|
|
}
|
|
int Nightcharts::addPiece(QString name, QColor color, float Percentage)
|
|
{
|
|
this->nPiece++;
|
|
pieceNC piece;
|
|
piece.addName(name);
|
|
piece.setColor(color);
|
|
piece.setPerc(Percentage);
|
|
pieces.append(piece);
|
|
|
|
return 0;
|
|
}
|
|
int Nightcharts::setCords(double x, double y, double w, double h)
|
|
{
|
|
this->cX = x;
|
|
this->cY = y;
|
|
this->cW = w;
|
|
this->cH = h;
|
|
this->lX = cX+cW+20;
|
|
this->lY = cY;
|
|
|
|
return 0;
|
|
}
|
|
int Nightcharts::setLegendCords(double x, double y)
|
|
{
|
|
this->lX = x;
|
|
this->lY = y;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Nightcharts::setType(Nightcharts::type t)
|
|
{
|
|
this->ctype = t;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Nightcharts::setLegendType(Nightcharts::legend_type t)
|
|
{
|
|
this->cltype = t;
|
|
|
|
return 0;
|
|
}
|
|
int Nightcharts::setFont(QFont f)
|
|
{
|
|
this->font = f;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Nightcharts::setShadows(bool ok)
|
|
{
|
|
this->shadows = ok;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Nightcharts::draw(QPainter *painter)
|
|
{
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
painter->setPen(Qt::NoPen);
|
|
if (this->ctype==Nightcharts::Pie)
|
|
{
|
|
pW = 0;
|
|
double pdegree = 0;
|
|
|
|
//Options
|
|
//QLinearGradient gradient(cX + 0.5*cW, cY, cX + 0.5*cW, cY + cH*2.5);
|
|
QRadialGradient gradient(cX + 0.5*cW, cY+0.5*cH, 0.5*cW);
|
|
gradient.setColorAt(1,Qt::black);
|
|
|
|
|
|
//Draw
|
|
//pdegree = (360/100)*pieces[i].pPerc;
|
|
if (shadows)
|
|
{
|
|
double sumangle = 0;
|
|
for (int i=0;i<pieces.size();i++)
|
|
{
|
|
sumangle += 3.6*pieces[i].pPerc;
|
|
}
|
|
painter->setBrush(Qt::darkGray);
|
|
painter->drawPie(cX,cY+pW+5,cW,cH,palpha*16,sumangle*16);
|
|
}
|
|
|
|
QPen pen;
|
|
pen.setWidth(2);
|
|
|
|
double aggregatedAngle = 0.0;
|
|
for (int i=0;i<pieces.size();i++)
|
|
{
|
|
gradient.setColorAt(0,pieces[i].rgbColor);
|
|
// Added for radial gradient
|
|
gradient.setColorAt(0.85,pieces[i].rgbColor);
|
|
gradient.setColorAt(0.95,pieces[i].rgbColor.darker(120));
|
|
gradient.setColorAt(1,pieces[i].rgbColor.darker(140));
|
|
// <--
|
|
painter->setBrush(gradient);
|
|
pen.setColor(pieces[i].rgbColor);
|
|
painter->setPen(pen);
|
|
pdegree = 3.6*pieces[i].pPerc;
|
|
painter->drawPie(cX,cY,cW,cH,aggregatedAngle*16,pdegree*16);
|
|
aggregatedAngle += pdegree;
|
|
}
|
|
}
|
|
else if (this->ctype==Nightcharts::Dpie)
|
|
{
|
|
pW = 50;
|
|
double pdegree = 0;
|
|
QPointF p;
|
|
|
|
QLinearGradient gradient(cX-0.5*cW,cY+cH/2,cX+1.5*cW,cY+cH/2);
|
|
gradient.setColorAt(0,Qt::black);
|
|
gradient.setColorAt(1,Qt::white);
|
|
QLinearGradient gradient_side(cX,cY+cH,cX+cW,cY+cH);
|
|
gradient_side.setColorAt(0,Qt::black);
|
|
|
|
double sumangle = 0;
|
|
for (int i=0;i<pieces.size();i++)
|
|
{
|
|
sumangle += 3.6*pieces[i].pPerc;
|
|
}
|
|
if (shadows)
|
|
{
|
|
painter->setBrush(Qt::darkGray);
|
|
painter->drawPie(cX,cY+pW+5,cW,cH,palpha*16,sumangle*16);
|
|
}
|
|
int q = GetQuater(palpha+sumangle);
|
|
|
|
if (q ==2 || q==3)
|
|
{
|
|
QPointF p = GetPoint(palpha+sumangle);
|
|
QPointF points[4] =
|
|
{
|
|
QPointF(p.x(),p.y()),
|
|
QPointF(p.x(),p.y()+pW),
|
|
QPointF(cX+cW/2,cY+cH/2+pW),
|
|
QPointF(cX+cW/2,cY+cH/2)
|
|
};
|
|
gradient_side.setColorAt(1,pieces[pieces.size()-1].rgbColor);
|
|
painter->setBrush(gradient_side);
|
|
painter->drawPolygon(points,4);
|
|
}
|
|
p = GetPoint(palpha);
|
|
q = GetQuater(palpha);
|
|
if (q ==1 || q==4)
|
|
{
|
|
QPointF points[4] =
|
|
{
|
|
QPointF(p.x(),p.y()),
|
|
QPointF(p.x(),p.y()+pW),
|
|
QPointF(cX+cW/2,cY+cH/2+pW),
|
|
QPointF(cX+cW/2,cY+cH/2)
|
|
};
|
|
gradient_side.setColorAt(1,pieces[0].rgbColor);
|
|
painter->setBrush(gradient_side);
|
|
painter->drawPolygon(points,4);
|
|
}
|
|
|
|
for (int i=0;i<pieces.size();i++)
|
|
{
|
|
gradient.setColorAt(0.5,pieces[i].rgbColor);
|
|
painter->setBrush(gradient);
|
|
pdegree = 3.6*pieces[i].pPerc;
|
|
painter->drawPie(cX,cY,cW,cH,palpha*16,pdegree*16);
|
|
|
|
double a_ = Angle360(palpha);
|
|
int q_ = GetQuater(palpha);
|
|
|
|
palpha += pdegree;
|
|
|
|
double a = Angle360(palpha);
|
|
int q = GetQuater(palpha);
|
|
|
|
QPainterPath path;
|
|
p = GetPoint(palpha);
|
|
|
|
if((q == 3 || q == 4) && (q_ == 3 || q_ == 4))
|
|
{
|
|
// 1)
|
|
if (a>a_)
|
|
{
|
|
QPointF p_old = GetPoint(palpha-pdegree);
|
|
path.moveTo(p_old.x()-1,p_old.y());
|
|
path.arcTo(cX,cY,cW,cH,palpha-pdegree,pdegree);
|
|
path.lineTo(p.x(),p.y()+pW);
|
|
path.arcTo(cX,cY+pW,cW,cH,palpha,-pdegree);
|
|
}
|
|
// 2)
|
|
else
|
|
{
|
|
path.moveTo(cX,cY+cH/2);
|
|
path.arcTo(cX,cY,cW,cH,180,Angle360(palpha)-180);
|
|
path.lineTo(p.x(),p.y()+pW);
|
|
path.arcTo(cX,cY+pW,cW,cH,Angle360(palpha),-Angle360(palpha)+180);
|
|
path.lineTo(cX,cY+cH/2);
|
|
|
|
path.moveTo(p.x(),p.y());
|
|
path.arcTo(cX,cY,cW,cH,palpha-pdegree,360-Angle360(palpha-pdegree));
|
|
path.lineTo(cX+cW,cY+cH/2+pW);
|
|
path.arcTo(cX,cY+pW,cW,cH,0,-360+Angle360(palpha-pdegree));
|
|
}
|
|
|
|
}
|
|
// 3)
|
|
else if((q == 3 || q == 4) && (q_ == 1 || q_ == 2) && a>a_ )
|
|
{
|
|
path.moveTo(cX,cY+cH/2);
|
|
path.arcTo(cX,cY,cW,cH,180,Angle360(palpha)-180);
|
|
path.lineTo(p.x(),p.y()+pW);
|
|
path.arcTo(cX,cY+pW,cW,cH,Angle360(palpha),-Angle360(palpha)+180);
|
|
path.lineTo(cX,cY+cH/2);
|
|
}
|
|
// 4)
|
|
else if((q == 1 || q == 2) && (q_ == 3 || q_ == 4) && a<a_)
|
|
{
|
|
p = GetPoint(palpha-pdegree);
|
|
path.moveTo(p.x(),p.y());
|
|
path.arcTo(cX,cY,cW,cH,palpha-pdegree,360-Angle360(palpha-pdegree));
|
|
path.lineTo(cX+cW,cY+cH/2+pW);
|
|
path.arcTo(cX,cY+pW,cW,cH,0,-360+Angle360(palpha-pdegree));
|
|
}
|
|
// 5)
|
|
else if((q ==1 || q==2) && (q_==1 || q_==2) && a<a_)
|
|
{
|
|
path.moveTo(cX,cY+cH/2);
|
|
path.arcTo(cX,cY,cW,cH,180,180);
|
|
path.lineTo(cX+cW,cY+cH/2+pW);
|
|
path.arcTo(cX,cY+pW,cW,cH,0,-180);
|
|
path.lineTo(cX,cY+cH/2);
|
|
}
|
|
if (!path.isEmpty())
|
|
{
|
|
gradient_side.setColorAt(1,pieces[i].rgbColor);
|
|
painter->setBrush(gradient_side);
|
|
painter->drawPath(path);
|
|
}
|
|
}
|
|
}
|
|
else if (this->ctype==Nightcharts::Histogramm)
|
|
{
|
|
double pDist = 15;
|
|
double pW = (cW-(pieces.size())*pDist)/pieces.size();
|
|
|
|
QLinearGradient gradient(cX+cW/2,cY,cX+cW/2,cY+cH);
|
|
gradient.setColorAt(0,Qt::black);
|
|
QPen pen;
|
|
pen.setWidth(3);
|
|
|
|
for (int i=0;i<pieces.size();i++)
|
|
{
|
|
if (shadows)
|
|
{
|
|
painter->setPen(Qt::NoPen);
|
|
painter->setBrush(Qt::darkGray);
|
|
painter->drawRect(cX+pDist+i*(pW + pDist)-pDist/2,cY+cH-1,pW,-cH/100*pieces[i].pPerc+pDist/2-5);
|
|
}
|
|
gradient.setColorAt(1,pieces[i].rgbColor);
|
|
painter->setBrush(gradient);
|
|
pen.setColor(pieces[i].rgbColor);
|
|
painter->setPen(pen);
|
|
painter->drawRect(cX+pDist+i*(pW + pDist),cY+cH,pW,-cH/100*pieces[i].pPerc-5);
|
|
QString label = QString::number(pieces[i].pPerc)+"%";
|
|
painter->setPen(Qt::SolidLine);
|
|
painter->drawText(cX+pDist+i*(pW + pDist)+pW/2-painter->fontMetrics().horizontalAdvance(label)/2,cY+cH-cH/100*pieces[i].pPerc-painter->fontMetrics().height()/2,label);
|
|
}
|
|
painter->setPen(Qt::SolidLine);
|
|
for (int i=1;i<10;i++)
|
|
{
|
|
painter->drawLine(cX-3,cY+cH/10*i,cX+3,cY+cH/10*i);
|
|
//painter->drawText(cX-20,cY+cH/10*i,QString::number((10-i)*10)+"%");
|
|
}
|
|
painter->drawLine(cX,cY+cH,cX,cY);
|
|
painter->drawLine(cX,cY,cX+4,cY+10);
|
|
painter->drawLine(cX,cY,cX-4,cY+10);
|
|
painter->drawLine(cX,cY+cH,cX+cW,cY+cH);
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void Nightcharts::drawLegend(QPainter *painter)
|
|
{
|
|
//double ptext = 25;
|
|
double angle = palpha;
|
|
painter->setPen(Qt::SolidLine);
|
|
painter->setPen(textColor);
|
|
|
|
switch(cltype)
|
|
{
|
|
case Nightcharts::Vertical:
|
|
{
|
|
int dist = 5;
|
|
//painter->drawRoundRect(cX+cW+20,cY,dist*2+200,pieces.size()*(painter->fontMetrics().height()+2*dist)+dist,15,15);
|
|
for (int i=pieces.size()-1;i>=0;i--)
|
|
{
|
|
painter->setBrush(pieces[i].rgbColor);
|
|
float x = lX+dist;
|
|
float y = lY+dist+i*(painter->fontMetrics().height()+2*dist);
|
|
painter->drawRect(x,y,painter->fontMetrics().height(),painter->fontMetrics().height());
|
|
painter->drawText(x+painter->fontMetrics().height()+dist,y+painter->fontMetrics().height()/2+dist,pieces[i].pname + " (" + QString::number(pieces[i].pPerc, 'd', 1)+"%)");
|
|
}
|
|
break;
|
|
}
|
|
case Nightcharts::Round:
|
|
for (int i=pieces.size()-1;i>=0;i--)
|
|
{
|
|
float len = 100;
|
|
double pdegree = 3.6*pieces[i].pPerc;
|
|
angle -= pdegree/2;
|
|
QPointF p = GetPoint(angle);
|
|
QPointF p_ = GetPoint(angle, cW+len,cH+len);
|
|
int q = GetQuater(angle);
|
|
if (q == 3 || q == 4)
|
|
{
|
|
p.setY(p.y()+pW/2);
|
|
p_.setY(p_.y()+pW/2);
|
|
}
|
|
painter->drawLine(p.x(),p.y(),p_.x(),p_.y());
|
|
QString label = pieces[i].pname + " - " + QString::number(pieces[i].pPerc)+"%";
|
|
float recW = painter->fontMetrics().horizontalAdvance(label)+10;
|
|
float recH = painter->fontMetrics().height()+10;
|
|
p_.setX(p_.x()-recW/2 + recW/2*cos(angle*M_PI/180));
|
|
p_.setY(p_.y()+recH/2 + recH/2*sin(angle*M_PI/180));
|
|
painter->setBrush(textColor);
|
|
painter->drawRect(p_.x() ,p_.y(), recW, -recH);
|
|
painter->drawText(p_.x()+5, p_.y()-recH/2+5, label);
|
|
angle -= pdegree/2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
QPointF Nightcharts::GetPoint(double angle, double R1, double R2)
|
|
{
|
|
if (R1 == 0 && R2 == 0)
|
|
{
|
|
R1 = cW;
|
|
R2 = cH;
|
|
}
|
|
QPointF point;
|
|
double x = R1/2*cos(angle*M_PI/180);
|
|
x+=cW/2+cX;
|
|
double y = -R2/2*sin(angle*M_PI/180);
|
|
y+=cH/2+cY;
|
|
point.setX(x);
|
|
point.setY(y);
|
|
return point;
|
|
}
|
|
|
|
int Nightcharts::GetQuater(double angle)
|
|
{
|
|
angle = Angle360(angle);
|
|
|
|
if(angle>=0 && angle<90)
|
|
return 1;
|
|
if(angle>=90 && angle<180)
|
|
return 2;
|
|
if(angle>=180 && angle<270)
|
|
return 3;
|
|
if(angle>=270 && angle<360)
|
|
return 4;
|
|
|
|
return 1;
|
|
}
|
|
|
|
double Nightcharts::Angle360(double angle)
|
|
{
|
|
int i = (int)angle;
|
|
double delta = angle - i;
|
|
return (i%360 + delta);
|
|
}
|
|
|
|
pieceNC::pieceNC()
|
|
{
|
|
}
|
|
void pieceNC::addName(QString name)
|
|
{
|
|
pname = name;
|
|
}
|
|
void pieceNC::setColor(Qt::GlobalColor color)
|
|
{
|
|
rgbColor = color;
|
|
}
|
|
void pieceNC::setColor(QColor color)
|
|
{
|
|
rgbColor = color;
|
|
}
|
|
|
|
void pieceNC::setPerc(float Percentage)
|
|
{
|
|
pPerc = Percentage;
|
|
}
|
|
|
|
int Nightcharts::pieceCount() const
|
|
{
|
|
return pieces.count();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Nightcharts::setTextColor(const QColor& color)
|
|
{
|
|
textColor = color;
|
|
}
|