#include "Qiankunmap.h"
#include <QtDebug>
#include <QPainter>
#include <QPainterPath>
#include <QStaticText>
#include <QHoverEvent>
#include <QTimer>
#include <cmath>
static auto angle_8_1 = 360.0 / 8.0;
static auto angle_24_1 = 360.0 / 24.0;
static auto angle_32_1 = 360.0 / 32.0;
//渐变背景颜色结构体
typedef struct GRADIENTCOLOR_DATAS_{
double fBkgndAngleVal; //渐变背景角度从0到1
QColor cBkgndAngleClr; //渐变背景当前角度颜色
}GRADIENTCOLOR_DATAS,*PGRADIENTCOLOR_DATAS;
static QList<std::u16string> sTianGanChar ={u"乾",u"巽",u"坎",u"艮",u"坤",u"震",u"离",u"兑"};
static QList<std::u16string> sSolarsTerms={u"冬至",u"小寒",u"大寒",u"立春",u"雨水",u"惊蛰",u"春分",u"清明",u"谷雨",u"立夏",u"小满",u"芒种",
u"夏至",u"小暑",u"大暑",u"立秋",u"处暑",u"白露",u"秋分",u"寒露",u"霜降",u"立冬",u"小雪",u"大雪"};
static QList<std::u16string> sElementsTwo={u"丙丁火",u"已坤土",u"庚辛金",u"乾阳金",u"壬癸水",u"戊艮土",u"甲乙木",u"巽风木"};
static QList<std::u16string> sElementsOne={u"午火",u"未土",u"申金",u"酉金",u"戌土",u"亥水",u"子水",u"丑土",u"寅木",u"卯木",u"辰土",u"巳水"};
static QList<std::u16string> sTianGanDiz={u"子",u"壬",u"丑",u"癸",u"寅",u"艮",u"卯",u"甲",u"辰",u"乙",u"巳",u"巽",u"午",u"丙",u"未",u"丁",u"申",u"坤",u"酉",u"庚",u"戌",u"辛",u"亥",u"乾"};
static QList<GRADIENTCOLOR_DATAS> vBkgColorsList = {{0, QColor(35, 40, 3, 255)},{0.16, QColor(136, 106, 22, 255)},{0.225, QColor(166, 140, 41, 255)},
{0.285, QColor(204, 181, 74, 255)},{0.345, QColor(235, 219, 102, 255)},{0.415, QColor(245, 236, 112, 255)},
{0.52, QColor(209, 190, 76, 255)},{0.57, QColor(187, 156, 51, 255)},{0.635, QColor(168, 142, 42, 255)},
{0.695, QColor(202, 174, 68, 255)},{0.75, QColor(218, 202, 86, 255)},{0.815, QColor(208, 187, 73, 255)},
{0.88, QColor(187, 156, 51, 255)},{0.935, QColor(137, 108, 26, 255)},{1, QColor(35, 40, 3, 255)}}; //渐变背景颜色集合
Qiankunmap::Qiankunmap(QWidget *parent)
: QWidget(parent)
{
resize(600, 600);
timer_ = new QTimer(this);
connect(timer_, &QTimer::timeout, this, &Qiankunmap::onTimer);
timer_->start(30);
}
void Qiankunmap::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter painter(this);
painter.fillRect(rect(), Qt::white);
painter.setRenderHints(QPainter::Antialiasing);
// 移动当前的坐标系到绘制的中心,这样便于坐标计算
painter.translate(QPointF(width()/ 2.0 , height() / 2.0));
auto radius = std::min(this->width(), this->height()) / 2.0;
// 从外层到内的圆环占据整个绘制的比例
auto radius_1 = radius * (300.0 - 10.000) / 300.0;
auto radius_2 = radius * (300.0 - 60.00) / 300.0;
auto radius_3 = radius * (300.0 - 120.0) / 300.0;
auto radius_4 = radius * (300.0 - 150.0) / 300.0;
auto radius_5 = radius * (300.0 - 190.0) / 300.0;
auto radius_6 = radius * (300.0 - 220.0) / 300.0;
auto radius_7 = radius * (300.0 - 250.0) / 300.0; // 鱼圆圈
painter.save();
painter.setPen(Qt::NoPen);
QConicalGradient coneGradient(0, 0, 180.0);
int sCount=vBkgColorsList.count();
for(int s=0;s<sCount;s++){
coneGradient.setColorAt(vBkgColorsList[s].fBkgndAngleVal,vBkgColorsList[s].cBkgndAngleClr);
}
painter.setBrush(coneGradient);
painter.drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter.restore();
drawYinYangFish(&painter, radius_7);
drawGua(&painter, radius_6);
drawGuaCharacter(&painter, radius_5, radius_6);
drawCircle(&painter, radius_5, QColor(0x808000), 3.0);
drawTianGanWith5Elements(&painter, radius_4, radius_5);
drawCircle(&painter, radius_4, QColor(0x808000), 3.0);
drawDiZhiWith5Elements(&painter, radius_3, radius_4);
drawCircle(&painter, radius_3, QColor(0xDC143C), 3.0);
drawTianGanDiZhi(&painter, radius_2, radius_3);
drawCircle(&painter, radius_2, QColor(Qt::black), 2.0);
draw24SolarTerms(&painter, radius_1, radius_2);
drawCircle(&painter, radius_1, QColor(0x834447), 6.0);
drawOneEighthSeperator(&painter, radius_1, radius_7);
drawOneTwentyFourthSeperator(&painter, radius_1, radius_3);
drawQuarterSeperator(&painter, radius_3, radius_4);
}
void Qiankunmap::drawYinYangFish(QPainter *painter, qreal radius)
{
auto diameter = 2.0 * radius;
painter->save();
painter->setPen(Qt::black);
painter->setBrush(Qt::black);
painter->drawEllipse(QRectF(-radius, -radius, diameter, diameter));
painter->restore();
// white fish head
auto fishHeadRadius = radius / 2.0f;
QPainterPath path(QPointF(0.0f, -radius));
path.arcTo(QRectF(-radius, -radius, diameter, diameter), 90.0, 180.0);
path.arcTo(QRectF(-fishHeadRadius, 0.0, radius, radius), -90.0, -180.0);
path.arcTo(QRectF(-fishHeadRadius, -radius, radius, radius), -90.0, 180.0);
painter->save();
painter->setPen(QPen(QColor(Qt::black), 2.0));
painter->drawPath(path); // he he
painter->fillPath(path, Qt::white);
painter->restore();
// white fish eye
auto fishEyeWidth = radius / 2.5f;
painter->save();
painter->setPen(QPen(QBrush(Qt::black), fishEyeWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPoint(QPointF(0.0f, -radius / 2.0f));
painter->restore();
// black fish eye
painter->save();
painter->setPen(QPen(QBrush(Qt::white), fishEyeWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawPoint(QPointF(0.0f, radius / 2.0f));
painter->restore();
}
void Qiankunmap::drawGua(QPainter *painter, qreal radius)
{
painter->save();
painter->rotate(degree_);
auto penWidth = 4.0;
static auto spacerAngle = angle_8_1 / 8.0;
static auto rightStartAngle = (angle_8_1 + angle_8_1 / 2.0 + spacerAngle) * 16;
static auto leftStartAngle = (90.0 + spacerAngle) * 16;
static auto spanAngleFull = (angle_8_1 - 2 * spacerAngle) * 16;
static auto spanAngleHalf = (angle_8_1 / 2.0 - 2 * spacerAngle) * 16;
auto drawer = [=](qreal angle, std::tuple<bool, QColor, QColor> top, std::tuple<bool, QColor, QColor> middle, std::tuple<bool, QColor, QColor> bottom){
painter->save();
painter->rotate(angle);
// top
if(std::get<0>(top)){
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(top)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawArc(QRectF(-radius, -radius, 2 * radius, 2 * radius),
rightStartAngle,
spanAngleFull);
painter->restore();
}else{
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(top)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius, -radius, 2 * radius, 2 * radius),
rightStartAngle,
spanAngleHalf);
painter->restore();
painter->save();
painter->setPen(QPen(QBrush(std::get<2>(top)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
painter->drawArc(QRectF(-radius, -radius, 2 * radius, 2 * radius),
leftStartAngle,
spanAngleHalf);
painter->restore();
}
// middle
auto radius_temp = radius - 2.0 * penWidth;
if(std::get<0>(middle)){
painter->save();
painter->setPen(QPen(QBrush(std::get<1>(middle)), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawArc(QRectF(-radius_temp, -radius_tem