#include "Bond.h" #include #include #include #include #include Bond::Bond(QWidget* parent) : QWidget(parent) { } void Bond::UpdataGenerateTestData() { // 生成测试数据:2x2 PCB,每个PCB 2x2 PT矩阵,每个PT矩阵 2x3固晶点 int pcbIndex = 0; int dieIndex = 0; std::srand(std::time(nullptr)); for (int pcbRow = 0; pcbRow < 2; ++pcbRow) { for (int pcbCol = 0; pcbCol < 2; ++pcbCol) { int iPcbMatId = ++pcbIndex; pcbDimensions[iPcbMatId] = qMakePair(2, 2); // PCB包含2x2 PT矩阵 int ptIndex = 0; for (int ptRow = 0; ptRow < 2; ++ptRow) { for (int ptCol = 0; ptCol < 2; ++ptCol) { int iPtMatId = ++ptIndex; ptDimensions[iPcbMatId][iPtMatId] = qMakePair(2, 3); // PT矩阵包含2x3固晶点 for (int dieRow = 0; dieRow < 2; ++dieRow) { for (int dieCol = 0; dieCol < 3; ++dieCol) { ns_mat::POINT_INFO_STRUCT point; point.stIndex.iPcbMatId = iPcbMatId; point.stIndex.iPtMatId = iPtMatId; point.stIndex.iPcbRow = pcbRow; point.stIndex.iPcbCol = pcbCol; point.stIndex.iPtRow = dieRow; point.stIndex.iPtCol = dieCol; point.stIndex.iIndex = ++dieIndex; point.stBondStatus.bDieStatus = static_cast(std::rand() % 7); bondData.append(point); } } } } } } } void Bond::initFrom(QWidget* parent) { m_pScene = new QGraphicsScene(parent); m_pView = new BondGraphicsView(m_pScene); int width = parent->width(); int height = parent->height(); // Step 1: 收集PCB全局布局信息 QMap, int> pcbPosMap; QSet uniquePcbIds; foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) { QPair pos(point.stIndex.iPcbRow, point.stIndex.iPcbCol); if (!pcbPosMap.contains(pos)) { pcbPosMap[pos] = point.stIndex.iPcbMatId; } uniquePcbIds.insert(point.stIndex.iPcbMatId); } // 计算PCB全局行列数 int maxPcbRow = 0, maxPcbCol = 0; for (const QPair& pos : pcbPosMap.keys()) { maxPcbRow = qMax(maxPcbRow, pos.first); maxPcbCol = qMax(maxPcbCol, pos.second); } int pcbRows = maxPcbRow + 1; int pcbCols = maxPcbCol + 1; // Step 2: 计算PCB布局参数 qreal margin = width / maxPcbCol * 0.05; qreal pcbSpacing = margin; int fontSize = qMax(static_cast(margin), 1); QFont font; font.setPointSize(fontSize); qreal totalWidth = width - 2 * margin; qreal totalHeight = height - 2 * margin; qreal pcbWidth = (totalWidth - (pcbCols - 1) * pcbSpacing) / pcbCols; qreal pcbHeight = (totalHeight - (pcbRows - 1) * pcbSpacing) / pcbRows; // Step 3: 预处理数据分组 QMap>> groupedData; foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) { groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point); } // 绘制PCB并记录位置 QMap pcbRects; for (int row = 0; row < pcbRows; ++row) { for (int col = 0; col < pcbCols; ++col) { QPair pos(row, col); if (pcbPosMap.contains(pos)) { int pcbId = pcbPosMap[pos]; QRectF rect( margin + col * (pcbWidth + pcbSpacing), margin + row * (pcbHeight + pcbSpacing), pcbWidth, pcbHeight ); pcbRects[pcbId] = rect; // 绘制PCB背景 QGraphicsRectItem* pcbItem = new QGraphicsRectItem(rect); pcbItem->setBrush(QColor("#e1d4e6")); m_pScene->addItem(pcbItem); // 添加PCB标签 QGraphicsTextItem* text = new QGraphicsTextItem(QString(tr("PCB%1")).arg(pcbId)); text->setFont(font); qreal fixedHeight = qMin(pcbWidth / std::ceil(static_cast(groupedData[pcbId].keys().size()) / std::ceil(std::sqrt(groupedData[pcbId].keys().size()))) * 0.1 , pcbHeight / std::ceil(std::sqrt(groupedData[pcbId].keys().size())) * 0.1); qreal actualHeight = text->boundingRect().height(); if (actualHeight > 0) { qreal scaleFactor = fixedHeight / actualHeight; text->setScale(scaleFactor); } text->setPos(rect.x(), rect.y()); m_pScene->addItem(text); } } } // Step 4: 绘制PT矩阵和固晶点 foreach(int pcbId, uniquePcbIds) { QRectF pcbRect = pcbRects.value(pcbId); if (!pcbRect.isValid()) continue; // 获取当前PCB的所有PT矩阵 QList ptMatIds = groupedData[pcbId].keys(); int ptMatCount = ptMatIds.size(); if (ptMatCount == 0) continue; // 计算PT矩阵布局行列数(方形布局) int ptRows = std::ceil(std::sqrt(ptMatCount)); int ptCols = std::ceil(static_cast(ptMatCount) / ptRows); while (ptRows * ptCols < ptMatCount) ptCols++; qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1); int fontSize_1 = qMax(static_cast(ptMargin), 1); QFont font_1; font_1.setPointSize(fontSize_1); // 计算PT矩阵尺寸 qreal ptWidth = (pcbRect.width() - (ptCols + 1) * ptMargin) / ptCols; qreal ptHeight = (pcbRect.height() - (ptRows + 1) * ptMargin) / ptRows; // 绘制每个PT矩阵 for (int i = 0; i < ptMatIds.size(); ++i) { int ptId = ptMatIds[i]; int row = i / ptCols; int col = i % ptCols; QRectF ptRect( pcbRect.x() + col * (ptWidth + ptMargin) + ptMargin, pcbRect.y() + row * (ptHeight + ptMargin) + ptMargin, ptWidth, ptHeight ); // 绘制PT矩阵背景 QGraphicsRectItem* ptItem = new QGraphicsRectItem(ptRect); ptItem->setBrush(QColor("#d5e4f8")); m_pScene->addItem(ptItem); // 添加PT矩阵标签 QGraphicsTextItem* ptText = new QGraphicsTextItem(QString(tr("PT矩阵%1")).arg(ptId)); ptText->setFont(font_1); qreal fixedHeight_1 = qMin(ptWidth / ptDimensions[pcbId][ptId].second * 0.3, ptHeight / ptDimensions[pcbId][ptId].first * 0.3); qreal actualHeight_1 = ptText->boundingRect().height(); if (actualHeight_1 > 0) { qreal scaleFactor_1 = fixedHeight_1 / actualHeight_1; ptText->setScale(scaleFactor_1); } ptText->setPos(ptRect.x(), ptRect.y()); m_pScene->addItem(ptText); // Step 5: 绘制固晶点 QList points = groupedData[pcbId][ptId]; if (points.isEmpty()) continue; // 获取固晶点矩阵尺寸 QPair dieDims = ptDimensions[pcbId][ptId]; int dieRows = dieDims.first; int dieCols = dieDims.second; qreal dieMargin = qMin(ptWidth / dieCols * 0.3, ptHeight / dieRows * 0.3); // 计算固晶点尺寸 qreal dieWidth = (ptRect.width() - (dieCols + 1) * dieMargin) / dieCols; qreal dieHeight = (ptRect.height() - (dieRows + 1) * dieMargin) / dieRows; int fontSize_2 = qMax(static_cast(qMin(dieWidth, dieHeight) * 0.2), 1); QFont font_2; font_2.setPointSize(fontSize_2); foreach(const ns_mat::POINT_INFO_STRUCT & point, points) { // 计算固晶点位置 QRectF dieRect( ptRect.x() + point.stIndex.iPtCol * (dieWidth + dieMargin) + dieMargin, ptRect.y() + point.stIndex.iPtRow * (dieHeight + dieMargin) + dieMargin, dieWidth, dieHeight ); // 绘制固晶点 BondItem* dieItem = new BondItem(point); dieItem->setRect(dieRect); m_pScene->addItem(dieItem); // 添加固晶点编号 QGraphicsTextItem* dieText = new QGraphicsTextItem(dieItem); dieText->setPlainText("PT" + QString::number(point.stIndex.iIndex)); dieText->setFont(font_2); dieText->setPos(dieRect.center() - QPointF(dieText->boundingRect().width() / 2, dieText->boundingRect().height() / 2)); } } } m_pView->setScene(m_pScene); m_pView->resize(width, height); } void Bond::paintInitFrom(QWidget* parent) { int width = parent->width(); int height = parent->height(); globalPixmap = QPixmap(width, height); globalPixmap.fill(Qt::white); QPainter painter(&globalPixmap); painter.setRenderHint(QPainter::Antialiasing); QFont baseFont = painter.font(); // Step 1: 收集PCB全局布局信息 QMap, int> pcbPosMap; QSet uniquePcbIds; foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) { QPair pos(point.stIndex.iPcbRow, point.stIndex.iPcbCol); if (!pcbPosMap.contains(pos)) { pcbPosMap[pos] = point.stIndex.iPcbMatId; } uniquePcbIds.insert(point.stIndex.iPcbMatId); } // 计算PCB全局行列数 int maxPcbRow = 0, maxPcbCol = 0; for (const QPair& pos : pcbPosMap.keys()) { maxPcbRow = qMax(maxPcbRow, pos.first); maxPcbCol = qMax(maxPcbCol, pos.second); } int pcbRows = maxPcbRow + 1; int pcbCols = maxPcbCol + 1; //TODO:yang maxPcbCol = 1; // Step 2: 计算PCB布局参数 qreal margin = width / maxPcbCol * 0.05; qreal pcbSpacing = margin; qreal totalWidth = width - 2 * margin; qreal totalHeight = height - 2 * margin; qreal pcbWidth = (totalWidth - (pcbCols - 1) * pcbSpacing) / pcbCols; qreal pcbHeight = (totalHeight - (pcbRows - 1) * pcbSpacing) / pcbRows; // Step 3: 预处理数据分组 QMap>> groupedData; foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) { groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point); } // 绘制PCB并记录位置 QMap pcbRects; for (int row = 0; row < pcbRows; ++row) { for (int col = 0; col < pcbCols; ++col) { QPair pos(row, col); if (pcbPosMap.contains(pos)) { int pcbId = pcbPosMap[pos]; QRectF rect( margin + col * (pcbWidth + pcbSpacing), margin + row * (pcbHeight + pcbSpacing), pcbWidth, pcbHeight ); pcbRects[pcbId] = rect; // 绘制PCB背景 painter.setPen(Qt::NoPen); painter.setBrush(QColor("#e1d4e6")); painter.drawRect(rect); } } } // Step 4: 绘制PT矩阵和固晶点 foreach(int pcbId, uniquePcbIds) { QRectF pcbRect = pcbRects.value(pcbId); if (!pcbRect.isValid()) continue; // 获取当前PCB的所有PT矩阵 QList ptMatIds = groupedData[pcbId].keys(); int ptMatCount = ptMatIds.size(); if (ptMatCount == 0) continue; // 计算PT矩阵布局行列数(方形布局) int ptRows = std::ceil(std::sqrt(ptMatCount)); int ptCols = std::ceil(static_cast(ptMatCount) / ptRows); while (ptRows * ptCols < ptMatCount) ptCols++; qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1); // 计算PT矩阵尺寸 qreal ptWidth = (pcbRect.width() - (ptCols + 1) * ptMargin) / ptCols; qreal ptHeight = (pcbRect.height() - (ptRows + 1) * ptMargin) / ptRows; // 绘制每个PT矩阵 for (int i = 0; i < ptMatIds.size(); ++i) { int ptId = ptMatIds[i]; int row = i / ptCols; int col = i % ptCols; QRectF ptRect( pcbRect.x() + col * (ptWidth + ptMargin) + ptMargin, pcbRect.y() + row * (ptHeight + ptMargin) + ptMargin, ptWidth, ptHeight ); // 绘制PT矩阵背景 painter.setPen(Qt::NoPen); painter.setBrush(QColor("#d5e4f8")); painter.drawRect(ptRect); // Step 5: 绘制固晶点 QList points = groupedData[pcbId][ptId]; if (points.isEmpty()) continue; // 获取固晶点矩阵尺寸 QPair dieDims = ptDimensions[pcbId][ptId]; int dieRows = dieDims.first; int dieCols = dieDims.second; qreal dieMargin = qMin(ptWidth / dieCols * 0.3, ptHeight / dieRows * 0.3); // 计算固晶点尺寸 qreal dieWidth = (ptRect.width() - (dieCols + 1) * dieMargin) / dieCols; qreal dieHeight = (ptRect.height() - (dieRows + 1) * dieMargin) / dieRows; foreach(const ns_mat::POINT_INFO_STRUCT & point, points) { // 计算固晶点位置 QRectF dieRect( ptRect.x() + point.stIndex.iPtCol * (dieWidth + dieMargin) + dieMargin, ptRect.y() + point.stIndex.iPtRow * (dieHeight + dieMargin) + dieMargin, dieWidth, dieHeight ); // 绘制固晶点 painter.setPen(Qt::NoPen); painter.setBrush(getColorByStatus(point.stBondStatus.bDieStatus)); painter.drawRect(dieRect); } } } painter.end(); } QColor Bond::getColorByStatus(ns_mat::DIE_STATUS status) { switch (status) { //case ns_mat::DIE_STATUS::NO_PICK: return QColor(200, 200, 200); //case ns_mat::DIE_STATUS::WAF_PICK_DONE: return QColor(100, 200, 230); //case ns_mat::DIE_STATUS::TRANSFER_BOND_DONE: return QColor(255, 255, 0); case ns_mat::DIE_STATUS::TRANSFER_PICK_DONE: return QColor(255, 165, 0); case ns_mat::DIE_STATUS::LOOKUP_CALIB_DONE: return QColor(0, 150, 255); case ns_mat::DIE_STATUS::BOND_DONE: return QColor(144, 238, 144); case ns_mat::DIE_STATUS::BOND_DEL: return QColor(255, 50, 50); default: return Qt::gray; } } void Bond::UpdataVal(std::vector& stPointInfo) { for (auto&a: stPointInfo) { bondData.append(a); } } QPixmap Bond::getGlobalPixmap() const { return globalPixmap; }