203 lines
7.6 KiB
C++
203 lines
7.6 KiB
C++
#include "main_window.h"
|
|
#include <QFileDialog>
|
|
#include <QVBoxLayout>
|
|
#include <QHBoxLayout>
|
|
#include <QGroupBox>
|
|
#include <QFormLayout>
|
|
#include <QStyle>
|
|
#include <QMessageBox>
|
|
#include <QPainter>
|
|
#include <QtMath>
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QMainWindow(parent)
|
|
{
|
|
setWindowTitle("Sistema de Inspección y Medición de Soldaduras (Línea Única)");
|
|
resize(1200, 800);
|
|
|
|
createUI();
|
|
createDefaultSampleImage();
|
|
}
|
|
|
|
void MainWindow::createUI()
|
|
{
|
|
QWidget *centralWidget = new QWidget(this);
|
|
setCentralWidget(centralWidget);
|
|
|
|
QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);
|
|
mainLayout->setContentsMargins(8, 8, 8, 8);
|
|
mainLayout->setSpacing(8);
|
|
|
|
// Left sidebar panel
|
|
QWidget *panel = new QWidget(centralWidget);
|
|
panel->setFixedWidth(320);
|
|
QVBoxLayout *panelLayout = new QVBoxLayout(panel);
|
|
panelLayout->setContentsMargins(4, 4, 4, 4);
|
|
|
|
// Image loading section
|
|
QGroupBox *grpFile = new QGroupBox("1. Imagen de Inspección", panel);
|
|
QVBoxLayout *fileLayout = new QVBoxLayout(grpFile);
|
|
|
|
QPushButton *btnOpen = new QPushButton("Cargar Imagen...", grpFile);
|
|
btnOpen->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
|
|
btnOpen->setFixedHeight(36);
|
|
|
|
m_lblImgDimensions = new QLabel("Resolución: -", grpFile);
|
|
|
|
fileLayout->addWidget(btnOpen);
|
|
fileLayout->addWidget(m_lblImgDimensions);
|
|
panelLayout->addWidget(grpFile);
|
|
|
|
// Calibration setup section
|
|
QGroupBox *grpCalib = new QGroupBox("2. Calibración por Escala", panel);
|
|
QVBoxLayout *calibLayout = new QVBoxLayout(grpCalib);
|
|
|
|
QFormLayout *formCalib = new QFormLayout();
|
|
m_spinCalibMm = new QDoubleSpinBox(grpCalib);
|
|
m_spinCalibMm->setRange(0.001, 10000.0);
|
|
m_spinCalibMm->setValue(10.0);
|
|
m_spinCalibMm->setSuffix(" mm");
|
|
m_spinCalibMm->setDecimals(3);
|
|
formCalib->addRow("Largo Real Patrón:", m_spinCalibMm);
|
|
calibLayout->addLayout(formCalib);
|
|
|
|
m_btnCalibrate = new QPushButton("Fijar Calibración con Línea Actual", grpCalib);
|
|
m_btnCalibrate->setFixedHeight(34);
|
|
m_btnCalibrate->setStyleSheet("font-weight: bold; background-color: #2b5b84; color: white; border-radius: 4px;");
|
|
|
|
m_lblScale = new QLabel("Escala: Sin Calibrar", grpCalib);
|
|
m_lblScale->setStyleSheet("font-weight: bold; color: #ffb400;");
|
|
|
|
calibLayout->addWidget(m_btnCalibrate);
|
|
calibLayout->addWidget(m_lblScale);
|
|
panelLayout->addWidget(grpCalib);
|
|
|
|
// Measurement readout section
|
|
QGroupBox *grpMeas = new QGroupBox("3. Medición en Vivo", panel);
|
|
QVBoxLayout *measLayout = new QVBoxLayout(grpMeas);
|
|
|
|
m_lblMeasurement = new QLabel("Medida: -\nDistancia: - px", grpMeas);
|
|
m_lblMeasurement->setStyleSheet("font-size: 14px; font-weight: bold; color: #ff5555; background: #1e1e24; padding: 10px; border-radius: 4px;");
|
|
|
|
QPushButton *btnResetLine = new QPushButton("Centrar Línea en Pantalla", grpMeas);
|
|
|
|
measLayout->addWidget(m_lblMeasurement);
|
|
measLayout->addWidget(btnResetLine);
|
|
panelLayout->addWidget(grpMeas);
|
|
|
|
// Instructions box
|
|
QGroupBox *grpHelp = new QGroupBox("Modo de Uso", panel);
|
|
QVBoxLayout *helpLayout = new QVBoxLayout(grpHelp);
|
|
QLabel *lblHelp = new QLabel(
|
|
"1. Coloque la línea roja de 1 px sobre el patrón de la imagen cuyo largo conozca.\n\n"
|
|
"2. Ingrese la distancia real en mm y presione 'Fijar Calibración'.\n\n"
|
|
"3. Arrastre esa misma línea a cualquier punto para medir la soldadura o distancia deseada.\n\n"
|
|
"• Rueda del mouse: Zoom.\n"
|
|
"• Clic derecho + arrastrar: Desplazarse.", grpHelp);
|
|
lblHelp->setWordWrap(true);
|
|
lblHelp->setStyleSheet("color: #ccc; font-size: 11px;");
|
|
helpLayout->addWidget(lblHelp);
|
|
panelLayout->addWidget(grpHelp);
|
|
|
|
panelLayout->addStretch();
|
|
|
|
// OpenGL Central Viewport Widget
|
|
m_glWidget = new WeldOpenGLWidget(centralWidget);
|
|
|
|
mainLayout->addWidget(panel);
|
|
mainLayout->addWidget(m_glWidget, 1);
|
|
|
|
// Connect signals & slots
|
|
connect(btnOpen, &QPushButton::clicked, this, &MainWindow::openImage);
|
|
connect(m_btnCalibrate, &QPushButton::clicked, this, &MainWindow::onCalibrateClicked);
|
|
connect(btnResetLine, &QPushButton::clicked, m_glWidget, &WeldOpenGLWidget::resetLine);
|
|
|
|
connect(m_glWidget, &WeldOpenGLWidget::calibrationUpdated, this, &MainWindow::updateCalibrationInfo);
|
|
connect(m_glWidget, &WeldOpenGLWidget::measurementUpdated, this, &MainWindow::updateMeasurementInfo);
|
|
connect(m_glWidget, &WeldOpenGLWidget::imageLoaded, this, [this](int w, int h) {
|
|
m_lblImgDimensions->setText(QString("Resolución: %1 x %2 px").arg(w).arg(h));
|
|
});
|
|
}
|
|
|
|
void MainWindow::createDefaultSampleImage()
|
|
{
|
|
QImage img(1000, 700, QImage::Format_RGB32);
|
|
img.fill(QColor(40, 42, 48));
|
|
|
|
QPainter painter(&img);
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
|
|
// Draw simulated weld seam
|
|
for (int x = 100; x < 900; x += 6) {
|
|
double y = 350 + qSin(x / 30.0) * 15 + qCos(x / 7.0) * 8;
|
|
double r = 25 + qSin(x / 10.0) * 5;
|
|
painter.setBrush(QColor(130, 135, 145));
|
|
painter.setPen(QPen(QColor(170, 175, 185), 1.5));
|
|
painter.drawEllipse(QPointF(x, y), r, r * 0.5);
|
|
}
|
|
|
|
// Draw reference pattern bar (200px = 10mm)
|
|
int scaleX = 150;
|
|
int scaleY = 560;
|
|
int scaleLenPx = 200;
|
|
|
|
painter.setBrush(QColor(230, 230, 230));
|
|
painter.setPen(Qt::NoPen);
|
|
painter.drawRoundedRect(scaleX - 20, scaleY - 30, scaleLenPx + 40, 70, 8, 8);
|
|
|
|
QPen rulerPen(Qt::black, 4, Qt::SolidLine, Qt::SquareCap);
|
|
painter.setPen(rulerPen);
|
|
painter.drawLine(scaleX, scaleY, scaleX + scaleLenPx, scaleY);
|
|
painter.drawLine(scaleX, scaleY - 15, scaleX, scaleY + 15);
|
|
painter.drawLine(scaleX + scaleLenPx, scaleY - 15, scaleX + scaleLenPx, scaleY + 15);
|
|
|
|
painter.setFont(QFont("Arial", 11, QFont::Bold));
|
|
painter.drawText(QRect(scaleX - 20, scaleY + 10, scaleLenPx + 40, 25), Qt::AlignCenter, "PATRÓN DE PRUEBA: 10.0 mm");
|
|
|
|
img.save("/home/sebastian/repos/weld_measure/sample_weld.png");
|
|
m_glWidget->setImage(img);
|
|
|
|
// Position single line right over the sample pattern bar (200px = 10mm)
|
|
m_glWidget->setLinePoints(QPointF(scaleX, scaleY), QPointF(scaleX + scaleLenPx, scaleY));
|
|
m_glWidget->calibrateWithCurrentLine(10.0);
|
|
}
|
|
|
|
void MainWindow::openImage()
|
|
{
|
|
QString fileName = QFileDialog::getOpenFileName(this, "Abrir Imagen de Inspección", "", "Imágenes (*.png *.jpg *.jpeg *.bmp *.tif *.tiff)");
|
|
if (!fileName.isEmpty()) {
|
|
if (!m_glWidget->loadImage(fileName)) {
|
|
QMessageBox::warning(this, "Error", "No se pudo cargar la imagen seleccionada.");
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::onCalibrateClicked()
|
|
{
|
|
double knownMm = m_spinCalibMm->value();
|
|
m_glWidget->calibrateWithCurrentLine(knownMm);
|
|
QMessageBox::information(this, "Calibración Exitosa",
|
|
QString("Escala fijada correctamente:\n%1 mm/px\n\nAhora puede mover la misma línea para medir cualquier parte de la imagen.")
|
|
.arg(m_glWidget->mmPerPixel(), 0, 'g', 5));
|
|
}
|
|
|
|
void MainWindow::updateCalibrationInfo(double mmPerPx)
|
|
{
|
|
if (m_glWidget->isCalibrated() && mmPerPx > 0.0) {
|
|
m_lblScale->setText(QString("Escala: %1 mm/px").arg(mmPerPx, 0, 'g', 5));
|
|
m_lblScale->setStyleSheet("font-weight: bold; color: #55ff55;");
|
|
} else {
|
|
m_lblScale->setText("Escala: Sin Calibrar");
|
|
m_lblScale->setStyleSheet("font-weight: bold; color: #ffb400;");
|
|
}
|
|
}
|
|
|
|
void MainWindow::updateMeasurementInfo(double px, double mm)
|
|
{
|
|
Q_UNUSED(px);
|
|
if (m_glWidget->isCalibrated()) {
|
|
m_lblMeasurement->setText(QString("Medida: %1 mm").arg(mm, 0, 'f', 2));
|
|
} else {
|
|
m_lblMeasurement->setText("Medida: Sin Calibrar");
|
|
}
|
|
}
|