Трассировка контуров с обнаружением отверстий для 2D-каракулей [закрыто]C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Трассировка контуров с обнаружением отверстий для 2D-каракулей [закрыто]

Сообщение Anonymous »

У меня есть программа на Qt C++, которая позволяет пользователю свободно рисовать каракули. Эта каракуля затем будет преобразована в многоугольник. В настоящее время эта функциональность реализована, но я предпочитаю реализовать трассировщик контуров с алгоритмом поиска отверстий и показывать эти контуры красным цветом.
В качестве вывода я ожидаю что-то вроде этого :
Изображение

ввод — зеленая линия (каракуля, которую пользователь свободно рисовать с помощью мыши). Результатом являются только красные линии вокруг нарисованной от руки зеленой линии. Пользователь свободно рисует зеленым карандашом, и как только кнопка мыши будет отпущена, должны появиться красные линии. Однако моя текущая реализация не кажется правильной. Я предпочитаю получать странные линии только в некоторых частях каракулей. Почему это происходит? Я провел так много исследований, но, в конце концов, кажется, ничто не решает проблему:
Изображение

Мой код:

Код: Выделить всё

main.cpp:

Код: Выделить всё

#include "MainWindow.h"

#include 

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

Код: Выделить всё

MainWindow.h:

Код: Выделить всё

#pragma once

#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class DrawingWidget;

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;

DrawingWidget *drawingWidget;
};

Код: Выделить всё

MainWindow.cpp:

Код: Выделить всё

#include "MainWindow.h"
#include "DrawingWidget.h"
#include "ui_MainWindow.h"

#include 
#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Create a central widget that will hold the layout
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);

// Create a layout for the central widget
QVBoxLayout *layout = new QVBoxLayout(centralWidget);

// Create the DrawingWidget and add it to the layout
drawingWidget = new DrawingWidget(this);
layout->addWidget(drawingWidget);

// Create a horizontal layout for the controls (e.g., the pencil thickness slider)
QHBoxLayout *controlsLayout = new QHBoxLayout();
QLabel *label = new QLabel("Pencil Thickness:");
controlsLayout->addWidget(label);

QSlider *slider = new QSlider(Qt::Horizontal);
slider->setRange(1, 20);
connect(slider, &QSlider::valueChanged, drawingWidget, &DrawingWidget::setPencilThickness);
controlsLayout->addWidget(slider);

// Add the controls layout to the main layout
layout->addLayout(controlsLayout);
}

MainWindow::~MainWindow()
{
delete ui;
}

Код: Выделить всё

DrawingWidget.h:

Код: Выделить всё

#pragma once

#include 
#include 
#include 

class DrawingWidgetPriv;

class DrawingWidget : public QWidget {
Q_OBJECT

public:
explicit DrawingWidget(QWidget *parent = nullptr);

void setPencilThickness(int thickness);

QVector detectContours(const QVector &points);

protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;

private:
DrawingWidgetPriv* _priv = nullptr;

void drawLineTo(const QPoint &endPoint);
void drawOutlineAroundDrawing();  // Method to detect outline and draw the polygon
QVector simplify(const QVector &points, double epsilon);  // Simplify points using Douglas-Peucker algorithm
};

Код: Выделить всё

DrawingWidget.cpp:

Код: Выделить всё

#include "DrawingWidget.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//// #### DrawingWidgetPriv #####################################

class DrawingWidgetPriv
{
friend DrawingWidget;

public:
DrawingWidgetPriv(DrawingWidget* widget);
~DrawingWidgetPriv();

private:
DrawingWidget* _widget = nullptr;

QImage _image;
QPoint _lastPoint;
bool _drawing;
int _pencilThickness;
QVector _points;   // Store points for the polygon
};

DrawingWidgetPriv::DrawingWidgetPriv(DrawingWidget* widget)
{
_widget = widget;
}

DrawingWidgetPriv::~DrawingWidgetPriv()
{
delete _widget;
}

//// #### DrawingWidget #####################################

DrawingWidget::DrawingWidget(QWidget *parent)
: QWidget(parent)
{
_priv = new DrawingWidgetPriv(this);
_priv->_drawing = false;
_priv->_pencilThickness = 1;

_priv->_image = QImage(800, 600, QImage::Format_ARGB32);
_priv->_image.fill(QColor(82, 94, 197));
}

void DrawingWidget::setPencilThickness(int thickness) {
_priv->_pencilThickness = thickness;
}

void DrawingWidget::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true); // Enable anti-aliasing
painter.drawImage(0, 0, _priv->_image);
}

void DrawingWidget::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
_priv->_lastPoint = event->pos();
_priv->_drawing = true;
_priv->_points.clear();  // Clear previous points
_priv->_points.append(_priv->_lastPoint);  // Add the first point
}
}

void DrawingWidget::mouseMoveEvent(QMouseEvent *event) {
if ((event->buttons() & Qt::LeftButton) && _priv->_drawing) {
QPoint currentPoint = event->pos();
drawLineTo(currentPoint);
_priv->_points.append(currentPoint);  // Store points for later outline detection
}
}

void DrawingWidget::mouseReleaseEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton && _priv->_drawing) {
drawLineTo(event->pos());
_priv->_drawing = false;

// After drawing is finished, draw the outline polygon
drawOutlineAroundDrawing();
}
}

void DrawingWidget::drawLineTo(const QPoint &endPoint) {
QPainter painter(&_priv->_image);
painter.setRenderHint(QPainter::Antialiasing, true); // Enable anti-aliasing
QPen pen(QColor(136, 190, 55), _priv->_pencilThickness, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen);
painter.drawLine(_priv->_lastPoint, endPoint);
_priv->_lastPoint = endPoint;
update();
}

Заранее благодарен за любую помощь. Я также прошу вас, ребята, предоставить пример кода любого решения, которое вы предлагаете. Поскольку это не входит в сферу моей компетенции, мне может понадобиться нечто большее, чем просто текст объяснения в качестве решения/обратной связи. Спасибо большое :)

Подробнее здесь: https://stackoverflow.com/questions/792 ... d-scribble
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»