代码拉取完成,页面将自动刷新
#include "Heart.h"
#include <QPointF>
#define PI 3.14159265358
Heart::Heart(int frameCount, qreal cx, qreal cy)
:_cx(cx)
,_cy(cy)
,_frameCount(frameCount)
{
std::srand(std::time(0));
refreshPoints();
}
Heart::~Heart()
{
}
void Heart::next()
{
_frame = (_frame + 1) % _frameCount;
}
void Heart::draw(QPainter &painter, const QColor &color) const
{
for (const HeartPoint &hp : _allPoints[_frame]) {
painter.fillRect(hp.x, hp.y, hp.size, hp.size, color);
}
}
void Heart::setCenterPoint(const QPointF &point)
{
qreal offset_x = point.x() - _cx;
qreal offset_y = point.y() - _cy;
if (offset_x != 0 || offset_y != 0) {
_cx = point.x();
_cy = point.y();
for (auto iter = _allPoints.begin(); iter != _allPoints.end(); ++iter) {
for (HeartPoint &hp : iter.value()) {
hp.x += offset_x;
hp.y += offset_y;
}
}
}
}
void Heart::build(int count)
{
// 爱心
for (int i=0; i<count; i++) {
qreal t = PI * 2 * rand() / RAND_MAX;
_points.push_back(heartPoint(t));
}
// 爱心内扩散
for (const QPointF &p : qAsConst(_points)) {
for (int i=0; i<3; i++) {
_edgeDiffusionPoints.push_back(scatterInside(p.x(), p.y(), 0.05));
}
}
// 爱心再次扩散
for (int i=0; i<4000; i++) {
auto placeholder = rand();
QPointF p = _points.at(placeholder % _points.size());
_centerDiffusionPoints.push_back(scatterInside(p.x(), p.y(), 0.17));
}
}
void Heart::calc(int generate_frame)
{
qreal ratio = 10 * curve(PI * generate_frame / 10);
int halo_radius = 4 + 6 * (1 + curve(PI * generate_frame / 10));
int halo_count = 3000 + 4000 * abs(pow(curve(PI * generate_frame / 10), 2));
QVector<HeartPoint> points;
// 光环
QVector<QPointF> heart_halo_point;
for (int i=0; i<halo_count; i++) {
qreal t = PI * 2 * rand() / RAND_MAX;
QPointF p = heartPoint(t, 11.6);
p = shrink(p.x(), p.y(), halo_radius);
if (heart_halo_point.contains(p)) {
continue;
}
heart_halo_point.push_back(p);
qreal x = 14 - rand() % 29 + p.x();
qreal y = 14 - rand() % 29 + p.y();
qreal size = rand() % 3 > 0 ? 2 : 1;
points.push_back({x, y, size});
}
// 轮廓
for (const QPointF &p : qAsConst(_points)) {
QPointF point = calcPosition(p.x(), p.y(), ratio);
qreal size = rand() % 3 + 1;
points.push_back({point.x(), point.y(), size});
}
// 内容
for (const QPointF &p : qAsConst(_edgeDiffusionPoints)) {
QPointF point = calcPosition(p.x(), p.y(), ratio);
qreal size = rand() % 2 + 1;
points.push_back({point.x(), point.y(), size});
}
for (const QPointF &p : qAsConst(_centerDiffusionPoints)) {
QPointF point = calcPosition(p.x(), p.y(), ratio);
qreal size = rand() % 2 + 1;
points.push_back({point.x(), point.y(), size});
}
_allPoints[generate_frame] = points;
}
QPointF Heart::calcPosition(qreal x, qreal y, qreal ratio) const
{
// 调整缩放比例
qreal force = 1 / (pow(pow(x - _cx, 2) + pow(y - _cy, 2), 0.520));
qreal dx = ratio * force * (x - _cx) + (1 - rand() % 3);
qreal dy = ratio * force * (y - _cy) + (1 - rand() % 3);
return {x - dx, y - dy};
}
QPointF Heart::heartPoint(qreal t, qreal shrink_ratio) const
{
qreal x = 16 * pow(sin(t), 3);
qreal y = 5 * cos(2 * t) + 2 * cos(3 * t) + cos(4 * t) - 13 * cos(t);
// 放大
x *= shrink_ratio;
y *= shrink_ratio;
// 移到画布中央
x += _cx;
y += _cy;
return {x, y};
}
QPointF Heart::scatterInside(qreal x, qreal y, qreal beta) const
{
qreal ratio_x = - beta * log((qreal)rand() / RAND_MAX);
qreal ratio_y = - beta * log((qreal)rand() / RAND_MAX);
return {x - ratio_x * (x - _cx), y - ratio_y * (y - _cy)};
}
QPointF Heart::shrink(qreal x, qreal y, qreal ratio) const
{
qreal force = -1 / pow(pow(x - _cx, 2) + pow(y - _cy, 2), 0.6);
return {x - ratio * force * (x - _cx), y - ratio * force * (y - _cy)};
}
qreal Heart::curve(qreal p)
{
return 2 * (2 * sin(4 * p)) / (2 * PI);
}
void Heart::refreshPoints()
{
_points.clear();
_edgeDiffusionPoints.clear();
_centerDiffusionPoints.clear();
_allPoints.clear();
build(2000);
for (int frame=0; frame<_frameCount; frame++) {
calc(frame);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。