tools/hhtracer/tracer.cpp
author unC0Rr
Fri, 10 Jan 2025 17:37:34 +0100
changeset 16084 2d65bd46c92f
permissions -rw-r--r--
Start work on hedgehog tracer
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16084
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     1
#include "tracer.h"
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     2
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     3
#include <QRandomGenerator>
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     4
#include <QSvgGenerator>
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     5
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     6
Tracer::Tracer(QObject* parent)
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     7
    : QObject{parent},
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     8
      palette_{{Qt::black,
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
     9
                Qt::white,
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    10
                {"#f29ce7"},
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    11
                {"#9f086e"},
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    12
                {"#54a2fa"},
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    13
                {"#2c78d2"}}} {}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    14
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    15
QList<QColor> Tracer::palette() const { return palette_; }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    16
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    17
void Tracer::setPalette(const QList<QColor>& newPalette) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    18
  if (palette_ == newPalette) return;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    19
  palette_ = newPalette;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    20
  emit paletteChanged();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    21
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    22
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    23
double Tracer::bestSolution() const { return bestSolution_; }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    24
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    25
void Tracer::start(const QString& fileName) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    26
  qDebug() << "Starting using" << fileName;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    27
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    28
  bestSolution_ = 0;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    29
  solutions_.clear();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    30
  generation_.clear();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    31
  image_ = QImage{};
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    32
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    33
  if (palette_.isEmpty()) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    34
    qDebug("Empty palette");
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    35
    return;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    36
  }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    37
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    38
  image_.load(QUrl(fileName).toLocalFile());
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    39
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    40
  if (image_.isNull()) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    41
    qDebug("Failed to load image");
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    42
    return;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    43
  }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    44
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    45
  for (int i = 0; i < 100; ++i) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    46
    generation_.append(Solution{{32, 32}, palette_});
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    47
  }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    48
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    49
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    50
void Tracer::step() {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    51
  solutions_.clear();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    52
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    53
  for (auto& solution : generation_) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    54
    const auto fileName = newFileName();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    55
    solutions_.append(fileName);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    56
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    57
    solution.render(fileName);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    58
  }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    59
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    60
  qDebug() << solutions_;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    61
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    62
  emit solutionsChanged();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    63
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    64
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    65
QStringList Tracer::solutions() const { return solutions_; }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    66
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    67
QString Tracer::newFileName() {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    68
  static qlonglong counter{0};
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    69
  counter += 1;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    70
  return tempDir_.filePath(
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    71
      QStringLiteral("hedgehog_%1.svg").arg(counter, 3, 32, QChar(u'_')));
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    72
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    73
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    74
Solution::Solution(QSizeF size, const QList<QColor>& palette) : size{size} {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    75
  fitness = 0;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    76
  primitives = {Primitive(size, palette)};
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    77
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    78
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    79
void Solution::render(const QString& fileName) const {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    80
  const auto imageSize = size.toSize();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    81
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    82
  QSvgGenerator generator;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    83
  generator.setFileName(fileName);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    84
  generator.setSize(imageSize);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    85
  generator.setViewBox(QRect(0, 0, imageSize.width(), imageSize.height()));
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    86
  generator.setTitle("Hedgehog");
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    87
  generator.setDescription("Approximation of a target image using primitives");
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    88
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    89
  QPainter painter;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    90
  painter.begin(&generator);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    91
  painter.setRenderHint(QPainter::Antialiasing, true);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    92
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    93
  for (const auto& primitive : primitives) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    94
    painter.setPen(primitive.pen);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    95
    painter.setBrush(primitive.brush);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    96
    painter.resetTransform();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    97
    painter.translate(primitive.origin);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    98
    painter.rotate(primitive.rotation);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
    99
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   100
    switch (primitive.type) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   101
      case Polygon: {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   102
        QPolygonF polygon;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   103
        polygon.append({0, 0});
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   104
        polygon.append(primitive.points);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   105
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   106
        painter.drawPolygon(polygon);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   107
        break;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   108
      }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   109
      case Circle:
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   110
        painter.drawEllipse({0, 0}, primitive.radius1, primitive.radius2);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   111
        break;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   112
    }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   113
  }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   114
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   115
  painter.end();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   116
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   117
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   118
double Solution::cost() const {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   119
  return std::accumulate(primitives.constBegin(), primitives.constEnd(), 0,
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   120
                         [](auto a, auto p) { return a + p.cost(); });
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   121
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   122
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   123
Primitive::Primitive(QSizeF size, const QList<QColor>& palette) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   124
  auto rg = QRandomGenerator::global();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   125
  auto randomPoint = [&]() -> QPointF {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   126
    return {rg->bounded(size.width()), rg->bounded(size.height())};
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   127
  };
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   128
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   129
  if (rg->bounded(2) == 0) {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   130
    type = Polygon;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   131
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   132
    points.append(randomPoint());
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   133
    points.append(randomPoint());
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   134
  } else {
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   135
    type = Circle;
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   136
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   137
    radius1 = rg->bounded(size.width());
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   138
    radius2 = rg->bounded(size.width());
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   139
    rotation = rg->bounded(90);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   140
  }
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   141
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   142
  pen = QPen(palette[rg->bounded(palette.length())]);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   143
  pen.setWidthF(rg->bounded(size.width() * 0.1));
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   144
  brush = QBrush(palette[rg->bounded(palette.length())]);
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   145
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   146
  origin = randomPoint();
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   147
}
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   148
2d65bd46c92f Start work on hedgehog tracer
unC0Rr
parents:
diff changeset
   149
double Primitive::cost() const { return 1.0 + 0.1 * points.length(); }