123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #include "Bond.h"
- #include <QDebug>
- #include <QPair>
- #include <QSet>
- #include <QMap>
- #include <cmath>
- Bond::Bond(QWidget* parent) : QWidget(parent) {
- generateTestData();
- }
- void Bond::generateTestData() {
- // 生成测试数据: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<ns_mat::DIE_STATUS>(std::rand() % 7);
- bondData.append(point);
- }
- }
- }
- }
- }
- }
- }
- void Bond::initFrom(QWidget* parent) {
- scene = new QGraphicsScene(parent);
- view = new BondGraphicsView(scene);
- int width = parent->width();
- int height = parent->height();
- // Step 1: 收集PCB全局布局信息
- QMap<QPair<int, int>, int> pcbPosMap;
- QSet<int> uniquePcbIds;
- foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
- QPair<int, int> 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<int, int>& 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<int>(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<int, QMap<int, QList<ns_mat::POINT_INFO_STRUCT>>> groupedData;
- foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
- groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point);
- }
- // 绘制PCB并记录位置
- QMap<int, QRectF> pcbRects;
- for (int row = 0; row < pcbRows; ++row) {
- for (int col = 0; col < pcbCols; ++col) {
- QPair<int, int> 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"));
- scene->addItem(pcbItem);
- // 添加PCB标签
- QGraphicsTextItem* text = new QGraphicsTextItem(QString("PCB%1").arg(pcbId));
- text->setFont(font);
- qreal fixedHeight = qMin(pcbWidth / std::ceil(static_cast<qreal>(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());
- scene->addItem(text);
- }
- }
- }
- // Step 4: 绘制PT矩阵和固晶点
- foreach(int pcbId, uniquePcbIds) {
- QRectF pcbRect = pcbRects.value(pcbId);
- if (!pcbRect.isValid()) continue;
- // 获取当前PCB的所有PT矩阵
- QList<int> 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<qreal>(ptMatCount) / ptRows);
- while (ptRows * ptCols < ptMatCount) ptCols++;
- qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1);
- int fontSize_1 = qMax(static_cast<int>(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"));
- scene->addItem(ptItem);
- // 添加PT矩阵标签
- QGraphicsTextItem* ptText = new QGraphicsTextItem(QString("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());
- scene->addItem(ptText);
- // Step 5: 绘制固晶点
- QList<ns_mat::POINT_INFO_STRUCT> points = groupedData[pcbId][ptId];
- if (points.isEmpty()) continue;
- // 获取固晶点矩阵尺寸
- QPair<int, int> 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<int>(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);
- scene->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));
- }
- }
- }
- view->setScene(scene);
- view->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<QPair<int, int>, int> pcbPosMap;
- QSet<int> uniquePcbIds;
- foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
- QPair<int, int> 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<int, int>& 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;
- 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<int, QMap<int, QList<ns_mat::POINT_INFO_STRUCT>>> groupedData;
- foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
- groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point);
- }
- // 绘制PCB并记录位置
- QMap<int, QRectF> pcbRects;
- for (int row = 0; row < pcbRows; ++row) {
- for (int col = 0; col < pcbCols; ++col) {
- QPair<int, int> 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<int> 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<qreal>(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<ns_mat::POINT_INFO_STRUCT> points = groupedData[pcbId][ptId];
- if (points.isEmpty()) continue;
- // 获取固晶点矩阵尺寸
- QPair<int, int> 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;
- }
- }
- QPixmap Bond::getGlobalPixmap() const {
- return globalPixmap;
- }
|