#include "MappingUI.h" #include MappingUI::MappingUI(QWidget *parent) : QWidget(parent) { ui.setupUi(this); connect(ui.pushButton_clearCurSelect, SIGNAL(clicked()), this, SLOT(slot_clearCurSelect())); connect(ui.pushButton_addCurRow, SIGNAL(clicked()), this, SLOT(slot_addCurRow())); connect(ui.pushButton_addCurRol, SIGNAL(clicked()), this, SLOT(slot_addCurRol())); connect(ui.pushButton_addCurArea, SIGNAL(clicked()), this, SLOT(slot_addCurArea())); } MappingUI::~MappingUI() { ClearSceneAndVec(); } void MappingUI::UseRecipeMappingAndGetCoord(RecipeAttrObj recipeObj, bool isShowDieText) { m_isShowDieText = isShowDieText; m_recipeAttrObj = recipeObj; SetMappingToInitStatus(); DrawMapping(); } void MappingUI::DrawMapping() { //先清除所有 ClearSceneAndVec(); if (m_recipeAttrObj.m_PPID.size() < 1) { return; } //计算每个区域X和Y方向die的数量 CountAreaData(); double rectFirstPointX = m_recipeAttrObj.m_baseDieCoordX - (m_recipeAttrObj.m_dieWidth / 2.0); double rectFirstPointY = -1 * m_recipeAttrObj.m_baseDIeCoordY - (m_recipeAttrObj.m_dieHeight / 2.0); { //添加坐标系 m_baseLineXCoordObj = std::make_shared(); m_baseLineXCoordObj->SetLineCoord(m_recipeAttrObj.m_waferDie / 2 * -1 - 5, 0, m_recipeAttrObj.m_waferDie / 2 + 5, 0, false); m_baseLineXCoordObj->setPos(0, 0); m_allLineItem.push_back(m_baseLineXCoordObj); m_mappingScene.addItem(m_baseLineXCoordObj.get()); std::shared_ptr YCoordLineObj = std::make_shared(); YCoordLineObj->SetLineCoord(0, m_recipeAttrObj.m_waferDie / 2 * -1 - 5, 0, m_recipeAttrObj.m_waferDie / 2 + 5, false); YCoordLineObj->setPos(m_baseLineXCoordObj->pos().x(), m_baseLineXCoordObj->pos().y()); m_allLineItem.push_back(YCoordLineObj); m_mappingScene.addItem(YCoordLineObj.get()); } { //添加基准die std::shared_ptr baseDieObj = nullptr; baseDieObj = std::make_shared(0, 0, m_recipeAttrObj.m_dieWidth, m_recipeAttrObj.m_dieHeight); SetDieAttr(baseDieObj, true, false, rectFirstPointX, rectFirstPointY); baseDieObj->setBrush(BASE_POINT_COLOR); baseDieObj->setPos(m_baseLineXCoordObj->pos().x() + rectFirstPointX, m_baseLineXCoordObj->pos().y() + rectFirstPointY); m_allDieItem.push_back(baseDieObj); m_mappingScene.addItem(baseDieObj.get()); } { //绘制晶圆圆形 std::shared_ptr EllipseObj = nullptr; EllipseObj = std::make_shared(0, 0, m_recipeAttrObj.m_waferDie, m_recipeAttrObj.m_waferDie); m_ellipseItem.push_back(EllipseObj); EllipseObj->setPen(QPen(RECT_COLOR)); EllipseObj->setPos(m_baseLineXCoordObj->pos().x() - m_recipeAttrObj.m_waferDie / 2, m_baseLineXCoordObj->pos().y() - m_recipeAttrObj.m_waferDie / 2); m_mappingScene.addItem(EllipseObj.get()); } //基准die往上延伸 for (int i = 0; i < MAX_EXTEND_NUM; i++) { double xCoord = rectFirstPointX; double yCoord = rectFirstPointY + i * m_recipeAttrObj.m_dieHeight; if (yCoord < -1 * m_recipeAttrObj.m_waferDie / 2) { break; } LeftExtend(xCoord, yCoord); bool isIncludeBaseDie = false; i == 0 ? isIncludeBaseDie = true : isIncludeBaseDie = false; RightExtend(xCoord, yCoord, isIncludeBaseDie); } //基准die往下延伸 for (int i = 1; i < MAX_EXTEND_NUM; i++) { double xCoord = rectFirstPointX; double yCoord = rectFirstPointY - i * m_recipeAttrObj.m_dieHeight; if (yCoord > m_recipeAttrObj.m_waferDie / 2) { break; } LeftExtend(xCoord, yCoord); RightExtend(xCoord, yCoord, false); } //绘制区域横线,直接划分成固定区域 for (int i = 0; i < m_areaGridNum + 1; i++) { std::shared_ptr LineObj = std::make_shared( -m_recipeAttrObj.m_waferDie / 2, -m_recipeAttrObj.m_waferDie / 2 + (m_recipeAttrObj.m_waferDie / m_areaGridNum) * i, m_recipeAttrObj.m_waferDie / 2, -m_recipeAttrObj.m_waferDie / 2 + (m_recipeAttrObj.m_waferDie / m_areaGridNum) * i); LineObj->setPen(QPen(AREA_LINE_COLOR)); m_allLineItem.push_back(LineObj); m_mappingScene.addItem(LineObj.get()); } //绘制区域竖线,直接划分成固定区域 for (int i = 0; i < m_areaGridNum + 1; i++) { std::shared_ptr LineObj = std::make_shared( -m_recipeAttrObj.m_waferDie / 2 + (m_recipeAttrObj.m_waferDie / m_areaGridNum) * i, -m_recipeAttrObj.m_waferDie / 2, -m_recipeAttrObj.m_waferDie / 2 + (m_recipeAttrObj.m_waferDie / m_areaGridNum) * i, m_recipeAttrObj.m_waferDie / 2); LineObj->setPen(QPen(AREA_LINE_COLOR)); m_allLineItem.push_back(LineObj); m_mappingScene.addItem(LineObj.get()); } ui.graphicsView->setScene(&m_mappingScene); if (!m_isScale) { ui.graphicsView->scale(m_scaleFactor, m_scaleFactor); m_isScale = true; } } void MappingUI::SetLabelHide() { //ui.horizontalLayout->removeWidget(ui.label); //ui.horizontalLayout->removeWidget(ui.label_2); ui.horizontalLayout_2->removeWidget(ui.pushButton_clearCurSelect); ui.horizontalLayout_2->removeWidget(ui.pushButton_addCurRow); ui.horizontalLayout_2->removeWidget(ui.pushButton_addCurRol); ui.horizontalLayout_2->removeWidget(ui.pushButton_addCurArea); ui.horizontalLayout_2->removeItem(ui.horizontalSpacer_2); //ui.label->hide(); //ui.label_2->hide(); ui.pushButton_clearCurSelect->hide(); ui.pushButton_addCurRow->hide(); ui.pushButton_addCurRol->hide(); ui.pushButton_addCurArea->hide(); //ui.verticalLayout->removeItem(ui.horizontalLayout); } void MappingUI::SetMappingToInitStatus() { for (auto& iter : m_allDieItem) { if (iter->Mark() || iter->Base()) { continue; } iter->setBrush(Qt::NoBrush); } m_selectDieVec.clear(); } void MappingUI::GetCurAreaAllDie(std::vector>& outCurAreaDie) { outCurAreaDie.clear(); for (auto& iter : m_allDieItem) { if (iter->AreaIdX() == m_curAreaIdX && iter->AreaIdY() == m_curAreaIdY) { outCurAreaDie.push_back(iter); } } } void MappingUI::UpdateMappingArea(int areaIdX, int areaidY) { for (auto& iter : m_allDieItem) { if (iter->Mark() || iter->Base()) { continue; } if (iter->AreaIdX() == areaIdX && iter->AreaIdY() == areaidY) { iter->setBrush(DIE_MARK_END); } } } void MappingUI::DieMarkUIUpdateAlreadyMark() { for (auto& iter : m_selectDieVec) { if (iter->Mark() || iter->Base()) { continue; } iter->setBrush(DIE_MARK_END); } } void MappingUI::CommonClearSelectDie() { for (auto& iter : m_allDieItem) { if (iter->Mark() || iter->Base()) { continue; } iter->ShowTextItem(false); //iter->ShowTextItemFunc(); if (iter->AlreadlyMarked()) { iter->setBrush(DIE_MARK_END); } if (iter->brush().color() == CUR_SELECT_DIE) { iter->setBrush(Qt::NoBrush); } iter->Select(false); } m_selectDieVec.clear(); } void MappingUI::LeftExtend(double firstX, double firstY) { for (int i = 1; i < MAX_EXTEND_NUM; i++) { double rectFirstX = firstX - m_recipeAttrObj.m_dieWidth * i; double rectFirstY = firstY; if (JudgeIsInWafer(rectFirstX, rectFirstY)) { AddDieRect(rectFirstX, rectFirstY); } else { if (rectFirstX < -1 * m_recipeAttrObj.m_waferDie / 2) { break; } } } } void MappingUI::RightExtend(double firstX, double firstY, bool isIncludeCur) { int startPos = 0; isIncludeCur ? startPos = 1 : startPos = 0; for (int i = startPos; i < MAX_EXTEND_NUM; i++) { double rectFirstX = firstX + m_recipeAttrObj.m_dieWidth * i; double rectFirstY = firstY; if (JudgeIsInWafer(rectFirstX, rectFirstY)) { AddDieRect(rectFirstX, rectFirstY); } else { if (rectFirstX > m_recipeAttrObj.m_waferDie / 2) { break; } } } } void MappingUI::AddDieRect(double xCoord, double yCoord) { std::shared_ptr rectObj = std::make_shared( xCoord, yCoord, m_recipeAttrObj.m_dieWidth, m_recipeAttrObj.m_dieHeight); rectObj->ShowTextItem(m_isShowDieText); rectObj->setPen(QPen(RECT_COLOR)); SetDieAttr(rectObj, false, false, xCoord, yCoord); if (JudgeIsMark(rectObj)) { rectObj->Mark(true); rectObj->setBrush(MARK_POINT_COLOR); } /*if (JudgeIsMark(xCoord, yCoord)) { SetDieAttr(rectObj, false, true, xCoord, yCoord); rectObj->setBrush(MARK_POINT_COLOR); } else { SetDieAttr(rectObj, false, false, xCoord, yCoord); }*/ rectObj->setPos(m_baseLineXCoordObj->pos().x() + xCoord, m_baseLineXCoordObj->pos().y() + yCoord); m_allDieItem.push_back(rectObj); m_mappingScene.addItem(rectObj.get()); } void MappingUI::SetDieAttr(std::shared_ptr& dieObj, bool isBase, bool isMark, double xCoord, double yCoord) { connect(dieObj.get(), SIGNAL(signal_select(double,double)), this, SLOT(slot_UpdateAllDieStatus(double, double))); dieObj->Base(isBase); dieObj->Mark(isMark); dieObj->xCoord(xCoord); dieObj->yCoord(yCoord); dieObj->RealDieXCoord(xCoord + m_recipeAttrObj.m_dieWidth / 2.0); dieObj->RealDieYCoord(-1 * yCoord - m_recipeAttrObj.m_dieHeight / 2.0); /*if (dieObj->Mark()) { dieObj->RealDieYCoord(yCoord - m_recipeAttrObj.m_dieHeight / 2.0); }*/ //计算die最大最小Y坐标 if (dieObj->RealDieYCoord() > m_dieMaxYcoord) { m_dieMaxYcoord = dieObj->RealDieYCoord(); } if (dieObj->RealDieYCoord() < m_dieMinYccord) { m_dieMinYccord = dieObj->RealDieYCoord(); } } bool MappingUI::JudgeIsInWafer(double xCoord, double yCoord) { if (abs(xCoord) > (m_recipeAttrObj.m_waferDie / 2.0) || abs(yCoord) > m_recipeAttrObj.m_waferDie / 2.0) { return false; } int judgeIsOk = 0; //矩形左上侧点 if (sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(yCoord, 2)) > abs(xCoord) && sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(xCoord, 2)) > abs(yCoord)) { judgeIsOk++; } //矩形左下侧点 if (sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(yCoord + m_recipeAttrObj.m_dieHeight, 2)) > abs(xCoord) && sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(xCoord, 2)) > abs(yCoord + m_recipeAttrObj.m_dieHeight)) { judgeIsOk++; } //矩形右上侧点 if (sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(yCoord, 2)) > abs(xCoord + m_recipeAttrObj.m_dieWidth) && sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(xCoord + m_recipeAttrObj.m_dieWidth, 2)) > abs(yCoord)) { judgeIsOk++; } //矩形右下侧点 if (sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(yCoord + +m_recipeAttrObj.m_dieHeight, 2)) > abs(xCoord + m_recipeAttrObj.m_dieWidth) && sqrt(std::pow(m_recipeAttrObj.m_waferDie / 2, 2) - std::pow(xCoord + m_recipeAttrObj.m_dieWidth, 2)) > abs(yCoord + m_recipeAttrObj.m_dieHeight)) { judgeIsOk++; } if (4 == judgeIsOk) { return true; } return false; } bool MappingUI::JudgeIsMark(std::shared_ptr& die) { /*if (m_recipeAttrObj.m_mark1CoordX >= xCoord && m_recipeAttrObj.m_mark1CoordX <= (xCoord + m_recipeAttrObj.m_dieWidth) && m_recipeAttrObj.m_mark1CoordY >= yCoord && m_recipeAttrObj.m_mark1CoordY <= (yCoord + m_recipeAttrObj.m_dieHeight)) { return true; } if (m_recipeAttrObj.m_mark2CoordX >= xCoord && m_recipeAttrObj.m_mark2CoordX <= (xCoord + m_recipeAttrObj.m_dieWidth) && m_recipeAttrObj.m_mark2CoordY >= yCoord && m_recipeAttrObj.m_mark2CoordY <= (yCoord + m_recipeAttrObj.m_dieHeight)) { return true; }*/ if (abs(m_recipeAttrObj.m_mark1CoordX - die->RealDieXCoord()) <= m_recipeAttrObj.m_dieWidth / 2.0 && abs(m_recipeAttrObj.m_mark1CoordY - die->RealDieYCoord()) <= m_recipeAttrObj.m_dieHeight / 2.0) { return true; } if (abs(m_recipeAttrObj.m_mark2CoordX - die->RealDieXCoord()) <= m_recipeAttrObj.m_dieWidth / 2.0 && abs(m_recipeAttrObj.m_mark2CoordY - die->RealDieYCoord()) <= m_recipeAttrObj.m_dieHeight / 2.0) { return true; } return false; } void MappingUI::CountAreaData() { //根据晶圆尺寸,12寸(300mm)分为10个区域,8寸(200mm)分为8个区域,6寸(150mm)分为5个区域 if (abs(m_recipeAttrObj.m_waferDie - 300) < 20) { m_areaGridNum = 10; } if (abs(m_recipeAttrObj.m_waferDie - 200) < 20) { m_areaGridNum = 8; } if (abs(m_recipeAttrObj.m_waferDie - 150) < 20) { m_areaGridNum = 5; } if (abs(m_recipeAttrObj.m_waferDie - 100) < 20) { m_areaGridNum = 4; } if (abs(m_recipeAttrObj.m_waferDie - 50) < 20) { m_areaGridNum = 2; } m_areaXDirDieNum = std::ceil(m_recipeAttrObj.m_waferDie / m_areaGridNum / m_recipeAttrObj.m_dieWidth); m_areaYDirDieNum = std::ceil(m_recipeAttrObj.m_waferDie / m_areaGridNum / m_recipeAttrObj.m_dieHeight); } void MappingUI::ClearSceneAndVec() { QList items = m_mappingScene.items(); foreach(QGraphicsItem *item, items) { m_mappingScene.removeItem(item); //delete item; // 如果需要,可以删除项以释放内存 } m_allDieItem.clear(); m_ellipseItem.clear(); m_allLineItem.clear(); m_curDie = nullptr; m_dieMaxYcoord = 0.0; m_dieMinYccord = 0.0; } void MappingUI::AddSelectDie(std::shared_ptr& selectDie) { if (m_selectDieVec.size() < 1) { m_selectDieVec.push_back(selectDie); } bool isUnique = false; for (auto& iter : m_selectDieVec) { if (abs(iter->RealDieXCoord() - selectDie->RealDieXCoord()) <= JUDGE_DECIMAL && abs(iter->RealDieYCoord() - selectDie->RealDieYCoord()) <= JUDGE_DECIMAL) { isUnique = true; } } if (!isUnique) { m_selectDieVec.push_back(selectDie); } } void MappingUI::wheelEvent(QWheelEvent *event) { ui.graphicsView->resetMatrix(); // 滚轮向上放大,向下缩小 qDebug() << event->angleDelta().y(); if (event->angleDelta().y() > 0) { if (m_scaleFactor < 10) { m_scaleFactor *= 1.05; // 放大 } } else { if (m_scaleFactor > 2) { m_scaleFactor /= 1.05; // 缩小 } } qDebug() << event->angleDelta().y()<< " "<< m_scaleFactor; ui.graphicsView->scale(m_scaleFactor, m_scaleFactor); } void MappingUI::mousePressEvent(QMouseEvent *event) { /*if (event->button() == Qt::LeftButton) { for (auto& iter : m_allItem) { if (iter->Base() != true && iter->Mark() != true) { iter->setBrush(Qt::NoBrush); } } }*/ } void MappingUI::slot_UpdateAllDieStatus(double xCoord, double yCoord) { //iter->setBrush(Qt::NoBrush); //清除UI选中特征,先备注在这儿 for (auto& iter : m_allDieItem) { if (abs(xCoord - iter->RealDieXCoord()) <= JUDGE_DECIMAL && abs(yCoord - iter->RealDieYCoord()) <= JUDGE_DECIMAL) { AddSelectDie(iter); //UI显示die相关信息 m_curDieCoordX = xCoord; m_curDieCoordY = yCoord; m_curAreaIdX = iter->AreaIdX(); m_curAreaIdY = iter->AreaIdY(); m_curDie = iter; QString str = QString::fromLocal8Bit("X坐标:") + QString::number(xCoord) + QString::fromLocal8Bit(", Y坐标:") + QString::number(yCoord) + QString::fromLocal8Bit(", 区域ID->X:") + QString::number(iter->AreaIdX()) + QString::fromLocal8Bit(", 区域ID->Y:") + QString::number(iter->AreaIdY()) + QString::fromLocal8Bit(", 序列号:") + iter->SerialNum(); ui.label->setText(str); if (!iter->Select()) { m_selectDieVec.erase( std::remove_if(m_selectDieVec.begin(), m_selectDieVec.end(), [xCoord, yCoord](std::shared_ptr obj) { return abs(xCoord - obj->RealDieXCoord()) <= JUDGE_DECIMAL && abs(yCoord - obj->RealDieYCoord()) <= JUDGE_DECIMAL; }), m_selectDieVec.end() ); } } } int i = 0; } void MappingUI::slot_clearCurSelect() { CommonClearSelectDie(); QMessageBox::StandardButton button = QMessageBox::information( nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("清除选中die成功"), QMessageBox::Yes, QMessageBox::NoButton); } void MappingUI::slot_addCurRow() { for (auto& iter : m_allDieItem) { if (iter->Mark()) { continue; } if (iter->RealDieYCoord() == m_curDieCoordY) { iter->Select(true); iter->setBrush(CUR_SELECT_DIE); AddSelectDie(iter); } } } void MappingUI::slot_addCurRol() { for (auto& iter : m_allDieItem) { if (iter->Mark()) { continue; } if (iter->RealDieXCoord() == m_curDieCoordX) { iter->Select(true); iter->setBrush(CUR_SELECT_DIE); m_selectDieVec.push_back(iter); } } } void MappingUI::slot_addCurArea() { for (auto& iter : m_allDieItem) { if (iter->Mark()) { continue; } if (iter->AreaIdX() == m_curAreaIdX && iter->AreaIdY() == m_curAreaIdY) { iter->Select(true); iter->setBrush(CUR_SELECT_DIE); AddSelectDie(iter); } } }