Bond.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. #include "Bond.h"
  2. #include <QDebug>
  3. #include <QPair>
  4. #include <QSet>
  5. #include <QMap>
  6. #include <cmath>
  7. Bond::Bond(QWidget* parent)
  8. : QWidget(parent)
  9. {
  10. }
  11. void Bond::UpdataGenerateTestData()
  12. {
  13. // 生成测试数据:2x2 PCB,每个PCB 2x2 PT矩阵,每个PT矩阵 2x3固晶点
  14. int pcbIndex = 0;
  15. int dieIndex = 0;
  16. std::srand(std::time(nullptr));
  17. for (int pcbRow = 0; pcbRow < 2; ++pcbRow) {
  18. for (int pcbCol = 0; pcbCol < 2; ++pcbCol) {
  19. int iPcbMatId = ++pcbIndex;
  20. pcbDimensions[iPcbMatId] = qMakePair(2, 2); // PCB包含2x2 PT矩阵
  21. int ptIndex = 0;
  22. for (int ptRow = 0; ptRow < 2; ++ptRow) {
  23. for (int ptCol = 0; ptCol < 2; ++ptCol) {
  24. int iPtMatId = ++ptIndex;
  25. ptDimensions[iPcbMatId][iPtMatId] = qMakePair(2, 3); // PT矩阵包含2x3固晶点
  26. for (int dieRow = 0; dieRow < 2; ++dieRow) {
  27. for (int dieCol = 0; dieCol < 3; ++dieCol) {
  28. ns_mat::POINT_INFO_STRUCT point;
  29. point.stIndex.iPcbMatId = iPcbMatId;
  30. point.stIndex.iPtMatId = iPtMatId;
  31. point.stIndex.iPcbRow = pcbRow;
  32. point.stIndex.iPcbCol = pcbCol;
  33. point.stIndex.iPtRow = dieRow;
  34. point.stIndex.iPtCol = dieCol;
  35. point.stIndex.iIndex = ++dieIndex;
  36. point.stBondStatus.bDieStatus = static_cast<ns_mat::DIE_STATUS>(std::rand() % 7);
  37. bondData.append(point);
  38. }
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. /*
  46. void Bond::initFrom(QWidget* parent) {
  47. m_pScene = new QGraphicsScene(parent);
  48. m_pView = new BondGraphicsView(m_pScene);
  49. int width = parent->width();
  50. int height = parent->height();
  51. // Step 1: 收集PCB全局布局信息
  52. QMap<QPair<int, int>, int> pcbPosMap;
  53. QSet<int> uniquePcbIds;
  54. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  55. QPair<int, int> pos(point.stIndex.iPcbRow, point.stIndex.iPcbCol);
  56. if (!pcbPosMap.contains(pos)) {
  57. pcbPosMap[pos] = point.stIndex.iPcbMatId;
  58. }
  59. uniquePcbIds.insert(point.stIndex.iPcbMatId);
  60. }
  61. // 计算PCB全局行列数
  62. int maxPcbRow = 0, maxPcbCol = 0;
  63. for (const QPair<int, int>& pos : pcbPosMap.keys()) {
  64. maxPcbRow = qMax(maxPcbRow, pos.first);
  65. maxPcbCol = qMax(maxPcbCol, pos.second);
  66. }
  67. int pcbRows = maxPcbRow + 1;
  68. int pcbCols = maxPcbCol + 1;
  69. // Step 2: 计算PCB布局参数
  70. qreal margin = width / maxPcbCol * 0.05;
  71. qreal pcbSpacing = margin;
  72. int fontSize = qMax(static_cast<int>(margin), 1);
  73. QFont font;
  74. font.setPointSize(fontSize);
  75. qreal totalWidth = width - 2 * margin;
  76. qreal totalHeight = height - 2 * margin;
  77. qreal pcbWidth = (totalWidth - (pcbCols - 1) * pcbSpacing) / pcbCols;
  78. qreal pcbHeight = (totalHeight - (pcbRows - 1) * pcbSpacing) / pcbRows;
  79. // Step 3: 预处理数据分组
  80. QMap<int, QMap<int, QList<ns_mat::POINT_INFO_STRUCT>>> groupedData;
  81. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  82. groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point);
  83. }
  84. // 绘制PCB并记录位置
  85. QMap<int, QRectF> pcbRects;
  86. for (int row = 0; row < pcbRows; ++row) {
  87. for (int col = 0; col < pcbCols; ++col) {
  88. QPair<int, int> pos(row, col);
  89. if (pcbPosMap.contains(pos)) {
  90. int pcbId = pcbPosMap[pos];
  91. QRectF rect(
  92. margin + col * (pcbWidth + pcbSpacing),
  93. margin + row * (pcbHeight + pcbSpacing),
  94. pcbWidth,
  95. pcbHeight
  96. );
  97. pcbRects[pcbId] = rect;
  98. // 绘制PCB背景
  99. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(rect);
  100. pcbItem->setBrush(QColor("#e1d4e6"));
  101. m_pScene->addItem(pcbItem);
  102. // 添加PCB标签
  103. QGraphicsTextItem* text = new QGraphicsTextItem(QString(tr("PCB%1")).arg(pcbId));
  104. text->setFont(font);
  105. qreal fixedHeight = qMin(pcbWidth / std::ceil(static_cast<qreal>(groupedData[pcbId].keys().size()) / std::ceil(std::sqrt(groupedData[pcbId].keys().size()))) * 0.1
  106. , pcbHeight / std::ceil(std::sqrt(groupedData[pcbId].keys().size())) * 0.1);
  107. qreal actualHeight = text->boundingRect().height();
  108. if (actualHeight > 0) {
  109. qreal scaleFactor = fixedHeight / actualHeight;
  110. text->setScale(scaleFactor);
  111. }
  112. text->setPos(rect.x(), rect.y());
  113. m_pScene->addItem(text);
  114. }
  115. }
  116. }
  117. // Step 4: 绘制PT矩阵和固晶点
  118. foreach(int pcbId, uniquePcbIds) {
  119. QRectF pcbRect = pcbRects.value(pcbId);
  120. if (!pcbRect.isValid()) continue;
  121. // 获取当前PCB的所有PT矩阵
  122. QList<int> ptMatIds = groupedData[pcbId].keys();
  123. int ptMatCount = ptMatIds.size();
  124. if (ptMatCount == 0) continue;
  125. // 计算PT矩阵布局行列数(方形布局)
  126. int ptRows = std::ceil(std::sqrt(ptMatCount));
  127. int ptCols = std::ceil(static_cast<qreal>(ptMatCount) / ptRows);
  128. while (ptRows * ptCols < ptMatCount) ptCols++;
  129. qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1);
  130. int fontSize_1 = qMax(static_cast<int>(ptMargin), 1);
  131. QFont font_1;
  132. font_1.setPointSize(fontSize_1);
  133. // 计算PT矩阵尺寸
  134. qreal ptWidth = (pcbRect.width() - (ptCols + 1) * ptMargin) / ptCols;
  135. qreal ptHeight = (pcbRect.height() - (ptRows + 1) * ptMargin) / ptRows;
  136. // 绘制每个PT矩阵
  137. for (int i = 0; i < ptMatIds.size(); ++i) {
  138. int ptId = ptMatIds[i];
  139. int row = i / ptCols;
  140. int col = i % ptCols;
  141. QRectF ptRect(
  142. pcbRect.x() + col * (ptWidth + ptMargin) + ptMargin,
  143. pcbRect.y() + row * (ptHeight + ptMargin) + ptMargin,
  144. ptWidth,
  145. ptHeight
  146. );
  147. // 绘制PT矩阵背景
  148. QGraphicsRectItem* ptItem = new QGraphicsRectItem(ptRect);
  149. ptItem->setBrush(QColor("#d5e4f8"));
  150. m_pScene->addItem(ptItem);
  151. // 添加PT矩阵标签
  152. QGraphicsTextItem* ptText = new QGraphicsTextItem(QString(tr("PT矩阵%1")).arg(ptId));
  153. ptText->setFont(font_1);
  154. qreal fixedHeight_1 = qMin(ptWidth / ptDimensions[pcbId][ptId].second * 0.3, ptHeight / ptDimensions[pcbId][ptId].first * 0.3);
  155. qreal actualHeight_1 = ptText->boundingRect().height();
  156. if (actualHeight_1 > 0) {
  157. qreal scaleFactor_1 = fixedHeight_1 / actualHeight_1;
  158. ptText->setScale(scaleFactor_1);
  159. }
  160. ptText->setPos(ptRect.x(), ptRect.y());
  161. m_pScene->addItem(ptText);
  162. // Step 5: 绘制固晶点
  163. QList<ns_mat::POINT_INFO_STRUCT> points = groupedData[pcbId][ptId];
  164. if (points.isEmpty()) continue;
  165. // 获取固晶点矩阵尺寸
  166. QPair<int, int> dieDims = ptDimensions[pcbId][ptId];
  167. int dieRows = dieDims.first;
  168. int dieCols = dieDims.second;
  169. qreal dieMargin = qMin(ptWidth / dieCols * 0.3, ptHeight / dieRows * 0.3);
  170. // 计算固晶点尺寸
  171. qreal dieWidth = (ptRect.width() - (dieCols + 1) * dieMargin) / dieCols;
  172. qreal dieHeight = (ptRect.height() - (dieRows + 1) * dieMargin) / dieRows;
  173. int fontSize_2 = qMax(static_cast<int>(qMin(dieWidth, dieHeight) * 0.2), 1);
  174. QFont font_2;
  175. font_2.setPointSize(fontSize_2);
  176. foreach(const ns_mat::POINT_INFO_STRUCT & point, points) {
  177. // 计算固晶点位置
  178. QRectF dieRect(
  179. ptRect.x() + point.stIndex.iPtCol * (dieWidth + dieMargin) + dieMargin,
  180. ptRect.y() + point.stIndex.iPtRow * (dieHeight + dieMargin) + dieMargin,
  181. dieWidth,
  182. dieHeight
  183. );
  184. // 绘制固晶点
  185. BondItem* dieItem = new BondItem(point);
  186. dieItem->setRect(dieRect);
  187. m_pScene->addItem(dieItem);
  188. // 添加固晶点编号
  189. QGraphicsTextItem* dieText = new QGraphicsTextItem(dieItem);
  190. dieText->setPlainText("PT" + QString::number(point.stIndex.iIndex));
  191. dieText->setFont(font_2);
  192. dieText->setPos(dieRect.center() - QPointF(dieText->boundingRect().width() / 2,
  193. dieText->boundingRect().height() / 2));
  194. }
  195. }
  196. }
  197. m_pView->setScene(m_pScene);
  198. m_pView->resize(width, height);
  199. }
  200. */
  201. void Bond::initFrom(QWidget* parent) {
  202. m_pScene = new QGraphicsScene(parent);
  203. m_pView = new BondGraphicsView(m_pScene);
  204. m_pView->setCViewInterface(m_pCViewInterface);
  205. int width = parent->width();
  206. int height = parent->height();
  207. double maxWidth = maxPoint.x() - minPoint.x();
  208. double maxHeight = maxPoint.y() - minPoint.y();
  209. double ratio;
  210. if (maxHeight > maxWidth) {
  211. ratio = maxHeight / (width - 100);
  212. }
  213. else {
  214. ratio = maxWidth / (width - 100);
  215. }
  216. //目前没提供pt固晶点大小,以下用测试大小,后续可替换(实际大小,接口替换处)
  217. double dieWidth = 20000;
  218. double dieHeight = 20000;
  219. QFont matrixFont;
  220. double matrixFontSize = qMin(dieWidth/ratio, dieHeight / ratio)*0.1;
  221. matrixFont.setPointSizeF(matrixFontSize); // 使用浮点大小
  222. for (int i = 0; i < bondData.size(); ++i) {
  223. // 绘制固晶点
  224. //转换大小
  225. double dieWidthr = dieWidth / ratio;
  226. double dieHeightr = dieHeight / ratio;
  227. double diex, diey;
  228. diex = (bondData[i].stBondStatus.stAlnBondPosition.x - minPoint.x() + dieWidth) / ratio;
  229. diey = (bondData[i].stBondStatus.stAlnBondPosition.y - minPoint.y() + dieHeight) / ratio;
  230. // 计算固晶点位置
  231. QRectF dieRect(
  232. diex,
  233. diey,
  234. dieWidthr,
  235. dieHeightr
  236. );
  237. BondItem* dieItem = new BondItem(bondData[i]);
  238. dieItem->setRect(dieRect);
  239. dieItem->setZValue(1.0);
  240. m_pScene->addItem(dieItem);
  241. // 添加固晶点编号
  242. QGraphicsTextItem* dieText = new QGraphicsTextItem(dieItem);
  243. dieText->setPlainText("PT" + QString::number(bondData[i].stIndex.iIndex));
  244. double dieFontSize = qMin(dieWidthr, dieHeightr) * 0.2;
  245. QFont font;
  246. font.setPointSizeF(dieFontSize); // 使用浮点大小
  247. dieText->setFont(font);
  248. dieText->setPos(dieRect.center() - QPointF(dieText->boundingRect().width() / 2,
  249. dieText->boundingRect().height() / 2));
  250. }
  251. /*
  252. //绘制pt矩阵和Pcb矩阵
  253. for (auto outerIt = m_pcbMaxPointmap.begin(); outerIt != m_pcbMaxPointmap.end(); ++outerIt) {
  254. int outerKey = outerIt.key(); // 外层 key
  255. const QMap<int, QPointF>& innerMap = outerIt.value();
  256. qDebug() << "Outer Key:" << outerKey;
  257. for (auto innerIt = innerMap.begin(); innerIt != innerMap.end(); ++innerIt) {
  258. int innerKey = innerIt.key(); // 内层 key
  259. const QPointF& maxPtPoint = innerIt.value();
  260. const QPointF& minPtPoint = m_pcbMinPointmap.value(outerKey).value(innerKey);
  261. qDebug() << " Inner Key:" << innerKey;
  262. }
  263. }
  264. */
  265. QPen ptpen(Qt::blue, 0.5);
  266. QPen pcbpen(Qt::red, 0.5);
  267. QPen subpen(Qt::black, 0.5);
  268. //绘制pt矩阵和Pcb矩阵
  269. POINT_INFO_STRUCT maxPcbPoint = m_vptMaxPoints[0];
  270. POINT_INFO_STRUCT minPcbPoint = m_vptMaxPoints[0];
  271. int pcbmatx, pcbmaty, pcbmatWidth, pcbmatHeight;
  272. QVector<POINT_INFO_STRUCT> maxSubPoints;
  273. QVector<POINT_INFO_STRUCT> minSubPoints;
  274. for (int i = 0;i < m_vptMaxPoints.size();i++) {
  275. if (minPcbPoint.stIndex.iPcbRow != m_vptMinPoints[i].stIndex.iPcbRow || minPcbPoint.stIndex.iPcbCol != m_vptMinPoints[i].stIndex.iPcbCol) {
  276. //绘制pcb矩阵
  277. pcbmatx = (minPcbPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.4 * dieWidth) / ratio;
  278. pcbmaty = (minPcbPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.4 * dieHeight) / ratio;
  279. pcbmatWidth = (maxPcbPoint.stBondStatus.stAlnBondPosition.x - minPcbPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.2) / ratio;
  280. pcbmatHeight = (maxPcbPoint.stBondStatus.stAlnBondPosition.y - minPcbPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.2) / ratio;
  281. QRectF pcbRect(
  282. pcbmatx,
  283. pcbmaty,
  284. pcbmatWidth,
  285. pcbmatHeight
  286. );
  287. // 绘制PCB矩阵背景
  288. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(pcbRect);
  289. pcbItem->setPen(pcbpen);
  290. //ptItem->setBrush(QColor("#d5e4f8"));
  291. m_pScene->addItem(pcbItem);
  292. // 添加PCB标签
  293. QRectF pcbTextRect(
  294. pcbmatx,
  295. pcbmaty,
  296. dieWidth / ratio * 0.6,
  297. dieHeight / ratio * 0.2
  298. );
  299. QGraphicsRectItem* pcbTextItem = new QGraphicsRectItem(pcbTextRect);
  300. pcbTextItem->setPen(Qt::NoPen);
  301. m_pScene->addItem(pcbTextItem);
  302. QGraphicsTextItem* pcbText = new QGraphicsTextItem(pcbTextItem);
  303. pcbText->setPlainText(QString(QString(tr("Pcb%1*%2")).arg(minPcbPoint.stIndex.iPcbRow).arg(minPcbPoint.stIndex.iPcbCol)));
  304. pcbText->setFont(matrixFont);
  305. // 将文本居中于 pcbTextRect
  306. pcbText->setPos(pcbTextRect.center() - QPointF(pcbText->boundingRect().width() / 2,
  307. pcbText->boundingRect().height() / 2));
  308. pcbText->setFont(matrixFont);
  309. maxSubPoints.append(maxPcbPoint);
  310. minSubPoints.append(minPcbPoint);
  311. maxPcbPoint = m_vptMaxPoints[i];
  312. minPcbPoint = m_vptMinPoints[i];
  313. }
  314. else {
  315. if (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x > maxPcbPoint.stBondStatus.stAlnBondPosition.x)
  316. maxPcbPoint = m_vptMaxPoints[i];
  317. if (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x < minPcbPoint.stBondStatus.stAlnBondPosition.x)
  318. minPcbPoint = m_vptMinPoints[i];
  319. if (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y > maxPcbPoint.stBondStatus.stAlnBondPosition.y)
  320. maxPcbPoint = m_vptMaxPoints[i];
  321. if (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y < minPcbPoint.stBondStatus.stAlnBondPosition.y)
  322. minPcbPoint = m_vptMinPoints[i];
  323. }
  324. int ptmatx, ptmaty, ptmatWidth, ptmatHeight;
  325. ptmatx = (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.7 * dieWidth) / ratio ;
  326. ptmaty = (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.7 * dieHeight) / ratio ;
  327. ptmatWidth = (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x - m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x +dieWidth*1.6)/ratio;
  328. ptmatHeight = (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y - m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y + dieHeight*1.6) / ratio;
  329. QRectF ptRect(
  330. ptmatx,
  331. ptmaty,
  332. ptmatWidth,
  333. ptmatHeight
  334. );
  335. //qDebug() << m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x << " " << m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y;
  336. //qDebug() << m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x << " " << m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y;
  337. // 绘制PT矩阵背景
  338. QGraphicsRectItem* ptItem = new QGraphicsRectItem(ptRect);
  339. ptItem->setPen(ptpen);
  340. //ptItem->setBrush(QColor("#d5e4f8"));
  341. m_pScene->addItem(ptItem);
  342. // 添加PT矩阵标签
  343. QRectF ptTextRect(
  344. ptmatx,
  345. ptmaty,
  346. dieWidth/ratio* 0.6,
  347. dieHeight / ratio * 0.2
  348. );
  349. QGraphicsRectItem* ptTextItem = new QGraphicsRectItem(ptTextRect);
  350. ptTextItem->setPen(Qt::NoPen);
  351. m_pScene->addItem(ptTextItem);
  352. QGraphicsTextItem* ptText = new QGraphicsTextItem(ptTextItem);
  353. ptText->setPlainText(QString(tr("PtMat%1")).arg(m_vptMinPoints[i].stIndex.iPtMatId));
  354. ptText->setFont(matrixFont);
  355. // 将文本居中于 ptTextRect
  356. ptText->setPos(ptTextRect.center()- QPointF(ptText->boundingRect().width() / 2,
  357. ptText->boundingRect().height() / 2));
  358. }
  359. pcbmatx = (minPcbPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.4 * dieWidth) / ratio;
  360. pcbmaty = (minPcbPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.4 * dieHeight) / ratio;
  361. pcbmatWidth = (maxPcbPoint.stBondStatus.stAlnBondPosition.x - minPcbPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.2) / ratio;
  362. pcbmatHeight = (maxPcbPoint.stBondStatus.stAlnBondPosition.y - minPcbPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.2) / ratio;
  363. QRectF pcbRect(
  364. pcbmatx,
  365. pcbmaty,
  366. pcbmatWidth,
  367. pcbmatHeight
  368. );
  369. // 绘制PCB矩阵背景
  370. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(pcbRect);
  371. pcbItem->setPen(pcbpen);
  372. //ptItem->setBrush(QColor("#d5e4f8"));
  373. m_pScene->addItem(pcbItem);
  374. // 添加PCB标签
  375. QRectF pcbTextRect(
  376. pcbmatx,
  377. pcbmaty,
  378. dieWidth / ratio * 0.6,
  379. dieHeight / ratio * 0.2
  380. );
  381. QGraphicsRectItem* pcbTextItem = new QGraphicsRectItem(pcbTextRect);
  382. pcbTextItem->setPen(Qt::NoPen);
  383. m_pScene->addItem(pcbTextItem);
  384. QGraphicsTextItem* pcbText = new QGraphicsTextItem(pcbTextItem);
  385. pcbText->setPlainText(QString(QString(tr("Pcb%1*%2")).arg(minPcbPoint.stIndex.iPcbRow).arg(minPcbPoint.stIndex.iPcbCol)));
  386. pcbText->setFont(matrixFont);
  387. // 将文本居中于 pcbTextRect
  388. pcbText->setPos(pcbTextRect.center() - QPointF(pcbText->boundingRect().width() / 2,
  389. pcbText->boundingRect().height() / 2));
  390. pcbText->setFont(matrixFont);
  391. //绘制sub矩阵
  392. maxSubPoints.append(maxPcbPoint);
  393. minSubPoints.append(minPcbPoint);
  394. POINT_INFO_STRUCT maxSubPoint = maxSubPoints[0];
  395. POINT_INFO_STRUCT minSubPoint = minSubPoints[0];
  396. int submatx, submaty, submatWidth, submatHeight;
  397. for (int i = 0;i < maxSubPoints.size();i++) {
  398. if (maxSubPoint.stIndex.iPcbMatId != maxSubPoints[i].stIndex.iPcbMatId) {
  399. submatx = (minSubPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.1 * dieWidth) / ratio;
  400. submaty = (minSubPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.1 * dieHeight) / ratio;
  401. submatWidth = (maxSubPoint.stBondStatus.stAlnBondPosition.x - minSubPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.8) / ratio;
  402. submatHeight = (maxSubPoint.stBondStatus.stAlnBondPosition.y - minSubPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.8) / ratio;
  403. QRectF subRect(
  404. submatx,
  405. submaty,
  406. submatWidth,
  407. submatHeight
  408. );
  409. // 绘制SUB矩阵背景
  410. QGraphicsRectItem* subItem = new QGraphicsRectItem(subRect);
  411. subItem->setPen(subpen);
  412. //ptItem->setBrush(QColor("#d5e4f8"));
  413. m_pScene->addItem(subItem);
  414. // 添加PCB标签
  415. QRectF subTextRect(
  416. submatx,
  417. submaty,
  418. dieWidth / ratio * 0.6,
  419. dieHeight / ratio * 0.2
  420. );
  421. QGraphicsRectItem* subTextItem = new QGraphicsRectItem(subTextRect);
  422. subTextItem->setPen(Qt::NoPen);
  423. m_pScene->addItem(subTextItem);
  424. QGraphicsTextItem* subText = new QGraphicsTextItem(subTextItem);
  425. subText->setPlainText(QString(QString(tr("Sub%1")).arg(minSubPoint.stIndex.iPcbMatId)));
  426. subText->setFont(matrixFont);
  427. // 将文本居中于 pcbTextRect
  428. subText->setPos(subTextRect.center() - QPointF(subText->boundingRect().width() / 2,
  429. pcbText->boundingRect().height() / 2));
  430. subText->setFont(matrixFont);
  431. }
  432. else {
  433. if (maxSubPoints[i].stBondStatus.stAlnBondPosition.x > maxSubPoint.stBondStatus.stAlnBondPosition.x)
  434. maxSubPoint = maxSubPoints[i];
  435. if (minSubPoints[i].stBondStatus.stAlnBondPosition.x < minSubPoint.stBondStatus.stAlnBondPosition.x)
  436. minPcbPoint = minSubPoints[i];
  437. if (maxSubPoints[i].stBondStatus.stAlnBondPosition.y > maxSubPoint.stBondStatus.stAlnBondPosition.y)
  438. maxSubPoint = maxSubPoints[i];
  439. if (minSubPoints[i].stBondStatus.stAlnBondPosition.y < minSubPoint.stBondStatus.stAlnBondPosition.y)
  440. minSubPoint = minSubPoints[i];
  441. }
  442. }
  443. submatx = (minSubPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.1 * dieWidth) / ratio;
  444. submaty = (minSubPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.1 * dieHeight) / ratio;
  445. submatWidth = (maxSubPoint.stBondStatus.stAlnBondPosition.x - minSubPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.8) / ratio;
  446. submatHeight = (maxSubPoint.stBondStatus.stAlnBondPosition.y - minSubPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.8) / ratio;
  447. QRectF subRect(
  448. submatx,
  449. submaty,
  450. submatWidth,
  451. submatHeight
  452. );
  453. QGraphicsRectItem* subItem = new QGraphicsRectItem(subRect);
  454. // 设置边框颜色为红色,线宽为2
  455. subItem->setPen(subpen);
  456. // 绘制SUB矩阵背景
  457. //ptItem->setBrush(QColor("#d5e4f8"));
  458. m_pScene->addItem(subItem);
  459. // 添加PCB标签
  460. QRectF subTextRect(
  461. submatx,
  462. submaty,
  463. dieWidth / ratio * 0.6,
  464. dieHeight / ratio * 0.2
  465. );
  466. QGraphicsRectItem* subTextItem = new QGraphicsRectItem(subTextRect);
  467. subTextItem->setPen(Qt::NoPen);
  468. m_pScene->addItem(subTextItem);
  469. QGraphicsTextItem* subText = new QGraphicsTextItem(subTextItem);
  470. subText->setPlainText(QString(QString(tr("Sub%1")).arg(minSubPoint.stIndex.iPcbMatId)));
  471. subText->setFont(matrixFont);
  472. // 将文本居中于 pcbTextRect
  473. subText->setPos(subTextRect.center() - QPointF(subText->boundingRect().width() / 2,
  474. pcbText->boundingRect().height() / 2));
  475. subText->setFont(matrixFont);
  476. m_pView->setScene(m_pScene);
  477. m_pView->resize(width, height);
  478. // 创建一个 QPixmap 对象用于保存绘制的图像
  479. globalPixmap = QPixmap(width, height);
  480. globalPixmap.fill(Qt::white); // 填充背景色为白色
  481. QPixmap originalPixmap = QPixmap::grabWidget(m_pView);
  482. // 设置目标尺寸(例如:宽度 200,高度 150)
  483. QSize targetSize(width, height);
  484. // 不保持比例,直接拉伸到指定尺寸
  485. QPixmap scaledPixmap = originalPixmap.scaled(
  486. targetSize,
  487. Qt::IgnoreAspectRatio,
  488. Qt::SmoothTransformation
  489. );
  490. globalPixmap = scaledPixmap;
  491. }
  492. void Bond::paintInitFrom(QWidget* parent) {
  493. /*
  494. int width = parent->width();
  495. int height = parent->height();
  496. globalPixmap = QPixmap(width, height);
  497. globalPixmap.fill(Qt::white);
  498. QPainter painter(&globalPixmap);
  499. painter.setRenderHint(QPainter::Antialiasing);
  500. QFont baseFont = painter.font();
  501. // Step 1: 收集PCB全局布局信息
  502. QMap<QPair<int, int>, int> pcbPosMap;
  503. QSet<int> uniquePcbIds;
  504. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  505. QPair<int, int> pos(point.stIndex.iPcbRow, point.stIndex.iPcbCol);
  506. if (!pcbPosMap.contains(pos)) {
  507. pcbPosMap[pos] = point.stIndex.iPcbMatId;
  508. }
  509. uniquePcbIds.insert(point.stIndex.iPcbMatId);
  510. }
  511. // 计算PCB全局行列数
  512. int maxPcbRow = 0, maxPcbCol = 0;
  513. for (const QPair<int, int>& pos : pcbPosMap.keys()) {
  514. maxPcbRow = qMax(maxPcbRow, pos.first);
  515. maxPcbCol = qMax(maxPcbCol, pos.second);
  516. }
  517. int pcbRows = maxPcbRow + 1;
  518. int pcbCols = maxPcbCol + 1;
  519. //TODO:yang
  520. maxPcbCol = 1;
  521. // Step 2: 计算PCB布局参数
  522. qreal margin = width / maxPcbCol * 0.05;
  523. qreal pcbSpacing = margin;
  524. qreal totalWidth = width - 2 * margin;
  525. qreal totalHeight = height - 2 * margin;
  526. qreal pcbWidth = (totalWidth - (pcbCols - 1) * pcbSpacing) / pcbCols;
  527. qreal pcbHeight = (totalHeight - (pcbRows - 1) * pcbSpacing) / pcbRows;
  528. // Step 3: 预处理数据分组
  529. QMap<int, QMap<int, QList<ns_mat::POINT_INFO_STRUCT>>> groupedData;
  530. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  531. groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point);
  532. }
  533. // 绘制PCB并记录位置
  534. QMap<int, QRectF> pcbRects;
  535. for (int row = 0; row < pcbRows; ++row) {
  536. for (int col = 0; col < pcbCols; ++col) {
  537. QPair<int, int> pos(row, col);
  538. if (pcbPosMap.contains(pos)) {
  539. int pcbId = pcbPosMap[pos];
  540. QRectF rect(
  541. margin + col * (pcbWidth + pcbSpacing),
  542. margin + row * (pcbHeight + pcbSpacing),
  543. pcbWidth,
  544. pcbHeight
  545. );
  546. pcbRects[pcbId] = rect;
  547. // 绘制PCB背景
  548. painter.setPen(Qt::NoPen);
  549. painter.setBrush(QColor("#e1d4e6"));
  550. painter.drawRect(rect);
  551. }
  552. }
  553. }
  554. // Step 4: 绘制PT矩阵和固晶点
  555. foreach(int pcbId, uniquePcbIds) {
  556. QRectF pcbRect = pcbRects.value(pcbId);
  557. if (!pcbRect.isValid()) continue;
  558. // 获取当前PCB的所有PT矩阵
  559. QList<int> ptMatIds = groupedData[pcbId].keys();
  560. int ptMatCount = ptMatIds.size();
  561. if (ptMatCount == 0) continue;
  562. // 计算PT矩阵布局行列数(方形布局)
  563. int ptRows = std::ceil(std::sqrt(ptMatCount));
  564. int ptCols = std::ceil(static_cast<qreal>(ptMatCount) / ptRows);
  565. while (ptRows * ptCols < ptMatCount) ptCols++;
  566. qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1);
  567. // 计算PT矩阵尺寸
  568. qreal ptWidth = (pcbRect.width() - (ptCols + 1) * ptMargin) / ptCols;
  569. qreal ptHeight = (pcbRect.height() - (ptRows + 1) * ptMargin) / ptRows;
  570. // 绘制每个PT矩阵
  571. for (int i = 0; i < ptMatIds.size(); ++i) {
  572. int ptId = ptMatIds[i];
  573. int row = i / ptCols;
  574. int col = i % ptCols;
  575. QRectF ptRect(
  576. pcbRect.x() + col * (ptWidth + ptMargin) + ptMargin,
  577. pcbRect.y() + row * (ptHeight + ptMargin) + ptMargin,
  578. ptWidth,
  579. ptHeight
  580. );
  581. // 绘制PT矩阵背景
  582. painter.setPen(Qt::NoPen);
  583. painter.setBrush(QColor("#d5e4f8"));
  584. painter.drawRect(ptRect);
  585. // Step 5: 绘制固晶点
  586. QList<ns_mat::POINT_INFO_STRUCT> points = groupedData[pcbId][ptId];
  587. if (points.isEmpty()) continue;
  588. // 获取固晶点矩阵尺寸
  589. QPair<int, int> dieDims = ptDimensions[pcbId][ptId];
  590. int dieRows = dieDims.first;
  591. int dieCols = dieDims.second;
  592. qreal dieMargin = qMin(ptWidth / dieCols * 0.3, ptHeight / dieRows * 0.3);
  593. // 计算固晶点尺寸
  594. qreal dieWidth = (ptRect.width() - (dieCols + 1) * dieMargin) / dieCols;
  595. qreal dieHeight = (ptRect.height() - (dieRows + 1) * dieMargin) / dieRows;
  596. foreach(const ns_mat::POINT_INFO_STRUCT & point, points) {
  597. // 计算固晶点位置
  598. QRectF dieRect(
  599. ptRect.x() + point.stIndex.iPtCol * (dieWidth + dieMargin) + dieMargin,
  600. ptRect.y() + point.stIndex.iPtRow * (dieHeight + dieMargin) + dieMargin,
  601. dieWidth,
  602. dieHeight
  603. );
  604. // 绘制固晶点
  605. painter.setPen(Qt::NoPen);
  606. //painter.setBrush(getColorByStatus(point.stBondStatus.bDieStatus));
  607. painter.drawRect(dieRect);
  608. }
  609. }
  610. }
  611. painter.end();
  612. */
  613. }
  614. QColor Bond::getColorByStatus() {
  615. ns_mat::DIE_STATUS status;
  616. //status = stPointInfo.stBondStatus.bDieStatus;
  617. switch (status) {
  618. //case ns_mat::DIE_STATUS::NO_PICK: return QColor(200, 200, 200);
  619. //case ns_mat::DIE_STATUS::WAF_PICK_DONE: return QColor(100, 200, 230);
  620. //case ns_mat::DIE_STATUS::TRANSFER_BOND_DONE: return QColor(255, 255, 0);
  621. case ns_mat::DIE_STATUS::TRANSFER_PICK_DONE: return QColor(255, 165, 0);
  622. case ns_mat::DIE_STATUS::LOOKUP_CALIB_DONE: return QColor(0, 150, 255);
  623. case ns_mat::DIE_STATUS::BOND_DONE: return QColor(144, 238, 144);
  624. case ns_mat::DIE_STATUS::BOND_DEL: return QColor(255, 50, 50);
  625. default: return Qt::gray;
  626. }
  627. }
  628. void Bond::UpdataVal(std::vector<ns_mat::POINT_INFO_STRUCT>& stPointInfo)
  629. {
  630. maxPoint = QPointF(stPointInfo[0].stBondStatus.stAlnBondPosition.x, stPointInfo[0].stBondStatus.stAlnBondPosition.y);
  631. minPoint = QPointF(stPointInfo[0].stBondStatus.stAlnBondPosition.x, stPointInfo[0].stBondStatus.stAlnBondPosition.y);
  632. QVector<POINT_INFO_STRUCT> ptMatrix;
  633. QMap<int, QMap<int, QVector<POINT_INFO_STRUCT>>> pcbMatrix;
  634. UINT iPcbMatId = stPointInfo[0].stIndex.iPcbMatId;
  635. UINT iPtId = stPointInfo[0].stIndex.iPtMatId;
  636. POINT_INFO_STRUCT ptMinPoint = stPointInfo[0];
  637. POINT_INFO_STRUCT ptMaxPoint = stPointInfo[0];
  638. QMap<int, QPointF> ptMinPointmap;
  639. QMap<int, QPointF> ptMaxPointmap;
  640. QMap<int, QMap<int, QPointF>> pcbMinPointmap;
  641. QMap<int, QMap<int, QPointF>> pcbMaxPointmap;
  642. int pcbRow = stPointInfo[0].stIndex.iPcbRow;
  643. int pcbCol = stPointInfo[0].stIndex.iPcbCol;
  644. int pcbId = 1;
  645. for (auto&a: stPointInfo)
  646. {
  647. bondData.append(a);
  648. if (a.stIndex.iPtMatId == iPtId) {
  649. ptMatrix.append(a);
  650. }
  651. else {
  652. m_vptMaxPoints.append(ptMaxPoint);
  653. m_vptMinPoints.append(ptMinPoint);
  654. iPtId = a.stIndex.iPtMatId;
  655. ptMaxPoint = a;
  656. ptMinPoint = a;
  657. }
  658. //遍历找到最小和最大边界点
  659. if (a.stBondStatus.stAlnBondPosition.x > maxPoint.x())
  660. maxPoint.setX(a.stBondStatus.stAlnBondPosition.x);
  661. if(a.stBondStatus.stAlnBondPosition.x < minPoint.x())
  662. minPoint.setX(a.stBondStatus.stAlnBondPosition.x);
  663. if (a.stBondStatus.stAlnBondPosition.y > maxPoint.y())
  664. maxPoint.setY(a.stBondStatus.stAlnBondPosition.y);
  665. if (a.stBondStatus.stAlnBondPosition.y < minPoint.y())
  666. minPoint.setY(a.stBondStatus.stAlnBondPosition.y);
  667. //判断pt最小和最大对角点
  668. if (a.stBondStatus.stAlnBondPosition.x > ptMaxPoint.stBondStatus.stAlnBondPosition.x)
  669. ptMaxPoint = a;
  670. if (a.stBondStatus.stAlnBondPosition.x < ptMinPoint.stBondStatus.stAlnBondPosition.x)
  671. ptMinPoint = a;
  672. if (a.stBondStatus.stAlnBondPosition.y > ptMaxPoint.stBondStatus.stAlnBondPosition.y)
  673. ptMaxPoint = a;
  674. if (a.stBondStatus.stAlnBondPosition.y < ptMinPoint.stBondStatus.stAlnBondPosition.y)
  675. ptMinPoint = a;
  676. /*
  677. if (a.stIndex.iPcbMatId == iPcbMatId && a.stIndex.iPtMatId == iPtId && (pcbRow == a.stIndex.iPcbRow && pcbCol == a.stIndex.iPcbCol)) {
  678. ptMatrix.append(a);
  679. }
  680. else {
  681. if (a.stIndex.iPcbMatId == iPcbMatId && (pcbRow == a.stIndex.iPcbRow && pcbCol == a.stIndex.iPcbCol)) {
  682. m_pPtMatrixMap.insert(iPtId, ptMatrix);
  683. ptMatrix.clear();
  684. ptMinPointmap.insert(iPtId, ptMinPoint);
  685. ptMaxPointmap.insert(iPtId, ptMaxPoint);
  686. ptMinPointmap.clear();
  687. ptMaxPointmap.clear();
  688. iPtId = a.stIndex.iPtMatId;
  689. }
  690. else {
  691. m_pPcbMatrixMap.insert(iPcbMatId, m_pPtMatrixMap);
  692. m_pcbMinPointmap.insert(iPcbMatId, ptMinPointmap);
  693. m_pcbMaxPointmap.insert(iPcbMatId, ptMaxPointmap);
  694. pcbMatrix.clear();
  695. iPcbMatId = a.stIndex.iPcbMatId;
  696. m_pPtMatrixMap.clear();
  697. }
  698. }
  699. */
  700. qDebug() << a.stBondStatus.stAlnBondPosition.x << " " << a.stBondStatus.stAlnBondPosition.y;
  701. //qDebug() << a.stIndex.iPtMatId << " " << a.stIndex.iPcbMatId;
  702. }
  703. m_vptMaxPoints.append(ptMaxPoint);
  704. m_vptMinPoints.append(ptMinPoint);
  705. //m_pPtMatrixMap.insert(iPtId, ptMatrix);
  706. //m_pPcbMatrixMap.insert(iPcbMatId, m_pPtMatrixMap);
  707. //ptMinPointmap.insert(iPtId, ptMinPoint);
  708. //ptMaxPointmap.insert(iPtId, ptMaxPoint);
  709. //m_pcbMinPointmap.insert(iPcbId, ptMinPointmap);
  710. //m_pcbMaxPointmap.insert(iPcbId, ptMaxPointmap);
  711. }
  712. QPixmap Bond::getGlobalPixmap() const {
  713. return globalPixmap;
  714. }
  715. void Bond::setBondInfo(ns_module::CViewInterface* CViewInterface) {
  716. m_pCViewInterface = CViewInterface;
  717. }