Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <QWidget>
- #include <QPaintEvent>
- #include <QPainter>
- #include <QKeyEvent>
- #include <QMouseEvent>
- #include <QPen>
- #include <vector>
- #include <math.h>
- struct BasePoint
- {
- int x, y;
- QColor color;
- BasePoint(int _x, int _y, QColor _color)
- :x(_x), y(_y), color(_color)
- {
- }
- };
- struct Cluster;
- struct KPoint : public BasePoint
- {
- Cluster *parentCluster;
- KPoint(int _x = 0, int _y = 0, QColor _color = QColor(Qt::black))
- : BasePoint(_x, _y, _color), parentCluster(nullptr)
- {
- }
- };
- struct Cluster : public BasePoint
- {
- std::vector<KPoint*> kpoints;
- int minx, miny, maxx, maxy;
- Cluster(int _x, int _y, QColor _color)
- : BasePoint(_x, _y, _color)
- {
- }
- };
- class KMeans : public QWidget
- {
- std::vector<KPoint*> kpoints;
- std::vector<Cluster*> clusters;
- int pointRadius;
- int clusterCenterRadius;
- public:
- KMeans(QWidget* parent = 0) :
- QWidget(parent), pointRadius(3), clusterCenterRadius(6)
- {
- genPoints(200);
- }
- void genPoints(int nr)
- {
- while (nr--)
- kpoints.push_back(new KPoint(rand() % width(), rand() % height()));
- }
- void paintEvent(QPaintEvent *e)
- {
- QPainter painter(this);
- painter.setPen(Qt::black);
- for (KPoint* &p : kpoints)
- {
- QColor pointColor;
- if (p->parentCluster)
- {
- pointColor = p->parentCluster->color;
- painter.setPen(pointColor);
- painter.drawLine(p->x, p->y, p->parentCluster->x, p->parentCluster->y);
- }
- else
- {
- pointColor = Qt::black;
- }
- painter.setPen(Qt::black);
- painter.setBrush(pointColor);
- painter.drawEllipse(p->x - pointRadius, p->y - pointRadius, pointRadius * 2, pointRadius * 2);
- }
- for (auto &c : clusters)
- {
- painter.setBrush(c->color);
- painter.drawEllipse(c->x - clusterCenterRadius, c->y - clusterCenterRadius, clusterCenterRadius * 2, clusterCenterRadius * 2);
- }
- }
- void mousePressEvent(QMouseEvent *e)
- {
- switch (e->button())
- {
- case Qt::LeftButton:
- //...
- clusters.push_back(new Cluster(e->x(), e->y(), Qt::red));
- iterate();
- update(); //redesenarea ferestrei (se apeleaza paintEvent())
- break;
- case Qt::RightButton:
- deleteCluster(e->x(), e->y());
- iterate();
- update();
- break;
- }
- }
- void deleteCluster(int x, int y) {
- Cluster *cdel;
- for (auto c : clusters) {
- if (c->x == x && c->y == y) {
- cdel = c;
- }
- }
- clusters.erase(std::remove(clusters.begin(), clusters.end(), cdel), clusters.end());
- }
- void keyPressEvent(QKeyEvent *e)
- {
- switch (e->key())
- {
- case Qt::Key_Space:
- clearCenters();
- iterate();
- updateCenters();
- update();
- break;
- case Qt::Key_Escape:
- this->close();
- };
- }
- void iterate() {
- for (auto p : kpoints) {
- float min = FLT_MAX;
- Cluster* minCLuster;
- for (auto c : clusters) {
- float temp = calculateDistance(p, c);
- if (temp< min) {
- minCLuster = c;
- min = temp;
- }
- }
- minCLuster->kpoints.push_back(p);
- p->parentCluster = minCLuster;
- }
- }
- void clearCenters() {
- for (auto c : clusters) {
- c->kpoints.clear();
- }
- }
- void updateCenters() {
- int sumx = 0;
- int sumy = 0;
- for (auto c : clusters) {
- for (auto k : c->kpoints) {
- sumx += k->x;
- sumy += k->y;
- }
- c->x = sumx / c->kpoints.size();
- c->y = sumy / c->kpoints.size();
- sumx = 0;
- sumy = 0;
- }
- }
- float calculateDistance(KPoint *p, Cluster *c) {
- return (p->x - c->x)*(p->x - c->x) + (p->y - c->y)*(p->y - c->y);
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement