Bond.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  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. if (bondData.size() == 0) {
  223. return;
  224. }
  225. for (int i = 0; i < bondData.size(); ++i) {
  226. // 绘制固晶点
  227. //转换大小
  228. double dieWidthr = dieWidth / ratio;
  229. double dieHeightr = dieHeight / ratio;
  230. double diex, diey;
  231. diex = (bondData[i].stBondStatus.stAlnBondPosition.x - minPoint.x() + dieWidth) / ratio;
  232. diey = (bondData[i].stBondStatus.stAlnBondPosition.y - minPoint.y() + dieHeight) / ratio;
  233. // 计算固晶点位置
  234. QRectF dieRect(
  235. diex,
  236. diey,
  237. dieWidthr,
  238. dieHeightr
  239. );
  240. BondItem* dieItem = new BondItem(bondData[i]);
  241. dieItem->setRect(dieRect);
  242. dieItem->setZValue(1.0);
  243. m_pScene->addItem(dieItem);
  244. // 添加固晶点编号
  245. QGraphicsTextItem* dieText = new QGraphicsTextItem(dieItem);
  246. dieText->setPlainText("PT" + QString::number(bondData[i].stIndex.iIndex));
  247. double dieFontSize = qMin(dieWidthr, dieHeightr) * 0.2;
  248. QFont font;
  249. font.setPointSizeF(dieFontSize); // 使用浮点大小
  250. dieText->setFont(font);
  251. dieText->setPos(dieRect.center() - QPointF(dieText->boundingRect().width() / 2,
  252. dieText->boundingRect().height() / 2));
  253. }
  254. QPen ptpen(Qt::blue, 0.5);
  255. QPen pcbpen(Qt::red, 0.5);
  256. QPen subpen(Qt::black, 0.5);
  257. //绘制pt矩阵和Pcb矩阵
  258. POINT_INFO_STRUCT maxPcbPoint = m_vptMaxPoints[0];
  259. POINT_INFO_STRUCT minPcbPoint = m_vptMaxPoints[0];
  260. int pcbmatx, pcbmaty, pcbmatWidth, pcbmatHeight;
  261. QVector<POINT_INFO_STRUCT> maxSubPoints;
  262. QVector<POINT_INFO_STRUCT> minSubPoints;
  263. for (int i = 0;i < m_vptMaxPoints.size();i++) {
  264. if (minPcbPoint.stIndex.iPcbRow != m_vptMinPoints[i].stIndex.iPcbRow || minPcbPoint.stIndex.iPcbCol != m_vptMinPoints[i].stIndex.iPcbCol) {
  265. //绘制pcb矩阵
  266. pcbmatx = (minPcbPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.4 * dieWidth) / ratio;
  267. pcbmaty = (minPcbPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.4 * dieHeight) / ratio;
  268. pcbmatWidth = (maxPcbPoint.stBondStatus.stAlnBondPosition.x - minPcbPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.2) / ratio;
  269. pcbmatHeight = (maxPcbPoint.stBondStatus.stAlnBondPosition.y - minPcbPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.2) / ratio;
  270. QRectF pcbRect(
  271. pcbmatx,
  272. pcbmaty,
  273. pcbmatWidth,
  274. pcbmatHeight
  275. );
  276. // 绘制PCB矩阵背景
  277. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(pcbRect);
  278. pcbItem->setPen(pcbpen);
  279. //ptItem->setBrush(QColor("#d5e4f8"));
  280. m_pScene->addItem(pcbItem);
  281. // 添加PCB标签
  282. QRectF pcbTextRect(
  283. pcbmatx,
  284. pcbmaty,
  285. dieWidth / ratio * 0.6,
  286. dieHeight / ratio * 0.2
  287. );
  288. QGraphicsRectItem* pcbTextItem = new QGraphicsRectItem(pcbTextRect);
  289. pcbTextItem->setPen(Qt::NoPen);
  290. m_pScene->addItem(pcbTextItem);
  291. QGraphicsTextItem* pcbText = new QGraphicsTextItem(pcbTextItem);
  292. pcbText->setPlainText(QString(QString(tr("Pcb%1*%2")).arg(minPcbPoint.stIndex.iPcbRow).arg(minPcbPoint.stIndex.iPcbCol)));
  293. pcbText->setFont(matrixFont);
  294. // 将文本居中于 pcbTextRect
  295. pcbText->setPos(pcbTextRect.center() - QPointF(pcbText->boundingRect().width() / 2,
  296. pcbText->boundingRect().height() / 2));
  297. pcbText->setFont(matrixFont);
  298. maxSubPoints.append(maxPcbPoint);
  299. minSubPoints.append(minPcbPoint);
  300. maxPcbPoint = m_vptMaxPoints[i];
  301. minPcbPoint = m_vptMinPoints[i];
  302. }
  303. else {
  304. if (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x > maxPcbPoint.stBondStatus.stAlnBondPosition.x)
  305. maxPcbPoint = m_vptMaxPoints[i];
  306. if (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x < minPcbPoint.stBondStatus.stAlnBondPosition.x)
  307. minPcbPoint = m_vptMinPoints[i];
  308. if (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y > maxPcbPoint.stBondStatus.stAlnBondPosition.y)
  309. maxPcbPoint = m_vptMaxPoints[i];
  310. if (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y < minPcbPoint.stBondStatus.stAlnBondPosition.y)
  311. minPcbPoint = m_vptMinPoints[i];
  312. }
  313. int ptmatx, ptmaty, ptmatWidth, ptmatHeight;
  314. ptmatx = (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.7 * dieWidth) / ratio ;
  315. ptmaty = (m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.7 * dieHeight) / ratio ;
  316. ptmatWidth = (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x - m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x +dieWidth*1.6)/ratio;
  317. ptmatHeight = (m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y - m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y + dieHeight*1.6) / ratio;
  318. QRectF ptRect(
  319. ptmatx,
  320. ptmaty,
  321. ptmatWidth,
  322. ptmatHeight
  323. );
  324. //qDebug() << m_vptMinPoints[i].stBondStatus.stAlnBondPosition.x << " " << m_vptMinPoints[i].stBondStatus.stAlnBondPosition.y;
  325. //qDebug() << m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.x << " " << m_vptMaxPoints[i].stBondStatus.stAlnBondPosition.y;
  326. // 绘制PT矩阵背景
  327. QGraphicsRectItem* ptItem = new QGraphicsRectItem(ptRect);
  328. ptItem->setPen(ptpen);
  329. //ptItem->setBrush(QColor("#d5e4f8"));
  330. m_pScene->addItem(ptItem);
  331. // 添加PT矩阵标签
  332. QRectF ptTextRect(
  333. ptmatx,
  334. ptmaty,
  335. dieWidth/ratio* 0.6,
  336. dieHeight / ratio * 0.2
  337. );
  338. QGraphicsRectItem* ptTextItem = new QGraphicsRectItem(ptTextRect);
  339. ptTextItem->setPen(Qt::NoPen);
  340. m_pScene->addItem(ptTextItem);
  341. QGraphicsTextItem* ptText = new QGraphicsTextItem(ptTextItem);
  342. ptText->setPlainText(QString(tr("PtMat%1")).arg(m_vptMinPoints[i].stIndex.iPtMatId));
  343. ptText->setFont(matrixFont);
  344. // 将文本居中于 ptTextRect
  345. ptText->setPos(ptTextRect.center()- QPointF(ptText->boundingRect().width() / 2,
  346. ptText->boundingRect().height() / 2));
  347. }
  348. pcbmatx = (minPcbPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.4 * dieWidth) / ratio;
  349. pcbmaty = (minPcbPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.4 * dieHeight) / ratio;
  350. pcbmatWidth = (maxPcbPoint.stBondStatus.stAlnBondPosition.x - minPcbPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.2) / ratio;
  351. pcbmatHeight = (maxPcbPoint.stBondStatus.stAlnBondPosition.y - minPcbPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.2) / ratio;
  352. QRectF pcbRect(
  353. pcbmatx,
  354. pcbmaty,
  355. pcbmatWidth,
  356. pcbmatHeight
  357. );
  358. // 绘制PCB矩阵背景
  359. QGraphicsRectItem* pcbItem = new QGraphicsRectItem(pcbRect);
  360. pcbItem->setPen(pcbpen);
  361. //ptItem->setBrush(QColor("#d5e4f8"));
  362. m_pScene->addItem(pcbItem);
  363. // 添加PCB标签
  364. QRectF pcbTextRect(
  365. pcbmatx,
  366. pcbmaty,
  367. dieWidth / ratio * 0.6,
  368. dieHeight / ratio * 0.2
  369. );
  370. QGraphicsRectItem* pcbTextItem = new QGraphicsRectItem(pcbTextRect);
  371. pcbTextItem->setPen(Qt::NoPen);
  372. m_pScene->addItem(pcbTextItem);
  373. QGraphicsTextItem* pcbText = new QGraphicsTextItem(pcbTextItem);
  374. pcbText->setPlainText(QString(QString(tr("Pcb%1*%2")).arg(minPcbPoint.stIndex.iPcbRow).arg(minPcbPoint.stIndex.iPcbCol)));
  375. pcbText->setFont(matrixFont);
  376. // 将文本居中于 pcbTextRect
  377. pcbText->setPos(pcbTextRect.center() - QPointF(pcbText->boundingRect().width() / 2,
  378. pcbText->boundingRect().height() / 2));
  379. pcbText->setFont(matrixFont);
  380. //绘制sub矩阵
  381. maxSubPoints.append(maxPcbPoint);
  382. minSubPoints.append(minPcbPoint);
  383. POINT_INFO_STRUCT maxSubPoint = maxSubPoints[0];
  384. POINT_INFO_STRUCT minSubPoint = minSubPoints[0];
  385. int submatx, submaty, submatWidth, submatHeight;
  386. for (int i = 0;i < maxSubPoints.size();i++) {
  387. if (maxSubPoint.stIndex.iPcbMatId != maxSubPoints[i].stIndex.iPcbMatId) {
  388. submatx = (minSubPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.1 * dieWidth) / ratio;
  389. submaty = (minSubPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.1 * dieHeight) / ratio;
  390. submatWidth = (maxSubPoint.stBondStatus.stAlnBondPosition.x - minSubPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.8) / ratio;
  391. submatHeight = (maxSubPoint.stBondStatus.stAlnBondPosition.y - minSubPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.8) / ratio;
  392. QRectF subRect(
  393. submatx,
  394. submaty,
  395. submatWidth,
  396. submatHeight
  397. );
  398. // 绘制SUB矩阵背景
  399. QGraphicsRectItem* subItem = new QGraphicsRectItem(subRect);
  400. subItem->setPen(subpen);
  401. //ptItem->setBrush(QColor("#d5e4f8"));
  402. m_pScene->addItem(subItem);
  403. // 添加PCB标签
  404. QRectF subTextRect(
  405. submatx,
  406. submaty,
  407. dieWidth / ratio * 0.6,
  408. dieHeight / ratio * 0.2
  409. );
  410. QGraphicsRectItem* subTextItem = new QGraphicsRectItem(subTextRect);
  411. subTextItem->setPen(Qt::NoPen);
  412. m_pScene->addItem(subTextItem);
  413. QGraphicsTextItem* subText = new QGraphicsTextItem(subTextItem);
  414. subText->setPlainText(QString(QString(tr("Sub%1")).arg(minSubPoint.stIndex.iPcbMatId)));
  415. subText->setFont(matrixFont);
  416. // 将文本居中于 pcbTextRect
  417. subText->setPos(subTextRect.center() - QPointF(subText->boundingRect().width() / 2,
  418. subText->boundingRect().height() / 2));
  419. subText->setFont(matrixFont);
  420. }
  421. else {
  422. if (maxSubPoints[i].stBondStatus.stAlnBondPosition.x > maxSubPoint.stBondStatus.stAlnBondPosition.x)
  423. maxSubPoint = maxSubPoints[i];
  424. if (minSubPoints[i].stBondStatus.stAlnBondPosition.x < minSubPoint.stBondStatus.stAlnBondPosition.x)
  425. minPcbPoint = minSubPoints[i];
  426. if (maxSubPoints[i].stBondStatus.stAlnBondPosition.y > maxSubPoint.stBondStatus.stAlnBondPosition.y)
  427. maxSubPoint = maxSubPoints[i];
  428. if (minSubPoints[i].stBondStatus.stAlnBondPosition.y < minSubPoint.stBondStatus.stAlnBondPosition.y)
  429. minSubPoint = minSubPoints[i];
  430. }
  431. }
  432. submatx = (minSubPoint.stBondStatus.stAlnBondPosition.x - minPoint.x() + 0.1 * dieWidth) / ratio;
  433. submaty = (minSubPoint.stBondStatus.stAlnBondPosition.y - minPoint.y() + 0.1 * dieHeight) / ratio;
  434. submatWidth = (maxSubPoint.stBondStatus.stAlnBondPosition.x - minSubPoint.stBondStatus.stAlnBondPosition.x + dieWidth * 2.8) / ratio;
  435. submatHeight = (maxSubPoint.stBondStatus.stAlnBondPosition.y - minSubPoint.stBondStatus.stAlnBondPosition.y + dieHeight * 2.8) / ratio;
  436. QRectF subRect(
  437. submatx,
  438. submaty,
  439. submatWidth,
  440. submatHeight
  441. );
  442. QGraphicsRectItem* subItem = new QGraphicsRectItem(subRect);
  443. // 设置边框颜色为红色,线宽为2
  444. subItem->setPen(subpen);
  445. // 绘制SUB矩阵背景
  446. //ptItem->setBrush(QColor("#d5e4f8"));
  447. m_pScene->addItem(subItem);
  448. // 添加PCB标签
  449. QRectF subTextRect(
  450. submatx,
  451. submaty,
  452. dieWidth / ratio * 0.6,
  453. dieHeight / ratio * 0.2
  454. );
  455. QGraphicsRectItem* subTextItem = new QGraphicsRectItem(subTextRect);
  456. subTextItem->setPen(Qt::NoPen);
  457. m_pScene->addItem(subTextItem);
  458. QGraphicsTextItem* subText = new QGraphicsTextItem(subTextItem);
  459. subText->setPlainText(QString(QString(tr("Sub%1")).arg(minSubPoint.stIndex.iPcbMatId)));
  460. subText->setFont(matrixFont);
  461. // 将文本居中于 pcbTextRect
  462. subText->setPos(subTextRect.center() - QPointF(subText->boundingRect().width() / 2,
  463. subText->boundingRect().height() / 2));
  464. subText->setFont(matrixFont);
  465. m_pView->setScene(m_pScene);
  466. m_pView->resize(width, height);
  467. // 创建一个 QPixmap 对象用于保存绘制的图像
  468. globalPixmap = QPixmap(width, height);
  469. globalPixmap.fill(Qt::white); // 填充背景色为白色
  470. QPixmap originalPixmap = QPixmap::grabWidget(m_pView);
  471. // 设置目标尺寸(例如:宽度 200,高度 150)
  472. QSize targetSize(width, height);
  473. // 不保持比例,直接拉伸到指定尺寸
  474. QPixmap scaledPixmap = originalPixmap.scaled(
  475. targetSize,
  476. Qt::IgnoreAspectRatio,
  477. Qt::SmoothTransformation
  478. );
  479. globalPixmap = scaledPixmap;
  480. }
  481. void Bond::paintInitFrom(QWidget* parent) {
  482. /*
  483. int width = parent->width();
  484. int height = parent->height();
  485. globalPixmap = QPixmap(width, height);
  486. globalPixmap.fill(Qt::white);
  487. QPainter painter(&globalPixmap);
  488. painter.setRenderHint(QPainter::Antialiasing);
  489. QFont baseFont = painter.font();
  490. // Step 1: 收集PCB全局布局信息
  491. QMap<QPair<int, int>, int> pcbPosMap;
  492. QSet<int> uniquePcbIds;
  493. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  494. QPair<int, int> pos(point.stIndex.iPcbRow, point.stIndex.iPcbCol);
  495. if (!pcbPosMap.contains(pos)) {
  496. pcbPosMap[pos] = point.stIndex.iPcbMatId;
  497. }
  498. uniquePcbIds.insert(point.stIndex.iPcbMatId);
  499. }
  500. // 计算PCB全局行列数
  501. int maxPcbRow = 0, maxPcbCol = 0;
  502. for (const QPair<int, int>& pos : pcbPosMap.keys()) {
  503. maxPcbRow = qMax(maxPcbRow, pos.first);
  504. maxPcbCol = qMax(maxPcbCol, pos.second);
  505. }
  506. int pcbRows = maxPcbRow + 1;
  507. int pcbCols = maxPcbCol + 1;
  508. //TODO:yang
  509. maxPcbCol = 1;
  510. // Step 2: 计算PCB布局参数
  511. qreal margin = width / maxPcbCol * 0.05;
  512. qreal pcbSpacing = margin;
  513. qreal totalWidth = width - 2 * margin;
  514. qreal totalHeight = height - 2 * margin;
  515. qreal pcbWidth = (totalWidth - (pcbCols - 1) * pcbSpacing) / pcbCols;
  516. qreal pcbHeight = (totalHeight - (pcbRows - 1) * pcbSpacing) / pcbRows;
  517. // Step 3: 预处理数据分组
  518. QMap<int, QMap<int, QList<ns_mat::POINT_INFO_STRUCT>>> groupedData;
  519. foreach(const ns_mat::POINT_INFO_STRUCT & point, bondData) {
  520. groupedData[point.stIndex.iPcbMatId][point.stIndex.iPtMatId].append(point);
  521. }
  522. // 绘制PCB并记录位置
  523. QMap<int, QRectF> pcbRects;
  524. for (int row = 0; row < pcbRows; ++row) {
  525. for (int col = 0; col < pcbCols; ++col) {
  526. QPair<int, int> pos(row, col);
  527. if (pcbPosMap.contains(pos)) {
  528. int pcbId = pcbPosMap[pos];
  529. QRectF rect(
  530. margin + col * (pcbWidth + pcbSpacing),
  531. margin + row * (pcbHeight + pcbSpacing),
  532. pcbWidth,
  533. pcbHeight
  534. );
  535. pcbRects[pcbId] = rect;
  536. // 绘制PCB背景
  537. painter.setPen(Qt::NoPen);
  538. painter.setBrush(QColor("#e1d4e6"));
  539. painter.drawRect(rect);
  540. }
  541. }
  542. }
  543. // Step 4: 绘制PT矩阵和固晶点
  544. foreach(int pcbId, uniquePcbIds) {
  545. QRectF pcbRect = pcbRects.value(pcbId);
  546. if (!pcbRect.isValid()) continue;
  547. // 获取当前PCB的所有PT矩阵
  548. QList<int> ptMatIds = groupedData[pcbId].keys();
  549. int ptMatCount = ptMatIds.size();
  550. if (ptMatCount == 0) continue;
  551. // 计算PT矩阵布局行列数(方形布局)
  552. int ptRows = std::ceil(std::sqrt(ptMatCount));
  553. int ptCols = std::ceil(static_cast<qreal>(ptMatCount) / ptRows);
  554. while (ptRows * ptCols < ptMatCount) ptCols++;
  555. qreal ptMargin = qMin(pcbWidth / ptCols * 0.1, pcbHeight / ptRows * 0.1);
  556. // 计算PT矩阵尺寸
  557. qreal ptWidth = (pcbRect.width() - (ptCols + 1) * ptMargin) / ptCols;
  558. qreal ptHeight = (pcbRect.height() - (ptRows + 1) * ptMargin) / ptRows;
  559. // 绘制每个PT矩阵
  560. for (int i = 0; i < ptMatIds.size(); ++i) {
  561. int ptId = ptMatIds[i];
  562. int row = i / ptCols;
  563. int col = i % ptCols;
  564. QRectF ptRect(
  565. pcbRect.x() + col * (ptWidth + ptMargin) + ptMargin,
  566. pcbRect.y() + row * (ptHeight + ptMargin) + ptMargin,
  567. ptWidth,
  568. ptHeight
  569. );
  570. // 绘制PT矩阵背景
  571. painter.setPen(Qt::NoPen);
  572. painter.setBrush(QColor("#d5e4f8"));
  573. painter.drawRect(ptRect);
  574. // Step 5: 绘制固晶点
  575. QList<ns_mat::POINT_INFO_STRUCT> points = groupedData[pcbId][ptId];
  576. if (points.isEmpty()) continue;
  577. // 获取固晶点矩阵尺寸
  578. QPair<int, int> dieDims = ptDimensions[pcbId][ptId];
  579. int dieRows = dieDims.first;
  580. int dieCols = dieDims.second;
  581. qreal dieMargin = qMin(ptWidth / dieCols * 0.3, ptHeight / dieRows * 0.3);
  582. // 计算固晶点尺寸
  583. qreal dieWidth = (ptRect.width() - (dieCols + 1) * dieMargin) / dieCols;
  584. qreal dieHeight = (ptRect.height() - (dieRows + 1) * dieMargin) / dieRows;
  585. foreach(const ns_mat::POINT_INFO_STRUCT & point, points) {
  586. // 计算固晶点位置
  587. QRectF dieRect(
  588. ptRect.x() + point.stIndex.iPtCol * (dieWidth + dieMargin) + dieMargin,
  589. ptRect.y() + point.stIndex.iPtRow * (dieHeight + dieMargin) + dieMargin,
  590. dieWidth,
  591. dieHeight
  592. );
  593. // 绘制固晶点
  594. painter.setPen(Qt::NoPen);
  595. //painter.setBrush(getColorByStatus(point.stBondStatus.bDieStatus));
  596. painter.drawRect(dieRect);
  597. }
  598. }
  599. }
  600. painter.end();
  601. */
  602. }
  603. void Bond::UpdataVal(std::vector<ns_mat::POINT_INFO_STRUCT>& stPointInfo)
  604. {
  605. maxPoint = QPointF(stPointInfo[0].stBondStatus.stAlnBondPosition.x, stPointInfo[0].stBondStatus.stAlnBondPosition.y);
  606. minPoint = QPointF(stPointInfo[0].stBondStatus.stAlnBondPosition.x, stPointInfo[0].stBondStatus.stAlnBondPosition.y);
  607. QVector<POINT_INFO_STRUCT> ptMatrix;
  608. QMap<int, QMap<int, QVector<POINT_INFO_STRUCT>>> pcbMatrix;
  609. UINT iPcbMatId = stPointInfo[0].stIndex.iPcbMatId;
  610. UINT iPtId = stPointInfo[0].stIndex.iPtMatId;
  611. POINT_INFO_STRUCT ptMinPoint = stPointInfo[0];
  612. POINT_INFO_STRUCT ptMaxPoint = stPointInfo[0];
  613. QMap<int, QPointF> ptMinPointmap;
  614. QMap<int, QPointF> ptMaxPointmap;
  615. QMap<int, QMap<int, QPointF>> pcbMinPointmap;
  616. QMap<int, QMap<int, QPointF>> pcbMaxPointmap;
  617. int pcbRow = stPointInfo[0].stIndex.iPcbRow;
  618. int pcbCol = stPointInfo[0].stIndex.iPcbCol;
  619. int pcbId = 1;
  620. for (auto&a: stPointInfo)
  621. {
  622. bondData.append(a);
  623. if (a.stIndex.iPtMatId == iPtId) {
  624. ptMatrix.append(a);
  625. }
  626. else {
  627. m_vptMaxPoints.append(ptMaxPoint);
  628. m_vptMinPoints.append(ptMinPoint);
  629. iPtId = a.stIndex.iPtMatId;
  630. ptMaxPoint = a;
  631. ptMinPoint = a;
  632. }
  633. //遍历找到最小和最大边界点
  634. if (a.stBondStatus.stAlnBondPosition.x > maxPoint.x())
  635. maxPoint.setX(a.stBondStatus.stAlnBondPosition.x);
  636. if(a.stBondStatus.stAlnBondPosition.x < minPoint.x())
  637. minPoint.setX(a.stBondStatus.stAlnBondPosition.x);
  638. if (a.stBondStatus.stAlnBondPosition.y > maxPoint.y())
  639. maxPoint.setY(a.stBondStatus.stAlnBondPosition.y);
  640. if (a.stBondStatus.stAlnBondPosition.y < minPoint.y())
  641. minPoint.setY(a.stBondStatus.stAlnBondPosition.y);
  642. //判断pt最小和最大对角点
  643. if (a.stBondStatus.stAlnBondPosition.x > ptMaxPoint.stBondStatus.stAlnBondPosition.x)
  644. ptMaxPoint = a;
  645. if (a.stBondStatus.stAlnBondPosition.x < ptMinPoint.stBondStatus.stAlnBondPosition.x)
  646. ptMinPoint = a;
  647. if (a.stBondStatus.stAlnBondPosition.y > ptMaxPoint.stBondStatus.stAlnBondPosition.y)
  648. ptMaxPoint = a;
  649. if (a.stBondStatus.stAlnBondPosition.y < ptMinPoint.stBondStatus.stAlnBondPosition.y)
  650. ptMinPoint = a;
  651. /*
  652. if (a.stIndex.iPcbMatId == iPcbMatId && a.stIndex.iPtMatId == iPtId && (pcbRow == a.stIndex.iPcbRow && pcbCol == a.stIndex.iPcbCol)) {
  653. ptMatrix.append(a);
  654. }
  655. else {
  656. if (a.stIndex.iPcbMatId == iPcbMatId && (pcbRow == a.stIndex.iPcbRow && pcbCol == a.stIndex.iPcbCol)) {
  657. m_pPtMatrixMap.insert(iPtId, ptMatrix);
  658. ptMatrix.clear();
  659. ptMinPointmap.insert(iPtId, ptMinPoint);
  660. ptMaxPointmap.insert(iPtId, ptMaxPoint);
  661. ptMinPointmap.clear();
  662. ptMaxPointmap.clear();
  663. iPtId = a.stIndex.iPtMatId;
  664. }
  665. else {
  666. m_pPcbMatrixMap.insert(iPcbMatId, m_pPtMatrixMap);
  667. m_pcbMinPointmap.insert(iPcbMatId, ptMinPointmap);
  668. m_pcbMaxPointmap.insert(iPcbMatId, ptMaxPointmap);
  669. pcbMatrix.clear();
  670. iPcbMatId = a.stIndex.iPcbMatId;
  671. m_pPtMatrixMap.clear();
  672. }
  673. }
  674. */
  675. qDebug() << a.stBondStatus.stAlnBondPosition.x << " " << a.stBondStatus.stAlnBondPosition.y;
  676. //qDebug() << a.stIndex.iPtMatId << " " << a.stIndex.iPcbMatId;
  677. }
  678. m_vptMaxPoints.append(ptMaxPoint);
  679. m_vptMinPoints.append(ptMinPoint);
  680. //m_pPtMatrixMap.insert(iPtId, ptMatrix);
  681. //m_pPcbMatrixMap.insert(iPcbMatId, m_pPtMatrixMap);
  682. //ptMinPointmap.insert(iPtId, ptMinPoint);
  683. //ptMaxPointmap.insert(iPtId, ptMaxPoint);
  684. //m_pcbMinPointmap.insert(iPcbId, ptMinPointmap);
  685. //m_pcbMaxPointmap.insert(iPcbId, ptMaxPointmap);
  686. }
  687. QPixmap Bond::getGlobalPixmap() const {
  688. return globalPixmap;
  689. }
  690. void Bond::setBondInfo(ns_module::CViewInterface* CViewInterface) {
  691. m_pCViewInterface = CViewInterface;
  692. }